dominds 1.16.7 → 1.16.10
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.md +1 -1
- package/README.zh.md +1 -1
- package/dist/dialog-display-state.js +35 -3
- package/dist/docs/app-constitution.md +2 -2
- package/dist/docs/app-constitution.zh.md +2 -2
- package/dist/docs/dialog-system.md +49 -0
- package/dist/docs/dialog-system.zh.md +49 -0
- package/dist/docs/team_mgmt-toolset.md +1 -1
- package/dist/docs/team_mgmt-toolset.zh.md +1 -1
- package/dist/llm/gen/codex.d.ts +1 -9
- package/dist/llm/gen/codex.js +3 -29
- package/dist/llm/kernel-driver/drive.js +22 -81
- package/dist/llm/kernel-driver/flow.js +232 -51
- package/dist/llm/kernel-driver/reply-guidance.d.ts +1 -0
- package/dist/llm/kernel-driver/reply-guidance.js +39 -5
- package/dist/llm/kernel-driver/tellask-special.js +3 -5
- package/dist/llm/stop-reason-i18n.d.ts +1 -1
- package/dist/llm/stop-reason-i18n.js +0 -4
- package/dist/persistence.js +14 -4
- package/dist/runtime/interjection-pause-stop.d.ts +5 -0
- package/dist/runtime/interjection-pause-stop.js +39 -0
- package/dist/runtime/reply-prompt-copy.js +2 -2
- package/dist/server/websocket-handler.js +14 -0
- package/dist/tools/apply-patch.js +5 -5
- package/dist/tools/builtins.js +11 -12
- package/dist/tools/prompts/codex_inspect_and_patch_tools/en/errors.md +45 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/en/index.md +37 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/en/principles.md +41 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/en/scenarios.md +40 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/en/tools.md +47 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/errors.md +45 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/index.md +37 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/principles.md +41 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/scenarios.md +40 -0
- package/dist/tools/prompts/codex_inspect_and_patch_tools/zh/tools.md +47 -0
- package/dist/tools/team_mgmt.js +13 -21
- package/package.json +4 -4
- package/webapp/dist/assets/{_basePickBy-B7FV6Gnn.js → _basePickBy-BKgfg72Q.js} +3 -3
- package/webapp/dist/assets/{_basePickBy-B7FV6Gnn.js.map → _basePickBy-BKgfg72Q.js.map} +1 -1
- package/webapp/dist/assets/{_baseUniq-CmVnLJpw.js → _baseUniq-DKhs7H5s.js} +2 -2
- package/webapp/dist/assets/{_baseUniq-CmVnLJpw.js.map → _baseUniq-DKhs7H5s.js.map} +1 -1
- package/webapp/dist/assets/{arc-DSJlh9AU.js → arc-Tykg3Fx4.js} +2 -2
- package/webapp/dist/assets/{arc-DSJlh9AU.js.map → arc-Tykg3Fx4.js.map} +1 -1
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-Cd2cTHzo.js → architectureDiagram-2XIMDMQ5-BAyn6_in.js} +7 -7
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-Cd2cTHzo.js.map → architectureDiagram-2XIMDMQ5-BAyn6_in.js.map} +1 -1
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-C0uEp_Tz.js → blockDiagram-WCTKOSBZ-CGbo6x6_.js} +7 -7
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-C0uEp_Tz.js.map → blockDiagram-WCTKOSBZ-CGbo6x6_.js.map} +1 -1
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-B37U92JK.js → c4Diagram-IC4MRINW-CUizxwo0.js} +3 -3
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-B37U92JK.js.map → c4Diagram-IC4MRINW-CUizxwo0.js.map} +1 -1
- package/webapp/dist/assets/{channel-DLHnjnQf.js → channel-DvP7WrjO.js} +2 -2
- package/webapp/dist/assets/{channel-DLHnjnQf.js.map → channel-DvP7WrjO.js.map} +1 -1
- package/webapp/dist/assets/{chunk-4BX2VUAB-DnZvfQyp.js → chunk-4BX2VUAB-cgnNaqgV.js} +2 -2
- package/webapp/dist/assets/{chunk-4BX2VUAB-DnZvfQyp.js.map → chunk-4BX2VUAB-cgnNaqgV.js.map} +1 -1
- package/webapp/dist/assets/{chunk-55IACEB6-BG-cjz3M.js → chunk-55IACEB6-BEUsguTg.js} +2 -2
- package/webapp/dist/assets/{chunk-55IACEB6-BG-cjz3M.js.map → chunk-55IACEB6-BEUsguTg.js.map} +1 -1
- package/webapp/dist/assets/{chunk-FMBD7UC4-B1L8cPfl.js → chunk-FMBD7UC4-B2p0efxm.js} +2 -2
- package/webapp/dist/assets/{chunk-FMBD7UC4-B1L8cPfl.js.map → chunk-FMBD7UC4-B2p0efxm.js.map} +1 -1
- package/webapp/dist/assets/{chunk-JSJVCQXG-C65w23ZF.js → chunk-JSJVCQXG-Bd09WM0B.js} +2 -2
- package/webapp/dist/assets/{chunk-JSJVCQXG-C65w23ZF.js.map → chunk-JSJVCQXG-Bd09WM0B.js.map} +1 -1
- package/webapp/dist/assets/{chunk-KX2RTZJC-_4YSMrEL.js → chunk-KX2RTZJC-DaLNbvSI.js} +2 -2
- package/webapp/dist/assets/{chunk-KX2RTZJC-_4YSMrEL.js.map → chunk-KX2RTZJC-DaLNbvSI.js.map} +1 -1
- package/webapp/dist/assets/{chunk-NQ4KR5QH-ComURSQb.js → chunk-NQ4KR5QH-6dsWbn61.js} +4 -4
- package/webapp/dist/assets/{chunk-NQ4KR5QH-ComURSQb.js.map → chunk-NQ4KR5QH-6dsWbn61.js.map} +1 -1
- package/webapp/dist/assets/{chunk-QZHKN3VN-BrxvuRI6.js → chunk-QZHKN3VN-C0e1qWr4.js} +2 -2
- package/webapp/dist/assets/{chunk-QZHKN3VN-BrxvuRI6.js.map → chunk-QZHKN3VN-C0e1qWr4.js.map} +1 -1
- package/webapp/dist/assets/{chunk-WL4C6EOR-CW7tAF_z.js → chunk-WL4C6EOR-ChheG0OU.js} +6 -6
- package/webapp/dist/assets/{chunk-WL4C6EOR-CW7tAF_z.js.map → chunk-WL4C6EOR-ChheG0OU.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-BWrPbwfd.js → classDiagram-VBA2DB6C-uUAnWHsS.js} +7 -7
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-BWrPbwfd.js.map → classDiagram-VBA2DB6C-uUAnWHsS.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BWrPbwfd.js → classDiagram-v2-RAHNMMFH-uUAnWHsS.js} +7 -7
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BWrPbwfd.js.map → classDiagram-v2-RAHNMMFH-uUAnWHsS.js.map} +1 -1
- package/webapp/dist/assets/{clone-B-TYPsxN.js → clone-BiXgC0aE.js} +2 -2
- package/webapp/dist/assets/{clone-B-TYPsxN.js.map → clone-BiXgC0aE.js.map} +1 -1
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-C1bfZcVY.js → cose-bilkent-S5V4N54A-C-h7F7gA.js} +2 -2
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-C1bfZcVY.js.map → cose-bilkent-S5V4N54A-C-h7F7gA.js.map} +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-BfD08d2e.js → dagre-KLK3FWXG-5B3k91Lo.js} +7 -7
- package/webapp/dist/assets/{dagre-KLK3FWXG-BfD08d2e.js.map → dagre-KLK3FWXG-5B3k91Lo.js.map} +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-Dyd9OucT.js → diagram-E7M64L7V-CFtPXaNS.js} +8 -8
- package/webapp/dist/assets/{diagram-E7M64L7V-Dyd9OucT.js.map → diagram-E7M64L7V-CFtPXaNS.js.map} +1 -1
- package/webapp/dist/assets/{diagram-IFDJBPK2-BN-JCceb.js → diagram-IFDJBPK2-CUuPPDwe.js} +7 -7
- package/webapp/dist/assets/{diagram-IFDJBPK2-BN-JCceb.js.map → diagram-IFDJBPK2-CUuPPDwe.js.map} +1 -1
- package/webapp/dist/assets/{diagram-P4PSJMXO-C2jh_Kry.js → diagram-P4PSJMXO-D7oYhsVm.js} +7 -7
- package/webapp/dist/assets/{diagram-P4PSJMXO-C2jh_Kry.js.map → diagram-P4PSJMXO-D7oYhsVm.js.map} +1 -1
- package/webapp/dist/assets/{erDiagram-INFDFZHY-C3Pj10OJ.js → erDiagram-INFDFZHY-DUDHdT_e.js} +5 -5
- package/webapp/dist/assets/{erDiagram-INFDFZHY-C3Pj10OJ.js.map → erDiagram-INFDFZHY-DUDHdT_e.js.map} +1 -1
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-a5vzSSCo.js → flowDiagram-PKNHOUZH-CT7lC5J1.js} +7 -7
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-a5vzSSCo.js.map → flowDiagram-PKNHOUZH-CT7lC5J1.js.map} +1 -1
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-DIua0Qjr.js → ganttDiagram-A5KZAMGK-BhlcqqDR.js} +3 -3
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-DIua0Qjr.js.map → ganttDiagram-A5KZAMGK-BhlcqqDR.js.map} +1 -1
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CJt16FXK.js → gitGraphDiagram-K3NZZRJ6-CYLYfqiB.js} +8 -8
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CJt16FXK.js.map → gitGraphDiagram-K3NZZRJ6-CYLYfqiB.js.map} +1 -1
- package/webapp/dist/assets/{graph-lQSuHjYm.js → graph-twAxd7MO.js} +3 -3
- package/webapp/dist/assets/{graph-lQSuHjYm.js.map → graph-twAxd7MO.js.map} +1 -1
- package/webapp/dist/assets/{index-B7llu28V.js → index-Bc1jJvgU.js} +36 -175
- package/webapp/dist/assets/{index-B7llu28V.js.map → index-Bc1jJvgU.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-DzJuXz5H.js → infoDiagram-LFFYTUFH-BAA1VoC0.js} +6 -6
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-DzJuXz5H.js.map → infoDiagram-LFFYTUFH-BAA1VoC0.js.map} +1 -1
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-BP_s17vw.js → ishikawaDiagram-PHBUUO56-CyPvSx5W.js} +2 -2
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-BP_s17vw.js.map → ishikawaDiagram-PHBUUO56-CyPvSx5W.js.map} +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-Lic1mhBM.js → journeyDiagram-4ABVD52K-CbOLT63I.js} +5 -5
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-Lic1mhBM.js.map → journeyDiagram-4ABVD52K-CbOLT63I.js.map} +1 -1
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Baf2kCwQ.js → kanban-definition-K7BYSVSG-CUS-wMLR.js} +3 -3
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Baf2kCwQ.js.map → kanban-definition-K7BYSVSG-CUS-wMLR.js.map} +1 -1
- package/webapp/dist/assets/{layout-DUMDc8rv.js → layout-C0HW4ZHi.js} +5 -5
- package/webapp/dist/assets/{layout-DUMDc8rv.js.map → layout-C0HW4ZHi.js.map} +1 -1
- package/webapp/dist/assets/{linear-CZMoHeVH.js → linear-DNEgfkh6.js} +2 -2
- package/webapp/dist/assets/{linear-CZMoHeVH.js.map → linear-DNEgfkh6.js.map} +1 -1
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DB2sQ--_.js → mindmap-definition-YRQLILUH-D5URwhNx.js} +4 -4
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DB2sQ--_.js.map → mindmap-definition-YRQLILUH-D5URwhNx.js.map} +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Dgdrlric.js → pieDiagram-SKSYHLDU-BQbBOUPk.js} +8 -8
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Dgdrlric.js.map → pieDiagram-SKSYHLDU-BQbBOUPk.js.map} +1 -1
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-CJcFYfqf.js → quadrantDiagram-337W2JSQ-B_dFbPid.js} +3 -3
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-CJcFYfqf.js.map → quadrantDiagram-337W2JSQ-B_dFbPid.js.map} +1 -1
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-CDsT-ac7.js → requirementDiagram-Z7DCOOCP-CtWDUSB3.js} +4 -4
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-CDsT-ac7.js.map → requirementDiagram-Z7DCOOCP-CtWDUSB3.js.map} +1 -1
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-DiO55skm.js → sankeyDiagram-WA2Y5GQK-CqRH7yj4.js} +2 -2
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-DiO55skm.js.map → sankeyDiagram-WA2Y5GQK-CqRH7yj4.js.map} +1 -1
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-CNHjdBNC.js → sequenceDiagram-2WXFIKYE-B1-5-5Qx.js} +4 -4
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-CNHjdBNC.js.map → sequenceDiagram-2WXFIKYE-B1-5-5Qx.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-CtS3TXEd.js → stateDiagram-RAJIS63D-9krZSpaD.js} +9 -9
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-CtS3TXEd.js.map → stateDiagram-RAJIS63D-9krZSpaD.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BdjJA1de.js → stateDiagram-v2-FVOUBMTO-DDLC-q0s.js} +5 -5
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BdjJA1de.js.map → stateDiagram-v2-FVOUBMTO-DDLC-q0s.js.map} +1 -1
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-D3AiTIhK.js → timeline-definition-YZTLITO2-C64HbHNO.js} +3 -3
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-D3AiTIhK.js.map → timeline-definition-YZTLITO2-C64HbHNO.js.map} +1 -1
- package/webapp/dist/assets/{treemap-KZPCXAKY-F6nRvLGK.js → treemap-KZPCXAKY-TEywEA7B.js} +5 -5
- package/webapp/dist/assets/{treemap-KZPCXAKY-F6nRvLGK.js.map → treemap-KZPCXAKY-TEywEA7B.js.map} +1 -1
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BoukZEuo.js → vennDiagram-LZ73GAT5-CT9sZ6ft.js} +2 -2
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BoukZEuo.js.map → vennDiagram-LZ73GAT5-CT9sZ6ft.js.map} +1 -1
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-ByfGkhZz.js → xychartDiagram-JWTSCODW-CEAg_tiv.js} +3 -3
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-ByfGkhZz.js.map → xychartDiagram-JWTSCODW-CEAg_tiv.js.map} +1 -1
- package/webapp/dist/index.html +1 -1
- package/dist/tools/plan.d.ts +0 -2
- package/dist/tools/plan.js +0 -171
- package/dist/tools/prompts/codex_style_tools/en/errors.md +0 -102
- package/dist/tools/prompts/codex_style_tools/en/index.md +0 -59
- package/dist/tools/prompts/codex_style_tools/en/principles.md +0 -87
- package/dist/tools/prompts/codex_style_tools/en/scenarios.md +0 -88
- package/dist/tools/prompts/codex_style_tools/en/tools.md +0 -119
- package/dist/tools/prompts/codex_style_tools/zh/errors.md +0 -102
- package/dist/tools/prompts/codex_style_tools/zh/index.md +0 -59
- package/dist/tools/prompts/codex_style_tools/zh/principles.md +0 -87
- package/dist/tools/prompts/codex_style_tools/zh/scenarios.md +0 -88
- package/dist/tools/prompts/codex_style_tools/zh/tools.md +0 -119
package/README.md
CHANGED
|
@@ -203,7 +203,7 @@ Then:
|
|
|
203
203
|
|
|
204
204
|
Platform note:
|
|
205
205
|
|
|
206
|
-
- On Windows, the runtime does not register the `
|
|
206
|
+
- On Windows, the runtime does not register the `codex_inspect_and_patch_tools` toolset. Do not grant `codex_inspect_and_patch_tools` in `.minds/team.yaml` for Windows hosts.
|
|
207
207
|
|
|
208
208
|
## Start from scratch
|
|
209
209
|
|
package/README.zh.md
CHANGED
|
@@ -142,7 +142,7 @@ dominds
|
|
|
142
142
|
|
|
143
143
|
平台说明:
|
|
144
144
|
|
|
145
|
-
- Windows 运行时不会注册 `
|
|
145
|
+
- Windows 运行时不会注册 `codex_inspect_and_patch_tools` 工具集。在 Windows 主机上的 `.minds/team.yaml` 中不要授予 `codex_inspect_and_patch_tools`。
|
|
146
146
|
|
|
147
147
|
## 从零开始(空文件夹启动)
|
|
148
148
|
|
|
@@ -51,6 +51,7 @@ const evt_registry_1 = require("./evt-registry");
|
|
|
51
51
|
const log_1 = require("./log");
|
|
52
52
|
const persistence_1 = require("./persistence");
|
|
53
53
|
const persistence_errors_1 = require("./persistence-errors");
|
|
54
|
+
const interjection_pause_stop_1 = require("./runtime/interjection-pause-stop");
|
|
54
55
|
const log = (0, log_1.createLogger)('dialog-display-state');
|
|
55
56
|
let broadcastToClients;
|
|
56
57
|
const activeRunsByDialogKey = new Map();
|
|
@@ -128,11 +129,21 @@ async function getRunControlCountsSnapshot() {
|
|
|
128
129
|
}
|
|
129
130
|
else if (latest?.executionMarker?.kind === 'interrupted' &&
|
|
130
131
|
isStoppedReasonResumable(latest.executionMarker.reason)) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
// Keep run-control counts aligned with actual Continue affordance:
|
|
133
|
+
// - ordinary interrupted dialogs count as resumable only when no blocker remains
|
|
134
|
+
// - interjection-paused dialogs still count as resumable even if blocker facts remain,
|
|
135
|
+
// because the intended UX is that Continue exits the temporary paused projection
|
|
136
|
+
// and re-evaluates the original task from fresh facts
|
|
137
|
+
if ((0, interjection_pause_stop_1.isUserInterjectionPauseStopReason)(latest.executionMarker.reason)) {
|
|
134
138
|
resumable++;
|
|
135
139
|
}
|
|
140
|
+
else {
|
|
141
|
+
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
142
|
+
const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(dialogId, 'running');
|
|
143
|
+
if (q4h.length === 0 && pendingSubdialogs.length === 0) {
|
|
144
|
+
resumable++;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
136
147
|
}
|
|
137
148
|
}
|
|
138
149
|
catch (error) {
|
|
@@ -470,6 +481,27 @@ async function refreshRunControlProjectionFromPersistenceFacts(dialogId, trigger
|
|
|
470
481
|
latest.executionMarker.kind === 'dead') {
|
|
471
482
|
return { kind: 'dead', reason: latest.executionMarker.reason };
|
|
472
483
|
}
|
|
484
|
+
if (latest.executionMarker?.kind === 'interrupted' &&
|
|
485
|
+
(0, interjection_pause_stop_1.isUserInterjectionPauseStopReason)(latest.executionMarker.reason)) {
|
|
486
|
+
// WARNING:
|
|
487
|
+
// This is the one place where the projection intentionally preserves the paused-interjection
|
|
488
|
+
// stopped state ahead of the current blocker facts. That is not a bug: after a user
|
|
489
|
+
// interjection we want the UI to keep showing "original task paused; click Continue" even if
|
|
490
|
+
// the underlying dialog is still waiting on Q4H/subdialogs.
|
|
491
|
+
//
|
|
492
|
+
// The true source-of-truth decision about what Continue should do next lives in
|
|
493
|
+
// `flow.ts`'s resume path, which performs a fresh fact scan at resume time and then either:
|
|
494
|
+
// - restores `blocked`, or
|
|
495
|
+
// - keeps driving immediately.
|
|
496
|
+
//
|
|
497
|
+
// Do not "heal" this branch away by prioritizing blocker facts here; that would collapse the
|
|
498
|
+
// temporary interjection UX and make repeated interjection turns revert too early.
|
|
499
|
+
return {
|
|
500
|
+
kind: 'stopped',
|
|
501
|
+
reason: latest.executionMarker.reason,
|
|
502
|
+
continueEnabled: isStoppedReasonResumable(latest.executionMarker.reason),
|
|
503
|
+
};
|
|
504
|
+
}
|
|
473
505
|
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
474
506
|
const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(dialogId, 'running');
|
|
475
507
|
const hasQ4H = q4h.length > 0;
|
|
@@ -444,7 +444,7 @@ Suggested team shape:
|
|
|
444
444
|
- non-goal: does not directly edit product code or take over build/process management.
|
|
445
445
|
- `web_developer`
|
|
446
446
|
- primary responsibility: implement UI/interaction fixes, consume `web_tester` findings, and close the loop;
|
|
447
|
-
- default toolsets: code-edit/search tools such as `
|
|
447
|
+
- default toolsets: code-edit/search tools such as `codex_inspect_and_patch_tools` (or equivalent) plus optional access to read tester evidence;
|
|
448
448
|
- non-goal: should not blur browser acceptance into an implicit “I also tested it” posture; when acceptance is needed, it should explicitly tell/ask `web_tester`.
|
|
449
449
|
|
|
450
450
|
Suggested `team.yaml` fragment:
|
|
@@ -463,7 +463,7 @@ members:
|
|
|
463
463
|
icon: '🛠️'
|
|
464
464
|
toolsets:
|
|
465
465
|
- ws_read
|
|
466
|
-
-
|
|
466
|
+
- codex_inspect_and_patch_tools
|
|
467
467
|
```
|
|
468
468
|
|
|
469
469
|
Requirements for the `playwright_interactive` toolset design:
|
|
@@ -443,7 +443,7 @@ Web Dev App 需要明确区分三套命名,避免再次漂移:
|
|
|
443
443
|
- 非目标:不直接修改业务代码;不接管构建/进程管理。
|
|
444
444
|
- `web_developer`
|
|
445
445
|
- 主要职责:实现页面/UI/交互修复,消费 `web_tester` 的缺陷报告并完成闭环。
|
|
446
|
-
- 默认工具集:代码修改/检索工具(如 `
|
|
446
|
+
- 默认工具集:代码修改/检索工具(如 `codex_inspect_and_patch_tools` 或等价工具)+ 可选读取 `web_tester` 产出的证据。
|
|
447
447
|
- 非目标:不把浏览器验收职责模糊地“顺手做掉”;需要时应显式 tellask `web_tester` 做验收。
|
|
448
448
|
|
|
449
449
|
建议的 `team.yaml` 片段:
|
|
@@ -462,7 +462,7 @@ members:
|
|
|
462
462
|
icon: '🛠️'
|
|
463
463
|
toolsets:
|
|
464
464
|
- ws_read
|
|
465
|
-
-
|
|
465
|
+
- codex_inspect_and_patch_tools
|
|
466
466
|
```
|
|
467
467
|
|
|
468
468
|
关于 `playwright_interactive` 工具集的设计要求:
|
|
@@ -155,6 +155,55 @@ Dialog state is persisted to storage at key points:
|
|
|
155
155
|
|
|
156
156
|
This ensures crash recovery and enables the backend to resume from any persisted state without depending on frontend state.
|
|
157
157
|
|
|
158
|
+
### User Interjection Pause And Continue Semantics
|
|
159
|
+
|
|
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
|
+
|
|
162
|
+
**Normative semantics**:
|
|
163
|
+
|
|
164
|
+
1. Every user interjection message is driven as a complete normal round.
|
|
165
|
+
2. If that round needs tools, the system MUST finish the full tool round and any post-tool follow-up before pausing.
|
|
166
|
+
3. The system only projects the original task as resumable `stopped` when this interjection has actually parked an original task that still needs explicit restoration.
|
|
167
|
+
4. If there is no parked original task to resume afterwards (for example, no inter-dialog reply obligation needs reassertion), the interjection round should simply finish and return to the true underlying state without showing this special `stopped` panel.
|
|
168
|
+
5. As long as the user keeps sending new messages, the dialog stays in temporary interjection-chat handling, and that paused projection remains in place only if it was established in the first place.
|
|
169
|
+
6. Only an explicit UI `Continue` attempts to restore the original task.
|
|
170
|
+
|
|
171
|
+
**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.
|
|
172
|
+
|
|
173
|
+
**Key point**: this `stopped` state is only a temporary run-control / UI projection. It is not the same as an ordinary system-stop failure, and it is not the final business source of truth. It also does not apply to every interjection; it exists only when there really is a parked original task to resume.
|
|
174
|
+
|
|
175
|
+
After the user clicks `Continue`, the backend MUST re-evaluate fresh persistence facts and decide which true-source case now applies. It must not infer the result purely from the visible `displayState`:
|
|
176
|
+
|
|
177
|
+
- **Case 1: the dialog no longer has a reply obligation**
|
|
178
|
+
If there is also no blocker, the dialog should simply continue driving. If it has already become ordinary idle-waiting-user, then `resume_dialog` is no longer actually resumable.
|
|
179
|
+
- **Case 2: the dialog still has a reply obligation and is still suspended**
|
|
180
|
+
Typical examples are pending Q4H or pending subdialogs. In this case, `Continue` should exit the interjection-paused projection and restore the true `blocked` state.
|
|
181
|
+
- **Case 3: the dialog still has a reply obligation but is no longer suspended and is eligible to proceed**
|
|
182
|
+
For example, the blocker has disappeared, or a queued prompt provides a valid continuation path. In this case, `Continue` must not first fall back to an intermediate placeholder `blocked/idle` state; it should keep driving immediately.
|
|
183
|
+
|
|
184
|
+
**This leads to two implementation constraints**:
|
|
185
|
+
|
|
186
|
+
- `refreshRunControlProjectionFromPersistenceFacts()` MUST preserve the special "interjection handled; original task paused" `stopped` projection until the user explicitly clicks `Continue`; otherwise the UI collapses back to ordinary `blocked` too early and breaks multi-turn interjection UX. Conversely, when there is no parked original task, this paused projection should not be created at all.
|
|
187
|
+
- The actual outcome of `Continue` MUST be decided in the resume drive path by re-reading fresh persistence facts. "Continue is clickable" does not mean "the dialog will definitely enter proceeding immediately".
|
|
188
|
+
- If `Continue` reveals that the true state is still `blocked`, the reply-obligation reassertion copy should be materialized immediately as a runtime guide in both `dlg.msgs` and persisted course history, while also surfacing as a frontend bubble. That lets the later real resume path rely on ordinary context replay instead of synthesizing a second duplicate runtime prompt.
|
|
189
|
+
- The run-control toolbar's `resumable` count should align with "manual Continue attempt is meaningful". Therefore an interjection-paused `stopped` dialog still counts as resumable even when underlying blocker facts remain, because the business meaning of `Continue` there is "exit the temporary paused projection and re-evaluate from source-of-truth facts".
|
|
190
|
+
|
|
191
|
+
**Mental-model warning**:
|
|
192
|
+
|
|
193
|
+
- Do not reason about this flow from `displayState.kind === 'stopped'` alone.
|
|
194
|
+
- Do not reason about it from blocker facts alone and then wonder why the UI still shows `stopped`.
|
|
195
|
+
- Do not reason about it from `resume_dialog` eligibility alone and assume resumption always means immediate running.
|
|
196
|
+
- Do not flatten every `origin === 'user'` prompt into "interjection"; a non-empty `q4hAnswerCallId` means askHuman answer continuation and follows a different semantic path.
|
|
197
|
+
|
|
198
|
+
You need all of the following together to understand the behavior correctly:
|
|
199
|
+
|
|
200
|
+
- reply-guidance suppression / deferred reassertion for interjection turns
|
|
201
|
+
- flow logic for "pause after local interjection reply" plus "fresh-fact second decision after Continue"
|
|
202
|
+
- dialog-display-state projection preservation
|
|
203
|
+
- websocket resume entry semantics distinguishing "allowed to attempt Continue" from "actually re-entered driving"
|
|
204
|
+
|
|
205
|
+
This is an intentionally cross-module semantic contract. Do not locally "simplify" one piece based only on its surface meaning.
|
|
206
|
+
|
|
158
207
|
---
|
|
159
208
|
|
|
160
209
|
## 3-Type Teammate Tellask Taxonomy
|
|
@@ -154,6 +154,55 @@
|
|
|
154
154
|
|
|
155
155
|
这确保了崩溃恢复,并使后端能够从任何持久化状态恢复,而不依赖于前端状态。
|
|
156
156
|
|
|
157
|
+
### 用户插话暂停与 Continue 语义
|
|
158
|
+
|
|
159
|
+
当某个对话仍带有跨对话回复义务,但用户临时插话要求它先处理本地问题时,系统必须区分**UI 投影**与**真实驱动源状态**。
|
|
160
|
+
|
|
161
|
+
**规范语义**:
|
|
162
|
+
|
|
163
|
+
1. 每条用户插话消息都按正常驱动轮完整执行。
|
|
164
|
+
2. 若该轮需要工具,则必须先完整跑完该工具轮及其 post-tool follow-up。
|
|
165
|
+
3. 只有当这条插话确实打断了一个仍待恢复的“原任务”时,系统才把该原任务投影为可 `Continue` 的 `stopped`,让用户先看到最后一条回复。
|
|
166
|
+
4. 若当前并不存在待恢复的原任务(例如没有待重申的跨对话回复义务),则插话轮结束后应直接回到真实 underlying state,而不显示这个特殊 `stopped` 面板。
|
|
167
|
+
5. 只要用户继续发送新消息,就继续作为插话临时对话处理;这个 paused projection 仅在它已被建立时持续保持。
|
|
168
|
+
6. 只有用户显式点击 UI `Continue`,系统才尝试恢复原任务。
|
|
169
|
+
|
|
170
|
+
**严格边界**:`askHuman` 的正式回答不属于这里的“用户插话”。只要一条 prompt 带着真实的 `q4hAnswerCallId`,它就属于 askHuman 回复通道,语义上是在继续已 materialize 的提问/应答链路,绝不能被压入“本地临时插话聊天”。
|
|
171
|
+
|
|
172
|
+
**关键点**:这里的 `stopped` 只是一个临时 run-control / UI 投影,不等于普通 system-stop 失败,也不是最终的业务真源;并且它不是所有插话都会出现,只在“确有一个待恢复的原任务被临时停靠”时出现。
|
|
173
|
+
|
|
174
|
+
点击 `Continue` 后,后端必须重新从 persistence 真源判定当前对话属于哪一种情况,而不能只根据表面的 `displayState` 做静态推断:
|
|
175
|
+
|
|
176
|
+
- **情况 1:当前对话没有回复义务**
|
|
177
|
+
这时若也没有其他 blocker,就应直接继续 drive;若已回到普通待用户输入态,则 `resume_dialog` 不应再被视为可继续。
|
|
178
|
+
- **情况 2:当前对话仍有回复义务,但处于 suspend 状态**
|
|
179
|
+
常见于仍在等待 Q4H / pending subdialogs。此时 `Continue` 应退出插话 paused projection,并恢复成真实的 `blocked`。
|
|
180
|
+
- **情况 3:当前对话仍有回复义务,但已不再 suspend,具备继续推进条件**
|
|
181
|
+
例如 blocker 已消失,或存在允许继续的 queued prompt。此时 `Continue` 不应先落一个中间 `blocked/idle` 占位态,而应直接继续 drive。
|
|
182
|
+
|
|
183
|
+
**因此有两个实现约束**:
|
|
184
|
+
|
|
185
|
+
- `refreshRunControlProjectionFromPersistenceFacts()` 在用户尚未点击 `Continue` 前,必须保留这层“插话已处理;原任务已暂停”的 `stopped` 投影;否则 UI 会过早塌回普通 `blocked`,破坏多轮插话体验。反过来,如果当前其实没有待恢复原任务,则根本不应建立这层 paused projection。
|
|
186
|
+
- 真正决定 `Continue` 结果的逻辑,必须在恢复驱动路径中重新读取 fresh persistence facts;不能把“可点 Continue”误解为“必然立即 proceeding”。
|
|
187
|
+
- 若 `Continue` 后真源仍是 `blocked`,回复责任重申文案应当立即作为 runtime guide 同时进入 `dlg.msgs` 与持久化课程历史,并同步发前端气泡;这样后面真正恢复 drive 时只需正常读取上下文,不应再额外补发一条重复的 runtime prompt。
|
|
188
|
+
- run-control 工具栏中的 `resumable` 计数,应与“是否允许手动 Continue 尝试”保持一致。因此,处于 interjection-paused `stopped` 的对话即便底层仍有 blocker,也应计入 `resumable`;因为 `Continue` 的业务语义正是“退出这层临时 paused projection,并从真源重判下一步”。
|
|
189
|
+
|
|
190
|
+
**心智模型提醒**:
|
|
191
|
+
|
|
192
|
+
- 不能只看 `displayState.kind === 'stopped'` 就理解这条链路。
|
|
193
|
+
- 不能只看 blocker facts 就理解为什么 UI 仍显示 `stopped`。
|
|
194
|
+
- 也不能只看 `resume_dialog` eligibility 就推断恢复后一定马上运行。
|
|
195
|
+
- 更不能把所有 `origin === 'user'` 的输入都笼统视作“用户插话”;`q4hAnswerCallId` 非空的 prompt 是 askHuman answer continuation,必须按另一条语义链处理。
|
|
196
|
+
|
|
197
|
+
必须把以下几块一起看,才能形成完整且精确的理解:
|
|
198
|
+
|
|
199
|
+
- reply-guidance 中对插话轮的回复义务 suppression / deferred reassertion
|
|
200
|
+
- flow 中“插话回复后停车”与“Continue 后 fresh fact 二次判定”
|
|
201
|
+
- dialog-display-state 中 paused projection 的保留策略
|
|
202
|
+
- websocket resume 入口对“可尝试 Continue”与“实际已恢复 drive”的区分
|
|
203
|
+
|
|
204
|
+
这是一条跨模块协同语义,不允许在单点上做“表面看起来更简单”的局部简化。
|
|
205
|
+
|
|
157
206
|
---
|
|
158
207
|
|
|
159
208
|
## 三类队友诉请分类
|
|
@@ -533,7 +533,7 @@ Best practices:
|
|
|
533
533
|
|
|
534
534
|
- Make `member_defaults` conservative. Grant additional tools/dirs on a per-member basis.
|
|
535
535
|
- Prefer toolsets over individually enumerating tools unless you need a one-off tool.
|
|
536
|
-
- Platform note: Windows runtime intentionally does not register `
|
|
536
|
+
- Platform note: Windows runtime intentionally does not register `codex_inspect_and_patch_tools`; do not grant that toolset in `.minds/team.yaml` on Windows hosts.
|
|
537
537
|
- Keep `.minds/team.yaml` ownership tight; only the team manager should be able to edit it.
|
|
538
538
|
- Avoid repeating built-in constraints in `team.yaml`:
|
|
539
539
|
- `*.tsk/**` (encapsulated Taskdocs) are hard-denied for all general file tools.
|
|
@@ -452,7 +452,7 @@ members:
|
|
|
452
452
|
|
|
453
453
|
- 使 `member_defaults` 保守。按成员授予额外的工具/目录
|
|
454
454
|
- 优先使用工具集而不是单独枚举工具,除非你需要一次性工具
|
|
455
|
-
- 平台说明:Windows 运行时不会注册 `
|
|
455
|
+
- 平台说明:Windows 运行时不会注册 `codex_inspect_and_patch_tools`;在 Windows 主机上的 `.minds/team.yaml` 中不要授予该工具集
|
|
456
456
|
- 保持 `.minds/team.yaml` 的所有权严格;只有团队管理者应该能够编辑它
|
|
457
457
|
- 避免在 `team.yaml` 中重复内置约束:
|
|
458
458
|
- `*.tsk/**`(封装的差遣牒任务包)对所有通用文件工具被硬性拒绝
|
package/dist/llm/gen/codex.d.ts
CHANGED
|
@@ -11,15 +11,7 @@ import type { FuncTool } from '../../tool';
|
|
|
11
11
|
import type { ChatMessage, ProviderConfig } from '../client';
|
|
12
12
|
import type { LlmBatchResult, LlmFailureDisposition, LlmGenerator, LlmRequestContext, LlmStreamReceiver, LlmStreamResult } from '../gen';
|
|
13
13
|
export declare function resolveCodexServiceTier(serviceTier: ChatGptResponsesRequest['service_tier'] | undefined): Exclude<NonNullable<ChatGptResponsesRequest['service_tier']>, 'default'> | undefined;
|
|
14
|
-
export declare function
|
|
15
|
-
template: string;
|
|
16
|
-
defaultModel: string;
|
|
17
|
-
loadPrompt: (model: string) => string | null;
|
|
18
|
-
}): string;
|
|
19
|
-
export declare function resolveCodexInstructions(systemPrompt: string, options?: {
|
|
20
|
-
defaultModel?: string;
|
|
21
|
-
loadPrompt?: (model: string) => string | null;
|
|
22
|
-
}): string;
|
|
14
|
+
export declare function resolveCodexInstructions(systemPrompt: string): string;
|
|
23
15
|
export declare class CodexGen implements LlmGenerator {
|
|
24
16
|
get apiType(): string;
|
|
25
17
|
classifyFailure(error: unknown): LlmFailureDisposition | undefined;
|
package/dist/llm/gen/codex.js
CHANGED
|
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.CodexGen = void 0;
|
|
37
37
|
exports.resolveCodexServiceTier = resolveCodexServiceTier;
|
|
38
|
-
exports.spliceCodexBuiltinPrompt = spliceCodexBuiltinPrompt;
|
|
39
38
|
exports.resolveCodexInstructions = resolveCodexInstructions;
|
|
40
39
|
const log_1 = require("../../log");
|
|
41
40
|
const i18n_text_1 = require("../../runtime/i18n-text");
|
|
@@ -47,7 +46,6 @@ const tool_output_limit_1 = require("./tool-output-limit");
|
|
|
47
46
|
const tool_result_image_ingest_1 = require("./tool-result-image-ingest");
|
|
48
47
|
const log = (0, log_1.createLogger)('llm/codex');
|
|
49
48
|
const codexFallbackInstructions = 'You are Codex CLI.';
|
|
50
|
-
const CODEX_SYSTEM_PROMPT_DIRECTIVE_PATTERN = /^([ \t]*)@codex-system-prompt(?::([A-Za-z0-9._-]+))?([ \t]*)$/gm;
|
|
51
49
|
function resolveCodexServiceTier(serviceTier) {
|
|
52
50
|
// The ChatGPT codex backend rejects the literal `default` tier even though some SDK typings
|
|
53
51
|
// still list it. Omitting the field preserves the standard tier semantics without a 400.
|
|
@@ -116,29 +114,8 @@ function tryExtractApiReturnedModel(value) {
|
|
|
116
114
|
const trimmed = model.trim();
|
|
117
115
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
118
116
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
const resolved = params.template.replace(CODEX_SYSTEM_PROMPT_DIRECTIVE_PATTERN, (_match, leading, overrideModel, trailing) => {
|
|
122
|
-
const selectedModel = overrideModel ?? params.defaultModel;
|
|
123
|
-
const prompt = params.loadPrompt(selectedModel);
|
|
124
|
-
if (prompt === null) {
|
|
125
|
-
throw new Error(`Bundled Codex prompt template not found for model: ${selectedModel}`);
|
|
126
|
-
}
|
|
127
|
-
replaced = true;
|
|
128
|
-
return `${leading}${prompt}${trailing}`;
|
|
129
|
-
});
|
|
130
|
-
return replaced ? resolved : params.template;
|
|
131
|
-
}
|
|
132
|
-
function resolveCodexInstructions(systemPrompt, options) {
|
|
133
|
-
const baseInstructions = systemPrompt.trim().length > 0 ? systemPrompt : codexFallbackInstructions;
|
|
134
|
-
if (options?.defaultModel === undefined || options.loadPrompt === undefined) {
|
|
135
|
-
return baseInstructions;
|
|
136
|
-
}
|
|
137
|
-
return spliceCodexBuiltinPrompt({
|
|
138
|
-
template: baseInstructions,
|
|
139
|
-
defaultModel: options.defaultModel,
|
|
140
|
-
loadPrompt: options.loadPrompt,
|
|
141
|
-
});
|
|
117
|
+
function resolveCodexInstructions(systemPrompt) {
|
|
118
|
+
return systemPrompt.trim().length > 0 ? systemPrompt : codexFallbackInstructions;
|
|
142
119
|
}
|
|
143
120
|
function funcToolToCodex(funcTool) {
|
|
144
121
|
// MCP schemas are passed through to providers. Codex tool schema types are narrower; runtime
|
|
@@ -534,10 +511,7 @@ class CodexGen {
|
|
|
534
511
|
if (!agent.model) {
|
|
535
512
|
throw new Error(`Internal error: Model is undefined for agent '${agent.id}'`);
|
|
536
513
|
}
|
|
537
|
-
const instructions = resolveCodexInstructions(systemPrompt
|
|
538
|
-
defaultModel: agent.model,
|
|
539
|
-
loadPrompt: codexAuth.loadCodexPromptSync,
|
|
540
|
-
});
|
|
514
|
+
const instructions = resolveCodexInstructions(systemPrompt);
|
|
541
515
|
const payload = await buildCodexRequest(providerConfig, agent, instructions, funcTools, requestContext, context, receiver.toolResultImageIngest);
|
|
542
516
|
let sayingStarted = false;
|
|
543
517
|
let thinkingStarted = false;
|
|
@@ -807,7 +807,6 @@ async function emitAssistantSaying(dlg, content) {
|
|
|
807
807
|
await dlg.sayingChunk(content);
|
|
808
808
|
await dlg.sayingFinish();
|
|
809
809
|
}
|
|
810
|
-
const KERNEL_DRIVER_IDENTICAL_UPDATE_PLAN_ONLY_STOP_THRESHOLD = 3;
|
|
811
810
|
function resolveFuncToolFollowupMode(tool) {
|
|
812
811
|
return tool?.followupMode ?? 'immediate';
|
|
813
812
|
}
|
|
@@ -820,20 +819,6 @@ function shouldImmediatelyFollowUpToolOutcome(tool, outcome) {
|
|
|
820
819
|
}
|
|
821
820
|
return shouldImmediatelyFollowUpSuccessfulToolResult(tool);
|
|
822
821
|
}
|
|
823
|
-
function formatIdenticalUpdatePlanLoopStopDetail(language) {
|
|
824
|
-
return language === 'zh'
|
|
825
|
-
? `检测到连续 ${String(KERNEL_DRIVER_IDENTICAL_UPDATE_PLAN_ONLY_STOP_THRESHOLD)} 次完全相同的 update_plan 自动续跑,已停止本次自动执行以避免自激发循环。你可以点击“继续”人工观察,或先修改计划内容再继续。`
|
|
826
|
-
: `Detected ${String(KERNEL_DRIVER_IDENTICAL_UPDATE_PLAN_ONLY_STOP_THRESHOLD)} consecutive identical update_plan auto-follow-up rounds. Stopped this automatic run to avoid a self-trigger loop. You can click Continue to inspect manually, or change the plan content before resuming.`;
|
|
827
|
-
}
|
|
828
|
-
function extractAssistantSayingRoundSignature(newMsgs) {
|
|
829
|
-
const contents = newMsgs
|
|
830
|
-
.filter((msg) => msg.type === 'saying_msg' && msg.role === 'assistant')
|
|
831
|
-
.map((msg) => msg.content);
|
|
832
|
-
if (contents.length === 0) {
|
|
833
|
-
return undefined;
|
|
834
|
-
}
|
|
835
|
-
return JSON.stringify(contents);
|
|
836
|
-
}
|
|
837
822
|
async function executeFunctionCalls(args) {
|
|
838
823
|
const functionPromises = args.funcCalls.map(async (func) => {
|
|
839
824
|
throwIfAborted(args.abortSignal, args.dlg);
|
|
@@ -933,7 +918,6 @@ async function executeFunctionRound(args) {
|
|
|
933
918
|
shouldStopAfterReplyTool: false,
|
|
934
919
|
pairedMessages: [],
|
|
935
920
|
tellaskToolOutputs: [],
|
|
936
|
-
updatePlanOnlyRound: false,
|
|
937
921
|
};
|
|
938
922
|
}
|
|
939
923
|
throwIfAborted(args.abortSignal, args.dlg);
|
|
@@ -977,24 +961,6 @@ async function executeFunctionRound(args) {
|
|
|
977
961
|
}
|
|
978
962
|
return shouldImmediatelyFollowUpToolOutcome(tool, outcome);
|
|
979
963
|
});
|
|
980
|
-
const updatePlanOnlyRound = (() => {
|
|
981
|
-
if (tellaskRound.normalCalls.length === 0) {
|
|
982
|
-
return false;
|
|
983
|
-
}
|
|
984
|
-
if (tellaskRound.handledCallIds.length > 0 || tellaskRound.toolOutputs.length > 0) {
|
|
985
|
-
return false;
|
|
986
|
-
}
|
|
987
|
-
for (const call of tellaskRound.normalCalls) {
|
|
988
|
-
if (call.name !== 'update_plan') {
|
|
989
|
-
return false;
|
|
990
|
-
}
|
|
991
|
-
const outcome = genericOutcomeByCallId.get(call.id);
|
|
992
|
-
if (outcome !== 'success') {
|
|
993
|
-
return false;
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
return true;
|
|
997
|
-
})();
|
|
998
964
|
const resultByCallId = new Map();
|
|
999
965
|
const register = (result) => {
|
|
1000
966
|
const existing = resultByCallId.get(result.id);
|
|
@@ -1043,7 +1009,6 @@ async function executeFunctionRound(args) {
|
|
|
1043
1009
|
shouldStopAfterReplyTool: tellaskRound.shouldStopAfterReplyTool,
|
|
1044
1010
|
pairedMessages,
|
|
1045
1011
|
tellaskToolOutputs: [...tellaskRound.toolOutputs],
|
|
1046
|
-
updatePlanOnlyRound,
|
|
1047
1012
|
};
|
|
1048
1013
|
}
|
|
1049
1014
|
async function resetDiligenceBudgetAfterQ4H(dlg, team) {
|
|
@@ -1202,8 +1167,6 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1202
1167
|
let retryStoppedRecoveryPrompt;
|
|
1203
1168
|
let skipTaskdocForThisDrive = humanPrompt?.skipTaskdoc === true;
|
|
1204
1169
|
let genIterNo = 0;
|
|
1205
|
-
let consecutiveIdenticalUpdatePlanOnlyRounds = 0;
|
|
1206
|
-
let lastIdenticalUpdatePlanRoundSignature;
|
|
1207
1170
|
// Quirk retry state intentionally spans multiple request invocations in the same driver run,
|
|
1208
1171
|
// including course changes. Provider/API retry heuristics are tracked independently from
|
|
1209
1172
|
// user-facing course boundaries.
|
|
@@ -1417,16 +1380,28 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1417
1380
|
if (currentPrompt.origin === 'user' &&
|
|
1418
1381
|
replyGuidance.suppressInterDialogReplyGuidance &&
|
|
1419
1382
|
replyGuidance.deferredReplyReassertionDirective !== undefined) {
|
|
1383
|
+
// WARNING:
|
|
1384
|
+
// User interjection suppression is a reversible state transition, not a one-shot
|
|
1385
|
+
// latch. The normal cycle is:
|
|
1386
|
+
// - user interjects -> suppress reply obligation
|
|
1387
|
+
// - operator clicks Continue -> restore reply obligation
|
|
1388
|
+
// - user interjects again -> suppress it again
|
|
1389
|
+
//
|
|
1390
|
+
// Therefore a repeated interjection after a blocked Continue MUST re-arm the deferred
|
|
1391
|
+
// state and re-materialize the suppression guide, even when the underlying reply
|
|
1392
|
+
// directive itself did not change.
|
|
1420
1393
|
const existingDeferredReplyReassertion = await persistence_1.DialogPersistence.getDeferredReplyReassertion(dlg.id, dlg.status);
|
|
1421
1394
|
const nextDeferredReplyReassertion = {
|
|
1422
|
-
reason: '
|
|
1395
|
+
reason: 'user_interjection_with_parked_original_task',
|
|
1423
1396
|
directive: replyGuidance.deferredReplyReassertionDirective,
|
|
1424
1397
|
};
|
|
1425
|
-
|
|
1426
|
-
|
|
1398
|
+
const mustRearmDeferredReplyReassertion = existingDeferredReplyReassertion === undefined ||
|
|
1399
|
+
existingDeferredReplyReassertion.resumeGuideSurfaced === true ||
|
|
1400
|
+
!hasSameReplyDirective(existingDeferredReplyReassertion.directive, nextDeferredReplyReassertion.directive);
|
|
1401
|
+
if (mustRearmDeferredReplyReassertion) {
|
|
1427
1402
|
await persistence_1.DialogPersistence.setDeferredReplyReassertion(dlg.id, nextDeferredReplyReassertion, dlg.status);
|
|
1428
1403
|
}
|
|
1429
|
-
if (
|
|
1404
|
+
if (mustRearmDeferredReplyReassertion) {
|
|
1430
1405
|
currentRuntimeGuideMsg = replyGuidance.transientGuideContent
|
|
1431
1406
|
? {
|
|
1432
1407
|
type: 'transient_guide_msg',
|
|
@@ -1466,6 +1441,9 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1466
1441
|
currentRuntimeGuideMsg = undefined;
|
|
1467
1442
|
}
|
|
1468
1443
|
if (isQ4HAnswerPrompt) {
|
|
1444
|
+
if (!replyGuidance.isQ4HAnswerPrompt) {
|
|
1445
|
+
throw new Error(`kernel-driver q4h answer classification invariant violation: msgId=${currentPrompt.msgId} was parsed as q4h answer before reply-guidance but not after`);
|
|
1446
|
+
}
|
|
1469
1447
|
// Record only the answered call correlation / user language for the resumed round.
|
|
1470
1448
|
// The actual human answer fact was already persisted via askHuman tellask result flow.
|
|
1471
1449
|
await dlg.receiveHumanReply({
|
|
@@ -1474,6 +1452,9 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1474
1452
|
q4hAnswerCallId,
|
|
1475
1453
|
});
|
|
1476
1454
|
}
|
|
1455
|
+
else if (replyGuidance.isQ4HAnswerPrompt) {
|
|
1456
|
+
throw new Error(`kernel-driver q4h answer classification invariant violation: msgId=${currentPrompt.msgId} was classified as q4h answer by reply-guidance without a normalized q4hAnswerCallId`);
|
|
1457
|
+
}
|
|
1477
1458
|
else {
|
|
1478
1459
|
await dlg.addChatMessages({
|
|
1479
1460
|
type: 'prompting_msg',
|
|
@@ -1992,25 +1973,6 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1992
1973
|
newMsgs.push(...routed.pairedMessages);
|
|
1993
1974
|
}
|
|
1994
1975
|
await dlg.addChatMessages(...newMsgs);
|
|
1995
|
-
const assistantSayingRoundSignature = extractAssistantSayingRoundSignature(newMsgs);
|
|
1996
|
-
const identicalUpdatePlanRoundSignature = routed.updatePlanOnlyRound
|
|
1997
|
-
? JSON.stringify({
|
|
1998
|
-
assistantSayingRoundSignature: assistantSayingRoundSignature ?? '',
|
|
1999
|
-
})
|
|
2000
|
-
: undefined;
|
|
2001
|
-
if (identicalUpdatePlanRoundSignature !== undefined) {
|
|
2002
|
-
if (identicalUpdatePlanRoundSignature === lastIdenticalUpdatePlanRoundSignature) {
|
|
2003
|
-
consecutiveIdenticalUpdatePlanOnlyRounds += 1;
|
|
2004
|
-
}
|
|
2005
|
-
else {
|
|
2006
|
-
consecutiveIdenticalUpdatePlanOnlyRounds = 1;
|
|
2007
|
-
lastIdenticalUpdatePlanRoundSignature = identicalUpdatePlanRoundSignature;
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2010
|
-
else {
|
|
2011
|
-
consecutiveIdenticalUpdatePlanOnlyRounds = 0;
|
|
2012
|
-
lastIdenticalUpdatePlanRoundSignature = undefined;
|
|
2013
|
-
}
|
|
2014
1976
|
const persistedFbrState = await loadDialogFbrState(dlg);
|
|
2015
1977
|
if (persistedFbrState) {
|
|
2016
1978
|
if (persistedFbrState.phase === 'finalization') {
|
|
@@ -2096,27 +2058,6 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
2096
2058
|
await resetDiligenceBudgetAfterQ4H(dlg, team);
|
|
2097
2059
|
break;
|
|
2098
2060
|
}
|
|
2099
|
-
if (consecutiveIdenticalUpdatePlanOnlyRounds >=
|
|
2100
|
-
KERNEL_DRIVER_IDENTICAL_UPDATE_PLAN_ONLY_STOP_THRESHOLD) {
|
|
2101
|
-
const detail = formatIdenticalUpdatePlanLoopStopDetail((0, work_language_1.getWorkLanguage)());
|
|
2102
|
-
log_1.log.error(detail, new Error('kernel_driver_identical_update_plan_loop_stopped'), {
|
|
2103
|
-
dialogId: dlg.id.valueOf(),
|
|
2104
|
-
rootId: dlg.id.rootId,
|
|
2105
|
-
selfId: dlg.id.selfId,
|
|
2106
|
-
course: dlg.currentCourse,
|
|
2107
|
-
genseq: dlg.activeGenSeqOrUndefined ?? null,
|
|
2108
|
-
consecutiveIdenticalUpdatePlanOnlyRounds,
|
|
2109
|
-
identicalUpdatePlanRoundSignature,
|
|
2110
|
-
});
|
|
2111
|
-
throw new KernelDriverInterruptedError({
|
|
2112
|
-
kind: 'system_stop',
|
|
2113
|
-
detail,
|
|
2114
|
-
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
2115
|
-
detail,
|
|
2116
|
-
kind: 'identical_update_plan_loop',
|
|
2117
|
-
}),
|
|
2118
|
-
});
|
|
2119
|
-
}
|
|
2120
2061
|
// Start an immediate post-tool generation only when this round produced tool outputs that
|
|
2121
2062
|
// warrant same-drive LLM reaction right away. Provider-native side-channel UI events are
|
|
2122
2063
|
// meaningful output, but they are not transcript/context inputs and therefore must not
|