@deepseek-ai/dsh-plan-mode 0.1.0-rc.8 → 0.1.1-rc.2

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/README.i18n.yaml CHANGED
@@ -3,4 +3,4 @@
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/plan/plan-mode/README.md
5
5
  README.md: 3eabe2cb3f04b434b7f908f7beca869f1022a59e
6
- README.zh.md: f7d6a1f8e9f5ba95f8aad9457f3dde5fc415fdcf
6
+ README.zh.md: b3548da880af5d0cacfebba4486294d9d5085626
package/README.zh.md CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  `ctx.planMode.set(agent, active)` 会在 agent 空闲时立即追加独立的 `plan/mode` 事件,因为下一个提示词之前不会运行轮内 pre-step。agent 运行时,该方法会保留待生效选择,直到下一个被接受的轮内 pre-step。返回值区分 `committed`、`queued`、表示反转的 `cancelled` 和 `noop`。`get(agent)` 返回 `{ active, pending? }`,将用于组装当前步骤的日志状态与用户的轮中选择分开。初始与续步 pre-step 都会应用待生效选择;同一步骤的请求恢复重试会复用已冻结的 assembly,并将该选择保留到下一个被接受的轮内 pre-step。当最后记录的请求头描述了另一状态时,用户选择的变更会贡献一条插件来源的 `user/message` 通知(两条提交路径皆然)。
12
12
 
13
+ <a id="model-and-human-interactions"></a>
14
+
13
15
  ## 模型与人类交互
14
16
 
15
17
  激活时,`plan:policy` 会渲染已配置的 `section`。插件始终注册 `exit_plan_mode`,使工具 schema 在转换期间保持稳定;其 execute 路径只接受已激活的 plan mode,且只有通过 `ctx.userQuestions` 获得用户明确批准后才退出。
@@ -22,7 +24,7 @@ Web 客户端使用该插件提供的 `/plan` 命令;其他入口可以直接
22
24
 
23
25
  ## 会话投影
24
26
 
25
- 当组合挂载 `ctx.sessionProjections`([`@deepseek-ai/dsh-session-projection`](../../session/session-projection/README.md))时,本包会在一个注入的子插件中注册 `plan` 投影单元。名为 `plan` 且携带已记录 `args` 的 `command/run` 记录会开始一个候选目标(`off` → 未激活,其余 → 激活);与它配对的 `command/done` 保留成功选择并丢弃错误选择;`plan/mode` 提交已记录状态并清除已保留的选择。其他任何事件都返回同一个状态引用。`view` 推导 `{ active, pending }`,其中 `pending` 仅在未结算或已成功的选择与已记录状态不同时为 true。该值仍完全由日志回放得出,因此 host 重启、其他标签页和冷读都能仅凭日志恢复它,被拒绝的带图 `/plan off` 也不会留下待退出状态。key 由 `src/types.ts` 通过声明合并加入 `SessionProjectionMap`:host 消费方经 `./types` 获取,client 聚合经 `./client` 获取。框架负责驱动该单元,载体通过历史尾页和 `session/projection` 推送帧提供其值。未挂载注册表的组合不受影响。
27
+ 当组合挂载 `ctx.sessionProjections`([`@deepseek-ai/dsh-session-projection`](../../session/session-projection/README.zh.md))时,本包会在一个注入的子插件中注册 `plan` 投影单元。名为 `plan` 且携带已记录 `args` 的 `command/run` 记录会开始一个候选目标(`off` → 未激活,其余 → 激活);与它配对的 `command/done` 保留成功选择并丢弃错误选择;`plan/mode` 提交已记录状态并清除已保留的选择。其他任何事件都返回同一个状态引用。`view` 推导 `{ active, pending }`,其中 `pending` 仅在未结算或已成功的选择与已记录状态不同时为 true。该值仍完全由日志回放得出,因此 host 重启、其他标签页和冷读都能仅凭日志恢复它,被拒绝的带图 `/plan off` 也不会留下待退出状态。key 由 `src/types.ts` 通过声明合并加入 `SessionProjectionMap`:host 消费方经 `./types` 获取,client 聚合经 `./client` 获取。框架负责驱动该单元,载体通过历史尾页和 `session/projection` 推送帧提供其值。未挂载注册表的组合不受影响。
26
28
 
27
29
  ## 配置
28
30
 
@@ -37,7 +39,7 @@ Web 客户端使用该插件提供的 `/plan` 命令;其他入口可以直接
37
39
 
38
40
  `section` 必填且非空。出现未知键时,插件会加载失败。该包不接受任意命名的 mode、工具过滤器、沙箱设置或批准策略。
39
41
 
40
- 设计:[plan 专用协作状态](../../../.agents/notes/implemented/simplification/2026-07-22-plan-specific-collaboration-state.md)。
42
+ 设计:[plan 专用协作状态](../../../.agents/notes/implemented/simplification/2026-07-22-plan-specific-collaboration-state.zh.md)。
41
43
 
42
44
  ## 模型体验
43
45
 
@@ -79,7 +81,7 @@ You are in plan mode. Explore and design before presenting the complete plan thr
79
81
 
80
82
  #### 模型所见内容
81
83
 
82
- [`exit_plan_mode` schema](../../../docs/tool-catalog.md#deepseek-aidsh-plan-mode) 在两种状态下均可用;在 plan mode 外执行会失败,而 plan mode 内经批准的评审会返回规范的 `{ approved: true }` 值,并渲染既有的确认文本。拒绝仍是携带评审反馈的失败调用,放弃审阅则是一次指明用户接手的失败调用。
84
+ [`exit_plan_mode` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-plan-mode) 在两种状态下均可用;在 plan mode 外执行会失败,而 plan mode 内经批准的评审会返回规范的 `{ approved: true }` 值,并渲染既有的确认文本。拒绝仍是携带评审反馈的失败调用,放弃审阅则是一次指明用户接手的失败调用。
83
85
 
84
86
  #### Token 影响
85
87
 
@@ -89,6 +91,8 @@ You are in plan mode. Explore and design before presenting the complete plan thr
89
91
 
90
92
  mode 转换不改变工具目录;plan 参数与评审结果按常规方式扩展对话。
91
93
 
94
+ <a id="known-limitations-and-deferred-work"></a>
95
+
92
96
  ## 已知限制与暂缓事项
93
97
 
94
98
  - Plan mode 只进行引导,而不强制执行;需要强制限制的部署必须分别配置沙箱与批准控制。
package/lib/index.js CHANGED
@@ -80,6 +80,14 @@ function foldPlanMode(events, end = events.length) {
80
80
  }
81
81
  return active;
82
82
  }
83
+ const planUnitStateSchema = z.object({
84
+ active: z.boolean(),
85
+ wanted: z.boolean().nullable(),
86
+ running: z.object({
87
+ commandId: z.string(),
88
+ wanted: z.boolean()
89
+ }).strict().nullable()
90
+ }).strict();
83
91
  /** Wire payload schema of the `plan` projection. */
84
92
  const planProjectionSchema = z.object({
85
93
  active: z.boolean(),
@@ -152,7 +160,7 @@ var PlanModeController = class extends Service {
152
160
  ctx.inject(["sessionProjections"], (projectionCtx) => {
153
161
  projectionCtx.sessionProjections.register({
154
162
  key: "plan",
155
- schema: planProjectionSchema,
163
+ stateSchema: planUnitStateSchema,
156
164
  init: () => ({
157
165
  active: false,
158
166
  wanted: null,
@@ -185,12 +193,15 @@ var PlanModeController = class extends Service {
185
193
  };
186
194
  return state;
187
195
  },
188
- view: (state) => {
189
- const wanted = state.running?.wanted ?? state.wanted;
190
- return {
191
- active: state.active,
192
- pending: wanted !== null && wanted !== state.active
193
- };
196
+ wire: {
197
+ viewSchema: planProjectionSchema,
198
+ view: (state) => {
199
+ const wanted = state.running?.wanted ?? state.wanted;
200
+ return {
201
+ active: state.active,
202
+ pending: wanted !== null && wanted !== state.active
203
+ };
204
+ }
194
205
  },
195
206
  stateVersion: 2
196
207
  });
@@ -25,6 +25,7 @@
25
25
  import { Context, Service } from '@deepseek-ai/cordis';
26
26
  import type { Agent } from '@deepseek-ai/dsh-agent';
27
27
  import type { SessionEvent } from '@deepseek-ai/dsh-session';
28
+ import type { CommandId } from '@deepseek-ai/dsh-commands';
28
29
  export type * from './types.ts';
29
30
  declare module '@deepseek-ai/dsh-session/types' {
30
31
  interface SessionEventMap {
@@ -70,6 +71,27 @@ export declare function resolveConfig(config: PlanModeConfig): PlanModeConfig;
70
71
  * @returns Whether plan mode is active.
71
72
  */
72
73
  export declare function foldPlanMode(events: readonly SessionEvent[], end?: number): boolean;
74
+ /**
75
+ * Projection unit state: the logged mode, the latest successful `/plan`
76
+ * selection not yet resolved by a `plan/mode` commit, and an execution whose
77
+ * paired `command/done` has not settled. Plain JSON (persisted-cache
78
+ * precondition).
79
+ */
80
+ interface PlanUnitState {
81
+ active: boolean;
82
+ /** The selection's target mode; null when no selection is outstanding. */
83
+ wanted: boolean | null;
84
+ /** The latest plan command awaiting its paired settlement. */
85
+ running: {
86
+ commandId: CommandId;
87
+ wanted: boolean;
88
+ } | null;
89
+ }
90
+ declare module '@deepseek-ai/dsh-session-projection/types' {
91
+ interface SessionProjectionStateMap {
92
+ plan: PlanUnitState;
93
+ }
94
+ }
73
95
  /**
74
96
  * `ctx.planMode`: owns logged plan state, applies and narrates selected state at step start,
75
97
  * the `plan:policy` section, the `/plan` command, and the stable exit tool.
@@ -92,6 +92,14 @@ export function foldPlanMode(events, end = events.length) {
92
92
  }
93
93
  return active;
94
94
  }
95
+ const planUnitStateSchema = zod.object({
96
+ active: zod.boolean(),
97
+ wanted: zod.boolean().nullable(),
98
+ running: zod.object({
99
+ commandId: zod.string(),
100
+ wanted: zod.boolean(),
101
+ }).strict().nullable(),
102
+ }).strict();
95
103
  /** Wire payload schema of the `plan` projection. */
96
104
  const planProjectionSchema = zod.object({
97
105
  active: zod.boolean(),
@@ -183,7 +191,7 @@ export class PlanModeController extends Service {
183
191
  ctx.inject(['sessionProjections'], (projectionCtx) => {
184
192
  projectionCtx.sessionProjections.register({
185
193
  key: 'plan',
186
- schema: planProjectionSchema,
194
+ stateSchema: planUnitStateSchema,
187
195
  init: () => ({ active: false, wanted: null, running: null }),
188
196
  apply: (state, event) => {
189
197
  if (event.type === 'command/run' && event.data.name === 'plan') {
@@ -203,9 +211,12 @@ export class PlanModeController extends Service {
203
211
  }
204
212
  return state;
205
213
  },
206
- view: (state) => {
207
- const wanted = state.running?.wanted ?? state.wanted;
208
- return { active: state.active, pending: wanted !== null && wanted !== state.active };
214
+ wire: {
215
+ viewSchema: planProjectionSchema,
216
+ view: (state) => {
217
+ const wanted = state.running?.wanted ?? state.wanted;
218
+ return { active: state.active, pending: wanted !== null && wanted !== state.active };
219
+ },
209
220
  },
210
221
  stateVersion: 2,
211
222
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-plan-mode",
3
3
  "description": "Logged per-agent plan mode with deployment guidance, a direct slash command, and a user-reviewed exit",
4
- "version": "0.1.0-rc.8",
4
+ "version": "0.1.1-rc.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -41,16 +41,16 @@
41
41
  ],
42
42
  "license": "MIT",
43
43
  "peerDependencies": {
44
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.8",
45
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.8",
46
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.8",
47
- "@deepseek-ai/dsh-session": "^0.1.0-rc.8",
48
- "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.8",
49
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8",
50
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.8",
51
- "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.8",
52
- "@deepseek-ai/cordis": "^4.0.1",
53
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.8"
44
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
45
+ "@deepseek-ai/dsh-commands": "^0.1.1-rc.2",
46
+ "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
47
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
48
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
49
+ "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
50
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
51
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
52
+ "@deepseek-ai/dsh-user-questions": "^0.1.1-rc.2",
53
+ "@deepseek-ai/cordis": "^4.0.1"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "@deepseek-ai/dsh-commands": {
@@ -61,17 +61,17 @@
61
61
  "zod": "^4.4.3"
62
62
  },
63
63
  "devDependencies": {
64
- "@deepseek-ai/dsh-agent-loop": "^0.1.0-rc.8",
65
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.8",
66
- "@deepseek-ai/dsh-code-runtime": "^0.1.0-rc.8",
67
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.8",
68
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.8",
69
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.8",
70
- "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.8",
71
- "@deepseek-ai/dsh-session": "^0.1.0-rc.8",
72
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8",
73
- "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.8",
74
- "@deepseek-ai/cordis": "^4.0.1",
75
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.8"
64
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
65
+ "@deepseek-ai/dsh-agent-loop": "^0.1.1-rc.2",
66
+ "@deepseek-ai/dsh-code-runtime": "^0.1.1-rc.2",
67
+ "@deepseek-ai/dsh-commands": "^0.1.1-rc.2",
68
+ "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
69
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
70
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
71
+ "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
72
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
73
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
74
+ "@deepseek-ai/dsh-user-questions": "^0.1.1-rc.2",
75
+ "@deepseek-ai/cordis": "^4.0.1"
76
76
  }
77
77
  }