@deepseek-ai/dsh-user-questions 0.2.0-rc.1 → 0.2.0-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
@@ -9,26 +9,17 @@
9
9
  en: 79d2910e509a2512
10
10
  zh: 7af1982658f00d64
11
11
  /deepseek-ai-dsh-user-questions/summary:
12
- en: d27ce8b495269248
13
- zh: 691a7cc7f3d892d0
12
+ en: 2c1ade8d86e6a8c7
13
+ zh: 97d43dcf997d6ff7
14
14
  /deepseek-ai-dsh-user-questions/table-of-contents:
15
- en: ad3919bb107cc38d
16
- zh: 557af29a8318b65c
17
- /deepseek-ai-dsh-user-questions/service-userquestionservice-ctx-key-userquestions:
18
- en: 1ba3467a2588da42
19
- zh: 74f6e516f71116d9
20
- /deepseek-ai-dsh-user-questions/service-userquestionservice-ctx-key-userquestions/public-api:
21
- en: f7c183c8728b05cd
22
- zh: f0104632d8eb2938
23
- /deepseek-ai-dsh-user-questions/service-userquestionservice-ctx-key-userquestions/key-types:
24
- en: 10637ca40891d520
25
- zh: 015662eb651d19cb
26
- /deepseek-ai-dsh-user-questions/service-userquestionservice-ctx-key-userquestions/presentation-intent:
27
- en: d3809cfa854f1c02
28
- zh: f9bcc88f1db8fd83
15
+ en: 382a21c0ea17b2e4
16
+ zh: 1a4335e571de92dd
17
+ /deepseek-ai-dsh-user-questions/ask-a-question:
18
+ en: 0c45d3161b0df13a
19
+ zh: efff84a7917a799e
29
20
  /deepseek-ai-dsh-user-questions/role:
30
- en: 1d4b9680e35350a7
31
- zh: fcba25211099b880
21
+ en: 1a321b5a204dc4dd
22
+ zh: 5e30055a3774e606
32
23
  /deepseek-ai-dsh-user-questions/model-experience:
33
24
  en: 95167d0c957a0ab5
34
25
  zh: 582c04395648786c
@@ -36,8 +27,8 @@
36
27
  en: 40294c1c31b74824
37
28
  zh: cd40bdfe1a1c37dc
38
29
  /deepseek-ai-dsh-user-questions/known-limitations-and-deferred-work:
39
- en: 9c2d868427856d56
40
- zh: f0d19979fd90d826
30
+ en: a2334c0fcb02d2d8
31
+ zh: 4592c204397387ac
41
32
  /deepseek-ai-dsh-user-questions/known-limitations-and-deferred-work/dev-note:
42
- en: f5f2c82d2e085ccf
43
- zh: d04ca73d1db0ef0f
33
+ en: afb3435052693913
34
+ zh: 675913943166be2d
package/README.md CHANGED
@@ -9,11 +9,11 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- User-interaction Service Definition. It owns `ctx.userQuestions`, the service a model-facing tool or permission plugin uses when it needs to pause work and ask the human for a decision. Use it when a consumer must suspend an operation until the user answers.
12
+ Use `ctx.userQuestions` when a tool or permission flow needs a structured answer from the user. `ask()` waits for that answer; `askTimed()` may release the agent to continue independent work while the question remains answerable in the Session.
13
13
 
14
14
  ## Table of Contents
15
15
 
16
- - [Service: `UserQuestionService` (ctx key: `userQuestions`)](#service-userquestionservice-ctx-key-userquestions)
16
+ - [Ask a question](#service-userquestionservice-ctx-key-userquestions)
17
17
  - [Role](#role)
18
18
  - [Model Experience](#model-experience)
19
19
  - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
@@ -22,32 +22,22 @@ User-interaction Service Definition. It owns `ctx.userQuestions`, the service a
22
22
  -----
23
23
 
24
24
  <a id="service-userquestionservice-ctx-key-userquestions"></a>
25
- ## Service: `UserQuestionService` (ctx key: `userQuestions`)
25
+ ## Ask a question
26
26
 
27
- ### Public API
28
-
29
- - `ctx.userQuestions.ask(request): Promise<AskUserQuestionAnswer>` Dispatch the answerer waterfall and wait for the first accepted answer.
30
-
31
- ### Key Types
32
-
33
- - `AskUserQuestionRequest` — `{ questions: [{ id, question, detail?, header?, options?, multiSelect?, intent? }], agent?, signal? }`; `detail` supplies supporting text that providers render with the question without turning it into an option label. When present, `agent` must be the registry's exact live runtime root.
34
- - `AskUserQuestionOption` — `{ label, description? }`.
35
- - `AskUserQuestionIntent` — `{ kind: 'plan-review', approve }`; the tagged presentation intent below.
36
- - `AskUserQuestionAnswer` — `{ answers: [{ id, selected, custom? }] }`.
37
- - `UserQuestionError` — `HarnessError` subclass with codes such as `EMPTY_QUESTIONS`, `BAD_INTENT`, `NO_PROVIDER`, `ASK_ABORTED`, `CALLER_NOT_LIVE`, and `DELEGATED_CALLER`.
27
+ Call `ask()` when work cannot continue without the answer. Call `askTimed()` when the agent may continue independent work after a foreground wait. An answer UI claims that wait through `attachWait`, receives the Host-computed remaining duration, and counts down on its own clock. Without a claim, including after the last Client disconnects, the service releases the model at the original deadline. The `userQuestions` projection derives durable questions from the tool call, its result, and the eventual reply; Client claims are not persisted.
38
28
 
39
29
  For a single-select question, `custom` overrides the selected choice and `selected` is empty. For a multi-select question, `custom` may supplement the labels in `selected`. A UI may preserve a skipped item as `{ id, selected: [] }`, keeping the existing answer shape while retaining other answers in the batch.
40
30
 
41
- When a request carries an agent, `ask()` authenticates its exact identity through the live `AgentRegistry` and admits only a runtime root. Durable lineage is not authority: a session with historical delegation depth may ask after it is resumed as a new runtime root, while a live child owned by another agent is rejected even if its durable depth is zero. The Web answerer receives only Agent-scoped requests; an agentless programmatic request remains available to unscoped local waterfall listeners and fails with `NO_PROVIDER` when none accepts it.
31
+ A question may carry a presentation `intent`, which declares that it IS a known kind of decision so a UI that recognises the tag may present it as such; the one tag is `plan-review`, whose `detail` is the plan under review and whose `approve` names the affirmative option. An intent changes presentation only: a UI honouring it answers with the same option labels a generic UI would send, and a UI that does not know the tag renders the generic option list. `ask()` rejects with `BAD_INTENT` the two assertions no type can carry: an `approve` naming none of that question's own options, and an intent on a question with no `detail`. `dsh-plan-mode` sets it on the `exit_plan_mode` review question.
42
32
 
43
- ### Presentation intent
33
+ When a request carries an agent, `ask()` authenticates its exact identity through the live `AgentRegistry` and admits only a runtime root. A live child cannot open a human interaction. An agentless programmatic request remains available to unscoped local waterfall listeners and fails with `NO_PROVIDER` when none accepts it.
44
34
 
45
- `intent` declares that a question IS a known kind of decision, so a UI that recognises the tag may present it as such — `plan-review` says `detail` is a plan under review, and `dsh-plan-mode` sets it on the `exit_plan_mode` question. An intent changes presentation only: a UI honouring it answers with the same option labels a generic UI would send, and a UI that does not know the tag renders the generic option list, so callers read the same answer fields either way. `approve` names the label that approves rather than relying on option order. `ask()` rejects with `BAD_INTENT` the two assertions no type can carry: an `approve` naming none of that question's own options, and an intent on a question with no `detail` — the thing it declares itself a review of.
35
+ While the tool call is open, the only answer path is that request; a browser that reconnects receives it again and can still complete it. Once the call has returned pending, or the process that owned it ended, the question is `continued`: the `answer` Remote method steers the reply into the agent as a `user-question-reply` message. No Remote method abandons a question — a Client that puts its panel away sends nothing, so the call stays answerable until an answer arrives. Answering a closed Session resumes its root agent first. Neither path fabricates a result for the finished tool call.
46
36
 
47
37
  <a id="role"></a>
48
38
  ## Role
49
39
 
50
- This is the Service Definition package. Consumers such as `@deepseek-ai/dsh-tool-ask-user` depend on this service; the Web client contributes an Agent-scoped answerer through Remote Events. The loop stays unchanged: a tool call awaits the waterfall result, and that result resumes the normal agent loop.
40
+ `UserQuestionService` owns each `TimedQuestionWait`, its cancellable Client claims, and its unattended timer. A claimed wait leaves countdown and focus/edit decisions to the Client. An unattended timeout aborts only the foreground request signal and returns pending, never aborting the Turn. The `userQuestions` projection records open, continued, and settled timed calls from existing Session events: native calls use the logged tool schema, while PTC sub-calls enter when their result is pending. The `answer` RPC validates one answer per question and accepts one queued reply per continued call; a second reply fails with `REPLY_QUEUED`. A discarded reply leaves the question answerable. A late batch stays in the projection because the original tool result contains the timeout, not that answer.
51
41
 
52
42
  <a id="model-experience"></a>
53
43
  ## Model Experience
@@ -64,6 +54,7 @@ No direct invalidation; the named consumer owns any request-prefix changes.
64
54
 
65
55
  - **Agent-scoped Web answering** — Remote Events route the shipped Web answerer only when the request carries a live Agent scope; agentless callers need an unscoped local waterfall listener.
66
56
  - **The vocabulary is the question-form shape only** — selectable options plus optional custom text; richer interaction shapes (file pickers, diff-preview confirmations) have no seam vocabulary yet.
57
+ - **Draft text is not part of Host question persistence** — the question survives restart across clients through the projection; unfinished input remains local to one browser profile.
67
58
 
68
59
 
69
60
  <a id="dev-note"></a>
@@ -74,8 +65,6 @@ No direct invalidation; the named consumer owns any request-prefix changes.
74
65
 
75
66
  None.
76
67
 
77
- The optional plan-review `callId` identifies the logged tool invocation for document navigation. It does not change the answer or its validation.
78
-
79
68
  </details>
80
69
 
81
- **Runtime invariant:** No companion is published. The answerer waterfall is resolved per request and returns directly to its caller; the seam publishes no independent request/answer audit stream.
70
+ **Runtime invariant:** the `userQuestions` projection is derived from recorded tool calls, PTC dispatches, and admitted user messages; no separate question state is stored. A continued question can create a new user turn, but it cannot resume a finished tool call. No runtime invariant companion is published because the projection fold and the continued-only Remote methods enforce this boundary at their owners.
package/README.zh.md CHANGED
@@ -9,11 +9,11 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- 用户交互 Service Definition。它定义 `ctx.userQuestions`,供面向模型的工具或权限插件在需要暂停工作并询问人类决定时使用。当消费方必须暂停操作并等待用户回答时,请使用它。
12
+ 当工具或权限流程需要用户提供结构化答案时,使用 `ctx.userQuestions`。`ask()` 会等待回答;`askTimed()` 可以放行 agent 继续独立工作,而问题仍留在会话中供用户回答。
13
13
 
14
14
  ## 目录
15
15
 
16
- - [服务:`UserQuestionService`(ctx 键:`userQuestions`)](#service-userquestionservice-ctx-key-userquestions)
16
+ - [提出问题](#service-userquestionservice-ctx-key-userquestions)
17
17
  - [职责](#role)
18
18
  - [模型体验](#model-experience)
19
19
  - [已知限制与暂缓事项](#known-limitations-and-deferred-work)
@@ -22,32 +22,22 @@ kind: "package-reference"
22
22
  -----
23
23
 
24
24
  <a id="service-userquestionservice-ctx-key-userquestions"></a>
25
- ## 服务:`UserQuestionService`(ctx 键:`userQuestions`)
25
+ ## 提出问题
26
26
 
27
- ### 公开 API
28
-
29
- - `ctx.userQuestions.ask(request): Promise<AskUserQuestionAnswer>` 派发回答者 waterfall,并等待首个被接受的回答。
30
-
31
- ### 关键类型
32
-
33
- - `AskUserQuestionRequest`:`{ questions: [{ id, question, detail?, header?, options?, multiSelect?, intent? }], agent?, signal? }`;`detail` 提供辅助文本,提供方会将其随问题一起渲染,而不会将其变成选项标签。如提供 `agent`,它必须与注册表中的存活运行时根 agent(智能体)是同一对象。
34
- - `AskUserQuestionOption`:`{ label, description? }`。
35
- - `AskUserQuestionIntent`:`{ kind: 'plan-review', approve }`;即下文的带标签呈现意图。
36
- - `AskUserQuestionAnswer`:`{ answers: [{ id, selected, custom? }] }`。
37
- - `UserQuestionError`:`HarnessError` 的子类,包含 `EMPTY_QUESTIONS`、`BAD_INTENT`、`NO_PROVIDER`、`ASK_ABORTED`、`CALLER_NOT_LIVE` 和 `DELEGATED_CALLER` 等代码。
27
+ 当工作无法在没有答案的情况下继续时调用 `ask()`。当 agent 可以在一段前台等待后继续独立工作时调用 `askTimed()`。回答 UI 通过 `attachWait` 接手等待,取得 Host 计算的剩余时长,并用本地时钟倒计时。没有接手方时,包括最后一个 Client 断开之后,服务在原 deadline 放行模型。`userQuestions` projection 从工具调用、其结果和最终回复派生持久问题;Client 接手状态不落盘。
38
28
 
39
29
  对于单选题,`custom` 会覆盖选中的选项,且 `selected` 为空。对于多选题,`custom` 可以补充 `selected` 中的标签。UI 可以把跳过的条目保留为 `{ id, selected: [] }`,既维持现有回答形态,也保留该批次中的其他回答。
40
30
 
41
- 请求包含 agent 时,`ask()` 会通过当前 `AgentRegistry` 验证该 agent 与注册表中的存活实例是同一对象,并且只允许运行时根调用。持久谱系不构成权限依据:带有历史委托深度的会话恢复为新的运行时根后可以提问;归属于另一个 agent 的存活子级即使持久化记录的委托深度为零也会被拒绝。Web 回答者只接收带 Agent scope 的请求;不含 agent 的程序化请求仍会交给本地未限定 scope 的 waterfall listener,若无人接受则以 `NO_PROVIDER` 失败。
31
+ 问题可以携带呈现意图 `intent`,声明它就是某种已知决策,识别该标记的 UI 可以按该决策呈现;目前唯一的标记是 `plan-review`,其 `detail` 是待审阅的计划,`approve` 指明表示同意的选项。意图只改变呈现:遵循它的 UI 回答的选项标签与通用 UI 相同,不认识该标记的 UI 则渲染通用选项列表。`ask()` 会以 `BAD_INTENT` 拒绝两种类型无法表达的断言:`approve` 未命名该问题自己的任何选项,以及没有 `detail` 的问题声明了意图。`dsh-plan-mode` 在 `exit_plan_mode` 的审阅问题上设置它。
42
32
 
43
- ### 呈现意图
33
+ 请求包含 agent 时,`ask()` 会通过当前 `AgentRegistry` 验证该 agent 与注册表中的存活实例是同一对象,并且只允许运行时根调用。存活子级不能发起人机交互。不含 agent 的程序化请求仍会交给本地未限定 scope 的 waterfall listener,若无人接受则以 `NO_PROVIDER` 失败。
44
34
 
45
- `intent` 声明某个问题本身就是一种已知决策,因此认识该标签的 UI 可以照此呈现——`plan-review` 表示 `detail` 是一份待审阅的计划,`dsh-plan-mode` 会在 `exit_plan_mode` 的问题上设置它。意图只改变呈现:遵循它的 UI 回答的仍是通用 UI 会发送的那些选项标签,不认识该标签的 UI 渲染通用选项列表,因此调用方两种情况下读到的回答字段相同。`approve` 指名表示批准的标签,而不依赖选项顺序。有两项断言无法通过类型表达,`ask()` 会以 `BAD_INTENT` 拒绝它们:`approve` 未命中该问题自身的任一选项,以及意图落在没有 `detail` 的问题上——而 `detail` 正是它自称在审阅的东西。
35
+ 工具调用开放期间,唯一的回答路径就是这条请求;重新连接的浏览器会再次收到它,仍可完成。调用返回 pending 之后,或拥有它的进程结束之后,问题进入 `continued`:`answer` Remote 方法把回复作为 `user-question-reply` 消息 steer 给 agent。没有任何 Remote 方法会放弃问题——Client 收起面板时不发送任何内容,因此该调用在收到回答前一直可回答。回答已关闭的会话时先恢复其根 agent。两条路径都不会为已结束的工具调用伪造结果。
46
36
 
47
37
  <a id="role"></a>
48
38
  ## 职责
49
39
 
50
- 这是 Service Definition 包。`@deepseek-ai/dsh-tool-ask-user` 等 Consumer 依赖此服务;Web Client 通过 Remote Events 贡献带 Agent scope 的回答者。循环保持不变:工具调用等待 waterfall 结果,该结果随后恢复正常的 agent loop(智能体循环)。
40
+ `UserQuestionService` 拥有每个 `TimedQuestionWait`、可取消的 Client 接手记录和无人接手计时器。有人接手时,倒计时与聚焦/编辑决策归 Client 所有。无人接手时超时只中止前台请求的 signal 并返回 pending,不中止 Turn。`userQuestions` projection 从现有 Session 事件记录开放、已继续和已结算的计时调用:原生调用按记录的工具 schema 识别,PTC 子调用在结果为 pending 时进入投影。`answer` RPC 验证每个问题恰有一条回答,且每个已继续的调用只接收一条排队中的回复;第二条回复以 `REPLY_QUEUED` 失败。回复被丢弃后,问题仍可回答。迟到批次保留在投影中,因为原工具结果包含的是超时而不是该回答。
51
41
 
52
42
  <a id="model-experience"></a>
53
43
  ## 模型体验
@@ -64,6 +54,7 @@ kind: "package-reference"
64
54
 
65
55
  - **带 Agent scope 的 Web 回答**:Remote Events 仅在请求带有存活 Agent scope 时路由随产品交付的 Web 回答者;agentless 调用方需要本地未限定 scope 的 waterfall listener。
66
56
  - **词汇仅包含问题表单形态**:可供选择的选项加可选的自定义文本;更丰富的交互形态(文件选择器、diff 预览确认)尚无 seam 词汇。
57
+ - **草稿文本不属于 Host 问题持久化状态**:问题通过 projection 跨客户端重启保留;未完成的输入仍只保存在一个浏览器配置中。
67
58
 
68
59
 
69
60
  <a id="dev-note"></a>
@@ -74,8 +65,6 @@ kind: "package-reference"
74
65
 
75
66
  无。
76
67
 
77
- 计划审批中可选的 `callId` 标识已记录的工具调用,供文档导航使用,不改变回答及其校验。
78
-
79
68
  </details>
80
69
 
81
- **运行时不变式:** 不发布伴生入口。answerer waterfall 按请求解析并把结果直接返回调用方;该 seam 不发布独立的请求/回答审计流。
70
+ **运行时不变式:** `userQuestions` projection 由已记录的工具调用、PTC 子调用和准入的用户消息推导,不存储单独的问题状态。已继续的问题可以创建新的用户轮次,但不能恢复已结束的工具调用。此包不发布运行时不变量 companion,因为 projection 折叠和只接受已继续问题的 Remote 方法已在各自归属处保证这一边界。