@yolk_vat-y/dsh-project-memory 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/README.md +43 -5
- package/README.zh-CN.md +44 -7
- package/client/client.js +1439 -464
- package/client/client.js.map +1 -1
- package/package.json +2 -2
- package/src/auto-inject.js +214 -0
- package/src/client/MemoryView.tsx +349 -0
- package/src/client/TaskCommandNode.tsx +41 -30
- package/src/client/TaskComponents.tsx +388 -0
- package/src/client/TaskPanel.module.css +225 -40
- package/src/client/TaskPanel.tsx +174 -391
- package/src/client/client.ts +4 -4
- package/src/client/locales.ts +74 -0
- package/src/client/task-data-store.ts +152 -0
- package/src/client/task-hooks.ts +169 -0
- package/src/client/task-ui-store.ts +118 -0
- package/src/commands/insight-actions.js +390 -0
- package/src/commands/task-actions.js +17 -7
- package/src/commands/tasks.js +6 -3
- package/src/global-seed.js +41 -0
- package/src/index.js +42 -7
- package/src/insight-store.js +558 -0
- package/src/project-profile.js +78 -0
- package/src/reflection-pipeline.js +146 -0
- package/src/similarity.js +52 -0
- package/src/store.js +73 -0
- package/src/tools/lesson-tools.js +101 -0
- package/src/tools/task-tools.js +31 -2
- package/src/types.js +56 -0
- package/src/client/task-store.ts +0 -192
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
### Added — v0.5 tiered insight memory (lessons / decisions / procedures)
|
|
6
|
+
|
|
7
|
+
- **Single insight entity across three scopes**: task (private drafts inside tasks.json) / project (.dsh-project-memory/insights.json) / global (~/.config/dsh-project-memory/global.json). One schema, one dedupe, one capacity policy.
|
|
8
|
+
- **New model tool save_lesson** — write at any scope (explicit scope > task_id > bound task > project). Bidirectional token-overlap dedupe: >= 0.7 merges, 0.65~0.7 reinforces (task-hit accumulation, no content write).
|
|
9
|
+
- **Promotion = scope change, not a copy**: the same insight hit by 2 tasks auto-promotes task → project, 3+ tasks project → global (sourceTaskIds accumulate; no double-write ever). Manual promote/demote available via panel.
|
|
10
|
+
- **Soft archive**: archived:true hides from recall/injection and stays restorable; capacity decay (decayDays, hitCount==0) and overflow prune only archived entries.
|
|
11
|
+
- **Secret filter on write**: token/private-key/password-shaped content is rejected before persisting.
|
|
12
|
+
- **Non-destructive migration**: v0.4 experience.json notes are imported into insights.json once (kind: experience, source: migrate, migratedAt marker); legacy experience file keeps serving remember/forget/query_memory until the recall-unification PR retires it.
|
|
13
|
+
- **Reflection pipeline (PR 1b)**: optional LLM reflection (reflection.enabled: false by default) that only writes task-level drafts (source: reflect) on task switch-away/archive with cooldown + content-digest gating and silent failure. reflectTaskAfter / isReflectDue / fireReflect + test.
|
|
14
|
+
- **Silent injection engine (PR 2)**: entry resident block + relevance-gated injection; project-profile tags (package.json/go.mod/Cargo.toml); scope-tags intersection filter for global procedures; content fingerprint dedupe (60 s window); fully inert (returns the default decision) on any error or missing session cwd. Wired via the host's official **agent/pre-step** seam (`ctx.on('agent/pre-step', …)`, appending a plugin-source `[Memory Inject]` UserMessage to each step's `enter` messages) — patching `llm.stream` cannot intercept the host's internal reference. `installAutoInject` in index, `autoContext.enabled: true` default.
|
|
15
|
+
- **TaskPanel memory views (PR 3)**: header button cycles Task / Project / Global; lists + actions confirm/promote/demote/archive/restore/delete/edit + create form (procedures carry an "as Skill" trigger); task cards now show their insights inline. New user command /insight (server side commands/insight-actions.js: list/save/edit/actions).
|
|
16
|
+
- **New config groups**: insight.* (dedupOverlap 0.7, reinforceBand 0.65, maxProject 100, maxGlobalProcedures 200, promoteConfidence 0.7, globalPromoteTasks 3, decayDays 90, globalFile), reflection.* (enabled false, cooldownMs 1800000, maxLessonsPerReflect 3, maxDecisionsPerReflect 2), autoContext.* (enabled true, maxTokens 400, relevanceMin 0.25). select_task cards now include insights.
|
|
17
|
+
|
|
18
|
+
### Files
|
|
19
|
+
- src/similarity.js, src/insight-store.js, src/global-seed.js, src/types.js, src/tools/lesson-tools.js, src/reflection-pipeline.js, src/auto-inject.js, src/project-profile.js, src/commands/insight-actions.js, src/client/MemoryView.tsx
|
|
20
|
+
- Changed: src/store.js, src/index.js, src/tools/task-tools.js, src/commands/tasks.js, src/commands/task-actions.js, src/client/{TaskPanel,TaskComponents,task-data-store,locales}.ts(x), TaskPanel.module.css, package.json
|
|
21
|
+
- Tests: insight-store 11 / reflection-pipeline 5 / auto-inject 9 / insight-actions 7 (total 209, exit 0)
|
|
22
|
+
|
|
23
|
+
### Notes
|
|
24
|
+
- Design rationale, deviations (non-destructive migration; reflection triggers subset; auto-inject host verification) and the live-verification checklist live in PLAN-v0.5.0.md §10–§12.
|
|
25
|
+
- Requires a dsh web restart to load the new server code and rebuilt client bundle.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- **/insight flooding the conversation**: `/insight list` returns a large JSON payload; it is now registered into `conversation.chat.commandview` (with `/tasks`, `/task`) and renders as a one-line summary, so switching memory views no longer dumps megabytes of JSON into the chat. Task-card memory labels localized (`mem.section-label`).
|
|
29
|
+
- **Task panel "任务面板(点击重试)" crash (`Cannot read properties of undefined (reading 'filter')`)**: root cause was a latent BroadcastChannel bug — its handler used a functional updater but `setDataState` only accepted a plain object, so the first cross-tab sync replaced the store with a function and `data.tasks` became undefined. `setDataState` now accepts object or updater and always normalizes to the full shape; `TaskPanel` reads defensively (`Array.isArray(data.tasks)`).
|
|
30
|
+
- **Memory view infinite refresh loop flooding the conversation**: `refresh`'s `useCallback` included `loading` in its deps while the effect re-ran it, so every `loading` toggle recreated `refresh` → effect → `/insight list` → … (each command execution appends a chat node). Now guarded by refs (`inflightRef` + 800 ms `lastRunRef`) with `loading` kept out of the dependency array; a memory view fetch happens once per scope change/mount only.
|
|
31
|
+
|
|
32
|
+
## 0.4.4 (2026-09-06)
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- **Task data/UI store separation**: `task-data-store.ts` (server-synced data + BroadcastChannel cross-tab sync) and `task-ui-store.ts` (local UI state + localStorage) completely decoupled
|
|
36
|
+
- **Explicit panel open**: panel only opens on `/tasks`, `/task` (list form), or model calling `show_task_panel` tool
|
|
37
|
+
- **Cross-tab data sync**: BroadcastChannel broadcasts only tasks/archivedCount; UI state (closed/minimized/position) stays per-tab
|
|
38
|
+
- **Model tool `show_task_panel`**: model can now explicitly summon the panel via event bus
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- **Default hidden on startup**: `closed: true` forced, ignores localStorage residue
|
|
42
|
+
- **No auto-open on page refresh**: UI `closed` state not persisted, refresh = hidden
|
|
43
|
+
- **No auto-open on session switch**: only data syncs in background; panel closed = no `/tasks` command
|
|
44
|
+
- **MiniBar collapse crash**: fixed `useTaskDrag` hook called in event handler (React hooks rule violation) causing "任务面板(点击重试)" error boundary
|
|
45
|
+
- **Command node side effects**: `TaskCommandNode` now only syncs data; list commands explicitly call `open()`
|
|
46
|
+
|
|
47
|
+
### Refactored
|
|
48
|
+
- Removed legacy `task-store.ts` (232 lines)
|
|
49
|
+
- Split into 4 single-responsibility modules:
|
|
50
|
+
- `task-data-store.ts` — server data + cross-tab sync (~180 lines)
|
|
51
|
+
- `task-ui-store.ts` — local UI state + localStorage (~120 lines)
|
|
52
|
+
- `task-hooks.ts` — `useTaskDrag` / `useTaskEdit` (~150 lines)
|
|
53
|
+
- `TaskComponents.tsx` — `MiniBar` / `TaskCard` presentational (~330 lines)
|
|
54
|
+
- `TaskPanel.tsx` slimmed to container (~380 lines): data fetching, command bridging, event listening
|
|
55
|
+
|
|
56
|
+
### Tested
|
|
57
|
+
- Unit tests: 166 passed
|
|
58
|
+
- TaskBridge integration: 11 passed
|
|
59
|
+
- Client build: ✅
|
|
60
|
+
- Full harness build: ✅
|
|
61
|
+
|
|
3
62
|
## 0.4.3 (2026-09-04)
|
|
4
63
|
### 修复
|
|
5
64
|
- **CI 依赖解析**:锁定 devDependencies 版本,新增 package-lock.json
|
package/README.md
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
# dsh-project-memory
|
|
2
2
|
|
|
3
|
+
> 如果这个插件帮你省下 1 小时 Debug 时间,请点个 Star。
|
|
4
|
+
|
|
3
5
|
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
6
|
|
|
5
7
|
[](https://github.com/00080000/dsh-project-memory/actions/workflows/ci.yml) [](LICENSE) [](https://www.npmjs.com/package/@yolk_vat-y/dsh-project-memory) [](https://dsh-plugin.org/plugins/00080000/dsh-project-memory) [](https://awesome-dsh-plugin.com)
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
|
|
10
|
+
A persistent **project development memory** for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) agents. Built specifically for project development, natively integrated with dsh's task system: task lists and files read during a session are automatically persisted as cross-session task records, with tasks ↔ files linked — workflows can be switched and resumed, no need to re-scope the whole project, solving context loss. Documents (PDF/Markdown/txt) and code symbols are stored separately per workspace; documents are automatically cross-linked to the code symbols they mention. Experience notes (problem → solution) are automatically deduplicated, preventing repeated mistakes. All data is stored per project on disk, survives session compaction and handover; recalls include `path:line` citations for source verification. Only one dependency, no vector DB, no native builds.
|
|
8
11
|
|
|
9
12
|
> The plugin keeps a compact project **memory** on disk, with every entry pointing to a concrete file and line — the agent can reorient quickly instead of re-reading the whole project. Tasks and experience persist across session compactions and handovers.
|
|
10
13
|
|
|
14
|
+

|
|
15
|
+
The workflow panel is collapsible, automatically adapts to dsh and theme plugin styles, and offers four card style options to switch between.
|
|
16
|
+

|
|
11
17
|
## Features
|
|
12
18
|
|
|
19
|
+
- **TaskBridge: cross-session development tasks** — the plugin watches each session's live todo list (`todo_write` events) and file reads (`tool/call`): progress snapshots (`steps`) and touched files sync into durable per-project task entities. An unbound session that writes a todo auto-creates a task. New sessions continue by `list_tasks` → `select_task` (bind / rename / unarchive); `query_memory` gains `type: 'task'` and appends a task-count hint to `type: 'all'` results. The user-side `/tasks` command shows the task stack, step progress, involved files, and the current session binding. Titles are chosen by the model via `select_task(title=…)` (fallback: the part of your message after the last colon). Capacity is project-size adaptive (`fileCount/20`, clamped 5–100). Storage: `.dsh-project-memory/tasks.json` + `binding.json`. Auto-sync requires a dsh build with session events + `todo_write` (verified on 0.1.2-alpha.x); on older hosts the task tools still work as a plain record list.
|
|
20
|
+
- **Task Panel (v0.4.2+): Floating task panel in dsh web** — built on the real dsh web 0.1.2-rc.1 client plugin contract (cordis inject + apply, registered into host `shell.overlay` slot). Draggable cards show steps/files (click to copy path); collapse to a draggable mini-bar; hide completely (summon with `/task` / `/tasks`). Render errors have error boundaries — panel crash no longer takes down the host.
|
|
21
|
+
- **Task Panel Behavior** —
|
|
22
|
+
- **Default hidden**: panel does not show on dsh web startup
|
|
23
|
+
- **Explicit summon**: type `/tasks` or `/task` (list form) to open; model calls `show_task_panel` tool to open
|
|
24
|
+
- **Session switch**: only syncs data in background, **does not** auto-open panel
|
|
25
|
+
- **Page refresh**: panel stays hidden (UI state `closed` not persisted)
|
|
26
|
+
- **Manual close**: click × to fully hide (no mini-bar); reopen requires explicit summon
|
|
27
|
+
- **Collapse to mini-bar**: click ↓ to keep draggable top bar; click bar to expand
|
|
28
|
+
- **Bidirectional task-list sync (host ↔ plugin tasks, v0.4.2+)** — `select_task` or `/task switch` pushes task steps to host `todo/write` so dsh's rendered task list mirrors the plugin's task entity. Config `tasklist.syncHostOnAdopt` (default on) to toggle. Empty `todo/write` means "clear": unbound session clears list without creating junk tasks; bound session clears that task's steps (task retained). Panel edits (step text/status) = write back bound task + push host list, sharing one code path with model `todo_write`. `/task` subcommands: `switch`, `archive`, `unbind`, `rename`, `todos` (invoked by panel buttons/clicks, not the model); `unbind` also clears the host task list above the input.
|
|
29
|
+
- **Panel editing & themes (v0.4.2+)** — bound cards: double-click title/step for inline edit (input auto-grows); click step status icon to cycle todo→in-progress→done. Non-bound cards read-only. **Four visual themes** (click folder icon left of title, persisted locally): Native / Glassmorphism / Brutalist / Terminal monospace — only material, geometry, typeface, density change; colors always use dsw alias tokens, follow host light/dark and theme plugins.
|
|
13
30
|
- **Document memorization** — PDF, Markdown, and plain text files are chunked and summarized by the LLM; each entry carries a `path:line` citation back to the source.
|
|
14
31
|
- **Code symbol memory** — function, class, and method names with full type signatures (generics, parameters, return types, overloads) are extracted by a dependency-free source scanner (string/comment masking, multi-line signature joining, indentation-aware Python, class-method context), without LLM token usage.
|
|
15
32
|
- **L1 Enhanced Regex** — zero-dep regex scanner now extracts generics, parameter/return types, overloads, interfaces, and type aliases for all supported languages, producing one-line identity signatures `fn(a: A, b: B): R — file.ts:42`.
|
|
@@ -20,9 +37,9 @@ A persistent **project memory** for [DeepSeek Harness](https://github.com/deepse
|
|
|
20
37
|
- **BM25 memory recall** — ranked search over documents, symbols, and experience notes, with optional LLM query expansion to handle vocabulary mismatch. **CJK-optimized**: precise phrase boost (3+ char phrases ×1.5 score on title/keywords match), synonym table (e.g. 数据库连接池 ↔ 连接池 ↔ DB pool), and CJK-aware word boundaries for doc↔symbol linking.
|
|
21
38
|
- **blindSpots-aware recall** — document summaries carry a `blindSpots` field (what the summary explicitly does NOT cover). When a query hits a blind spot, `query_memory` appends a warning pointing the model to read the source file, preventing hallucination from partial summaries.
|
|
22
39
|
- **Experience notes** — problems → solutions; similar problems supersede instead of duplicating, and notes are returned only when a search matches. The note store is bounded: capacity scales with project size (clamped to 100–2000), and the oldest notes are pruned when the limit is exceeded. **Supersede tightened to bidirectional 0.7 overlap** (was 0.6); **experience `problem` field now participates in CJK phrase boost** for long-tail query recall.
|
|
40
|
+
- **v0.5 tiered insight memory (lessons / decisions / procedures)** — one `insight` entity across three scopes: `task` (private drafts in `tasks.json`), `project` (`.dsh-project-memory/insights.json`), `global` (`~/.config/dsh-project-memory/global.json`). `save_lesson` writes any scope; dedupe is bidirectional token overlap ≥ 0.7 (merge) with a 0.65–0.7 reinforce band; **promotion is a scope change, not a copy** — 2 tasks hitting the same insight promote it to project, 3+ to global. Archive is soft (`archived`), decay/capacity prune archived entries only; writes are filtered for secret/token-shaped content. LLM **reflection is off by default** and only ever writes task-level drafts (`source: reflect`) on task switch-away/archive. Panel gains a Task / Project / Global memory view with approve, promote/demote, archive/restore, delete, edit and a create form (procedures can carry an “as Skill” trigger). Old `experience.json` notes are imported into `insights.json` once, non-destructively. Defaults & rationale: `PLAN-v0.5.0.md`.
|
|
23
41
|
- **Streaming TF + IDF caching** — query path caches IDF (term inverse frequency) per store version; on cache hit, single-pass streaming scores 20k entries in ~8 ms (5k files) / ~1 ms (1k files) with zero intermediate objects; write path is O(1) version bump.
|
|
24
42
|
- **Lock-free sync transactions** — all writes (index / watch / remember / forget / watch_repo) go through synchronous transactions `store.commit(fn)`; fn succeeds then atomic write; JS single-threaded event loop guarantees no interleaving; `remember`/`forget` never blocked by watch re-indexing.
|
|
25
|
-
- **TaskBridge: cross-session development tasks** — the plugin watches each session's live todo list (`todo_write` events) and file reads (`tool/call`): progress snapshots (`steps`) and touched files sync into durable per-project task entities. An unbound session that writes a todo auto-creates a task. New sessions continue by `list_tasks` → `select_task` (bind / rename / unarchive); `query_memory` gains `type: 'task'` and appends a task-count hint to `type: 'all'` results. The user-side `/tasks` command shows the task stack, step progress, involved files, and the current session binding. Titles are chosen by the model via `select_task(title=…)` (fallback: the part of your message after the last colon). Capacity is project-size adaptive (`fileCount/20`, clamped 5–100). Storage: `.dsh-project-memory/tasks.json` + `binding.json`. Auto-sync requires a dsh build with session events + `todo_write` (verified on 0.1.2-alpha.x); on older hosts the task tools still work as a plain record list.
|
|
26
43
|
- **Minimal dependencies** — pure JavaScript; the only runtime dependency is `pdfjs-dist` (PDF text extraction), no native builds required.
|
|
27
44
|
- **Negligible overhead** — pure in-process operation; cold start <100 ms (5k files), typical project query median 2–3 ms (p99 < 7 ms); bottleneck is LLM summarization and PDF parsing, not the plugin.
|
|
28
45
|
|
|
@@ -103,9 +120,13 @@ The tools below are **invoked by the agent**, not typed by the user. In the chat
|
|
|
103
120
|
| `list_tasks` | List task records for the project (archived marked). Call first in a new session before continuing work. |
|
|
104
121
|
| `select_task` | Bind the session to a task so its todo list and file reads sync into it. Exact `taskId`, or exact `title` (multiple matches return candidates; no match creates a new task). Pass `title` with `taskId` to rename. Auto-unarchives. |
|
|
105
122
|
| `archive_task` | Archive a task (hide from default views, exclude from capacity, stop syncing). `select_task` restores it. |
|
|
123
|
+
| `show_task_panel` | Show the task panel in the UI. Call when the user asks to see the task list or when you want to display the panel. |
|
|
106
124
|
| `/tasks` (typed by the user, not the model) | Shows the task stack: title, step progress, involved files, and which task the current session is bound to. |
|
|
125
|
+
| `/task` (typed by the user, not the model) | Task panel subcommands: `switch` / `archive` / `unbind` / `rename` / `todos`. Invoked by panel buttons/clicks; does not go through the model. |
|
|
126
|
+
| `/insight` (typed by the user, not the model) | v0.5 memory view actions (panel buttons): `list [task|project|global]`, `confirm` / `promote` / `demote` / `archive` / `restore` / `delete` `<scope> <id>`, `save <scope> <json>`, `edit <scope> <id> <json>`. |
|
|
107
127
|
| `remember problem solution` | Save an experience note. Similar problems supersede instead of duplicating. |
|
|
108
128
|
| `forget id_or_query` | Delete stale experience notes. |
|
|
129
|
+
| `save_lesson` (agent tool) | Save a lesson/decision/procedure at task/project/global scope (single insight entity). Near-duplicates merge (≥ 0.7 overlap) or reinforce (0.65–0.7); 2+ tasks hitting the same insight auto-promote task → project, 3+ → global. Params: `title`, `kind`, `scope`, `pattern`/`fix` or `choice`/`reason` or `steps`/`trigger`, `task_id`, `files`, `symbols`, `confidence`, `root`. |
|
|
109
130
|
|
|
110
131
|
## Design
|
|
111
132
|
|
|
@@ -113,9 +134,12 @@ The tools below are **invoked by the agent**, not typed by the user. In the chat
|
|
|
113
134
|
.dsh-project-memory/
|
|
114
135
|
format.json layout marker (v2, sharded)
|
|
115
136
|
shards/ one self-describing JSON per indexed source file
|
|
116
|
-
|
|
137
|
+
({ relPath, record, entries }) — writes touch only dirty shards
|
|
117
138
|
experience.json problem → solution notes (retrieval-only)
|
|
118
139
|
watch.json watched roots
|
|
140
|
+
tasks.json TaskBridge task entities (cross-session)
|
|
141
|
+
binding.json current session ↔ task binding
|
|
142
|
+
insights.json v0.5 project-scope insights (lessons/decisions/procedures); v0.4 experience notes imported once, non-destructively
|
|
119
143
|
```
|
|
120
144
|
|
|
121
145
|
Stores created before v0.2.0 (single `entries.json` / `index.json`) migrate automatically and idempotently on first load. Within one dsh process, all tool calls share a single in-memory store per project, so hot-path indexing writes only the shard that changed.
|
|
@@ -125,6 +149,16 @@ Stores created before v0.2.0 (single `entries.json` / `index.json`) migrate auto
|
|
|
125
149
|
- **Query expansion** — when `llmQueryExpansion` is on, `query_memory` asks `ctx.llm` to rewrite the query into several variants (synonyms, EN/CN, identifier guesses) and merges BM25 scores across variants; when off, queries never touch the LLM. Cross-language recall (a Chinese question hitting English content) comes from index time instead: doc keywords are required to cover the document's own language AND English, and doc↔symbol links surface English symbol names from Chinese hits.
|
|
126
150
|
- **Consistency** — the fact layer follows the codebase (hash re-extract / remove-on-delete); the experience layer is retrieval-only with supersede and `forget`. Store writes are serialized per memory directory; the lock is in-process, so avoid running multiple dsh instances against the same project store concurrently.
|
|
127
151
|
|
|
152
|
+
## Architecture (Task Panel)
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
TaskPanel (Container)
|
|
156
|
+
├── task-data-store (server data, cross-tab sync via BroadcastChannel)
|
|
157
|
+
├── task-ui-store (local UI state, localStorage)
|
|
158
|
+
├── task-hooks (useTaskDrag, useTaskEdit)
|
|
159
|
+
└── TaskComponents (MiniBar, TaskCard — presentational only)
|
|
160
|
+
```
|
|
161
|
+
|
|
128
162
|
## Design tradeoffs
|
|
129
163
|
|
|
130
164
|
These are deliberate scope choices.
|
|
@@ -201,7 +235,7 @@ These are deliberate scope choices.
|
|
|
201
235
|
|
|
202
236
|
**Why:** Experience notes are low-stakes, high-volume, and retrieval-only. Aggressive deletion prevents stale noise from polluting search. For precision, delete by ID (shown in `query_memory` output).
|
|
203
237
|
|
|
204
|
-
###
|
|
238
|
+
### 10. TypeScript enhancement is optional, lazy, and cached
|
|
205
239
|
|
|
206
240
|
**We do:** L2 TS Compiler API enhancement runs async in a priority queue (P0 on `fs/observed`, P1 on `watch`, P2 on `index_repo`), results cached by content hash in `type-cache/`. Zero config — just `npm i -D typescript@5` or `typescript@6`. Falls back to L1 regex if TS absent or disabled.
|
|
207
241
|
|
|
@@ -219,6 +253,7 @@ These are deliberate scope choices.
|
|
|
219
253
|
| `maxFileSizeMb` | 50 | skip documents (incl. PDF) and code files larger than this (MB) |
|
|
220
254
|
| `maxOutputChars` | 8000 | cap for `query_memory` result text (chars) |
|
|
221
255
|
| `tasklist.enabled` | true | enable TaskBridge auto-sync (task entities from the session todo list and file reads) |
|
|
256
|
+
| `tasklist.syncHostOnAdopt` | true | when `select_task`/`/task switch` binds a task, push its steps to host `todo/write` so dsh's task list mirrors the task |
|
|
222
257
|
| `maxPdfPages` | 1000 | PDF page cap when pages are not otherwise limited |
|
|
223
258
|
| `llmQueryExpansion` | false | expand queries via `ctx.llm` before BM25 (off by default to save tokens) |
|
|
224
259
|
| `expansionCount` | 6 | max expansion variants |
|
|
@@ -228,6 +263,9 @@ These are deliberate scope choices.
|
|
|
228
263
|
| `watchInterval` | 15 | poll interval (seconds) |
|
|
229
264
|
| `tsPath` | (auto) | optional absolute path to a specific `typescript` install; if omitted, resolves from project cwd → plugin node_modules |
|
|
230
265
|
| `enableTypeScript` | true | set `false` to disable L2 TS enhancement entirely (L1 regex only) |
|
|
266
|
+
| `insight.*` | dedupOverlap `0.7` · reinforceBand `0.65` · maxProject `100` · maxGlobalProcedures `200` · promoteConfidence `0.7` · globalPromoteTasks `3` · decayDays `90` · `globalFile` (auto) | v0.5 insight dedupe / reinforce / promotion / capacity / archive settings |
|
|
267
|
+
| `reflection.enabled` | false | v0.5 LLM reflection, **draft-only at task level** (fires on task switch-away / archive). `cooldownMs` `1800000`, `maxLessonsPerReflect` `3`, `maxDecisionsPerReflect` `2` |
|
|
268
|
+
| `autoContext.enabled` | true | v0.5 silent injection wrapper (entry block + relevance). Inert (full passthrough) until the host exposes a resolvable session cwd; `maxTokens` `400` |
|
|
231
269
|
|
|
232
270
|
### Toggling features
|
|
233
271
|
|
|
@@ -263,7 +301,7 @@ These commands are for **maintaining the plugin code** — regular users do not
|
|
|
263
301
|
|
|
264
302
|
```bash
|
|
265
303
|
npm install
|
|
266
|
-
npm test #
|
|
304
|
+
npm test # 211 tests (166 core + 11 TaskBridge + 11 insight-store + 5 reflection + 9 auto-inject + 9 insight-actions)
|
|
267
305
|
```
|
|
268
306
|
|
|
269
307
|
## License
|
package/README.zh-CN.md
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
# dsh-project-memory
|
|
2
2
|
|
|
3
|
+
> 如果这个插件帮你省下 1 小时 Debug 时间,请点个 Star。
|
|
4
|
+
|
|
3
5
|
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
6
|
|
|
5
7
|
[](https://github.com/00080000/dsh-project-memory/actions/workflows/ci.yml) [](LICENSE) [](https://www.npmjs.com/package/@yolk_vat-y/dsh-project-memory) [](https://dsh-plugin.org/plugins/00080000/dsh-project-memory) [](https://awesome-dsh-plugin.com)
|
|
6
8
|
|
|
7
|
-
为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)agent 提供持久化的
|
|
9
|
+
为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)agent 提供持久化的 **项目开发记忆**。专门针对项目开发,原生融合 dsh 任务系统,会话内任务清单与读过的文件自动沉淀为跨会话任务记录,任务↔文件自动关联——开发工作流可切换、可续接,无需重复梳理整个项目,解决上下文失效;文档(PDF/Markdown/txt)与代码符号写入工作区独立存储,文档自动交叉链接至所提及的代码符号;经验笔记(问题 → 方案)自动去重,避免重复踩坑。所有数据按项目落盘,跨会话压缩与交接保留,召回附带 `路径:行号` 可回源核实。单依赖,无向量数据库,无原生构建。
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
> 插件在磁盘上维护一份精简的项目**记忆**,每条记录指向具体的文件与行号;agent 需要快速了解项目时先查**记忆**,无需重读整个项目。任务与经验跨会话压缩与交接保持。
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
工作流卡片可收起,自动适应dsh及主题插件风格,提供四种卡片风格切换。
|
|
10
16
|
|
|
17
|
+

|
|
11
18
|
## 特性
|
|
12
19
|
|
|
20
|
+
- **TaskBridge:跨会话开发任务** — 监听会话内宿主 `todo_write` 维护的任务清单与 `tool/call` 读文件:进度快照(steps)与触碰文件自动同步进跨会话的任务实体。未绑定会话写 todo 时自动建档。新会话通过 `list_tasks` → `select_task`(绑定/改名/解归档)续接;`query_memory` 新增 `type:'task'`,`type:'all'` 结果尾部附任务计数提示。用户侧 `/tasks` 命令展示任务栈、步骤进度、涉及文件与当前会话绑定。标题由模型经 `select_task(title=…)` 命名(回退:取消息最后一个「:」后的任务段)。容量随项目体积自适应(fileCount/20,clamp 5–100)。存储:`.dsh-project-memory/tasks.json` + `binding.json`。自动同步需含会话事件与 `todo_write` 的 dsh(0.1.2-alpha.x 实测);旧宿主下降级为纯记录。
|
|
21
|
+
- **Task Panel(v0.4.2+):dsh web 浮动任务面板** — 按 dsh web 0.1.2-rc.1 真实 client 插件契约落地(cordis inject + apply,注册进宿主 `shell.overlay` 槽)。卡片可拖拽、展开查看步骤/文件(点击复制路径);折叠为可拖拽顶部迷你条;可彻底隐藏(输入 `/task` / `/tasks` 唤起)。渲染错误有边界兜底,面板崩溃不再拖垮宿主。
|
|
22
|
+
- **任务面板行为** —
|
|
23
|
+
- **默认隐藏**:dsh web 启动时面板不显示
|
|
24
|
+
- **显式唤起**:输入 `/tasks` 或 `/task`(列表形式)打开;模型调用 `show_task_panel` 工具打开
|
|
25
|
+
- **会话切换**:仅后台同步数据,**不**自动打开面板
|
|
26
|
+
- **刷新页面**:面板保持隐藏(UI 状态 `closed` 不持久化)
|
|
27
|
+
- **手动关闭**:点击 × 彻底隐藏(无迷你条);重新打开需显式唤起
|
|
28
|
+
- **折叠迷你条**:点击 ↓ 仅保留顶部可拖拽迷你条;点击迷你条展开
|
|
29
|
+
- **任务清单双向同步(宿主 ↔ 插件任务,v0.4.2+)** — `select_task` 或 `/task switch` 绑定任务时,将任务 steps 推给宿主 `todo/write`,dsh 渲染的任务清单跟随我们维护的任务实体。配置 `tasklist.syncHostOnAdopt`(默认开)可关。空 `todo/write` 语义定为「清空」:未绑定会话清空清单不再误建垃圾任务;已绑定则清空该任务 steps(任务保留)。面板编辑(改步骤文本/状态)= 写回绑定任务并推宿主清单,与模型 `todo_write` 共用一套逻辑,无第二套同步。`/task` 新增 `switch` / `archive` / `unbind` / `rename` / `todos`(均由面板按钮/双击调用,不经模型);`unbind` 同时清掉输入框上方的宿主任务清单。
|
|
30
|
+
- **面板编辑与风格(v0.4.2+)** — 绑定卡片:双击标题/步骤行内编辑(输入框随内容自动增高),点步骤状态图标循环 待办→进行中→已完成;非绑定卡片只读。**四档外观风格**(点标题左侧文件夹图标切换,本地记忆):原生 / 玻璃拟态 / 粗野主义 / 终端等宽——只改材质、几何、字型与密度,颜色始终取自 dsw 别名令牌,跟随宿主明暗与主题插件。
|
|
13
31
|
- **文档记忆** — PDF、Markdown、纯文本按块切分并由 LLM 生成摘要,每条记忆携带 `路径:行号` 引用回源文件。
|
|
14
32
|
- **代码符号记忆** — 通过零依赖的源码扫描器提取函数、类与方法名及完整类型签名(泛型、参数类型、返回类型、重载签名),包含字符串/注释掩码、多行签名续行、Python 缩进感知、类方法上下文,不使用 LLM token。
|
|
15
33
|
- **L1 增强正则** — 零依赖正则扫描器现可提取泛型、参数/返回类型、重载、接口、类型别名,产出单行身份签名 `fn(a: A, b: B): R — file.ts:42`。
|
|
@@ -20,9 +38,9 @@
|
|
|
20
38
|
- **BM25 记忆召回** — 对文档、符号与经验笔记进行排序召回,可选 LLM 查询扩展以应对表述不一致。**CJK 增强**:精确短语乘法加分(3+ 字短语在标题/关键词命中 ×1.5)、同义词表(如 数据库连接池 ↔ 连接池 ↔ DB pool)、CJK 感知的文档↔符号链接边界。
|
|
21
39
|
- **blindSpots 感知召回** — 文档摘要携带 `blindSpots` 字段(明确说明摘要未覆盖的内容)。查询命中盲区时,`query_memory` 追加提示引导模型去读原文,防止半截摘要误导。
|
|
22
40
|
- **经验笔记** — 记录问题 → 方案;相似问题覆盖而非重复;笔记仅在检索命中时返回。笔记数量有界:容量随项目规模伸缩(钳制在 100–2000),超限时淘汰最旧的笔记。**覆盖阈值收紧为双向 0.7 重叠**(原 0.6);**经验 `problem` 字段现参与 CJK 短语加分**,提升长尾问句召回。
|
|
41
|
+
- **v0.5 分层 insight 记忆(教训 / 决策 / 流程)** — 一个 `insight` 实体贯穿三级:`task`(任务私有草稿,存 `tasks.json`)、`project`(`.dsh-project-memory/insights.json`)、`global`(`~/.config/dsh-project-memory/global.json`)。`save_lesson` 三级可写;去重采用双向 token overlap ≥ 0.7(合并)外加 0.65–0.7 近重复强化带;**提升 = scope 字段变更而非复制**——同一 insight 被 2 个任务命中升 project、3+ 升 global。归档为软删(`archived`),容量/衰减只清归档区;写盘前过滤密钥/token 形态内容。LLM **反思默认关闭**,且只产任务级草稿(`source: reflect`,触发于任务切走/归档时)。面板新增 Task / Project / Global 记忆视图:审核、提升/降级、归档/恢复、删除、编辑与新建表单(procedure 可带"作为 Skill"触发关键词)。旧 `experience.json` 笔记**非破坏**导入 `insights.json` 一次。默认值与设计说明见 `PLAN-v0.5.0.md`。
|
|
23
42
|
- **流式 TF + IDF 缓存** — 查询路径按存储版本缓存 IDF(词逆频率);命中时单次流式遍历 20k 条目仅需 ~8 ms(5k 文件) / ~1 ms(1k 文件),零中间对象;写入路径仅 O(1) 版本号递增。
|
|
24
43
|
- **无锁同步事务** — 不采用锁:所有写入(index / watch / remember / forget / watch_repo)统一走同步事务 `store.commit(fn)`,fn 成功后才一次落盘;JS 单线程事件循环保证事务间不交错,`remember`/`forget` 不会被 watch 重索引阻塞排队。多实例并发写入同一项目存储时,得益于 CAS 幂等更新与原子提交,自然具备幂等性,无数据损坏风险。
|
|
25
|
-
- **TaskBridge:跨会话开发任务** — 监听会话内宿主 `todo_write` 维护的任务清单与 `tool/call` 读文件:进度快照(steps)与触碰文件自动同步进跨会话的任务实体。未绑定会话写 todo 时自动建档。新会话通过 `list_tasks` → `select_task`(绑定/改名/解归档)续接;`query_memory` 新增 `type:'task'`,`type:'all'` 结果尾部附任务计数提示。用户侧 `/tasks` 命令展示任务栈、步骤进度、涉及文件与当前会话绑定。标题由模型经 `select_task(title=…)` 命名(回退:取消息最后一个「:」后的任务段)。容量随项目体积自适应(fileCount/20,clamp 5–100)。存储:`.dsh-project-memory/tasks.json` + `binding.json`。自动同步需含会话事件与 `todo_write` 的 dsh(0.1.2-alpha.x 实测);旧宿主下降级为纯记录。
|
|
26
44
|
- **依赖极简** — 纯 JavaScript;唯一运行时依赖是 `pdfjs-dist`(PDF 文本提取),无需原生构建。
|
|
27
45
|
- **开销可忽略** — 纯进程内操作;冷启动 <100 ms(5k 文件),典型项目查询中位数 2–3 ms(p99 < 7 ms);瓶颈在 LLM 摘要与 PDF 解析,插件本身不阻塞。
|
|
28
46
|
|
|
@@ -103,9 +121,13 @@ dsh plugin --profile web add /path/to/dsh-project-memory.tgz
|
|
|
103
121
|
| `list_tasks` | 列出本项目任务记录(含归档,带标记)。新会话/续接前先调用。 |
|
|
104
122
|
| `select_task` | 将会话绑定到某任务(此后 todo 清单与读文件同步进该任务)。按 `taskId` 精确绑定,或按 `title` 完全匹配(多个同名返回候选;无则新建)。带 title 可改名;自动解归档。 |
|
|
105
123
|
| `archive_task` | 归档任务(隐藏默认视图、不占容量、停止同步)。`select_task` 可恢复。 |
|
|
124
|
+
| `show_task_panel` | 在 UI 中打开任务面板。用户要求查看任务列表或你想展示面板时调用。 |
|
|
106
125
|
| `/tasks`(用户输入,不经模型) | 展示任务栈:标题、步骤进度、涉及文件、当前会话绑定哪套任务。 |
|
|
126
|
+
| `/task`(用户输入,不经模型) | 任务面板子命令:`switch` / `archive` / `unbind` / `rename` / `todos`(面板按钮/点击触发,不经模型)。 |
|
|
127
|
+
| `/insight`(用户输入,不经模型) | v0.5 记忆视图动作(面板按钮触发):`list [task|project|global]`、`confirm` / `promote` / `demote` / `archive` / `restore` / `delete` `<scope> <id>`、`save <scope> <json>`、`edit <scope> <id> <json>`。 |
|
|
107
128
|
| `remember problem solution` | 保存经验笔记。相似问题覆盖而非重复。 |
|
|
108
129
|
| `forget id_or_query` | 删除过期经验笔记。 |
|
|
130
|
+
| `save_lesson`(模型工具) | 在 task/project/global 任一作用域保存教训/决策/流程(单一 insight 实体)。近重复按双向 overlap ≥ 0.7 合并、0.65–0.7 强化;同一 insight 被 2+ 任务命中自动 task→project、3+ → global。参数:`title`、`kind`、`scope`、`pattern`/`fix` 或 `choice`/`reason` 或 `steps`/`trigger`、`task_id`、`files`、`symbols`、`confidence`、`root`。 |
|
|
109
131
|
|
|
110
132
|
## 设计
|
|
111
133
|
|
|
@@ -113,9 +135,12 @@ dsh plugin --profile web add /path/to/dsh-project-memory.tgz
|
|
|
113
135
|
.dsh-project-memory/
|
|
114
136
|
format.json 布局标记(v2,分片式)
|
|
115
137
|
shards/ 每个被索引源文件一个自描述 JSON
|
|
116
|
-
|
|
138
|
+
({ relPath, record, entries })——写入只落脏分片
|
|
117
139
|
experience.json 问题 → 方案笔记(仅检索)
|
|
118
140
|
watch.json 被监听根目录
|
|
141
|
+
tasks.json TaskBridge 任务实体(跨会话)
|
|
142
|
+
binding.json 当前会话 ↔ 任务绑定
|
|
143
|
+
insights.json v0.5 项目级 insights(教训/决策/流程);v0.4 经验笔记非破坏导入一次
|
|
119
144
|
```
|
|
120
145
|
|
|
121
146
|
v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次加载时自动幂等迁移。同一个 dsh 进程内,所有工具调用共享每个项目的单一内存 store 实例,热路径索引只写发生变化的那一个分片。
|
|
@@ -125,9 +150,17 @@ v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次
|
|
|
125
150
|
- **查询扩展** — `llmQueryExpansion` 开启时,`query_memory` 让 `ctx.llm` 将查询改写为多个变体(同义词、中英、符号名猜测),再跨变体合并 BM25 分数;关闭时查询完全不碰 LLM。跨语种召回(中文问题命中英文内容)改由索引时承担:文档 keywords 要求同时覆盖文档语言与英文,doc↔symbol 链接也会从中文命中带出英文符号名。
|
|
126
151
|
- **一致性** — 事实层跟随代码库(哈希重抽 / 删除即移除);经验层仅检索,配合覆盖与 `forget` 机制。每个记忆目录的写入走同步事务 `store.commit(fn)`:fn 内完成校验与变更、成功后才原子落盘,单进程内天然串行;请避免多个 dsh 实例同时写同一项目存储。
|
|
127
152
|
|
|
128
|
-
##
|
|
153
|
+
## 架构(任务面板)
|
|
129
154
|
|
|
130
|
-
|
|
155
|
+
```
|
|
156
|
+
TaskPanel (Container)
|
|
157
|
+
├── task-data-store (服务端数据,跨标签页 BroadcastChannel 同步)
|
|
158
|
+
├── task-ui-store (本地 UI 状态,localStorage)
|
|
159
|
+
├── task-hooks (useTaskDrag, useTaskEdit)
|
|
160
|
+
└── TaskComponents (MiniBar, TaskCard — 纯展示组件)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## 设计取舍
|
|
131
164
|
|
|
132
165
|
### 1. 同步无锁事务,而非异步锁
|
|
133
166
|
|
|
@@ -201,7 +234,7 @@ v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次
|
|
|
201
234
|
|
|
202
235
|
**为什么:** 经验笔记低风险、高量、仅检索。激进删除防止陈旧噪音污染搜索。精确删用 ID(`query_memory` 输出里有)。
|
|
203
236
|
|
|
204
|
-
###
|
|
237
|
+
### 10. TS 增强可选、异步、缓存
|
|
205
238
|
|
|
206
239
|
**我们做:** L2 TS Compiler API 在优先级队列异步跑(P0 `fs/observed`、P1 `watch`、P2 `index_repo`),结果按内容哈希缓存 `type-cache/`。零配置——`npm i -D typescript@5` 或 `npm i -D typescript@6` 即用。无 TS 或禁用时优雅回退 L1 正则。
|
|
207
240
|
|
|
@@ -219,6 +252,7 @@ v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次
|
|
|
219
252
|
| `maxFileSizeMb` | 50 | 大于该值(MB)的文档(含 PDF)/代码文件跳过 |
|
|
220
253
|
| `maxOutputChars` | 8000 | `query_memory` 返回文本上限(字符) |
|
|
221
254
|
| `tasklist.enabled` | true | 启用 TaskBridge 自动同步(由会话 todo 清单与文件读取沉淀任务实体) |
|
|
255
|
+
| `tasklist.syncHostOnAdopt` | true | `select_task`/`/task switch` 绑定任务时,将其 steps 推给宿主 `todo/write`,使 dsh 任务清单镜像任务实体 |
|
|
222
256
|
| `maxPdfPages` | 1000 | 未另行限制时 PDF 的页数上限 |
|
|
223
257
|
| `llmQueryExpansion` | false | BM25 检索前通过 `ctx.llm` 扩展查询(默认关闭,节省 token) |
|
|
224
258
|
| `expansionCount` | 6 | 扩展变体上限 |
|
|
@@ -228,6 +262,9 @@ v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次
|
|
|
228
262
|
| `watchInterval` | 15 | 轮询间隔(秒) |
|
|
229
263
|
| `tsPath` | (自动) | 可选:强制指定特定 `typescript` 安装路径;省略时按项目 cwd → 插件 node_modules 向上解析 |
|
|
230
264
|
| `enableTypeScript` | true | 设为 `false` 彻底禁用 L2 TS 增强(仅保留 L1 正则) |
|
|
265
|
+
| `insight.*` | dedupOverlap `0.7` · reinforceBand `0.65` · maxProject `100` · maxGlobalProcedures `200` · promoteConfidence `0.7` · globalPromoteTasks `3` · decayDays `90` · `globalFile`(自动) | v0.5 insight 去重/强化/提升/容量/归档设置 |
|
|
266
|
+
| `reflection.enabled` | false | v0.5 LLM 反思,**只写任务级草稿**(触发于任务切走/归档)。`cooldownMs` `1800000`、`maxLessonsPerReflect` `3`、`maxDecisionsPerReflect` `2` |
|
|
267
|
+
| `autoContext.enabled` | true | v0.5 静默注入包装(entry 常驻块 + relevance)。宿主无法解析会话 cwd 时完全透传(零副作用);`maxTokens` `400` |
|
|
231
268
|
|
|
232
269
|
### 功能开关
|
|
233
270
|
|
|
@@ -263,7 +300,7 @@ dsh web --patch ./config.yml
|
|
|
263
300
|
|
|
264
301
|
```bash
|
|
265
302
|
npm install
|
|
266
|
-
npm test #
|
|
303
|
+
npm test # 211 项测试(核心 166 + TaskBridge 11 + insight-store 11 + reflection 5 + auto-inject 9 + insight-actions 9)
|
|
267
304
|
```
|
|
268
305
|
|
|
269
306
|
## 许可证
|