@zhushanwen/pi-session-manager 0.2.3 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhushanwen/pi-session-manager",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Pi extension for managing agent-managed sessions — create, send, read history, list, status, abort via ctx.ui.select channel.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -30,11 +30,11 @@
30
30
  "README.md"
31
31
  ],
32
32
  "dependencies": {
33
- "@zhushanwen/extension-protocol": "0.17.0",
34
- "@zhushanwen/pi-ext-guards": "0.4.2",
35
- "@zhushanwen/pi-extension-logger": "0.6.1",
36
- "@zhushanwen/pi-notify-ledger-host": "0.2.3",
37
- "@zhushanwen/subagent-core": "1.2.0"
33
+ "@zhushanwen/extension-protocol": "0.18.0",
34
+ "@zhushanwen/pi-notify-ledger-host": "0.3.0",
35
+ "@zhushanwen/subagent-core": "1.3.0",
36
+ "@zhushanwen/pi-ext-guards": "0.4.3",
37
+ "@zhushanwen/pi-extension-logger": "0.6.2"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^24.0.0",
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@earendil-works/pi-coding-agent": "*",
46
- "typebox": "*"
46
+ "typebox": "1.3.27"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "@earendil-works/pi-coding-agent": {
@@ -11,7 +11,7 @@ describe("U5-A4 tool-error-handling", () => {
11
11
  vi.clearAllMocks();
12
12
  });
13
13
 
14
- it("select returning undefined (user cancel/timeout) → cancelled throw(W4 范式:错误路径 throw)", async () => {
14
+ it("select returning undefined (user cancel/channel error) → cancelled throw(W4 范式:错误路径 throw)", async () => {
15
15
  await expectToolRejects(
16
16
  createToolHarness(vi.fn().mockResolvedValue(undefined)),
17
17
  "create_managed_session",
@@ -53,8 +53,8 @@ describe("U5-A2 tool-execute", () => {
53
53
  expect(options).toHaveLength(1);
54
54
  const payload = JSON.parse(options[0]);
55
55
  expect(payload.action).toBe(expectedAction);
56
- // third arg has timeout
57
- expect(opts).toHaveProperty("timeout");
56
+ // third arg: timeout 不传(ADR-0122 无包内挂死兜底,全 action 无 timer 长挂)
57
+ expect(opts).toHaveProperty("timeout", undefined);
58
58
  });
59
59
 
60
60
  it("create_managed_session includes cwd and label in payload.params", async () => {
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  import type {
5
5
  ExtensionAPI,
6
6
  ExtensionContext,
7
+ ExtensionToolContext,
7
8
  SessionCompactEvent,
8
9
  SessionStartEvent,
9
10
  } from "@earendil-works/pi-coding-agent";
@@ -55,27 +56,19 @@ const AbortSessionParams = Type.Object({
55
56
 
56
57
  // ── select 通道辅助 ──
57
58
 
58
- /** select 超时(ms):工具等待 runtime handler respond 的最大时间(create/history 走长链路放宽)。
59
- * watch 刻意缺席(notify-once D2:不传 timeout、fire-and-forget 长挂——P1 实测 `if
60
- * (opts?.timeout)` 才设 timer)。形制 = `Exclude<SessionManagerAction, "watch">`:
61
- * 协议 action 集 6→7 后漏配键即编译期红(计划 blocker #1 的修复形态)。 */
62
- const SELECT_TIMEOUT_MS: Record<Exclude<SessionManagerAction, "watch">, number> = {
63
- create: 60_000,
64
- send: 30_000,
65
- history: 60_000,
66
- status: 30_000,
67
- list: 30_000,
68
- abort: 30_000,
69
- };
70
-
71
59
  /**
72
60
  * 通过 select 通道向 runtime handler 发送 session 管理请求(传输核走 protocol 的
73
61
  * callMarkerRpc 原语,D8)。回包为 handler respond 的 JSON 字符串(value 恒 raw);
74
- * 失败四态(cancelled/timeout/channel-error/non-json)由 executeTool 统一 throw——
75
- * pi agent-loop 仅在 execute throw 时置 isError:true,返回值里的 isError 字段被丢弃
76
- * (pi-agent-core dist/agent-loop.js:453-483 executePreparedToolCall:正常 return
77
- * 硬编码 isError:false、catch 置 true——0.84.4 实读 :468/:470-476;语义登记 PS-56)。
62
+ * 失败态(cancelled/channel-error/non-json)由 executeTool 统一 throw——
63
+ * execute throw → pi agent-loop catch 置 isError:true(pi-agent-core dist/agent-loop.js
64
+ * executePreparedToolCall,1.0.0 实读 catch :581-588);1.0.0 起返回值 isError:true 也被
65
+ * 尊重(同文件 :579 `isError: result.isError === true`,0.84.4 时返回值会被丢弃)——
66
+ * 本工具失败恒走 throw,两版语义等价(语义登记 PS-56)。
78
67
  * 通道异常与非 JSON 回包的留痕由原语经注入的 log 承担。
68
+ *
69
+ * 不传 timeout(ADR-0122:无包内挂死兜底,handler 不回包时工具调用长挂、失败直报;
70
+ * 原 SELECT_TIMEOUT_MS per-action 表已删——原 watch 通道 D2/P1 的无 timer 长挂形态
71
+ * 现为全部 action 统一形态:任意晚的 respond 按 id 精确 resolve)。
79
72
  */
80
73
  function callSessionManager(
81
74
  ctx: ExtensionContext,
@@ -95,8 +88,7 @@ function callSessionManager(
95
88
  ui: { select: ctx.ui.select.bind(ctx.ui) },
96
89
  };
97
90
  return callMarkerRpc(guiCtx, SESSION_MANAGER_MARKER, payload, {
98
- // watch 不传 timeout(D2/P1:无 timer 长挂不死,任意晚的 respond 按 id 精确 resolve;PS-59)
99
- timeout: action === "watch" ? undefined : SELECT_TIMEOUT_MS[action],
91
+ // 全 action 不传 timeout(ADR-0122:无包内挂死兜底;无 timer 长挂,任意晚的 respond 按 id 精确 resolve)
100
92
  log: (msg, detail) => logger.error(`[session-manager] ${msg}`, detail),
101
93
  });
102
94
  }
@@ -117,10 +109,13 @@ function asResultRecord(v: unknown): Record<string, unknown> | undefined {
117
109
  /**
118
110
  * 统一的 execute 包装:调用 select 通道并解析结果。
119
111
  * 返回标准 AgentToolResult 形状;select 取消/超时/异常/非 JSON 回包是错误路径,
120
- * 必须 throw(extension-conventions「禁止错误成功模式」——pi 契约里 execute 只有
121
- * throw 才被置 isError:true,返回值携带 isError 字段会被 agent-loop 丢弃
122
- * (agent-loop.js:453-483,PS-56),ask-user/scheduler/session-reader 的 W4 throw
123
- * 范式同款;调用方 agent 需能区分成功与失败以决定重试/放弃)。
112
+ * 必须 throw(extension-conventions「禁止错误成功模式」——execute throw → pi
113
+ * agent-loop catch 置 isError:true(pi-agent-core dist/agent-loop.js
114
+ * executePreparedToolCall,1.0.0 实读 catch :581-588);1.0.0 起返回值 isError:true
115
+ * 也被尊重(同文件 :579 `isError: result.isError === true`,0.84.4 时返回值会被
116
+ * 丢弃)——本工具失败恒走 throw,两版语义等价(语义登记 PS-56);
117
+ * ask-user/scheduler/session-reader 的 W4 throw 范式同款,调用方 agent 需能区分
118
+ * 成功与失败以决定重试/放弃)。
124
119
  */
125
120
  async function executeTool(
126
121
  ctx: ExtensionContext,
@@ -130,13 +125,13 @@ async function executeTool(
130
125
  ): Promise<{ content: Array<{ type: "text"; text: string }>; details: undefined }> {
131
126
  const result = await callSessionManager(ctx, action, params);
132
127
  if (!result.ok) {
133
- // 行为微变①(D8,有意——对齐 plugin-bridge 形态):非 JSON 回包从「catch 后
128
+ // 行为微变①(D8,有意):非 JSON 回包从「catch 后
134
129
  // parsed=undefined 静默当成功文本返回」改为 throw + 提示文本(留痕由原语
135
- // 经注入的 logger.error 承担);其余三态维持原 cancelled/timeout 折叠文案。
130
+ // 经注入的 logger.error 承担);不传 timeout 后剩余 cancelled/channel-error 两态折叠。
136
131
  const text =
137
132
  result.reason === "non-json"
138
133
  ? `Session manager ${action}: non-JSON response from runtime (protocol mismatch — redeploy same-version runtime + extension; see extension logs).`
139
- : `Session manager ${action}: cancelled or timed out.`;
134
+ : `Session manager ${action}: cancelled or channel error.`;
140
135
  throw new Error(text);
141
136
  }
142
137
  const raw = result.value;
@@ -189,7 +184,8 @@ function registerSessionTool<S extends TObject>(pi: ExtensionAPI, cfg: SessionTo
189
184
  params: Static<S>,
190
185
  _signal: AbortSignal | undefined,
191
186
  _onUpdate: unknown,
192
- ctx: ExtensionContext,
187
+ // pi 1.0.0:ToolDefinition.execute 第 5 参 ctx 收窄为 ExtensionToolContext
188
+ ctx: ExtensionToolContext,
193
189
  ) {
194
190
  return executeTool(ctx, cfg.action, cfg.toParams(params), cfg.onResult);
195
191
  },