Bundle
dsh-work-report
Neural Ledger · 神经账本 — turn your DSH collaboration sessions into a visual work ledger: token analytics, smart insights, trend forecasting, and one-click daily/weekly/monthly Markdown reports.
- Source
- Elpsycoogroo
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 23 hours ago
Readme
# Neural Ledger · 神经账本
English | [中文](README.zh.md)
> **One-liner:** A zero-patch DSH plugin that turns your AI collaboration sessions into a beautiful work ledger — token analytics, smart insights, trend forecasting, and one-click daily / weekly / monthly reports. Live data from your own sessions, no DSH source touched.


## Features
- **📊 Living dashboard** — Session counts, turns, tool calls, token usage, and AI time in one glance.
- **💡 Smart insights** — Auto-generated findings: which session burned the most tokens, what took the longest, how much subagent collaboration matters, and overall conversation efficiency.
- **📈 Token analytics** — Daily token bars, token composition donut (uncached input / cache read / output), per-session token & time rankings.
- **🔮 Trend forecasting** — Linear-regression prediction of the next 7 days, monthly estimates, and a budget-overrun warning (default 50M tokens/month).
- **🗂 Workspace breakdown** — Compare token consumption across projects; tree drill-down `workspace → parent agent → subagent`.
- **📋 One-click reports** — Export daily / weekly / monthly reports as Markdown, with per-turn demand → outcome storylines and subagent task details. Copy to clipboard or download.
- **📤 Export session context** — Tree picker (workspace → parent agent → subagent, collapsible, fuzzy search incl. workspace) → generates a *distilled context* (prompt-like): metadata, goal, per-turn demands/outcomes, tool summary, and a continue-work prompt ready to feed another agent.
- **🌐 i18n** — Toggle Chinese / English for the whole UI and exported reports (remembers your choice).
- **🎬 Sample mode** — Built-in mock dataset for previewing the whole dashboard without waiting for real data.
- **Draggable FAB** — The floating action button is draggable, position is remembered, and a hover label follows it live.
- **No DSH source modification** — Only DOM-level integration; DSH files are never touched.
## Quick Start
### Install from GitHub
```bash
dsh plugin --profile web add github:Elpsycoogroo/dsh-work-report
```
> **pnpm blocks build scripts by default**: installing from GitHub runs the project's own build script, and pnpm refuses until you allowlist it. Run the command once — pnpm prints the key to add under `allowBuilds` in `~/.dsh/profiles/web/pnpm-workspace.yaml`. Add it and run again.
### Install from npm (once published)
```bash
dsh plugin --profile web add dsh-work-report
```
### Manual install in this repo
Clone/symlink the plugin at `dsh/plugins/dsh-work-report` and build once:
```bash
cd dsh/plugins/dsh-work-report
npm install
npm run build
```
> ⚠️ **Don't manually copy only `lib/`** into the profile's `node_modules/` — a copy missing `package.json` (and `cordis.patch.yml`) cannot be resolved by the DSH loader. Copy the whole package. For ongoing development use `node dev.mjs` (watch src/ → auto-build → auto-sync the **whole package** into the profile).
### Usage
1. Open DSH, click the **🧠 floating button** (bottom-right by default, draggable anywhere).
2. The Neural Ledger overlay opens with real data from your sessions.
3. Pick a report type (日报 / 周报 / 月报 — auto-switches daily window 1/7/30 days).
4. Hit **📋 Copy** or **⬇ Download** to get the Markdown report.
5. **📤 Export Context** — pick a session from the collapsible tree (workspace → parent → subagent) or fuzzy-search it, then copy/download the distilled context as a prompt for another agent.
6. **🌐 EN** — toggle the whole UI (and exports) between Chinese and English.
### ⚠️ Read before forking/self-hosting (war stories)
1. **`package.json` must export `"./package.json"`**: DSH's client-modules reads a plugin's manifest via `require.resolve('<pkg>/package.json')`. If `exports` doesn't expose that subpath, it throws `ERR_PACKAGE_PATH_NOT_EXPORTED` and the plugin shows *in the plugin list but its client.js is never injected into the page*.
2. **All three names must match**: the `name` in `package.json`, in the plugin's own `cordis.patch.yml`, and the name referenced from your profile bundle.
3. **You MUST restart dsh after changing the manifest/reinstalling**: client-modules caches the "not a client plugin" verdict for the process lifetime.
4. **`sessionPersistence.readFrom()` may be unavailable**: the server falls back to projcache (`storages/session_projcache.json`); token totals for subagents missing from the cache are aggregated from event `usage` blocks.
## Contributor Docs / 给开源作者
Local dev, debugging and integration guides are in [DEVELOPING.md](DEVELOPING.md) / [DEVELOPING.zh.md](DEVELOPING.zh.md).
## How It Works
### Architecture
```
browser (client plugin)
ReportView ── StatCards / Insights / TokenCharts / ForecastCard
├── WorkspaceChart / EfficiencyCharts / ToolRanking
└── SessionTimeline (workspace → parent agent → subagent)
│
└── fetch('/api/work-report?days=7&mock=1') ← requested by ReportView, shared by all cards
Host (server plugin) [ctx.webServer.register({ kind: 'exact', path: '/api/work-report' })]
ctx.get('sessions') → attached (in-memory) sessions
ctx.get('sessionPersistence') → cold (persisted) sessions + events
storages/session_projcache.json → tokenUsage / sessionStats / contextPressure / subagent labels
→ buildReport(config) → { sessions, token, time, insights, forecast, dailyTokens, workspaceTokens }
```
### Data sources
- **Active sessions** — `ctx.sessions.list()` (attached, in-memory).
- **Cold sessions** — `persistence.list()` + `persistence.readFrom(id, 0)` for events and `parentSession` linkage. `readFrom` is optional; when absent, metadata comes from projcache.
- **Token / stats** — projcache projections (`tokenUsage.totals`, `sessionStats`, `contextPressure`) with event-`usage` aggregation as fallback.
- **Subagent labels** — projcache `subagent.identity.label` (e.g. `Worker A - 代码开发`); parent linkage via `meta.parentSession`.
- **Archived sessions** — filtered using `workspace.json`'s `global.archivedSessionIds`; blank sessions (0 tokens & 0 time) are filtered out too.
### Report generation
- **Recursive text extraction** — demand / outcome text pulled from any message nesting shape, skipping `<system-reminder>`, `Current runtime context.`, and other noise.
- **Turn storyline** — each turn records user demand, AI outcome, tool calls (✓/✗), and token usage.
- **Forecast** — linear regression over daily tokens, with fallback base for sparse data; 7-day projection + 30-day estimate vs budget.
## Files
```
dsh-work-report/
├── package.json
├── tsconfig.json
├── tsdown.config.ts
├── cordis.patch.yml
├── README.md # English docs
├── README.zh.md # 中文文档
├── DEVELOPING.md # English contributor guide
├── DEVELOPING.zh.md # 中文开发者指南
├── CONTRIBUTING.md # 中文贡献指南
├── CONTRIBUTING.en.md # English contributing guide
├── GITHUB_SETUP.md # GitHub repo setup checklist
├── pull_request_template.md
├── pull_request_template.en.md
├── mock-report.json # built-in sample dataset (🎬 Sample mode)
├── screenshots/ # README screenshots (dashboard previews)
├── .github/ # ISSUE_TEMPLATE (bug_report.yml / feature_request.yml)
└── src/
├── index.ts # Host entry (re-exports)
├── server/
│ ├── index.ts # webServer route /api/work-report
│ └── report-data.ts # data collection, aggregation, insights, forecast
├── client/
│ ├── index.ts # client entry: draggable FAB + overlay mount
│ ├── i18n.tsx # zh/en dictionaries + language provider
│ ├── ReportView.tsx # main dashboard
│ ├── StatCards.tsx # stat cards
│ ├── Insights.tsx # smart insight cards
│ ├── TokenCharts.tsx # daily bars + composition donut
│ ├── ForecastCard.tsx # trend prediction + budget warning
│ ├── WorkspaceChart.tsx # workspace token comparison
│ ├── EfficiencyCharts.tsx # per-session time & token rankings
│ ├── ToolRanking.tsx # session-type token share
│ ├── SessionTimeline.tsx # 3-level tree session list
│ ├── ContextExporter.tsx # export session context (tree picker + search)
│ ├── markdown.ts # daily/weekly/monthly report generator
│ └── report-api.ts # API fetch + formatting utils
└── types/
└── dsh-env.d.ts # ambient type declarations
```
## Build & Publish to npm
### Build locally
```bash
cd dsh/plugins/dsh-work-report
npm run build # tsdown: host ESM (lib/index.js) + browser CJS (lib/client.js)
node dev.mjs # watch mode: auto-build + auto-sync whole package to profile
```
> Browser bundle inlines echarts (kept in `devDependencies` so tsdown bundles it; module-table externals are only `react` / `@deepseek-ai/*`).
### Publish to npm (once you own the package name)
```bash
npm login
exports_subpath=./package.json # keep exports["./package.json"] — DSH client-modules needs it
npm version patch -m "chore(release): v%s"
npm publish --access public
# verify the tarball contains everything the runtime needs:
npm pack --dry-run | grep -E "package.json|cordis.patch.yml|lib/(index|client)\.js|mock-report"
```
> The published files are controlled by `package.json`'s `files` field (`lib`, `src`, `mock-report.json`, `cordis.patch.yml`, docs). Before the first publish make sure `files` includes every runtime file — the DSH loader resolves `package.json` and `cordis.patch.yml` at runtime, not just `lib/`.
## Console Logs
| Source | Level | Description |
| ----------------- | ----- | --------------------------------------- |
| `client/index.ts` | log | Version loaded (`v0.1.0 loaded`) |
| `server/index.ts` | log | Route registered (`host plugin loaded`) |
| `server/index.ts` | error | Report build failure |
## License
MIT
Install
dsh plugin --profile web add github:Elpsycoogroo/dsh-work-report
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-work-report from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.