dominds 1.16.3 → 1.16.5
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 +1 -0
- package/dist/dialog-display-state.js +71 -2
- package/dist/dialog-fork.js +9 -0
- package/dist/dialog.d.ts +3 -0
- package/dist/dialog.js +4 -0
- package/dist/docs/mcp-support.md +6 -2
- package/dist/llm/api-quirks.js +34 -6
- package/dist/llm/client.d.ts +1 -1
- package/dist/llm/defaults.yaml +6 -3
- package/dist/llm/gen/anthropic.d.ts +3 -3
- package/dist/llm/gen/anthropic.js +115 -21
- package/dist/llm/gen/codex.js +78 -13
- package/dist/llm/gen/failure-classifier.d.ts +0 -2
- package/dist/llm/gen/failure-classifier.js +102 -25
- package/dist/llm/gen/openai-compatible.d.ts +6 -3
- package/dist/llm/gen/openai-compatible.js +132 -16
- package/dist/llm/gen/openai.d.ts +2 -2
- package/dist/llm/gen/openai.js +95 -15
- package/dist/llm/gen/tool-result-image-ingest.d.ts +39 -0
- package/dist/llm/gen/tool-result-image-ingest.js +158 -0
- package/dist/llm/gen.d.ts +17 -1
- package/dist/llm/kernel-driver/drive.js +23 -8
- package/dist/llm/kernel-driver/runtime.d.ts +1 -1
- package/dist/llm/kernel-driver/runtime.js +63 -34
- package/dist/persistence.d.ts +2 -0
- package/dist/persistence.js +107 -0
- package/dist/priming.js +76 -0
- package/dist/server/websocket-handler.js +90 -3
- package/dist/tools/team_mgmt.js +2 -2
- package/package.json +4 -4
- package/webapp/dist/assets/{_basePickBy-BJWCmtUm.js → _basePickBy-B7FV6Gnn.js} +3 -3
- package/webapp/dist/assets/_basePickBy-B7FV6Gnn.js.map +1 -0
- package/webapp/dist/assets/{_baseUniq-D6k_lGfs.js → _baseUniq-CmVnLJpw.js} +2 -2
- package/webapp/dist/assets/_baseUniq-CmVnLJpw.js.map +1 -0
- package/webapp/dist/assets/{arc-DYDaESgj.js → arc-DSJlh9AU.js} +2 -2
- package/webapp/dist/assets/arc-DSJlh9AU.js.map +1 -0
- package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-DZMT7dqc.js → architectureDiagram-2XIMDMQ5-Cd2cTHzo.js} +26 -8
- package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-Cd2cTHzo.js.map +1 -0
- package/webapp/dist/assets/{blockDiagram-VD42YOAC-CABpgVAa.js → blockDiagram-WCTKOSBZ-C0uEp_Tz.js} +187 -170
- package/webapp/dist/assets/blockDiagram-WCTKOSBZ-C0uEp_Tz.js.map +1 -0
- package/webapp/dist/assets/{c4Diagram-YG6GDRKO-COLZS8Ul.js → c4Diagram-IC4MRINW-B37U92JK.js} +4 -4
- package/webapp/dist/assets/c4Diagram-IC4MRINW-B37U92JK.js.map +1 -0
- package/webapp/dist/assets/{channel-CYFm9Cri.js → channel-DLHnjnQf.js} +2 -2
- package/webapp/dist/assets/channel-DLHnjnQf.js.map +1 -0
- package/webapp/dist/assets/{chunk-4BX2VUAB-CX_-XbaN.js → chunk-4BX2VUAB-DnZvfQyp.js} +2 -2
- package/webapp/dist/assets/chunk-4BX2VUAB-DnZvfQyp.js.map +1 -0
- package/webapp/dist/assets/{chunk-55IACEB6-ByD-NdBC.js → chunk-55IACEB6-BG-cjz3M.js} +2 -2
- package/webapp/dist/assets/chunk-55IACEB6-BG-cjz3M.js.map +1 -0
- package/webapp/dist/assets/{chunk-FMBD7UC4-DYGviJnf.js → chunk-FMBD7UC4-B1L8cPfl.js} +2 -2
- package/webapp/dist/assets/chunk-FMBD7UC4-B1L8cPfl.js.map +1 -0
- package/webapp/dist/assets/{chunk-TZMSLE5B-_HISzxl3.js → chunk-JSJVCQXG-C65w23ZF.js} +14 -6
- package/webapp/dist/assets/chunk-JSJVCQXG-C65w23ZF.js.map +1 -0
- package/webapp/dist/assets/{chunk-QN33PNHL-B8DWRL9f.js → chunk-KX2RTZJC-_4YSMrEL.js} +2 -2
- package/webapp/dist/assets/chunk-KX2RTZJC-_4YSMrEL.js.map +1 -0
- package/webapp/dist/assets/{chunk-DI55MBZ5-DV7sdJmQ.js → chunk-NQ4KR5QH-ComURSQb.js} +9 -7
- package/webapp/dist/assets/chunk-NQ4KR5QH-ComURSQb.js.map +1 -0
- package/webapp/dist/assets/{chunk-QZHKN3VN-B1aYIzMR.js → chunk-QZHKN3VN-BrxvuRI6.js} +2 -2
- package/webapp/dist/assets/chunk-QZHKN3VN-BrxvuRI6.js.map +1 -0
- package/webapp/dist/assets/{chunk-B4BG7PRW-BANemsDD.js → chunk-WL4C6EOR-CW7tAF_z.js} +171 -121
- package/webapp/dist/assets/chunk-WL4C6EOR-CW7tAF_z.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-2ON5EDUG-CpyYj1Rc.js → classDiagram-VBA2DB6C-BWrPbwfd.js} +7 -6
- package/webapp/dist/assets/classDiagram-VBA2DB6C-BWrPbwfd.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-CpyYj1Rc.js → classDiagram-v2-RAHNMMFH-BWrPbwfd.js} +7 -6
- package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-BWrPbwfd.js.map +1 -0
- package/webapp/dist/assets/{clone-B_9AxWIU.js → clone-B-TYPsxN.js} +2 -2
- package/webapp/dist/assets/clone-B-TYPsxN.js.map +1 -0
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-17ECLfPR.js → cose-bilkent-S5V4N54A-C1bfZcVY.js} +2 -2
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-C1bfZcVY.js.map +1 -0
- package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
- package/webapp/dist/assets/{dagre-6UL2VRFP-DhRqcF1o.js → dagre-KLK3FWXG-BfD08d2e.js} +7 -7
- package/webapp/dist/assets/dagre-KLK3FWXG-BfD08d2e.js.map +1 -0
- package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
- package/webapp/dist/assets/{diagram-PSM6KHXK-lpDT6Wwb.js → diagram-E7M64L7V-Dyd9OucT.js} +10 -10
- package/webapp/dist/assets/diagram-E7M64L7V-Dyd9OucT.js.map +1 -0
- package/webapp/dist/assets/{diagram-QEK2KX5R-ohxbPpDH.js → diagram-IFDJBPK2-BN-JCceb.js} +9 -8
- package/webapp/dist/assets/diagram-IFDJBPK2-BN-JCceb.js.map +1 -0
- package/webapp/dist/assets/{diagram-S2PKOQOG-DAFFGfch.js → diagram-P4PSJMXO-C2jh_Kry.js} +8 -8
- package/webapp/dist/assets/diagram-P4PSJMXO-C2jh_Kry.js.map +1 -0
- package/webapp/dist/assets/{erDiagram-Q2GNP2WA-BH-7rI43.js → erDiagram-INFDFZHY-C3Pj10OJ.js} +96 -75
- package/webapp/dist/assets/erDiagram-INFDFZHY-C3Pj10OJ.js.map +1 -0
- package/webapp/dist/assets/{flowDiagram-NV44I4VS-CdEjFbz4.js → flowDiagram-PKNHOUZH-a5vzSSCo.js} +98 -81
- package/webapp/dist/assets/flowDiagram-PKNHOUZH-a5vzSSCo.js.map +1 -0
- package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Cju2t-lK.js → ganttDiagram-A5KZAMGK-DIua0Qjr.js} +28 -3
- package/webapp/dist/assets/ganttDiagram-A5KZAMGK-DIua0Qjr.js.map +1 -0
- package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-CUJ5oxCg.js → gitGraphDiagram-K3NZZRJ6-CJt16FXK.js} +38 -46
- package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-CJt16FXK.js.map +1 -0
- package/webapp/dist/assets/graph-lQSuHjYm.js +782 -0
- package/webapp/dist/assets/graph-lQSuHjYm.js.map +1 -0
- package/webapp/dist/assets/{index-BLnM-uON.js → index-B7llu28V.js} +1279 -1059
- package/webapp/dist/assets/{index-BLnM-uON.js.map → index-B7llu28V.js.map} +1 -1
- package/webapp/dist/assets/{index-xvYYeHuy.css → index-YaxF76or.css} +1 -1
- package/webapp/dist/assets/{infoDiagram-HS3SLOUP-Df8p0okQ.js → infoDiagram-LFFYTUFH-DzJuXz5H.js} +7 -7
- package/webapp/dist/assets/infoDiagram-LFFYTUFH-DzJuXz5H.js.map +1 -0
- package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-BP_s17vw.js +966 -0
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-BP_s17vw.js.map +1 -0
- package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-BXMl8H-d.js → journeyDiagram-4ABVD52K-Lic1mhBM.js} +5 -5
- package/webapp/dist/assets/journeyDiagram-4ABVD52K-Lic1mhBM.js.map +1 -0
- package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-Cc5RwCEh.js → kanban-definition-K7BYSVSG-Baf2kCwQ.js} +5 -3
- package/webapp/dist/assets/kanban-definition-K7BYSVSG-Baf2kCwQ.js.map +1 -0
- package/webapp/dist/assets/{layout-BB2SvQcE.js → layout-DUMDc8rv.js} +5 -5
- package/webapp/dist/assets/layout-DUMDc8rv.js.map +1 -0
- package/webapp/dist/assets/{linear-Cj50lA0a.js → linear-CZMoHeVH.js} +2 -2
- package/webapp/dist/assets/linear-CZMoHeVH.js.map +1 -0
- package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-BLBklJVX.js → mindmap-definition-YRQLILUH-DB2sQ--_.js} +7 -5
- package/webapp/dist/assets/mindmap-definition-YRQLILUH-DB2sQ--_.js.map +1 -0
- package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
- package/webapp/dist/assets/{pieDiagram-ADFJNKIX-BQrOgSc-.js → pieDiagram-SKSYHLDU-Dgdrlric.js} +8 -8
- package/webapp/dist/assets/pieDiagram-SKSYHLDU-Dgdrlric.js.map +1 -0
- package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-C62TxtsO.js → quadrantDiagram-337W2JSQ-CJcFYfqf.js} +3 -3
- package/webapp/dist/assets/quadrantDiagram-337W2JSQ-CJcFYfqf.js.map +1 -0
- package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-Is6Q3osM.js → requirementDiagram-Z7DCOOCP-CDsT-ac7.js} +16 -6
- package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-CDsT-ac7.js.map +1 -0
- package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-CCAW8Dr2.js → sankeyDiagram-WA2Y5GQK-DiO55skm.js} +2 -2
- package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-DiO55skm.js.map +1 -0
- package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-DpODpbl6.js → sequenceDiagram-2WXFIKYE-CNHjdBNC.js} +601 -201
- package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-CNHjdBNC.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-B8LHaf5T.js → stateDiagram-RAJIS63D-CtS3TXEd.js} +9 -9
- package/webapp/dist/assets/stateDiagram-RAJIS63D-CtS3TXEd.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-4FzTkpgz.js → stateDiagram-v2-FVOUBMTO-BdjJA1de.js} +5 -5
- package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-BdjJA1de.js.map +1 -0
- package/webapp/dist/assets/{timeline-definition-IT6M3QCI-Ckxc4qZe.js → timeline-definition-YZTLITO2-D3AiTIhK.js} +3 -3
- package/webapp/dist/assets/timeline-definition-YZTLITO2-D3AiTIhK.js.map +1 -0
- package/webapp/dist/assets/{treemap-GDKQZRPO-QQa4vKMv.js → treemap-KZPCXAKY-F6nRvLGK.js} +37 -24
- package/webapp/dist/assets/treemap-KZPCXAKY-F6nRvLGK.js.map +1 -0
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-BoukZEuo.js +2487 -0
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-BoukZEuo.js.map +1 -0
- package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-Ba2uJcs6.js → xychartDiagram-JWTSCODW-ByfGkhZz.js} +4 -4
- package/webapp/dist/assets/xychartDiagram-JWTSCODW-ByfGkhZz.js.map +1 -0
- package/webapp/dist/index.html +2 -2
- package/webapp/dist/assets/_basePickBy-BJWCmtUm.js.map +0 -1
- package/webapp/dist/assets/_baseUniq-D6k_lGfs.js.map +0 -1
- package/webapp/dist/assets/arc-DYDaESgj.js.map +0 -1
- package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DZMT7dqc.js.map +0 -1
- package/webapp/dist/assets/blockDiagram-VD42YOAC-CABpgVAa.js.map +0 -1
- package/webapp/dist/assets/c4Diagram-YG6GDRKO-COLZS8Ul.js.map +0 -1
- package/webapp/dist/assets/channel-CYFm9Cri.js.map +0 -1
- package/webapp/dist/assets/chunk-4BX2VUAB-CX_-XbaN.js.map +0 -1
- package/webapp/dist/assets/chunk-55IACEB6-ByD-NdBC.js.map +0 -1
- package/webapp/dist/assets/chunk-B4BG7PRW-BANemsDD.js.map +0 -1
- package/webapp/dist/assets/chunk-DI55MBZ5-DV7sdJmQ.js.map +0 -1
- package/webapp/dist/assets/chunk-FMBD7UC4-DYGviJnf.js.map +0 -1
- package/webapp/dist/assets/chunk-QN33PNHL-B8DWRL9f.js.map +0 -1
- package/webapp/dist/assets/chunk-QZHKN3VN-B1aYIzMR.js.map +0 -1
- package/webapp/dist/assets/chunk-TZMSLE5B-_HISzxl3.js.map +0 -1
- package/webapp/dist/assets/classDiagram-2ON5EDUG-CpyYj1Rc.js.map +0 -1
- package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-CpyYj1Rc.js.map +0 -1
- package/webapp/dist/assets/clone-B_9AxWIU.js.map +0 -1
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-17ECLfPR.js.map +0 -1
- package/webapp/dist/assets/dagre-6UL2VRFP-DhRqcF1o.js.map +0 -1
- package/webapp/dist/assets/diagram-PSM6KHXK-lpDT6Wwb.js.map +0 -1
- package/webapp/dist/assets/diagram-QEK2KX5R-ohxbPpDH.js.map +0 -1
- package/webapp/dist/assets/diagram-S2PKOQOG-DAFFGfch.js.map +0 -1
- package/webapp/dist/assets/erDiagram-Q2GNP2WA-BH-7rI43.js.map +0 -1
- package/webapp/dist/assets/flowDiagram-NV44I4VS-CdEjFbz4.js.map +0 -1
- package/webapp/dist/assets/ganttDiagram-JELNMOA3-Cju2t-lK.js.map +0 -1
- package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-CUJ5oxCg.js.map +0 -1
- package/webapp/dist/assets/graph-mhcc7ldf.js +0 -425
- package/webapp/dist/assets/graph-mhcc7ldf.js.map +0 -1
- package/webapp/dist/assets/infoDiagram-HS3SLOUP-Df8p0okQ.js.map +0 -1
- package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-BXMl8H-d.js.map +0 -1
- package/webapp/dist/assets/kanban-definition-3W4ZIXB7-Cc5RwCEh.js.map +0 -1
- package/webapp/dist/assets/layout-BB2SvQcE.js.map +0 -1
- package/webapp/dist/assets/linear-Cj50lA0a.js.map +0 -1
- package/webapp/dist/assets/mindmap-definition-VGOIOE7T-BLBklJVX.js.map +0 -1
- package/webapp/dist/assets/pieDiagram-ADFJNKIX-BQrOgSc-.js.map +0 -1
- package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-C62TxtsO.js.map +0 -1
- package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-Is6Q3osM.js.map +0 -1
- package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-CCAW8Dr2.js.map +0 -1
- package/webapp/dist/assets/sequenceDiagram-WL72ISMW-DpODpbl6.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-FKZM4ZOC-B8LHaf5T.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3-4FzTkpgz.js.map +0 -1
- package/webapp/dist/assets/timeline-definition-IT6M3QCI-Ckxc4qZe.js.map +0 -1
- package/webapp/dist/assets/treemap-GDKQZRPO-QQa4vKMv.js.map +0 -1
- package/webapp/dist/assets/xychartDiagram-PRI3JC2R-Ba2uJcs6.js.map +0 -1
|
@@ -51,6 +51,7 @@ export declare function broadcastDisplayStateMarker(dialogId: DialogID, marker:
|
|
|
51
51
|
reason?: DialogInterruptionReason;
|
|
52
52
|
}): void;
|
|
53
53
|
export declare function computeIdleDisplayState(dlg: Dialog): Promise<DialogDisplayState>;
|
|
54
|
+
export declare function refreshRunControlProjectionFromPersistenceFacts(dialogId: DialogID, trigger: 'resume_dialog' | 'resume_all' | 'run_control_snapshot' | 'pending_subdialogs_changed' | 'q4h_changed'): Promise<DialogLatestFile | null>;
|
|
54
55
|
export declare function reconcileDisplayStatesAfterRestart(): Promise<void>;
|
|
55
56
|
export declare function requestInterruptDialog(dialogId: DialogID, reason: StopRequestedReason): Promise<{
|
|
56
57
|
applied: boolean;
|
|
@@ -39,6 +39,7 @@ exports.clearDialogInterruptedExecutionMarker = clearDialogInterruptedExecutionM
|
|
|
39
39
|
exports.setDialogDisplayState = setDialogDisplayState;
|
|
40
40
|
exports.broadcastDisplayStateMarker = broadcastDisplayStateMarker;
|
|
41
41
|
exports.computeIdleDisplayState = computeIdleDisplayState;
|
|
42
|
+
exports.refreshRunControlProjectionFromPersistenceFacts = refreshRunControlProjectionFromPersistenceFacts;
|
|
42
43
|
exports.reconcileDisplayStatesAfterRestart = reconcileDisplayStatesAfterRestart;
|
|
43
44
|
exports.requestInterruptDialog = requestInterruptDialog;
|
|
44
45
|
exports.requestEmergencyStopAll = requestEmergencyStopAll;
|
|
@@ -84,6 +85,9 @@ function isDialogLatestResumable(latest) {
|
|
|
84
85
|
latest.displayState.continueEnabled &&
|
|
85
86
|
latest.executionMarker?.kind === 'interrupted');
|
|
86
87
|
}
|
|
88
|
+
function isSameDisplayState(left, right) {
|
|
89
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
90
|
+
}
|
|
87
91
|
function classifyRunControlBucket(state) {
|
|
88
92
|
if (!state)
|
|
89
93
|
return 'none';
|
|
@@ -122,8 +126,13 @@ async function getRunControlCountsSnapshot() {
|
|
|
122
126
|
if (latest?.generating === true) {
|
|
123
127
|
proceeding++;
|
|
124
128
|
}
|
|
125
|
-
else if (
|
|
126
|
-
|
|
129
|
+
else if (latest?.executionMarker?.kind === 'interrupted' &&
|
|
130
|
+
isStoppedReasonResumable(latest.executionMarker.reason)) {
|
|
131
|
+
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
132
|
+
const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(dialogId, 'running');
|
|
133
|
+
if (q4h.length === 0 && pendingSubdialogs.length === 0) {
|
|
134
|
+
resumable++;
|
|
135
|
+
}
|
|
127
136
|
}
|
|
128
137
|
}
|
|
129
138
|
catch (error) {
|
|
@@ -444,6 +453,66 @@ async function computeIdleDisplayStateFromPersistence(dialogId) {
|
|
|
444
453
|
}
|
|
445
454
|
return { kind: 'idle_waiting_user' };
|
|
446
455
|
}
|
|
456
|
+
async function refreshRunControlProjectionFromPersistenceFacts(dialogId, trigger) {
|
|
457
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(dialogId, 'running');
|
|
458
|
+
if (!latest) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
if (latest.generating === true) {
|
|
462
|
+
return latest;
|
|
463
|
+
}
|
|
464
|
+
if (hasActiveRun(dialogId)) {
|
|
465
|
+
return latest;
|
|
466
|
+
}
|
|
467
|
+
const desired = await (async () => {
|
|
468
|
+
if (dialogId.selfId !== dialogId.rootId &&
|
|
469
|
+
latest.executionMarker &&
|
|
470
|
+
latest.executionMarker.kind === 'dead') {
|
|
471
|
+
return { kind: 'dead', reason: latest.executionMarker.reason };
|
|
472
|
+
}
|
|
473
|
+
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
474
|
+
const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(dialogId, 'running');
|
|
475
|
+
const hasQ4H = q4h.length > 0;
|
|
476
|
+
const hasSubdialogs = pendingSubdialogs.length > 0;
|
|
477
|
+
if (hasQ4H && hasSubdialogs) {
|
|
478
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input_and_subdialogs' } };
|
|
479
|
+
}
|
|
480
|
+
if (hasQ4H) {
|
|
481
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input' } };
|
|
482
|
+
}
|
|
483
|
+
if (hasSubdialogs) {
|
|
484
|
+
return { kind: 'blocked', reason: { kind: 'waiting_for_subdialogs' } };
|
|
485
|
+
}
|
|
486
|
+
if (latest.executionMarker?.kind === 'interrupted') {
|
|
487
|
+
return {
|
|
488
|
+
kind: 'stopped',
|
|
489
|
+
reason: latest.executionMarker.reason,
|
|
490
|
+
continueEnabled: isStoppedReasonResumable(latest.executionMarker.reason),
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
return { kind: 'idle_waiting_user' };
|
|
494
|
+
})();
|
|
495
|
+
const executionMarkerNeedsHealing = desired.kind === 'stopped'
|
|
496
|
+
? latest.executionMarker?.kind !== 'interrupted' ||
|
|
497
|
+
JSON.stringify(latest.executionMarker.reason) !== JSON.stringify(desired.reason)
|
|
498
|
+
: desired.kind === 'dead'
|
|
499
|
+
? latest.executionMarker?.kind !== 'dead' ||
|
|
500
|
+
JSON.stringify(latest.executionMarker.reason) !== JSON.stringify(desired.reason)
|
|
501
|
+
: latest.executionMarker?.kind === 'interrupted';
|
|
502
|
+
const displayStateNeedsHealing = !isSameDisplayState(latest.displayState, desired);
|
|
503
|
+
if (!displayStateNeedsHealing && !executionMarkerNeedsHealing) {
|
|
504
|
+
return latest;
|
|
505
|
+
}
|
|
506
|
+
log.warn('Healing stale run-control projection from persistence facts', undefined, {
|
|
507
|
+
dialogId: dialogId.valueOf(),
|
|
508
|
+
trigger,
|
|
509
|
+
previousDisplayState: latest.displayState ?? null,
|
|
510
|
+
previousExecutionMarker: latest.executionMarker ?? null,
|
|
511
|
+
healedDisplayState: desired,
|
|
512
|
+
});
|
|
513
|
+
await setDialogDisplayState(dialogId, desired);
|
|
514
|
+
return await persistence_1.DialogPersistence.loadDialogLatest(dialogId, 'running');
|
|
515
|
+
}
|
|
447
516
|
async function computeIdleDisplayStateForReconciliation(dialogId) {
|
|
448
517
|
try {
|
|
449
518
|
return await computeIdleDisplayStateFromPersistence(dialogId);
|
package/dist/dialog-fork.js
CHANGED
|
@@ -113,6 +113,7 @@ function isPersistedMessageRecord(record) {
|
|
|
113
113
|
// not contribute to message-count / context reconstruction semantics.
|
|
114
114
|
case 'web_search_call_record':
|
|
115
115
|
case 'native_tool_call_record':
|
|
116
|
+
case 'tool_result_image_ingest_record':
|
|
116
117
|
case 'quest_for_sup_record':
|
|
117
118
|
case 'tellask_reply_resolution_record':
|
|
118
119
|
case 'tellask_call_anchor_record':
|
|
@@ -199,6 +200,14 @@ function rewriteRecordForFork(record, newRootId) {
|
|
|
199
200
|
...record,
|
|
200
201
|
contentItems: rewriteFuncResultContentItems(record.contentItems, newRootId),
|
|
201
202
|
};
|
|
203
|
+
case 'tool_result_image_ingest_record':
|
|
204
|
+
return {
|
|
205
|
+
...record,
|
|
206
|
+
artifact: {
|
|
207
|
+
...record.artifact,
|
|
208
|
+
rootId: newRootId,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
202
211
|
case 'subdialog_created_record':
|
|
203
212
|
case 'reminders_reconciled_record':
|
|
204
213
|
case 'questions4human_reconciled_record':
|
package/dist/dialog.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type { DialogPrompt, DialogRunControlSpec, DialogSubdialogReplyTarget, Dr
|
|
|
18
18
|
import type { LanguageCode } from '@longrun-ai/kernel/types/language';
|
|
19
19
|
import type { CalleeCourseNumber, CalleeGenerationSeqNumber, CallingCourseNumber, DialogMetadataFile, HumanQuestion, ProviderData, ReasoningPayload, TellaskCallRecordName, TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
|
|
20
20
|
import { ChatMessage, FuncResultMsg, TellaskCarryoverMsg, TellaskResultMsg } from './llm/client';
|
|
21
|
+
import type { ToolResultImageIngest } from './llm/gen';
|
|
21
22
|
import type { JsonValue } from './tool';
|
|
22
23
|
import { Reminder, ReminderOptions, ReminderOwner } from './tool';
|
|
23
24
|
type NewCourseHookResult = {
|
|
@@ -406,6 +407,7 @@ export declare abstract class Dialog {
|
|
|
406
407
|
action?: WebSearchCallAction;
|
|
407
408
|
}): Promise<void>;
|
|
408
409
|
nativeToolCall(payload: NativeToolCallPayload): Promise<void>;
|
|
410
|
+
toolResultImageIngest(payload: ToolResultImageIngest): Promise<void>;
|
|
409
411
|
callingStart(payload: {
|
|
410
412
|
callName: 'tellaskBack' | 'tellask' | 'tellaskSessionless' | 'askHuman' | 'freshBootsReasoning';
|
|
411
413
|
callId: string;
|
|
@@ -624,6 +626,7 @@ export declare abstract class DialogStore {
|
|
|
624
626
|
action?: WebSearchCallAction;
|
|
625
627
|
}): Promise<void>;
|
|
626
628
|
nativeToolCall(_dialog: Dialog, _payload: NativeToolCallPayload): Promise<void>;
|
|
629
|
+
toolResultImageIngest(_dialog: Dialog, _payload: ToolResultImageIngest): Promise<void>;
|
|
627
630
|
/**
|
|
628
631
|
* Load current course number from persisted metadata
|
|
629
632
|
* This method should be implemented by subclasses to read from storage
|
package/dist/dialog.js
CHANGED
|
@@ -1144,6 +1144,9 @@ class Dialog {
|
|
|
1144
1144
|
async nativeToolCall(payload) {
|
|
1145
1145
|
await this.dlgStore.nativeToolCall(this, payload);
|
|
1146
1146
|
}
|
|
1147
|
+
async toolResultImageIngest(payload) {
|
|
1148
|
+
await this.dlgStore.toolResultImageIngest(this, payload);
|
|
1149
|
+
}
|
|
1147
1150
|
// Tellask-special call lifecycle events
|
|
1148
1151
|
async callingStart(payload) {
|
|
1149
1152
|
// Store callId for inline call-result correlation
|
|
@@ -1578,6 +1581,7 @@ class DialogStore {
|
|
|
1578
1581
|
async funcCallRequested(_dialog, _funcId, _funcName, _argumentsStr) { }
|
|
1579
1582
|
async webSearchCall(_dialog, _payload) { }
|
|
1580
1583
|
async nativeToolCall(_dialog, _payload) { }
|
|
1584
|
+
async toolResultImageIngest(_dialog, _payload) { }
|
|
1581
1585
|
/**
|
|
1582
1586
|
* Load current course number from persisted metadata
|
|
1583
1587
|
* This method should be implemented by subclasses to read from storage
|
package/dist/docs/mcp-support.md
CHANGED
|
@@ -335,9 +335,13 @@ Policy:
|
|
|
335
335
|
reduce tool set, etc.).
|
|
336
336
|
- **Network/retriable errors**: Dominds may auto-retry only for clearly retriable classes such as
|
|
337
337
|
transient network failures/timeouts and provider transient errors (e.g. rate limits or 5xx), using
|
|
338
|
-
|
|
338
|
+
strategy-specific backoff. Explicit short transport failures may use a brief aggressive burst, explicit
|
|
339
|
+
rate-limit signals may use smart-rate backoff, and everything else should default to conservative
|
|
340
|
+
keepalive retry instead of stopping just because a fixed retry-count ceiling was reached. Only
|
|
341
|
+
high-confidence non-progress cases should stop automatic retry.
|
|
339
342
|
|
|
340
|
-
This keeps the system responsive
|
|
343
|
+
This keeps the system responsive while still avoiding pointless automatic loops caused by invalid tool
|
|
344
|
+
schemas or other high-confidence non-retriable failures.
|
|
341
345
|
|
|
342
346
|
## Environment Variables (`env`)
|
|
343
347
|
|
package/dist/llm/api-quirks.js
CHANGED
|
@@ -7,6 +7,7 @@ const DOMINDS_LLM_EMPTY_RESPONSE_ERROR_CODE = 'DOMINDS_LLM_EMPTY_RESPONSE';
|
|
|
7
7
|
const XCODE_BEST_EMPTY_RESPONSE_SINGLE_RETRY_DELAY_MS = 3000;
|
|
8
8
|
const XCODE_BEST_EMPTY_RESPONSE_GIVE_UP_THRESHOLD = 5;
|
|
9
9
|
const XCODE_BEST_GATEWAY_HTML_502_RETRY_MESSAGE = 'xcode.best gateway returned an HTML 502 Bad Gateway page; retrying conservatively.';
|
|
10
|
+
const XCODE_BEST_AUTH_UNAVAILABLE_RETRY_MESSAGE = 'xcode.best upstream returned 500 auth_unavailable: no auth available; treating it as an infrastructure failure and retrying conservatively.';
|
|
10
11
|
const XCODE_BEST_UNEXPECTED_EOF_RETRY_MESSAGE = 'xcode.best upstream stream ended unexpectedly (unexpected EOF); retrying conservatively.';
|
|
11
12
|
const LOCAL_FILE_IO_ERROR_CODES = new Set(['ENOENT', 'ENOTDIR', 'EISDIR', 'EACCES', 'EPERM']);
|
|
12
13
|
const LOCAL_FILE_IO_SYSCALLS = new Set([
|
|
@@ -42,6 +43,21 @@ function isXcodeBestUnexpectedEofFailure(failure, error) {
|
|
|
42
43
|
failure.message.toLowerCase().includes('unexpected eof')) &&
|
|
43
44
|
!hasLikelyLocalFileErrorContext(error));
|
|
44
45
|
}
|
|
46
|
+
function isXcodeBestAuthUnavailableFailure(failure, error) {
|
|
47
|
+
const status = failure.status ?? readErrorStatus(error);
|
|
48
|
+
if (status !== 500) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const code = (failure.code ?? readErrorCode(error))?.trim().toLowerCase();
|
|
52
|
+
if (code === 'auth_unavailable') {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
const message = (readErrorMessage(error) ?? failure.message).toLowerCase();
|
|
56
|
+
if (message.includes('auth_unavailable')) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return code === 'internal_server_error' && message.includes('no auth available');
|
|
60
|
+
}
|
|
45
61
|
function getErrorChain(error) {
|
|
46
62
|
const queue = [error];
|
|
47
63
|
const visited = new Set();
|
|
@@ -248,12 +264,12 @@ function buildXcodeBestEmptyResponseGiveUpText(providerConfig, provider) {
|
|
|
248
264
|
const providerName = providerConfig.name.trim().length > 0 ? providerConfig.name : provider;
|
|
249
265
|
const summaryTextI18n = {
|
|
250
266
|
zh: `${providerName} 在同一对话上下文中连续返回 empty response。` +
|
|
251
|
-
`Dominds 已在 ${String(XCODE_BEST_EMPTY_RESPONSE_GIVE_UP_THRESHOLD)} 次 empty response
|
|
252
|
-
'
|
|
267
|
+
`Dominds 已在 ${String(XCODE_BEST_EMPTY_RESPONSE_GIVE_UP_THRESHOLD)} 次 empty response 后停止沿用同一上下文继续自动重试,因为这通常表示 provider 侧该对话上下文已经卡住;` +
|
|
268
|
+
'如果不引入新的信息或新的指令,直接点继续大概率仍然无真实进展;更建议补充上下文、改写问题、换一个切入方式,或在确实需要人类判断时调用 askHuman。',
|
|
253
269
|
en: `${providerName} returned empty responses repeatedly for the same dialog context. ` +
|
|
254
|
-
`Dominds stopped
|
|
255
|
-
'context is stuck; simply pressing Continue is still unlikely to make real progress, ' +
|
|
256
|
-
'so it is better to
|
|
270
|
+
`Dominds stopped repeating the same-context automatic retry path after ${String(XCODE_BEST_EMPTY_RESPONSE_GIVE_UP_THRESHOLD)} empty responses because this usually means the provider-side conversation ` +
|
|
271
|
+
'context is stuck; simply pressing Continue without new information or fresh instructions is still unlikely to make real progress, ' +
|
|
272
|
+
'so it is better to add context, reframe the ask, change the angle, or call askHuman when human judgment is genuinely needed.',
|
|
257
273
|
};
|
|
258
274
|
return {
|
|
259
275
|
providerName,
|
|
@@ -269,6 +285,11 @@ function createXcodeBestFailureQuirkHandlerSession(providerConfig) {
|
|
|
269
285
|
onFailure(args) {
|
|
270
286
|
const { providerName, summaryTextI18n, recoveryAction } = buildXcodeBestEmptyResponseGiveUpText(providerConfig, args.provider);
|
|
271
287
|
if (args.failure.code === DOMINDS_LLM_EMPTY_RESPONSE_ERROR_CODE) {
|
|
288
|
+
// xcode.best can enter a same-context deadlock where the upstream keeps returning empty
|
|
289
|
+
// responses forever until the dialog context changes materially. A short burst of
|
|
290
|
+
// temporary retries is still worthwhile for transient glitches, but once the streak reaches
|
|
291
|
+
// the threshold we must stop repeating the exact same automatic path and require fresh
|
|
292
|
+
// information / fresh instructions instead of hiding the deadlock behind slow retries.
|
|
272
293
|
consecutiveEmptyResponseCount += 1;
|
|
273
294
|
if (consecutiveEmptyResponseCount < XCODE_BEST_EMPTY_RESPONSE_GIVE_UP_THRESHOLD) {
|
|
274
295
|
return {
|
|
@@ -279,7 +300,7 @@ function createXcodeBestFailureQuirkHandlerSession(providerConfig) {
|
|
|
279
300
|
return {
|
|
280
301
|
kind: 'give_up',
|
|
281
302
|
message: `${providerName} returned empty responses repeatedly for the same dialog context; ` +
|
|
282
|
-
'automatic
|
|
303
|
+
'Dominds stopped repeating the same-context automatic retry path; continuing without new information is still unlikely to make real progress, so it is better to introduce fresh instructions or new context based on the real situation.',
|
|
283
304
|
summaryTextI18n,
|
|
284
305
|
recoveryAction: consumedDiligencePushRecoverySinceLastSuccess
|
|
285
306
|
? { kind: 'none' }
|
|
@@ -301,6 +322,13 @@ function createXcodeBestFailureQuirkHandlerSession(providerConfig) {
|
|
|
301
322
|
message: XCODE_BEST_GATEWAY_HTML_502_RETRY_MESSAGE,
|
|
302
323
|
};
|
|
303
324
|
}
|
|
325
|
+
if (isXcodeBestAuthUnavailableFailure(args.failure, args.error)) {
|
|
326
|
+
return {
|
|
327
|
+
kind: 'retry_strategy',
|
|
328
|
+
retryStrategy: 'conservative',
|
|
329
|
+
message: XCODE_BEST_AUTH_UNAVAILABLE_RETRY_MESSAGE,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
304
332
|
return { kind: 'default' };
|
|
305
333
|
},
|
|
306
334
|
onRequestSucceeded() {
|
package/dist/llm/client.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export type ProviderConfig = {
|
|
|
56
56
|
baseUrl: string;
|
|
57
57
|
apiKeyEnvVar: string;
|
|
58
58
|
tool_result_max_chars?: number;
|
|
59
|
-
|
|
59
|
+
llm_retry_aggressive_max_retries?: number;
|
|
60
60
|
llm_retry_initial_delay_ms?: number;
|
|
61
61
|
llm_retry_conservative_delay_ms?: number;
|
|
62
62
|
llm_retry_backoff_multiplier?: number;
|
package/dist/llm/defaults.yaml
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Optional provider-level retry controls for kernel dialog driving:
|
|
2
|
-
# -
|
|
2
|
+
# - llm_retry_aggressive_max_retries: front-loaded fast retries before Dominds automatically downgrades
|
|
3
|
+
# to conservative slow retry (default 3). Automatic retries no longer stop just because a retry
|
|
4
|
+
# count budget was exhausted.
|
|
3
5
|
# - llm_retry_initial_delay_ms: delay before the 1st retry (default 1000).
|
|
4
6
|
# - llm_retry_conservative_delay_ms: base delay for provider-classified conservative retries (default 30000; fixed for first 10 retries, then ramps by x1.5 with the normal max-delay cap).
|
|
5
7
|
# - llm_retry_backoff_multiplier: exponential factor between retries (default 1.5).
|
|
@@ -7,8 +9,9 @@
|
|
|
7
9
|
# - apiQuirks: optional provider/gateway quirk profile(s) for non-standard transport behavior
|
|
8
10
|
# and provider-specific failure handling that can override the driver's default retry disposition.
|
|
9
11
|
# Example: `apiQuirks: xcode.best` currently covers both keepalive/heartbeat stream quirks and
|
|
10
|
-
# repeated empty-response
|
|
11
|
-
# classification for gateway-returned HTML 502 Bad Gateway pages
|
|
12
|
+
# repeated empty-response deadlock detection for the same unchanged dialog context, plus conservative retry
|
|
13
|
+
# classification for gateway-returned HTML 502 Bad Gateway pages and
|
|
14
|
+
# `500 auth_unavailable: no auth available` infrastructure failures.
|
|
12
15
|
# - tool_result_max_chars: optional transport-level cap for a single tool-result text payload
|
|
13
16
|
# before Dominds projects it into the provider request. Use this when a provider/gateway enforces
|
|
14
17
|
# a stricter per-item string limit than Dominds' built-in defaults.
|
|
@@ -8,7 +8,7 @@ export type AnthropicStreamConsumeResult = {
|
|
|
8
8
|
usage: LlmUsageStats;
|
|
9
9
|
llmGenModel?: string;
|
|
10
10
|
};
|
|
11
|
-
export declare function buildAnthropicRequestMessagesWrapper(context: ChatMessage[],
|
|
11
|
+
export declare function buildAnthropicRequestMessagesWrapper(context: ChatMessage[], requestContextOrProviderConfig?: LlmRequestContext | ProviderConfig, providerConfigMaybe?: ProviderConfig): Promise<MessageParam[]>;
|
|
12
12
|
export declare function consumeAnthropicStream(stream: AsyncIterable<MessageStreamEvent>, receiver: LlmStreamReceiver, abortSignal?: AbortSignal, forcedJsonToolName?: string): Promise<AnthropicStreamConsumeResult>;
|
|
13
13
|
/**
|
|
14
14
|
* Reconstruct Anthropic context from persisted messages with genseq tracking.
|
|
@@ -29,6 +29,6 @@ export declare function reconstructAnthropicContextWrapperAsync(persistedMessage
|
|
|
29
29
|
export declare class AnthropicGen implements LlmGenerator {
|
|
30
30
|
get apiType(): string;
|
|
31
31
|
classifyFailure(error: unknown): LlmFailureDisposition | undefined;
|
|
32
|
-
genToReceiver(providerConfig: ProviderConfig, agent: Team.Member, systemPrompt: string, funcTools: FuncTool[],
|
|
33
|
-
genMoreMessages(providerConfig: ProviderConfig, agent: Team.Member, systemPrompt: string, funcTools: FuncTool[],
|
|
32
|
+
genToReceiver(providerConfig: ProviderConfig, agent: Team.Member, systemPrompt: string, funcTools: FuncTool[], requestContext: LlmRequestContext, context: ChatMessage[], receiver: LlmStreamReceiver, _genseq: number, abortSignal?: AbortSignal): Promise<LlmStreamResult>;
|
|
33
|
+
genMoreMessages(providerConfig: ProviderConfig, agent: Team.Member, systemPrompt: string, funcTools: FuncTool[], requestContext: LlmRequestContext, context: ChatMessage[], genseq: number, abortSignal?: AbortSignal): Promise<LlmBatchResult>;
|
|
34
34
|
}
|
|
@@ -18,6 +18,7 @@ const artifacts_1 = require("./artifacts");
|
|
|
18
18
|
const failure_classifier_1 = require("./failure-classifier");
|
|
19
19
|
const tool_call_context_1 = require("./tool-call-context");
|
|
20
20
|
const tool_output_limit_1 = require("./tool-output-limit");
|
|
21
|
+
const tool_result_image_ingest_1 = require("./tool-result-image-ingest");
|
|
21
22
|
const log = (0, log_1.createLogger)('llm/anthropic');
|
|
22
23
|
const ANTHROPIC_JSON_RESPONSE_TOOL_NAME = 'dominds_json_response';
|
|
23
24
|
const ANTHROPIC_JSON_RESPONSE_TOOL_DESCRIPTION = 'Return the final answer as a JSON object. Do not include any non-JSON text.';
|
|
@@ -75,6 +76,13 @@ function isRecord(value) {
|
|
|
75
76
|
function isNonArrayRecord(value) {
|
|
76
77
|
return isRecord(value) && !Array.isArray(value);
|
|
77
78
|
}
|
|
79
|
+
function isLlmRequestContext(value) {
|
|
80
|
+
return (isNonArrayRecord(value) &&
|
|
81
|
+
typeof value.dialogSelfId === 'string' &&
|
|
82
|
+
typeof value.dialogRootId === 'string' &&
|
|
83
|
+
typeof value.providerKey === 'string' &&
|
|
84
|
+
typeof value.modelKey === 'string');
|
|
85
|
+
}
|
|
78
86
|
function tryExtractApiReturnedModel(value) {
|
|
79
87
|
// NOTE: External API payload; a runtime check is unavoidable.
|
|
80
88
|
if (!isRecord(value))
|
|
@@ -177,7 +185,7 @@ function parseForcedJsonToolInput(rawJson, fallbackInput, at) {
|
|
|
177
185
|
}
|
|
178
186
|
throw new Error(`Invalid ${at}: ${errorText}; raw=${JSON.stringify(preview)}`);
|
|
179
187
|
}
|
|
180
|
-
async function funcResultToAnthropicToolResultBlock(chatMsg, limitChars) {
|
|
188
|
+
async function funcResultToAnthropicToolResultBlock(chatMsg, limitChars, requestContext, allowedImageKeys, onToolResultImageIngest) {
|
|
181
189
|
const items = chatMsg.contentItems;
|
|
182
190
|
if (!Array.isArray(items) || items.length === 0) {
|
|
183
191
|
return {
|
|
@@ -194,22 +202,85 @@ async function funcResultToAnthropicToolResultBlock(chatMsg, limitChars) {
|
|
|
194
202
|
}
|
|
195
203
|
if (item.type === 'input_image') {
|
|
196
204
|
if (!(0, artifacts_1.isVisionImageMimeType)(item.mimeType)) {
|
|
205
|
+
if (onToolResultImageIngest) {
|
|
206
|
+
await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
|
|
207
|
+
requestContext,
|
|
208
|
+
toolCallId: chatMsg.id,
|
|
209
|
+
toolName: chatMsg.name,
|
|
210
|
+
artifact: item.artifact,
|
|
211
|
+
disposition: 'filtered_mime_unsupported',
|
|
212
|
+
mimeType: item.mimeType,
|
|
213
|
+
providerPathLabel: 'Anthropic Messages path',
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
197
216
|
content.push({
|
|
198
217
|
type: 'text',
|
|
199
218
|
text: `[image omitted: unsupported mimeType=${item.mimeType}]`,
|
|
200
219
|
});
|
|
201
220
|
continue;
|
|
202
221
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
222
|
+
if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildToolResultImageBudgetKeyForMsg)(chatMsg, item.artifact))) {
|
|
223
|
+
if (onToolResultImageIngest) {
|
|
224
|
+
await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
|
|
225
|
+
requestContext,
|
|
226
|
+
toolCallId: chatMsg.id,
|
|
227
|
+
toolName: chatMsg.name,
|
|
228
|
+
artifact: item.artifact,
|
|
229
|
+
disposition: 'filtered_size_limit',
|
|
230
|
+
detail: (0, tool_result_image_ingest_1.buildToolResultImageBudgetLimitDetail)({
|
|
231
|
+
byteLength: item.byteLength,
|
|
232
|
+
budgetBytes: tool_result_image_ingest_1.ANTHROPIC_TOOL_RESULT_IMAGE_BUDGET_BYTES,
|
|
233
|
+
}),
|
|
234
|
+
providerPathLabel: 'Anthropic Messages path',
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
content.push({
|
|
238
|
+
type: 'text',
|
|
239
|
+
text: `[image omitted: request image budget exceeded bytes=${String(item.byteLength)} budget=${String(tool_result_image_ingest_1.ANTHROPIC_TOOL_RESULT_IMAGE_BUDGET_BYTES)}]`,
|
|
240
|
+
});
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const bytesResult = await (0, tool_result_image_ingest_1.readToolResultImageBytesSafe)(item.artifact);
|
|
244
|
+
if (bytesResult.kind === 'missing') {
|
|
245
|
+
if (onToolResultImageIngest) {
|
|
246
|
+
await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
|
|
247
|
+
requestContext,
|
|
248
|
+
toolCallId: chatMsg.id,
|
|
249
|
+
toolName: chatMsg.name,
|
|
250
|
+
artifact: item.artifact,
|
|
251
|
+
disposition: 'filtered_missing',
|
|
252
|
+
providerPathLabel: 'Anthropic Messages path',
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
210
255
|
content.push({ type: 'text', text: `[image missing: ${item.artifact.relPath}]` });
|
|
211
256
|
continue;
|
|
212
257
|
}
|
|
258
|
+
if (bytesResult.kind === 'read_failed') {
|
|
259
|
+
if (onToolResultImageIngest) {
|
|
260
|
+
await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
|
|
261
|
+
requestContext,
|
|
262
|
+
toolCallId: chatMsg.id,
|
|
263
|
+
toolName: chatMsg.name,
|
|
264
|
+
artifact: item.artifact,
|
|
265
|
+
disposition: 'filtered_read_failed',
|
|
266
|
+
detail: bytesResult.detail,
|
|
267
|
+
providerPathLabel: 'Anthropic Messages path',
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
content.push({ type: 'text', text: `[image unreadable: ${item.artifact.relPath}]` });
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (onToolResultImageIngest) {
|
|
274
|
+
await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
|
|
275
|
+
requestContext,
|
|
276
|
+
toolCallId: chatMsg.id,
|
|
277
|
+
toolName: chatMsg.name,
|
|
278
|
+
artifact: item.artifact,
|
|
279
|
+
disposition: 'fed_native',
|
|
280
|
+
providerPathLabel: 'Anthropic Messages path',
|
|
281
|
+
}));
|
|
282
|
+
}
|
|
283
|
+
const bytes = bytesResult.bytes;
|
|
213
284
|
const base64 = bytes.toString('base64');
|
|
214
285
|
content.push({
|
|
215
286
|
type: 'image',
|
|
@@ -237,14 +308,16 @@ async function funcResultToAnthropicToolResultBlock(chatMsg, limitChars) {
|
|
|
237
308
|
content: limitAnthropicToolOutputBlocks(content, chatMsg, limitChars),
|
|
238
309
|
};
|
|
239
310
|
}
|
|
240
|
-
async function chatMessageToContentBlocksAsync(chatMsg, limitChars) {
|
|
311
|
+
async function chatMessageToContentBlocksAsync(chatMsg, limitChars, requestContext, allowedImageKeys, onToolResultImageIngest) {
|
|
241
312
|
if (chatMsg.type !== 'func_result_msg') {
|
|
242
313
|
return chatMessageToContentBlocks(chatMsg);
|
|
243
314
|
}
|
|
244
|
-
return [
|
|
315
|
+
return [
|
|
316
|
+
await funcResultToAnthropicToolResultBlock(chatMsg, limitChars, requestContext, allowedImageKeys, onToolResultImageIngest),
|
|
317
|
+
];
|
|
245
318
|
}
|
|
246
|
-
async function chatMessageToAnthropicAsync(chatMsg, limitChars) {
|
|
247
|
-
const contentBlocks = await chatMessageToContentBlocksAsync(chatMsg, limitChars);
|
|
319
|
+
async function chatMessageToAnthropicAsync(chatMsg, limitChars, requestContext, allowedImageKeys, onToolResultImageIngest) {
|
|
320
|
+
const contentBlocks = await chatMessageToContentBlocksAsync(chatMsg, limitChars, requestContext, allowedImageKeys, onToolResultImageIngest);
|
|
248
321
|
if (contentBlocks.length === 0) {
|
|
249
322
|
throw new Error(`No content blocks generated for message: ${JSON.stringify(chatMsg)}`);
|
|
250
323
|
}
|
|
@@ -257,7 +330,7 @@ async function chatMessageToAnthropicAsync(chatMsg, limitChars) {
|
|
|
257
330
|
content: contentBlocks.length === 1 ? contentBlocks : contentBlocks,
|
|
258
331
|
};
|
|
259
332
|
}
|
|
260
|
-
async function buildAnthropicRequestMessages(context, providerConfig) {
|
|
333
|
+
async function buildAnthropicRequestMessages(context, requestContext, providerConfig, onToolResultImageIngest) {
|
|
261
334
|
// We keep the async path for func_result_msg because it may contain image artifacts.
|
|
262
335
|
const normalized = (0, tool_call_context_1.normalizeToolCallPairs)(context);
|
|
263
336
|
const violation = (0, tool_call_context_1.findFirstToolCallAdjacencyViolation)(normalized);
|
|
@@ -273,13 +346,25 @@ async function buildAnthropicRequestMessages(context, providerConfig) {
|
|
|
273
346
|
}
|
|
274
347
|
const messages = [];
|
|
275
348
|
const toolResultMaxChars = (0, tool_output_limit_1.resolveProviderToolResultMaxChars)(providerConfig);
|
|
349
|
+
const allowedImageKeys = (0, tool_result_image_ingest_1.selectLatestToolResultImagesWithinBudget)(normalized, tool_result_image_ingest_1.ANTHROPIC_TOOL_RESULT_IMAGE_BUDGET_BYTES);
|
|
276
350
|
for (const msg of normalized) {
|
|
277
|
-
messages.push(await chatMessageToAnthropicAsync(msg, toolResultMaxChars));
|
|
351
|
+
messages.push(await chatMessageToAnthropicAsync(msg, toolResultMaxChars, requestContext, allowedImageKeys, onToolResultImageIngest));
|
|
278
352
|
}
|
|
279
353
|
return assembleAnthropicTurns(messages);
|
|
280
354
|
}
|
|
281
|
-
async function buildAnthropicRequestMessagesWrapper(context,
|
|
282
|
-
|
|
355
|
+
async function buildAnthropicRequestMessagesWrapper(context, requestContextOrProviderConfig, providerConfigMaybe) {
|
|
356
|
+
const requestContext = isLlmRequestContext(requestContextOrProviderConfig)
|
|
357
|
+
? requestContextOrProviderConfig
|
|
358
|
+
: {
|
|
359
|
+
dialogSelfId: '',
|
|
360
|
+
dialogRootId: '',
|
|
361
|
+
providerKey: 'anthropic',
|
|
362
|
+
modelKey: 'unknown',
|
|
363
|
+
};
|
|
364
|
+
const providerConfig = isLlmRequestContext(requestContextOrProviderConfig)
|
|
365
|
+
? providerConfigMaybe
|
|
366
|
+
: requestContextOrProviderConfig;
|
|
367
|
+
return await buildAnthropicRequestMessages(context, requestContext, providerConfig);
|
|
283
368
|
}
|
|
284
369
|
/**
|
|
285
370
|
* Reconstruct Anthropic context from persisted messages.
|
|
@@ -800,7 +885,12 @@ function reconstructAnthropicContextWrapper(persistedMessages) {
|
|
|
800
885
|
return reconstructed;
|
|
801
886
|
}
|
|
802
887
|
async function reconstructAnthropicContextWrapperAsync(persistedMessages) {
|
|
803
|
-
const reconstructed = await buildAnthropicRequestMessages(persistedMessages
|
|
888
|
+
const reconstructed = await buildAnthropicRequestMessages(persistedMessages, {
|
|
889
|
+
dialogSelfId: '',
|
|
890
|
+
dialogRootId: '',
|
|
891
|
+
providerKey: 'anthropic',
|
|
892
|
+
modelKey: 'unknown',
|
|
893
|
+
});
|
|
804
894
|
// Validate the reconstructed context
|
|
805
895
|
try {
|
|
806
896
|
validateReconstructedContext(reconstructed);
|
|
@@ -824,12 +914,12 @@ class AnthropicGen {
|
|
|
824
914
|
classifyFailure(error) {
|
|
825
915
|
return (0, failure_classifier_1.classifyAnthropicFailure)(error);
|
|
826
916
|
}
|
|
827
|
-
async genToReceiver(providerConfig, agent, systemPrompt, funcTools,
|
|
917
|
+
async genToReceiver(providerConfig, agent, systemPrompt, funcTools, requestContext, context, receiver, _genseq, abortSignal) {
|
|
828
918
|
const apiKey = process.env[providerConfig.apiKeyEnvVar];
|
|
829
919
|
if (!apiKey)
|
|
830
920
|
throw new Error(`Missing API key env var ${providerConfig.apiKeyEnvVar}`);
|
|
831
921
|
const client = new sdk_1.Anthropic({ apiKey, baseURL: providerConfig.baseUrl });
|
|
832
|
-
const requestMessages = await buildAnthropicRequestMessages(context, providerConfig);
|
|
922
|
+
const requestMessages = await buildAnthropicRequestMessages(context, requestContext, providerConfig, receiver.toolResultImageIngest);
|
|
833
923
|
const anthropicParams = agent.model_params?.anthropic || {};
|
|
834
924
|
const forceJsonResponse = resolveAnthropicJsonResponseEnabled(agent);
|
|
835
925
|
const maxTokens = agent.model_params?.max_tokens;
|
|
@@ -874,12 +964,15 @@ class AnthropicGen {
|
|
|
874
964
|
const stream = client.messages.stream(streamParams);
|
|
875
965
|
return consumeAnthropicStream(stream, receiver, abortSignal, forceJsonResponse ? ANTHROPIC_JSON_RESPONSE_TOOL_NAME : undefined);
|
|
876
966
|
}
|
|
877
|
-
async genMoreMessages(providerConfig, agent, systemPrompt, funcTools,
|
|
967
|
+
async genMoreMessages(providerConfig, agent, systemPrompt, funcTools, requestContext, context, genseq, abortSignal) {
|
|
878
968
|
const apiKey = process.env[providerConfig.apiKeyEnvVar];
|
|
879
969
|
if (!apiKey)
|
|
880
970
|
throw new Error(`Missing API key env var ${providerConfig.apiKeyEnvVar}`);
|
|
881
971
|
const client = new sdk_1.Anthropic({ apiKey, baseURL: providerConfig.baseUrl });
|
|
882
|
-
const
|
|
972
|
+
const outputs = [];
|
|
973
|
+
const requestMessages = await buildAnthropicRequestMessages(context, requestContext, providerConfig, async (ingest) => {
|
|
974
|
+
outputs.push({ kind: 'tool_result_image_ingest', ingest });
|
|
975
|
+
});
|
|
883
976
|
const anthropicParams = agent.model_params?.anthropic || {};
|
|
884
977
|
const forceJsonResponse = resolveAnthropicJsonResponseEnabled(agent);
|
|
885
978
|
const maxTokens = agent.model_params?.max_tokens;
|
|
@@ -940,6 +1033,7 @@ class AnthropicGen {
|
|
|
940
1033
|
};
|
|
941
1034
|
return {
|
|
942
1035
|
messages: anthropicToChatMessages(response, genseq, forceJsonResponse ? ANTHROPIC_JSON_RESPONSE_TOOL_NAME : undefined),
|
|
1036
|
+
...(outputs.length > 0 ? { outputs } : {}),
|
|
943
1037
|
usage,
|
|
944
1038
|
llmGenModel: returnedModel,
|
|
945
1039
|
};
|