dominds 1.16.1 → 1.16.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/dist/dialog-display-state.d.ts +4 -0
- package/dist/dialog-display-state.js +138 -19
- package/dist/dialog-fork.js +13 -5
- package/dist/dialog-interruption.d.ts +18 -0
- package/dist/dialog-interruption.js +34 -0
- package/dist/docs/dominds-agent-collaboration.zh.md +401 -0
- package/dist/llm/api-quirks.d.ts +11 -0
- package/dist/llm/api-quirks.js +322 -24
- package/dist/llm/defaults.yaml +2 -1
- package/dist/llm/gen/mock.d.ts +1 -1
- package/dist/llm/gen/mock.js +12 -0
- package/dist/llm/gen/openai-compatible.d.ts +1 -1
- package/dist/llm/gen/openai-compatible.js +9 -1
- package/dist/llm/gen/openai.d.ts +1 -1
- package/dist/llm/gen/openai.js +16 -2
- package/dist/llm/gen.d.ts +10 -0
- package/dist/llm/gen.js +10 -0
- package/dist/llm/kernel-driver/drive.js +994 -866
- package/dist/llm/kernel-driver/runtime.d.ts +16 -2
- package/dist/llm/kernel-driver/runtime.js +75 -10
- package/dist/llm/stop-reason-i18n.d.ts +9 -0
- package/dist/llm/stop-reason-i18n.js +114 -0
- package/dist/persistence-errors.d.ts +26 -0
- package/dist/persistence-errors.js +68 -0
- package/dist/persistence.d.ts +119 -82
- package/dist/persistence.js +1055 -426
- package/dist/server/api-routes.js +174 -58
- package/dist/server/websocket-handler.js +125 -21
- package/dist/tools/team_mgmt.js +2 -2
- package/package.json +3 -3
- package/webapp/dist/assets/{_basePickBy-C0MXVhMo.js → _basePickBy-BJWCmtUm.js} +3 -3
- package/webapp/dist/assets/_basePickBy-BJWCmtUm.js.map +1 -0
- package/webapp/dist/assets/{_baseUniq-CRygl41M.js → _baseUniq-D6k_lGfs.js} +2 -2
- package/webapp/dist/assets/_baseUniq-D6k_lGfs.js.map +1 -0
- package/webapp/dist/assets/{arc-BeHJtnt2.js → arc-DYDaESgj.js} +2 -2
- package/webapp/dist/assets/arc-DYDaESgj.js.map +1 -0
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CGdo5TVi.js → architectureDiagram-VXUJARFQ-DZMT7dqc.js} +8 -26
- package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DZMT7dqc.js.map +1 -0
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-C59VaSGw.js → blockDiagram-VD42YOAC-CABpgVAa.js} +170 -187
- package/webapp/dist/assets/blockDiagram-VD42YOAC-CABpgVAa.js.map +1 -0
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-B3YCBmTx.js → c4Diagram-YG6GDRKO-COLZS8Ul.js} +4 -4
- package/webapp/dist/assets/c4Diagram-YG6GDRKO-COLZS8Ul.js.map +1 -0
- package/webapp/dist/assets/{channel-Dn4i8EAY.js → channel-CYFm9Cri.js} +2 -2
- package/webapp/dist/assets/channel-CYFm9Cri.js.map +1 -0
- package/webapp/dist/assets/{chunk-4BX2VUAB-CQbB3HlW.js → chunk-4BX2VUAB-CX_-XbaN.js} +2 -2
- package/webapp/dist/assets/chunk-4BX2VUAB-CX_-XbaN.js.map +1 -0
- package/webapp/dist/assets/{chunk-55IACEB6-CkQR_Qu9.js → chunk-55IACEB6-ByD-NdBC.js} +2 -2
- package/webapp/dist/assets/chunk-55IACEB6-ByD-NdBC.js.map +1 -0
- package/webapp/dist/assets/{chunk-WL4C6EOR-Bjl-j3bf.js → chunk-B4BG7PRW-BANemsDD.js} +121 -171
- package/webapp/dist/assets/chunk-B4BG7PRW-BANemsDD.js.map +1 -0
- package/webapp/dist/assets/{chunk-NQ4KR5QH-DBxY8LL2.js → chunk-DI55MBZ5-DV7sdJmQ.js} +7 -9
- package/webapp/dist/assets/chunk-DI55MBZ5-DV7sdJmQ.js.map +1 -0
- package/webapp/dist/assets/{chunk-FMBD7UC4-YSIOuaST.js → chunk-FMBD7UC4-DYGviJnf.js} +2 -2
- package/webapp/dist/assets/chunk-FMBD7UC4-DYGviJnf.js.map +1 -0
- package/webapp/dist/assets/{chunk-KX2RTZJC-DFiwgnFf.js → chunk-QN33PNHL-B8DWRL9f.js} +2 -2
- package/webapp/dist/assets/chunk-QN33PNHL-B8DWRL9f.js.map +1 -0
- package/webapp/dist/assets/{chunk-QZHKN3VN-BAdR6lLc.js → chunk-QZHKN3VN-B1aYIzMR.js} +2 -2
- package/webapp/dist/assets/chunk-QZHKN3VN-B1aYIzMR.js.map +1 -0
- package/webapp/dist/assets/{chunk-JSJVCQXG-CWDLRawz.js → chunk-TZMSLE5B-_HISzxl3.js} +6 -14
- package/webapp/dist/assets/chunk-TZMSLE5B-_HISzxl3.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-KBeS6WXD.js → classDiagram-2ON5EDUG-CpyYj1Rc.js} +6 -7
- package/webapp/dist/assets/classDiagram-2ON5EDUG-CpyYj1Rc.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-KBeS6WXD.js → classDiagram-v2-WZHVMYZB-CpyYj1Rc.js} +6 -7
- package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-CpyYj1Rc.js.map +1 -0
- package/webapp/dist/assets/{clone-C7-aS2vm.js → clone-B_9AxWIU.js} +2 -2
- package/webapp/dist/assets/clone-B_9AxWIU.js.map +1 -0
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-Bo5IsL-5.js → cose-bilkent-S5V4N54A-17ECLfPR.js} +2 -2
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-17ECLfPR.js.map +1 -0
- package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-C3FeHj7D.js → dagre-6UL2VRFP-DhRqcF1o.js} +7 -7
- package/webapp/dist/assets/dagre-6UL2VRFP-DhRqcF1o.js.map +1 -0
- package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-0HfiRW0u.js → diagram-PSM6KHXK-lpDT6Wwb.js} +10 -10
- package/webapp/dist/assets/diagram-PSM6KHXK-lpDT6Wwb.js.map +1 -0
- package/webapp/dist/assets/{diagram-IFDJBPK2-DJwh7SMO.js → diagram-QEK2KX5R-ohxbPpDH.js} +8 -9
- package/webapp/dist/assets/diagram-QEK2KX5R-ohxbPpDH.js.map +1 -0
- package/webapp/dist/assets/{diagram-P4PSJMXO-Y0RbvUZX.js → diagram-S2PKOQOG-DAFFGfch.js} +8 -8
- package/webapp/dist/assets/diagram-S2PKOQOG-DAFFGfch.js.map +1 -0
- package/webapp/dist/assets/{erDiagram-INFDFZHY-B183xyLa.js → erDiagram-Q2GNP2WA-BH-7rI43.js} +75 -96
- package/webapp/dist/assets/erDiagram-Q2GNP2WA-BH-7rI43.js.map +1 -0
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-C_BR3Y3J.js → flowDiagram-NV44I4VS-CdEjFbz4.js} +81 -98
- package/webapp/dist/assets/flowDiagram-NV44I4VS-CdEjFbz4.js.map +1 -0
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-CHLgkuJT.js → ganttDiagram-JELNMOA3-Cju2t-lK.js} +3 -28
- package/webapp/dist/assets/ganttDiagram-JELNMOA3-Cju2t-lK.js.map +1 -0
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D6C_HU1q.js → gitGraphDiagram-V2S2FVAM-CUJ5oxCg.js} +46 -38
- package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-CUJ5oxCg.js.map +1 -0
- package/webapp/dist/assets/graph-mhcc7ldf.js +425 -0
- package/webapp/dist/assets/graph-mhcc7ldf.js.map +1 -0
- package/webapp/dist/assets/{index-CLoNHmSQ.js → index-BLnM-uON.js} +2098 -1841
- package/webapp/dist/assets/{index-CLoNHmSQ.js.map → index-BLnM-uON.js.map} +1 -1
- package/webapp/dist/assets/{index-YaxF76or.css → index-xvYYeHuy.css} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-mnMS61NO.js → infoDiagram-HS3SLOUP-Df8p0okQ.js} +7 -7
- package/webapp/dist/assets/infoDiagram-HS3SLOUP-Df8p0okQ.js.map +1 -0
- package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BdeERn0r.js → journeyDiagram-XKPGCS4Q-BXMl8H-d.js} +5 -5
- package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-BXMl8H-d.js.map +1 -0
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-MLeCGcYg.js → kanban-definition-3W4ZIXB7-Cc5RwCEh.js} +3 -5
- package/webapp/dist/assets/kanban-definition-3W4ZIXB7-Cc5RwCEh.js.map +1 -0
- package/webapp/dist/assets/{layout-DY9VEQ9M.js → layout-BB2SvQcE.js} +5 -5
- package/webapp/dist/assets/layout-BB2SvQcE.js.map +1 -0
- package/webapp/dist/assets/{linear-D-T1xRsr.js → linear-Cj50lA0a.js} +2 -2
- package/webapp/dist/assets/linear-Cj50lA0a.js.map +1 -0
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CrVm8vj2.js → mindmap-definition-VGOIOE7T-BLBklJVX.js} +5 -7
- package/webapp/dist/assets/mindmap-definition-VGOIOE7T-BLBklJVX.js.map +1 -0
- package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-GtLLV0r1.js → pieDiagram-ADFJNKIX-BQrOgSc-.js} +8 -8
- package/webapp/dist/assets/pieDiagram-ADFJNKIX-BQrOgSc-.js.map +1 -0
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-BCgk_2LP.js → quadrantDiagram-AYHSOK5B-C62TxtsO.js} +3 -3
- package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-C62TxtsO.js.map +1 -0
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DYUKHWKR.js → requirementDiagram-UZGBJVZJ-Is6Q3osM.js} +6 -16
- package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-Is6Q3osM.js.map +1 -0
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CFAH8OaY.js → sankeyDiagram-TZEHDZUN-CCAW8Dr2.js} +2 -2
- package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-CCAW8Dr2.js.map +1 -0
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-BTnhbv6w.js → sequenceDiagram-WL72ISMW-DpODpbl6.js} +201 -601
- package/webapp/dist/assets/sequenceDiagram-WL72ISMW-DpODpbl6.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-DWUnJTwO.js → stateDiagram-FKZM4ZOC-B8LHaf5T.js} +9 -9
- package/webapp/dist/assets/stateDiagram-FKZM4ZOC-B8LHaf5T.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-B-fc52bp.js → stateDiagram-v2-4FDKWEC3-4FzTkpgz.js} +5 -5
- package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3-4FzTkpgz.js.map +1 -0
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-BMZ52QaG.js → timeline-definition-IT6M3QCI-Ckxc4qZe.js} +3 -3
- package/webapp/dist/assets/timeline-definition-IT6M3QCI-Ckxc4qZe.js.map +1 -0
- package/webapp/dist/assets/{treemap-KZPCXAKY-fgSrze0S.js → treemap-GDKQZRPO-QQa4vKMv.js} +24 -37
- package/webapp/dist/assets/treemap-GDKQZRPO-QQa4vKMv.js.map +1 -0
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-D6aviLtC.js → xychartDiagram-PRI3JC2R-Ba2uJcs6.js} +4 -4
- package/webapp/dist/assets/xychartDiagram-PRI3JC2R-Ba2uJcs6.js.map +1 -0
- package/webapp/dist/index.html +2 -2
- package/webapp/dist/assets/_basePickBy-C0MXVhMo.js.map +0 -1
- package/webapp/dist/assets/_baseUniq-CRygl41M.js.map +0 -1
- package/webapp/dist/assets/arc-BeHJtnt2.js.map +0 -1
- package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-CGdo5TVi.js.map +0 -1
- package/webapp/dist/assets/blockDiagram-WCTKOSBZ-C59VaSGw.js.map +0 -1
- package/webapp/dist/assets/c4Diagram-IC4MRINW-B3YCBmTx.js.map +0 -1
- package/webapp/dist/assets/channel-Dn4i8EAY.js.map +0 -1
- package/webapp/dist/assets/chunk-4BX2VUAB-CQbB3HlW.js.map +0 -1
- package/webapp/dist/assets/chunk-55IACEB6-CkQR_Qu9.js.map +0 -1
- package/webapp/dist/assets/chunk-FMBD7UC4-YSIOuaST.js.map +0 -1
- package/webapp/dist/assets/chunk-JSJVCQXG-CWDLRawz.js.map +0 -1
- package/webapp/dist/assets/chunk-KX2RTZJC-DFiwgnFf.js.map +0 -1
- package/webapp/dist/assets/chunk-NQ4KR5QH-DBxY8LL2.js.map +0 -1
- package/webapp/dist/assets/chunk-QZHKN3VN-BAdR6lLc.js.map +0 -1
- package/webapp/dist/assets/chunk-WL4C6EOR-Bjl-j3bf.js.map +0 -1
- package/webapp/dist/assets/classDiagram-VBA2DB6C-KBeS6WXD.js.map +0 -1
- package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-KBeS6WXD.js.map +0 -1
- package/webapp/dist/assets/clone-C7-aS2vm.js.map +0 -1
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-Bo5IsL-5.js.map +0 -1
- package/webapp/dist/assets/dagre-KLK3FWXG-C3FeHj7D.js.map +0 -1
- package/webapp/dist/assets/diagram-E7M64L7V-0HfiRW0u.js.map +0 -1
- package/webapp/dist/assets/diagram-IFDJBPK2-DJwh7SMO.js.map +0 -1
- package/webapp/dist/assets/diagram-P4PSJMXO-Y0RbvUZX.js.map +0 -1
- package/webapp/dist/assets/erDiagram-INFDFZHY-B183xyLa.js.map +0 -1
- package/webapp/dist/assets/flowDiagram-PKNHOUZH-C_BR3Y3J.js.map +0 -1
- package/webapp/dist/assets/ganttDiagram-A5KZAMGK-CHLgkuJT.js.map +0 -1
- package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-D6C_HU1q.js.map +0 -1
- package/webapp/dist/assets/graph-D0hgB-X8.js +0 -782
- package/webapp/dist/assets/graph-D0hgB-X8.js.map +0 -1
- package/webapp/dist/assets/infoDiagram-LFFYTUFH-mnMS61NO.js.map +0 -1
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-XFIJsnJj.js +0 -966
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-XFIJsnJj.js.map +0 -1
- package/webapp/dist/assets/journeyDiagram-4ABVD52K-BdeERn0r.js.map +0 -1
- package/webapp/dist/assets/kanban-definition-K7BYSVSG-MLeCGcYg.js.map +0 -1
- package/webapp/dist/assets/layout-DY9VEQ9M.js.map +0 -1
- package/webapp/dist/assets/linear-D-T1xRsr.js.map +0 -1
- package/webapp/dist/assets/mindmap-definition-YRQLILUH-CrVm8vj2.js.map +0 -1
- package/webapp/dist/assets/pieDiagram-SKSYHLDU-GtLLV0r1.js.map +0 -1
- package/webapp/dist/assets/quadrantDiagram-337W2JSQ-BCgk_2LP.js.map +0 -1
- package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-DYUKHWKR.js.map +0 -1
- package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-CFAH8OaY.js.map +0 -1
- package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-BTnhbv6w.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-RAJIS63D-DWUnJTwO.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-B-fc52bp.js.map +0 -1
- package/webapp/dist/assets/timeline-definition-YZTLITO2-BMZ52QaG.js.map +0 -1
- package/webapp/dist/assets/treemap-KZPCXAKY-fgSrze0S.js.map +0 -1
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-D5DmDY9l.js +0 -2487
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-D5DmDY9l.js.map +0 -1
- package/webapp/dist/assets/xychartDiagram-JWTSCODW-D6aviLtC.js.map +0 -1
|
@@ -7,6 +7,7 @@ const id_1 = require("@longrun-ai/kernel/utils/id");
|
|
|
7
7
|
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
8
8
|
const dialog_1 = require("../../dialog");
|
|
9
9
|
const dialog_display_state_1 = require("../../dialog-display-state");
|
|
10
|
+
const dialog_interruption_1 = require("../../dialog-interruption");
|
|
10
11
|
const evt_registry_1 = require("../../evt-registry");
|
|
11
12
|
const log_1 = require("../../log");
|
|
12
13
|
const load_1 = require("../../minds/load");
|
|
@@ -16,9 +17,12 @@ const reply_prompt_copy_1 = require("../../runtime/reply-prompt-copy");
|
|
|
16
17
|
const work_language_1 = require("../../runtime/work-language");
|
|
17
18
|
const tool_1 = require("../../tool");
|
|
18
19
|
const taskdoc_1 = require("../../utils/taskdoc");
|
|
20
|
+
const api_quirks_1 = require("../api-quirks");
|
|
19
21
|
const client_1 = require("../client");
|
|
22
|
+
const gen_1 = require("../gen");
|
|
20
23
|
const registry_1 = require("../gen/registry");
|
|
21
24
|
const tool_call_context_1 = require("../gen/tool-call-context");
|
|
25
|
+
const stop_reason_i18n_1 = require("../stop-reason-i18n");
|
|
22
26
|
const tools_projection_1 = require("../tools-projection");
|
|
23
27
|
const context_1 = require("./context");
|
|
24
28
|
const context_health_1 = require("./context-health");
|
|
@@ -94,7 +98,17 @@ class KernelDriverInterruptedError extends Error {
|
|
|
94
98
|
}
|
|
95
99
|
}
|
|
96
100
|
function resolveStoppedContinueEnabled(reason) {
|
|
97
|
-
return reason
|
|
101
|
+
return (0, dialog_interruption_1.isInterruptionReasonManualResumeEligible)(reason);
|
|
102
|
+
}
|
|
103
|
+
function buildAbortedSystemStopReason() {
|
|
104
|
+
return {
|
|
105
|
+
kind: 'system_stop',
|
|
106
|
+
detail: 'Aborted.',
|
|
107
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
108
|
+
detail: 'Aborted.',
|
|
109
|
+
kind: 'aborted',
|
|
110
|
+
}),
|
|
111
|
+
};
|
|
98
112
|
}
|
|
99
113
|
function throwIfAborted(abortSignal, dlg) {
|
|
100
114
|
if (!abortSignal?.aborted)
|
|
@@ -106,7 +120,7 @@ function throwIfAborted(abortSignal, dlg) {
|
|
|
106
120
|
if (stopRequested === 'user_stop') {
|
|
107
121
|
throw new KernelDriverInterruptedError({ kind: 'user_stop' });
|
|
108
122
|
}
|
|
109
|
-
throw new KernelDriverInterruptedError(
|
|
123
|
+
throw new KernelDriverInterruptedError(buildAbortedSystemStopReason());
|
|
110
124
|
}
|
|
111
125
|
function isFbrSubdialogDialog(dlg) {
|
|
112
126
|
return dlg instanceof dialog_1.SubDialog && dlg.assignmentFromSup.callName === 'freshBootsReasoning';
|
|
@@ -916,6 +930,7 @@ async function executeFunctionRound(args) {
|
|
|
916
930
|
shouldStopAfterReplyTool: false,
|
|
917
931
|
pairedMessages: [],
|
|
918
932
|
tellaskToolOutputs: [],
|
|
933
|
+
updatePlanOnlyRound: false,
|
|
919
934
|
};
|
|
920
935
|
}
|
|
921
936
|
throwIfAborted(args.abortSignal, args.dlg);
|
|
@@ -959,26 +974,23 @@ async function executeFunctionRound(args) {
|
|
|
959
974
|
}
|
|
960
975
|
return shouldImmediatelyFollowUpToolOutcome(tool, outcome);
|
|
961
976
|
});
|
|
962
|
-
const
|
|
977
|
+
const updatePlanOnlyRound = (() => {
|
|
963
978
|
if (tellaskRound.normalCalls.length === 0) {
|
|
964
|
-
return
|
|
979
|
+
return false;
|
|
965
980
|
}
|
|
966
981
|
if (tellaskRound.handledCallIds.length > 0 || tellaskRound.toolOutputs.length > 0) {
|
|
967
|
-
return
|
|
982
|
+
return false;
|
|
968
983
|
}
|
|
969
|
-
const signatures = [];
|
|
970
984
|
for (const call of tellaskRound.normalCalls) {
|
|
971
985
|
if (call.name !== 'update_plan') {
|
|
972
|
-
return
|
|
986
|
+
return false;
|
|
973
987
|
}
|
|
974
988
|
const outcome = genericOutcomeByCallId.get(call.id);
|
|
975
989
|
if (outcome !== 'success') {
|
|
976
|
-
return
|
|
990
|
+
return false;
|
|
977
991
|
}
|
|
978
|
-
const argsStr = typeof call.arguments === 'string' ? call.arguments : JSON.stringify(call.arguments ?? {});
|
|
979
|
-
signatures.push(argsStr);
|
|
980
992
|
}
|
|
981
|
-
return
|
|
993
|
+
return true;
|
|
982
994
|
})();
|
|
983
995
|
const resultByCallId = new Map();
|
|
984
996
|
const register = (result) => {
|
|
@@ -1028,7 +1040,7 @@ async function executeFunctionRound(args) {
|
|
|
1028
1040
|
shouldStopAfterReplyTool: tellaskRound.shouldStopAfterReplyTool,
|
|
1029
1041
|
pairedMessages,
|
|
1030
1042
|
tellaskToolOutputs: [...tellaskRound.toolOutputs],
|
|
1031
|
-
|
|
1043
|
+
updatePlanOnlyRound,
|
|
1032
1044
|
};
|
|
1033
1045
|
}
|
|
1034
1046
|
async function resetDiligenceBudgetAfterQ4H(dlg, team) {
|
|
@@ -1100,6 +1112,16 @@ async function maybeContinueWithDiligencePrompt(args) {
|
|
|
1100
1112
|
}
|
|
1101
1113
|
return { kind: 'break' };
|
|
1102
1114
|
}
|
|
1115
|
+
async function maybePrepareRetryStoppedRecoveryPrompt(args) {
|
|
1116
|
+
if (args.reason.recoveryAction.kind !== 'diligence_push_once') {
|
|
1117
|
+
return { kind: 'break' };
|
|
1118
|
+
}
|
|
1119
|
+
return await maybeContinueWithDiligencePrompt({
|
|
1120
|
+
dlg: args.dlg,
|
|
1121
|
+
team: args.team,
|
|
1122
|
+
suppressDiligencePushForDrive: args.suppressDiligencePushForDrive,
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1103
1125
|
async function maybeContinueWithHealthPromptBeforeDiligence(args) {
|
|
1104
1126
|
const { dlg, providerCfg, model } = args;
|
|
1105
1127
|
// This path is only used as a higher-priority alternative to Diligence Push.
|
|
@@ -1174,10 +1196,15 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1174
1196
|
let fbrConclusion;
|
|
1175
1197
|
let pubRemindersVer = dlg.remindersVer;
|
|
1176
1198
|
let pendingPrompt = humanPrompt;
|
|
1199
|
+
let retryStoppedRecoveryPrompt;
|
|
1177
1200
|
let skipTaskdocForThisDrive = humanPrompt?.skipTaskdoc === true;
|
|
1178
1201
|
let genIterNo = 0;
|
|
1179
1202
|
let consecutiveIdenticalUpdatePlanOnlyRounds = 0;
|
|
1180
1203
|
let lastIdenticalUpdatePlanRoundSignature;
|
|
1204
|
+
// Quirk retry state intentionally spans multiple request invocations in the same driver run,
|
|
1205
|
+
// including course changes. Provider/API retry heuristics are tracked independently from
|
|
1206
|
+
// user-facing course boundaries.
|
|
1207
|
+
const retryQuirkSessionByProviderModel = new Map();
|
|
1181
1208
|
if (!humanPrompt) {
|
|
1182
1209
|
try {
|
|
1183
1210
|
const executionMarker = await (0, dialog_display_state_1.loadDialogExecutionMarker)(dlg.id, 'running');
|
|
@@ -1193,332 +1220,564 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1193
1220
|
}
|
|
1194
1221
|
await (0, dialog_display_state_1.clearDialogInterruptedExecutionMarker)(dlg.id);
|
|
1195
1222
|
await (0, dialog_display_state_1.setDialogDisplayState)(dlg.id, { kind: 'proceeding' });
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1223
|
+
driveCoreLoop: for (;;) {
|
|
1224
|
+
try {
|
|
1225
|
+
for (;;) {
|
|
1226
|
+
genIterNo += 1;
|
|
1227
|
+
throwIfAborted(abortSignal, dlg);
|
|
1228
|
+
const activeFbrState = await loadDialogFbrState(dlg);
|
|
1229
|
+
if (isFbrSubdialogDialog(dlg)) {
|
|
1230
|
+
dlg.setFbrConclusionToolsEnabled(activeFbrState !== undefined && (0, fbr_1.isFbrFinalizationState)(activeFbrState));
|
|
1231
|
+
if (pendingPrompt === undefined &&
|
|
1232
|
+
activeFbrState &&
|
|
1233
|
+
activeFbrState.promptDelivered !== true) {
|
|
1234
|
+
pendingPrompt = buildKernelDriverFbrPrompt(dlg, activeFbrState);
|
|
1235
|
+
}
|
|
1207
1236
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
language: (0, work_language_1.getWorkLanguage)(),
|
|
1217
|
-
});
|
|
1218
|
-
const policyValidation = (0, guardrails_1.validateKernelDriverPolicyInvariants)(policy, (0, work_language_1.getWorkLanguage)());
|
|
1219
|
-
if (!policyValidation.ok) {
|
|
1220
|
-
throw new Error(`kernel-driver policy invariant violation: ${policyValidation.detail}`);
|
|
1221
|
-
}
|
|
1222
|
-
const agent = policy.effectiveAgent;
|
|
1223
|
-
const systemPrompt = policy.effectiveSystemPrompt;
|
|
1224
|
-
const agentTools = policy.effectiveAgentTools;
|
|
1225
|
-
const provider = agent.provider ?? team.memberDefaults.provider;
|
|
1226
|
-
const model = agent.model ?? team.memberDefaults.model;
|
|
1227
|
-
if (!provider) {
|
|
1228
|
-
throw new Error(`Configuration Error: No provider configured for agent '${dlg.agentId}'. Please specify a provider in the agent's configuration or in member_defaults section of .minds/team.yaml.`);
|
|
1229
|
-
}
|
|
1230
|
-
if (!model) {
|
|
1231
|
-
throw new Error(`Configuration Error: No model configured for agent '${dlg.agentId}'. Please specify a model in the agent's configuration or in member_defaults section of .minds/team.yaml.`);
|
|
1232
|
-
}
|
|
1233
|
-
const llmCfg = await client_1.LlmConfig.load();
|
|
1234
|
-
const providerCfg = llmCfg.getProvider(provider);
|
|
1235
|
-
if (!providerCfg) {
|
|
1236
|
-
throw new Error(`Provider configuration error: Provider '${provider}' not found for agent '${dlg.agentId}'. Please check .minds/llm.yaml and .minds/team.yaml configuration.`);
|
|
1237
|
-
}
|
|
1238
|
-
if (!providerCfg.models || !providerCfg.models[model]) {
|
|
1239
|
-
throw new Error(`Configuration error: invalid model '${model}' for provider '${provider}' (agent='${dlg.agentId}').`);
|
|
1240
|
-
}
|
|
1241
|
-
const llmGen = (0, registry_1.getLlmGenerator)(providerCfg.apiType);
|
|
1242
|
-
if (!llmGen) {
|
|
1243
|
-
throw new Error(`LLM generator not found: API type '${providerCfg.apiType}' for provider '${provider}' in agent '${dlg.agentId}'. Please check .minds/llm.yaml configuration.`);
|
|
1244
|
-
}
|
|
1245
|
-
const retryPolicy = resolveKernelDriverRetryPolicy(providerCfg);
|
|
1246
|
-
const canonicalFuncTools = agentTools.filter((t) => t.type === 'func');
|
|
1247
|
-
const isSubdialog = dlg.id.rootId !== dlg.id.selfId;
|
|
1248
|
-
const fbrEffortDefault = resolveFbrEffortDefaultForTool(agent);
|
|
1249
|
-
const effectiveFuncTools = policy.mode === 'default'
|
|
1250
|
-
? mergeTellaskVirtualTools(canonicalFuncTools, {
|
|
1251
|
-
includeTellaskBack: isSubdialog,
|
|
1252
|
-
fbrEffortDefault,
|
|
1253
|
-
})
|
|
1254
|
-
: canonicalFuncTools;
|
|
1255
|
-
const projected = (0, tools_projection_1.projectFuncToolsForProvider)(providerCfg.apiType, effectiveFuncTools);
|
|
1256
|
-
const funcTools = projected.tools;
|
|
1257
|
-
if (genIterNo > 1) {
|
|
1258
|
-
const snapshot = dlg.getLastContextHealth();
|
|
1259
|
-
const hasQueuedUpNext = dlg.hasUpNext() || pendingPrompt !== undefined;
|
|
1260
|
-
const modelInfoForRemediation = resolveModelInfo(providerCfg, model);
|
|
1261
|
-
const cautionRemediationCadenceGenerations = (0, context_health_1.resolveCautionRemediationCadenceGenerations)(modelInfoForRemediation?.caution_remediation_cadence_generations);
|
|
1262
|
-
const criticalCountdownRemaining = (0, context_health_1.resolveCriticalCountdownRemaining)(dlg.id.key(), snapshot);
|
|
1263
|
-
const healthDecision = (0, context_health_1.decideKernelDriverContextHealth)({
|
|
1264
|
-
dialogKey: dlg.id.key(),
|
|
1265
|
-
snapshot,
|
|
1266
|
-
hadUserPromptThisGen: isUserOriginPrompt(pendingPrompt),
|
|
1267
|
-
canInjectPromptThisGen: !hasQueuedUpNext,
|
|
1268
|
-
cautionRemediationCadenceGenerations,
|
|
1269
|
-
criticalCountdownRemaining,
|
|
1237
|
+
const minds = await (0, load_1.loadAgentMinds)(dlg.agentId, dlg);
|
|
1238
|
+
const team = minds.team;
|
|
1239
|
+
const policy = (0, guardrails_1.buildKernelDriverPolicy)({
|
|
1240
|
+
dlg,
|
|
1241
|
+
agent: minds.agent,
|
|
1242
|
+
systemPrompt: minds.systemPrompt,
|
|
1243
|
+
agentTools: minds.agentTools,
|
|
1244
|
+
language: (0, work_language_1.getWorkLanguage)(),
|
|
1270
1245
|
});
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1246
|
+
const policyValidation = (0, guardrails_1.validateKernelDriverPolicyInvariants)(policy, (0, work_language_1.getWorkLanguage)());
|
|
1247
|
+
if (!policyValidation.ok) {
|
|
1248
|
+
throw new Error(`kernel-driver policy invariant violation: ${policyValidation.detail}`);
|
|
1249
|
+
}
|
|
1250
|
+
const agent = policy.effectiveAgent;
|
|
1251
|
+
const systemPrompt = policy.effectiveSystemPrompt;
|
|
1252
|
+
const agentTools = policy.effectiveAgentTools;
|
|
1253
|
+
const prepareRetryStoppedRecovery = async (reason) => {
|
|
1254
|
+
retryStoppedRecoveryPrompt = undefined;
|
|
1255
|
+
const recovery = await maybePrepareRetryStoppedRecoveryPrompt({
|
|
1256
|
+
dlg,
|
|
1257
|
+
team,
|
|
1258
|
+
suppressDiligencePushForDrive,
|
|
1259
|
+
reason,
|
|
1278
1260
|
});
|
|
1279
|
-
|
|
1261
|
+
if (recovery.kind !== 'continue') {
|
|
1262
|
+
return 'stop';
|
|
1263
|
+
}
|
|
1264
|
+
retryStoppedRecoveryPrompt = recovery.prompt;
|
|
1265
|
+
return 'continue';
|
|
1266
|
+
};
|
|
1267
|
+
const provider = agent.provider ?? team.memberDefaults.provider;
|
|
1268
|
+
const model = agent.model ?? team.memberDefaults.model;
|
|
1269
|
+
if (!provider) {
|
|
1270
|
+
throw new Error(`Configuration Error: No provider configured for agent '${dlg.agentId}'. Please specify a provider in the agent's configuration or in member_defaults section of .minds/team.yaml.`);
|
|
1280
1271
|
}
|
|
1281
|
-
if (
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1272
|
+
if (!model) {
|
|
1273
|
+
throw new Error(`Configuration Error: No model configured for agent '${dlg.agentId}'. Please specify a model in the agent's configuration or in member_defaults section of .minds/team.yaml.`);
|
|
1274
|
+
}
|
|
1275
|
+
const llmCfg = await client_1.LlmConfig.load();
|
|
1276
|
+
const providerCfg = llmCfg.getProvider(provider);
|
|
1277
|
+
if (!providerCfg) {
|
|
1278
|
+
throw new Error(`Provider configuration error: Provider '${provider}' not found for agent '${dlg.agentId}'. Please check .minds/llm.yaml and .minds/team.yaml configuration.`);
|
|
1279
|
+
}
|
|
1280
|
+
if (!providerCfg.models || !providerCfg.models[model]) {
|
|
1281
|
+
throw new Error(`Configuration error: invalid model '${model}' for provider '${provider}' (agent='${dlg.agentId}').`);
|
|
1282
|
+
}
|
|
1283
|
+
const llmGen = (0, registry_1.getLlmGenerator)(providerCfg.apiType);
|
|
1284
|
+
if (!llmGen) {
|
|
1285
|
+
throw new Error(`LLM generator not found: API type '${providerCfg.apiType}' for provider '${provider}' in agent '${dlg.agentId}'. Please check .minds/llm.yaml configuration.`);
|
|
1286
|
+
}
|
|
1287
|
+
const resolveRetryQuirkSession = () => {
|
|
1288
|
+
const key = `${provider}::${model}`;
|
|
1289
|
+
const existing = retryQuirkSessionByProviderModel.get(key);
|
|
1290
|
+
if (existing) {
|
|
1291
|
+
return existing;
|
|
1297
1292
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
|
|
1302
|
-
kind: 'caution',
|
|
1303
|
-
mode: 'soft',
|
|
1304
|
-
})
|
|
1305
|
-
: (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
|
|
1306
|
-
kind: 'critical',
|
|
1307
|
-
mode: 'countdown',
|
|
1308
|
-
promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
|
|
1309
|
-
promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
|
|
1310
|
-
});
|
|
1311
|
-
pendingPrompt = {
|
|
1312
|
-
content: guideText,
|
|
1313
|
-
msgId: (0, id_1.generateShortId)(),
|
|
1314
|
-
grammar: 'markdown',
|
|
1315
|
-
origin: 'runtime',
|
|
1316
|
-
userLanguageCode: language,
|
|
1317
|
-
};
|
|
1293
|
+
const created = (0, api_quirks_1.createLlmFailureQuirkHandlerSession)(providerCfg);
|
|
1294
|
+
if (!created) {
|
|
1295
|
+
return undefined;
|
|
1318
1296
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1297
|
+
retryQuirkSessionByProviderModel.set(key, created);
|
|
1298
|
+
return created;
|
|
1299
|
+
};
|
|
1300
|
+
const retryPolicy = resolveKernelDriverRetryPolicy(providerCfg);
|
|
1301
|
+
const canonicalFuncTools = agentTools.filter((t) => t.type === 'func');
|
|
1302
|
+
const isSubdialog = dlg.id.rootId !== dlg.id.selfId;
|
|
1303
|
+
const fbrEffortDefault = resolveFbrEffortDefaultForTool(agent);
|
|
1304
|
+
const effectiveFuncTools = policy.mode === 'default'
|
|
1305
|
+
? mergeTellaskVirtualTools(canonicalFuncTools, {
|
|
1306
|
+
includeTellaskBack: isSubdialog,
|
|
1307
|
+
fbrEffortDefault,
|
|
1308
|
+
})
|
|
1309
|
+
: canonicalFuncTools;
|
|
1310
|
+
const projected = (0, tools_projection_1.projectFuncToolsForProvider)(providerCfg.apiType, effectiveFuncTools);
|
|
1311
|
+
const funcTools = projected.tools;
|
|
1312
|
+
if (genIterNo > 1) {
|
|
1313
|
+
const snapshot = dlg.getLastContextHealth();
|
|
1314
|
+
const hasQueuedUpNext = dlg.hasUpNext() || pendingPrompt !== undefined;
|
|
1315
|
+
const modelInfoForRemediation = resolveModelInfo(providerCfg, model);
|
|
1316
|
+
const cautionRemediationCadenceGenerations = (0, context_health_1.resolveCautionRemediationCadenceGenerations)(modelInfoForRemediation?.caution_remediation_cadence_generations);
|
|
1317
|
+
const criticalCountdownRemaining = (0, context_health_1.resolveCriticalCountdownRemaining)(dlg.id.key(), snapshot);
|
|
1318
|
+
const healthDecision = (0, context_health_1.decideKernelDriverContextHealth)({
|
|
1319
|
+
dialogKey: dlg.id.key(),
|
|
1320
|
+
snapshot,
|
|
1321
|
+
hadUserPromptThisGen: isUserOriginPrompt(pendingPrompt),
|
|
1322
|
+
canInjectPromptThisGen: !hasQueuedUpNext,
|
|
1323
|
+
cautionRemediationCadenceGenerations,
|
|
1324
|
+
criticalCountdownRemaining,
|
|
1325
|
+
});
|
|
1326
|
+
if (healthDecision.kind === 'suspend') {
|
|
1327
|
+
log_1.log.debug('kernel-driver suspend iterative generation due to critical context while waiting for human prompt', undefined, {
|
|
1338
1328
|
dialogId: dlg.id.valueOf(),
|
|
1339
|
-
|
|
1329
|
+
rootId: dlg.id.rootId,
|
|
1330
|
+
selfId: dlg.id.selfId,
|
|
1331
|
+
genIterNo,
|
|
1332
|
+
pendingPromptOrigin: pendingPrompt?.origin ?? null,
|
|
1340
1333
|
});
|
|
1341
1334
|
break;
|
|
1342
1335
|
}
|
|
1343
|
-
if (
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
if (currentPrompt.origin === 'user' &&
|
|
1360
|
-
replyGuidance.suppressInterDialogReplyGuidance &&
|
|
1361
|
-
replyGuidance.deferredReplyReassertionDirective !== undefined) {
|
|
1362
|
-
const existingDeferredReplyReassertion = await persistence_1.DialogPersistence.getDeferredReplyReassertion(dlg.id, dlg.status);
|
|
1363
|
-
const nextDeferredReplyReassertion = {
|
|
1364
|
-
reason: 'user_interjection_while_pending_subdialog',
|
|
1365
|
-
directive: replyGuidance.deferredReplyReassertionDirective,
|
|
1366
|
-
};
|
|
1367
|
-
if (existingDeferredReplyReassertion === undefined ||
|
|
1368
|
-
!hasSameReplyDirective(existingDeferredReplyReassertion.directive, nextDeferredReplyReassertion.directive)) {
|
|
1369
|
-
await persistence_1.DialogPersistence.setDeferredReplyReassertion(dlg.id, nextDeferredReplyReassertion, dlg.status);
|
|
1336
|
+
if (healthDecision.kind === 'continue') {
|
|
1337
|
+
if (healthDecision.reason === 'critical_force_new_course') {
|
|
1338
|
+
const language = (0, work_language_1.getWorkLanguage)();
|
|
1339
|
+
const newCoursePrompt = (0, driver_messages_1.formatNewCourseStartPrompt)(language, {
|
|
1340
|
+
nextCourse: dlg.currentCourse + 1,
|
|
1341
|
+
source: 'critical_auto_clear',
|
|
1342
|
+
});
|
|
1343
|
+
await dlg.startNewCourse(newCoursePrompt);
|
|
1344
|
+
dlg.setLastContextHealth({ kind: 'unavailable', reason: 'usage_unavailable' });
|
|
1345
|
+
(0, context_health_1.resetContextHealthRoundState)(dlg.id.key());
|
|
1346
|
+
const nextPrompt = resolveUpNextPrompt(dlg);
|
|
1347
|
+
if (!nextPrompt) {
|
|
1348
|
+
throw new Error(`kernel-driver critical force-new-course invariant violation: missing upNext prompt after startNewCourse for dialog=${dlg.id.valueOf()}`);
|
|
1349
|
+
}
|
|
1350
|
+
pendingPrompt = nextPrompt;
|
|
1351
|
+
skipTaskdocForThisDrive = false;
|
|
1370
1352
|
}
|
|
1371
|
-
if (
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
}
|
|
1378
|
-
:
|
|
1353
|
+
else if (!hasQueuedUpNext) {
|
|
1354
|
+
const language = (0, work_language_1.getWorkLanguage)();
|
|
1355
|
+
const guideText = healthDecision.reason === 'caution_soft_remediation'
|
|
1356
|
+
? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
|
|
1357
|
+
kind: 'caution',
|
|
1358
|
+
mode: 'soft',
|
|
1359
|
+
})
|
|
1360
|
+
: (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
|
|
1361
|
+
kind: 'critical',
|
|
1362
|
+
mode: 'countdown',
|
|
1363
|
+
promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
|
|
1364
|
+
promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
|
|
1365
|
+
});
|
|
1366
|
+
pendingPrompt = {
|
|
1367
|
+
content: guideText,
|
|
1368
|
+
msgId: (0, id_1.generateShortId)(),
|
|
1369
|
+
grammar: 'markdown',
|
|
1370
|
+
origin: 'runtime',
|
|
1371
|
+
userLanguageCode: language,
|
|
1372
|
+
};
|
|
1379
1373
|
}
|
|
1380
1374
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
if (
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
else {
|
|
1420
|
-
await dlg.addChatMessages({
|
|
1421
|
-
type: 'prompting_msg',
|
|
1422
|
-
role: 'user',
|
|
1423
|
-
genseq: dlg.activeGenSeq,
|
|
1424
|
-
msgId: currentPrompt.msgId,
|
|
1425
|
-
grammar: 'markdown',
|
|
1426
|
-
content: replyGuidance.promptContent,
|
|
1427
|
-
});
|
|
1428
|
-
await dlg.persistUserMessage(replyGuidance.promptContent, currentPrompt.msgId, 'markdown', origin, persistedUserLanguageCode, q4hAnswerCallId, replyGuidance.persistedTellaskReplyDirective);
|
|
1429
|
-
}
|
|
1430
|
-
if (renderPromptAsRuntimeGuideBubble) {
|
|
1431
|
-
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1432
|
-
type: 'runtime_guide_evt',
|
|
1433
|
-
course: dlg.currentCourse,
|
|
1434
|
-
genseq: dlg.activeGenSeq,
|
|
1435
|
-
content: replyGuidance.promptContent,
|
|
1436
|
-
});
|
|
1437
|
-
}
|
|
1438
|
-
else if (!isQ4HAnswerPrompt) {
|
|
1439
|
-
// Emit the live user-side boundary event for UI generation bubbles.
|
|
1440
|
-
// Without this, realtime turns can miss user content + divider (<hr/>).
|
|
1441
|
-
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1442
|
-
type: 'end_of_user_saying_evt',
|
|
1443
|
-
course: dlg.currentCourse,
|
|
1444
|
-
genseq: dlg.activeGenSeq,
|
|
1445
|
-
msgId: currentPrompt.msgId,
|
|
1446
|
-
content: replyGuidance.promptContent,
|
|
1447
|
-
grammar: 'markdown',
|
|
1448
|
-
origin,
|
|
1449
|
-
userLanguageCode: persistedUserLanguageCode,
|
|
1450
|
-
q4hAnswerCallId,
|
|
1375
|
+
}
|
|
1376
|
+
let contextHealthForGen;
|
|
1377
|
+
let llmGenModelForGen = model;
|
|
1378
|
+
const currentPrompt = pendingPrompt;
|
|
1379
|
+
const currentReplyTarget = currentPrompt?.subdialogReplyTarget;
|
|
1380
|
+
const currentFbrState = await loadDialogFbrState(dlg);
|
|
1381
|
+
let currentRuntimeGuideMsg;
|
|
1382
|
+
const currentPromptFromFbrState = currentPrompt !== undefined &&
|
|
1383
|
+
currentFbrState !== undefined &&
|
|
1384
|
+
currentFbrState.promptDelivered !== true;
|
|
1385
|
+
pendingPrompt = undefined;
|
|
1386
|
+
await dlg.notifyGeneratingStart(currentPrompt?.msgId);
|
|
1387
|
+
try {
|
|
1388
|
+
if (currentPrompt) {
|
|
1389
|
+
const origin = currentPrompt.origin;
|
|
1390
|
+
if (origin === 'diligence_push' &&
|
|
1391
|
+
(dlg.disableDiligencePush || suppressDiligencePushForDrive)) {
|
|
1392
|
+
log_1.log.debug('kernel-driver skip diligence prompt after disable toggle', undefined, {
|
|
1393
|
+
dialogId: dlg.id.valueOf(),
|
|
1394
|
+
msgId: currentPrompt.msgId,
|
|
1395
|
+
});
|
|
1396
|
+
break;
|
|
1397
|
+
}
|
|
1398
|
+
if (currentPrompt.skipTaskdoc === true) {
|
|
1399
|
+
skipTaskdocForThisDrive = true;
|
|
1400
|
+
}
|
|
1401
|
+
const persistedUserLanguageCode = currentPrompt.userLanguageCode ?? dlg.getLastUserLanguageCode();
|
|
1402
|
+
const q4hAnswerCallId = normalizeQ4HAnswerCallId(currentPrompt.q4hAnswerCallId);
|
|
1403
|
+
// `q4hAnswerCallId` marks a continuation input for an already-materialized askHuman
|
|
1404
|
+
// answer. It is not a second business-level user prompt that should re-enter transcript.
|
|
1405
|
+
const isQ4HAnswerPrompt = q4hAnswerCallId !== undefined;
|
|
1406
|
+
const promptLanguage = persistedUserLanguageCode === 'zh' || persistedUserLanguageCode === 'en'
|
|
1407
|
+
? persistedUserLanguageCode
|
|
1408
|
+
: (0, work_language_1.getWorkLanguage)();
|
|
1409
|
+
const replyGuidance = await (0, reply_guidance_1.resolvePromptReplyGuidance)({
|
|
1410
|
+
dlg,
|
|
1411
|
+
prompt: currentPrompt,
|
|
1412
|
+
language: promptLanguage,
|
|
1451
1413
|
});
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1414
|
+
if (currentPrompt.origin === 'user' &&
|
|
1415
|
+
replyGuidance.suppressInterDialogReplyGuidance &&
|
|
1416
|
+
replyGuidance.deferredReplyReassertionDirective !== undefined) {
|
|
1417
|
+
const existingDeferredReplyReassertion = await persistence_1.DialogPersistence.getDeferredReplyReassertion(dlg.id, dlg.status);
|
|
1418
|
+
const nextDeferredReplyReassertion = {
|
|
1419
|
+
reason: 'user_interjection_while_pending_subdialog',
|
|
1420
|
+
directive: replyGuidance.deferredReplyReassertionDirective,
|
|
1421
|
+
};
|
|
1422
|
+
if (existingDeferredReplyReassertion === undefined ||
|
|
1423
|
+
!hasSameReplyDirective(existingDeferredReplyReassertion.directive, nextDeferredReplyReassertion.directive)) {
|
|
1424
|
+
await persistence_1.DialogPersistence.setDeferredReplyReassertion(dlg.id, nextDeferredReplyReassertion, dlg.status);
|
|
1425
|
+
}
|
|
1426
|
+
if (existingDeferredReplyReassertion === undefined) {
|
|
1427
|
+
currentRuntimeGuideMsg = replyGuidance.transientGuideContent
|
|
1428
|
+
? {
|
|
1429
|
+
type: 'transient_guide_msg',
|
|
1430
|
+
role: 'assistant',
|
|
1431
|
+
content: replyGuidance.transientGuideContent,
|
|
1432
|
+
}
|
|
1433
|
+
: undefined;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
else if (currentPrompt.origin === 'user' &&
|
|
1437
|
+
!replyGuidance.suppressInterDialogReplyGuidance) {
|
|
1438
|
+
await persistence_1.DialogPersistence.setDeferredReplyReassertion(dlg.id, undefined, dlg.status);
|
|
1439
|
+
}
|
|
1440
|
+
if (!replyGuidance.suppressInterDialogReplyGuidance &&
|
|
1441
|
+
!currentRuntimeGuideMsg &&
|
|
1442
|
+
replyGuidance.transientGuideContent) {
|
|
1443
|
+
currentRuntimeGuideMsg = {
|
|
1444
|
+
type: 'transient_guide_msg',
|
|
1445
|
+
role: 'assistant',
|
|
1446
|
+
content: replyGuidance.transientGuideContent,
|
|
1447
|
+
};
|
|
1448
|
+
}
|
|
1449
|
+
if (replyGuidance.promptContent === undefined) {
|
|
1450
|
+
throw new Error(`kernel-driver reply guidance invariant violation: missing prompt content for dialog=${dlg.id.valueOf()} msgId=${currentPrompt.msgId}`);
|
|
1451
|
+
}
|
|
1452
|
+
const renderPromptAsRuntimeGuideBubble = origin === 'runtime' &&
|
|
1453
|
+
(0, reply_prompt_copy_1.isStandaloneRuntimeGuidePromptContent)(replyGuidance.promptContent);
|
|
1454
|
+
if (currentRuntimeGuideMsg) {
|
|
1455
|
+
await dlg.addChatMessages(currentRuntimeGuideMsg);
|
|
1456
|
+
await persistence_1.DialogPersistence.persistRuntimeGuide(dlg, currentRuntimeGuideMsg.content, dlg.activeGenSeq);
|
|
1457
|
+
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1458
|
+
type: 'runtime_guide_evt',
|
|
1459
|
+
course: dlg.currentCourse,
|
|
1460
|
+
genseq: dlg.activeGenSeq,
|
|
1461
|
+
content: currentRuntimeGuideMsg.content,
|
|
1462
|
+
});
|
|
1463
|
+
currentRuntimeGuideMsg = undefined;
|
|
1464
|
+
}
|
|
1465
|
+
if (isQ4HAnswerPrompt) {
|
|
1466
|
+
// Record only the answered call correlation / user language for the resumed round.
|
|
1467
|
+
// The actual human answer fact was already persisted via askHuman tellask result flow.
|
|
1468
|
+
await dlg.receiveHumanReply({
|
|
1469
|
+
content: replyGuidance.promptContent,
|
|
1470
|
+
userLanguageCode: persistedUserLanguageCode,
|
|
1471
|
+
q4hAnswerCallId,
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
else {
|
|
1475
|
+
await dlg.addChatMessages({
|
|
1476
|
+
type: 'prompting_msg',
|
|
1477
|
+
role: 'user',
|
|
1478
|
+
genseq: dlg.activeGenSeq,
|
|
1479
|
+
msgId: currentPrompt.msgId,
|
|
1480
|
+
grammar: 'markdown',
|
|
1481
|
+
content: replyGuidance.promptContent,
|
|
1482
|
+
});
|
|
1483
|
+
await dlg.persistUserMessage(replyGuidance.promptContent, currentPrompt.msgId, 'markdown', origin, persistedUserLanguageCode, q4hAnswerCallId, replyGuidance.persistedTellaskReplyDirective);
|
|
1484
|
+
}
|
|
1485
|
+
if (renderPromptAsRuntimeGuideBubble) {
|
|
1486
|
+
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1487
|
+
type: 'runtime_guide_evt',
|
|
1488
|
+
course: dlg.currentCourse,
|
|
1489
|
+
genseq: dlg.activeGenSeq,
|
|
1490
|
+
content: replyGuidance.promptContent,
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
else if (!isQ4HAnswerPrompt) {
|
|
1494
|
+
// Emit the live user-side boundary event for UI generation bubbles.
|
|
1495
|
+
// Without this, realtime turns can miss user content + divider (<hr/>).
|
|
1496
|
+
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1497
|
+
type: 'end_of_user_saying_evt',
|
|
1498
|
+
course: dlg.currentCourse,
|
|
1499
|
+
genseq: dlg.activeGenSeq,
|
|
1500
|
+
msgId: currentPrompt.msgId,
|
|
1501
|
+
content: replyGuidance.promptContent,
|
|
1502
|
+
grammar: 'markdown',
|
|
1503
|
+
origin,
|
|
1504
|
+
userLanguageCode: persistedUserLanguageCode,
|
|
1505
|
+
q4hAnswerCallId,
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
if (currentPromptFromFbrState && currentFbrState) {
|
|
1509
|
+
await persistDialogFbrState(dlg, (0, fbr_1.markFbrPromptDelivered)(currentFbrState));
|
|
1510
|
+
}
|
|
1511
|
+
// Ideal: provider SDKs should support a dedicated role='environment' for runtime
|
|
1512
|
+
// metadata. Today, most providers only accept user/assistant (and tool as a special
|
|
1513
|
+
// case), so Dominds must project environment/system-like content as role='user'.
|
|
1514
|
+
const replyTarget = currentPrompt.subdialogReplyTarget;
|
|
1515
|
+
if (replyTarget) {
|
|
1516
|
+
const normalizedCallId = replyTarget.callId.trim();
|
|
1517
|
+
if (normalizedCallId === '') {
|
|
1518
|
+
throw new Error(`kernel-driver assignment anchor invariant violation: empty callId (dialog=${dlg.id.valueOf()})`);
|
|
1519
|
+
}
|
|
1520
|
+
const record = {
|
|
1521
|
+
ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
1522
|
+
type: 'tellask_call_anchor_record',
|
|
1523
|
+
anchorRole: 'assignment',
|
|
1524
|
+
callId: normalizedCallId,
|
|
1525
|
+
genseq: dlg.activeGenSeq,
|
|
1526
|
+
...(0, storage_1.toRootGenerationAnchor)({
|
|
1527
|
+
rootCourse: (dlg instanceof dialog_1.SubDialog ? dlg.rootDialog : dlg).currentCourse,
|
|
1528
|
+
rootGenseq: (dlg instanceof dialog_1.SubDialog ? dlg.rootDialog : dlg).activeGenSeqOrUndefined ?? 0,
|
|
1529
|
+
}),
|
|
1530
|
+
};
|
|
1531
|
+
const course = dlg.activeGenCourseOrUndefined ?? dlg.currentCourse;
|
|
1532
|
+
await persistence_1.DialogPersistence.appendEvent(dlg.id, course, record, dlg.status);
|
|
1464
1533
|
}
|
|
1465
|
-
const record = {
|
|
1466
|
-
ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
1467
|
-
type: 'tellask_call_anchor_record',
|
|
1468
|
-
anchorRole: 'assignment',
|
|
1469
|
-
callId: normalizedCallId,
|
|
1470
|
-
genseq: dlg.activeGenSeq,
|
|
1471
|
-
...(0, storage_1.toRootGenerationAnchor)({
|
|
1472
|
-
rootCourse: (dlg instanceof dialog_1.SubDialog ? dlg.rootDialog : dlg).currentCourse,
|
|
1473
|
-
rootGenseq: (dlg instanceof dialog_1.SubDialog ? dlg.rootDialog : dlg).activeGenSeqOrUndefined ?? 0,
|
|
1474
|
-
}),
|
|
1475
|
-
};
|
|
1476
|
-
const course = dlg.activeGenCourseOrUndefined ?? dlg.currentCourse;
|
|
1477
|
-
await persistence_1.DialogPersistence.appendEvent(dlg.id, course, record, dlg.status);
|
|
1478
1534
|
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1535
|
+
await dlg.processReminderUpdates();
|
|
1536
|
+
pubRemindersVer = dlg.remindersVer;
|
|
1537
|
+
const taskDocMsg = dlg.taskDocPath && !skipTaskdocForThisDrive
|
|
1538
|
+
? await (0, taskdoc_1.formatTaskDocContent)(dlg)
|
|
1539
|
+
: undefined;
|
|
1540
|
+
const renderedReminders = await renderRemindersForContext(dlg);
|
|
1541
|
+
const ctxMsgs = (0, context_1.assembleDriveContextMessages)({
|
|
1542
|
+
base: {
|
|
1543
|
+
prependedContextMessages: policy.prependedContextMessages,
|
|
1544
|
+
memories: minds.memories,
|
|
1545
|
+
taskDocMsg,
|
|
1546
|
+
coursePrefixMsgs: dlg.getCoursePrefixMsgs(),
|
|
1547
|
+
dialogMsgsForContext: await buildDialogMsgsForContext(dlg),
|
|
1548
|
+
},
|
|
1549
|
+
ephemeral: {
|
|
1550
|
+
runtimeGuideMsgs: currentRuntimeGuideMsg ? [currentRuntimeGuideMsg] : undefined,
|
|
1551
|
+
},
|
|
1552
|
+
tail: { renderedReminders },
|
|
1553
|
+
});
|
|
1554
|
+
const newMsgs = [];
|
|
1555
|
+
const streamedFuncCalls = [];
|
|
1556
|
+
let sawWebSearchSideChannelOutput = false;
|
|
1557
|
+
let sawNativeToolSideChannelOutput = false;
|
|
1558
|
+
const streamOrBatch = async () => {
|
|
1559
|
+
let batchAttemptCourse;
|
|
1560
|
+
let batchAttemptCheckpointOffset;
|
|
1561
|
+
const rollbackBatchAttempt = async () => {
|
|
1562
|
+
if (batchAttemptCourse === undefined || batchAttemptCheckpointOffset === undefined) {
|
|
1563
|
+
throw new Error(`kernel-driver batch retry invariant violation: missing checkpoint (dialog=${dlg.id.valueOf()})`);
|
|
1564
|
+
}
|
|
1565
|
+
await persistence_1.DialogPersistence.rollbackCourseFileToOffset(dlg.id, batchAttemptCourse, batchAttemptCheckpointOffset, dlg.status);
|
|
1566
|
+
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1567
|
+
type: 'genseq_discard_evt',
|
|
1568
|
+
course: batchAttemptCourse,
|
|
1569
|
+
genseq: dlg.activeGenSeq,
|
|
1570
|
+
reason: 'retry',
|
|
1571
|
+
});
|
|
1572
|
+
sawWebSearchSideChannelOutput = false;
|
|
1573
|
+
sawNativeToolSideChannelOutput = false;
|
|
1574
|
+
streamedFuncCalls.length = 0;
|
|
1575
|
+
newMsgs.length = 0;
|
|
1576
|
+
};
|
|
1577
|
+
if (agent.streaming === false) {
|
|
1578
|
+
const batch = await (0, runtime_1.runLlmRequestWithRetry)({
|
|
1579
|
+
dlg,
|
|
1580
|
+
provider,
|
|
1581
|
+
modelId: model,
|
|
1582
|
+
providerConfig: providerCfg,
|
|
1583
|
+
abortSignal,
|
|
1584
|
+
maxRetries: retryPolicy.maxRetries,
|
|
1585
|
+
retryInitialDelayMs: retryPolicy.initialDelayMs,
|
|
1586
|
+
retryConservativeDelayMs: retryPolicy.conservativeDelayMs,
|
|
1587
|
+
retryBackoffMultiplier: retryPolicy.backoffMultiplier,
|
|
1588
|
+
retryMaxDelayMs: retryPolicy.maxDelayMs,
|
|
1589
|
+
classifyFailure: llmGen.classifyFailure?.bind(llmGen),
|
|
1590
|
+
quirkFailureHandlerSession: resolveRetryQuirkSession(),
|
|
1591
|
+
canRetry: () => true,
|
|
1592
|
+
onRetry: rollbackBatchAttempt,
|
|
1593
|
+
onGiveUp: rollbackBatchAttempt,
|
|
1594
|
+
onRetryStopped: prepareRetryStoppedRecovery,
|
|
1595
|
+
doRequest: async () => {
|
|
1596
|
+
batchAttemptCourse = dlg.activeGenCourseOrUndefined ?? dlg.currentCourse;
|
|
1597
|
+
batchAttemptCheckpointOffset = await persistence_1.DialogPersistence.captureCourseFileOffset(dlg.id, batchAttemptCourse, dlg.status);
|
|
1598
|
+
sawWebSearchSideChannelOutput = false;
|
|
1599
|
+
sawNativeToolSideChannelOutput = false;
|
|
1600
|
+
streamedFuncCalls.length = 0;
|
|
1601
|
+
newMsgs.length = 0;
|
|
1602
|
+
const batchResult = await llmGen.genMoreMessages(providerCfg, agent, systemPrompt, funcTools, {
|
|
1603
|
+
dialogSelfId: dlg.id.selfId,
|
|
1604
|
+
dialogRootId: dlg.id.rootId,
|
|
1605
|
+
promptCacheKey: `${dlg.id.selfId}:c${String(dlg.currentCourse)}`,
|
|
1606
|
+
}, ctxMsgs, dlg.activeGenSeq, abortSignal);
|
|
1607
|
+
if (!hasMeaningfulBatchOutput(batchResult)) {
|
|
1608
|
+
throw {
|
|
1609
|
+
status: 503,
|
|
1610
|
+
code: KERNEL_DRIVER_EMPTY_LLM_RESPONSE_ERROR_CODE,
|
|
1611
|
+
message: `LLM returned empty response (provider=${provider}, model=${model}, streaming=false).`,
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
return batchResult;
|
|
1615
|
+
},
|
|
1616
|
+
});
|
|
1617
|
+
return {
|
|
1618
|
+
usage: batch.usage,
|
|
1619
|
+
llmGenModel: batch.llmGenModel,
|
|
1620
|
+
batchMessages: batch.messages,
|
|
1621
|
+
batchOutputs: batch.outputs,
|
|
1622
|
+
};
|
|
1507
1623
|
}
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1624
|
+
let currentSayingContent = '';
|
|
1625
|
+
let currentThinkingContent = '';
|
|
1626
|
+
let currentThinkingReasoning = undefined;
|
|
1627
|
+
let streamAttemptCourse;
|
|
1628
|
+
let streamAttemptCheckpointOffset;
|
|
1629
|
+
let streamAttemptSayingContent;
|
|
1630
|
+
let streamAttemptSayingGenseq;
|
|
1631
|
+
let streamActive = { kind: 'idle' };
|
|
1632
|
+
const rollbackStreamAttempt = async () => {
|
|
1633
|
+
if (streamAttemptCourse === undefined ||
|
|
1634
|
+
streamAttemptCheckpointOffset === undefined) {
|
|
1635
|
+
throw new Error(`kernel-driver stream retry invariant violation: missing checkpoint (dialog=${dlg.id.valueOf()})`);
|
|
1636
|
+
}
|
|
1637
|
+
await persistence_1.DialogPersistence.rollbackCourseFileToOffset(dlg.id, streamAttemptCourse, streamAttemptCheckpointOffset, dlg.status);
|
|
1638
|
+
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1639
|
+
type: 'genseq_discard_evt',
|
|
1640
|
+
course: streamAttemptCourse,
|
|
1641
|
+
genseq: dlg.activeGenSeq,
|
|
1642
|
+
reason: 'retry',
|
|
1643
|
+
});
|
|
1644
|
+
streamActive = { kind: 'idle' };
|
|
1645
|
+
currentThinkingContent = '';
|
|
1646
|
+
currentThinkingReasoning = undefined;
|
|
1647
|
+
currentSayingContent = '';
|
|
1648
|
+
streamAttemptSayingContent = undefined;
|
|
1649
|
+
streamAttemptSayingGenseq = undefined;
|
|
1650
|
+
sawWebSearchSideChannelOutput = false;
|
|
1651
|
+
sawNativeToolSideChannelOutput = false;
|
|
1652
|
+
streamedFuncCalls.length = 0;
|
|
1653
|
+
newMsgs.length = 0;
|
|
1654
|
+
};
|
|
1655
|
+
const receiver = {
|
|
1656
|
+
streamError: async (detail) => {
|
|
1657
|
+
await dlg.streamError(detail);
|
|
1658
|
+
},
|
|
1659
|
+
thinkingStart: async () => {
|
|
1660
|
+
throwIfAborted(abortSignal, dlg);
|
|
1661
|
+
if (streamActive.kind !== 'idle') {
|
|
1662
|
+
const detail = `Protocol violation: thinkingStart while ${streamActive.kind} is active`;
|
|
1663
|
+
await dlg.streamError(detail);
|
|
1664
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
1665
|
+
detail,
|
|
1666
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
1667
|
+
detail,
|
|
1668
|
+
kind: 'conflicting_stream',
|
|
1669
|
+
}),
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
streamActive = { kind: 'thinking' };
|
|
1673
|
+
currentThinkingContent = '';
|
|
1674
|
+
currentThinkingReasoning = undefined;
|
|
1675
|
+
await dlg.thinkingStart();
|
|
1676
|
+
},
|
|
1677
|
+
thinkingChunk: async (chunk) => {
|
|
1678
|
+
throwIfAborted(abortSignal, dlg);
|
|
1679
|
+
currentThinkingContent += chunk;
|
|
1680
|
+
await dlg.thinkingChunk(chunk);
|
|
1681
|
+
},
|
|
1682
|
+
thinkingFinish: async (reasoning) => {
|
|
1683
|
+
throwIfAborted(abortSignal, dlg);
|
|
1684
|
+
if (streamActive.kind !== 'thinking') {
|
|
1685
|
+
const detail = `Protocol violation: thinkingFinish while ${streamActive.kind} is active`;
|
|
1686
|
+
await dlg.streamError(detail);
|
|
1687
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
1688
|
+
detail,
|
|
1689
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
1690
|
+
detail,
|
|
1691
|
+
kind: 'conflicting_stream',
|
|
1692
|
+
}),
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
streamActive = { kind: 'idle' };
|
|
1696
|
+
if (reasoning)
|
|
1697
|
+
currentThinkingReasoning = reasoning;
|
|
1698
|
+
await dlg.thinkingFinish(reasoning);
|
|
1699
|
+
if (currentThinkingContent.length > 0 || currentThinkingReasoning !== undefined) {
|
|
1700
|
+
newMsgs.push({
|
|
1701
|
+
type: 'thinking_msg',
|
|
1702
|
+
role: 'assistant',
|
|
1703
|
+
genseq: dlg.activeGenSeq,
|
|
1704
|
+
content: currentThinkingContent,
|
|
1705
|
+
reasoning: currentThinkingReasoning,
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
currentThinkingContent = '';
|
|
1709
|
+
currentThinkingReasoning = undefined;
|
|
1710
|
+
},
|
|
1711
|
+
sayingStart: async () => {
|
|
1712
|
+
throwIfAborted(abortSignal, dlg);
|
|
1713
|
+
if (streamActive.kind !== 'idle') {
|
|
1714
|
+
const detail = `Protocol violation: sayingStart while ${streamActive.kind} is active`;
|
|
1715
|
+
await dlg.streamError(detail);
|
|
1716
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
1717
|
+
detail,
|
|
1718
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
1719
|
+
detail,
|
|
1720
|
+
kind: 'conflicting_stream',
|
|
1721
|
+
}),
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
streamActive = { kind: 'saying' };
|
|
1725
|
+
currentSayingContent = '';
|
|
1726
|
+
await dlg.sayingStart();
|
|
1727
|
+
},
|
|
1728
|
+
sayingChunk: async (chunk) => {
|
|
1729
|
+
throwIfAborted(abortSignal, dlg);
|
|
1730
|
+
currentSayingContent += chunk;
|
|
1731
|
+
await dlg.sayingChunk(chunk);
|
|
1732
|
+
},
|
|
1733
|
+
sayingFinish: async () => {
|
|
1734
|
+
throwIfAborted(abortSignal, dlg);
|
|
1735
|
+
if (streamActive.kind !== 'saying') {
|
|
1736
|
+
const detail = `Protocol violation: sayingFinish while ${streamActive.kind} is active`;
|
|
1737
|
+
await dlg.streamError(detail);
|
|
1738
|
+
throw new gen_1.LlmStreamErrorEmittedError({
|
|
1739
|
+
detail,
|
|
1740
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
1741
|
+
detail,
|
|
1742
|
+
kind: 'conflicting_stream',
|
|
1743
|
+
}),
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
streamActive = { kind: 'idle' };
|
|
1747
|
+
await dlg.sayingFinish();
|
|
1748
|
+
const sayingMessage = {
|
|
1749
|
+
type: 'saying_msg',
|
|
1750
|
+
role: 'assistant',
|
|
1751
|
+
genseq: dlg.activeGenSeq,
|
|
1752
|
+
content: currentSayingContent,
|
|
1753
|
+
};
|
|
1754
|
+
newMsgs.push(sayingMessage);
|
|
1755
|
+
streamAttemptSayingContent = currentSayingContent;
|
|
1756
|
+
streamAttemptSayingGenseq = sayingMessage.genseq;
|
|
1757
|
+
},
|
|
1758
|
+
funcCall: async (callId, name, argsStr) => {
|
|
1759
|
+
throwIfAborted(abortSignal, dlg);
|
|
1760
|
+
streamedFuncCalls.push({
|
|
1761
|
+
type: 'func_call_msg',
|
|
1762
|
+
role: 'assistant',
|
|
1763
|
+
genseq: dlg.activeGenSeq,
|
|
1764
|
+
id: callId,
|
|
1765
|
+
name,
|
|
1766
|
+
arguments: argsStr,
|
|
1767
|
+
});
|
|
1768
|
+
},
|
|
1769
|
+
webSearchCall: async (call) => {
|
|
1770
|
+
throwIfAborted(abortSignal, dlg);
|
|
1771
|
+
sawWebSearchSideChannelOutput = true;
|
|
1772
|
+
await dlg.webSearchCall(projectLlmWebSearchCall(call));
|
|
1773
|
+
},
|
|
1774
|
+
nativeToolCall: async (call) => {
|
|
1775
|
+
throwIfAborted(abortSignal, dlg);
|
|
1776
|
+
sawNativeToolSideChannelOutput = true;
|
|
1777
|
+
await dlg.nativeToolCall(call);
|
|
1778
|
+
},
|
|
1779
|
+
};
|
|
1780
|
+
const res = await (0, runtime_1.runLlmRequestWithRetry)({
|
|
1522
1781
|
dlg,
|
|
1523
1782
|
provider,
|
|
1524
1783
|
modelId: model,
|
|
@@ -1530,620 +1789,489 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
|
|
|
1530
1789
|
retryBackoffMultiplier: retryPolicy.backoffMultiplier,
|
|
1531
1790
|
retryMaxDelayMs: retryPolicy.maxDelayMs,
|
|
1532
1791
|
classifyFailure: llmGen.classifyFailure?.bind(llmGen),
|
|
1792
|
+
quirkFailureHandlerSession: resolveRetryQuirkSession(),
|
|
1533
1793
|
canRetry: () => true,
|
|
1534
|
-
onRetry:
|
|
1535
|
-
onGiveUp:
|
|
1794
|
+
onRetry: rollbackStreamAttempt,
|
|
1795
|
+
onGiveUp: rollbackStreamAttempt,
|
|
1796
|
+
onRetryStopped: prepareRetryStoppedRecovery,
|
|
1536
1797
|
doRequest: async () => {
|
|
1537
|
-
|
|
1538
|
-
|
|
1798
|
+
streamAttemptCourse = dlg.activeGenCourseOrUndefined ?? dlg.currentCourse;
|
|
1799
|
+
streamAttemptCheckpointOffset = await persistence_1.DialogPersistence.captureCourseFileOffset(dlg.id, streamAttemptCourse, dlg.status);
|
|
1800
|
+
streamActive = { kind: 'idle' };
|
|
1801
|
+
currentThinkingContent = '';
|
|
1802
|
+
currentThinkingReasoning = undefined;
|
|
1803
|
+
currentSayingContent = '';
|
|
1804
|
+
streamAttemptSayingContent = undefined;
|
|
1805
|
+
streamAttemptSayingGenseq = undefined;
|
|
1539
1806
|
sawWebSearchSideChannelOutput = false;
|
|
1540
1807
|
sawNativeToolSideChannelOutput = false;
|
|
1541
1808
|
streamedFuncCalls.length = 0;
|
|
1542
1809
|
newMsgs.length = 0;
|
|
1543
|
-
const
|
|
1810
|
+
const streamResult = await llmGen.genToReceiver(providerCfg, agent, systemPrompt, funcTools, {
|
|
1544
1811
|
dialogSelfId: dlg.id.selfId,
|
|
1545
1812
|
dialogRootId: dlg.id.rootId,
|
|
1546
1813
|
promptCacheKey: `${dlg.id.selfId}:c${String(dlg.currentCourse)}`,
|
|
1547
|
-
}, ctxMsgs, dlg.activeGenSeq, abortSignal);
|
|
1548
|
-
|
|
1814
|
+
}, ctxMsgs, receiver, dlg.activeGenSeq, abortSignal);
|
|
1815
|
+
const hasThinkingContent = currentThinkingContent.trim() !== '';
|
|
1816
|
+
const hasSayingContent = (streamAttemptSayingContent ?? '').trim() !== '';
|
|
1817
|
+
const hasFunctionCall = streamedFuncCalls.length > 0;
|
|
1818
|
+
if (!hasThinkingContent &&
|
|
1819
|
+
!hasSayingContent &&
|
|
1820
|
+
!hasFunctionCall &&
|
|
1821
|
+
!sawWebSearchSideChannelOutput &&
|
|
1822
|
+
!sawNativeToolSideChannelOutput) {
|
|
1549
1823
|
throw {
|
|
1550
1824
|
status: 503,
|
|
1551
1825
|
code: KERNEL_DRIVER_EMPTY_LLM_RESPONSE_ERROR_CODE,
|
|
1552
|
-
message: `LLM returned empty response (provider=${provider}, model=${model}, streaming=
|
|
1826
|
+
message: `LLM returned empty response (provider=${provider}, model=${model}, streaming=true).`,
|
|
1553
1827
|
};
|
|
1554
1828
|
}
|
|
1555
|
-
return
|
|
1829
|
+
return streamResult;
|
|
1556
1830
|
},
|
|
1557
1831
|
});
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
};
|
|
1564
|
-
}
|
|
1565
|
-
let currentSayingContent = '';
|
|
1566
|
-
let currentThinkingContent = '';
|
|
1567
|
-
let currentThinkingReasoning = undefined;
|
|
1568
|
-
let streamAttemptCourse;
|
|
1569
|
-
let streamAttemptCheckpointOffset;
|
|
1570
|
-
let streamAttemptSayingContent;
|
|
1571
|
-
let streamAttemptSayingGenseq;
|
|
1572
|
-
let streamActive = { kind: 'idle' };
|
|
1573
|
-
const rollbackStreamAttempt = async () => {
|
|
1574
|
-
if (streamAttemptCourse === undefined || streamAttemptCheckpointOffset === undefined) {
|
|
1575
|
-
throw new Error(`kernel-driver stream retry invariant violation: missing checkpoint (dialog=${dlg.id.valueOf()})`);
|
|
1832
|
+
if (streamAttemptSayingContent !== undefined) {
|
|
1833
|
+
lastAssistantSayingContent = streamAttemptSayingContent;
|
|
1834
|
+
lastAssistantSayingGenseq =
|
|
1835
|
+
streamAttemptSayingGenseq === undefined ? null : streamAttemptSayingGenseq;
|
|
1836
|
+
lastAssistantReplyTarget = currentReplyTarget;
|
|
1576
1837
|
}
|
|
1577
|
-
|
|
1578
|
-
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1579
|
-
type: 'genseq_discard_evt',
|
|
1580
|
-
course: streamAttemptCourse,
|
|
1581
|
-
genseq: dlg.activeGenSeq,
|
|
1582
|
-
reason: 'retry',
|
|
1583
|
-
});
|
|
1584
|
-
streamActive = { kind: 'idle' };
|
|
1585
|
-
currentThinkingContent = '';
|
|
1586
|
-
currentThinkingReasoning = undefined;
|
|
1587
|
-
currentSayingContent = '';
|
|
1588
|
-
streamAttemptSayingContent = undefined;
|
|
1589
|
-
streamAttemptSayingGenseq = undefined;
|
|
1590
|
-
sawWebSearchSideChannelOutput = false;
|
|
1591
|
-
sawNativeToolSideChannelOutput = false;
|
|
1592
|
-
streamedFuncCalls.length = 0;
|
|
1593
|
-
newMsgs.length = 0;
|
|
1838
|
+
return { usage: res.usage, llmGenModel: res.llmGenModel };
|
|
1594
1839
|
};
|
|
1595
|
-
const
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
},
|
|
1599
|
-
thinkingStart: async () => {
|
|
1600
|
-
throwIfAborted(abortSignal, dlg);
|
|
1601
|
-
if (streamActive.kind !== 'idle') {
|
|
1602
|
-
const detail = `Protocol violation: thinkingStart while ${streamActive.kind} is active`;
|
|
1603
|
-
await dlg.streamError(detail);
|
|
1604
|
-
throw new Error(detail);
|
|
1605
|
-
}
|
|
1606
|
-
streamActive = { kind: 'thinking' };
|
|
1607
|
-
currentThinkingContent = '';
|
|
1608
|
-
currentThinkingReasoning = undefined;
|
|
1609
|
-
await dlg.thinkingStart();
|
|
1610
|
-
},
|
|
1611
|
-
thinkingChunk: async (chunk) => {
|
|
1612
|
-
throwIfAborted(abortSignal, dlg);
|
|
1613
|
-
currentThinkingContent += chunk;
|
|
1614
|
-
await dlg.thinkingChunk(chunk);
|
|
1615
|
-
},
|
|
1616
|
-
thinkingFinish: async (reasoning) => {
|
|
1617
|
-
throwIfAborted(abortSignal, dlg);
|
|
1618
|
-
if (streamActive.kind !== 'thinking') {
|
|
1619
|
-
const detail = `Protocol violation: thinkingFinish while ${streamActive.kind} is active`;
|
|
1620
|
-
await dlg.streamError(detail);
|
|
1621
|
-
throw new Error(detail);
|
|
1622
|
-
}
|
|
1623
|
-
streamActive = { kind: 'idle' };
|
|
1624
|
-
if (reasoning)
|
|
1625
|
-
currentThinkingReasoning = reasoning;
|
|
1626
|
-
await dlg.thinkingFinish(reasoning);
|
|
1627
|
-
if (currentThinkingContent.length > 0 || currentThinkingReasoning !== undefined) {
|
|
1628
|
-
newMsgs.push({
|
|
1629
|
-
type: 'thinking_msg',
|
|
1630
|
-
role: 'assistant',
|
|
1631
|
-
genseq: dlg.activeGenSeq,
|
|
1632
|
-
content: currentThinkingContent,
|
|
1633
|
-
reasoning: currentThinkingReasoning,
|
|
1634
|
-
});
|
|
1635
|
-
}
|
|
1636
|
-
currentThinkingContent = '';
|
|
1637
|
-
currentThinkingReasoning = undefined;
|
|
1638
|
-
},
|
|
1639
|
-
sayingStart: async () => {
|
|
1640
|
-
throwIfAborted(abortSignal, dlg);
|
|
1641
|
-
if (streamActive.kind !== 'idle') {
|
|
1642
|
-
const detail = `Protocol violation: sayingStart while ${streamActive.kind} is active`;
|
|
1643
|
-
await dlg.streamError(detail);
|
|
1644
|
-
throw new Error(detail);
|
|
1645
|
-
}
|
|
1646
|
-
streamActive = { kind: 'saying' };
|
|
1647
|
-
currentSayingContent = '';
|
|
1648
|
-
await dlg.sayingStart();
|
|
1649
|
-
},
|
|
1650
|
-
sayingChunk: async (chunk) => {
|
|
1651
|
-
throwIfAborted(abortSignal, dlg);
|
|
1652
|
-
currentSayingContent += chunk;
|
|
1653
|
-
await dlg.sayingChunk(chunk);
|
|
1654
|
-
},
|
|
1655
|
-
sayingFinish: async () => {
|
|
1656
|
-
throwIfAborted(abortSignal, dlg);
|
|
1657
|
-
if (streamActive.kind !== 'saying') {
|
|
1658
|
-
const detail = `Protocol violation: sayingFinish while ${streamActive.kind} is active`;
|
|
1659
|
-
await dlg.streamError(detail);
|
|
1660
|
-
throw new Error(detail);
|
|
1661
|
-
}
|
|
1662
|
-
streamActive = { kind: 'idle' };
|
|
1663
|
-
await dlg.sayingFinish();
|
|
1664
|
-
const sayingMessage = {
|
|
1665
|
-
type: 'saying_msg',
|
|
1666
|
-
role: 'assistant',
|
|
1667
|
-
genseq: dlg.activeGenSeq,
|
|
1668
|
-
content: currentSayingContent,
|
|
1669
|
-
};
|
|
1670
|
-
newMsgs.push(sayingMessage);
|
|
1671
|
-
streamAttemptSayingContent = currentSayingContent;
|
|
1672
|
-
streamAttemptSayingGenseq = sayingMessage.genseq;
|
|
1673
|
-
},
|
|
1674
|
-
funcCall: async (callId, name, argsStr) => {
|
|
1675
|
-
throwIfAborted(abortSignal, dlg);
|
|
1676
|
-
streamedFuncCalls.push({
|
|
1677
|
-
type: 'func_call_msg',
|
|
1678
|
-
role: 'assistant',
|
|
1679
|
-
genseq: dlg.activeGenSeq,
|
|
1680
|
-
id: callId,
|
|
1681
|
-
name,
|
|
1682
|
-
arguments: argsStr,
|
|
1683
|
-
});
|
|
1684
|
-
},
|
|
1685
|
-
webSearchCall: async (call) => {
|
|
1686
|
-
throwIfAborted(abortSignal, dlg);
|
|
1687
|
-
sawWebSearchSideChannelOutput = true;
|
|
1688
|
-
await dlg.webSearchCall(projectLlmWebSearchCall(call));
|
|
1689
|
-
},
|
|
1690
|
-
nativeToolCall: async (call) => {
|
|
1691
|
-
throwIfAborted(abortSignal, dlg);
|
|
1692
|
-
sawNativeToolSideChannelOutput = true;
|
|
1693
|
-
await dlg.nativeToolCall(call);
|
|
1694
|
-
},
|
|
1695
|
-
};
|
|
1696
|
-
const res = await (0, runtime_1.runLlmRequestWithRetry)({
|
|
1697
|
-
dlg,
|
|
1698
|
-
provider,
|
|
1699
|
-
modelId: model,
|
|
1700
|
-
providerConfig: providerCfg,
|
|
1701
|
-
abortSignal,
|
|
1702
|
-
maxRetries: retryPolicy.maxRetries,
|
|
1703
|
-
retryInitialDelayMs: retryPolicy.initialDelayMs,
|
|
1704
|
-
retryConservativeDelayMs: retryPolicy.conservativeDelayMs,
|
|
1705
|
-
retryBackoffMultiplier: retryPolicy.backoffMultiplier,
|
|
1706
|
-
retryMaxDelayMs: retryPolicy.maxDelayMs,
|
|
1707
|
-
classifyFailure: llmGen.classifyFailure?.bind(llmGen),
|
|
1708
|
-
canRetry: () => true,
|
|
1709
|
-
onRetry: rollbackStreamAttempt,
|
|
1710
|
-
onGiveUp: rollbackStreamAttempt,
|
|
1711
|
-
doRequest: async () => {
|
|
1712
|
-
streamAttemptCourse = dlg.activeGenCourseOrUndefined ?? dlg.currentCourse;
|
|
1713
|
-
streamAttemptCheckpointOffset = await persistence_1.DialogPersistence.captureCourseFileOffset(dlg.id, streamAttemptCourse, dlg.status);
|
|
1714
|
-
streamActive = { kind: 'idle' };
|
|
1715
|
-
currentThinkingContent = '';
|
|
1716
|
-
currentThinkingReasoning = undefined;
|
|
1717
|
-
currentSayingContent = '';
|
|
1718
|
-
streamAttemptSayingContent = undefined;
|
|
1719
|
-
streamAttemptSayingGenseq = undefined;
|
|
1720
|
-
sawWebSearchSideChannelOutput = false;
|
|
1721
|
-
sawNativeToolSideChannelOutput = false;
|
|
1722
|
-
streamedFuncCalls.length = 0;
|
|
1723
|
-
newMsgs.length = 0;
|
|
1724
|
-
const streamResult = await llmGen.genToReceiver(providerCfg, agent, systemPrompt, funcTools, {
|
|
1725
|
-
dialogSelfId: dlg.id.selfId,
|
|
1726
|
-
dialogRootId: dlg.id.rootId,
|
|
1727
|
-
promptCacheKey: `${dlg.id.selfId}:c${String(dlg.currentCourse)}`,
|
|
1728
|
-
}, ctxMsgs, receiver, dlg.activeGenSeq, abortSignal);
|
|
1729
|
-
const hasThinkingContent = currentThinkingContent.trim() !== '';
|
|
1730
|
-
const hasSayingContent = (streamAttemptSayingContent ?? '').trim() !== '';
|
|
1731
|
-
const hasFunctionCall = streamedFuncCalls.length > 0;
|
|
1732
|
-
if (!hasThinkingContent &&
|
|
1733
|
-
!hasSayingContent &&
|
|
1734
|
-
!hasFunctionCall &&
|
|
1735
|
-
!sawWebSearchSideChannelOutput &&
|
|
1736
|
-
!sawNativeToolSideChannelOutput) {
|
|
1737
|
-
throw {
|
|
1738
|
-
status: 503,
|
|
1739
|
-
code: KERNEL_DRIVER_EMPTY_LLM_RESPONSE_ERROR_CODE,
|
|
1740
|
-
message: `LLM returned empty response (provider=${provider}, model=${model}, streaming=true).`,
|
|
1741
|
-
};
|
|
1742
|
-
}
|
|
1743
|
-
return streamResult;
|
|
1744
|
-
},
|
|
1745
|
-
});
|
|
1746
|
-
if (streamAttemptSayingContent !== undefined) {
|
|
1747
|
-
lastAssistantSayingContent = streamAttemptSayingContent;
|
|
1748
|
-
lastAssistantSayingGenseq =
|
|
1749
|
-
streamAttemptSayingGenseq === undefined ? null : streamAttemptSayingGenseq;
|
|
1750
|
-
lastAssistantReplyTarget = currentReplyTarget;
|
|
1840
|
+
const llmOutput = await streamOrBatch();
|
|
1841
|
+
if (typeof llmOutput.llmGenModel === 'string' && llmOutput.llmGenModel.trim() !== '') {
|
|
1842
|
+
llmGenModelForGen = llmOutput.llmGenModel.trim();
|
|
1751
1843
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1844
|
+
contextHealthForGen = computeContextHealthSnapshot({
|
|
1845
|
+
providerCfg,
|
|
1846
|
+
model,
|
|
1847
|
+
usage: llmOutput.usage,
|
|
1848
|
+
});
|
|
1849
|
+
dlg.setLastContextHealth(contextHealthForGen);
|
|
1850
|
+
const batchOutputs = Array.isArray(llmOutput.batchOutputs) && llmOutput.batchOutputs.length > 0
|
|
1851
|
+
? llmOutput.batchOutputs
|
|
1852
|
+
: Array.isArray(llmOutput.batchMessages)
|
|
1853
|
+
? llmOutput.batchMessages.map((message) => ({ kind: 'message', message }))
|
|
1854
|
+
: [];
|
|
1855
|
+
for (const output of batchOutputs) {
|
|
1856
|
+
switch (output.kind) {
|
|
1857
|
+
case 'message': {
|
|
1858
|
+
const msg = output.message;
|
|
1859
|
+
if (msg.type === 'thinking_msg' || msg.type === 'saying_msg') {
|
|
1860
|
+
newMsgs.push(msg);
|
|
1861
|
+
if (msg.type === 'thinking_msg') {
|
|
1862
|
+
await (0, events_1.emitThinkingEvents)(dlg, msg.content, msg.reasoning);
|
|
1863
|
+
}
|
|
1864
|
+
else {
|
|
1865
|
+
lastAssistantSayingContent = msg.content;
|
|
1866
|
+
lastAssistantSayingGenseq = msg.genseq;
|
|
1867
|
+
lastAssistantReplyTarget = currentReplyTarget;
|
|
1868
|
+
await emitAssistantSaying(dlg, msg.content);
|
|
1869
|
+
}
|
|
1870
|
+
break;
|
|
1777
1871
|
}
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
lastAssistantSayingGenseq = msg.genseq;
|
|
1781
|
-
lastAssistantReplyTarget = currentReplyTarget;
|
|
1782
|
-
await emitAssistantSaying(dlg, msg.content);
|
|
1872
|
+
if (msg.type === 'func_call_msg') {
|
|
1873
|
+
streamedFuncCalls.push(msg);
|
|
1783
1874
|
}
|
|
1784
1875
|
break;
|
|
1785
1876
|
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1877
|
+
case 'web_search_call': {
|
|
1878
|
+
sawWebSearchSideChannelOutput = true;
|
|
1879
|
+
await dlg.webSearchCall(projectLlmWebSearchCall(output.call));
|
|
1880
|
+
break;
|
|
1881
|
+
}
|
|
1882
|
+
case 'native_tool_call': {
|
|
1883
|
+
sawNativeToolSideChannelOutput = true;
|
|
1884
|
+
await dlg.nativeToolCall(output.call);
|
|
1885
|
+
break;
|
|
1886
|
+
}
|
|
1887
|
+
default: {
|
|
1888
|
+
const _exhaustive = output;
|
|
1889
|
+
throw new Error(`Unhandled batch output kind: ${String(_exhaustive)}`);
|
|
1788
1890
|
}
|
|
1789
|
-
break;
|
|
1790
|
-
}
|
|
1791
|
-
case 'web_search_call': {
|
|
1792
|
-
sawWebSearchSideChannelOutput = true;
|
|
1793
|
-
await dlg.webSearchCall(projectLlmWebSearchCall(output.call));
|
|
1794
|
-
break;
|
|
1795
|
-
}
|
|
1796
|
-
case 'native_tool_call': {
|
|
1797
|
-
sawNativeToolSideChannelOutput = true;
|
|
1798
|
-
await dlg.nativeToolCall(output.call);
|
|
1799
|
-
break;
|
|
1800
|
-
}
|
|
1801
|
-
default: {
|
|
1802
|
-
const _exhaustive = output;
|
|
1803
|
-
throw new Error(`Unhandled batch output kind: ${String(_exhaustive)}`);
|
|
1804
1891
|
}
|
|
1805
1892
|
}
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
functionCallCount: streamedFuncCalls.length,
|
|
1818
|
-
});
|
|
1819
|
-
if (policyViolationKind) {
|
|
1820
|
-
const violationText = (0, driver_messages_1.formatDomindsNoteFbrToollessViolation)((0, work_language_1.getWorkLanguage)(), {
|
|
1821
|
-
kind: policyViolationKind,
|
|
1893
|
+
const tellaskCallCount = policy.allowTellaskFunctions
|
|
1894
|
+
? streamedFuncCalls.filter((c) => c.name === 'tellask' ||
|
|
1895
|
+
c.name === 'tellaskSessionless' ||
|
|
1896
|
+
c.name === 'tellaskBack' ||
|
|
1897
|
+
c.name === 'askHuman' ||
|
|
1898
|
+
c.name === 'freshBootsReasoning').length
|
|
1899
|
+
: 0;
|
|
1900
|
+
const policyViolationKind = (0, guardrails_1.resolveKernelDriverPolicyViolationKind)({
|
|
1901
|
+
policy,
|
|
1902
|
+
tellaskCallCount,
|
|
1903
|
+
functionCallCount: streamedFuncCalls.length,
|
|
1822
1904
|
});
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
genseq
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1905
|
+
if (policyViolationKind) {
|
|
1906
|
+
const violationText = (0, driver_messages_1.formatDomindsNoteFbrToollessViolation)((0, work_language_1.getWorkLanguage)(), {
|
|
1907
|
+
kind: policyViolationKind,
|
|
1908
|
+
});
|
|
1909
|
+
const genseq = dlg.activeGenSeq;
|
|
1910
|
+
const violationMsg = {
|
|
1911
|
+
type: 'saying_msg',
|
|
1912
|
+
role: 'assistant',
|
|
1913
|
+
genseq,
|
|
1914
|
+
content: violationText,
|
|
1915
|
+
};
|
|
1916
|
+
await emitAssistantSaying(dlg, violationText);
|
|
1917
|
+
newMsgs.push(violationMsg);
|
|
1918
|
+
await dlg.addChatMessages(...newMsgs);
|
|
1919
|
+
lastAssistantSayingContent = violationText;
|
|
1920
|
+
lastAssistantSayingGenseq = genseq;
|
|
1921
|
+
lastAssistantReplyTarget = currentReplyTarget;
|
|
1922
|
+
const persistedFbrState = await loadDialogFbrState(dlg);
|
|
1923
|
+
if (!persistedFbrState) {
|
|
1924
|
+
return {
|
|
1925
|
+
lastAssistantSayingContent,
|
|
1926
|
+
lastAssistantSayingGenseq,
|
|
1927
|
+
lastFunctionCallGenseq,
|
|
1928
|
+
lastAssistantReplyTarget,
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
1931
|
+
const nextFbrState = (0, fbr_1.advanceFbrState)(persistedFbrState);
|
|
1932
|
+
if (nextFbrState) {
|
|
1933
|
+
if (!isFbrSubdialogDialog(dlg)) {
|
|
1934
|
+
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
1935
|
+
}
|
|
1936
|
+
await persistDialogFbrState(dlg, nextFbrState);
|
|
1937
|
+
dlg.setFbrConclusionToolsEnabled((0, fbr_1.isFbrFinalizationState)(nextFbrState));
|
|
1938
|
+
pendingPrompt = buildKernelDriverFbrPrompt(dlg, nextFbrState);
|
|
1939
|
+
continue;
|
|
1940
|
+
}
|
|
1941
|
+
fbrConclusion = {
|
|
1942
|
+
responseText: (0, fbr_1.buildProgrammaticFbrUnreasonableSituationContent)({
|
|
1943
|
+
language: (0, work_language_1.getWorkLanguage)(),
|
|
1944
|
+
finalizationAttempts: persistedFbrState.effort,
|
|
1945
|
+
}),
|
|
1946
|
+
responseGenseq: genseq,
|
|
1843
1947
|
};
|
|
1844
|
-
}
|
|
1845
|
-
const nextFbrState = (0, fbr_1.advanceFbrState)(persistedFbrState);
|
|
1846
|
-
if (nextFbrState) {
|
|
1847
1948
|
if (!isFbrSubdialogDialog(dlg)) {
|
|
1848
1949
|
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
1849
1950
|
}
|
|
1850
|
-
await persistDialogFbrState(dlg,
|
|
1851
|
-
dlg.setFbrConclusionToolsEnabled(
|
|
1852
|
-
|
|
1853
|
-
continue;
|
|
1951
|
+
await persistDialogFbrState(dlg, undefined);
|
|
1952
|
+
dlg.setFbrConclusionToolsEnabled(false);
|
|
1953
|
+
break;
|
|
1854
1954
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
1955
|
+
for (const call of streamedFuncCalls) {
|
|
1956
|
+
const rawCallGenseq = call.genseq;
|
|
1957
|
+
if (!Number.isFinite(rawCallGenseq) || rawCallGenseq <= 0)
|
|
1958
|
+
continue;
|
|
1959
|
+
const callGenseq = Math.floor(rawCallGenseq);
|
|
1960
|
+
if (lastFunctionCallGenseq === null || callGenseq > lastFunctionCallGenseq) {
|
|
1961
|
+
lastFunctionCallGenseq = callGenseq;
|
|
1962
|
+
}
|
|
1864
1963
|
}
|
|
1865
|
-
await
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
if (
|
|
1875
|
-
|
|
1964
|
+
const routed = await executeFunctionRound({
|
|
1965
|
+
dlg,
|
|
1966
|
+
agent,
|
|
1967
|
+
agentTools,
|
|
1968
|
+
funcCalls: streamedFuncCalls,
|
|
1969
|
+
callbacks,
|
|
1970
|
+
abortSignal,
|
|
1971
|
+
allowTellaskFunctions: policy.allowTellaskFunctions,
|
|
1972
|
+
});
|
|
1973
|
+
if (routed.tellaskToolOutputs.length > 0) {
|
|
1974
|
+
newMsgs.push(...routed.tellaskToolOutputs);
|
|
1876
1975
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
const identicalUpdatePlanRoundSignature = routed.updatePlanOnlyRawArgumentsSignature !== undefined &&
|
|
1896
|
-
assistantSayingRoundSignature !== undefined
|
|
1897
|
-
? JSON.stringify({
|
|
1898
|
-
assistantSayingRoundSignature,
|
|
1899
|
-
updatePlanRawArgumentsSignature: routed.updatePlanOnlyRawArgumentsSignature,
|
|
1900
|
-
})
|
|
1901
|
-
: undefined;
|
|
1902
|
-
if (identicalUpdatePlanRoundSignature !== undefined) {
|
|
1903
|
-
if (identicalUpdatePlanRoundSignature === lastIdenticalUpdatePlanRoundSignature) {
|
|
1904
|
-
consecutiveIdenticalUpdatePlanOnlyRounds += 1;
|
|
1976
|
+
if (routed.pairedMessages.length > 0) {
|
|
1977
|
+
newMsgs.push(...routed.pairedMessages);
|
|
1978
|
+
}
|
|
1979
|
+
await dlg.addChatMessages(...newMsgs);
|
|
1980
|
+
const assistantSayingRoundSignature = extractAssistantSayingRoundSignature(newMsgs);
|
|
1981
|
+
const identicalUpdatePlanRoundSignature = routed.updatePlanOnlyRound
|
|
1982
|
+
? JSON.stringify({
|
|
1983
|
+
assistantSayingRoundSignature: assistantSayingRoundSignature ?? '',
|
|
1984
|
+
})
|
|
1985
|
+
: undefined;
|
|
1986
|
+
if (identicalUpdatePlanRoundSignature !== undefined) {
|
|
1987
|
+
if (identicalUpdatePlanRoundSignature === lastIdenticalUpdatePlanRoundSignature) {
|
|
1988
|
+
consecutiveIdenticalUpdatePlanOnlyRounds += 1;
|
|
1989
|
+
}
|
|
1990
|
+
else {
|
|
1991
|
+
consecutiveIdenticalUpdatePlanOnlyRounds = 1;
|
|
1992
|
+
lastIdenticalUpdatePlanRoundSignature = identicalUpdatePlanRoundSignature;
|
|
1993
|
+
}
|
|
1905
1994
|
}
|
|
1906
1995
|
else {
|
|
1907
|
-
consecutiveIdenticalUpdatePlanOnlyRounds =
|
|
1908
|
-
lastIdenticalUpdatePlanRoundSignature =
|
|
1996
|
+
consecutiveIdenticalUpdatePlanOnlyRounds = 0;
|
|
1997
|
+
lastIdenticalUpdatePlanRoundSignature = undefined;
|
|
1909
1998
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1999
|
+
const persistedFbrState = await loadDialogFbrState(dlg);
|
|
2000
|
+
if (persistedFbrState) {
|
|
2001
|
+
if (persistedFbrState.phase === 'finalization') {
|
|
2002
|
+
const inspection = (0, fbr_1.inspectFbrConclusionAttempt)(newMsgs);
|
|
2003
|
+
if (inspection.kind === 'accepted') {
|
|
2004
|
+
log_1.log.debug('kernel-driver accepted FBR conclusion attempt', undefined, {
|
|
2005
|
+
dialogId: dlg.id.valueOf(),
|
|
2006
|
+
toolName: inspection.toolName,
|
|
2007
|
+
callId: inspection.callId,
|
|
2008
|
+
});
|
|
2009
|
+
fbrConclusion = {
|
|
2010
|
+
responseText: inspection.content,
|
|
2011
|
+
responseGenseq: inspection.genseq,
|
|
2012
|
+
};
|
|
2013
|
+
if (!isFbrSubdialogDialog(dlg)) {
|
|
2014
|
+
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
2015
|
+
}
|
|
2016
|
+
await persistDialogFbrState(dlg, undefined);
|
|
2017
|
+
dlg.setFbrConclusionToolsEnabled(false);
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
if (inspection.kind === 'rejected') {
|
|
2021
|
+
const detail = `FBR conclusion attempt rejected: ${inspection.reason}`;
|
|
2022
|
+
await dlg.streamError(detail);
|
|
2023
|
+
log_1.log.warn(detail, undefined, {
|
|
2024
|
+
rootId: dlg.id.rootId,
|
|
2025
|
+
selfId: dlg.id.selfId,
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
const nextFbrState = (0, fbr_1.advanceFbrState)(persistedFbrState);
|
|
2030
|
+
if (nextFbrState) {
|
|
1929
2031
|
if (!isFbrSubdialogDialog(dlg)) {
|
|
1930
2032
|
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
1931
2033
|
}
|
|
1932
|
-
await persistDialogFbrState(dlg,
|
|
1933
|
-
dlg.setFbrConclusionToolsEnabled(
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
if (inspection.kind === 'rejected') {
|
|
1937
|
-
const detail = `FBR conclusion attempt rejected: ${inspection.reason}`;
|
|
1938
|
-
await dlg.streamError(detail);
|
|
1939
|
-
log_1.log.warn(detail, undefined, {
|
|
1940
|
-
rootId: dlg.id.rootId,
|
|
1941
|
-
selfId: dlg.id.selfId,
|
|
1942
|
-
});
|
|
2034
|
+
await persistDialogFbrState(dlg, nextFbrState);
|
|
2035
|
+
dlg.setFbrConclusionToolsEnabled((0, fbr_1.isFbrFinalizationState)(nextFbrState));
|
|
2036
|
+
pendingPrompt = buildKernelDriverFbrPrompt(dlg, nextFbrState);
|
|
2037
|
+
continue;
|
|
1943
2038
|
}
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
2039
|
+
fbrConclusion = {
|
|
2040
|
+
responseText: (0, fbr_1.buildProgrammaticFbrUnreasonableSituationContent)({
|
|
2041
|
+
language: (0, work_language_1.getWorkLanguage)(),
|
|
2042
|
+
finalizationAttempts: persistedFbrState.effort,
|
|
2043
|
+
}),
|
|
2044
|
+
responseGenseq: lastAssistantSayingGenseq ??
|
|
2045
|
+
lastFunctionCallGenseq ??
|
|
2046
|
+
dlg.activeGenSeqOrUndefined ??
|
|
2047
|
+
1,
|
|
2048
|
+
};
|
|
1947
2049
|
if (!isFbrSubdialogDialog(dlg)) {
|
|
1948
2050
|
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
1949
2051
|
}
|
|
1950
|
-
await persistDialogFbrState(dlg,
|
|
1951
|
-
dlg.setFbrConclusionToolsEnabled(
|
|
1952
|
-
|
|
2052
|
+
await persistDialogFbrState(dlg, undefined);
|
|
2053
|
+
dlg.setFbrConclusionToolsEnabled(false);
|
|
2054
|
+
break;
|
|
2055
|
+
}
|
|
2056
|
+
if (routed.shouldStopAfterReplyTool) {
|
|
2057
|
+
log_1.log.debug('kernel-driver stop round after explicit replyTellask* tool', undefined, {
|
|
2058
|
+
dialogId: dlg.id.valueOf(),
|
|
2059
|
+
toolNames: streamedFuncCalls
|
|
2060
|
+
.filter((call) => call.name === 'replyTellask' ||
|
|
2061
|
+
call.name === 'replyTellaskSessionless' ||
|
|
2062
|
+
call.name === 'replyTellaskBack')
|
|
2063
|
+
.map((call) => call.name),
|
|
2064
|
+
});
|
|
2065
|
+
break;
|
|
2066
|
+
}
|
|
2067
|
+
if (dlg.hasUpNext()) {
|
|
2068
|
+
pendingPrompt = resolveUpNextPrompt(dlg);
|
|
1953
2069
|
continue;
|
|
1954
2070
|
}
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
finalizationAttempts: persistedFbrState.effort,
|
|
1959
|
-
}),
|
|
1960
|
-
responseGenseq: lastAssistantSayingGenseq ??
|
|
1961
|
-
lastFunctionCallGenseq ??
|
|
1962
|
-
dlg.activeGenSeqOrUndefined ??
|
|
1963
|
-
1,
|
|
1964
|
-
};
|
|
1965
|
-
if (!isFbrSubdialogDialog(dlg)) {
|
|
1966
|
-
throw new Error(`kernel-driver FBR invariant violation: persisted FBR state on non-FBR dialog (${dlg.id.valueOf()})`);
|
|
2071
|
+
if (dlg.remindersVer > pubRemindersVer) {
|
|
2072
|
+
await dlg.processReminderUpdates();
|
|
2073
|
+
pubRemindersVer = dlg.remindersVer;
|
|
1967
2074
|
}
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
if (routed.shouldStopAfterReplyTool) {
|
|
1973
|
-
log_1.log.debug('kernel-driver stop round after explicit replyTellask* tool', undefined, {
|
|
1974
|
-
dialogId: dlg.id.valueOf(),
|
|
1975
|
-
toolNames: streamedFuncCalls
|
|
1976
|
-
.filter((call) => call.name === 'replyTellask' ||
|
|
1977
|
-
call.name === 'replyTellaskSessionless' ||
|
|
1978
|
-
call.name === 'replyTellaskBack')
|
|
1979
|
-
.map((call) => call.name),
|
|
1980
|
-
});
|
|
1981
|
-
break;
|
|
1982
|
-
}
|
|
1983
|
-
if (dlg.hasUpNext()) {
|
|
1984
|
-
pendingPrompt = resolveUpNextPrompt(dlg);
|
|
1985
|
-
continue;
|
|
1986
|
-
}
|
|
1987
|
-
if (dlg.remindersVer > pubRemindersVer) {
|
|
1988
|
-
await dlg.processReminderUpdates();
|
|
1989
|
-
pubRemindersVer = dlg.remindersVer;
|
|
1990
|
-
}
|
|
1991
|
-
// Tool execution may have created pending Q4H/subdialogs mid-round. Respect the
|
|
1992
|
-
// dialog's actual suspension state here so auto-continue is decided in one place.
|
|
1993
|
-
const suspensionAfterToolRound = await dlg.getSuspensionStatus({
|
|
1994
|
-
allowPendingSubdialogs: routed.hasImmediateFollowupToolCalls,
|
|
1995
|
-
});
|
|
1996
|
-
if (!suspensionAfterToolRound.canDrive) {
|
|
1997
|
-
await resetDiligenceBudgetAfterQ4H(dlg, team);
|
|
1998
|
-
break;
|
|
1999
|
-
}
|
|
2000
|
-
if (consecutiveIdenticalUpdatePlanOnlyRounds >=
|
|
2001
|
-
KERNEL_DRIVER_IDENTICAL_UPDATE_PLAN_ONLY_STOP_THRESHOLD) {
|
|
2002
|
-
const detail = formatIdenticalUpdatePlanLoopStopDetail((0, work_language_1.getWorkLanguage)());
|
|
2003
|
-
log_1.log.error(detail, new Error('kernel_driver_identical_update_plan_loop_stopped'), {
|
|
2004
|
-
dialogId: dlg.id.valueOf(),
|
|
2005
|
-
rootId: dlg.id.rootId,
|
|
2006
|
-
selfId: dlg.id.selfId,
|
|
2007
|
-
course: dlg.currentCourse,
|
|
2008
|
-
genseq: dlg.activeGenSeqOrUndefined ?? null,
|
|
2009
|
-
consecutiveIdenticalUpdatePlanOnlyRounds,
|
|
2010
|
-
identicalUpdatePlanRoundSignature,
|
|
2011
|
-
});
|
|
2012
|
-
throw new KernelDriverInterruptedError({ kind: 'system_stop', detail });
|
|
2013
|
-
}
|
|
2014
|
-
// Start an immediate post-tool generation only when this round produced tool outputs that
|
|
2015
|
-
// warrant same-drive LLM reaction right away. Provider-native side-channel UI events are
|
|
2016
|
-
// meaningful output, but they are not transcript/context inputs and therefore must not
|
|
2017
|
-
// trigger another immediate generation round by themselves.
|
|
2018
|
-
const shouldStartImmediatePostToolGeneration = routed.hasImmediateFollowupToolCalls || routed.tellaskToolOutputs.length > 0;
|
|
2019
|
-
if (!shouldStartImmediatePostToolGeneration) {
|
|
2020
|
-
const healthFirst = await maybeContinueWithHealthPromptBeforeDiligence({
|
|
2021
|
-
dlg,
|
|
2022
|
-
providerCfg,
|
|
2023
|
-
model,
|
|
2075
|
+
// Tool execution may have created pending Q4H/subdialogs mid-round. Respect the
|
|
2076
|
+
// dialog's actual suspension state here so auto-continue is decided in one place.
|
|
2077
|
+
const suspensionAfterToolRound = await dlg.getSuspensionStatus({
|
|
2078
|
+
allowPendingSubdialogs: routed.hasImmediateFollowupToolCalls,
|
|
2024
2079
|
});
|
|
2025
|
-
if (
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2080
|
+
if (!suspensionAfterToolRound.canDrive) {
|
|
2081
|
+
await resetDiligenceBudgetAfterQ4H(dlg, team);
|
|
2082
|
+
break;
|
|
2083
|
+
}
|
|
2084
|
+
if (consecutiveIdenticalUpdatePlanOnlyRounds >=
|
|
2085
|
+
KERNEL_DRIVER_IDENTICAL_UPDATE_PLAN_ONLY_STOP_THRESHOLD) {
|
|
2086
|
+
const detail = formatIdenticalUpdatePlanLoopStopDetail((0, work_language_1.getWorkLanguage)());
|
|
2087
|
+
log_1.log.error(detail, new Error('kernel_driver_identical_update_plan_loop_stopped'), {
|
|
2088
|
+
dialogId: dlg.id.valueOf(),
|
|
2089
|
+
rootId: dlg.id.rootId,
|
|
2090
|
+
selfId: dlg.id.selfId,
|
|
2091
|
+
course: dlg.currentCourse,
|
|
2092
|
+
genseq: dlg.activeGenSeqOrUndefined ?? null,
|
|
2093
|
+
consecutiveIdenticalUpdatePlanOnlyRounds,
|
|
2094
|
+
identicalUpdatePlanRoundSignature,
|
|
2095
|
+
});
|
|
2096
|
+
throw new KernelDriverInterruptedError({
|
|
2097
|
+
kind: 'system_stop',
|
|
2098
|
+
detail,
|
|
2099
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({
|
|
2100
|
+
detail,
|
|
2101
|
+
kind: 'identical_update_plan_loop',
|
|
2102
|
+
}),
|
|
2103
|
+
});
|
|
2031
2104
|
}
|
|
2032
|
-
|
|
2105
|
+
// Start an immediate post-tool generation only when this round produced tool outputs that
|
|
2106
|
+
// warrant same-drive LLM reaction right away. Provider-native side-channel UI events are
|
|
2107
|
+
// meaningful output, but they are not transcript/context inputs and therefore must not
|
|
2108
|
+
// trigger another immediate generation round by themselves.
|
|
2109
|
+
const shouldStartImmediatePostToolGeneration = routed.hasImmediateFollowupToolCalls || routed.tellaskToolOutputs.length > 0;
|
|
2110
|
+
if (!shouldStartImmediatePostToolGeneration) {
|
|
2111
|
+
const healthFirst = await maybeContinueWithHealthPromptBeforeDiligence({
|
|
2112
|
+
dlg,
|
|
2113
|
+
providerCfg,
|
|
2114
|
+
model,
|
|
2115
|
+
});
|
|
2116
|
+
if (healthFirst.kind === 'health_continue') {
|
|
2117
|
+
pendingPrompt = healthFirst.prompt;
|
|
2118
|
+
if (healthFirst.resetTaskdoc) {
|
|
2119
|
+
skipTaskdocForThisDrive = false;
|
|
2120
|
+
}
|
|
2121
|
+
continue;
|
|
2122
|
+
}
|
|
2123
|
+
if (healthFirst.kind === 'health_suspend') {
|
|
2124
|
+
break;
|
|
2125
|
+
}
|
|
2126
|
+
const next = await maybeContinueWithDiligencePrompt({
|
|
2127
|
+
dlg,
|
|
2128
|
+
team,
|
|
2129
|
+
suppressDiligencePushForDrive: suppressDiligencePushForDrive,
|
|
2130
|
+
});
|
|
2131
|
+
if (next.kind === 'continue') {
|
|
2132
|
+
pendingPrompt = next.prompt;
|
|
2133
|
+
continue;
|
|
2134
|
+
}
|
|
2033
2135
|
break;
|
|
2034
2136
|
}
|
|
2035
|
-
|
|
2036
|
-
dlg,
|
|
2037
|
-
team,
|
|
2038
|
-
suppressDiligencePushForDrive: suppressDiligencePushForDrive,
|
|
2039
|
-
});
|
|
2040
|
-
if (next.kind === 'continue') {
|
|
2041
|
-
pendingPrompt = next.prompt;
|
|
2137
|
+
if (shouldStartImmediatePostToolGeneration) {
|
|
2042
2138
|
continue;
|
|
2043
2139
|
}
|
|
2044
|
-
break;
|
|
2045
2140
|
}
|
|
2046
|
-
|
|
2047
|
-
|
|
2141
|
+
finally {
|
|
2142
|
+
await dlg.notifyGeneratingFinish(contextHealthForGen, llmGenModelForGen);
|
|
2048
2143
|
}
|
|
2049
2144
|
}
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
}
|
|
2054
|
-
throwIfAborted(abortSignal, dlg);
|
|
2055
|
-
finalDisplayState = await (0, dialog_display_state_1.computeIdleDisplayState)(dlg);
|
|
2056
|
-
}
|
|
2057
|
-
catch (err) {
|
|
2058
|
-
const stopRequested = (0, dialog_display_state_1.getStopRequestedReason)(dlg.id);
|
|
2059
|
-
const interruptedReason = err instanceof runtime_1.LlmRetryStoppedError
|
|
2060
|
-
? err.reason
|
|
2061
|
-
: err instanceof KernelDriverInterruptedError
|
|
2062
|
-
? err.reason
|
|
2063
|
-
: abortSignal.aborted
|
|
2064
|
-
? stopRequested === 'emergency_stop'
|
|
2065
|
-
? { kind: 'emergency_stop' }
|
|
2066
|
-
: stopRequested === 'user_stop'
|
|
2067
|
-
? { kind: 'user_stop' }
|
|
2068
|
-
: { kind: 'system_stop', detail: 'Aborted.' }
|
|
2069
|
-
: undefined;
|
|
2070
|
-
if (interruptedReason) {
|
|
2071
|
-
finalDisplayState = {
|
|
2072
|
-
kind: 'stopped',
|
|
2073
|
-
reason: interruptedReason,
|
|
2074
|
-
continueEnabled: resolveStoppedContinueEnabled(interruptedReason),
|
|
2075
|
-
};
|
|
2076
|
-
(0, dialog_display_state_1.broadcastDisplayStateMarker)(dlg.id, { kind: 'interrupted', reason: interruptedReason });
|
|
2145
|
+
throwIfAborted(abortSignal, dlg);
|
|
2146
|
+
finalDisplayState = await (0, dialog_display_state_1.computeIdleDisplayState)(dlg);
|
|
2147
|
+
break driveCoreLoop;
|
|
2077
2148
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
catch {
|
|
2084
|
-
// best-effort
|
|
2149
|
+
catch (err) {
|
|
2150
|
+
if (err instanceof runtime_1.LlmRetryStoppedError && retryStoppedRecoveryPrompt !== undefined) {
|
|
2151
|
+
pendingPrompt = retryStoppedRecoveryPrompt;
|
|
2152
|
+
retryStoppedRecoveryPrompt = undefined;
|
|
2153
|
+
continue driveCoreLoop;
|
|
2085
2154
|
}
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
finalDisplayState =
|
|
2155
|
+
retryStoppedRecoveryPrompt = undefined;
|
|
2156
|
+
const stopRequested = (0, dialog_display_state_1.getStopRequestedReason)(dlg.id);
|
|
2157
|
+
const interruptedReason = err instanceof runtime_1.LlmRetryStoppedError
|
|
2158
|
+
? err.reason
|
|
2159
|
+
: err instanceof KernelDriverInterruptedError
|
|
2160
|
+
? err.reason
|
|
2161
|
+
: abortSignal.aborted
|
|
2162
|
+
? stopRequested === 'emergency_stop'
|
|
2163
|
+
? { kind: 'emergency_stop' }
|
|
2164
|
+
: stopRequested === 'user_stop'
|
|
2165
|
+
? { kind: 'user_stop' }
|
|
2166
|
+
: buildAbortedSystemStopReason()
|
|
2167
|
+
: undefined;
|
|
2168
|
+
if (interruptedReason) {
|
|
2169
|
+
finalDisplayState = {
|
|
2170
|
+
kind: 'stopped',
|
|
2171
|
+
reason: interruptedReason,
|
|
2172
|
+
continueEnabled: resolveStoppedContinueEnabled(interruptedReason),
|
|
2173
|
+
};
|
|
2174
|
+
(0, dialog_display_state_1.broadcastDisplayStateMarker)(dlg.id, { kind: 'interrupted', reason: interruptedReason });
|
|
2101
2175
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2176
|
+
else {
|
|
2177
|
+
const llmRequestFailure = err instanceof runtime_1.LlmRequestFailedError ? err : undefined;
|
|
2178
|
+
const emittedStreamError = err instanceof gen_1.LlmStreamErrorEmittedError ? err : undefined;
|
|
2179
|
+
const errText = llmRequestFailure?.detail ??
|
|
2180
|
+
emittedStreamError?.detail ??
|
|
2181
|
+
(0, log_1.extractErrorDetails)(err).message;
|
|
2182
|
+
if (!llmRequestFailure?.streamErrorEmitted && !emittedStreamError) {
|
|
2183
|
+
try {
|
|
2184
|
+
await dlg.streamError(errText);
|
|
2185
|
+
}
|
|
2186
|
+
catch {
|
|
2187
|
+
// best-effort
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
finalDisplayState = {
|
|
2191
|
+
kind: 'stopped',
|
|
2192
|
+
reason: (llmRequestFailure?.i18nStopReason ?? emittedStreamError?.i18nStopReason) !== undefined
|
|
2193
|
+
? {
|
|
2194
|
+
kind: 'system_stop',
|
|
2195
|
+
detail: errText,
|
|
2196
|
+
i18nStopReason: llmRequestFailure?.i18nStopReason ??
|
|
2197
|
+
emittedStreamError?.i18nStopReason ??
|
|
2198
|
+
(0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({ detail: errText }),
|
|
2199
|
+
}
|
|
2200
|
+
: {
|
|
2201
|
+
kind: 'system_stop',
|
|
2202
|
+
detail: errText,
|
|
2203
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({ detail: errText }),
|
|
2204
|
+
},
|
|
2205
|
+
continueEnabled: true,
|
|
2206
|
+
};
|
|
2207
|
+
(0, dialog_display_state_1.broadcastDisplayStateMarker)(dlg.id, {
|
|
2208
|
+
kind: 'interrupted',
|
|
2209
|
+
reason: (llmRequestFailure?.i18nStopReason ?? emittedStreamError?.i18nStopReason) !== undefined
|
|
2210
|
+
? {
|
|
2211
|
+
kind: 'system_stop',
|
|
2212
|
+
detail: errText,
|
|
2213
|
+
i18nStopReason: llmRequestFailure?.i18nStopReason ??
|
|
2214
|
+
emittedStreamError?.i18nStopReason ??
|
|
2215
|
+
(0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({ detail: errText }),
|
|
2216
|
+
}
|
|
2217
|
+
: {
|
|
2218
|
+
kind: 'system_stop',
|
|
2219
|
+
detail: errText,
|
|
2220
|
+
i18nStopReason: (0, stop_reason_i18n_1.buildHumanSystemStopReasonTextI18n)({ detail: errText }),
|
|
2221
|
+
},
|
|
2105
2222
|
});
|
|
2106
|
-
finalDisplayState = { kind: 'idle_waiting_user' };
|
|
2107
2223
|
}
|
|
2224
|
+
break driveCoreLoop;
|
|
2108
2225
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
finalDisplayState.kind !== 'dead') {
|
|
2112
|
-
const stopRequested = (0, dialog_display_state_1.getStopRequestedReason)(dlg.id);
|
|
2113
|
-
const lateInterruptedReason = stopRequested === 'emergency_stop'
|
|
2114
|
-
? { kind: 'emergency_stop' }
|
|
2115
|
-
: stopRequested === 'user_stop'
|
|
2116
|
-
? { kind: 'user_stop' }
|
|
2117
|
-
: { kind: 'system_stop', detail: 'Aborted.' };
|
|
2118
|
-
finalDisplayState = {
|
|
2119
|
-
kind: 'stopped',
|
|
2120
|
-
reason: lateInterruptedReason,
|
|
2121
|
-
continueEnabled: resolveStoppedContinueEnabled(lateInterruptedReason),
|
|
2122
|
-
};
|
|
2123
|
-
(0, dialog_display_state_1.broadcastDisplayStateMarker)(dlg.id, { kind: 'interrupted', reason: lateInterruptedReason });
|
|
2124
|
-
}
|
|
2226
|
+
}
|
|
2227
|
+
if (!finalDisplayState) {
|
|
2125
2228
|
try {
|
|
2126
|
-
|
|
2127
|
-
if (dlg.id.selfId !== dlg.id.rootId && latest?.executionMarker?.kind === 'dead') {
|
|
2128
|
-
finalDisplayState = { kind: 'dead', reason: latest.executionMarker.reason };
|
|
2129
|
-
}
|
|
2229
|
+
finalDisplayState = await (0, dialog_display_state_1.computeIdleDisplayState)(dlg);
|
|
2130
2230
|
}
|
|
2131
|
-
catch (
|
|
2132
|
-
log_1.log.warn('kernel-driver failed to
|
|
2231
|
+
catch (stateErr) {
|
|
2232
|
+
log_1.log.warn('kernel-driver failed to compute final display-state projection; falling back to idle', stateErr, {
|
|
2133
2233
|
dialogId: dlg.id.valueOf(),
|
|
2134
2234
|
});
|
|
2235
|
+
finalDisplayState = { kind: 'idle_waiting_user' };
|
|
2135
2236
|
}
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2237
|
+
}
|
|
2238
|
+
if (abortSignal.aborted &&
|
|
2239
|
+
finalDisplayState.kind !== 'stopped' &&
|
|
2240
|
+
finalDisplayState.kind !== 'dead') {
|
|
2241
|
+
const stopRequested = (0, dialog_display_state_1.getStopRequestedReason)(dlg.id);
|
|
2242
|
+
const lateInterruptedReason = stopRequested === 'emergency_stop'
|
|
2243
|
+
? { kind: 'emergency_stop' }
|
|
2244
|
+
: stopRequested === 'user_stop'
|
|
2245
|
+
? { kind: 'user_stop' }
|
|
2246
|
+
: buildAbortedSystemStopReason();
|
|
2247
|
+
finalDisplayState = {
|
|
2248
|
+
kind: 'stopped',
|
|
2249
|
+
reason: lateInterruptedReason,
|
|
2250
|
+
continueEnabled: resolveStoppedContinueEnabled(lateInterruptedReason),
|
|
2251
|
+
};
|
|
2252
|
+
(0, dialog_display_state_1.broadcastDisplayStateMarker)(dlg.id, { kind: 'interrupted', reason: lateInterruptedReason });
|
|
2253
|
+
}
|
|
2254
|
+
try {
|
|
2255
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(dlg.id, 'running');
|
|
2256
|
+
if (dlg.id.selfId !== dlg.id.rootId && latest?.executionMarker?.kind === 'dead') {
|
|
2257
|
+
finalDisplayState = { kind: 'dead', reason: latest.executionMarker.reason };
|
|
2144
2258
|
}
|
|
2145
|
-
await (0, dialog_display_state_1.setDialogDisplayState)(dlg.id, finalDisplayState);
|
|
2146
2259
|
}
|
|
2260
|
+
catch (err) {
|
|
2261
|
+
log_1.log.warn('kernel-driver failed to re-check displayState before finalizing', err, {
|
|
2262
|
+
dialogId: dlg.id.valueOf(),
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
if (finalDisplayState.kind === 'stopped') {
|
|
2266
|
+
await (0, dialog_display_state_1.setDialogExecutionMarker)(dlg.id, {
|
|
2267
|
+
kind: 'interrupted',
|
|
2268
|
+
reason: finalDisplayState.reason,
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
else if (finalDisplayState.kind !== 'dead') {
|
|
2272
|
+
await (0, dialog_display_state_1.clearDialogInterruptedExecutionMarker)(dlg.id);
|
|
2273
|
+
}
|
|
2274
|
+
await (0, dialog_display_state_1.setDialogDisplayState)(dlg.id, finalDisplayState);
|
|
2147
2275
|
return {
|
|
2148
2276
|
lastAssistantSayingContent,
|
|
2149
2277
|
lastAssistantSayingGenseq,
|