dsh-plugin-prompt-tool 0.1.2 → 0.1.3
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/AGENTS.md +0 -2
- package/README.md +211 -204
- package/lib/client.js +126 -51
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +46 -23
- package/lib/index.mjs +375 -88
- package/package.json +96 -88
- package/preset/prompt-injector.mjs +6 -1
- package/preset.md +1 -1
- package/vendor/dsh-anchored-standard/README.md +205 -48
- package/vendor/dsh-anchored-standard/preset/agent.cordis.yml +2 -2
- package/vendor/dsh-anchored-standard/preset/compaction-epoch.mjs +10 -3
package/package.json
CHANGED
|
@@ -1,88 +1,96 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-plugin-prompt-tool",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "DSH 插件:提示词工具,规范模型的思维链与回答内容,提供 Web UI 编辑 preset.md 与 AGENTS.md,并按 skills 目录注册可开关技能。",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/Czerror/dsh-plugin-prompt-tool.git"
|
|
9
|
-
},
|
|
10
|
-
"type": "module",
|
|
11
|
-
"main": "lib/index.mjs",
|
|
12
|
-
"types": "lib/index.d.mts",
|
|
13
|
-
"exports": {
|
|
14
|
-
".": {
|
|
15
|
-
"types": "./lib/index.d.mts",
|
|
16
|
-
"default": "./lib/index.mjs"
|
|
17
|
-
},
|
|
18
|
-
"./client": "./lib/client.js",
|
|
19
|
-
"./package.json": "./package.json"
|
|
20
|
-
},
|
|
21
|
-
"engines": {
|
|
22
|
-
"node": ">=20"
|
|
23
|
-
},
|
|
24
|
-
"dsh": {
|
|
25
|
-
"bundle": {
|
|
26
|
-
"patch": "./cordis.patch.yml"
|
|
27
|
-
},
|
|
28
|
-
"client": {
|
|
29
|
-
"inject": [
|
|
30
|
-
"@deepseek-ai/dsh-client-
|
|
31
|
-
"@deepseek-ai/dsh-client-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"@deepseek-ai/
|
|
39
|
-
"@deepseek-ai/dsh-
|
|
40
|
-
"@deepseek-ai/dsh-client-
|
|
41
|
-
"@deepseek-ai/dsh-client-
|
|
42
|
-
"@deepseek-ai/dsh-client-ui-
|
|
43
|
-
"@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"@deepseek-ai/dsh-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"@deepseek-ai/
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@
|
|
56
|
-
"@
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-plugin-prompt-tool",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "DSH 插件:提示词工具,规范模型的思维链与回答内容,提供 Web UI 编辑 preset.md 与 AGENTS.md,并按 skills 目录注册可开关技能。",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Czerror/dsh-plugin-prompt-tool.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "lib/index.mjs",
|
|
12
|
+
"types": "lib/index.d.mts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./lib/index.d.mts",
|
|
16
|
+
"default": "./lib/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./client": "./lib/client.js",
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20"
|
|
23
|
+
},
|
|
24
|
+
"dsh": {
|
|
25
|
+
"bundle": {
|
|
26
|
+
"patch": "./cordis.patch.yml"
|
|
27
|
+
},
|
|
28
|
+
"client": {
|
|
29
|
+
"inject": [
|
|
30
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
31
|
+
"@deepseek-ai/dsh-client-connection",
|
|
32
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins"
|
|
33
|
+
],
|
|
34
|
+
"platform": "web"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
39
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
|
|
40
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
|
|
41
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
|
|
42
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
|
|
43
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6",
|
|
44
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
45
|
+
"@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
|
|
46
|
+
"@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
|
|
47
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
48
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
49
|
+
"react": "^18.2.0",
|
|
50
|
+
"@deepseek-ai/dsh-commands": "^0.1.0-rc.6"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
54
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
|
|
55
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
|
|
57
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
|
|
59
|
+
"@deepseek-ai/dsh-commands": "0.1.0-rc.6",
|
|
60
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
61
|
+
"@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
|
|
62
|
+
"@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
|
|
63
|
+
"@types/node": "^26.2.0",
|
|
64
|
+
"@types/react": "~18.3.1",
|
|
65
|
+
"clsx": "^2.1.1",
|
|
66
|
+
"lightningcss": "^1.32.0",
|
|
67
|
+
"oxlint": "^1.78.0",
|
|
68
|
+
"react": "^18.3.1",
|
|
69
|
+
"tsdown": "^0.22.2",
|
|
70
|
+
"typescript": "^5.9.2"
|
|
71
|
+
},
|
|
72
|
+
"files": [
|
|
73
|
+
"lib",
|
|
74
|
+
"cordis.patch.yml",
|
|
75
|
+
"LICENSE",
|
|
76
|
+
"preset",
|
|
77
|
+
"vendor/dsh-anchored-standard/preset",
|
|
78
|
+
"vendor/dsh-anchored-standard/LICENSE",
|
|
79
|
+
"vendor/dsh-anchored-standard/NOTICE",
|
|
80
|
+
"skills",
|
|
81
|
+
"preset.md",
|
|
82
|
+
"AGENTS.md",
|
|
83
|
+
"plan.md",
|
|
84
|
+
"README.md"
|
|
85
|
+
],
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build": "tsdown",
|
|
88
|
+
"prepare": "tsdown",
|
|
89
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
|
90
|
+
"lint": "oxlint src test tsdown.config.ts",
|
|
91
|
+
"test": "pnpm build && node --test \"test/*.test.mjs\""
|
|
92
|
+
},
|
|
93
|
+
"dependencies": {
|
|
94
|
+
"yaml": "^2.9.0"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* turn1 reasoning 以 "we" 开头 → 下一轮注入 promptText 一次;
|
|
7
7
|
* we 未确认 → 最多再等一轮,仍无则强制注入(兜底,绝不卡死)。
|
|
8
8
|
*
|
|
9
|
+
* promptText 由宿主在生成 preset 时准备好:
|
|
10
|
+
* - 默认等于 preset.md 原文;
|
|
11
|
+
* - 开启 injectAgentsPrompt 时,宿主会把 AGENTS.md 拼接到 preset.md 头部。
|
|
12
|
+
* 本模块只负责把最终文本作为一条 user 消息注入,不做路径探测。
|
|
13
|
+
*
|
|
9
14
|
* 实测依据:
|
|
10
15
|
* - 复杂任务 + 原版 2 工具 + maxTokens 1024 → turn1 reasoning "We need";
|
|
11
16
|
* - 简单任务模型直接调工具干活(无 we 首词),走兜底注入;
|
|
@@ -119,4 +124,4 @@ export function apply(ctx, config) {
|
|
|
119
124
|
}
|
|
120
125
|
return { ...decision, messages: [message, ...decision.messages] }
|
|
121
126
|
})
|
|
122
|
-
}
|
|
127
|
+
}
|
package/preset.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
You are a helpful software assistant.
|
|
2
|
-
Begin every reasoning block with 'We need'.
|
|
2
|
+
Begin every reasoning block or thinking with "'We need', '我需要'".
|
|
3
3
|
DeepSeek harness operates in local execution mode. Answer requests directly in the
|
|
4
4
|
user's language. No preamble, qualification, or redirection.
|
|
5
5
|
|
|
@@ -2,15 +2,85 @@
|
|
|
2
2
|
|
|
3
3
|
[中文说明](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
(
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Experimental DeepSeek Harness agent presets — one base mode plus two variants
|
|
6
|
+
— that anchor a session's first model request on the Minimal condition
|
|
7
|
+
(real Minimal tool schema, no auto-injected context), then promote to a small
|
|
8
|
+
resident catalog once the session is durable, unlocking heavier Standard tools
|
|
9
|
+
on demand.
|
|
10
10
|
|
|
11
11
|
This is a community project. It is not an official DeepSeek preset and is not
|
|
12
12
|
affiliated with or endorsed by DeepSeek.
|
|
13
13
|
|
|
14
|
+
Welcome to submit feedback on the plugin in the form of Issues or PRs. For ideas for new plugins or useful findings, please submit them under the [repository](https://github.com/0liveiraaa/DeepseekCotexplorations).
|
|
15
|
+
|
|
16
|
+
## Modes at a glance
|
|
17
|
+
|
|
18
|
+
| Mode | Directory | First model request | Anchor mechanism | Promotion signal | Cost |
|
|
19
|
+
|---|---|---|---|---|---|
|
|
20
|
+
| Anchored Standard | `preset/` | 2 tools (the Minimal pair) | Minimal tool schema | first durable `tool/call` **or** `assistant/message` (`promoteOn: either`) | none |
|
|
21
|
+
| Zero-Anchored Standard | `zero-anchored-standard/` | 0 tools | one fixed anchor turn | the anchor reply (`assistant/message`) | +1 model call |
|
|
22
|
+
| Whoami Standard | `whoami-standard/` | 0 tools | one "你是谁" self-introduction turn | the self-introduction reply (`assistant/message`) | +1 model call |
|
|
23
|
+
|
|
24
|
+
Every mode directory is self-contained and installs alone under whatever id
|
|
25
|
+
you copy it to (see [Install](#install)).
|
|
26
|
+
|
|
27
|
+
## Terminology
|
|
28
|
+
|
|
29
|
+
- **trajectory** — the style of the model's first reasoning chain. The
|
|
30
|
+
Minimal condition produces "We need…" first lines; the Standard condition
|
|
31
|
+
produces "Let me…" ("standard-like") first lines.
|
|
32
|
+
- **anchor** — the first-request conditions that select the trajectory. Issue
|
|
33
|
+
#11 isolated three levers: the tool schema, the output budget, and the
|
|
34
|
+
injected reminders.
|
|
35
|
+
- **bootstrap phase** — request #1 of a session: the bootstrap tool pair, no
|
|
36
|
+
auto-injected context, optional output cap.
|
|
37
|
+
- **promotion** — the durable session event that ends the bootstrap phase.
|
|
38
|
+
Base mode: first `tool/call` or `assistant/message`, whichever comes first.
|
|
39
|
+
Variants: the anchor reply.
|
|
40
|
+
- **durable** — recorded in the session event log. Phase state is derived
|
|
41
|
+
from durable events, so resume and reload preserve it.
|
|
42
|
+
- **resident catalog** — the promoted tool set: the bootstrap pair plus the
|
|
43
|
+
discovery tools plus every tool the model explicitly unlocked.
|
|
44
|
+
- **discovery tools** — `dev_tool_search`, `skill_search`, `skill_load`: the
|
|
45
|
+
on-demand unlock surface for heavier Standard tools.
|
|
46
|
+
- **materialized copy** — the committed copy of a `shared/` plugin inside a
|
|
47
|
+
mode directory, generated by `npm run sync`.
|
|
48
|
+
|
|
49
|
+
## How it works
|
|
50
|
+
|
|
51
|
+
The base mode in one request lifecycle (the variants change only the first
|
|
52
|
+
turn — see their sections):
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
user's first message
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
┌ request #1 ─ bootstrap phase ──────────────────────────────┐
|
|
59
|
+
│ tools : bash + str_replace_editor (Minimal's real pair) │
|
|
60
|
+
│ context : no AGENTS.md digest, no skill-catalog reminder │
|
|
61
|
+
│ budget : adapter default (`bootstrapMaxTokens` optional) │
|
|
62
|
+
└─────────────────────────────────────────────────────────────┘
|
|
63
|
+
│ first durable tool/call OR assistant/message
|
|
64
|
+
▼ PROMOTION — derived from durable events, resume-safe
|
|
65
|
+
┌ request #2+ ─ resident phase ──────────────────────────────┐
|
|
66
|
+
│ tools : bootstrap pair + discovery tools + unlocked │
|
|
67
|
+
│ context : standard injections restored │
|
|
68
|
+
│ budget : adapter default (a cap is stripped on promote) │
|
|
69
|
+
└─────────────────────────────────────────────────────────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Three first-request levers decide the trajectory (issue #11):
|
|
73
|
+
|
|
74
|
+
1. **Tool schema** — the decisive variable at the adapter-default maxTokens
|
|
75
|
+
(256000). The real Minimal pair anchored 5/5; every standard-family schema
|
|
76
|
+
fell standard-like 11/11.
|
|
77
|
+
2. **Output budget** — a 1024 first-request cap also anchored the trajectory
|
|
78
|
+
(26/32), independent of the tool descriptions. The base mode leaves this
|
|
79
|
+
lever unset (`bootstrapMaxTokens` is opt-in).
|
|
80
|
+
3. **Injected reminders** — the AGENTS.md/CLAUDE.md digest and the
|
|
81
|
+
available-skills reminder. With the skill catalog present the anchor did
|
|
82
|
+
not reproduce at all (0/9); both are stripped during bootstrap.
|
|
83
|
+
|
|
14
84
|
## Why
|
|
15
85
|
|
|
16
86
|
DeepSeek V4 Pro conditions strongly on the API-visible tool catalog. In the
|
|
@@ -23,23 +93,23 @@ Anchored Standard separates initial trajectory selection from later tool use:
|
|
|
23
93
|
1. Keep the Minimal complete system prompt.
|
|
24
94
|
2. Expose the Minimal preset's REAL tool schemas — persistent `bash` +
|
|
25
95
|
`str_replace_editor`, byte-identical to the official Minimal composition —
|
|
26
|
-
on the first model request
|
|
27
|
-
5/5 runs at the adapter-default maxTokens (256000) with zero `let me`
|
|
28
|
-
first-lines, while every standard-family schema (pwsh/read, pwsh only,
|
|
29
|
-
sandboxed bash/read) fell into standard-like behavior 11/11. The tool
|
|
30
|
-
schema identity is the decisive first-request variable at 256000, so no
|
|
31
|
-
output cap is needed.
|
|
96
|
+
on the first model request (lever 1 above).
|
|
32
97
|
3. Strip the auto-injected context on that first request as well — the
|
|
33
98
|
AGENTS.md/CLAUDE.md workspace digest and the available-skills reminder that
|
|
34
99
|
true Minimal never mounts (`suppressedContextSources` in the
|
|
35
|
-
`tool-bootstrap` row). User-initiated skill gestures are not
|
|
36
|
-
both injections return unchanged from request #2 on.
|
|
100
|
+
`tool-bootstrap` row; lever 3). User-initiated skill gestures are not
|
|
101
|
+
filtered, and both injections return unchanged from request #2 on.
|
|
37
102
|
4. After the session records its first durable promotion signal — a `tool/call`
|
|
38
|
-
or the first `assistant/message`, whichever comes first —
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
the
|
|
103
|
+
or the first `assistant/message`, whichever comes first — promote to the
|
|
104
|
+
RESIDENT catalog: the bootstrap pair plus the discovery tools plus whatever
|
|
105
|
+
the model has explicitly unlocked via `dev_tool_search`. Dumping the full
|
|
106
|
+
Standard catalog at promotion pulled the trajectory back to standard-like
|
|
107
|
+
behavior (the post-promotion regression), so heavier tools — `web_search`,
|
|
108
|
+
`subagent`, `workflow`, … — stay one `dev_tool_search` call away. Request
|
|
109
|
+
#1 always sees the bootstrap catalog; request #2 always sees the resident
|
|
110
|
+
catalog, so a text-only first reply can no longer trap the session in
|
|
111
|
+
bootstrap. (`promoteOn` in the `tool-bootstrap` row selects the trigger:
|
|
112
|
+
`either` default, `tool-call`, or `assistant-message`.)
|
|
43
113
|
5. Derive the phase from durable session events so resume and reload preserve it.
|
|
44
114
|
|
|
45
115
|
The bootstrap catalog is the same on every platform: the Minimal pair
|
|
@@ -59,9 +129,10 @@ Project2 V4.1b, DeepSeek V4 Pro, `reasoningEffort=max`, Windows native:
|
|
|
59
129
|
| r2 | 99 | 162 | 165 | 98 | 0 | 1 |
|
|
60
130
|
|
|
61
131
|
Both runs emitted exactly two tool-catalog snapshots: the two-tool Minimal
|
|
62
|
-
bootstrap, followed by the 25-tool Standard catalog
|
|
63
|
-
|
|
64
|
-
|
|
132
|
+
bootstrap, followed by the 25-tool Standard catalog (these runs predate the
|
|
133
|
+
post-promotion narrowing to the resident set — see [How it works](#how-it-works)).
|
|
134
|
+
The result is reproducible evidence for this task, not a claim of universal
|
|
135
|
+
improvement across models or workloads.
|
|
65
136
|
|
|
66
137
|
Cross-version evidence (issue #11, Windows + official endpoint, first-request
|
|
67
138
|
trajectory only): at the adapter-default maxTokens the Minimal tool schema
|
|
@@ -73,6 +144,65 @@ first-request variable at 256000.
|
|
|
73
144
|
Full methodology and aggregate evidence are in
|
|
74
145
|
[`xiaobright/modeltest`](https://github.com/xiaobright/modeltest).
|
|
75
146
|
|
|
147
|
+
## Configuration reference
|
|
148
|
+
|
|
149
|
+
All knobs are rows in each mode's `agent.cordis.yml`. Unknown keys fail at
|
|
150
|
+
preset mount.
|
|
151
|
+
|
|
152
|
+
`tool-bootstrap` (in `preset/agent.cordis.yml`; the row must stay FIRST —
|
|
153
|
+
waterfall registration order decides the first-request strip):
|
|
154
|
+
|
|
155
|
+
| Key | Default | Meaning |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `bootstrapTools` | `[bash, str_replace_editor]` | Tools visible on request #1. |
|
|
158
|
+
| `promoteOn` | `either` | Promotion trigger: `either`, `tool-call`, or `assistant-message`. |
|
|
159
|
+
| `bootstrapMaxTokens` | unset | Optional output cap for request #1; stripped after promotion. |
|
|
160
|
+
| `suppressedContextSources` | `[agent-instructions, skill-catalog]` | `source.kind` values stripped during bootstrap; `[]` disables the filter. |
|
|
161
|
+
| `compactionTools` | `[]` | Extra tools available between a compaction boundary and re-promotion. |
|
|
162
|
+
|
|
163
|
+
`zero-tool-bootstrap` (in `zero-anchored-standard/` and `whoami-standard/`):
|
|
164
|
+
`suppressedContextSources` and `compactionTools` have the same semantics
|
|
165
|
+
(promotion is always the first `assistant/message`), plus
|
|
166
|
+
`includeSubagents` — whether subagents also take the anchor phase (set `true`
|
|
167
|
+
in `whoami-standard`, `false` in `zero-anchored-standard`).
|
|
168
|
+
|
|
169
|
+
`anchor-turn` (in both variants): `text` — the synthetic first user message
|
|
170
|
+
(default "This round is a test. Tools are not open yet; all tools will open
|
|
171
|
+
next round." in zero-anchored, "你是谁" in whoami); `includeSubagents` —
|
|
172
|
+
whether subagents also take the anchor turn.
|
|
173
|
+
|
|
174
|
+
`instruction-hint` (all modes): `promoteOn` matching the mode's promotion
|
|
175
|
+
semantics (`either` in the base mode, `assistant-message` in the variants) —
|
|
176
|
+
the one-shot "instruction files exist, read them before acting" hint waits
|
|
177
|
+
for promotion.
|
|
178
|
+
|
|
179
|
+
## Repository layout
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
preset/ Anchored Standard — the base mode
|
|
183
|
+
zero-anchored-standard/ variant: fixed zero-tool anchor turn
|
|
184
|
+
whoami-standard/ variant: "你是谁" anchor turn, subagents inherit
|
|
185
|
+
shared/ single source of truth for plugins used by 2+ modes
|
|
186
|
+
scripts/sync-modes.mjs materializes shared/ plugins into every mode dir
|
|
187
|
+
test/ zero-dependency test suite (npm test)
|
|
188
|
+
verify/ one-shot headless verification runner
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Invariants, enforced by `npm run check`:
|
|
192
|
+
|
|
193
|
+
- Every mode directory is self-contained: installable by copying it alone;
|
|
194
|
+
`agent.cordis.yml` rows may reference only `./local.mjs` files, never `../`.
|
|
195
|
+
- Plugins shared by several modes live once in `shared/`; the copies in mode
|
|
196
|
+
directories are generated. Edit `shared/`, run `npm run sync`, commit both —
|
|
197
|
+
never edit a materialized copy.
|
|
198
|
+
- The `tool-bootstrap` row stays the FIRST row of `preset/agent.cordis.yml`.
|
|
199
|
+
|
|
200
|
+
This repository deliberately ships no AGENTS.md/CLAUDE.md: the presets' whole
|
|
201
|
+
mechanism is a clean request #1, stripping exactly those instruction-file
|
|
202
|
+
digests from it (issue #6: 0/9 anchored with the injection present). Shipping
|
|
203
|
+
one would only feed later rounds and contradict the mechanism being
|
|
204
|
+
documented. Everything an assistant needs is in this README.
|
|
205
|
+
|
|
76
206
|
## Compatibility
|
|
77
207
|
|
|
78
208
|
Developed and tested against:
|
|
@@ -98,7 +228,10 @@ so review upstream changes before using it with a newer release.
|
|
|
98
228
|
## Install
|
|
99
229
|
|
|
100
230
|
Clone this repository, then copy the entire `preset` directory into the user
|
|
101
|
-
preset root under the id `anchored-standard`.
|
|
231
|
+
preset root under the id `anchored-standard`. Every mode directory in this
|
|
232
|
+
repository is self-contained: the `zero-anchored-standard/` and
|
|
233
|
+
`whoami-standard/` variants install the same way, alone or together, with no
|
|
234
|
+
other directory required (see their sections below).
|
|
102
235
|
|
|
103
236
|
PowerShell:
|
|
104
237
|
|
|
@@ -139,9 +272,12 @@ variables that decide the anchor):
|
|
|
139
272
|
no available-skills reminder — only the user message and the minimal persona
|
|
140
273
|
system prompt;
|
|
141
274
|
- after the first tool call or the first assistant reply, the next changed
|
|
142
|
-
header should contain the
|
|
143
|
-
|
|
144
|
-
|
|
275
|
+
header should contain the promoted resident catalog: the bootstrap pair plus
|
|
276
|
+
`dev_tool_search`/`skill_search`/`skill_load` plus any tools the model
|
|
277
|
+
already unlocked;
|
|
278
|
+
- subsequent requests should keep that resident set (it grows only through
|
|
279
|
+
explicit `dev_tool_search` unlocks) and restore the standard context
|
|
280
|
+
injections.
|
|
145
281
|
|
|
146
282
|
Run the local zero-dependency tests with:
|
|
147
283
|
|
|
@@ -153,10 +289,10 @@ npm test
|
|
|
153
289
|
|
|
154
290
|
- With the default `promoteOn: either`, the session promotes after its first
|
|
155
291
|
durable `tool/call` OR its first `assistant/message`, whichever comes first —
|
|
156
|
-
request #1 sees the bootstrap catalog and every later request sees the
|
|
157
|
-
catalog. A text-only first reply therefore still promotes at
|
|
158
|
-
set `promoteOn: tool-call` to restore the original behavior,
|
|
159
|
-
response that makes no tool call never promotes.
|
|
292
|
+
request #1 sees the bootstrap catalog and every later request sees the
|
|
293
|
+
resident catalog. A text-only first reply therefore still promotes at
|
|
294
|
+
request #2; set `promoteOn: tool-call` to restore the original behavior,
|
|
295
|
+
where a first response that makes no tool call never promotes.
|
|
160
296
|
- A failed tool execution still promotes the session because the durable
|
|
161
297
|
`tool/call` already exists.
|
|
162
298
|
- The first request's output budget is NOT capped by default: the Minimal tool
|
|
@@ -164,12 +300,12 @@ npm test
|
|
|
164
300
|
opt-in. When set, the first request is capped and the cap is explicitly
|
|
165
301
|
stripped after promotion (the next request's seed proposal carries the
|
|
166
302
|
previous header's maxTokens forward).
|
|
167
|
-
- The
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
shell (same tool name, same layer; see Why).
|
|
171
|
-
keep the sandboxed filesystem while
|
|
172
|
-
local fs.
|
|
303
|
+
- The promoted catalog is the RESIDENT set — the bootstrap pair plus the
|
|
304
|
+
discovery tools plus everything the model unlocked via `dev_tool_search` —
|
|
305
|
+
not the full Standard dump. The Standard sandboxed `bash` row stays disabled
|
|
306
|
+
in favor of the persistent shell (same tool name, same layer; see Why). When
|
|
307
|
+
unlocked, the `read`/`write`/`edit` tools keep the sandboxed filesystem while
|
|
308
|
+
`str_replace_editor` uses the preset's local fs.
|
|
173
309
|
- A missing bootstrap tool degrades to the full catalog with a one-time
|
|
174
310
|
warning instead of failing requests, so a composition drift cannot brick a
|
|
175
311
|
session; invalid `promoteOn` values fail at preset mount instead.
|
|
@@ -181,8 +317,8 @@ npm test
|
|
|
181
317
|
Standard adds over Minimal). Set the list to `[]` to disable the context
|
|
182
318
|
filter; add other `source.kind` values to suppress more. A filter failure
|
|
183
319
|
degrades to keeping every message rather than eating context.
|
|
184
|
-
- The tool catalog changes
|
|
185
|
-
|
|
320
|
+
- The tool catalog changes at promotion and again whenever `dev_tool_search`
|
|
321
|
+
unlocks a new tool; request-prefix cache continuity breaks at those points.
|
|
186
322
|
- The preset has the same trust level as shell access. Review its files before
|
|
187
323
|
installation.
|
|
188
324
|
- The plugin performs no network requests and adds no telemetry.
|
|
@@ -198,11 +334,12 @@ on the first request it injects one fixed zero-tool anchor turn:
|
|
|
198
334
|
tools will open next round." — ahead of it.
|
|
199
335
|
2. The first real model request carries ZERO tools, so the session's first
|
|
200
336
|
reasoning chain follows the zero-injection "we" trajectory.
|
|
201
|
-
3. Once that anchor response is durable, the
|
|
202
|
-
and the real message proceeds with
|
|
337
|
+
3. Once that anchor response is durable, the resident catalog is exposed
|
|
338
|
+
and the real message proceeds with it.
|
|
203
339
|
|
|
204
340
|
Anchoring on the first message — not on session creation — keeps the
|
|
205
|
-
blank-session preset switcher usable. Subagents always see the
|
|
341
|
+
blank-session preset switcher usable. Subagents always see the resident
|
|
342
|
+
catalog.
|
|
206
343
|
|
|
207
344
|
Measured behavior (opencode-go, DeepSeek V4 Pro, `reasoningEffort=max`): the
|
|
208
345
|
anchor request is stable "we"-style with zero `let me`; the following
|
|
@@ -230,7 +367,7 @@ user's real first message is deferred to the next turn. Whatever the user types
|
|
|
230
367
|
first, the session warms up exactly one round and everything is ready when the
|
|
231
368
|
real message is processed:
|
|
232
369
|
|
|
233
|
-
1. When the user sends their first message, the `
|
|
370
|
+
1. When the user sends their first message, the `anchor-turn` plugin prepends a
|
|
234
371
|
fixed user message — "你是谁" (who are you) — ahead of it in the `next-turn`
|
|
235
372
|
inbox queue.
|
|
236
373
|
2. dsh claims exactly ONE `next-turn` message per turn, so the first model
|
|
@@ -240,15 +377,35 @@ real message is processed:
|
|
|
240
377
|
catalog (shells, `str_replace_editor`, the discovery tools) already
|
|
241
378
|
unlocked — heavier Standard tools are one `dev_tool_search` away.
|
|
242
379
|
|
|
243
|
-
The anchor text is configurable via the `
|
|
380
|
+
The anchor text is configurable via the `anchor-turn` row's `text` option
|
|
244
381
|
(default "你是谁"). Anchoring on the first message — not session creation —
|
|
245
|
-
keeps the blank-session preset switcher usable
|
|
246
|
-
|
|
247
|
-
|
|
382
|
+
keeps the blank-session preset switcher usable.
|
|
383
|
+
|
|
384
|
+
### Full-powered subagents
|
|
385
|
+
|
|
386
|
+
Whoami Standard ships with `includeSubagents: true` on both the
|
|
387
|
+
`zero-tool-bootstrap` and `anchor-turn` rows, so subagents spawned from a
|
|
388
|
+
session inherit the same anchor flow as top-level sessions:
|
|
389
|
+
|
|
390
|
+
1. A newly spawned subagent's first model request sees only the "你是谁"
|
|
391
|
+
anchor on an empty tool catalog.
|
|
392
|
+
2. The subagent's self-introduction reply is the promotion signal.
|
|
393
|
+
3. The delegated prompt runs on the next turn with the promoted resident
|
|
394
|
+
catalog (shells, `str_replace_editor`, and the discovery tools).
|
|
395
|
+
|
|
396
|
+
Set `includeSubagents: false` on both rows to restore the plain behavior,
|
|
397
|
+
where subagents start with the resident catalog immediately. Each subagent
|
|
398
|
+
costs one extra model call for its anchor turn — a delegation-heavy session
|
|
399
|
+
pays it per subagent.
|
|
400
|
+
|
|
401
|
+
`zero-anchored-standard` keeps subagents plain by default; enabling the same
|
|
402
|
+
flow there means setting `includeSubagents: true` on its `zero-tool-bootstrap`
|
|
403
|
+
and `anchor-turn` rows (its anchor text stays the fixed test notice).
|
|
404
|
+
|
|
405
|
+
The trade-off of the mode itself is one extra model call per session: the
|
|
406
|
+
anchor turn is always taken, even when the first message is urgent.
|
|
248
407
|
|
|
249
|
-
The
|
|
250
|
-
`../preset/` references, so install that directory as well (see the Install
|
|
251
|
-
section above).
|
|
408
|
+
The directory is self-contained; install it alone or alongside any other mode.
|
|
252
409
|
|
|
253
410
|
Install as a separate preset id:
|
|
254
411
|
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
* Please avoid commands that may produce a very large amount of output.
|
|
160
160
|
* Please run long lived commands in the background, e.g. 'sleep 10 &' or start a server in the background.
|
|
161
161
|
|
|
162
|
-
# Windows-only `bash` tool (see
|
|
162
|
+
# Windows-only `bash` tool (see custom-bash.mjs): registers the SAME
|
|
163
163
|
# tool name as the persistent shell with a Minimal-compatible description, but
|
|
164
164
|
# executes through the ordinary cross-platform subprocess seam (`bash -c`)
|
|
165
165
|
# instead of a PTY. `bashPath` defaults to `bash` on PATH; point it at Git
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
name: ./custom-bash.mjs
|
|
171
171
|
disabled: !!js process.platform !== 'win32'
|
|
172
172
|
config:
|
|
173
|
-
bashPath: '
|
|
173
|
+
bashPath: 'bash.exe'
|
|
174
174
|
|
|
175
175
|
# ── filesystem ──────────────────────────────────────────────────────────────
|
|
176
176
|
|
|
@@ -15,10 +15,16 @@
|
|
|
15
15
|
* State is memoized per session id and maintained incrementally through
|
|
16
16
|
* `observe()`; a cold session scans its durable log once (so resume and
|
|
17
17
|
* reload reconstruct the same phase), then O(1).
|
|
18
|
+
*
|
|
19
|
+
* By default subagents (`delegationDepth > 0`) are treated as already
|
|
20
|
+
* promoted so their first request can use tools. Set `includeSubagents: true`
|
|
21
|
+
* to make subagents follow the same bootstrap/anchor phase as top-level
|
|
22
|
+
* sessions.
|
|
18
23
|
*/
|
|
19
24
|
|
|
20
25
|
/** Build one epoch-aware promotion tracker. */
|
|
21
|
-
export function createEpochPromotion(promoteEvents) {
|
|
26
|
+
export function createEpochPromotion(promoteEvents, options = {}) {
|
|
27
|
+
const includeSubagents = options.includeSubagents === true
|
|
22
28
|
const promote = new Set(promoteEvents)
|
|
23
29
|
/** sessionId -> { boundary, promoted } */
|
|
24
30
|
const state = new Map()
|
|
@@ -53,8 +59,9 @@ export function createEpochPromotion(promoteEvents) {
|
|
|
53
59
|
if (agent === undefined) return { boundary: -1, promoted: true }
|
|
54
60
|
const session = agent.session
|
|
55
61
|
if (session === undefined) return { boundary: -1, promoted: true }
|
|
56
|
-
//
|
|
57
|
-
|
|
62
|
+
// By default subagents keep the full catalog from their very first
|
|
63
|
+
// request; includeSubagents makes them follow the normal bootstrap phase.
|
|
64
|
+
if (!includeSubagents && (session.header?.delegationDepth ?? 0) > 0) return { boundary: -1, promoted: true }
|
|
58
65
|
return state.get(session.id) ?? scan(session)
|
|
59
66
|
},
|
|
60
67
|
/** Incremental feed: call on every `session/event`. */
|