dominds 0.7.1 → 0.7.3
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-global-registry.js +58 -3
- package/dist/dialog.js +17 -0
- package/dist/docs/dialog-system.md +18 -16
- package/dist/docs/dialog-system.zh.md +20 -19
- package/dist/evt-registry.js +16 -7
- package/dist/llm/driver-v2/context.js +2 -1
- package/dist/llm/driver-v2/core.js +102 -119
- package/dist/llm/driver-v2/orchestrator.js +65 -38
- package/dist/llm/driver-v2/round.js +213 -35
- package/dist/llm/driver-v2/runtime-utils.js +1 -0
- package/dist/llm/driver-v2/supdialog-response.js +5 -18
- package/dist/llm/driver-v2/tellask-bridge.js +95 -6
- package/dist/llm/driver.js +29 -2
- package/dist/minds/builtin/cmdr/persona.md +3 -0
- package/dist/minds/builtin/dijiang/knowledge.md +287 -0
- package/dist/minds/builtin/dijiang/persona.md +7 -0
- package/dist/persistence.js +28 -0
- package/dist/server/websocket-handler.js +134 -25
- package/dist/shared/diligence.js +8 -2
- package/dist/showing-by-doing.js +31 -34
- package/dist/static/assets/{_baseUniq-BxKNVs_E.js → _baseUniq-zV3pyJ-s.js} +2 -2
- package/dist/static/assets/{_baseUniq-BxKNVs_E.js.map → _baseUniq-zV3pyJ-s.js.map} +1 -1
- package/dist/static/assets/{arc-SobL0GO-.js → arc-Ctgmrh71.js} +2 -2
- package/dist/static/assets/{arc-SobL0GO-.js.map → arc-Ctgmrh71.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-MMDS1QOC.js → architectureDiagram-VXUJARFQ-CAH1Zinn.js} +6 -6
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-MMDS1QOC.js.map → architectureDiagram-VXUJARFQ-CAH1Zinn.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-BOsSirNK.js → blockDiagram-VD42YOAC-Djz6JdD2.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-BOsSirNK.js.map → blockDiagram-VD42YOAC-Djz6JdD2.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D4jQkzwx.js → c4Diagram-YG6GDRKO-CSuskOyq.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D4jQkzwx.js.map → c4Diagram-YG6GDRKO-CSuskOyq.js.map} +1 -1
- package/dist/static/assets/{channel-CNJ5IKbI.js → channel-Ym6U59Kh.js} +2 -2
- package/dist/static/assets/{channel-CNJ5IKbI.js.map → channel-Ym6U59Kh.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-Dzp3xxyo.js → chunk-4BX2VUAB-CqbVylSz.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-Dzp3xxyo.js.map → chunk-4BX2VUAB-CqbVylSz.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-CbmixuSI.js → chunk-55IACEB6-CeWj8Jm_.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-CbmixuSI.js.map → chunk-55IACEB6-CeWj8Jm_.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-CdpmYjdb.js → chunk-B4BG7PRW-BjxJkuhq.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-CdpmYjdb.js.map → chunk-B4BG7PRW-BjxJkuhq.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-wBUIgR3h.js → chunk-DI55MBZ5-9kxfXB4B.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-wBUIgR3h.js.map → chunk-DI55MBZ5-9kxfXB4B.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-l62jcBz-.js → chunk-FMBD7UC4-DyM3IVWB.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-l62jcBz-.js.map → chunk-FMBD7UC4-DyM3IVWB.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-BXfKZUpE.js → chunk-QN33PNHL-DGU21aEB.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-BXfKZUpE.js.map → chunk-QN33PNHL-DGU21aEB.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-BYB4VxWj.js → chunk-QZHKN3VN-Cw9Hpt-y.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-BYB4VxWj.js.map → chunk-QZHKN3VN-Cw9Hpt-y.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-CvlWEnXl.js → chunk-TZMSLE5B-J-eTCnFj.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-CvlWEnXl.js.map → chunk-TZMSLE5B-J-eTCnFj.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-x2kw_AQY.js → classDiagram-2ON5EDUG-BvoDAd8E.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-x2kw_AQY.js.map → classDiagram-2ON5EDUG-BvoDAd8E.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-x2kw_AQY.js → classDiagram-v2-WZHVMYZB-BvoDAd8E.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-x2kw_AQY.js.map → classDiagram-v2-WZHVMYZB-BvoDAd8E.js.map} +1 -1
- package/dist/static/assets/{clone-CfBpi3MU.js → clone-CojsCkky.js} +2 -2
- package/dist/static/assets/{clone-CfBpi3MU.js.map → clone-CojsCkky.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-DQSzPb7y.js → cose-bilkent-S5V4N54A-BEtK3OcG.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-DQSzPb7y.js.map → cose-bilkent-S5V4N54A-BEtK3OcG.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-BuBo_U3J.js → dagre-6UL2VRFP-C5DMaVj0.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-BuBo_U3J.js.map → dagre-6UL2VRFP-C5DMaVj0.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-J2z13Z5A.js → diagram-PSM6KHXK-kVP0dZ6K.js} +7 -7
- package/dist/static/assets/{diagram-PSM6KHXK-J2z13Z5A.js.map → diagram-PSM6KHXK-kVP0dZ6K.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-x8XUGykE.js → diagram-QEK2KX5R-C4p2yibe.js} +6 -6
- package/dist/static/assets/{diagram-QEK2KX5R-x8XUGykE.js.map → diagram-QEK2KX5R-C4p2yibe.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-BE6Nr1BM.js → diagram-S2PKOQOG-B3vObsYY.js} +6 -6
- package/dist/static/assets/{diagram-S2PKOQOG-BE6Nr1BM.js.map → diagram-S2PKOQOG-B3vObsYY.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-D3qVnFAh.js → erDiagram-Q2GNP2WA-AKQItpVu.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-D3qVnFAh.js.map → erDiagram-Q2GNP2WA-AKQItpVu.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-Cjp9Rt9t.js → flowDiagram-NV44I4VS-2dalJoL3.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-Cjp9Rt9t.js.map → flowDiagram-NV44I4VS-2dalJoL3.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-D_hc66FC.js → ganttDiagram-JELNMOA3-DUw98Lbz.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-D_hc66FC.js.map → ganttDiagram-JELNMOA3-DUw98Lbz.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-1I_zaTtz.js → gitGraphDiagram-NY62KEGX-DdwIFk8M.js} +7 -7
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-1I_zaTtz.js.map → gitGraphDiagram-NY62KEGX-DdwIFk8M.js.map} +1 -1
- package/dist/static/assets/{graph-K6mmQESm.js → graph-BBEAP9Z9.js} +3 -3
- package/dist/static/assets/{graph-K6mmQESm.js.map → graph-BBEAP9Z9.js.map} +1 -1
- package/dist/static/assets/{index-RV1MEt3b.js → index-CqMOe9zt.js} +195 -114
- package/dist/static/assets/index-CqMOe9zt.js.map +1 -0
- package/dist/static/assets/{infoDiagram-WHAUD3N6-CqazW4ov.js → infoDiagram-WHAUD3N6-Cep11ST9.js} +5 -5
- package/dist/static/assets/{infoDiagram-WHAUD3N6-CqazW4ov.js.map → infoDiagram-WHAUD3N6-Cep11ST9.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CCwUViz2.js → journeyDiagram-XKPGCS4Q-Ba8wkBNB.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CCwUViz2.js.map → journeyDiagram-XKPGCS4Q-Ba8wkBNB.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-BKj9P06Z.js → kanban-definition-3W4ZIXB7-DhxNBORX.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-BKj9P06Z.js.map → kanban-definition-3W4ZIXB7-DhxNBORX.js.map} +1 -1
- package/dist/static/assets/{layout-BcrPlYah.js → layout-Ckbr6Zyz.js} +5 -5
- package/dist/static/assets/{layout-BcrPlYah.js.map → layout-Ckbr6Zyz.js.map} +1 -1
- package/dist/static/assets/{linear-DYXbzldi.js → linear-BrSsI51I.js} +2 -2
- package/dist/static/assets/{linear-DYXbzldi.js.map → linear-BrSsI51I.js.map} +1 -1
- package/dist/static/assets/{min-CAfJrdkg.js → min-CeEvLc8D.js} +3 -3
- package/dist/static/assets/{min-CAfJrdkg.js.map → min-CeEvLc8D.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-CXWJYrd0.js → mindmap-definition-VGOIOE7T-7ctLd3o3.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-CXWJYrd0.js.map → mindmap-definition-VGOIOE7T-7ctLd3o3.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-DjKlsPYr.js → pieDiagram-ADFJNKIX-CqyILziW.js} +7 -7
- package/dist/static/assets/{pieDiagram-ADFJNKIX-DjKlsPYr.js.map → pieDiagram-ADFJNKIX-CqyILziW.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-fcJtlyUO.js → quadrantDiagram-AYHSOK5B-Byi_xYum.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-fcJtlyUO.js.map → quadrantDiagram-AYHSOK5B-Byi_xYum.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DmB9Ezaa.js → requirementDiagram-UZGBJVZJ-Boj5vxiZ.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DmB9Ezaa.js.map → requirementDiagram-UZGBJVZJ-Boj5vxiZ.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-CdGDwaMo.js → sankeyDiagram-TZEHDZUN-DzoUAdfa.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-CdGDwaMo.js.map → sankeyDiagram-TZEHDZUN-DzoUAdfa.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-C-jiKkhi.js → sequenceDiagram-WL72ISMW-BKKxpG1m.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-C-jiKkhi.js.map → sequenceDiagram-WL72ISMW-BKKxpG1m.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-M9808W5W.js → stateDiagram-FKZM4ZOC-B-J7uRZT.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-M9808W5W.js.map → stateDiagram-FKZM4ZOC-B-J7uRZT.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-JE0YQyVh.js → stateDiagram-v2-4FDKWEC3-BOzmoUba.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-JE0YQyVh.js.map → stateDiagram-v2-4FDKWEC3-BOzmoUba.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-a2Rh8B62.js → timeline-definition-IT6M3QCI-zu1Rojx9.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-a2Rh8B62.js.map → timeline-definition-IT6M3QCI-zu1Rojx9.js.map} +1 -1
- package/dist/static/assets/{treemap-KMMF4GRG-D3tvybuo.js → treemap-KMMF4GRG-C4D91awC.js} +4 -4
- package/dist/static/assets/{treemap-KMMF4GRG-D3tvybuo.js.map → treemap-KMMF4GRG-C4D91awC.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-kmwKLP3Y.js → xychartDiagram-PRI3JC2R-YvLKaPZ-.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-kmwKLP3Y.js.map → xychartDiagram-PRI3JC2R-YvLKaPZ-.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/tools/context-health.js +7 -7
- package/dist/utils/task-doc.js +16 -16
- package/package.json +1 -1
- package/dist/docs/keep-going.zh.md +0 -162
- package/dist/docs/showing-by-doing.md +0 -208
- package/dist/docs/showing-by-doing.zh.md +0 -177
- package/dist/minds/promptdocs.js +0 -263
- package/dist/snippets/README.en.md +0 -3
- package/dist/static/assets/index-RV1MEt3b.js.map +0 -1
|
@@ -42,48 +42,75 @@ async function supplyResponseToSupdialog(...args) {
|
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
+
function formatDriveTriggerForLog(trigger) {
|
|
46
|
+
return {
|
|
47
|
+
action: trigger.action,
|
|
48
|
+
rootId: trigger.rootId,
|
|
49
|
+
entryFound: trigger.entryFound,
|
|
50
|
+
previousNeedsDrive: trigger.previousNeedsDrive,
|
|
51
|
+
nextNeedsDrive: trigger.nextNeedsDrive,
|
|
52
|
+
source: trigger.source,
|
|
53
|
+
reason: trigger.reason,
|
|
54
|
+
emittedAtMs: trigger.emittedAtMs,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function driveQueuedDialogsOnce() {
|
|
58
|
+
const dialogsToDrive = dialog_global_registry_1.globalDialogRegistry.getDialogsNeedingDrive();
|
|
59
|
+
for (const rootDialog of dialogsToDrive) {
|
|
60
|
+
try {
|
|
61
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialog.id, 'running');
|
|
62
|
+
const runStateKind = latest?.runState?.kind;
|
|
63
|
+
if (runStateKind === 'interrupted' || runStateKind === 'proceeding_stop_requested') {
|
|
64
|
+
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId, {
|
|
65
|
+
source: 'driver_v2_backend_loop',
|
|
66
|
+
reason: `run_state_blocked:${runStateKind}`,
|
|
67
|
+
});
|
|
68
|
+
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!(await rootDialog.canDrive())) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
await driveDialogStream(rootDialog, undefined, true);
|
|
75
|
+
const status = await rootDialog.getSuspensionStatus();
|
|
76
|
+
const shouldStayQueued = rootDialog.hasUpNext() || !status.canDrive;
|
|
77
|
+
if (shouldStayQueued) {
|
|
78
|
+
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(rootDialog.id.rootId, {
|
|
79
|
+
source: 'driver_v2_backend_loop',
|
|
80
|
+
reason: rootDialog.hasUpNext() ? 'post_drive_upnext_pending' : 'post_drive_suspended',
|
|
81
|
+
});
|
|
82
|
+
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, true, rootDialog.status);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId, {
|
|
86
|
+
source: 'driver_v2_backend_loop',
|
|
87
|
+
reason: 'post_drive_idle',
|
|
88
|
+
});
|
|
89
|
+
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
90
|
+
}
|
|
91
|
+
if (status.subdialogs) {
|
|
92
|
+
log_1.log.info(`Dialog ${rootDialog.id.rootId} suspended, waiting for subdialogs`);
|
|
93
|
+
}
|
|
94
|
+
if (status.q4h) {
|
|
95
|
+
log_1.log.info(`Dialog ${rootDialog.id.rootId} awaiting Q4H answer`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
log_1.log.error(`Error driving dialog ${rootDialog.id.rootId}:`, err, undefined, {
|
|
100
|
+
dialogId: rootDialog.id.rootId,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
45
105
|
function runBackendDriver() {
|
|
46
106
|
return (async () => {
|
|
47
107
|
while (true) {
|
|
48
108
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (runStateKind === 'interrupted' || runStateKind === 'proceeding_stop_requested') {
|
|
55
|
-
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
|
|
56
|
-
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
if (!(await rootDialog.canDrive())) {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
await driveDialogStream(rootDialog, undefined, true);
|
|
63
|
-
const status = await rootDialog.getSuspensionStatus();
|
|
64
|
-
const shouldStayQueued = rootDialog.hasUpNext() || !status.canDrive;
|
|
65
|
-
if (shouldStayQueued) {
|
|
66
|
-
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(rootDialog.id.rootId);
|
|
67
|
-
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, true, rootDialog.status);
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
|
|
71
|
-
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
72
|
-
}
|
|
73
|
-
if (status.subdialogs) {
|
|
74
|
-
log_1.log.info(`Dialog ${rootDialog.id.rootId} suspended, waiting for subdialogs`);
|
|
75
|
-
}
|
|
76
|
-
if (status.q4h) {
|
|
77
|
-
log_1.log.info(`Dialog ${rootDialog.id.rootId} awaiting Q4H answer`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
log_1.log.error(`Error driving dialog ${rootDialog.id.rootId}:`, err, undefined, {
|
|
82
|
-
dialogId: rootDialog.id.rootId,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
109
|
+
await driveQueuedDialogsOnce();
|
|
110
|
+
const trigger = await dialog_global_registry_1.globalDialogRegistry.waitForDriveTrigger();
|
|
111
|
+
log_1.log.debug('Backend driver woke from drive trigger event', undefined, {
|
|
112
|
+
trigger: formatDriveTriggerForLog(trigger),
|
|
113
|
+
});
|
|
87
114
|
}
|
|
88
115
|
catch (loopErr) {
|
|
89
116
|
log_1.log.error('Error in backend driver loop:', loopErr);
|
|
@@ -6,11 +6,95 @@ const dialog_run_state_1 = require("../../dialog-run-state");
|
|
|
6
6
|
const log_1 = require("../../log");
|
|
7
7
|
const load_1 = require("../../minds/load");
|
|
8
8
|
const persistence_1 = require("../../persistence");
|
|
9
|
+
const driver_messages_1 = require("../../shared/i18n/driver-messages");
|
|
9
10
|
const runtime_language_1 = require("../../shared/runtime-language");
|
|
11
|
+
const id_1 = require("../../shared/utils/id");
|
|
10
12
|
const context_health_1 = require("./context-health");
|
|
11
13
|
const core_1 = require("./core");
|
|
12
14
|
const policy_1 = require("./policy");
|
|
13
15
|
const supdialog_response_1 = require("./supdialog-response");
|
|
16
|
+
const defaultCriticalCountdownGenerations = 5;
|
|
17
|
+
async function loadPendingDiagnosticsSnapshot(args) {
|
|
18
|
+
const ownerDialogIdObj = new dialog_1.DialogID(args.ownerDialogId, args.rootId);
|
|
19
|
+
try {
|
|
20
|
+
const pending = await persistence_1.DialogPersistence.loadPendingSubdialogs(ownerDialogIdObj);
|
|
21
|
+
const matchedSubdialogIds = pending
|
|
22
|
+
.filter((record) => record.subdialogId === args.expectedSubdialogId)
|
|
23
|
+
.map((record) => record.subdialogId);
|
|
24
|
+
return {
|
|
25
|
+
kind: 'loaded',
|
|
26
|
+
ownerDialogId: args.ownerDialogId,
|
|
27
|
+
totalCount: pending.length,
|
|
28
|
+
matchedSubdialogIds,
|
|
29
|
+
records: pending.map((record) => ({
|
|
30
|
+
subdialogId: record.subdialogId,
|
|
31
|
+
callType: record.callType,
|
|
32
|
+
targetAgentId: record.targetAgentId,
|
|
33
|
+
tellaskSession: record.tellaskSession,
|
|
34
|
+
createdAt: record.createdAt,
|
|
35
|
+
tellaskHeadSummary: record.tellaskHead.trim().slice(0, 160),
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return {
|
|
41
|
+
kind: 'error',
|
|
42
|
+
ownerDialogId: args.ownerDialogId,
|
|
43
|
+
error: err instanceof Error ? err.message : String(err),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const contextHealthRoundStateByDialogKey = new Map();
|
|
48
|
+
function getContextHealthRoundState(dialog) {
|
|
49
|
+
const key = dialog.id.key();
|
|
50
|
+
const existing = contextHealthRoundStateByDialogKey.get(key);
|
|
51
|
+
if (existing) {
|
|
52
|
+
return existing;
|
|
53
|
+
}
|
|
54
|
+
const created = {};
|
|
55
|
+
contextHealthRoundStateByDialogKey.set(key, created);
|
|
56
|
+
return created;
|
|
57
|
+
}
|
|
58
|
+
function resetContextHealthRoundState(dialog) {
|
|
59
|
+
contextHealthRoundStateByDialogKey.delete(dialog.id.key());
|
|
60
|
+
}
|
|
61
|
+
function resolveCriticalCountdownRemaining(dialog, snapshot) {
|
|
62
|
+
if (!snapshot || snapshot.kind !== 'available') {
|
|
63
|
+
resetContextHealthRoundState(dialog);
|
|
64
|
+
return defaultCriticalCountdownGenerations;
|
|
65
|
+
}
|
|
66
|
+
if (snapshot.level !== 'critical') {
|
|
67
|
+
if (snapshot.level === 'healthy') {
|
|
68
|
+
resetContextHealthRoundState(dialog);
|
|
69
|
+
return defaultCriticalCountdownGenerations;
|
|
70
|
+
}
|
|
71
|
+
const state = getContextHealthRoundState(dialog);
|
|
72
|
+
state.lastSeenLevel = snapshot.level;
|
|
73
|
+
state.criticalCountdownRemaining = undefined;
|
|
74
|
+
return defaultCriticalCountdownGenerations;
|
|
75
|
+
}
|
|
76
|
+
const state = getContextHealthRoundState(dialog);
|
|
77
|
+
if (state.lastSeenLevel !== 'critical' ||
|
|
78
|
+
typeof state.criticalCountdownRemaining !== 'number' ||
|
|
79
|
+
!Number.isFinite(state.criticalCountdownRemaining)) {
|
|
80
|
+
state.lastSeenLevel = 'critical';
|
|
81
|
+
state.criticalCountdownRemaining = defaultCriticalCountdownGenerations;
|
|
82
|
+
}
|
|
83
|
+
const remaining = Math.floor(state.criticalCountdownRemaining);
|
|
84
|
+
return remaining > 0 ? remaining : 0;
|
|
85
|
+
}
|
|
86
|
+
function consumeCriticalCountdown(dialog) {
|
|
87
|
+
const state = getContextHealthRoundState(dialog);
|
|
88
|
+
const currentRaw = typeof state.criticalCountdownRemaining === 'number' &&
|
|
89
|
+
Number.isFinite(state.criticalCountdownRemaining)
|
|
90
|
+
? Math.floor(state.criticalCountdownRemaining)
|
|
91
|
+
: defaultCriticalCountdownGenerations;
|
|
92
|
+
const current = currentRaw > 0 ? currentRaw : 0;
|
|
93
|
+
const next = Math.max(0, current - 1);
|
|
94
|
+
state.lastSeenLevel = 'critical';
|
|
95
|
+
state.criticalCountdownRemaining = next;
|
|
96
|
+
return next;
|
|
97
|
+
}
|
|
14
98
|
function resolveEffectivePrompt(dialog, humanPrompt) {
|
|
15
99
|
if (humanPrompt) {
|
|
16
100
|
return humanPrompt;
|
|
@@ -22,7 +106,7 @@ function resolveEffectivePrompt(dialog, humanPrompt) {
|
|
|
22
106
|
return {
|
|
23
107
|
content: upNext.prompt,
|
|
24
108
|
msgId: upNext.msgId,
|
|
25
|
-
grammar: 'markdown',
|
|
109
|
+
grammar: upNext.grammar ?? 'markdown',
|
|
26
110
|
userLanguageCode: upNext.userLanguageCode === 'zh' || upNext.userLanguageCode === 'en'
|
|
27
111
|
? upNext.userLanguageCode
|
|
28
112
|
: undefined,
|
|
@@ -77,6 +161,24 @@ async function executeDriveRound(args) {
|
|
|
77
161
|
dialogId: dialog.id.valueOf(),
|
|
78
162
|
});
|
|
79
163
|
}
|
|
164
|
+
// Queued/auto drive (without fresh human input) must not proceed while dialog is
|
|
165
|
+
// suspended by pending Q4H or subdialogs. This prevents duplicate generations when
|
|
166
|
+
// multiple wake-ups race around the same subdialog completion boundary.
|
|
167
|
+
if (!humanPrompt) {
|
|
168
|
+
const suspension = await dialog.getSuspensionStatus();
|
|
169
|
+
if (!suspension.canDrive) {
|
|
170
|
+
log_1.log.info('driver-v2 skip queued auto-drive while dialog is suspended', {
|
|
171
|
+
dialogId: dialog.id.valueOf(),
|
|
172
|
+
rootId: dialog.id.rootId,
|
|
173
|
+
selfId: dialog.id.selfId,
|
|
174
|
+
waitInQue,
|
|
175
|
+
hasQueuedUpNext: dialog.hasUpNext(),
|
|
176
|
+
waitingQ4H: suspension.q4h,
|
|
177
|
+
waitingSubdialogs: suspension.subdialogs,
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
80
182
|
const minds = await (0, load_1.loadAgentMinds)(dialog.agentId, dialog);
|
|
81
183
|
const policy = (0, policy_1.buildDriverV2Policy)({
|
|
82
184
|
dlg: dialog,
|
|
@@ -89,18 +191,56 @@ async function executeDriveRound(args) {
|
|
|
89
191
|
if (!validation.ok) {
|
|
90
192
|
throw new Error(`driver-v2 policy invariant violation: ${validation.detail}`);
|
|
91
193
|
}
|
|
194
|
+
const snapshot = dialog.getLastContextHealth();
|
|
195
|
+
const hasQueuedUpNext = dialog.hasUpNext();
|
|
196
|
+
const criticalCountdownRemaining = resolveCriticalCountdownRemaining(dialog, snapshot);
|
|
92
197
|
const healthDecision = (0, context_health_1.decideDriverV2ContextHealth)({
|
|
93
|
-
snapshot
|
|
94
|
-
hadUserPromptThisGen:
|
|
95
|
-
criticalCountdownRemaining
|
|
198
|
+
snapshot,
|
|
199
|
+
hadUserPromptThisGen: humanPrompt !== undefined,
|
|
200
|
+
criticalCountdownRemaining,
|
|
96
201
|
});
|
|
97
202
|
if (healthDecision.kind === 'suspend') {
|
|
98
203
|
return;
|
|
99
204
|
}
|
|
205
|
+
let healthPrompt;
|
|
206
|
+
if (healthDecision.kind === 'continue') {
|
|
207
|
+
if (healthDecision.reason === 'critical_force_new_course') {
|
|
208
|
+
const language = (0, runtime_language_1.getWorkLanguage)();
|
|
209
|
+
const newCoursePrompt = language === 'zh'
|
|
210
|
+
? '系统因上下文已告急(critical)而自动开启新一程对话,请继续推进任务。'
|
|
211
|
+
: 'System auto-started a new dialog course because context health is critical. Please continue the task.';
|
|
212
|
+
await dialog.startNewCourse(newCoursePrompt);
|
|
213
|
+
dialog.setLastContextHealth({ kind: 'unavailable', reason: 'usage_unavailable' });
|
|
214
|
+
resetContextHealthRoundState(dialog);
|
|
215
|
+
}
|
|
216
|
+
else if (!hasQueuedUpNext) {
|
|
217
|
+
const language = (0, runtime_language_1.getWorkLanguage)();
|
|
218
|
+
const guideText = healthDecision.reason === 'caution_soft_remediation'
|
|
219
|
+
? (0, driver_messages_1.formatUserFacingContextHealthV3RemediationGuide)(language, {
|
|
220
|
+
kind: 'caution',
|
|
221
|
+
mode: 'soft',
|
|
222
|
+
})
|
|
223
|
+
: (0, driver_messages_1.formatUserFacingContextHealthV3RemediationGuide)(language, {
|
|
224
|
+
kind: 'critical',
|
|
225
|
+
mode: 'countdown',
|
|
226
|
+
promptsRemainingAfterThis: consumeCriticalCountdown(dialog),
|
|
227
|
+
promptsTotal: defaultCriticalCountdownGenerations,
|
|
228
|
+
});
|
|
229
|
+
healthPrompt = {
|
|
230
|
+
content: guideText,
|
|
231
|
+
msgId: (0, id_1.generateShortId)(),
|
|
232
|
+
grammar: 'markdown',
|
|
233
|
+
userLanguageCode: language,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
100
237
|
args.runtime.driveCount += 1;
|
|
101
238
|
args.runtime.totalGenIterations += 1;
|
|
102
239
|
args.runtime.usedLegacyDriveCore = false;
|
|
103
|
-
const
|
|
240
|
+
const promptForCore = healthDecision.kind === 'continue' && healthDecision.reason === 'critical_force_new_course'
|
|
241
|
+
? undefined
|
|
242
|
+
: (healthPrompt ?? humanPrompt);
|
|
243
|
+
const effectivePrompt = resolveEffectivePrompt(dialog, promptForCore);
|
|
104
244
|
subdialogReplyTarget = effectivePrompt?.subdialogReplyTarget;
|
|
105
245
|
if (effectivePrompt && effectivePrompt.userLanguageCode) {
|
|
106
246
|
dialog.setLastUserLanguageCode(effectivePrompt.userLanguageCode);
|
|
@@ -120,47 +260,85 @@ async function executeDriveRound(args) {
|
|
|
120
260
|
}
|
|
121
261
|
release();
|
|
122
262
|
}
|
|
123
|
-
if (followUp) {
|
|
124
|
-
args.scheduleDrive(dialog, {
|
|
125
|
-
waitInQue: true,
|
|
126
|
-
humanPrompt: {
|
|
127
|
-
content: followUp.prompt,
|
|
128
|
-
msgId: followUp.msgId,
|
|
129
|
-
grammar: 'markdown',
|
|
130
|
-
userLanguageCode: followUp.userLanguageCode === 'zh' || followUp.userLanguageCode === 'en'
|
|
131
|
-
? followUp.userLanguageCode
|
|
132
|
-
: undefined,
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
263
|
if (dialog instanceof dialog_1.SubDialog &&
|
|
138
264
|
driveResult &&
|
|
139
265
|
!driveResult.interrupted &&
|
|
140
266
|
driveResult.lastAssistantSayingContent !== null) {
|
|
141
|
-
|
|
142
|
-
if (!suspension.canDrive) {
|
|
143
|
-
log_1.log.info('driver-v2 skip supplying subdialog response because dialog is still suspended', {
|
|
144
|
-
rootId: dialog.id.rootId,
|
|
145
|
-
selfId: dialog.id.selfId,
|
|
146
|
-
waitingQ4H: suspension.q4h,
|
|
147
|
-
waitingSubdialogs: suspension.subdialogs,
|
|
148
|
-
});
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
267
|
+
let supplied = false;
|
|
151
268
|
if (subdialogReplyTarget) {
|
|
152
|
-
await (0, supdialog_response_1.supplySubdialogResponseToSpecificCallerIfPendingV2)({
|
|
269
|
+
supplied = await (0, supdialog_response_1.supplySubdialogResponseToSpecificCallerIfPendingV2)({
|
|
153
270
|
subdialog: dialog,
|
|
154
271
|
responseText: driveResult.lastAssistantSayingContent,
|
|
155
272
|
target: subdialogReplyTarget,
|
|
156
273
|
scheduleDrive: args.scheduleDrive,
|
|
157
274
|
});
|
|
158
|
-
|
|
275
|
+
if (!supplied) {
|
|
276
|
+
supplied = await (0, supdialog_response_1.supplySubdialogResponseToAssignedCallerIfPendingV2)({
|
|
277
|
+
subdialog: dialog,
|
|
278
|
+
responseText: driveResult.lastAssistantSayingContent,
|
|
279
|
+
scheduleDrive: args.scheduleDrive,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
159
282
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
283
|
+
else {
|
|
284
|
+
supplied = await (0, supdialog_response_1.supplySubdialogResponseToAssignedCallerIfPendingV2)({
|
|
285
|
+
subdialog: dialog,
|
|
286
|
+
responseText: driveResult.lastAssistantSayingContent,
|
|
287
|
+
scheduleDrive: args.scheduleDrive,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
if (!supplied && subdialogReplyTarget) {
|
|
291
|
+
const assignment = dialog.assignmentFromSup;
|
|
292
|
+
const ownerDialogIds = Array.from(new Set([subdialogReplyTarget.ownerDialogId, assignment.callerDialogId]));
|
|
293
|
+
const pendingSnapshots = await Promise.all(ownerDialogIds.map(async (ownerDialogId) => loadPendingDiagnosticsSnapshot({
|
|
294
|
+
rootId: dialog.id.rootId,
|
|
295
|
+
ownerDialogId,
|
|
296
|
+
expectedSubdialogId: dialog.id.selfId,
|
|
297
|
+
})));
|
|
298
|
+
const streamErr = `Subdialog response supply invariant violation: ` +
|
|
299
|
+
`subdialog=${dialog.id.selfId} root=${dialog.id.rootId} ` +
|
|
300
|
+
`targetOwner=${subdialogReplyTarget.ownerDialogId} targetCallType=${subdialogReplyTarget.callType} targetCallId=${subdialogReplyTarget.callId} ` +
|
|
301
|
+
`assignmentCaller=${assignment.callerDialogId} assignmentCallId=${assignment.callId} ` +
|
|
302
|
+
`pendingSnapshots=${pendingSnapshots.length}`;
|
|
303
|
+
try {
|
|
304
|
+
await dialog.streamError(streamErr);
|
|
305
|
+
}
|
|
306
|
+
catch (streamErrPost) {
|
|
307
|
+
log_1.log.warn('driver-v2 failed to emit stream_error_evt for response supply violation', {
|
|
308
|
+
rootId: dialog.id.rootId,
|
|
309
|
+
selfId: dialog.id.selfId,
|
|
310
|
+
targetOwnerDialogId: subdialogReplyTarget.ownerDialogId,
|
|
311
|
+
targetCallType: subdialogReplyTarget.callType,
|
|
312
|
+
targetCallId: subdialogReplyTarget.callId,
|
|
313
|
+
assignmentCallerDialogId: assignment.callerDialogId,
|
|
314
|
+
assignmentCallId: assignment.callId,
|
|
315
|
+
pendingSnapshots,
|
|
316
|
+
error: streamErrPost instanceof Error ? streamErrPost.message : String(streamErrPost),
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
log_1.log.error('driver-v2 subdialog produced response but found no pending caller to supply', {
|
|
320
|
+
rootId: dialog.id.rootId,
|
|
321
|
+
selfId: dialog.id.selfId,
|
|
322
|
+
targetOwnerDialogId: subdialogReplyTarget.ownerDialogId,
|
|
323
|
+
targetCallType: subdialogReplyTarget.callType,
|
|
324
|
+
targetCallId: subdialogReplyTarget.callId,
|
|
325
|
+
assignmentCallerDialogId: assignment.callerDialogId,
|
|
326
|
+
assignmentCallId: assignment.callId,
|
|
327
|
+
pendingSnapshots,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (followUp) {
|
|
332
|
+
args.scheduleDrive(dialog, {
|
|
333
|
+
waitInQue: true,
|
|
334
|
+
humanPrompt: {
|
|
335
|
+
content: followUp.prompt,
|
|
336
|
+
msgId: followUp.msgId,
|
|
337
|
+
grammar: followUp.grammar ?? 'markdown',
|
|
338
|
+
userLanguageCode: followUp.userLanguageCode === 'zh' || followUp.userLanguageCode === 'en'
|
|
339
|
+
? followUp.userLanguageCode
|
|
340
|
+
: undefined,
|
|
341
|
+
},
|
|
164
342
|
});
|
|
165
343
|
}
|
|
166
344
|
}
|
|
@@ -181,6 +181,7 @@ async function suspendForKeepGoingBudgetExhausted(options) {
|
|
|
181
181
|
bodyContent: question.bodyContent,
|
|
182
182
|
askedAt: question.askedAt,
|
|
183
183
|
callId: question.callId,
|
|
184
|
+
remainingCallIds: question.remainingCallIds,
|
|
184
185
|
callSiteRef: question.callSiteRef,
|
|
185
186
|
rootId: dlg.id.rootId,
|
|
186
187
|
agentId: dlg.agentId,
|
|
@@ -9,9 +9,7 @@ const dialog_instance_registry_1 = require("../../dialog-instance-registry");
|
|
|
9
9
|
const log_1 = require("../../log");
|
|
10
10
|
const persistence_1 = require("../../persistence");
|
|
11
11
|
const runtime_language_1 = require("../../shared/runtime-language");
|
|
12
|
-
const id_1 = require("../../shared/utils/id");
|
|
13
12
|
const inter_dialog_format_1 = require("../../shared/utils/inter-dialog-format");
|
|
14
|
-
const time_1 = require("../../shared/utils/time");
|
|
15
13
|
const pending_tellask_reminder_1 = require("../../tools/pending-tellask-reminder");
|
|
16
14
|
const subdialog_txn_1 = require("./subdialog-txn");
|
|
17
15
|
async function syncPendingTellaskReminderBestEffort(dlg, where) {
|
|
@@ -98,20 +96,6 @@ async function supplyResponseToSupdialogV2(args) {
|
|
|
98
96
|
if (tellaskHead.trim() === '') {
|
|
99
97
|
tellaskHead = responseText.slice(0, 100) + (responseText.length > 100 ? '...' : '');
|
|
100
98
|
}
|
|
101
|
-
const completedAt = (0, time_1.formatUnifiedTimestamp)(new Date());
|
|
102
|
-
const responseId = (0, id_1.generateShortId)();
|
|
103
|
-
await persistence_1.DialogPersistence.appendSubdialogResponse(parentDialog.id, {
|
|
104
|
-
responseId,
|
|
105
|
-
subdialogId: subdialogId.selfId,
|
|
106
|
-
response: responseText,
|
|
107
|
-
completedAt,
|
|
108
|
-
status,
|
|
109
|
-
callType,
|
|
110
|
-
tellaskHead,
|
|
111
|
-
responderId,
|
|
112
|
-
originMemberId,
|
|
113
|
-
callId: callId ?? '',
|
|
114
|
-
});
|
|
115
99
|
await persistence_1.DialogPersistence.savePendingSubdialogs(parentDialog.id, filteredPending);
|
|
116
100
|
const hasQ4H = await parentDialog.hasPendingQ4H();
|
|
117
101
|
const shouldRevive = !hasQ4H && filteredPending.length === 0;
|
|
@@ -134,7 +118,7 @@ async function supplyResponseToSupdialogV2(args) {
|
|
|
134
118
|
originMemberId: result.originMemberId ?? parentDialog.agentId,
|
|
135
119
|
});
|
|
136
120
|
// Keep in-memory dialog context in sync with live teammate-response events immediately.
|
|
137
|
-
//
|
|
121
|
+
// v2 context assembly now relies on dialog msgs + persisted teammate_response_record only.
|
|
138
122
|
const immediateMirror = {
|
|
139
123
|
type: 'tellask_result_msg',
|
|
140
124
|
role: 'tool',
|
|
@@ -153,7 +137,10 @@ async function supplyResponseToSupdialogV2(args) {
|
|
|
153
137
|
if (result.shouldRevive) {
|
|
154
138
|
log_1.log.info(`All Type ${callType} subdialogs complete, parent ${parentDialog.id.selfId} auto-reviving`);
|
|
155
139
|
if (parentDialog instanceof dialog_1.RootDialog) {
|
|
156
|
-
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(parentDialog.id.rootId
|
|
140
|
+
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(parentDialog.id.rootId, {
|
|
141
|
+
source: 'driver_v2_supply_response',
|
|
142
|
+
reason: `all_pending_subdialogs_resolved:type_${callType}`,
|
|
143
|
+
});
|
|
157
144
|
}
|
|
158
145
|
scheduleDrive(parentDialog, {
|
|
159
146
|
waitInQue: true,
|
|
@@ -46,7 +46,6 @@ const inter_dialog_format_1 = require("../../shared/utils/inter-dialog-format");
|
|
|
46
46
|
const time_1 = require("../../shared/utils/time");
|
|
47
47
|
const team_1 = require("../../team");
|
|
48
48
|
const pending_tellask_reminder_1 = require("../../tools/pending-tellask-reminder");
|
|
49
|
-
const id_2 = require("../../utils/id");
|
|
50
49
|
const subdialog_txn_1 = require("./subdialog-txn");
|
|
51
50
|
function showErrorToAi(err) {
|
|
52
51
|
try {
|
|
@@ -193,6 +192,33 @@ async function updateSubdialogAssignment(subdialog, assignment) {
|
|
|
193
192
|
subdialog.assignmentFromSup = assignment;
|
|
194
193
|
await persistence_1.DialogPersistence.updateSubdialogAssignment(subdialog.id, assignment);
|
|
195
194
|
}
|
|
195
|
+
async function lookupLiveRegisteredSubdialog(rootDialog, agentId, tellaskSession) {
|
|
196
|
+
const existing = rootDialog.lookupSubdialog(agentId, tellaskSession);
|
|
197
|
+
if (!existing) {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
const existingSession = existing.tellaskSession;
|
|
201
|
+
if (!existingSession) {
|
|
202
|
+
throw new Error(`Type B registry invariant violation: lookupSubdialog returned entry without tellaskSession (root=${rootDialog.id.valueOf()} sub=${existing.id.valueOf()})`);
|
|
203
|
+
}
|
|
204
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(existing.id, rootDialog.status);
|
|
205
|
+
const runState = latest?.runState;
|
|
206
|
+
if (!runState || runState.kind !== 'dead') {
|
|
207
|
+
return existing;
|
|
208
|
+
}
|
|
209
|
+
const removed = rootDialog.unregisterSubdialog(existing.agentId, existingSession);
|
|
210
|
+
if (!removed) {
|
|
211
|
+
throw new Error(`Failed to unregister dead registered subdialog: root=${rootDialog.id.valueOf()} sub=${existing.id.valueOf()} session=${existingSession}`);
|
|
212
|
+
}
|
|
213
|
+
await rootDialog.saveSubdialogRegistry();
|
|
214
|
+
log_1.log.info('Pruned dead registered subdialog from Type B registry', undefined, {
|
|
215
|
+
rootId: rootDialog.id.rootId,
|
|
216
|
+
subdialogId: existing.id.selfId,
|
|
217
|
+
agentId: existing.agentId,
|
|
218
|
+
tellaskSession: existingSession,
|
|
219
|
+
});
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
196
222
|
function extractLastAssistantResponse(messages, defaultMessage) {
|
|
197
223
|
let responseText = '';
|
|
198
224
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -392,13 +418,21 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
392
418
|
const isQ4H = firstMention === 'human';
|
|
393
419
|
if (isQ4H) {
|
|
394
420
|
try {
|
|
395
|
-
const
|
|
421
|
+
const normalizedCallId = callId.trim();
|
|
422
|
+
if (normalizedCallId === '') {
|
|
423
|
+
throw new Error(`Q4H call invariant violation: empty callId (rootId=${dlg.id.rootId} selfId=${dlg.id.selfId})`);
|
|
424
|
+
}
|
|
425
|
+
const questionId = `q4h-${dlg.id.rootId}-${dlg.id.selfId}-c${dlg.currentCourse}-${normalizedCallId}`;
|
|
426
|
+
const normalizedRemainingCallIds = Array.from(new Set((options?.q4hRemainingCallIds ?? [])
|
|
427
|
+
.map((value) => value.trim())
|
|
428
|
+
.filter((value) => value !== '' && value !== normalizedCallId)));
|
|
396
429
|
const question = {
|
|
397
430
|
id: questionId,
|
|
398
431
|
tellaskHead: tellaskHead.trim(),
|
|
399
432
|
bodyContent: body.trim(),
|
|
400
433
|
askedAt: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
401
|
-
callId:
|
|
434
|
+
callId: normalizedCallId,
|
|
435
|
+
remainingCallIds: normalizedRemainingCallIds.length > 0 ? normalizedRemainingCallIds : undefined,
|
|
402
436
|
callSiteRef: {
|
|
403
437
|
course: dlg.currentCourse,
|
|
404
438
|
messageIndex: dlg.msgs.length,
|
|
@@ -414,6 +448,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
414
448
|
bodyContent: question.bodyContent,
|
|
415
449
|
askedAt: question.askedAt,
|
|
416
450
|
callId: question.callId,
|
|
451
|
+
remainingCallIds: question.remainingCallIds,
|
|
417
452
|
callSiteRef: question.callSiteRef,
|
|
418
453
|
rootId: dlg.id.rootId,
|
|
419
454
|
agentId: dlg.agentId,
|
|
@@ -662,7 +697,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
662
697
|
callId,
|
|
663
698
|
collectiveTargets: options?.collectiveTargets ?? [parseResult.agentId],
|
|
664
699
|
};
|
|
665
|
-
const existing = rootDialog
|
|
700
|
+
const existing = await lookupLiveRegisteredSubdialog(rootDialog, parseResult.agentId, derivedSession);
|
|
666
701
|
if (existing) {
|
|
667
702
|
try {
|
|
668
703
|
await updateSubdialogAssignment(existing, assignment);
|
|
@@ -902,7 +937,7 @@ async function executeTellaskCall(dlg, agent, firstMention, tellaskHead, body, c
|
|
|
902
937
|
};
|
|
903
938
|
const pendingOwner = callerDialog;
|
|
904
939
|
const result = await (0, subdialog_txn_1.withSubdialogTxnLock)(rootDialog.id, async () => {
|
|
905
|
-
const existing = rootDialog
|
|
940
|
+
const existing = await lookupLiveRegisteredSubdialog(rootDialog, parseResult.agentId, parseResult.tellaskSession);
|
|
906
941
|
if (existing) {
|
|
907
942
|
try {
|
|
908
943
|
await updateSubdialogAssignment(existing, assignment);
|
|
@@ -1049,7 +1084,61 @@ async function executeTellaskCalls(args) {
|
|
|
1049
1084
|
const callbacks = ensureCallbacks(args.callbacks);
|
|
1050
1085
|
const malformedToolOutputs = await emitMalformedTellaskResponses(dlg, collectedCalls);
|
|
1051
1086
|
const validCalls = collectedCalls.filter((call) => call.validation.kind === 'valid');
|
|
1052
|
-
const
|
|
1087
|
+
const q4hCalls = validCalls.filter((call) => call.validation.firstMention === 'human');
|
|
1088
|
+
const nonQ4HCalls = validCalls
|
|
1089
|
+
.filter((call) => call.validation.firstMention !== 'human')
|
|
1090
|
+
.map((call) => ({ ...call }));
|
|
1091
|
+
let mergedQ4HCall = null;
|
|
1092
|
+
if (q4hCalls.length === 1) {
|
|
1093
|
+
mergedQ4HCall = { ...q4hCalls[0] };
|
|
1094
|
+
}
|
|
1095
|
+
else if (q4hCalls.length > 1) {
|
|
1096
|
+
const primary = q4hCalls[0];
|
|
1097
|
+
const remainingCallIds = q4hCalls
|
|
1098
|
+
.slice(1)
|
|
1099
|
+
.map((call) => call.callId.trim())
|
|
1100
|
+
.filter((callId) => callId !== '');
|
|
1101
|
+
const language = (0, runtime_language_1.getWorkLanguage)();
|
|
1102
|
+
const intro = language === 'zh'
|
|
1103
|
+
? `我这次有 ${q4hCalls.length} 个问题,想请你一次性回复:`
|
|
1104
|
+
: `I have ${q4hCalls.length} questions this round. Please answer them in one response:`;
|
|
1105
|
+
const mergedBody = [
|
|
1106
|
+
intro,
|
|
1107
|
+
...q4hCalls.map((call, index) => {
|
|
1108
|
+
const body = call.body.trim();
|
|
1109
|
+
const normalizedBody = body !== ''
|
|
1110
|
+
? body
|
|
1111
|
+
: language === 'zh'
|
|
1112
|
+
? '请结合当前上下文补充这一项。'
|
|
1113
|
+
: 'Please provide this item based on the current context.';
|
|
1114
|
+
return language === 'zh'
|
|
1115
|
+
? `问题 ${index + 1}:\n${normalizedBody}`
|
|
1116
|
+
: `Question ${index + 1}:\n${normalizedBody}`;
|
|
1117
|
+
}),
|
|
1118
|
+
].join('\n\n');
|
|
1119
|
+
mergedQ4HCall = {
|
|
1120
|
+
...primary,
|
|
1121
|
+
body: mergedBody,
|
|
1122
|
+
q4hRemainingCallIds: remainingCallIds.length > 0 ? remainingCallIds : undefined,
|
|
1123
|
+
};
|
|
1124
|
+
log_1.log.info('Q4H multi-question normalized into a single prompt', {
|
|
1125
|
+
rootId: dlg.id.rootId,
|
|
1126
|
+
selfId: dlg.id.selfId,
|
|
1127
|
+
mergedCount: q4hCalls.length,
|
|
1128
|
+
primaryCallId: primary.callId,
|
|
1129
|
+
remainingCallIds,
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
const executionCalls = mergedQ4HCall
|
|
1133
|
+
? [...nonQ4HCalls, mergedQ4HCall]
|
|
1134
|
+
: nonQ4HCalls;
|
|
1135
|
+
const results = [];
|
|
1136
|
+
for (const call of executionCalls) {
|
|
1137
|
+
const result = await executeTellaskCall(dlg, agent, call.validation.firstMention, call.tellaskHead, call.body, call.callId, callbacks, {
|
|
1138
|
+
q4hRemainingCallIds: call.q4hRemainingCallIds,
|
|
1139
|
+
});
|
|
1140
|
+
results.push(result);
|
|
1141
|
+
}
|
|
1053
1142
|
const suspend = results.some((result) => result.suspend);
|
|
1054
1143
|
const toolOutputs = [...malformedToolOutputs, ...results.flatMap((result) => result.toolOutputs)];
|
|
1055
1144
|
const subdialogsCreated = results.flatMap((result) => result.subdialogsCreated);
|