dsh-plugin-tool-management 0.10.0 → 0.11.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 +71 -1
- package/README.md +64 -49
- package/README_EN.md +58 -37
- package/docs/images/1-EN.png +0 -0
- package/docs/images/1.png +0 -0
- package/docs/images/2-EN.png +0 -0
- package/docs/images/2.png +0 -0
- package/docs/images/3-EN.png +0 -0
- package/docs/images/3.png +0 -0
- package/docs/images/4-EN.png +0 -0
- package/docs/images/4.png +0 -0
- package/docs/images/5-EN.png +0 -0
- package/docs/images/5.png +0 -0
- package/docs/images/6-EN.png +0 -0
- package/docs/images/6.png +0 -0
- package/docs/images/7-EN.png +0 -0
- package/docs/images/7.png +0 -0
- package/docs/images/8-EN.png +0 -0
- package/docs/images/8.png +0 -0
- package/docs/update.md +105 -12
- package/lib/client.js +2763 -546
- package/lib/compat/preset-reach.js +1 -10
- package/lib/compat/probe.js +158 -20
- package/lib/context-inject.js +11 -0
- package/lib/host-names.js +12 -0
- package/lib/http-fence.js +35 -15
- package/lib/hub.js +28 -2
- package/lib/imports/parsers.js +15 -9
- package/lib/imports/upload.js +43 -4
- package/lib/index.js +804 -3887
- package/lib/mcp/loader-token.js +238 -0
- package/lib/mcp/manager.js +1681 -0
- package/lib/mcp/override-blocks.js +10 -3
- package/lib/mcp/patch-yaml.js +351 -0
- package/lib/mcp/secret-guard.js +145 -0
- package/lib/{rules → memories}/archive-engine.js +1 -1
- package/lib/{rules → memories}/archive.js +1 -1
- package/lib/memories/constants.js +128 -0
- package/lib/memories/index-io.js +330 -0
- package/lib/memories/projection.js +280 -0
- package/lib/memories/service.js +686 -0
- package/lib/memories/snapshot.js +672 -0
- package/lib/ops/candidates.js +64 -0
- package/lib/ops/compat.js +136 -0
- package/lib/ops/ctx.js +9 -0
- package/lib/ops/memory.js +678 -0
- package/lib/ops/prompts.js +107 -0
- package/lib/ops/scene-records.js +460 -0
- package/lib/ops/scene-sync.js +17 -0
- package/lib/ops/sessions.js +603 -0
- package/lib/ops/trash.js +140 -0
- package/lib/paths.js +103 -0
- package/lib/prompts/preset-id.js +49 -0
- package/lib/{agents-md → prompts}/service.js +1 -1
- package/lib/request-gate.js +320 -0
- package/lib/scene-prompt-sync.js +4 -4
- package/lib/scenes/candidates.js +344 -0
- package/lib/{history → sessions}/bridge.js +15 -5
- package/lib/sessions/history.js +323 -0
- package/lib/{history → sessions}/tombstone.js +1 -1
- package/lib/{history → sessions}/workspace.js +92 -24
- package/lib/skills/core.js +74 -39
- package/lib/skills/readonly-discovery.js +4 -1
- package/lib/skills/service.js +98 -13
- package/lib/subagents/service.js +199 -55
- package/lib/tools/deps.js +8 -0
- package/lib/tools/mcp.js +110 -0
- package/lib/tools/memory.js +87 -0
- package/lib/tools/prompt.js +70 -0
- package/lib/tools/skills.js +139 -0
- package/lib/tools/subagent.js +40 -0
- package/package.json +7 -7
- package/lib/agents-md/preset-id.js +0 -49
- package/lib/rules/service.js +0 -3078
package/README_EN.md
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
[](https://dsh.market/)
|
|
9
9
|
[](https://awesome-dsh-plugin.com)
|
|
10
|
-
[](https://dshfind.com/
|
|
10
|
+
[](https://dshfind.com/en/plugins/ouli-1242/dsh-plugin-tool-management)
|
|
11
|
+
[](https://github.com/0xsline/awesome-deepseek-harness)
|
|
11
12
|
|
|
12
13
|
[简体中文](README.md) · **English** · [Changelog](CHANGELOG.md) · [Release overview](docs/update.md)
|
|
13
14
|
|
|
@@ -39,20 +40,20 @@ Hard-refresh the browser (Cmd/Ctrl+Shift-R) afterwards — a **Tools** panel in
|
|
|
39
40
|
|
|
40
41
|
In one line: **set up a scene for each kind of work — "day job / writing / coding" — and switch the whole stack with one click. Everything the plugin manages, the model can actually see.**
|
|
41
42
|
|
|
42
|
-
| Highlight | What it means
|
|
43
|
-
| ------------------------------------- |
|
|
44
|
-
| One-click scene switch | Each scene carries its own set: which MCP servers, which skills, which personas, which memories; flip it on and the whole stack follows, turn it off and everything comes back
|
|
45
|
-
| Memories reach the model on their own | Write a few `.md` files under a scene and they become its knowledge base — injected automatically, no copy-pasting every session
|
|
46
|
-
| Notes for MCP servers | Write "if A is down, fall back to B" as a note — the model sees it and acts on it
|
|
47
|
-
| Disable a single tool | Keep a server but mute one tool: invisible and uncallable; "Restart" only reconnects and never flips switches
|
|
48
|
-
| Skills at a glance | Which copy is in effect, which is shadowed by a same-name skill, which is preferred — all marked in the list
|
|
49
|
-
| Subagent = one file, one role | Write a role file and delegate; only the result comes back and it never clutters your History; which roles are available can follow the scene
|
|
50
|
-
| Several prompt presets | Keep multiple AGENTS.md baselines (terse mode, teaching tone, …), switch with one click; a scene can bind its own
|
|
51
|
-
| Sessions no longer lost | Archive grouped by project, searchable, batch-restorable; import transcripts from Claude Code / Cursor / Codex
|
|
52
|
-
| The model always sees it | Everything the plugin manages (memories / MCP / skills / subagents / prompts) is announced to the model — one message per domain, republished only on change; under Minimal nothing is injected by default (follows the preset), force any domain on in the Host tab
|
|
53
|
-
| Lock it and relax | Lock a scene to make all five domains read-only; unlock first to change anything
|
|
54
|
-
| Deleted is not gone | Deletes land in a recycle bin and can be restored;
|
|
55
|
-
| Safe by default | Secrets masked, plaintext needs a token; only the plugin's own files are written, skill sources stay untouched, and your config survives restarts and upgrades
|
|
43
|
+
| Highlight | What it means |
|
|
44
|
+
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
+
| One-click scene switch | Each scene carries its own set: which MCP servers, which skills, which personas, which memories; flip it on and the whole stack follows, turn it off and everything comes back |
|
|
46
|
+
| Memories reach the model on their own | Write a few `.md` files under a scene and they become its knowledge base — injected automatically, no copy-pasting every session |
|
|
47
|
+
| Notes for MCP servers | Write "if A is down, fall back to B" as a note — the model sees it and acts on it |
|
|
48
|
+
| Disable a single tool | Keep a server but mute one tool: invisible and uncallable; "Restart" only reconnects and never flips switches |
|
|
49
|
+
| Skills at a glance | Which copy is in effect, which is shadowed by a same-name skill, which is preferred — all marked in the list |
|
|
50
|
+
| Subagent = one file, one role | Write a role file and delegate; only the result comes back and it never clutters your History; which roles are available can follow the scene |
|
|
51
|
+
| Several prompt presets | Keep multiple AGENTS.md baselines (terse mode, teaching tone, …), switch with one click; a scene can bind its own |
|
|
52
|
+
| Sessions no longer lost | Archive grouped by project, searchable, batch-restorable; import transcripts from Claude Code / Cursor / Codex |
|
|
53
|
+
| The model always sees it | Everything the plugin manages (memories / MCP / skills / subagents / prompts) is announced to the model — one message per domain, republished only on change; under Minimal nothing is injected by default (follows the preset), force any domain on in the Host tab |
|
|
54
|
+
| Lock it and relax | Lock a scene to make create/update/delete in all five domains read-only; unlock first to change anything (creating/renaming/binding/activating a scene, the recycle bin, restart, export and token settings are **not** in the frozen list — see Scene lock) |
|
|
55
|
+
| Deleted is not gone | Deletes of skills / memories / personas / presets / scenes land in a recycle bin and can be restored; they also zip out and back in. **Session history is the exception: permanent delete skips the recycle bin and cannot be undone** |
|
|
56
|
+
| Safe by default | Secrets masked, plaintext needs a token; only the plugin's own files are written, skill sources stay untouched, and your config survives restarts and upgrades. **Masking is display-only**: secrets stay in cleartext in `cordis.patch.yml` and in up to 5 backup copies per patch file (see Configuration & security) |
|
|
56
57
|
|
|
57
58
|
## Quick start
|
|
58
59
|
|
|
@@ -85,18 +86,19 @@ The model can manage everything above via 14 tools (`mcp_manager_*` / `skill_man
|
|
|
85
86
|
- **Single-choice toggle**: only one scene at a time (others greyed out); turning all off = only `global` and `_shared` inject. New scenes start off.
|
|
86
87
|
- **Scene-bound prompt**: switching scenes rewrites `~/.dsh/AGENTS.md` (5-gen backup, auto-restore on exit).
|
|
87
88
|
- **Scene profile**: every scene combines MCP tools / skills / subagents / memories (any mix); opening a scene applies and narrows injection, closing restores verbatim (the toggle is the only entry). Checked means on, unchecked means off, and **a missing section means nothing is checked — so that whole domain is off** (a scene with no MCP section therefore stops every MCP server, and exit starts them again). While a scene is active those switches (MCP, skills, subagents) still work — changes are written into that scene's profile too (they take effect immediately and are kept for the next visit); only locking freezes them. The memory domain has a single source of truth and never goes through the profile.
|
|
89
|
+
- **"Entering/leaving the mode" and "enabling a scene" are two independent state axes**: the UI toggle is the only entry point (it moves both axes at once). If you bypass the UI and call the HTTP API directly, note that `scene-mode-set{scene:null}` only drops the runtime snapshot and does **not clear the enabled set** — memories and the prompt keep being injected for that scene; a full exit also needs `rules-set-active{scenes:[]}`.
|
|
88
90
|
- **Import**: `.md` / `.zip` (dir name = scene, bundles carry attachments), same names skipped never overwritten, over-limit items reported.
|
|
89
91
|
- **Export**: pick memories and zip them, keeping the `scene/name` layout; bundle memories bring their attachments along. Sources are read-only.
|
|
90
92
|
- **Injection budget**: default 64 KiB, oversized memories skipped with a list. Deletes go to recycle bin.
|
|
91
93
|
- **Subagent sessions do not receive memories**: memories are injected into the **top-level session only** — they are the parent's situation, not the facts a child needs; a child's context stays "persona + task", it can read memories on demand with `memory_manager_list/read`, and relevant facts belong in the `task`. Other domains are unaffected (MCP / skills / prompts still inject; the persona catalog follows each persona's `catalogDepth`).
|
|
92
|
-
- **Scene lock**: once locked, MCP / skills / subagents / memories / prompts
|
|
94
|
+
- **Scene lock**: once locked, create/update/delete across MCP / skills / subagents / memories / prompts is read-only — UI disabled plus a server-side guard; a scene must be running to lock, and a locked scene can't be closed until unlocked. **What freezes is the content, not the scene itself**: creating/deleting/renaming a scene, rebinding its prompt, switching the active set, recycle-bin restore and purge, MCP restart, export, injection settings and token settings are all outside the frozen list (they are not "content of the scene profile"). Switching the active set *is* refused while a locked scene is in effect — clearing it would leave the model-side write guard with nothing to check while the runtime still runs that scene's profile.
|
|
93
95
|
- **Deleting a scene deletes its memories too**: the scene record, profile and every memory go into one recycle-bin entry, restored as a whole; a running scene refuses deletion. Scene names are renameable (dir and profile follow, memory bodies untouched).
|
|
94
96
|
|
|
95
97
|
### Subagents
|
|
96
98
|
|
|
97
99
|
- **One file per persona**: `agents/<persona>.md`, frontmatter entirely optional.
|
|
98
100
|
- **A persona reaches the subagent's system prompt inside a role frame**: the body is used verbatim, wrapped in a `# Persona: <name>` heading, one authorizing line ("specified by the caller; where it conflicts with your default inclinations, it wins; the task states what to achieve, and this persona governs how") and one boundary line (it governs *how* you work, not *what* you may do), with the body fenced under `## Persona`. The frame follows the body's language. This makes the model read it as "I have been assigned a role" rather than as two stray sentences following the identity line — **the persona file itself needs no change**. The frame does not include `description`: that field exists so the *caller* can pick a persona; an introduction meant for the child belongs in the body.
|
|
99
|
-
- **Tool limits per Agent preset**: each preset gets its own allow/deny list (mutually exclusive), effective at runtime by the current preset — fixes the old "union of all presets" list that broke subagents after a preset switch.
|
|
101
|
+
- **Tool limits per Agent preset**: each preset gets its own allow/deny list (mutually exclusive), effective at runtime by the current preset — fixes the old "union of all presets" list that broke subagents after a preset switch. Two behaviours to know: **① an allow list is merged back with every currently running `mcp__*` tool** (the official `allow` means "cut everything outside the list", and not merging would cut MCP too), so ticking only `read` will not stop an MCP server that exposes a shell; **② when none of the listed names exists right now, the result is "no restriction"** (fail-open, not fail-closed) — on minimal presets an allow list easily ends up empty. The opposite failure is naming the reserved tool `run_code`: the official `tools.restrict()` throws outright (the subagent never starts), so the plugin strips it from the list and says so in the result.
|
|
100
102
|
- **`output:` hard output contract**: frontmatter may carry multiple `output:` lines (**one requirement per line**); the role frame renders them as a separate `## Output requirements (hard)` section after the persona definition. Use the prompt for how the role thinks (prose) and `output:` for what the deliverable must look like (format, severities, required markers, bans) — a persona with only an abstract requirement produces output nobody can check, and only checkable requirements actually get followed. The editor has an "Output requirements (hard)" box, and you can write the lines into the file directly.
|
|
101
103
|
- **Run and discard**: `subagent_manager_run` runs with the persona, returns only the result, never enters History. A child's context is **persona + task** only: memories are not injected (the child can read them with `memory_manager_*`, and relevant facts belong in the `task`). Scenes can bind which personas are available.
|
|
102
104
|
- **Two context modes**: by default the child starts fresh (it cannot see this conversation, so the task must be complete); with `inherit` the child is seeded with this conversation's **finished** turns (the same mechanism as the host's `subagent_fork`) and the task only states what is new. Only finished turns are inherited — a delegation made during the current turn cannot pass that turn's content (measured: a parent that delegated while still reading left the child to start from scratch), so treat `task` as self-contained in that case. The boundary against the host's two delegation tools (`subagent` / `subagent_fork`) is written into the context by this plugin: **work that matches a persona goes here**, and the host tools are for when no persona fits or a background job is needed.
|
|
@@ -109,7 +111,8 @@ The model can manage everything above via 14 tools (`mcp_manager_*` / `skill_man
|
|
|
109
111
|
- **CRUD + immediate effect**: writes to `cordis.patch.yml`, HMR picks it up.
|
|
110
112
|
- **Per-tool switches**: disable individual tools (invisible to the model, blocked at call), whole-server batch.
|
|
111
113
|
- **Stopped servers still show their tools**: a server that is not running keeps the tool names and descriptions last seen (marked "as of last run"); one that has never run can be probed with "start server to read tools".
|
|
112
|
-
- **Secret masking**:
|
|
114
|
+
- **Secret masking**: a credential is replaced **as a whole** by `••••••`, and only for keys that look sensitive (token / secret / password / auth / api key and friends); `$VAR` and `!!js` are indirections, so they stay readable, and a URL's query string becomes `?<redacted>`. "Reveal" needs a token.
|
|
115
|
+
- **A masked value is never written back into the patch file**: the edit dialog prefills secret fields with the masked text, so on save the plugin restores the value found in the patch file (= that field was left alone). When there is no original value, or the stored one is itself masked (meaning the real value was destroyed earlier), the key is skipped and the panel says so — in the latter case you have to fill it in again. Secrets already stored as a mask are reported as soon as you open the page. **A URL gets the same protection in a different shape**: its query string is masked as `?<redacted>` and is likewise restored from the stored value on save; when the patch holds nothing to restore, **the whole save is refused** with a prompt to retype the full URL — dropping the query silently would leave an address that connects but fails authentication, which is harder to notice than an error.
|
|
113
116
|
- **Migrate & back up**: cross-project/global migration rolls back on failure; JSON export/import.
|
|
114
117
|
- **Status & notes enter the system prompt**: currently usable servers are listed; **one that has connected before but cannot right now is also listed and labelled** (`(当前未连上;上次连上时 N 个工具)`) — so the model says "it is not connected, check it" instead of reading "configured but unreachable" as "not configured here" and suggesting you install one. Servers that have never connected are omitted. Your notes travel along as decision hints; levels are "global / app", new servers default to global. Note: a persona-complete preset such as minimal suppresses that section — there the model reads server names, enablement, tool counts and notes with `mcp_manager_list`.
|
|
115
118
|
|
|
@@ -120,26 +123,29 @@ The model can manage everything above via 14 tools (`mcp_manager_*` / `skill_man
|
|
|
120
123
|
- **Remove ≠ disable**: remove = directory not scanned at all (files untouched, restorable); disable = still listed but not callable.
|
|
121
124
|
- **Same-name skills: see which copy is in effect**: the winning copy is marked "preferred", shadowed ones name the source that wins, and enabling a shadowed copy says so instead of pretending it worked.
|
|
122
125
|
- **Custom dirs / ZIP import & export / recycle bin**.
|
|
126
|
+
- **Directories can be injected**: when a preset mounts no official skills-directory line (e.g. Minimal), this plugin's injection domain delivers them as a fallback, governed by the switches on the Host page (name + blurb; the body is still read from disk).
|
|
123
127
|
|
|
124
128
|
### Prompt presets
|
|
125
129
|
|
|
126
130
|
- Multiple `~/.dsh/AGENTS.md` baselines, one-click apply (the host re-reads that file every turn, so it takes effect on the next turn), 5-gen backup.
|
|
127
131
|
- **Remembers the preset applied last**: even after you hand-edit `AGENTS.md`, the model can still answer "which preset is this from" (flagged "changed since").
|
|
128
132
|
- **Description**: one line saying what a preset is for — shown in this panel only. It lives in a sibling `meta.json`, never in AGENTS.md, so it is never injected into prompts.
|
|
129
|
-
- Create with body inline, edit can change id (= dir rename, scene bindings follow). A referenced preset cannot be deleted (
|
|
133
|
+
- Create with body inline, edit can change id (= dir rename, scene bindings follow). A referenced preset cannot be deleted (scene binding / current contents of `AGENTS.md` / the one to restore when leaving the scene); deletes go to the recycle bin.
|
|
134
|
+
- **The body can be injected**: when a preset mounts no official AGENTS.md line (e.g. Minimal), this plugin's injection domain delivers the body of `~/.dsh/AGENTS.md` as a fallback (64 KiB cap; can be turned off on the Host page).
|
|
135
|
+
- **While a scene drives the baseline, Apply rebinds the scene to that preset** (bound by a scene, currently in AGENTS.md, or the baseline to restore on scene exit); deletes go to recycle bin.
|
|
130
136
|
- **While a scene drives the baseline, Apply rebinds the scene to that preset** (written into the scene profile, and the binding realigns immediately; allowed while unlocked — v0.9 reversed the old "other presets are refused" behavior); **only locking refuses**. The global baseline is restored from the snapshot on scene exit.
|
|
131
137
|
|
|
132
138
|
### Archived sessions
|
|
133
139
|
|
|
134
140
|
- Grouped by project, search, batch restore / delete, retention auto-cleanup.
|
|
135
141
|
- Workspace registration deleted → group rebuilt from session dirs, one-click re-register.
|
|
136
|
-
- Import Claude Code / Cursor / Codex / any text; export Markdown / JSONL.
|
|
142
|
+
- Import Claude Code / Cursor / Codex / any text; export Markdown / JSONL. **An export is a readable transcript, not a full backup**: only user/assistant text blocks survive — tool calls, images, reasoning and token stats are dropped, and a `## User` line inside a Markdown body will be read as a turn boundary on re-import (the exporter does not escape it). Use archiving if you need the full record.
|
|
137
143
|
|
|
138
144
|
### Host compatibility
|
|
139
145
|
|
|
140
146
|
The plugin uses the host's own `@deepseek-ai/*` libraries at runtime — they must be the same physical modules, or every "adapt to host" decision degrades into guesswork.
|
|
141
147
|
|
|
142
|
-
- **Host tab**: host version, usable capability count, per-action routing (native/adapter/unavailable), degradations & reasons.
|
|
148
|
+
- **Host tab**: host version, usable capability count, per-action routing (native/adapter/unavailable), degradations & reasons. The check-up itself is read-only, but the page has two explicit write entries: **access token** (writes the profile's `cordis.patch.yml`, takes effect after restart) and **injection settings** (writes `inject-settings.json`, takes effect immediately).
|
|
143
149
|
- **Command line**: `node scripts/doctor.mjs` (check), `node scripts/host-deps.mjs --fix` (align deps), `npm run sync:profile` (mirror the build into the profile's local install — a `file:` install is a hard-linked copy, so files ADDED by a build never show up there on their own).
|
|
144
150
|
- Under a **suppressing preset** such as `minimal` (persona `complete` / runtime context off) this plugin's injection is **off by default** (following the preset's intent), and the prompt and the skills are missing because their official rows are not mounted — the Host tab marks this per column, and its "Injection" block can force any domain back on.
|
|
145
151
|
- **Unchecking "Skills" or "Prompt" really stops them**: under standard presets the host delivers those two itself (the plugin steps aside), so unchecking now also stops the host's copy — the `skill-catalog` / `agent-instructions` messages are no longer let through on that step. The other three domains (memory / MCP / subagents) are only ever sent by this plugin, so their toggles were already complete.
|
|
@@ -155,7 +161,8 @@ The plugin uses the host's own `@deepseek-ai/*` libraries at runtime — they mu
|
|
|
155
161
|
| Skill policy / custom dirs | `~/.dsh/tool-management/skills-state.json` |
|
|
156
162
|
| Skills / memories / personas / presets | `~/.dsh/tool-management/{skills,memories,subagents,prompts}/` |
|
|
157
163
|
| Subagent toggles | `~/.dsh/tool-management/subagents-index.json` |
|
|
158
|
-
| Recycle bin
|
|
164
|
+
| Recycle bin (skills/personas/presets/scenes) | `~/.dsh/tool-management/trash/{skills,subagents,prompts,scenes}-trash/` |
|
|
165
|
+
| Memory recycle bin | `~/.dsh/tool-management/memories-trash/` (**a directory at the hub root, not under `trash/`**) |
|
|
159
166
|
| Archive ledger / retention | `~/.dsh/tool-management/history-*.json` |
|
|
160
167
|
| Memory index / scenes / profiles | `~/.dsh/tool-management/memories-index.json` |
|
|
161
168
|
| MCP sidecars (disabled tools / known tools / notes / settings) | `~/.dsh/tool-management/mcp-*.json` |
|
|
@@ -164,27 +171,41 @@ The plugin uses the host's own `@deepseek-ai/*` libraries at runtime — they mu
|
|
|
164
171
|
|
|
165
172
|
**No user data is stored inside the plugin's install directory** (`dsh plugin update` replaces it wholesale).
|
|
166
173
|
|
|
167
|
-
|
|
174
|
+
**`backups/` keeps 5 copies per patch file**: backup names carry a layer tag (`.global` / `.profile-<name>`), so the global patch and each profile patch keep 5 each — not 5 in total. A single bulk action (e.g. `mcpm-set-all`, or the several writes of entering a scene) can consume all 5 slots of one layer and push out earlier versions.
|
|
168
175
|
|
|
169
|
-
|
|
170
|
-
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
171
|
-
| `token` | Access token. When set, **all writes + plaintext secrets** require `x-dsh-token`; **unset = plaintext endpoints closed**. Also the escape hatch for curl / LAN. |
|
|
172
|
-
| `maxBodyBytes` | Request body cap, default 88 MiB. |
|
|
176
|
+
## Configuration & security
|
|
173
177
|
|
|
174
|
-
|
|
178
|
+
| Field | Description |
|
|
179
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
180
|
+
| `token` | Access token. When set, **all writes + plaintext secrets** require `x-dsh-token`; **unset = plaintext endpoints closed**. Also the escape hatch for curl / LAN. If you would rather not keep the token in the config file, set the `DSH_PLUGIN_TOOL_MANAGEMENT_TOKEN` environment variable instead (when both are present `config.token` wins; `tokenDisabled: true` disables both). |
|
|
181
|
+
| `tokenDisabled` | `true` = the token **stays in the config** but is not in effect (this is the line written by "Turn protection off"). Writes no longer require a token; plain-text reveal still does (the plain text *is* the credential). Switch it back on any time with "Turn protection on" — no need to retype it. |
|
|
182
|
+
| `maxBodyBytes` | Request body cap, default 88 MiB. |
|
|
183
|
+
|
|
184
|
+
- **Browser**: reads/writes via cookie, no token needed; but **plaintext secrets** (Reveal / export) need a token. **The token is managed under Tools → Compatibility → Access token** — a fixed entry point independent of the page. That block is one status pill + one plain sentence + three rows: the row label names the scope, the button names the verb, and the pill only answers "is protection on, is this run unlocked".
|
|
185
|
+
- **This run**: fill once, valid until DSH exits (stored in this browser only). Once accepted, the row turns into a green **Unlocked** chip plus Clear, right where the input was (it used to collapse to a lone Clear button, which read as "what I just typed is gone"); only then does the host accept this token and the two rows below become usable. The row is not shown at all while the host has no token (there is nothing to check it against).
|
|
186
|
+
- **Host config**: written into the profile's `cordis.patch.yml` (only those two lines change — comments and the `!!js` guard stay intact, and the previous file is backed up first); takes effect after a DSH restart. With no host token this row's button is the primary one ("Set token") and asks for the new token **twice** (a typo here means even you cannot match it). Once one is set, "Change token" opens a form with an extra **current token** field — changing it requires proving you know the current one, and being unlocked does **not** count (same rule as turning protection off): you must retype it in the form. The cursor lands in that field when the form opens; the three fields are **stacked** with Save/Clear below them (while the form is open it is the only row shown, and Enter submits), "Save new token" stays disabled until all three are filled, and a rejected token marks that field red.
|
|
187
|
+
- **Protection switch**: clicking "Turn protection off" opens an in-place confirm box (the only row shown while it is open — same rule as "Change token") that asks you to **type the current token again** (yes, even while unlocked — the already-verified credential in the request header does *not* count for turning protection off; otherwise one click right after unlocking would drop the guard). On confirm it only writes `tokenDisabled: true`, so **the token itself stays in the config** and "Turn protection on" brings it back without retyping. While off, writes no longer require a token; **plain-text reveal still requires it** (the plain text *is* the credential). Turning it on keeps the old rule: being unlocked, or having the token in the input box, is enough — otherwise anyone who can open the GUI could switch the protection off.
|
|
188
|
+
- **Delete token** (same row as "Change token"): removes both the `token` and `tokenDisabled` lines from the config, going back to the **never-set-up** state — writes need no token and plain-text secrets become unreadable again. It also opens an in-place confirm box asking for the current token, and the result honestly notes that "old backups still hold plaintext copies" (each backup is a full copy of the config; use "Clean old backups" in the page header to clear those too). Use the protection switch instead when you only want the gate off for now and want to keep the token.
|
|
189
|
+
- **Status pill**: No token yet / Protection off / Protection on · locked / Protection on · unlocked. When the config has been changed but DSH has not restarted, an amber banner below says so (the pill reflects the running process).
|
|
190
|
+
- **No "fill in the token" notice while the token is not in effect**: that notice stays only while something is actually gated (a token is in effect on the host). With the token off or unset it is dropped, and the panel's status pill tells you what is going on instead.
|
|
191
|
+
- **Where the notice appears**: the "missing or wrong access token" sentence (with its "Fill in token" button) exists **exactly once** — inside the dialog while one is open (that is what blocks your action, so it belongs in plain sight), just below the tabs otherwise. It does not depend on which page you are on or how that page renders errors, so no entry point (dialog submits, imports, exports, bulk actions) can lose it.
|
|
175
192
|
- **curl / scripts**: send `x-dsh-token`, or carry the browser cookie.
|
|
193
|
+
- **HTTP status convention**: except for the fence's 401/403, a missing token or a business failure is **HTTP 200 + `{ ok: false, error }`** — branch on `body.ok`, not on the status code.
|
|
194
|
+
- **The fence's degraded mode**: when the host has no `connection` service, the fence falls back to "loopback Host + same-origin" (there is no browser cookie to check), so any local process can call write ops by faking `Host: localhost`. If you forward the port to a LAN or the public internet, **configure a token** — it is the last door on that degraded path.
|
|
195
|
+
- **`dir-list`'s exposure**: the "pick a folder" dialog walks directories through it, so any caller past the fence/token can list directories at **any absolute path** (read-only). That is by design, not a hole — but do not expose the port to an untrusted network.
|
|
196
|
+
- **Plaintext on disk (read this)**: masking is a **display-only** measure. MCP `env` / `headers` and the plugin's own `config.token` stay in cleartext inside `~/.dsh/cordis.patch.yml` (and its per-profile copy), and every config change copies the **whole file** into `~/.dsh/tool-management/backups/` (5 copies kept **per patch file**, unencrypted, never rotated, never reclaimed on uninstall) — one secret can end up as `5 × (patch files holding it) + 1` plaintext copies. The token gate decides *who may read plaintext over HTTP*; it does nothing about *reading the files*. Any local process with read access to that directory can take every credential at once. **To clean up: Settings → Tools → Compatibility → "Clean old backups"** (next to Refresh — the button itself shows the current count) — pick how many to delete **per layer** (N deletes that layer's N oldest; the tiers run up to that layer's current count, default 2) — each layer has its own group, so any total is reachable, odd ones included; each row states what would be left, and the dialog asks you to confirm once more, stating the total number of files in that confirmation. Only backup files are touched, never the live config. You can also delete old files under `~/.dsh/tool-management/backups/` by hand.
|
|
176
197
|
- **Port forwarded to public**: configure a token — prevents strangers injecting MCP commands (≈ remote code execution) and stealing secrets.
|
|
177
198
|
|
|
178
199
|
## FAQ
|
|
179
200
|
|
|
180
|
-
| Symptom | Fix
|
|
181
|
-
| ----------------------------------------------------------------- |
|
|
182
|
-
| Pages missing after install | Hard refresh; restart DSH if that fails.
|
|
183
|
-
| Duplicate MCP tabs | Remove the stale loader row from `cordis.patch.yml`, restart.
|
|
184
|
-
| Broken config, DSH won't boot | Restore the newest `.bak-<timestamp>`.
|
|
185
|
-
| Action stopped after DSH upgrade | Settings → Tools → **Host** for the reason; `doctor.mjs` → `host-deps.mjs --fix`.
|
|
186
|
-
| Still asked to confirm in `approval=never`? | No card appears — straight through with a log line; switch back to "workspace write" to get asked again.
|
|
187
|
-
| `subagent_manager_run` reports provider unavailable
|
|
201
|
+
| Symptom | Fix |
|
|
202
|
+
| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
203
|
+
| Pages missing after install | Hard refresh; restart DSH if that fails. |
|
|
204
|
+
| Duplicate MCP tabs | Remove the stale loader row from `cordis.patch.yml`, restart. |
|
|
205
|
+
| Broken config, DSH won't boot | Restore the newest `.bak-<timestamp>`. |
|
|
206
|
+
| Action stopped after DSH upgrade | Settings → Tools → **Host** for the reason; `doctor.mjs` → `host-deps.mjs --fix`. |
|
|
207
|
+
| Still asked to confirm in `approval=never`? | No card appears — straight through with a log line; switch back to "workspace write" to get asked again. |
|
|
208
|
+
| `subagent_manager_run` reports provider unavailable | The provider isn't registered: `spawn` (default) / `fork` (`inherit`) come from `@deepseek-ai/dsh-subagent-spawn-in-process` / `-fork-in-process` — mount and restart. |
|
|
188
209
|
| Scene binds persona A, but official `subagent` ran something else | Those two are host tools and this plugin cannot hide them; it writes the boundary into the context instead (work matching a persona goes to `subagent_manager_run`; host tools only when no persona fits or a background job is needed), and `inherit` now matches fork's context inheritance. |
|
|
189
210
|
|
|
190
211
|
---
|
|
@@ -194,7 +215,7 @@ The plugin uses the host's own `@deepseek-ai/*` libraries at runtime — they mu
|
|
|
194
215
|
```bash
|
|
195
216
|
npm install
|
|
196
217
|
npm run build # tsc + sync client
|
|
197
|
-
npm test # build + i18n +
|
|
218
|
+
npm test # build + i18n + contract tests (pure-function invariants & host contracts; UI tests removed 2026-09-19)
|
|
198
219
|
npm run check:i18n # dictionary self-check
|
|
199
220
|
npm run doctor # host compatibility check
|
|
200
221
|
```
|
package/docs/images/1-EN.png
CHANGED
|
Binary file
|
package/docs/images/1.png
CHANGED
|
Binary file
|
package/docs/images/2-EN.png
CHANGED
|
Binary file
|
package/docs/images/2.png
CHANGED
|
Binary file
|
package/docs/images/3-EN.png
CHANGED
|
Binary file
|
package/docs/images/3.png
CHANGED
|
Binary file
|
package/docs/images/4-EN.png
CHANGED
|
Binary file
|
package/docs/images/4.png
CHANGED
|
Binary file
|
package/docs/images/5-EN.png
CHANGED
|
Binary file
|
package/docs/images/5.png
CHANGED
|
Binary file
|
package/docs/images/6-EN.png
CHANGED
|
Binary file
|
package/docs/images/6.png
CHANGED
|
Binary file
|
package/docs/images/7-EN.png
CHANGED
|
Binary file
|
package/docs/images/7.png
CHANGED
|
Binary file
|
package/docs/images/8-EN.png
CHANGED
|
Binary file
|
package/docs/images/8.png
CHANGED
|
Binary file
|
package/docs/update.md
CHANGED
|
@@ -2,55 +2,148 @@
|
|
|
2
2
|
|
|
3
3
|
每个版本大致改了什么——想知道「升上去会变什么」看这里就够了。逐条细节见 [Changelog](../CHANGELOG.md),功能说明见 [README](../README.md) / [README_EN](../README_EN.md)。
|
|
4
4
|
|
|
5
|
-
| 版本
|
|
6
|
-
|
|
7
|
-
| [0.
|
|
8
|
-
| [0.
|
|
9
|
-
| [0.9.
|
|
10
|
-
| [0.
|
|
11
|
-
| [0.8.
|
|
12
|
-
| [0.
|
|
13
|
-
| [0.
|
|
14
|
-
| [0.
|
|
15
|
-
| [0.5.
|
|
16
|
-
| [0.
|
|
5
|
+
| 版本 | 发布 | 主题 |
|
|
6
|
+
| ---------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
7
|
+
| [0.11.0](#0110---2026-09-20) | 2026-09-20 | 访问令牌卡片重构(可设置 / 关闭 / 修改 / 删除)+ 没解锁时锁住输入框 + 令牌安全修复 + 批量启停可撤销 + 兼容页清理旧备份 + 两页可搜索 + 体检改为真调 + 一批凭据与数据损坏修复 + 搜索与列表提速 |
|
|
8
|
+
| [0.10.0](#0100---2026-09-18) | 2026-09-18 | 注入框架改 markdown(动作句加粗前置)+ 注入采纳统计 + 人设角色框 / inherit / catalogDepth + 场景锁定补齐模型侧 + 记忆删除全走回收站 + 错误码全量双语 |
|
|
9
|
+
| [0.9.1](#091---2026-09-17) | 2026-09-17 | 注入实况 + 场景内开关同步档案 + 全选统一 + 退出场景卡死修复 |
|
|
10
|
+
| [0.9.0](#090---2026-09-16) | 2026-09-16 | 注入改走上下文通道(极简可注入)+ 五域各自注入 + 场景接管一致性修复 |
|
|
11
|
+
| [0.8.5](#085---2026-09-16) | 2026-09-16 | 历史页标签统一 + 目录存在即可重新登记 + 场景 MCP 备注 + 新增三域默认不启动 |
|
|
12
|
+
| [0.8.0](#080---2026-09-15) | 2026-09-15 | 场景锁定 + 子智能体开关 + 四域导出 |
|
|
13
|
+
| [0.7.0](#070---2026-09-15) | 2026-09-15 | 回收站全量 + 预设注入可见性 + 密钥令牌化 |
|
|
14
|
+
| [0.6.0](#060---2026-09-14) | 2026-09-14 | 宿主兼容体检 + 兼容页 |
|
|
15
|
+
| [0.5.1](#051---2026-09-13) | 2026-09-13 | 场景档案默认不勾选 + 场景页排版重做 |
|
|
16
|
+
| [0.5.0](#050---2026-09-13) | 2026-09-13 | 数据目录统一 + 场景显式化 + 界面重做 |
|
|
17
|
+
| [0.2.0](#020---2026-09-12) | 2026-09-12 | 五域合并进一个「工具」面板 |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 0.11.0 - 2026-09-20
|
|
22
|
+
|
|
23
|
+
- **访问令牌那块整个重排了,按作用域拆成两块**:「访问令牌」只管本次启动(状态胶囊 + 解锁框),「令牌管理」只管配置文件 —— 设置/修改、保护开关、删除、清除令牌四行静态清单,位置尺寸统一。所有写配置的操作都在弹窗里完成(要输一次令牌确认),页面不再有会展开收起的东西;成功就是弹窗收起 + 状态行更新,失败错误显示在弹窗内。
|
|
24
|
+
|
|
25
|
+
- **访问令牌能设置、能关掉、能改、也能彻底删掉了**:关掉只是"暂时不生效",令牌留在配置里,随时开回来不用重填。
|
|
26
|
+
|
|
27
|
+
- **关闭 / 修改 / 删除令牌都要当场再输一次当前令牌**:解锁过不算,三个销毁方向同一套就地确认。
|
|
28
|
+
|
|
29
|
+
- **用环境变量提供令牌的用户**:以前「保护开关」会把开着的保护显示成"开启保护"、找不到关闭入口 —— 现在方向按实际生效状态判断;文件里没有令牌值时「删除令牌」也不再显示。
|
|
30
|
+
|
|
31
|
+
- **两处残留清理**:宿主没配令牌但浏览器里记着旧令牌时,现在有「清除令牌」入口;别处触发"去填令牌"时,会先收起弹窗再聚焦解锁框。
|
|
32
|
+
|
|
33
|
+
- **「令牌未验证」的橙色横幅能手动关掉了**:它以前层级压过一切、会盖住宿主设置窗口;现在降到弹窗之下、带关闭键,关掉后本次锁态期间不再弹,解锁后再锁照常回来。
|
|
34
|
+
|
|
35
|
+
- **堵上一个令牌漏洞**:解锁一次后「清除令牌 + 强刷新」,对话照样能发 —— 宿主侧"本次启动验过"的记号只挂不清。现在清除令牌会把这个记号一并摘掉,必须重新填对令牌才能继续对话;其它标签页里残留的旧令牌也同步作废。
|
|
36
|
+
|
|
37
|
+
- **令牌开着、本次启动还没解锁时,输入框锁住、无法对话**:对话不经过插件的 HTTP 门禁,此前配了令牌没填也照样能聊、注入照样进上下文。现在这种情况输入框直接锁住并说明去哪填,填对后立刻恢复。
|
|
38
|
+
|
|
39
|
+
- **兼容页能清理旧备份了**:每份备份都是整份配置的副本、凭据在里面是明文。逐层级选删除份数,弹窗内二次确认,只删备份、不碰当前配置。
|
|
40
|
+
|
|
41
|
+
- **批量启停可以撤销了**:改完出现一条不会自动消失的提示,点「撤销」按操作前的状态写回。
|
|
42
|
+
|
|
43
|
+
- **提示词页与子智能体页能搜了**:一个输入框按名称 / 描述过滤,无命中说「没有匹配的…」。
|
|
44
|
+
|
|
45
|
+
- **兼容体检改为真调一次**:归档 / 解档 / 批量 / 删除与会话 detach / announce 各用一个哨兵 id 真调,调不通就降级并说清原因。
|
|
46
|
+
|
|
47
|
+
- **打码的密钥不会被「保存」写坏**:以前改完保存会把打码值当真值写回,真密钥永久丢失;现在用原值顶替,没原值就拒绝保存。
|
|
48
|
+
|
|
49
|
+
- **「设置令牌」不再可能把 DSH 写坏到起不来**:`config:` 形状认不出来就拒绝改写,不再插入重复键。
|
|
50
|
+
|
|
51
|
+
- **记忆索引损坏不再静默清空配置**:坏文件留存、拒绝写入并说明怎么办。
|
|
52
|
+
|
|
53
|
+
- **一批静默失败现在会明说**:子代理工具没注册上(子智能体页黄条)、记忆正文读不到(记忆页告警条)、开关没写进去、批量归档部分失败、导出撞名跳过。
|
|
54
|
+
|
|
55
|
+
- **几处会丢东西的坑**:编辑 MCP 服务器不再把 URL 里的凭据写成占位串;导出会话不再覆盖同名文件;MCP 重启中断不再把服务器留在停用态。
|
|
56
|
+
|
|
57
|
+
- **导入文件不再让设置面板变空白**;**详情弹窗不再被晚到的响应搅乱**;**「显示密钥」真的能显示明文了**。
|
|
58
|
+
|
|
59
|
+
- **令牌提示统一成一句话**,不再几秒后自己消失,且在弹窗里也看得见。
|
|
60
|
+
|
|
61
|
+
- **锁定场景补上一个绕开方式**:清空启用集合会让模型侧的锁定判据失效,现在会被拒绝。
|
|
62
|
+
|
|
63
|
+
- **场景名末尾带空格或点会被当场拦下**(界面与宿主此前两套校验、已经分叉)。
|
|
64
|
+
|
|
65
|
+
- **搜索与列表变快了**:六页搜索改成停手约 200ms 才过滤,列表只在数据或搜索词真变了才重算;会话批量删除不再逐条重扫全部会话。
|
|
66
|
+
|
|
67
|
+
- **导出与超大请求体加了边界**:单文件 32 MB / 合计 256 MB,超了明确报错;注定超限的上传在开始读之前就拒掉。
|
|
68
|
+
|
|
69
|
+
- **键盘可达与「减少动态效果」**:导入拖拽区变成真按钮、工具页签补上方向键切换;系统开了减少动态效果后,开关 / 拖拽区 / 预算条不再有过渡。
|
|
70
|
+
|
|
71
|
+
- **没配访问令牌时,查看明文密钥不再要求令牌**:此前点「显示密钥」只有一句"缺少访问令牌",跳到兼容页也没有任何可填的东西。有令牌(含"关掉保护")时照旧要带对的。
|
|
72
|
+
|
|
73
|
+
- **「注入」设置块不再因为没填令牌而整块消失**:读设置不再按写操作门禁(写仍然要令牌),所以不必先填令牌、也不必刷新页面。
|
|
74
|
+
|
|
75
|
+
- **技能 / 子智能体 / 记忆三页会显示场景与锁定横幅了**:此前服务端标了、界面读不到。顺带修掉一个更实的:记忆页的写控件在场景锁定时**从没被禁用**过。
|
|
76
|
+
|
|
77
|
+
- **场景锁定期间不再显示「改动会同步写进场景档案」那条长提示**:开关都是灰的,那句话没有落点,还与锁定横幅并排矛盾。
|
|
78
|
+
|
|
79
|
+
- **批量启停的撤销条改成琥珀色**:边框、提示句都染成告警色,更容易看见。
|
|
80
|
+
|
|
81
|
+
- **文档与实现对齐**:README 补上此前没写的边界(锁定到底冻结哪些、会话删除不进回收站、密钥在磁盘上始终是明文等)。
|
|
17
82
|
|
|
18
83
|
---
|
|
19
84
|
|
|
20
85
|
## 0.10.0 - 2026-09-18
|
|
21
86
|
|
|
22
87
|
- **「注入实况」显示每个域的采纳统计**:「注入 N 次 · 调用 M 次 · 采纳 K 次」,勾了开关但模型从没伸手一眼可见;节头并标注本进程观测到的工具调用数,区分「模型没用」与「统计没接上」。
|
|
88
|
+
|
|
23
89
|
- **人设可配「目录注入」(`catalogDepth`)**:控制常驻人设目录注入到哪一层会话(默认只在顶层),不限制子代理继续嵌套。
|
|
90
|
+
|
|
24
91
|
- **人设子代理支持 `inherit`**:继承本次会话**已完成**的轮次(本轮内委派仍要写全任务);贴合人设的任务从此一律走 `subagent_manager_run`,官方 `subagent` / `subagent_fork` 只在没人设贴合或需要后台任务时用。
|
|
92
|
+
|
|
25
93
|
- **人设新增「输出要求」字段(`output:`)**:一行一条硬要求,单独成节写进子代理系统提示词,并约束父代理的 `task` 只给目标与上下文、不规定做法。
|
|
26
94
|
|
|
27
95
|
- **注入框架重排为 markdown 四级结构**:`##` 标题 + 加粗动作句前置 + 补充动作行 + 取代声明,五域同一副骨架;场景记忆与子智能体引导语同步重写(给判据、给优先级、补触发条件),正文重复标题与「已清空」通知的插件前缀一并去掉。
|
|
96
|
+
|
|
28
97
|
- **提示词注入不再「裸送」**:与其余四域同款框架且整条包进 `<system-reminder>`(正文里的闭合标记会转义),界面显示来源文件与载入状态,模型侧正文带「来源:」行。
|
|
98
|
+
|
|
29
99
|
- **关掉「技能」或「提示词」的勾选,官方那条注入一起停**(此前只停本插件自己);其余三域勾选完全生效。
|
|
100
|
+
|
|
30
101
|
- **子代理会话不再注入场景记忆**(只在顶层注入),子代理上下文收敛为「角色 + 任务」,需要时用 `memory_manager_*` 自取。
|
|
102
|
+
|
|
31
103
|
- **人设进子代理系统提示词时带角色框**:`# 角色:名` 标题 + 授权/边界一行 + `## 角色定义` 围栏,不含 `description`,人设文件本身不用改。
|
|
104
|
+
|
|
32
105
|
- **MCP 列表改为全局在前、同级按名排序**,页面、场景档案勾选器与模型侧清单三处同序。
|
|
106
|
+
|
|
33
107
|
- **人设目录的注入判据定为「深度 < `catalogDepth`」**;「注入实况」两档状态改称「已注入 / 不在本会话注入」,无正文行不再画展开箭头。
|
|
108
|
+
|
|
34
109
|
- **五个管理工具的描述回指上下文里的注入块**,目录与工具互相指路。
|
|
110
|
+
|
|
35
111
|
- **全部服务端错误码补齐双语词条**(此前 15 码无词条,英文界面回退中文原文);目录选择器与技能详情 frontmatter 标签同样改走词典。
|
|
112
|
+
|
|
36
113
|
- **README 安全段补充**:栅栏降级面、`dir-list` 暴露面、HTTP 状态码以 `body.ok` 为准、裸 API 退出场景不清启用集。
|
|
114
|
+
|
|
37
115
|
- **文档更正**:人设「默认停用」(此前写成自动启用)、场景接管期间「应用 = 改绑该场景」(此前写会被拒绝)、「四域开关同步档案」更正为三域(并更正 0.9.1 条目同句)、密钥打码字形改为与实现一致。
|
|
38
116
|
|
|
39
117
|
- **场景锁定补齐模型侧**:`mcp_manager_add` / `skill_manager_create` / `memory_manager_write` / `prompt_manager_apply` 四个工具此前绕过守卫,锁定期间仍可调用。
|
|
118
|
+
|
|
40
119
|
- **记忆怎么删都进回收站**:形态转换与改名此前直接删旧文件(bundle 连附件一起),现在先入回收站再删。
|
|
120
|
+
|
|
41
121
|
- **`mcpm-tools-refresh` 要求令牌**:它会临时启停服务器并写两次补丁,此前漏在写操作门清单外。
|
|
122
|
+
|
|
42
123
|
- **子代理结果不再混入思考块**;「没有正文」按收尾原因分档说明,不再一律报「无输出」。
|
|
124
|
+
|
|
43
125
|
- **人设正文与名字里的 `{{…}}` 不再让子代理启动失败**。
|
|
126
|
+
|
|
44
127
|
- **子会话里调委派工具不再被本插件拦下**(不再向官方传 `maxDepth`,人设列表也不再按深度过滤)。
|
|
128
|
+
|
|
45
129
|
- **MCP 状态不再把「连不上」报成「可用」**:可用性只认当前真实注册的工具数;曾连上、当前不可用的如实标注。
|
|
130
|
+
|
|
46
131
|
- **场景里手动关掉的技能目录 / MCP 服务器,退出场景后正常还原**(快照全量记录进场景前状态)。
|
|
132
|
+
|
|
47
133
|
- **覆盖导入失败自动回滚**;编辑 MCP 服务器保留手写的 `toolCallTimeoutMs`;整台停用时「上次运行时」工具行不再标「已启用」。
|
|
134
|
+
|
|
48
135
|
- **场景进行中改 MCP serverName 或人设名,退出场景恢复正常还原**;重启等待窗口内的并发启用不再被快照覆盖。
|
|
136
|
+
|
|
49
137
|
- **记忆描述含独立 `---` 行不再截断**(此类多行描述改用引号标量序列化)。
|
|
138
|
+
|
|
50
139
|
- **提示词页「应用」失败现在会显示错误**;手工编辑 memories-index.json 的场景描述会触发注入重算。
|
|
140
|
+
|
|
51
141
|
- **兼容页「注入实况」的说明不再截断、节头不再错位**;技能页页头按钮窄栏自动收档,「全选」不再折行。
|
|
142
|
+
|
|
52
143
|
- **访问令牌比较改为常量时间**(双侧 sha256 + timingSafeEqual)。
|
|
144
|
+
|
|
53
145
|
- **测试与开发工具**:补 parseModeState 透传契约断言;client-render 夹具对齐现行响应形状;check-i18n 修复行首键漏对账;`preview-memory-note` / `preview-compat` 修到可跑。
|
|
146
|
+
|
|
54
147
|
- **六个管理页的启用项排到列表前面**:MCP / 技能 / 子智能体 / 提示词 / 记忆 / 场景,开着的浮在上面、停用后落回原位(两半内部保持原顺序,不是按名重排;提示词页没有开关,按「生效中」排)。拨开关引起的换位有 180ms 过渡,搜索 / 筛选 / 折叠与轮询刷新引起的位移不做动画,「减少动态效果」下直接落位。
|
|
55
148
|
|
|
56
149
|
---
|