dsh-next-actions 0.1.0 → 0.1.1
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 +13 -0
- package/DESIGN.md +1 -1
- package/README.md +17 -1
- package/client.js +6 -2
- package/index.js +46 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# 版本记录
|
|
2
2
|
|
|
3
|
+
## 0.1.1 — 2026-11-11
|
|
4
|
+
|
|
5
|
+
修复 DSH 升级后引导提示丢失:`AgentRegistry.roots()` 在 DSH 0.2.1-rc.3 起被移除,
|
|
6
|
+
原来的根 agent 判定抛错后被静默忽略,常驻提示语因此从未注册,模型只看到单独的工具描述。
|
|
7
|
+
|
|
8
|
+
- 改用会话 header 的 `origin: 'subagent'` 区分普通会话与子代理;子代理仍不注册工具与提示。
|
|
9
|
+
- 静默降级改为可诊断:引导安装失败、既有 agent 列表不可读、会话 header 无法判定都写 Host 日志;
|
|
10
|
+
Host logger 缺失时回退 `console.warn`。
|
|
11
|
+
- 引导语明确说明工程/代码工作同样适用:卡片在回答下方,不把回答变成 UI 回答。
|
|
12
|
+
- 工具描述自述触发时机,即使提示语丢失也能说明用途。
|
|
13
|
+
- 客户端光标插入被拒绝或抛错时回退为追加,并写 `console.warn` 说明降级。
|
|
14
|
+
- 测试改用当前 `AgentRegistry.list()` 接口,并覆盖子代理排除、各静默降级的告警。
|
|
15
|
+
|
|
3
16
|
## 0.1.0 — 2026-11-11
|
|
4
17
|
|
|
5
18
|
首个公开发布。
|
package/DESIGN.md
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
|
|
61
61
|
| 部分 | 文件 | 职责 |
|
|
62
62
|
| --- | --- | --- |
|
|
63
|
-
| Host | `index.js` | 为根 agent 注册 `suggest_next_actions`
|
|
63
|
+
| Host | `index.js` | 为根 agent 注册 `suggest_next_actions` 与一段常驻提示;子代理不注册(按会话 header 的 `origin` 区分);安装与判定失败写日志;`enabled:false` 时什么都不注册 |
|
|
64
64
|
| 规范化 | `lib/normalize.js` | 参数 → `{ shown, context, suggestions[≤3] }`:折叠空白、截断、按指令去重、推荐至多一条且置顶;危险标记来自模型字段或命令形状模式。结果作为 `tool/result.meta` 写入会话日志 |
|
|
65
65
|
| Client | `client.js`(手写单文件,含 CSS) | 两个 Conversation Definition:`next-actions` 把本工具结果上的 meta(native 与 PTC `run_code` 两条通路)发布为该轮卡片;`next-actions-sent` 把用户在该轮发出的第一条 `user/message` 发布为 `sent` 文本。`conversation.chat.turnTail` 渲染卡片;`tool.call.toolview` 渲染过程行 |
|
|
66
66
|
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Suggested next actions under DeepSeek Harness replies — clicking one fills the input, never sends.
|
|
4
4
|
> DSH Web/Desktop 插件:在回复下方显示 1–3 条「下一步建议」,点击只填入输入框。
|
|
5
5
|
|
|
6
|
-
**状态:v0.1.
|
|
6
|
+
**状态:v0.1.1(npm 包:[dsh-next-actions](https://www.npmjs.com/package/dsh-next-actions))。** 设计与理念见 [`DESIGN.md`](DESIGN.md),版本记录见 [`CHANGELOG.md`](CHANGELOG.md)。
|
|
7
7
|
|
|
8
8
|
## 安装
|
|
9
9
|
|
|
@@ -38,6 +38,7 @@ lib/normalize.js 参数规范化,结果写入 tool/result.meta
|
|
|
38
38
|
client.js Client(手写单文件):Definition、卡片、过程行与 CSS
|
|
39
39
|
cordis.patch.yml 插件行 patch
|
|
40
40
|
test/ node --test
|
|
41
|
+
assets/promo/ 宣传短片:源文件、封面与渲染脚本(成片不入库,不随 npm 发布)
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
## 开发
|
|
@@ -50,6 +51,21 @@ npm pack --dry-run # 打包检查
|
|
|
50
51
|
安装/卸载用 `plugin_manager` 的 `install_bundle` / `remove_bundle`;验证使用假 `DSH_HOME`。
|
|
51
52
|
Host 改动需重启 DSH,Client 改动需刷新页面。
|
|
52
53
|
|
|
54
|
+
## 发布
|
|
55
|
+
|
|
56
|
+
改 `package.json` 版本与 `CHANGELOG.md` 后:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
node --test
|
|
60
|
+
npm pack --dry-run
|
|
61
|
+
git tag -a v<version> -m "v<version>"
|
|
62
|
+
git push origin main --tags
|
|
63
|
+
npm publish --access public
|
|
64
|
+
npm view dsh-next-actions version # 确认 latest 指向新版本
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
发布后用假 `DSH_HOME` 从 registry 装一次;本机 `link:` 安装不需要切换。
|
|
68
|
+
|
|
53
69
|
关闭功能:在 profile 的 `cordis.patch.yml` 写
|
|
54
70
|
|
|
55
71
|
```yaml
|
package/client.js
CHANGED
|
@@ -277,8 +277,12 @@ window.__ModuleLoader__.load({
|
|
|
277
277
|
next = null
|
|
278
278
|
try {
|
|
279
279
|
// One editor edit at the caret: keeps @ references, undoable with ⌘Z.
|
|
280
|
-
if (actions.insertText(`\n\n${prompt}`, actions.captureInsertion()) !== true)
|
|
281
|
-
|
|
280
|
+
if (actions.insertText(`\n\n${prompt}`, actions.captureInsertion()) !== true) {
|
|
281
|
+
console.warn('[dsh-next-actions] insertText declined; appending the action instead')
|
|
282
|
+
next = `${draft.trimEnd()}\n\n${prompt}`
|
|
283
|
+
}
|
|
284
|
+
} catch (error) {
|
|
285
|
+
console.warn('[dsh-next-actions] insert at caret failed; appending the action instead', error)
|
|
282
286
|
next = `${draft.trimEnd()}\n\n${prompt}`
|
|
283
287
|
}
|
|
284
288
|
}
|
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const GUIDANCE = [
|
|
|
18
18
|
'Before your final answer, call suggest_next_actions once when this turn leaves real follow-up work:',
|
|
19
19
|
'a task finished or advanced, tools ran, files changed, review or approval is due,',
|
|
20
20
|
'or you were about to end with a list of next actions.',
|
|
21
|
+
'Use it for code and engineering work too; the card sits under the reply and the reply keeps its normal plain-text format.',
|
|
21
22
|
'Put those actions only in the card; the reply gets at most one lead-in sentence and never numbers or bullets them.',
|
|
22
23
|
'Skip greetings, acknowledgements, pure knowledge answers, repeated cards, and turns that already asked a structured question.',
|
|
23
24
|
].join(' ')
|
|
@@ -28,7 +29,8 @@ const TOOL = {
|
|
|
28
29
|
name: TOOL_NAME,
|
|
29
30
|
description: [
|
|
30
31
|
'Show 1–3 clickable next actions as a card under your reply; clicking one fills the message input, never sends.',
|
|
31
|
-
|
|
32
|
+
'Call it once before the final answer when this turn leaves real follow-up work.',
|
|
33
|
+
"Write the actions in the user's language and never repeat them in your prose.",
|
|
32
34
|
].join(' '),
|
|
33
35
|
parameters: {
|
|
34
36
|
type: 'object',
|
|
@@ -83,12 +85,18 @@ export function normalizeConfig(raw) {
|
|
|
83
85
|
return { enabled: !(raw !== null && typeof raw === 'object' && raw.enabled === false) }
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Ordinary session agents only. Delegated agents carry the durable
|
|
90
|
+
* `origin: 'subagent'` header; `AgentRegistry.roots()` no longer exists since
|
|
91
|
+
* DSH 0.2.1-rc.3, so the header is the supported discriminator. Fail open so a
|
|
92
|
+
* Harness change never silently hides the tool, and report the drift once.
|
|
93
|
+
*/
|
|
94
|
+
function isRoot(agent, onUnreadable) {
|
|
88
95
|
if (agent === undefined || agent === null) return true
|
|
89
96
|
try {
|
|
90
|
-
return
|
|
91
|
-
} catch {
|
|
97
|
+
return agent.session.header.origin !== 'subagent'
|
|
98
|
+
} catch (error) {
|
|
99
|
+
onUnreadable?.(error)
|
|
92
100
|
return true
|
|
93
101
|
}
|
|
94
102
|
}
|
|
@@ -96,17 +104,38 @@ function isRoot(ctx, agent) {
|
|
|
96
104
|
export function apply(ctx, config) {
|
|
97
105
|
if (!normalizeConfig(config).enabled) return
|
|
98
106
|
|
|
107
|
+
/** Host log, with a console fallback so a missing logger cannot hide the report. */
|
|
108
|
+
const warn = (message) => {
|
|
109
|
+
const line = `dsh-next-actions: ${message}`
|
|
110
|
+
try {
|
|
111
|
+
if (typeof ctx.logger?.warn === 'function') {
|
|
112
|
+
ctx.logger.warn(line)
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
// Fall through: the warning must not depend on a working logger.
|
|
117
|
+
}
|
|
118
|
+
console.warn(line)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Report a header-shape change once; `when` runs on every tool resolution. */
|
|
122
|
+
let headerFailureReported = false
|
|
123
|
+
const isRootAgent = (agent) => isRoot(agent, (error) => {
|
|
124
|
+
if (headerFailureReported) return
|
|
125
|
+
headerFailureReported = true
|
|
126
|
+
warn(`agent session header unreadable; treating the agent as a root: ${String(error)}`)
|
|
127
|
+
})
|
|
128
|
+
|
|
99
129
|
ctx.effect(
|
|
100
|
-
() => ctx.tools.register(TOOL, { when: ({ agent }) =>
|
|
130
|
+
() => ctx.tools.register(TOOL, { when: ({ agent }) => isRootAgent(agent) }),
|
|
101
131
|
'dsh-next-actions: tool',
|
|
102
132
|
)
|
|
103
133
|
|
|
104
134
|
/** agent → disposer of its prompt section. */
|
|
105
135
|
const installed = new Map()
|
|
106
136
|
const install = (agent) => {
|
|
107
|
-
if (installed.has(agent)) return
|
|
137
|
+
if (installed.has(agent) || !isRootAgent(agent)) return
|
|
108
138
|
try {
|
|
109
|
-
if (!ctx.agents.roots().includes(agent)) return
|
|
110
139
|
const prompt = agent.ctx.systemPrompt
|
|
111
140
|
const base = prompt.getSectionOrder?.('TOOL_REPORT')
|
|
112
141
|
installed.set(agent, agent.ctx.effect(() => prompt.section({
|
|
@@ -114,8 +143,10 @@ export function apply(ctx, config) {
|
|
|
114
143
|
order: typeof base === 'number' ? base + 50 : 2950,
|
|
115
144
|
text: GUIDANCE,
|
|
116
145
|
}), 'dsh-next-actions: guidance'))
|
|
117
|
-
} catch {
|
|
118
|
-
// The
|
|
146
|
+
} catch (error) {
|
|
147
|
+
// The tool still works without the guidance; surface the degradation
|
|
148
|
+
// instead of silently losing the standing instruction.
|
|
149
|
+
warn(`guidance not installed: ${String(error)}`)
|
|
119
150
|
}
|
|
120
151
|
}
|
|
121
152
|
|
|
@@ -123,9 +154,11 @@ export function apply(ctx, config) {
|
|
|
123
154
|
const offCreated = ctx.on('agent/created', ({ agent }) => install(agent))
|
|
124
155
|
const offDisposed = ctx.on('agent/disposed', ({ agent }) => installed.delete(agent))
|
|
125
156
|
try {
|
|
126
|
-
for (const agent of ctx.agents.
|
|
127
|
-
} catch {
|
|
128
|
-
// Agents created later still arrive through agent/created
|
|
157
|
+
for (const agent of ctx.agents.list()) install(agent)
|
|
158
|
+
} catch (error) {
|
|
159
|
+
// Agents created later still arrive through agent/created, but agents
|
|
160
|
+
// that were already live at apply time keep missing the guidance.
|
|
161
|
+
warn(`could not install guidance on existing agents: ${String(error)}`)
|
|
129
162
|
}
|
|
130
163
|
return () => {
|
|
131
164
|
offCreated()
|