@zhushanwen/pi-ask-user 7.2.0 → 7.2.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/ARCHITECTURE.md +2 -2
- package/README.md +2 -2
- package/package.json +3 -3
- package/src/__tests__/answer-codec.test.ts +2 -2
- package/src/__tests__/channel-handler.test.ts +1 -1
- package/src/__tests__/index.test.ts +1 -1
- package/src/answer-codec.ts +1 -1
- package/src/channel-handler.ts +3 -3
- package/src/index.ts +3 -3
package/ARCHITECTURE.md
CHANGED
|
@@ -57,7 +57,7 @@ Source: 10 files in `src/`, ~2085 lines total.
|
|
|
57
57
|
|
|
58
58
|
`AnswerValue` (`types.ts`) is the single structured answer model — `{ selected: string[]; other: string | null }`. The old internal/proto double model is gone: proto `AskUserOption.value` equaled `label` (both were the same string), so the proto layer consumes the same single model (`Result.answers: Record<string, AnswerValue>`, key = question text).
|
|
59
59
|
|
|
60
|
-
Serialization happens **once, at the protocol boundary**: `encodeAnswer(value, { key, multiSelect })` in `answer-codec.ts` converts an `AnswerValue` into proto answers entries, byte-aligned with `@
|
|
60
|
+
Serialization happens **once, at the protocol boundary**: `encodeAnswer(value, { key, multiSelect })` in `answer-codec.ts` converts an `AnswerValue` into proto answers entries, byte-aligned with `@zhushanwen/extension-protocol` helpers' decode contract (`getAskUserAnswer` / `getAskUserOther`):
|
|
61
61
|
|
|
62
62
|
- 单选:`answers[key] = selected[0]`
|
|
63
63
|
- 多选:`answers[key] = JSON.stringify(selected)`
|
|
@@ -176,7 +176,7 @@ Constants: `SPLIT_PANE_MIN_WIDTH = 84`, `SPLIT_PANE_LEFT_MIN = 32`, `SPLIT_PANE_
|
|
|
176
176
|
|
|
177
177
|
## Spec cross-reference
|
|
178
178
|
|
|
179
|
-
The original spec files (`.
|
|
179
|
+
The original spec files (`.taiji-harness/2026-06-15-ask-user/`) are no longer in the repo — this table is self-contained (FR = functional requirement from the original spec). Implementation anchors:
|
|
180
180
|
|
|
181
181
|
| Spec | Implemented in |
|
|
182
182
|
|------|----------------|
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ The tool's primary caller is the LLM. This README covers both **how an agent sho
|
|
|
10
10
|
pi install npm:@zhushanwen/pi-ask-user
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
> **Dev-only symlink**: during local development you may symlink this package into `~/.pi/agent/extensions/` for debugging, but **never use the symlinked copy for daily work**. Local directory discovery has an `index.ts` fallback that masks a missing `pi` manifest field — npm-installed copies then silently fail to load. See
|
|
13
|
+
> **Dev-only symlink**: during local development you may symlink this package into `~/.pi/agent/extensions/` for debugging, but **never use the symlinked copy for daily work**. Local directory discovery has an `index.ts` fallback that masks a missing `pi` manifest field — npm-installed copies then silently fail to load. See `docs/extensions/extension-conventions.md` "扩展安装红线".
|
|
14
14
|
|
|
15
15
|
## When to use
|
|
16
16
|
|
|
@@ -138,7 +138,7 @@ All three are consistent and point the same direction. If you tune behavior, edi
|
|
|
138
138
|
|
|
139
139
|
## Spec reference
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
Design spec files are not kept in this repo. The FR cross-reference table in ARCHITECTURE.md is self-contained: each entry names the behavior and where it is implemented in this codebase.
|
|
142
142
|
|
|
143
143
|
## License
|
|
144
144
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-ask-user",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.2",
|
|
4
4
|
"description": "Inline adaptive ask_user tool for Pi — single/multi-question structured input with split-pane preview and an inline free-text editor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
7
|
-
"
|
|
7
|
+
"taiji": {
|
|
8
8
|
"role": "universal"
|
|
9
9
|
},
|
|
10
10
|
"pi": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"ARCHITECTURE.md"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@
|
|
32
|
+
"@zhushanwen/extension-protocol": "0.11.0",
|
|
33
33
|
"@zhushanwen/pi-ext-guards": "0.4.0",
|
|
34
34
|
"@zhushanwen/pi-extension-logger": "0.6.0"
|
|
35
35
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/__tests__/answer-codec.test.ts
|
|
2
2
|
// encodeAnswer 单向序列化 round-trip 测试(TC-09)。
|
|
3
|
-
// 反向验证用 @
|
|
3
|
+
// 反向验证用 @zhushanwen/extension-protocol 的解码 helper(getAskUserAnswer / getAskUserOther)
|
|
4
4
|
// ——该 helper 是 proto answers 格式的唯一解码 SSOT,encode 输出必须与其字节级对齐。
|
|
5
5
|
// m1 增量(TC-01):property-based describe 作为 5 个确定性用例的随机化超集补充。
|
|
6
|
-
import { getAskUserAnswer, getAskUserOther } from "@
|
|
6
|
+
import { getAskUserAnswer, getAskUserOther } from "@zhushanwen/extension-protocol";
|
|
7
7
|
import fc from "fast-check";
|
|
8
8
|
import { describe, expect, it } from "vitest";
|
|
9
9
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// (single/multi/Other 三种答案形态,经 encodeAnswer 序列化)。
|
|
11
11
|
// - 取消(askUserInteract/custom 返回 null 或 cancelled)→ {cancelled: true}
|
|
12
12
|
// - 输入校验(channelPayload 缺失/无 questions)→ {cancelled: true}
|
|
13
|
-
import type { AskUserQuestion } from "@
|
|
13
|
+
import type { AskUserQuestion } from "@zhushanwen/extension-protocol";
|
|
14
14
|
import { describe, expect, it } from "vitest";
|
|
15
15
|
|
|
16
16
|
import { createAskUserChannelHandler } from "../channel-handler";
|
|
@@ -522,7 +522,7 @@ describe("execute — inline render (FR-3)", () => {
|
|
|
522
522
|
});
|
|
523
523
|
});
|
|
524
524
|
|
|
525
|
-
// ── RPC 模式(
|
|
525
|
+
// ── RPC 模式(taiji GUI 富交互协议)──────────────────
|
|
526
526
|
// hasUI=false + ui.select 存在 → 走 askUserInteract(select 通道 + ASK_USER_MARKER)。
|
|
527
527
|
// select 的返回值是前端 JSON.stringify 的 AskUserAnswers,index.ts 做格式转换。
|
|
528
528
|
describe("execute — RPC mode (askUserInteract via select channel)", () => {
|
package/src/answer-codec.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/answer-codec.ts
|
|
2
2
|
// AnswerValue → proto answers 条目的单向序列化(协议边界 SSOT)。
|
|
3
|
-
// 与 @
|
|
3
|
+
// 与 @zhushanwen/extension-protocol helpers.ts 的解码契约字节级对齐:
|
|
4
4
|
// - 单选:answers[key] = selected[0]
|
|
5
5
|
// - 多选:answers[key] = JSON.stringify(selected)
|
|
6
6
|
// - Other:answers[`${key}__other`] = other
|
package/src/channel-handler.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// ask_user channel handler:把 subagent 子进程的 ask_user 请求透传到主进程 UI 渲染。
|
|
4
4
|
//
|
|
5
|
-
// 设计(关键决策):askUserInteract(@
|
|
5
|
+
// 设计(关键决策):askUserInteract(@zhushanwen/extension-protocol)只在 RPC 模式可用
|
|
6
6
|
// (内部 isGuiCapable 检查 mode==='rpc',TUI 下抛错)。所以 handler 按 ctx.mode 分流:
|
|
7
7
|
// - RPC:转发器——调 askUserInteract(guiCtx, protoQuestions),复用 select 通道 +
|
|
8
8
|
// ASK_USER_MARKER 契约,主进程 ctx.ui.select 经 GUI sidecar 渲染(不进 parseSpawnLine,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
type AskUserAnswers,
|
|
22
22
|
askUserInteract,
|
|
23
23
|
type AskUserQuestion,
|
|
24
|
-
} from "@
|
|
24
|
+
} from "@zhushanwen/extension-protocol";
|
|
25
25
|
|
|
26
26
|
import { AskUserComponent } from "./component";
|
|
27
27
|
import { encodeAnswer } from "./answer-codec";
|
|
@@ -71,7 +71,7 @@ function protoToInternalQuestions(protoQuestions: AskUserQuestion[]): Question[]
|
|
|
71
71
|
* 内部 Result.answers:key = question 全文,value = 结构化 AnswerValue
|
|
72
72
|
* (selected = option label 数组,other = Other 自由文本)。
|
|
73
73
|
*
|
|
74
|
-
* proto AskUserAnswers 契约(@
|
|
74
|
+
* proto AskUserAnswers 契约(@zhushanwen/extension-protocol):
|
|
75
75
|
* - key = question.header ?? question 全文
|
|
76
76
|
* - 单选:value = 选中项 label string
|
|
77
77
|
* - 多选:value = JSON.stringify(选中项 label 数组)
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
type AskUserQuestion,
|
|
9
9
|
getAskUserAnswer,
|
|
10
10
|
getAskUserOther,
|
|
11
|
-
} from "@
|
|
11
|
+
} from "@zhushanwen/extension-protocol";
|
|
12
12
|
import { toErrorMessage } from "@zhushanwen/pi-ext-guards";
|
|
13
13
|
|
|
14
14
|
import { createAskUserChannelHandler } from "./channel-handler";
|
|
@@ -176,7 +176,7 @@ function protoAnswersToResult(
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
|
-
* RPC 模式(
|
|
179
|
+
* RPC 模式(taiji GUI)交互入口。
|
|
180
180
|
*
|
|
181
181
|
* 走 askUserInteract(select 通道 + ASK_USER_MARKER),前端 AskUserOverlay 渲染富交互 UI。
|
|
182
182
|
* 返回 Result(正常/取消),或抛错(select 异常 / 非 RPC 模式调用了此函数)。
|
|
@@ -295,7 +295,7 @@ Don't:
|
|
|
295
295
|
);
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
// 4. 交互执行:TUI 走 ctx.ui.custom,RPC(
|
|
298
|
+
// 4. 交互执行:TUI 走 ctx.ui.custom,RPC(taiji GUI)走 askUserInteract。
|
|
299
299
|
// 注意:hasUI 在 TUI 和 RPC 模式都为 true(dialog-capable),不能用于区分——
|
|
300
300
|
// 用 ctx.mode === 'rpc' 判定 GUI 渲染通道。
|
|
301
301
|
const useRpc = ctx.mode === "rpc";
|