dsh-any-agent 0.3.9 → 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 +153 -1
- package/README.md +75 -634
- package/README.zh.md +64 -649
- package/bin/dsh-any-agent.mjs +59 -0
- package/demo/mcp-client.mjs +130 -0
- package/demo/run.mjs +326 -0
- package/demo/transcript.json +47 -0
- package/docs/brand/README.md +58 -0
- package/docs/brand/header.jpg +0 -0
- package/docs/en/architecture.md +43 -0
- package/docs/en/compatibility.md +51 -0
- package/docs/en/demo.md +90 -0
- package/docs/en/install.md +257 -0
- package/docs/en/limits.md +27 -0
- package/docs/en/locking.md +24 -0
- package/docs/en/reference.md +40 -0
- package/docs/en/release.md +33 -0
- package/docs/en/security.md +59 -0
- package/docs/en/team.md +74 -0
- package/docs/en/tests.md +96 -0
- package/docs/en/usage.md +71 -0
- package/docs/zh/architecture.md +43 -0
- package/docs/zh/compatibility.md +49 -0
- package/docs/zh/demo.md +90 -0
- package/docs/zh/install.md +274 -0
- package/docs/zh/limits.md +30 -0
- package/docs/zh/locking.md +24 -0
- package/docs/zh/reference.md +40 -0
- package/docs/zh/release.md +38 -0
- package/docs/zh/security.md +59 -0
- package/docs/zh/team.md +71 -0
- package/docs/zh/tests.md +95 -0
- package/docs/zh/usage.md +69 -0
- package/package.json +5 -1
- package/scripts/check-release.mjs +73 -0
- package/src/acp.mjs +31 -3
- package/src/audit.mjs +32 -0
- package/src/bootstrap.mjs +26 -1
- package/src/config.mjs +178 -9
- package/src/host.mjs +148 -0
- package/src/hub.mjs +494 -73
- package/src/procstat.mjs +72 -0
- package/src/tools.mjs +561 -27
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,159 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## [0.5.0] — 2026-11-03
|
|
11
|
+
|
|
12
|
+
### Process model
|
|
13
|
+
|
|
14
|
+
- **The shared ACP process is now the default.** Sessions with the same `(cwd, permission)`
|
|
15
|
+
land on one DSH process: a second session costs ≈300 ms instead of a ≈4 s cold start, and the
|
|
16
|
+
300–480 MB is paid once per group instead of once per conversation.
|
|
17
|
+
`DSH_MCP_SHARED_PROCESS=0` restores one process per conversation (worth it when you need hard
|
|
18
|
+
isolation). Different workspaces or permission tiers still get separate processes —
|
|
19
|
+
`dsh-base` keeps the sandbox root and the approval policy process-wide.
|
|
20
|
+
- **`dsh_takeover` no longer kills a shared process blind.** When the PID it is about to kill
|
|
21
|
+
still carries other sessions, it refuses unless `force=true` and reports them as
|
|
22
|
+
`shared_sessions`; with `force` it says how many went down with it.
|
|
23
|
+
- **`dsh_doctor` de-duplicates RSS by PID** and reports the shared host count, so "live processes"
|
|
24
|
+
and "RSS total" stop multiplying by the number of sessions riding one process.
|
|
25
|
+
- Stale comments corrected: `DSH_MCP_IDLE_TTL_MS=0` is no longer the default (10 minutes since 0.4.0).
|
|
26
|
+
|
|
27
|
+
### Team mode and defaults
|
|
28
|
+
|
|
29
|
+
- **Agent Teams is now opt-in.** `DSH_MCP_TEAM` defaults to off. Enable with
|
|
30
|
+
`dsh-any-agent team on` (writes `<DSH_HOME>/.dsh-any-agent/settings.json`),
|
|
31
|
+
disable with `team off`, inspect with `team status`; no client config editing.
|
|
32
|
+
When on, the profile switches to `dsh-team`, the legacy subagent tools are
|
|
33
|
+
disabled, and `dsh_send` adds the "form a team when needed" line.
|
|
34
|
+
- **The default session permission is now `workspace-write`** (was
|
|
35
|
+
`danger-full-access`). `permission=danger-full-access` additionally requires
|
|
36
|
+
`DSH_MCP_ALLOW_FULL_ACCESS=1` on the machine, so a bare `dsh_start` can no
|
|
37
|
+
longer hand the caller whole-machine write access.
|
|
38
|
+
- `dsh_doctor` has a dedicated `team` check: on / off / requested-but-unavailable.
|
|
39
|
+
|
|
40
|
+
### Demo
|
|
41
|
+
|
|
42
|
+
- **`npm run demo`** — a five-minute, end-to-end case: create a conversation, dispatch a task with
|
|
43
|
+
`wait=false`, interject twice while it runs, collect the sentinel, then verify the artifacts on
|
|
44
|
+
disk (including `node --test`) instead of trusting the model's own summary. It runs against an
|
|
45
|
+
isolated registry / sentinel / lock directory, so it never touches your daily
|
|
46
|
+
`~/.dsh/.dsh-any-agent`. `--replay` walks a recorded transcript with no DSH and no tokens;
|
|
47
|
+
`--keep` keeps the workspace. Ships as `demo/` in the npm package.
|
|
48
|
+
|
|
49
|
+
## [0.4.0] — 2026-11-03
|
|
50
|
+
|
|
51
|
+
### Memory
|
|
52
|
+
|
|
53
|
+
- **Idle reaping is on by default.** `DSH_MCP_IDLE_TTL_MS` now defaults to
|
|
54
|
+
10 minutes (was `0` = never). Idle sessions release their DSH process and
|
|
55
|
+
resume automatically on the next call; the write lock is released with it.
|
|
56
|
+
Set `0` to restore the old "hold the lock forever" behavior.
|
|
57
|
+
- **`DSH_MCP_MAX_LIVE` defaults to 4** (was 8), keeping the worst case around
|
|
58
|
+
1.2–1.9 GB instead of 2.5–4 GB at the documented 300–480 MB/session.
|
|
59
|
+
- **`keep_alive` on `dsh_start`.** A session created with `keep_alive: true`
|
|
60
|
+
is exempt from idle TTL and `MAX_LIVE`; it keeps its DSH process (and write
|
|
61
|
+
lock) until `dsh_release`. Use it for "must stay attached" sessions.
|
|
62
|
+
- **Global RSS budget** via `DSH_MCP_MAX_RSS_MB` (default `0` = off). When the
|
|
63
|
+
sum of live child RSS exceeds the budget, the least-recently-used idle
|
|
64
|
+
sessions are reaped until it fits. `keep_alive` sessions are reaped last.
|
|
65
|
+
- **`dsh_list` / `dsh_status` report `rss_mb`** (and `keep_alive`), so the cost
|
|
66
|
+
is visible instead of guessed.
|
|
67
|
+
- **Optional child heap cap** via `DSH_MCP_CHILD_MAX_OLD_SPACE_MB` (default
|
|
68
|
+
`0` = off). It appends `--max-old-space-size=<n>` to the child's
|
|
69
|
+
`NODE_OPTIONS` without clobbering existing options.
|
|
70
|
+
- **Experimental shared ACP process** via `DSH_MCP_SHARED_PROCESS=1`. Sessions
|
|
71
|
+
with the same `(cwd, permission)` share one DSH process; ACP supports
|
|
72
|
+
concurrent sessions over one connection and DSH gives each session its own
|
|
73
|
+
Agent. Measured on DSH 0.1.7: two sessions → one PID, second `session/new`
|
|
74
|
+
took ~300 ms instead of ~4 s. Same `(cwd, permission)` is required because
|
|
75
|
+
`sandbox-policy.workspaceRoot`/`mode` and `approval.policy` are process-wide
|
|
76
|
+
in `dsh-base`. Trade-off: a process crash takes down the whole group; the
|
|
77
|
+
host writes error sentinels for every in-flight run and each session resumes
|
|
78
|
+
on the next call.
|
|
79
|
+
|
|
80
|
+
### Dispatch surface
|
|
81
|
+
|
|
82
|
+
- **`dsh_inbox`** — a cross-conversation approval inbox. `dsh_status` remains
|
|
83
|
+
single-conversation; this tool lists every pending approval with
|
|
84
|
+
conversation id/title, approval id, tool, reason, input, options and age.
|
|
85
|
+
- **`client_run_id` idempotency** on `dsh_send` / `dsh_interject`: resubmitting
|
|
86
|
+
the same key returns the first run (`replayed=true`) instead of creating a
|
|
87
|
+
second one. The key is written into the sentinel and evicted together with
|
|
88
|
+
the run record.
|
|
89
|
+
- **Session queue** via `dsh_send(queue=true)` (explicit opt-in; the default
|
|
90
|
+
busy behavior stays "error") plus **`dsh_queue`** for list/remove/update/
|
|
91
|
+
promote. Sentinels are written only at terminal state; removing a queued
|
|
92
|
+
item writes a `cancelled` sentinel.
|
|
93
|
+
- **`dsh_get` text budget**: `max_chars` truncates only the rendered text
|
|
94
|
+
(structured content keeps the full result) and reports
|
|
95
|
+
`answer_truncated` / `next_offset`.
|
|
96
|
+
- **`dsh_doctor`** — read-only health check: DSH binary/version, profile
|
|
97
|
+
existence/drift, state file, `runs`/`locks` writability, orphan lock holders,
|
|
98
|
+
session/RSS totals, effective config.
|
|
99
|
+
- **Optional metadata audit** via `DSH_MCP_AUDIT_FILE`: JSONL records for
|
|
100
|
+
start/send/queue/interject/interrupt/approve/release/takeover. It records
|
|
101
|
+
IDs, decisions and counts only — never prompts, answers, thinking or tool
|
|
102
|
+
input. Rotates at 10 MB.
|
|
103
|
+
- **`resolveDshBin` prefers the newest cached DSH** instead of the first
|
|
104
|
+
directory it finds. This machine had both 0.1.5 and 0.1.7 cached; picking
|
|
105
|
+
0.1.5 silently hid the experimental Agent Teams packages.
|
|
106
|
+
- **README positioning section**: the server is a dispatcher, not a capability
|
|
107
|
+
aggregator; DSH owns its tools/skills/teams, and dispatch is on demand.
|
|
108
|
+
|
|
109
|
+
### Team mode
|
|
110
|
+
|
|
111
|
+
- **Agent Teams is on by default** (`DSH_MCP_TEAM=1`). The default profile is
|
|
112
|
+
now `dsh-team`, auto-created from the same routing source with
|
|
113
|
+
`@deepseek-ai/dsh-experimental-agent-team` +
|
|
114
|
+
`@deepseek-ai/dsh-experimental-tool-agent-team`; the legacy `subagent` tools
|
|
115
|
+
are disabled, matching the official team profile layer. Requires DSH
|
|
116
|
+
`>= 0.1.7-0` (the packages ship with 0.1.7-rc.1).
|
|
117
|
+
- `dsh_send` injects a short "form a team if this needs parallel or multi-role
|
|
118
|
+
work" line before the caller's prompt; simple tasks are not forced into a
|
|
119
|
+
team. `dsh_send(team=false)` disables it for one call; `DSH_MCP_TEAM=0`
|
|
120
|
+
returns to `dsh-mcp` and disables injection.
|
|
121
|
+
- `TEAM_ACTIVE` is false when the selected profile does not actually contain
|
|
122
|
+
the team package, so an explicit `DSH_MCP_PROFILE` pointing at a non-team
|
|
123
|
+
profile does not inject a tool the agent cannot use.
|
|
124
|
+
- **Switching**: `DSH_MCP_TEAM=0` returns to `dsh-mcp` and disables injection;
|
|
125
|
+
`dsh_send(team=false)` disables it for one call; `DSH_MCP_PROFILE` still
|
|
126
|
+
wins over the default profile. `dsh_start` / `dsh_doctor` report the
|
|
127
|
+
effective team mode and profile.
|
|
128
|
+
|
|
129
|
+
### Correctness
|
|
130
|
+
|
|
131
|
+
- **A failed `ensureAlive` now has a terminal state.** It wakes every
|
|
132
|
+
`dsh_interject` waiter, writes an `error` sentinel, and attaches
|
|
133
|
+
`runId`/`status`/`sentinelFile` to the thrown error. Previously an interject
|
|
134
|
+
that arrived during a lock-conflict/cold-start window could wait forever
|
|
135
|
+
(`timeout_ms=0` has no timer).
|
|
136
|
+
- **`dsh_approval_decide` reports the effective outcome.** `decideApproval`
|
|
137
|
+
returns `effective: 'selected' | 'cancelled'` (plus `reason: 'no_option'`);
|
|
138
|
+
the tool text no longer claims "decided as allow" when ACP actually received
|
|
139
|
+
`cancelled`.
|
|
140
|
+
- **`dsh_get` can read a run back from its sentinel.** On a memory miss it
|
|
141
|
+
reads `RUNS_DIR/<conversation>/<run_id>.json`, returns
|
|
142
|
+
`run.source='sentinel'`, and always includes `sentinel_file` /
|
|
143
|
+
`sentinel_file_posix`.
|
|
144
|
+
- **Reap/respawn race fixed.** `stop()` is registered as `recycling` and
|
|
145
|
+
`proc` is cleared only after the child is confirmed gone, so a concurrent
|
|
146
|
+
`dsh_send` waits instead of spawning a new process against an unreleased
|
|
147
|
+
write lock. `lastChildPid` is updated only after a successful resume, so a
|
|
148
|
+
failed resume no longer loses the previous generation's takeover clue.
|
|
149
|
+
- **`timeout_ms` is validated.** Non-finite or negative values now raise
|
|
150
|
+
instead of silently becoming `NaN`/immediate background receipts.
|
|
151
|
+
|
|
152
|
+
### Tests
|
|
153
|
+
|
|
154
|
+
- New `failure-terminal.mjs` (interject wake + error sentinel + approval
|
|
155
|
+
effective + sentinel read-back).
|
|
156
|
+
- New `shared-host.mjs` (session routing, exit fan-out, refcount teardown,
|
|
157
|
+
RSS helper).
|
|
158
|
+
- New `shared-process.mjs` (real-DSH shared process; skips without DSH).
|
|
159
|
+
- New `dispatch-tools.mjs` (`dsh_inbox`, `client_run_id` idempotency, session
|
|
160
|
+
queue operations, `dsh_get` text budget).
|
|
161
|
+
- `guards.mjs` and `smoke.mjs` updated for the new defaults and the
|
|
162
|
+
`keepAlive` metadata field.
|
|
11
163
|
|
|
12
164
|
## [0.3.9] — 2026-11-02
|
|
13
165
|
|