dominds 1.26.5 → 1.27.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/dist/docs/dialog-system.md +9 -6
- package/dist/docs/dialog-system.zh.md +10 -7
- package/dist/llm/gen/mock.js +10 -3
- package/dist/llm/gen.d.ts +4 -0
- package/dist/llm/kernel-driver/drive.js +164 -97
- package/dist/llm/kernel-driver/flow.js +53 -230
- package/dist/llm/kernel-driver/reminder-context.d.ts +0 -2
- package/dist/llm/kernel-driver/reminder-context.js +0 -4
- package/dist/llm/kernel-driver/reply-guidance.d.ts +1 -8
- package/dist/llm/kernel-driver/reply-guidance.js +8 -27
- package/dist/llm/kernel-driver/sideDialog.js +0 -4
- package/dist/llm/kernel-driver/tellask-special.d.ts +22 -2
- package/dist/llm/kernel-driver/tellask-special.js +122 -4
- package/dist/llm/kernel-driver/types.d.ts +3 -2
- package/dist/minds/system-prompt.js +10 -6
- package/dist/persistence.d.ts +2 -3
- package/dist/persistence.js +26 -76
- package/dist/runtime/driver-messages.d.ts +0 -2
- package/dist/runtime/driver-messages.js +2 -10
- package/dist/runtime/interjection-pause-stop.js +7 -8
- package/dist/runtime/reply-prompt-copy.d.ts +7 -9
- package/dist/runtime/reply-prompt-copy.js +48 -50
- package/dist/server/dominds-self-update.js +46 -4
- package/dist/server/websocket-handler.js +0 -2
- package/package.json +3 -3
- package/webapp/dist/assets/{_basePickBy-zyTFuJGa.js → _basePickBy-B5vClVxA.js} +3 -3
- package/webapp/dist/assets/{_basePickBy-zyTFuJGa.js.map → _basePickBy-B5vClVxA.js.map} +1 -1
- package/webapp/dist/assets/{_baseUniq-nq34n_7W.js → _baseUniq-CFvt8kJS.js} +2 -2
- package/webapp/dist/assets/{_baseUniq-nq34n_7W.js.map → _baseUniq-CFvt8kJS.js.map} +1 -1
- package/webapp/dist/assets/{arc-Bv7_22Od.js → arc-tJQBTeDz.js} +2 -2
- package/webapp/dist/assets/{arc-Bv7_22Od.js.map → arc-tJQBTeDz.js.map} +1 -1
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CQe-mbPP.js → architectureDiagram-2XIMDMQ5-DHh9S187.js} +7 -7
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CQe-mbPP.js.map → architectureDiagram-2XIMDMQ5-DHh9S187.js.map} +1 -1
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CX4Uu1s4.js → blockDiagram-WCTKOSBZ-BbiZ5Eja.js} +7 -7
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CX4Uu1s4.js.map → blockDiagram-WCTKOSBZ-BbiZ5Eja.js.map} +1 -1
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-75vPtXd7.js → c4Diagram-IC4MRINW-DzSSDB-G.js} +3 -3
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-75vPtXd7.js.map → c4Diagram-IC4MRINW-DzSSDB-G.js.map} +1 -1
- package/webapp/dist/assets/{channel-lMsMuju8.js → channel-XrOKEkK6.js} +2 -2
- package/webapp/dist/assets/{channel-lMsMuju8.js.map → channel-XrOKEkK6.js.map} +1 -1
- package/webapp/dist/assets/{chunk-4BX2VUAB-I371XlIM.js → chunk-4BX2VUAB-DEe7fLDb.js} +2 -2
- package/webapp/dist/assets/{chunk-4BX2VUAB-I371XlIM.js.map → chunk-4BX2VUAB-DEe7fLDb.js.map} +1 -1
- package/webapp/dist/assets/{chunk-55IACEB6-GMAfwcRQ.js → chunk-55IACEB6-DS9LKRkK.js} +2 -2
- package/webapp/dist/assets/{chunk-55IACEB6-GMAfwcRQ.js.map → chunk-55IACEB6-DS9LKRkK.js.map} +1 -1
- package/webapp/dist/assets/{chunk-FMBD7UC4-X9ms5_sJ.js → chunk-FMBD7UC4-zmHWjnBv.js} +2 -2
- package/webapp/dist/assets/{chunk-FMBD7UC4-X9ms5_sJ.js.map → chunk-FMBD7UC4-zmHWjnBv.js.map} +1 -1
- package/webapp/dist/assets/{chunk-JSJVCQXG-s2a971Od.js → chunk-JSJVCQXG-CHhshmdw.js} +2 -2
- package/webapp/dist/assets/{chunk-JSJVCQXG-s2a971Od.js.map → chunk-JSJVCQXG-CHhshmdw.js.map} +1 -1
- package/webapp/dist/assets/{chunk-KX2RTZJC-CSSBs5H9.js → chunk-KX2RTZJC-BrS-M9-j.js} +2 -2
- package/webapp/dist/assets/{chunk-KX2RTZJC-CSSBs5H9.js.map → chunk-KX2RTZJC-BrS-M9-j.js.map} +1 -1
- package/webapp/dist/assets/{chunk-NQ4KR5QH-B8-jtfW1.js → chunk-NQ4KR5QH-aQEIAgyi.js} +4 -4
- package/webapp/dist/assets/{chunk-NQ4KR5QH-B8-jtfW1.js.map → chunk-NQ4KR5QH-aQEIAgyi.js.map} +1 -1
- package/webapp/dist/assets/{chunk-QZHKN3VN-3ZZehtFv.js → chunk-QZHKN3VN-NZNwDEz0.js} +2 -2
- package/webapp/dist/assets/{chunk-QZHKN3VN-3ZZehtFv.js.map → chunk-QZHKN3VN-NZNwDEz0.js.map} +1 -1
- package/webapp/dist/assets/{chunk-WL4C6EOR-D_AtipPw.js → chunk-WL4C6EOR-BA4Gts3V.js} +6 -6
- package/webapp/dist/assets/{chunk-WL4C6EOR-D_AtipPw.js.map → chunk-WL4C6EOR-BA4Gts3V.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-CTxhuDjN.js → classDiagram-VBA2DB6C-BnW_okvO.js} +7 -7
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-CTxhuDjN.js.map → classDiagram-VBA2DB6C-BnW_okvO.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-CTxhuDjN.js → classDiagram-v2-RAHNMMFH-BnW_okvO.js} +7 -7
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-CTxhuDjN.js.map → classDiagram-v2-RAHNMMFH-BnW_okvO.js.map} +1 -1
- package/webapp/dist/assets/{clone-C9MfpI1S.js → clone-yPnqRTsi.js} +2 -2
- package/webapp/dist/assets/{clone-C9MfpI1S.js.map → clone-yPnqRTsi.js.map} +1 -1
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CCYyTSie.js → cose-bilkent-S5V4N54A-CIVtbB4S.js} +2 -2
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CCYyTSie.js.map → cose-bilkent-S5V4N54A-CIVtbB4S.js.map} +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-DxM19yfA.js → dagre-KLK3FWXG-ChT-W9Qx.js} +7 -7
- package/webapp/dist/assets/{dagre-KLK3FWXG-DxM19yfA.js.map → dagre-KLK3FWXG-ChT-W9Qx.js.map} +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-BSc4Txf5.js → diagram-E7M64L7V-BN8EY3l2.js} +8 -8
- package/webapp/dist/assets/{diagram-E7M64L7V-BSc4Txf5.js.map → diagram-E7M64L7V-BN8EY3l2.js.map} +1 -1
- package/webapp/dist/assets/{diagram-IFDJBPK2-Cdj6m54B.js → diagram-IFDJBPK2-Vf6QwbQQ.js} +7 -7
- package/webapp/dist/assets/{diagram-IFDJBPK2-Cdj6m54B.js.map → diagram-IFDJBPK2-Vf6QwbQQ.js.map} +1 -1
- package/webapp/dist/assets/{diagram-P4PSJMXO-BKd75i65.js → diagram-P4PSJMXO-CjMHY4Wx.js} +7 -7
- package/webapp/dist/assets/{diagram-P4PSJMXO-BKd75i65.js.map → diagram-P4PSJMXO-CjMHY4Wx.js.map} +1 -1
- package/webapp/dist/assets/{erDiagram-INFDFZHY-eI9rTfbL.js → erDiagram-INFDFZHY-CdziCsxU.js} +5 -5
- package/webapp/dist/assets/{erDiagram-INFDFZHY-eI9rTfbL.js.map → erDiagram-INFDFZHY-CdziCsxU.js.map} +1 -1
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-BFDDBCeb.js → flowDiagram-PKNHOUZH-BAe40rMw.js} +7 -7
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-BFDDBCeb.js.map → flowDiagram-PKNHOUZH-BAe40rMw.js.map} +1 -1
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-ClhbFgCt.js → ganttDiagram-A5KZAMGK-CXdjtDXe.js} +3 -3
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-ClhbFgCt.js.map → ganttDiagram-A5KZAMGK-CXdjtDXe.js.map} +1 -1
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-DOiQN8_s.js → gitGraphDiagram-K3NZZRJ6-U_Rn0HLE.js} +8 -8
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-DOiQN8_s.js.map → gitGraphDiagram-K3NZZRJ6-U_Rn0HLE.js.map} +1 -1
- package/webapp/dist/assets/{graph-_a0YpojF.js → graph-HwBjKopa.js} +3 -3
- package/webapp/dist/assets/{graph-_a0YpojF.js.map → graph-HwBjKopa.js.map} +1 -1
- package/webapp/dist/assets/{index-Dou-k_rC.js → index-BWHqGclz.js} +34 -34
- package/webapp/dist/assets/{index-Dou-k_rC.js.map → index-BWHqGclz.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-txkiQJKc.js → infoDiagram-LFFYTUFH-Do9srBC6.js} +6 -6
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-txkiQJKc.js.map → infoDiagram-LFFYTUFH-Do9srBC6.js.map} +1 -1
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-D91OZx5x.js → ishikawaDiagram-PHBUUO56-xCtj-FXJ.js} +2 -2
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-D91OZx5x.js.map → ishikawaDiagram-PHBUUO56-xCtj-FXJ.js.map} +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BdmmINf5.js → journeyDiagram-4ABVD52K-B0JWfLyo.js} +5 -5
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BdmmINf5.js.map → journeyDiagram-4ABVD52K-B0JWfLyo.js.map} +1 -1
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-C-S70Yrl.js → kanban-definition-K7BYSVSG-CVcU1Etk.js} +3 -3
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-C-S70Yrl.js.map → kanban-definition-K7BYSVSG-CVcU1Etk.js.map} +1 -1
- package/webapp/dist/assets/{layout-BRJaSqhR.js → layout-aH6Cn20A.js} +5 -5
- package/webapp/dist/assets/{layout-BRJaSqhR.js.map → layout-aH6Cn20A.js.map} +1 -1
- package/webapp/dist/assets/{linear-DyNGMbe9.js → linear-Ck43kzmo.js} +2 -2
- package/webapp/dist/assets/{linear-DyNGMbe9.js.map → linear-Ck43kzmo.js.map} +1 -1
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-sDQWtZwL.js → mindmap-definition-YRQLILUH-6OIwzMyc.js} +4 -4
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-sDQWtZwL.js.map → mindmap-definition-YRQLILUH-6OIwzMyc.js.map} +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-CxO-PR0P.js → pieDiagram-SKSYHLDU-B61-NHoC.js} +8 -8
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-CxO-PR0P.js.map → pieDiagram-SKSYHLDU-B61-NHoC.js.map} +1 -1
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-2eCl6G-9.js → quadrantDiagram-337W2JSQ-0eM2SOom.js} +3 -3
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-2eCl6G-9.js.map → quadrantDiagram-337W2JSQ-0eM2SOom.js.map} +1 -1
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-BZP0MViS.js → requirementDiagram-Z7DCOOCP-ChcYQDgM.js} +4 -4
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-BZP0MViS.js.map → requirementDiagram-Z7DCOOCP-ChcYQDgM.js.map} +1 -1
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-BFByQmrg.js → sankeyDiagram-WA2Y5GQK-B9cEGu9g.js} +2 -2
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-BFByQmrg.js.map → sankeyDiagram-WA2Y5GQK-B9cEGu9g.js.map} +1 -1
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-vs-caW9J.js → sequenceDiagram-2WXFIKYE-D1vR0q93.js} +4 -4
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-vs-caW9J.js.map → sequenceDiagram-2WXFIKYE-D1vR0q93.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-B_yOKRoN.js → stateDiagram-RAJIS63D-ylazdvD-.js} +9 -9
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-B_yOKRoN.js.map → stateDiagram-RAJIS63D-ylazdvD-.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-B285fcqL.js → stateDiagram-v2-FVOUBMTO-CxtecSrX.js} +5 -5
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-B285fcqL.js.map → stateDiagram-v2-FVOUBMTO-CxtecSrX.js.map} +1 -1
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-B_yCavMb.js → timeline-definition-YZTLITO2-4rofIQXx.js} +3 -3
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-B_yCavMb.js.map → timeline-definition-YZTLITO2-4rofIQXx.js.map} +1 -1
- package/webapp/dist/assets/{treemap-KZPCXAKY-cErPVx9g.js → treemap-KZPCXAKY-0SBcN6kq.js} +5 -5
- package/webapp/dist/assets/{treemap-KZPCXAKY-cErPVx9g.js.map → treemap-KZPCXAKY-0SBcN6kq.js.map} +1 -1
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-C9qgK3p0.js → vennDiagram-LZ73GAT5-CCqbQjX8.js} +2 -2
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-C9qgK3p0.js.map → vennDiagram-LZ73GAT5-CCqbQjX8.js.map} +1 -1
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-B-gCl1Yj.js → xychartDiagram-JWTSCODW-Yl52k-Si.js} +3 -3
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-B-gCl1Yj.js.map → xychartDiagram-JWTSCODW-Yl52k-Si.js.map} +1 -1
- package/webapp/dist/index.html +1 -1
|
@@ -159,34 +159,37 @@ This ensures crash recovery and enables the backend to resume from any persisted
|
|
|
159
159
|
|
|
160
160
|
When a dialog still carries an inter-dialog reply obligation, but the user temporarily interjects and asks it to handle a local question first, the system must distinguish between the **UI projection** and the **true driving source state**.
|
|
161
161
|
|
|
162
|
-
Plainly: the system should answer the user's interjection first. Once the user receives a visible answer, the backend records that answer as A2H (Answer to Human) in Human Attention so the user can find and acknowledge it even if the dialog immediately continues automatically.
|
|
162
|
+
Plainly: the system should answer the user's interjection first. Once the user receives a visible answer, the backend records that answer as A2H (Answer to Human) in Human Attention so the user can find and acknowledge it even if the dialog immediately continues automatically. In addition to recovering A2H from visible `saying`, the LLM may also produce structured `answering` output (or call the equivalent `answerHuman` tool entry) to create A2H directly.
|
|
163
163
|
|
|
164
164
|
**Normative semantics**:
|
|
165
165
|
|
|
166
166
|
1. Every user interjection message is driven as a complete normal round.
|
|
167
167
|
2. If that round needs tools, the system MUST finish the full tool round and any post-tool follow-up before treating the interjection as answered.
|
|
168
168
|
3. A visible assistant `saying` settles the pending user-interjection reply only when no same-round function/tellask call remains after that `saying`.
|
|
169
|
-
4.
|
|
170
|
-
5. If an inter-dialog reply obligation still exists after the interjection is answered,
|
|
171
|
-
6. A2H disappears when the user acknowledges it. This is intentionally "read then burn"; the
|
|
169
|
+
4. The model may also produce structured `answering` output (or call `answerHuman({ answerContent })`) to express "this is an answer for the human." That output is always appended to the dialog's `a2h.yaml`, but it is not the same thing as a Side Dialog's formal reply to its requester.
|
|
170
|
+
5. If an inter-dialog reply obligation still exists after the interjection is answered, it remains ordinary durable reply-obligation state. Subsequent continuation is driven by the normal business paths: queued prompts, reply reminders, diligence push, or explicit resume when the dialog is genuinely blocked.
|
|
171
|
+
6. A2H disappears when the user acknowledges it. This is intentionally "read then burn"; `answerRef` only links back to the course/genseq that produced the answer. When A2H comes from visible `saying`, the canonical text remains in the transcript; when it comes from structured `answering`, the A2H item itself carries that one-way output text.
|
|
172
172
|
7. The Human Attention panel shows Q4H and A2H together. Q4H waits for a human answer; A2H waits only for human acknowledgement.
|
|
173
173
|
|
|
174
174
|
**Strict boundary**: a formal `askHuman` answer is not part of this "user interjection" category. As soon as a prompt carries a real `q4hAnswerCallId`, it belongs to the askHuman reply channel and semantically continues an already-materialized question/answer chain; it must never be downgraded into temporary local side-chat.
|
|
175
175
|
|
|
176
|
+
**Modeling boundary**: Dominds does not structurally model "current human question context", does not maintain coordinates for "which human question this A2H answers", and does not store `userInterjection` coordinates in A2H. `a2h` / `answering` is only one-way structured modeling at the LLM output layer: the model produced text meant for the human, and the runtime put it into the human-acknowledgement queue. Questions, interjections, task obligations, and continuation duties remain represented by existing business facts such as prompts, Q4H, reply obligations, and queued prompts.
|
|
177
|
+
|
|
176
178
|
**Key point**: pending user-interjection reply and inter-dialog reply obligation are independent business facts. Reminder/footer copy can use those two facts directly: if the interjection is still pending, prioritize answering the user; if it is settled and the reply obligation remains active, continue toward the required inter-dialog closure.
|
|
177
179
|
|
|
178
180
|
**Mental-model warning**:
|
|
179
181
|
|
|
180
182
|
- Do not flatten every `origin === 'user'` prompt into "interjection"; a non-empty `q4hAnswerCallId` means askHuman answer continuation and follows a different semantic path.
|
|
181
183
|
- Do not treat A2H as Q4H. A2H does not block drive and does not route input to an agent.
|
|
184
|
+
- Do not treat A2H as a "human question context" database. A2H only carries answer text, acknowledgement state, and answer provenance.
|
|
182
185
|
- Do not store A2H in the Problems panel. It belongs to Human Attention and is removed by Ack.
|
|
183
186
|
|
|
184
187
|
You need all of the following together to understand the behavior correctly:
|
|
185
188
|
|
|
186
|
-
- reply-guidance suppression
|
|
189
|
+
- reply-guidance suppression for interjection turns
|
|
187
190
|
- pending user-interjection reply settlement after visible final `saying`
|
|
188
191
|
- A2H persistence and Ack flow
|
|
189
|
-
-
|
|
192
|
+
- ordinary continuation through active reply obligations, diligence push, and queued prompts after the user-visible answer
|
|
190
193
|
|
|
191
194
|
This is an intentionally cross-module semantic contract. Do not locally "simplify" one piece based only on its surface meaning.
|
|
192
195
|
|
|
@@ -158,34 +158,37 @@ askerDialog 可以在执行期间接收来自当前需向它回复的支线对
|
|
|
158
158
|
|
|
159
159
|
当某个对话仍带有跨对话回复义务,但用户临时插话要求它先处理本地问题时,系统必须区分**UI 投影**与**真实驱动源状态**。
|
|
160
160
|
|
|
161
|
-
直白地说:先把用户这次插话接住并答完。用户看到可见答复后,后端把这条答复记录成 A2H(Answer to Human
|
|
161
|
+
直白地说:先把用户这次插话接住并答完。用户看到可见答复后,后端把这条答复记录成 A2H(Answer to Human)放进“待人处理”,这样即使对话马上自动续推,用户也能找到并确认已阅。除了从可见 `saying` 恢复 A2H 之外,LLM 还可以产生结构化 `answering` 输出(或调用等价的 `answerHuman` 工具入口)直接形成 A2H。
|
|
162
162
|
|
|
163
163
|
**规范语义**:
|
|
164
164
|
|
|
165
165
|
1. 每条用户插话消息都按正常驱动轮完整执行。
|
|
166
166
|
2. 若该轮需要工具,则必须先完整跑完该工具轮及其 post-tool follow-up,之后才可认为插话已答完。
|
|
167
|
-
3. 只有当模型产生可见 `saying`,且该 `saying` 后同轮没有普通 function/tellask call
|
|
168
|
-
4.
|
|
169
|
-
5.
|
|
170
|
-
6. 用户 Ack 以后 A2H
|
|
167
|
+
3. 只有当模型产生可见 `saying`,且该 `saying` 后同轮没有普通 function/tellask call 继续挂起时,才用这条 `saying` 结算“待回复用户插话”。
|
|
168
|
+
4. 模型也可以产生结构化 `answering` 输出(或调用 `answerHuman({ answerContent })`)来表达“这是给人类看的答复”。该输出无条件追加到该对话的 `a2h.yaml`,但它不等价于支线对话对诉请者的正式回贴。
|
|
169
|
+
5. 如果插话答完后仍有跨对话回复义务,它保持为普通的 durable reply-obligation 状态;后续由正常业务路径推进:queued prompt、回贴提醒、鞭策续推,或在对话确实阻塞时由显式 resume 触发。
|
|
170
|
+
6. 用户 Ack 以后 A2H 立即消失,语义是“阅后即焚”;`answerRef` 只回链到产生答复的 course/genseq,用于定位来源生成轮。若 A2H 来自可见 `saying`,正文真源仍在 transcript 中;若来自结构化 `answering`,A2H 条目本身承载该单向输出正文。
|
|
171
171
|
7. “待人处理”面板同时显示 Q4H 与 A2H:Q4H 等人回答,A2H 只等人确认已阅。
|
|
172
172
|
|
|
173
173
|
**严格边界**:`askHuman` 的正式回答不属于这里的“用户插话”。只要一条 prompt 带着真实的 `q4hAnswerCallId`,它就属于 askHuman 回复通道,语义上是在继续已 materialize 的提问/应答链路,绝不能被压入“本地临时插话聊天”。
|
|
174
174
|
|
|
175
|
+
**建模边界**:Dominds 不对“当前人类问题上下文”做结构化业务建模,不维护“这个 A2H 回答的是哪一个人类问题”的坐标,也不把 `userInterjection` 坐标写进 A2H。`a2h` / `answering` 只是 LLM 输出层面的单向结构化建模:模型产生一段给人类看的答复,运行时把它放入待人确认队列。问题/插话/任务义务本身仍由既有 prompt、Q4H、reply obligation、queued prompt 等业务事实表达。
|
|
176
|
+
|
|
175
177
|
**关键点**:“是否还有用户插话待可见回复”和“是否还有跨对话回复义务”是两个独立业务事实。提醒项 footer 可以直接用这两个事实定制:插话尚未答复时优先答人;插话已答复且回复义务仍 active 时,继续按跨对话回贴要求收口。
|
|
176
178
|
|
|
177
179
|
**心智模型提醒**:
|
|
178
180
|
|
|
179
181
|
- 更不能把所有 `origin === 'user'` 的输入都笼统视作“用户插话”;`q4hAnswerCallId` 非空的 prompt 是 askHuman answer continuation,必须按另一条语义链处理。
|
|
180
182
|
- 不能把 A2H 当成 Q4H;A2H 不阻塞 drive,也不把输入路由给智能体。
|
|
183
|
+
- 不能把 A2H 当成“人类问题上下文”数据库;A2H 只有答复正文、确认状态与答复来源定位。
|
|
181
184
|
- 不能把 A2H 放进 Problems 面板;它属于“待人处理”,由 Ack 删除。
|
|
182
185
|
|
|
183
186
|
必须把以下几块一起看,才能形成完整且精确的理解:
|
|
184
187
|
|
|
185
|
-
- reply-guidance 中对插话轮的回复义务 suppression
|
|
188
|
+
- reply-guidance 中对插话轮的回复义务 suppression
|
|
186
189
|
- 可见最终 `saying` 后对 pending user-interjection reply 的结算
|
|
187
190
|
- A2H 持久化与 Ack 流程
|
|
188
|
-
-
|
|
191
|
+
- 用户可见答复后的 active reply obligation、鞭策续推、queued prompt 等普通续推路径
|
|
189
192
|
|
|
190
193
|
这是一条跨模块协同语义,不允许在单点上做“表面看起来更简单”的局部简化。
|
|
191
194
|
|
package/dist/llm/gen/mock.js
CHANGED
|
@@ -71,10 +71,10 @@ const RUNTIME_PROMPT_WRAPPER_PREFIXES = [
|
|
|
71
71
|
'【系统提示】 上下文状态:🔴 告急;收到用户插话',
|
|
72
72
|
reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_EN,
|
|
73
73
|
reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_ZH,
|
|
74
|
+
reply_prompt_copy_1.ANSWERING_REPLY_REMINDER_PREFIX_EN,
|
|
75
|
+
reply_prompt_copy_1.ANSWERING_REPLY_REMINDER_PREFIX_ZH,
|
|
74
76
|
reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_EN,
|
|
75
77
|
reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_ZH,
|
|
76
|
-
reply_prompt_copy_1.REPLY_REASSERTION_PREFIX_EN,
|
|
77
|
-
reply_prompt_copy_1.REPLY_REASSERTION_PREFIX_ZH,
|
|
78
78
|
reply_prompt_copy_1.REPLY_SUPPRESSION_PREFIX_EN,
|
|
79
79
|
reply_prompt_copy_1.REPLY_SUPPRESSION_PREFIX_ZH,
|
|
80
80
|
];
|
|
@@ -485,6 +485,9 @@ responses:
|
|
|
485
485
|
}
|
|
486
486
|
await receiver.sayingFinish();
|
|
487
487
|
}
|
|
488
|
+
if (matched?.answeringResponse !== undefined && matched.answeringResponse.trim() !== '') {
|
|
489
|
+
await receiver.answering?.(matched.answeringResponse);
|
|
490
|
+
}
|
|
488
491
|
const funcCalls = matched?.funcCalls ?? [];
|
|
489
492
|
for (let i = 0; i < funcCalls.length; i++) {
|
|
490
493
|
const call = funcCalls[i];
|
|
@@ -606,6 +609,9 @@ responses:
|
|
|
606
609
|
kind: 'invalid_func_call',
|
|
607
610
|
call,
|
|
608
611
|
}));
|
|
612
|
+
const answeringOutputs = matched?.answeringResponse !== undefined && matched.answeringResponse.trim() !== ''
|
|
613
|
+
? [{ kind: 'answering', content: matched.answeringResponse }]
|
|
614
|
+
: [];
|
|
609
615
|
const messages = thinking !== undefined
|
|
610
616
|
? saying
|
|
611
617
|
? [thinking, saying, ...funcMsgs]
|
|
@@ -615,10 +621,11 @@ responses:
|
|
|
615
621
|
: [...funcMsgs];
|
|
616
622
|
return {
|
|
617
623
|
messages,
|
|
618
|
-
...(invalidFuncCallOutputs.length > 0
|
|
624
|
+
...(invalidFuncCallOutputs.length > 0 || answeringOutputs.length > 0
|
|
619
625
|
? {
|
|
620
626
|
outputs: [
|
|
621
627
|
...messages.map((message) => ({ kind: 'message', message })),
|
|
628
|
+
...answeringOutputs,
|
|
622
629
|
...invalidFuncCallOutputs,
|
|
623
630
|
],
|
|
624
631
|
}
|
package/dist/llm/gen.d.ts
CHANGED
|
@@ -20,6 +20,9 @@ export declare class LlmStreamErrorEmittedError extends Error {
|
|
|
20
20
|
export type LlmBatchOutput = {
|
|
21
21
|
kind: 'message';
|
|
22
22
|
message: ChatMessage;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'answering';
|
|
25
|
+
content: string;
|
|
23
26
|
} | {
|
|
24
27
|
kind: 'invalid_func_call';
|
|
25
28
|
call: LlmInvalidFuncCall;
|
|
@@ -156,6 +159,7 @@ export interface LlmStreamReceiver {
|
|
|
156
159
|
sayingStart: () => Promise<void>;
|
|
157
160
|
sayingChunk: (chunk: string) => Promise<void>;
|
|
158
161
|
sayingFinish: () => Promise<void>;
|
|
162
|
+
answering?: (content: string) => Promise<void>;
|
|
159
163
|
funcCall: (callId: string, name: string, args: string, ids?: {
|
|
160
164
|
rawCallId?: string;
|
|
161
165
|
effectiveCallId?: string;
|
|
@@ -257,18 +257,14 @@ function isUserOriginPrompt(prompt) {
|
|
|
257
257
|
}
|
|
258
258
|
async function resolveReminderContextFooterState(args) {
|
|
259
259
|
const latest = await persistence_1.DialogPersistence.loadDialogLatest(args.dlg.id, args.dlg.status);
|
|
260
|
-
const deferredReplyReassertion = latest?.deferredReplyReassertion;
|
|
261
260
|
const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(args.dlg.id, args.dlg.status);
|
|
262
261
|
const pendingUserInterjectionReply = latest?.pendingUserInterjectionReply !== undefined;
|
|
263
|
-
const hasDeferredReplyReassertion = deferredReplyReassertion?.reason === 'user_interjection_with_parked_original_task';
|
|
264
262
|
const hasActiveReplyObligation = activeReplyObligation !== undefined;
|
|
265
263
|
// Business scenario: a user can reopen a completed Side Dialog to ask a follow-up. A recorded
|
|
266
|
-
// final response with no active
|
|
264
|
+
// final response with no active reply task means the old handoff has already been
|
|
267
265
|
// reported back; if a real user message is now present, the footer should say "talk with the
|
|
268
266
|
// user now" instead of making the model infer that from old transcript/reminder context.
|
|
269
|
-
const hasCompletedHandoffWithoutPendingReply = latest?.sideDialogFinalResponse !== undefined &&
|
|
270
|
-
!hasDeferredReplyReassertion &&
|
|
271
|
-
!hasActiveReplyObligation;
|
|
267
|
+
const hasCompletedHandoffWithoutPendingReply = latest?.sideDialogFinalResponse !== undefined && !hasActiveReplyObligation;
|
|
272
268
|
const dialogScope = args.dlg instanceof dialog_1.SideDialog ? { kind: 'side_dialog' } : { kind: 'main_dialog' };
|
|
273
269
|
return (0, reminder_context_1.resolveReminderContextFooterStateFromSignals)({
|
|
274
270
|
dialogScope,
|
|
@@ -277,7 +273,6 @@ async function resolveReminderContextFooterState(args) {
|
|
|
277
273
|
contextHealth: args.dlg.getLastContextHealth(),
|
|
278
274
|
pendingUserInterjectionReply,
|
|
279
275
|
hasCompletedHandoffWithoutPendingReply,
|
|
280
|
-
hasDeferredReplyReassertion,
|
|
281
276
|
hasActiveReplyObligation,
|
|
282
277
|
});
|
|
283
278
|
}
|
|
@@ -343,11 +338,6 @@ async function maybeResolveAnsweredUserInterjection(args) {
|
|
|
343
338
|
id: `a2h-${Buffer.from(answerIdSource).toString('base64url')}`,
|
|
344
339
|
content: args.assistantSayingContent,
|
|
345
340
|
answeredAt: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
346
|
-
userInterjection: {
|
|
347
|
-
msgId: pending.msgId,
|
|
348
|
-
course: pending.course,
|
|
349
|
-
genseq: pending.genseq,
|
|
350
|
-
},
|
|
351
341
|
answerRef: {
|
|
352
342
|
course,
|
|
353
343
|
genseq: args.assistantSayingGenseq,
|
|
@@ -706,6 +696,7 @@ const TELLASK_SPECIAL_VIRTUAL_TOOLS = [
|
|
|
706
696
|
{
|
|
707
697
|
type: 'func',
|
|
708
698
|
name: 'askHuman',
|
|
699
|
+
followupMode: 'deferred',
|
|
709
700
|
description: 'Ask for required clarification/decision from human.',
|
|
710
701
|
parameters: {
|
|
711
702
|
type: 'object',
|
|
@@ -719,6 +710,23 @@ const TELLASK_SPECIAL_VIRTUAL_TOOLS = [
|
|
|
719
710
|
throw new Error('askHuman is handled by kernel-driver tellask-special channel');
|
|
720
711
|
},
|
|
721
712
|
},
|
|
713
|
+
{
|
|
714
|
+
type: 'func',
|
|
715
|
+
name: 'answerHuman',
|
|
716
|
+
followupMode: 'deferred',
|
|
717
|
+
description: 'Record the current human-facing answer for human attention.',
|
|
718
|
+
parameters: {
|
|
719
|
+
type: 'object',
|
|
720
|
+
properties: {
|
|
721
|
+
answerContent: { type: 'string' },
|
|
722
|
+
},
|
|
723
|
+
required: ['answerContent'],
|
|
724
|
+
additionalProperties: false,
|
|
725
|
+
},
|
|
726
|
+
call: async () => {
|
|
727
|
+
throw new Error('answerHuman is handled by kernel-driver tellask-special channel');
|
|
728
|
+
},
|
|
729
|
+
},
|
|
722
730
|
];
|
|
723
731
|
const CONTEXT_HEALTH_TOOL_RESULT_VISIBLE_BYTE_LIMIT = 2000;
|
|
724
732
|
const CONTEXT_HEALTH_LARGE_TOOL_RETURN_UNAVAILABLE_ZH = '这次函数返回内容太大,清理头脑之前不会显示给你。';
|
|
@@ -991,20 +999,6 @@ async function renderRemindersForContext(dlg) {
|
|
|
991
999
|
...renderedItems,
|
|
992
1000
|
];
|
|
993
1001
|
}
|
|
994
|
-
function hasSameReplyDirective(left, right) {
|
|
995
|
-
if (!left || !right) {
|
|
996
|
-
return left === right;
|
|
997
|
-
}
|
|
998
|
-
if (left.expectedReplyCallName !== right.expectedReplyCallName) {
|
|
999
|
-
return false;
|
|
1000
|
-
}
|
|
1001
|
-
if (left.targetDialogId !== right.targetDialogId ||
|
|
1002
|
-
left.targetCallId !== right.targetCallId ||
|
|
1003
|
-
left.tellaskContent !== right.tellaskContent) {
|
|
1004
|
-
return false;
|
|
1005
|
-
}
|
|
1006
|
-
return true;
|
|
1007
|
-
}
|
|
1008
1002
|
function buildPendingTellaskFuncResult(args) {
|
|
1009
1003
|
return {
|
|
1010
1004
|
type: 'func_result_msg',
|
|
@@ -1321,6 +1315,25 @@ async function emitAssistantSaying(dlg, content) {
|
|
|
1321
1315
|
await dlg.sayingChunk(content);
|
|
1322
1316
|
await dlg.sayingFinish();
|
|
1323
1317
|
}
|
|
1318
|
+
async function recordStructuredAnswering(args) {
|
|
1319
|
+
if (args.content.trim() === '')
|
|
1320
|
+
return undefined;
|
|
1321
|
+
const course = args.dlg.activeGenCourseOrUndefined ?? args.dlg.currentCourse;
|
|
1322
|
+
const genseq = args.dlg.activeGenSeqOrUndefined ?? 1;
|
|
1323
|
+
return await (0, tellask_special_1.recordAnswerToHuman)({
|
|
1324
|
+
dlg: args.dlg,
|
|
1325
|
+
answerContent: args.content,
|
|
1326
|
+
course,
|
|
1327
|
+
genseq,
|
|
1328
|
+
answerIdSource: [
|
|
1329
|
+
args.dlg.id.rootId,
|
|
1330
|
+
args.dlg.id.selfId,
|
|
1331
|
+
`c${String(course)}`,
|
|
1332
|
+
`g${String(genseq)}`,
|
|
1333
|
+
args.source,
|
|
1334
|
+
].join('|'),
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1324
1337
|
function formatInvalidFuncCallRuntimeGuide(language, call) {
|
|
1325
1338
|
const rawName = call.rawFunctionName !== undefined && call.rawFunctionName.trim() !== ''
|
|
1326
1339
|
? call.rawFunctionName.trim()
|
|
@@ -2051,6 +2064,7 @@ async function executeFunctionRound(args) {
|
|
|
2051
2064
|
shouldStopAfterPendingTellaskWait: false,
|
|
2052
2065
|
pairedMessages: [],
|
|
2053
2066
|
tellaskToolOutputs: [],
|
|
2067
|
+
answerHumanOutputs: [],
|
|
2054
2068
|
};
|
|
2055
2069
|
}
|
|
2056
2070
|
throwIfAborted(args.abortSignal, args.dlg);
|
|
@@ -2064,6 +2078,7 @@ async function executeFunctionRound(args) {
|
|
|
2064
2078
|
'replyTellaskSessionless',
|
|
2065
2079
|
'replyTellaskBack',
|
|
2066
2080
|
'askHuman',
|
|
2081
|
+
'answerHuman',
|
|
2067
2082
|
'freshBootsReasoning',
|
|
2068
2083
|
...(allowTellaskBack ? ['tellaskBack'] : []),
|
|
2069
2084
|
])
|
|
@@ -2167,6 +2182,7 @@ async function executeFunctionRound(args) {
|
|
|
2167
2182
|
shouldStopAfterPendingTellaskWait: tellaskRound.shouldStopAfterPendingTellaskWait,
|
|
2168
2183
|
pairedMessages,
|
|
2169
2184
|
tellaskToolOutputs: [...tellaskRound.toolOutputs],
|
|
2185
|
+
answerHumanOutputs: tellaskRound.answerHumanOutputs,
|
|
2170
2186
|
};
|
|
2171
2187
|
}
|
|
2172
2188
|
async function preserveDiligenceBudgetAcrossQ4H(dlg) {
|
|
@@ -2362,10 +2378,11 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
2362
2378
|
let lastAssistantSayingGenseq = null;
|
|
2363
2379
|
let lastAssistantThinkingContent = null;
|
|
2364
2380
|
let lastAssistantThinkingGenseq = null;
|
|
2381
|
+
let lastAssistantAnsweringContent = null;
|
|
2382
|
+
let lastAssistantAnsweringGenseq = null;
|
|
2365
2383
|
let lastFunctionCallGenseq = null;
|
|
2366
2384
|
let lastAssistantReplyTarget;
|
|
2367
2385
|
let lastBusinessContinuation = { kind: 'none' };
|
|
2368
|
-
let answeredUserInterjection;
|
|
2369
2386
|
let currentPromptIsUserInterjection = false;
|
|
2370
2387
|
let currentUserInterjectionReply;
|
|
2371
2388
|
let fbrConclusion;
|
|
@@ -2639,62 +2656,23 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
2639
2656
|
prompt: currentPrompt,
|
|
2640
2657
|
language: promptLanguage,
|
|
2641
2658
|
});
|
|
2642
|
-
const deferredReplyReassertionDirective = replyGuidance.deferredReplyReassertionDirective;
|
|
2643
2659
|
currentPromptIsUserInterjection =
|
|
2644
2660
|
currentPrompt.origin === 'user' &&
|
|
2645
2661
|
replyGuidance.suppressInterDialogReplyGuidance &&
|
|
2646
|
-
|
|
2662
|
+
!replyGuidance.isQ4HAnswerPrompt;
|
|
2647
2663
|
if (currentPromptIsUserInterjection) {
|
|
2648
|
-
// WARNING:
|
|
2649
|
-
// User interjection suppression is a reversible state transition, not a one-shot
|
|
2650
|
-
// latch. The normal cycle is:
|
|
2651
|
-
// - user interjects -> suppress reply obligation
|
|
2652
|
-
// - the visible local answer auto-reasserts the reply obligation
|
|
2653
|
-
// - user interjects again -> suppress it again
|
|
2654
|
-
//
|
|
2655
|
-
// Legacy blocked-Continue paths may also re-enter here. A repeated interjection MUST
|
|
2656
|
-
// re-arm the deferred state and re-materialize the suppression guide, even when the
|
|
2657
|
-
// underlying reply directive itself did not change.
|
|
2658
|
-
const deferredDirective = deferredReplyReassertionDirective;
|
|
2659
|
-
if (deferredDirective === undefined) {
|
|
2660
|
-
throw new Error(`kernel-driver user interjection invariant violation: missing deferred reply directive for dialog=${dlg.id.valueOf()} msgId=${currentPrompt.msgId}`);
|
|
2661
|
-
}
|
|
2662
|
-
const existingDeferredReplyReassertion = await persistence_1.DialogPersistence.getDeferredReplyReassertion(dlg.id, dlg.status);
|
|
2663
2664
|
currentUserInterjectionReply = {
|
|
2664
2665
|
msgId: currentPrompt.msgId,
|
|
2665
2666
|
course: (0, storage_1.toDialogCourseNumber)(dlg.activeGenCourseOrUndefined ?? dlg.currentCourse),
|
|
2666
2667
|
genseq: (0, storage_1.toCallSiteGenseqNo)(dlg.activeGenSeq),
|
|
2667
2668
|
};
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
existingDeferredReplyReassertion.userInterjection.msgId !==
|
|
2676
|
-
nextDeferredReplyReassertion.userInterjection.msgId ||
|
|
2677
|
-
existingDeferredReplyReassertion.userInterjection.course !==
|
|
2678
|
-
nextDeferredReplyReassertion.userInterjection.course ||
|
|
2679
|
-
existingDeferredReplyReassertion.userInterjection.genseq !==
|
|
2680
|
-
nextDeferredReplyReassertion.userInterjection.genseq ||
|
|
2681
|
-
!hasSameReplyDirective(existingDeferredReplyReassertion.directive, nextDeferredReplyReassertion.directive);
|
|
2682
|
-
if (mustRearmDeferredReplyReassertion) {
|
|
2683
|
-
await persistence_1.DialogPersistence.setDeferredReplyReassertion(dlg.id, nextDeferredReplyReassertion, dlg.status);
|
|
2684
|
-
}
|
|
2685
|
-
if (mustRearmDeferredReplyReassertion) {
|
|
2686
|
-
currentRuntimeGuideMsg = replyGuidance.transientGuideContent
|
|
2687
|
-
? {
|
|
2688
|
-
type: 'transient_guide_msg',
|
|
2689
|
-
role: 'assistant',
|
|
2690
|
-
content: replyGuidance.transientGuideContent,
|
|
2691
|
-
}
|
|
2692
|
-
: undefined;
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
else if (currentPrompt.origin === 'user' &&
|
|
2696
|
-
!replyGuidance.suppressInterDialogReplyGuidance) {
|
|
2697
|
-
await persistence_1.DialogPersistence.setDeferredReplyReassertion(dlg.id, undefined, dlg.status);
|
|
2669
|
+
currentRuntimeGuideMsg = replyGuidance.transientGuideContent
|
|
2670
|
+
? {
|
|
2671
|
+
type: 'transient_guide_msg',
|
|
2672
|
+
role: 'assistant',
|
|
2673
|
+
content: replyGuidance.transientGuideContent,
|
|
2674
|
+
}
|
|
2675
|
+
: undefined;
|
|
2698
2676
|
}
|
|
2699
2677
|
if (!replyGuidance.suppressInterDialogReplyGuidance &&
|
|
2700
2678
|
!currentRuntimeGuideMsg &&
|
|
@@ -2984,6 +2962,8 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
2984
2962
|
let streamAttemptSayingGenseq;
|
|
2985
2963
|
let streamAttemptThinkingContent;
|
|
2986
2964
|
let streamAttemptThinkingGenseq;
|
|
2965
|
+
let streamAttemptAnsweringContent;
|
|
2966
|
+
let streamAttemptAnsweringGenseq;
|
|
2987
2967
|
let streamActive = { kind: 'idle' };
|
|
2988
2968
|
const rollbackStreamAttempt = async () => {
|
|
2989
2969
|
if (streamAttemptCourse === undefined ||
|
|
@@ -3005,6 +2985,8 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3005
2985
|
streamAttemptSayingGenseq = undefined;
|
|
3006
2986
|
streamAttemptThinkingContent = undefined;
|
|
3007
2987
|
streamAttemptThinkingGenseq = undefined;
|
|
2988
|
+
streamAttemptAnsweringContent = undefined;
|
|
2989
|
+
streamAttemptAnsweringGenseq = undefined;
|
|
3008
2990
|
sawWebSearchSideChannelOutput = false;
|
|
3009
2991
|
sawNativeToolSideChannelOutput = false;
|
|
3010
2992
|
streamedFuncCalls.length = 0;
|
|
@@ -3117,6 +3099,35 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3117
3099
|
streamAttemptSayingContent = currentSayingContent;
|
|
3118
3100
|
streamAttemptSayingGenseq = sayingMessage.genseq;
|
|
3119
3101
|
},
|
|
3102
|
+
answering: async (content) => {
|
|
3103
|
+
throwIfAborted(abortSignal, dlg);
|
|
3104
|
+
if (streamActive.kind !== 'idle') {
|
|
3105
|
+
const detail = `Protocol violation: answering while ${streamActive.kind} is active`;
|
|
3106
|
+
await dlg.streamError(detail);
|
|
3107
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
3108
|
+
detail,
|
|
3109
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
3110
|
+
detail,
|
|
3111
|
+
kind: 'conflicting_stream',
|
|
3112
|
+
}),
|
|
3113
|
+
});
|
|
3114
|
+
}
|
|
3115
|
+
if (content.trim() !== '') {
|
|
3116
|
+
if (streamAttemptAnsweringContent !== undefined) {
|
|
3117
|
+
const detail = 'Protocol violation: multiple answering outputs in one generation';
|
|
3118
|
+
await dlg.streamError(detail);
|
|
3119
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
3120
|
+
detail,
|
|
3121
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
3122
|
+
detail,
|
|
3123
|
+
kind: 'conflicting_stream',
|
|
3124
|
+
}),
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
3127
|
+
streamAttemptAnsweringContent = content;
|
|
3128
|
+
streamAttemptAnsweringGenseq = dlg.activeGenSeq;
|
|
3129
|
+
}
|
|
3130
|
+
},
|
|
3120
3131
|
funcCall: async (callId, name, argsStr, ids) => {
|
|
3121
3132
|
throwIfAborted(abortSignal, dlg);
|
|
3122
3133
|
const rawCallId = trimOptionalCallId(ids?.rawCallId) ?? callId;
|
|
@@ -3190,6 +3201,8 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3190
3201
|
streamAttemptSayingGenseq = undefined;
|
|
3191
3202
|
streamAttemptThinkingContent = undefined;
|
|
3192
3203
|
streamAttemptThinkingGenseq = undefined;
|
|
3204
|
+
streamAttemptAnsweringContent = undefined;
|
|
3205
|
+
streamAttemptAnsweringGenseq = undefined;
|
|
3193
3206
|
sawWebSearchSideChannelOutput = false;
|
|
3194
3207
|
sawNativeToolSideChannelOutput = false;
|
|
3195
3208
|
streamedFuncCalls.length = 0;
|
|
@@ -3208,6 +3221,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3208
3221
|
msg.content.trim() !== '');
|
|
3209
3222
|
const hasFunctionCall = streamedFuncCalls.length > 0;
|
|
3210
3223
|
if (!hasFinishedMessageContent &&
|
|
3224
|
+
streamAttemptAnsweringContent === undefined &&
|
|
3211
3225
|
!hasFunctionCall &&
|
|
3212
3226
|
invalidFuncCallCount === 0 &&
|
|
3213
3227
|
!sawWebSearchSideChannelOutput &&
|
|
@@ -3235,6 +3249,20 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3235
3249
|
lastAssistantReplyTarget = currentReplyTarget;
|
|
3236
3250
|
}
|
|
3237
3251
|
}
|
|
3252
|
+
if (streamAttemptAnsweringContent !== undefined) {
|
|
3253
|
+
const answer = await recordStructuredAnswering({
|
|
3254
|
+
dlg,
|
|
3255
|
+
content: streamAttemptAnsweringContent,
|
|
3256
|
+
source: 'structured-answering',
|
|
3257
|
+
});
|
|
3258
|
+
if (answer !== undefined) {
|
|
3259
|
+
lastAssistantAnsweringContent = answer.content;
|
|
3260
|
+
lastAssistantAnsweringGenseq =
|
|
3261
|
+
streamAttemptAnsweringGenseq === undefined
|
|
3262
|
+
? answer.answerRef.genseq
|
|
3263
|
+
: streamAttemptAnsweringGenseq;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3238
3266
|
return { usage: res.usage, llmGenModel: res.llmGenModel };
|
|
3239
3267
|
};
|
|
3240
3268
|
const previousAssistantSayingGenseq = lastAssistantSayingGenseq;
|
|
@@ -3256,6 +3284,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3256
3284
|
: Array.isArray(llmOutput.batchMessages)
|
|
3257
3285
|
? llmOutput.batchMessages.map((message) => ({ kind: 'message', message }))
|
|
3258
3286
|
: [];
|
|
3287
|
+
let batchAnsweringSeen = false;
|
|
3259
3288
|
for (const output of batchOutputs) {
|
|
3260
3289
|
switch (output.kind) {
|
|
3261
3290
|
case 'message': {
|
|
@@ -3283,6 +3312,33 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3283
3312
|
}
|
|
3284
3313
|
break;
|
|
3285
3314
|
}
|
|
3315
|
+
case 'answering': {
|
|
3316
|
+
if (output.content.trim() === '') {
|
|
3317
|
+
break;
|
|
3318
|
+
}
|
|
3319
|
+
if (batchAnsweringSeen) {
|
|
3320
|
+
const detail = 'Protocol violation: multiple answering outputs in one generation';
|
|
3321
|
+
await dlg.streamError(detail);
|
|
3322
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
3323
|
+
detail,
|
|
3324
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
3325
|
+
detail,
|
|
3326
|
+
kind: 'conflicting_stream',
|
|
3327
|
+
}),
|
|
3328
|
+
});
|
|
3329
|
+
}
|
|
3330
|
+
batchAnsweringSeen = true;
|
|
3331
|
+
const answer = await recordStructuredAnswering({
|
|
3332
|
+
dlg,
|
|
3333
|
+
content: output.content,
|
|
3334
|
+
source: 'structured-answering',
|
|
3335
|
+
});
|
|
3336
|
+
if (answer !== undefined) {
|
|
3337
|
+
lastAssistantAnsweringContent = answer.content;
|
|
3338
|
+
lastAssistantAnsweringGenseq = answer.answerRef.genseq;
|
|
3339
|
+
}
|
|
3340
|
+
break;
|
|
3341
|
+
}
|
|
3286
3342
|
case 'invalid_func_call': {
|
|
3287
3343
|
invalidFuncCallCount += 1;
|
|
3288
3344
|
await persistInvalidFuncCallRuntimeGuide({
|
|
@@ -3323,6 +3379,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3323
3379
|
c.name === 'tellaskSessionless' ||
|
|
3324
3380
|
c.name === 'tellaskBack' ||
|
|
3325
3381
|
c.name === 'askHuman' ||
|
|
3382
|
+
c.name === 'answerHuman' ||
|
|
3326
3383
|
c.name === 'freshBootsReasoning').length
|
|
3327
3384
|
: 0;
|
|
3328
3385
|
const policyViolationKind = (0, guardrails_1.resolveKernelDriverPolicyViolationKind)({
|
|
@@ -3354,6 +3411,8 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3354
3411
|
lastAssistantSayingGenseq,
|
|
3355
3412
|
lastAssistantThinkingContent,
|
|
3356
3413
|
lastAssistantThinkingGenseq,
|
|
3414
|
+
lastAssistantAnsweringContent,
|
|
3415
|
+
lastAssistantAnsweringGenseq,
|
|
3357
3416
|
lastFunctionCallGenseq,
|
|
3358
3417
|
lastAssistantReplyTarget,
|
|
3359
3418
|
lastBusinessContinuation,
|
|
@@ -3396,9 +3455,11 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3396
3455
|
if (!Number.isFinite(rawCallGenseq) || rawCallGenseq <= 0)
|
|
3397
3456
|
continue;
|
|
3398
3457
|
const callGenseq = Math.floor(rawCallGenseq);
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
lastFunctionCallGenseq
|
|
3458
|
+
if (call.name !== 'answerHuman') {
|
|
3459
|
+
currentRoundFunctionCallGenseqs.push(callGenseq);
|
|
3460
|
+
if (lastFunctionCallGenseq === null || callGenseq > lastFunctionCallGenseq) {
|
|
3461
|
+
lastFunctionCallGenseq = callGenseq;
|
|
3462
|
+
}
|
|
3402
3463
|
}
|
|
3403
3464
|
}
|
|
3404
3465
|
const userInterjectionMsgIdForVisibleAnswer = currentPrompt?.origin === 'user' && !isQ4HAnswerPrompt
|
|
@@ -3406,7 +3467,29 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3406
3467
|
: currentGenerationBelongsToUserToolChain
|
|
3407
3468
|
? currentUserPromptMsgId
|
|
3408
3469
|
: undefined;
|
|
3409
|
-
|
|
3470
|
+
const routed = await executeFunctionRound({
|
|
3471
|
+
dlg,
|
|
3472
|
+
agent,
|
|
3473
|
+
agentTools,
|
|
3474
|
+
funcCalls: streamedFuncCalls,
|
|
3475
|
+
callbacks,
|
|
3476
|
+
abortSignal,
|
|
3477
|
+
allowTellaskFunctions: policy.allowTellaskFunctions,
|
|
3478
|
+
activePromptReplyDirective: currentPrompt?.tellaskReplyDirective,
|
|
3479
|
+
contextHealthForToolResultVisibility: pickContextHealthForLargeToolResultVisibility({
|
|
3480
|
+
previous: contextHealthBeforeGen,
|
|
3481
|
+
current: contextHealthForGen,
|
|
3482
|
+
}),
|
|
3483
|
+
});
|
|
3484
|
+
for (const answering of routed.answerHumanOutputs) {
|
|
3485
|
+
lastAssistantAnsweringContent = answering.answerContent;
|
|
3486
|
+
lastAssistantAnsweringGenseq = answering.genseq;
|
|
3487
|
+
}
|
|
3488
|
+
const currentRoundAnsweringGenseq = dlg.activeGenSeqOrUndefined;
|
|
3489
|
+
const hasCurrentRoundAnsweringOutput = currentRoundAnsweringGenseq !== undefined &&
|
|
3490
|
+
lastAssistantAnsweringGenseq === currentRoundAnsweringGenseq;
|
|
3491
|
+
if (userInterjectionMsgIdForVisibleAnswer !== undefined &&
|
|
3492
|
+
!hasCurrentRoundAnsweringOutput) {
|
|
3410
3493
|
const streamedCurrentRoundSayingContent = batchOutputs.length === 0 &&
|
|
3411
3494
|
lastAssistantSayingGenseq !== previousAssistantSayingGenseq
|
|
3412
3495
|
? lastAssistantSayingContent
|
|
@@ -3415,31 +3498,14 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3415
3498
|
lastAssistantSayingGenseq !== previousAssistantSayingGenseq
|
|
3416
3499
|
? lastAssistantSayingGenseq
|
|
3417
3500
|
: null;
|
|
3418
|
-
|
|
3501
|
+
await maybeResolveAnsweredUserInterjection({
|
|
3419
3502
|
dlg,
|
|
3420
3503
|
userPromptMsgId: userInterjectionMsgIdForVisibleAnswer,
|
|
3421
3504
|
assistantSayingContent: currentRoundAssistantSayingContent ?? streamedCurrentRoundSayingContent,
|
|
3422
3505
|
assistantSayingGenseq: currentRoundAssistantSayingGenseq ?? streamedCurrentRoundSayingGenseq,
|
|
3423
3506
|
functionCallGenseqs: currentRoundFunctionCallGenseqs,
|
|
3424
3507
|
});
|
|
3425
|
-
if (answer !== undefined) {
|
|
3426
|
-
answeredUserInterjection = answer;
|
|
3427
|
-
}
|
|
3428
3508
|
}
|
|
3429
|
-
const routed = await executeFunctionRound({
|
|
3430
|
-
dlg,
|
|
3431
|
-
agent,
|
|
3432
|
-
agentTools,
|
|
3433
|
-
funcCalls: streamedFuncCalls,
|
|
3434
|
-
callbacks,
|
|
3435
|
-
abortSignal,
|
|
3436
|
-
allowTellaskFunctions: policy.allowTellaskFunctions,
|
|
3437
|
-
activePromptReplyDirective: currentPrompt?.tellaskReplyDirective,
|
|
3438
|
-
contextHealthForToolResultVisibility: pickContextHealthForLargeToolResultVisibility({
|
|
3439
|
-
previous: contextHealthBeforeGen,
|
|
3440
|
-
current: contextHealthForGen,
|
|
3441
|
-
}),
|
|
3442
|
-
});
|
|
3443
3509
|
if (routed.tellaskToolOutputs.length > 0) {
|
|
3444
3510
|
newMsgs.push(...routed.tellaskToolOutputs);
|
|
3445
3511
|
}
|
|
@@ -3869,10 +3935,11 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
3869
3935
|
lastAssistantSayingGenseq,
|
|
3870
3936
|
lastAssistantThinkingContent,
|
|
3871
3937
|
lastAssistantThinkingGenseq,
|
|
3938
|
+
lastAssistantAnsweringContent,
|
|
3939
|
+
lastAssistantAnsweringGenseq,
|
|
3872
3940
|
lastFunctionCallGenseq,
|
|
3873
3941
|
lastAssistantReplyTarget,
|
|
3874
3942
|
lastBusinessContinuation,
|
|
3875
|
-
answeredUserInterjection,
|
|
3876
3943
|
fbrConclusion,
|
|
3877
3944
|
};
|
|
3878
3945
|
}
|