dominds 1.23.5 → 1.23.6
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.js +79 -30
- package/dist/dialog-interruption.js +2 -0
- package/dist/llm/kernel-driver/flow.js +140 -32
- package/dist/minds/system-prompt.js +4 -4
- package/dist/persistence.js +100 -14
- package/dist/runtime/inter-dialog-format.js +4 -4
- package/dist/runtime/reply-prompt-copy.js +4 -4
- package/dist/tools/prompts/control/en/principles.md +1 -1
- package/dist/tools/prompts/control/en/scenarios.md +1 -1
- package/dist/tools/prompts/control/en/tools.md +1 -1
- package/dist/tools/prompts/control/zh/principles.md +1 -1
- package/dist/tools/prompts/control/zh/scenarios.md +1 -1
- package/dist/tools/prompts/control/zh/tools.md +1 -1
- package/package.json +3 -3
- package/webapp/dist/assets/{_basePickBy-DMD1UhXs.js → _basePickBy-528dB5Tu.js} +3 -3
- package/webapp/dist/assets/{_basePickBy-DMD1UhXs.js.map → _basePickBy-528dB5Tu.js.map} +1 -1
- package/webapp/dist/assets/{_baseUniq-CsE8Qvwt.js → _baseUniq-DkdKmFUs.js} +2 -2
- package/webapp/dist/assets/{_baseUniq-CsE8Qvwt.js.map → _baseUniq-DkdKmFUs.js.map} +1 -1
- package/webapp/dist/assets/{arc-0h8sV6e1.js → arc-BXvXVeL_.js} +2 -2
- package/webapp/dist/assets/{arc-0h8sV6e1.js.map → arc-BXvXVeL_.js.map} +1 -1
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-BbMESECO.js → architectureDiagram-2XIMDMQ5-Ck1IMDXl.js} +7 -7
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-BbMESECO.js.map → architectureDiagram-2XIMDMQ5-Ck1IMDXl.js.map} +1 -1
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-DwkN-9a4.js → blockDiagram-WCTKOSBZ-DLRhkTKE.js} +7 -7
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-DwkN-9a4.js.map → blockDiagram-WCTKOSBZ-DLRhkTKE.js.map} +1 -1
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-CGYONEh1.js → c4Diagram-IC4MRINW-D2Hc1l7q.js} +3 -3
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-CGYONEh1.js.map → c4Diagram-IC4MRINW-D2Hc1l7q.js.map} +1 -1
- package/webapp/dist/assets/{channel-DbSJhm5-.js → channel-DuagLVFr.js} +2 -2
- package/webapp/dist/assets/{channel-DbSJhm5-.js.map → channel-DuagLVFr.js.map} +1 -1
- package/webapp/dist/assets/{chunk-4BX2VUAB-D1inRfgf.js → chunk-4BX2VUAB-BVowxdVQ.js} +2 -2
- package/webapp/dist/assets/{chunk-4BX2VUAB-D1inRfgf.js.map → chunk-4BX2VUAB-BVowxdVQ.js.map} +1 -1
- package/webapp/dist/assets/{chunk-55IACEB6-DL1IDg_h.js → chunk-55IACEB6-DOqixome.js} +2 -2
- package/webapp/dist/assets/{chunk-55IACEB6-DL1IDg_h.js.map → chunk-55IACEB6-DOqixome.js.map} +1 -1
- package/webapp/dist/assets/{chunk-FMBD7UC4-CugIlRDV.js → chunk-FMBD7UC4-BQE3IRbI.js} +2 -2
- package/webapp/dist/assets/{chunk-FMBD7UC4-CugIlRDV.js.map → chunk-FMBD7UC4-BQE3IRbI.js.map} +1 -1
- package/webapp/dist/assets/{chunk-JSJVCQXG-DKHSdeu1.js → chunk-JSJVCQXG-BWvy_u2h.js} +2 -2
- package/webapp/dist/assets/{chunk-JSJVCQXG-DKHSdeu1.js.map → chunk-JSJVCQXG-BWvy_u2h.js.map} +1 -1
- package/webapp/dist/assets/{chunk-KX2RTZJC-DCU9tkq6.js → chunk-KX2RTZJC-DsSmqNSf.js} +2 -2
- package/webapp/dist/assets/{chunk-KX2RTZJC-DCU9tkq6.js.map → chunk-KX2RTZJC-DsSmqNSf.js.map} +1 -1
- package/webapp/dist/assets/{chunk-NQ4KR5QH-DN3O2s2M.js → chunk-NQ4KR5QH-B3jQt0DX.js} +4 -4
- package/webapp/dist/assets/{chunk-NQ4KR5QH-DN3O2s2M.js.map → chunk-NQ4KR5QH-B3jQt0DX.js.map} +1 -1
- package/webapp/dist/assets/{chunk-QZHKN3VN-e3ztIJg0.js → chunk-QZHKN3VN-CWST9WcY.js} +2 -2
- package/webapp/dist/assets/{chunk-QZHKN3VN-e3ztIJg0.js.map → chunk-QZHKN3VN-CWST9WcY.js.map} +1 -1
- package/webapp/dist/assets/{chunk-WL4C6EOR-Dv907NPM.js → chunk-WL4C6EOR-DjGCVqJN.js} +6 -6
- package/webapp/dist/assets/{chunk-WL4C6EOR-Dv907NPM.js.map → chunk-WL4C6EOR-DjGCVqJN.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-DOTXtxYZ.js → classDiagram-VBA2DB6C-BnjkPcus.js} +7 -7
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-DOTXtxYZ.js.map → classDiagram-VBA2DB6C-BnjkPcus.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-DOTXtxYZ.js → classDiagram-v2-RAHNMMFH-BnjkPcus.js} +7 -7
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-DOTXtxYZ.js.map → classDiagram-v2-RAHNMMFH-BnjkPcus.js.map} +1 -1
- package/webapp/dist/assets/{clone-6lYQMWpu.js → clone-BlToIURl.js} +2 -2
- package/webapp/dist/assets/{clone-6lYQMWpu.js.map → clone-BlToIURl.js.map} +1 -1
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-DoJeDXV0.js → cose-bilkent-S5V4N54A-BDVnPWt2.js} +2 -2
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-DoJeDXV0.js.map → cose-bilkent-S5V4N54A-BDVnPWt2.js.map} +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-F_n_vhV9.js → dagre-KLK3FWXG-aEZUtpHt.js} +7 -7
- package/webapp/dist/assets/{dagre-KLK3FWXG-F_n_vhV9.js.map → dagre-KLK3FWXG-aEZUtpHt.js.map} +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-Crwhgyjv.js → diagram-E7M64L7V-CvNVSxxk.js} +8 -8
- package/webapp/dist/assets/{diagram-E7M64L7V-Crwhgyjv.js.map → diagram-E7M64L7V-CvNVSxxk.js.map} +1 -1
- package/webapp/dist/assets/{diagram-IFDJBPK2-CIt1nnn5.js → diagram-IFDJBPK2-Cvwaoava.js} +7 -7
- package/webapp/dist/assets/{diagram-IFDJBPK2-CIt1nnn5.js.map → diagram-IFDJBPK2-Cvwaoava.js.map} +1 -1
- package/webapp/dist/assets/{diagram-P4PSJMXO-qowipEfV.js → diagram-P4PSJMXO-ffnT7Lr_.js} +7 -7
- package/webapp/dist/assets/{diagram-P4PSJMXO-qowipEfV.js.map → diagram-P4PSJMXO-ffnT7Lr_.js.map} +1 -1
- package/webapp/dist/assets/{erDiagram-INFDFZHY-DV2BcYNa.js → erDiagram-INFDFZHY-DvGIVeJS.js} +5 -5
- package/webapp/dist/assets/{erDiagram-INFDFZHY-DV2BcYNa.js.map → erDiagram-INFDFZHY-DvGIVeJS.js.map} +1 -1
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CAbWV161.js → flowDiagram-PKNHOUZH-BkQUpSc9.js} +7 -7
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CAbWV161.js.map → flowDiagram-PKNHOUZH-BkQUpSc9.js.map} +1 -1
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-CfdR7FRr.js → ganttDiagram-A5KZAMGK-BlG96EZZ.js} +3 -3
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-CfdR7FRr.js.map → ganttDiagram-A5KZAMGK-BlG96EZZ.js.map} +1 -1
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-DuJFTELz.js → gitGraphDiagram-K3NZZRJ6-CnyjUBR4.js} +8 -8
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-DuJFTELz.js.map → gitGraphDiagram-K3NZZRJ6-CnyjUBR4.js.map} +1 -1
- package/webapp/dist/assets/{graph-cjRyzujT.js → graph-D-OO7MVR.js} +3 -3
- package/webapp/dist/assets/{graph-cjRyzujT.js.map → graph-D-OO7MVR.js.map} +1 -1
- package/webapp/dist/assets/{index-DgfF56L4.js → index-DvqI98wY.js} +39 -33
- package/webapp/dist/assets/{index-DgfF56L4.js.map → index-DvqI98wY.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-3wx-7AdD.js → infoDiagram-LFFYTUFH-Bid564Un.js} +6 -6
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-3wx-7AdD.js.map → infoDiagram-LFFYTUFH-Bid564Un.js.map} +1 -1
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-g6CMb1Qc.js → ishikawaDiagram-PHBUUO56-BoU1GXkx.js} +2 -2
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-g6CMb1Qc.js.map → ishikawaDiagram-PHBUUO56-BoU1GXkx.js.map} +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-DdCcmOBO.js → journeyDiagram-4ABVD52K-C-JJRe4y.js} +5 -5
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-DdCcmOBO.js.map → journeyDiagram-4ABVD52K-C-JJRe4y.js.map} +1 -1
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-BFw2emGl.js → kanban-definition-K7BYSVSG-BPGHC2fL.js} +3 -3
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-BFw2emGl.js.map → kanban-definition-K7BYSVSG-BPGHC2fL.js.map} +1 -1
- package/webapp/dist/assets/{layout-Clazq06r.js → layout-BFpoiNr0.js} +5 -5
- package/webapp/dist/assets/{layout-Clazq06r.js.map → layout-BFpoiNr0.js.map} +1 -1
- package/webapp/dist/assets/{linear-jdsBGgvD.js → linear-BwnDVwt9.js} +2 -2
- package/webapp/dist/assets/{linear-jdsBGgvD.js.map → linear-BwnDVwt9.js.map} +1 -1
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DLSZrW6l.js → mindmap-definition-YRQLILUH-D4aHh1Ye.js} +4 -4
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DLSZrW6l.js.map → mindmap-definition-YRQLILUH-D4aHh1Ye.js.map} +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Uj-Zpci6.js → pieDiagram-SKSYHLDU-DIp7yy6V.js} +8 -8
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Uj-Zpci6.js.map → pieDiagram-SKSYHLDU-DIp7yy6V.js.map} +1 -1
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DO7Sl1nV.js → quadrantDiagram-337W2JSQ-uKOhvCPR.js} +3 -3
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DO7Sl1nV.js.map → quadrantDiagram-337W2JSQ-uKOhvCPR.js.map} +1 -1
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-WrurrDKQ.js → requirementDiagram-Z7DCOOCP-Da_5DlcQ.js} +4 -4
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-WrurrDKQ.js.map → requirementDiagram-Z7DCOOCP-Da_5DlcQ.js.map} +1 -1
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-gcxbxuZB.js → sankeyDiagram-WA2Y5GQK-P3UD1XYS.js} +2 -2
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-gcxbxuZB.js.map → sankeyDiagram-WA2Y5GQK-P3UD1XYS.js.map} +1 -1
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-B98U2Npa.js → sequenceDiagram-2WXFIKYE-jY-eNlAg.js} +4 -4
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-B98U2Npa.js.map → sequenceDiagram-2WXFIKYE-jY-eNlAg.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-BUgfHMbd.js → stateDiagram-RAJIS63D-HMXNbLUd.js} +9 -9
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-BUgfHMbd.js.map → stateDiagram-RAJIS63D-HMXNbLUd.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-C8gH0rSW.js → stateDiagram-v2-FVOUBMTO-C-50Qbn8.js} +5 -5
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-C8gH0rSW.js.map → stateDiagram-v2-FVOUBMTO-C-50Qbn8.js.map} +1 -1
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-DnVikX3B.js → timeline-definition-YZTLITO2-CkiLYjSG.js} +3 -3
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-DnVikX3B.js.map → timeline-definition-YZTLITO2-CkiLYjSG.js.map} +1 -1
- package/webapp/dist/assets/{treemap-KZPCXAKY-BjhjT1IM.js → treemap-KZPCXAKY-DKYYu8t-.js} +5 -5
- package/webapp/dist/assets/{treemap-KZPCXAKY-BjhjT1IM.js.map → treemap-KZPCXAKY-DKYYu8t-.js.map} +1 -1
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CXjPMxrl.js → vennDiagram-LZ73GAT5-n9k6D3Up.js} +2 -2
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CXjPMxrl.js.map → vennDiagram-LZ73GAT5-n9k6D3Up.js.map} +1 -1
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-ByKmk3Cb.js → xychartDiagram-JWTSCODW-DJZb5SW1.js} +3 -3
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-ByKmk3Cb.js.map → xychartDiagram-JWTSCODW-DJZb5SW1.js.map} +1 -1
- package/webapp/dist/index.html +1 -1
|
@@ -96,6 +96,25 @@ function isSideDialogResponseAnchor(record) {
|
|
|
96
96
|
function isNonIdleDisplayProjection(state) {
|
|
97
97
|
return state !== undefined && state.kind !== 'idle_waiting_user';
|
|
98
98
|
}
|
|
99
|
+
function pendingReplyObligationDisplayState() {
|
|
100
|
+
return {
|
|
101
|
+
kind: 'stopped',
|
|
102
|
+
reason: { kind: 'pending_reply_obligation' },
|
|
103
|
+
continueEnabled: true,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function blockerDisplayState(args) {
|
|
107
|
+
if (args.hasQ4H && args.hasSideDialogs) {
|
|
108
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input_and_sideDialogs' } };
|
|
109
|
+
}
|
|
110
|
+
if (args.hasQ4H) {
|
|
111
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input' } };
|
|
112
|
+
}
|
|
113
|
+
if (args.hasSideDialogs) {
|
|
114
|
+
return { kind: 'blocked', reason: { kind: 'waiting_for_sideDialogs' } };
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
99
118
|
async function hasSideDialogFinalResponseAnchor(dialogId, latest) {
|
|
100
119
|
if (dialogId.selfId === dialogId.rootId) {
|
|
101
120
|
return false;
|
|
@@ -111,6 +130,35 @@ async function hasSideDialogFinalResponseAnchor(dialogId, latest) {
|
|
|
111
130
|
}
|
|
112
131
|
return false;
|
|
113
132
|
}
|
|
133
|
+
async function hasActiveSideDialogReplyObligation(dialogId) {
|
|
134
|
+
if (dialogId.selfId === dialogId.rootId) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const activeObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(dialogId, 'running');
|
|
138
|
+
return activeObligation !== undefined;
|
|
139
|
+
}
|
|
140
|
+
async function coerceIdleDisplayStateForActiveSideDialogReplyObligation(dialogId, displayState) {
|
|
141
|
+
if (displayState.kind !== 'idle_waiting_user') {
|
|
142
|
+
return displayState;
|
|
143
|
+
}
|
|
144
|
+
if (!(await hasActiveSideDialogReplyObligation(dialogId))) {
|
|
145
|
+
return displayState;
|
|
146
|
+
}
|
|
147
|
+
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
148
|
+
const pendingSideDialogs = await persistence_1.DialogPersistence.loadPendingSideDialogs(dialogId, 'running');
|
|
149
|
+
const blocked = blockerDisplayState({
|
|
150
|
+
hasQ4H: q4h.length > 0,
|
|
151
|
+
hasSideDialogs: pendingSideDialogs.length > 0,
|
|
152
|
+
});
|
|
153
|
+
const healedDisplayState = blocked ?? pendingReplyObligationDisplayState();
|
|
154
|
+
log.warn('Prevented sideDialog with active reply obligation from entering idle display state', new Error('sideDialog idle display-state invariant violation'), {
|
|
155
|
+
dialogId: dialogId.valueOf(),
|
|
156
|
+
rootId: dialogId.rootId,
|
|
157
|
+
selfId: dialogId.selfId,
|
|
158
|
+
healedDisplayState,
|
|
159
|
+
});
|
|
160
|
+
return healedDisplayState;
|
|
161
|
+
}
|
|
114
162
|
function classifyRunControlBucket(state) {
|
|
115
163
|
if (!state)
|
|
116
164
|
return 'none';
|
|
@@ -345,6 +393,7 @@ async function clearDialogInterruptedExecutionMarker(dialogId) {
|
|
|
345
393
|
await setDialogExecutionMarker(dialogId, undefined);
|
|
346
394
|
}
|
|
347
395
|
async function setDialogDisplayState(dialogId, displayState) {
|
|
396
|
+
displayState = await coerceIdleDisplayStateForActiveSideDialogReplyObligation(dialogId, displayState);
|
|
348
397
|
if (displayState.kind === 'dead' && dialogId.selfId === dialogId.rootId) {
|
|
349
398
|
log.warn('Rejecting dead displayState for main dialog (main dialogs must not be dead)', undefined, {
|
|
350
399
|
dialogId: dialogId.valueOf(),
|
|
@@ -441,7 +490,8 @@ async function computeIdleDisplayState(dlg) {
|
|
|
441
490
|
latest.executionMarker.kind === 'dead') {
|
|
442
491
|
return { kind: 'dead', reason: latest.executionMarker.reason };
|
|
443
492
|
}
|
|
444
|
-
if (latest?.executionMarker?.kind === 'interrupted'
|
|
493
|
+
if (latest?.executionMarker?.kind === 'interrupted' &&
|
|
494
|
+
latest.executionMarker.reason.kind !== 'pending_reply_obligation') {
|
|
445
495
|
return {
|
|
446
496
|
kind: 'stopped',
|
|
447
497
|
reason: latest.executionMarker.reason,
|
|
@@ -457,14 +507,12 @@ async function computeIdleDisplayState(dlg) {
|
|
|
457
507
|
}
|
|
458
508
|
const hasQ4H = await dlg.hasPendingQ4H();
|
|
459
509
|
const hasSideDialogs = await dlg.hasPendingSideDialogs();
|
|
460
|
-
|
|
461
|
-
|
|
510
|
+
const blocked = blockerDisplayState({ hasQ4H, hasSideDialogs });
|
|
511
|
+
if (blocked) {
|
|
512
|
+
return blocked;
|
|
462
513
|
}
|
|
463
|
-
if (
|
|
464
|
-
return
|
|
465
|
-
}
|
|
466
|
-
if (hasSideDialogs) {
|
|
467
|
-
return { kind: 'blocked', reason: { kind: 'waiting_for_sideDialogs' } };
|
|
514
|
+
if (await hasActiveSideDialogReplyObligation(dlg.id)) {
|
|
515
|
+
return pendingReplyObligationDisplayState();
|
|
468
516
|
}
|
|
469
517
|
return { kind: 'idle_waiting_user' };
|
|
470
518
|
}
|
|
@@ -480,7 +528,8 @@ async function computeIdleDisplayStateFromPersistence(dialogId) {
|
|
|
480
528
|
latest.executionMarker.kind === 'dead') {
|
|
481
529
|
return { kind: 'dead', reason: latest.executionMarker.reason };
|
|
482
530
|
}
|
|
483
|
-
if (latest?.executionMarker?.kind === 'interrupted'
|
|
531
|
+
if (latest?.executionMarker?.kind === 'interrupted' &&
|
|
532
|
+
latest.executionMarker.reason.kind !== 'pending_reply_obligation') {
|
|
484
533
|
return {
|
|
485
534
|
kind: 'stopped',
|
|
486
535
|
reason: latest.executionMarker.reason,
|
|
@@ -494,21 +543,19 @@ async function computeIdleDisplayStateFromPersistence(dialogId) {
|
|
|
494
543
|
continueEnabled: true,
|
|
495
544
|
};
|
|
496
545
|
}
|
|
497
|
-
if (latest && (await hasSideDialogFinalResponseAnchor(dialogId, latest))) {
|
|
498
|
-
return { kind: 'idle_waiting_user' };
|
|
499
|
-
}
|
|
500
546
|
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
501
547
|
const pendingSideDialogs = await persistence_1.DialogPersistence.loadPendingSideDialogs(dialogId, 'running');
|
|
502
548
|
const hasQ4H = q4h.length > 0;
|
|
503
549
|
const hasSideDialogs = pendingSideDialogs.length > 0;
|
|
504
|
-
|
|
505
|
-
|
|
550
|
+
const blocked = blockerDisplayState({ hasQ4H, hasSideDialogs });
|
|
551
|
+
if (blocked) {
|
|
552
|
+
return blocked;
|
|
506
553
|
}
|
|
507
|
-
if (
|
|
508
|
-
return
|
|
554
|
+
if (await hasActiveSideDialogReplyObligation(dialogId)) {
|
|
555
|
+
return pendingReplyObligationDisplayState();
|
|
509
556
|
}
|
|
510
|
-
if (
|
|
511
|
-
return { kind: '
|
|
557
|
+
if (latest && (await hasSideDialogFinalResponseAnchor(dialogId, latest))) {
|
|
558
|
+
return { kind: 'idle_waiting_user' };
|
|
512
559
|
}
|
|
513
560
|
return { kind: 'idle_waiting_user' };
|
|
514
561
|
}
|
|
@@ -602,23 +649,22 @@ async function refreshRunControlProjectionFromPersistenceFacts(dialogId, trigger
|
|
|
602
649
|
continueEnabled: true,
|
|
603
650
|
};
|
|
604
651
|
}
|
|
605
|
-
if (await hasSideDialogFinalResponseAnchor(dialogId, latest)) {
|
|
606
|
-
return { kind: 'idle_waiting_user' };
|
|
607
|
-
}
|
|
608
652
|
const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
|
|
609
653
|
const pendingSideDialogs = await persistence_1.DialogPersistence.loadPendingSideDialogs(dialogId, 'running');
|
|
610
654
|
const hasQ4H = q4h.length > 0;
|
|
611
655
|
const hasSideDialogs = pendingSideDialogs.length > 0;
|
|
612
|
-
|
|
613
|
-
|
|
656
|
+
const blocked = blockerDisplayState({ hasQ4H, hasSideDialogs });
|
|
657
|
+
if (blocked) {
|
|
658
|
+
return blocked;
|
|
614
659
|
}
|
|
615
|
-
if (
|
|
616
|
-
return
|
|
660
|
+
if (await hasActiveSideDialogReplyObligation(dialogId)) {
|
|
661
|
+
return pendingReplyObligationDisplayState();
|
|
617
662
|
}
|
|
618
|
-
if (
|
|
619
|
-
return { kind: '
|
|
663
|
+
if (await hasSideDialogFinalResponseAnchor(dialogId, latest)) {
|
|
664
|
+
return { kind: 'idle_waiting_user' };
|
|
620
665
|
}
|
|
621
|
-
if (latest.executionMarker?.kind === 'interrupted'
|
|
666
|
+
if (latest.executionMarker?.kind === 'interrupted' &&
|
|
667
|
+
latest.executionMarker.reason.kind !== 'pending_reply_obligation') {
|
|
622
668
|
return {
|
|
623
669
|
kind: 'stopped',
|
|
624
670
|
reason: latest.executionMarker.reason,
|
|
@@ -673,7 +719,9 @@ function isRecoverableGeneratingLatest(latest) {
|
|
|
673
719
|
if (marker.kind === 'dead') {
|
|
674
720
|
return false;
|
|
675
721
|
}
|
|
676
|
-
return marker.kind !== 'interrupted' ||
|
|
722
|
+
return (marker.kind !== 'interrupted' ||
|
|
723
|
+
marker.reason.kind === 'pending_course_start' ||
|
|
724
|
+
marker.reason.kind === 'pending_reply_obligation');
|
|
677
725
|
}
|
|
678
726
|
async function reconcileDisplayStatesAfterRestart() {
|
|
679
727
|
const dialogIds = await persistence_1.DialogPersistence.listAllDialogIds('running');
|
|
@@ -743,7 +791,8 @@ async function reconcileDisplayStatesAfterRestart() {
|
|
|
743
791
|
needsDrive: true,
|
|
744
792
|
displayState: { kind: 'proceeding' },
|
|
745
793
|
executionMarker: existingMarker?.kind === 'interrupted' &&
|
|
746
|
-
existingMarker.reason.kind === 'pending_course_start'
|
|
794
|
+
(existingMarker.reason.kind === 'pending_course_start' ||
|
|
795
|
+
existingMarker.reason.kind === 'pending_reply_obligation')
|
|
747
796
|
? undefined
|
|
748
797
|
: existingMarker,
|
|
749
798
|
},
|
|
@@ -24,6 +24,7 @@ function isInterruptionReasonManualResumeEligible(reason) {
|
|
|
24
24
|
case 'emergency_stop':
|
|
25
25
|
case 'server_restart':
|
|
26
26
|
case 'pending_course_start':
|
|
27
|
+
case 'pending_reply_obligation':
|
|
27
28
|
case 'fork_continue_ready':
|
|
28
29
|
case 'system_stop':
|
|
29
30
|
case 'llm_retry_stopped':
|
|
@@ -37,6 +38,7 @@ function isInterruptionReasonManualResumeEligible(reason) {
|
|
|
37
38
|
function doesInterruptionReasonRequireExplicitResume(reason) {
|
|
38
39
|
switch (reason.kind) {
|
|
39
40
|
case 'pending_course_start':
|
|
41
|
+
case 'pending_reply_obligation':
|
|
40
42
|
return false;
|
|
41
43
|
case 'user_stop':
|
|
42
44
|
case 'emergency_stop':
|
|
@@ -23,6 +23,26 @@ const idle_reminder_wake_1 = require("./idle-reminder-wake");
|
|
|
23
23
|
const reply_guidance_1 = require("./reply-guidance");
|
|
24
24
|
const sideDialog_1 = require("./sideDialog");
|
|
25
25
|
const tellask_special_1 = require("./tellask-special");
|
|
26
|
+
function buildRuntimeReplyReminderFollowUp(args) {
|
|
27
|
+
const common = {
|
|
28
|
+
prompt: args.prompt,
|
|
29
|
+
msgId: (0, id_1.generateShortId)(),
|
|
30
|
+
grammar: 'markdown',
|
|
31
|
+
origin: 'runtime',
|
|
32
|
+
userLanguageCode: args.language,
|
|
33
|
+
tellaskReplyDirective: args.directive,
|
|
34
|
+
};
|
|
35
|
+
return args.sideDialogReplyTarget === undefined
|
|
36
|
+
? {
|
|
37
|
+
kind: 'runtime_reply_reminder',
|
|
38
|
+
...common,
|
|
39
|
+
}
|
|
40
|
+
: {
|
|
41
|
+
kind: 'runtime_sideDialog_reply_reminder',
|
|
42
|
+
...common,
|
|
43
|
+
sideDialogReplyTarget: args.sideDialogReplyTarget,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
26
46
|
async function queueReplyReminderFollowUp(args) {
|
|
27
47
|
if (args.followUp.kind === 'runtime_sideDialog_reply_reminder') {
|
|
28
48
|
await args.dialog.queueRuntimeSideDialogPrompt({
|
|
@@ -74,6 +94,10 @@ function resolveDirectFallbackResponse(args) {
|
|
|
74
94
|
source: 'saying',
|
|
75
95
|
};
|
|
76
96
|
}
|
|
97
|
+
// Thinking-only output is intentionally a fallback candidate: some providers/models can finish a
|
|
98
|
+
// Side Dialog with useful content in thinking and no public saying. This helper only extracts the
|
|
99
|
+
// candidate; callers below must still reject it when a same-round function/tellask call needs
|
|
100
|
+
// auto-continuation, when the dialog is suspended, or when another follow-up prompt is queued.
|
|
77
101
|
if (args.driveResult.lastAssistantThinkingContent !== null &&
|
|
78
102
|
args.driveResult.lastAssistantThinkingContent.trim() !== '') {
|
|
79
103
|
if (typeof args.driveResult.lastAssistantThinkingGenseq !== 'number' ||
|
|
@@ -185,6 +209,79 @@ async function loadPendingDiagnosticsSnapshot(args) {
|
|
|
185
209
|
};
|
|
186
210
|
}
|
|
187
211
|
}
|
|
212
|
+
async function hasAssistantOutputAfterAssignmentAnchor(args) {
|
|
213
|
+
const events = await persistence_1.DialogPersistence.loadCourseEvents(args.dialog.id, args.dialog.currentCourse, args.dialog.status);
|
|
214
|
+
let assignmentGenseq;
|
|
215
|
+
for (const event of events) {
|
|
216
|
+
if (event.type === 'tellask_anchor_record' &&
|
|
217
|
+
event.anchorRole === 'assignment' &&
|
|
218
|
+
event.callId === args.callId) {
|
|
219
|
+
assignmentGenseq = event.genseq;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (assignmentGenseq !== undefined &&
|
|
223
|
+
(event.type === 'agent_thought_record' || event.type === 'agent_words_record') &&
|
|
224
|
+
event.genseq >= assignmentGenseq &&
|
|
225
|
+
event.content.trim() !== '') {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
async function resolveStrandedSideDialogReplyReminderFollowUp(args) {
|
|
232
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(args.dialog.id, args.dialog.status);
|
|
233
|
+
const displayState = latest?.displayState;
|
|
234
|
+
const isRecoverableProjection = displayState?.kind === 'idle_waiting_user' ||
|
|
235
|
+
(displayState?.kind === 'stopped' && displayState.reason.kind === 'pending_reply_obligation');
|
|
236
|
+
if (!latest ||
|
|
237
|
+
!isRecoverableProjection ||
|
|
238
|
+
latest.pendingCourseStartPrompt !== undefined ||
|
|
239
|
+
latest.executionMarker?.kind === 'dead') {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
const directive = await (0, tellask_special_1.loadActiveTellaskReplyDirective)(args.dialog);
|
|
243
|
+
if (!directive) {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
const ownerDialogId = directive.targetDialogId.trim();
|
|
247
|
+
if (ownerDialogId === '') {
|
|
248
|
+
throw new Error(`stranded sideDialog reply recovery invariant violation: empty targetDialogId ` +
|
|
249
|
+
`(dialogId=${args.dialog.id.valueOf()}, targetCallId=${directive.targetCallId})`);
|
|
250
|
+
}
|
|
251
|
+
const pending = await persistence_1.DialogPersistence.loadPendingSideDialogs(new dialog_1.DialogID(ownerDialogId, args.dialog.id.rootId), args.dialog.status);
|
|
252
|
+
const pendingRecord = pending.find((record) => record.sideDialogId === args.dialog.id.selfId && record.callId === directive.targetCallId);
|
|
253
|
+
if (!pendingRecord) {
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
if (!(await hasAssistantOutputAfterAssignmentAnchor({
|
|
257
|
+
dialog: args.dialog,
|
|
258
|
+
callId: pendingRecord.callId,
|
|
259
|
+
}))) {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
const language = (0, work_language_1.getWorkLanguage)();
|
|
263
|
+
const sideDialogReplyTarget = {
|
|
264
|
+
ownerDialogId,
|
|
265
|
+
callType: pendingRecord.callType,
|
|
266
|
+
callId: pendingRecord.callId,
|
|
267
|
+
callSiteCourse: pendingRecord.callSiteCourse,
|
|
268
|
+
callSiteGenseq: pendingRecord.callSiteGenseq,
|
|
269
|
+
};
|
|
270
|
+
return {
|
|
271
|
+
kind: 'runtime_sideDialog_reply_reminder',
|
|
272
|
+
prompt: await buildReplyToolReminderPrompt({
|
|
273
|
+
dlg: args.dialog,
|
|
274
|
+
directive,
|
|
275
|
+
language,
|
|
276
|
+
}),
|
|
277
|
+
msgId: (0, id_1.generateShortId)(),
|
|
278
|
+
grammar: 'markdown',
|
|
279
|
+
origin: 'runtime',
|
|
280
|
+
userLanguageCode: language,
|
|
281
|
+
tellaskReplyDirective: directive,
|
|
282
|
+
sideDialogReplyTarget,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
188
285
|
async function clearConsumedDeferredRootQueueIfIdle(dialog) {
|
|
189
286
|
if (dialog.id.selfId !== dialog.id.rootId) {
|
|
190
287
|
return;
|
|
@@ -366,6 +463,8 @@ async function inspectNoPromptSideDialogDrive(args) {
|
|
|
366
463
|
const inProgressGenerationResumeAllowed = args.driveOptions?.resumeInProgressGeneration === true;
|
|
367
464
|
const supplyResponseParentReviveAllowed = source === 'kernel_driver_supply_response_parent_revive' &&
|
|
368
465
|
hasNoPromptSideDialogResumeEntitlement(args.dialog, args.driveOptions);
|
|
466
|
+
const pendingReplyObligationResumeAllowed = latest?.executionMarker?.kind === 'interrupted' &&
|
|
467
|
+
latest.executionMarker.reason.kind === 'pending_reply_obligation';
|
|
369
468
|
if (lastEvent?.type === 'tellask_anchor_record' && lastEvent.anchorRole === 'response') {
|
|
370
469
|
return {
|
|
371
470
|
shouldReject: true,
|
|
@@ -378,7 +477,8 @@ async function inspectNoPromptSideDialogDrive(args) {
|
|
|
378
477
|
}
|
|
379
478
|
if (!explicitInterruptedResumeAllowed &&
|
|
380
479
|
!inProgressGenerationResumeAllowed &&
|
|
381
|
-
!supplyResponseParentReviveAllowed
|
|
480
|
+
!supplyResponseParentReviveAllowed &&
|
|
481
|
+
!pendingReplyObligationResumeAllowed) {
|
|
382
482
|
return {
|
|
383
483
|
shouldReject: true,
|
|
384
484
|
source,
|
|
@@ -640,6 +740,29 @@ async function executeDriveRound(args) {
|
|
|
640
740
|
// suspended by pending Q4H or sideDialogs. This prevents duplicate generations when
|
|
641
741
|
// multiple wake-ups race around the same sideDialog completion boundary.
|
|
642
742
|
if (!humanPrompt) {
|
|
743
|
+
if (dialog instanceof dialog_1.SideDialog && !dialog.hasUpNext()) {
|
|
744
|
+
const strandedReplyReminder = await resolveStrandedSideDialogReplyReminderFollowUp({
|
|
745
|
+
dialog,
|
|
746
|
+
});
|
|
747
|
+
if (strandedReplyReminder !== undefined) {
|
|
748
|
+
await queueReplyReminderFollowUp({ dialog, followUp: strandedReplyReminder });
|
|
749
|
+
args.scheduleDrive(dialog, {
|
|
750
|
+
waitInQue: true,
|
|
751
|
+
driveOptions: {
|
|
752
|
+
source: 'kernel_driver_follow_up',
|
|
753
|
+
reason: 'follow_up_prompt',
|
|
754
|
+
},
|
|
755
|
+
});
|
|
756
|
+
log_1.log.warn('kernel-driver recovered stranded sideDialog reply obligation by queueing reply reminder', undefined, {
|
|
757
|
+
dialogId: dialog.id.valueOf(),
|
|
758
|
+
rootId: dialog.id.rootId,
|
|
759
|
+
selfId: dialog.id.selfId,
|
|
760
|
+
targetCallId: strandedReplyReminder.tellaskReplyDirective.targetCallId,
|
|
761
|
+
targetOwnerDialogId: strandedReplyReminder.sideDialogReplyTarget.ownerDialogId,
|
|
762
|
+
});
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
643
766
|
if (dialog instanceof dialog_1.SideDialog && !dialog.hasUpNext()) {
|
|
644
767
|
try {
|
|
645
768
|
const inspection = await inspectNoPromptSideDialogDrive({ dialog, driveOptions });
|
|
@@ -916,8 +1039,10 @@ async function executeDriveRound(args) {
|
|
|
916
1039
|
driveResult.lastFunctionCallGenseq > 0 &&
|
|
917
1040
|
directFallbackResponse.responseGenseq <= driveResult.lastFunctionCallGenseq;
|
|
918
1041
|
if (hasInProgressFunctionCall) {
|
|
919
|
-
//
|
|
920
|
-
//
|
|
1042
|
+
// A candidate direct fallback, including thinking-only output, must be newer than the
|
|
1043
|
+
// latest same-round function/tellask call. Otherwise the call is still the active move
|
|
1044
|
+
// and may auto-continue; the candidate is merely pre-tool reasoning/progress, not final
|
|
1045
|
+
// tellasker delivery.
|
|
921
1046
|
log_1.log.debug('kernel-driver skip sideDialog response supply because latest assistant output is not after function calls', undefined, {
|
|
922
1047
|
rootId: dialog.id.rootId,
|
|
923
1048
|
selfId: dialog.id.selfId,
|
|
@@ -948,35 +1073,16 @@ async function executeDriveRound(args) {
|
|
|
948
1073
|
else {
|
|
949
1074
|
if (!activePromptWasReplyToolReminder) {
|
|
950
1075
|
const language = (0, work_language_1.getWorkLanguage)();
|
|
951
|
-
followUp =
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
grammar: 'markdown',
|
|
962
|
-
origin: 'runtime',
|
|
963
|
-
userLanguageCode: language,
|
|
964
|
-
tellaskReplyDirective: activeTellaskReplyDirective,
|
|
965
|
-
}
|
|
966
|
-
: {
|
|
967
|
-
kind: 'runtime_sideDialog_reply_reminder',
|
|
968
|
-
prompt: await buildReplyToolReminderPrompt({
|
|
969
|
-
dlg: dialog,
|
|
970
|
-
directive: activeTellaskReplyDirective,
|
|
971
|
-
language,
|
|
972
|
-
}),
|
|
973
|
-
msgId: (0, id_1.generateShortId)(),
|
|
974
|
-
grammar: 'markdown',
|
|
975
|
-
origin: 'runtime',
|
|
976
|
-
userLanguageCode: language,
|
|
977
|
-
tellaskReplyDirective: activeTellaskReplyDirective,
|
|
978
|
-
sideDialogReplyTarget,
|
|
979
|
-
};
|
|
1076
|
+
followUp = buildRuntimeReplyReminderFollowUp({
|
|
1077
|
+
directive: activeTellaskReplyDirective,
|
|
1078
|
+
prompt: await buildReplyToolReminderPrompt({
|
|
1079
|
+
dlg: dialog,
|
|
1080
|
+
directive: activeTellaskReplyDirective,
|
|
1081
|
+
language,
|
|
1082
|
+
}),
|
|
1083
|
+
language,
|
|
1084
|
+
sideDialogReplyTarget,
|
|
1085
|
+
});
|
|
980
1086
|
log_1.log.debug('kernel-driver queued sideDialog replyTellask reminder after plain reply', undefined, {
|
|
981
1087
|
dialogId: dialog.id.valueOf(),
|
|
982
1088
|
targetCallId: activeTellaskReplyDirective.targetCallId,
|
|
@@ -1064,6 +1170,8 @@ async function executeDriveRound(args) {
|
|
|
1064
1170
|
Number.isFinite(driveResult.lastFunctionCallGenseq) &&
|
|
1065
1171
|
driveResult.lastFunctionCallGenseq > 0 &&
|
|
1066
1172
|
directFallbackResponse.responseGenseq <= driveResult.lastFunctionCallGenseq;
|
|
1173
|
+
// Same rule as Side Dialog final delivery: direct fallback is allowed only after the
|
|
1174
|
+
// candidate content is known to be post-tool and no same-round call is waiting to continue.
|
|
1067
1175
|
if (!hasInProgressFunctionCall) {
|
|
1068
1176
|
if (!activePromptWasReplyToolReminder) {
|
|
1069
1177
|
const language = (0, work_language_1.getWorkLanguage)();
|
|
@@ -130,7 +130,7 @@ function buildSideDialogTellaskerReplyMarkerRules(language) {
|
|
|
130
130
|
'- 当前支线未完成时,不要默认直接 `tellaskBack`。先判断当前团队规程/SOP/职责卡能否明确负责人:若能明确且属于执行性处理,直接 `tellask` / `tellaskSessionless` 对应负责人;只有当必须向诉请者补充需求、做业务裁决、澄清验收口径、提供缺失输入,或现有规程无法明确判责时,才发起 `tellaskBack({ tellaskContent: "..." })`,并在 `tellaskContent` 中给出具体问题。',
|
|
131
131
|
'- 是否存在“待你收口的跨对话回复义务”、以及精确该调用哪个 reply 函数,均由运行时程序化判断;运行时会在 assignment 或最新 runtime/user 提示里直接点名。',
|
|
132
132
|
'- 若运行时点名了精确 reply 函数名,你只需调用那个被点名的函数;不要自己判断 `reply*` 变体。禁止调用 `tellaskBack` 发送最终结果,也禁止用 `tellask` 向诉请者发送最终结果。',
|
|
133
|
-
`-
|
|
133
|
+
`- 正式完成路径:只有在运行时当前明确点名了某个精确 reply 函数,且你通过那个函数回复时,运行时才会把该回复作为完成结果投递给诉请者,并在传递正文中添加 ${runtimeMarkers.finalCompleted}。不要依赖 direct-reply fallback;它只是运行时临时过渡兜底,不是正式回复机制。`,
|
|
134
134
|
'- 若运行时当前明确提示“没有待完成的跨对话回复义务”,就直接继续当前本地对话;不要凭记忆再次调用 `reply*`。',
|
|
135
135
|
'- "不得发普通文本中间汇报"只针对未完成态;若你已经完成任务并能给出最终交付,就应使用运行时当前点名的精确 reply 函数,不要使用 `tellaskBack` 或 `tellask`。',
|
|
136
136
|
'- 例外:FBR 支线为工具禁用模式(不得调用 `tellaskBack`);其回贴标记(`' +
|
|
@@ -145,7 +145,7 @@ function buildSideDialogTellaskerReplyMarkerRules(language) {
|
|
|
145
145
|
'- If the current Side Dialog is unfinished, do not default to `tellaskBack`. First judge whether current team SOP / role ownership already identifies the responsible executor: if yes and the issue is execution work, directly use `tellask` / `tellaskSessionless` for that owner; use `tellaskBack({ tellaskContent: "..." })` only when the tellasker must provide clarification, business decision, acceptance-criteria confirmation, missing input, or when existing SOP cannot determine ownership. Put concrete questions in `tellaskContent`.',
|
|
146
146
|
'- Runtime programmatically decides whether there is an active inter-dialog reply obligation for you, and which exact reply function name applies; runtime will state that directly in the assignment or the latest runtime/user prompt.',
|
|
147
147
|
'- If runtime names an exact reply function, call that named function and do not choose a `reply*` variant by yourself. Do not use `tellaskBack` or `tellask` to send final delivery.',
|
|
148
|
-
`-
|
|
148
|
+
`- Formal completion path: only replies sent through the exact reply function currently named by runtime are delivered to the tellasker as completion results and marked with ${runtimeMarkers.finalCompleted}. Do not rely on direct-reply fallback; it is only a temporary runtime transition safeguard, not the formal reply mechanism.`,
|
|
149
149
|
'- If runtime explicitly tells you there is no active inter-dialog reply obligation right now, just continue the current local conversation; do not call `reply*` again from memory.',
|
|
150
150
|
'- "Do not post a plain-text progress update" only applies to unfinished states; if the task is done and you can deliver the final result, use the exact reply function currently named by runtime instead of `tellaskBack` or `tellask`.',
|
|
151
151
|
'- Exception: FBR Side Dialog is tool-less (no \`tellaskBack\`); its reply markers (`' +
|
|
@@ -169,7 +169,7 @@ function buildTellaskReplyMarkerScopePolicy(language, dialogScope) {
|
|
|
169
169
|
'- `tellaskBack` 只允许用于回问诉请者;仅当必须向诉请者补需求/澄清/裁决/缺失输入,或现有团队规程无法明确判责时才使用。禁止用 `tellaskBack` 发送最终结果。',
|
|
170
170
|
'- 当前支线未完成时,不得把“阻塞/不确定”机械等同于 `tellaskBack`;若团队规程/SOP/职责卡已明确负责人,应直接 `tellask` / `tellaskSessionless` 对应负责人,不得发普通文本中间汇报。',
|
|
171
171
|
`- ${(0, reply_prompt_copy_1.buildSideDialogCompletionRule)('zh')}`,
|
|
172
|
-
`-
|
|
172
|
+
`- 正式完成路径中,仅当运行时当前明确点名了某个精确 reply 函数,且你通过那个函数回复时,运行时才会把该回复投递给诉请者并标注 ${runtimeMarkers.finalCompleted};不要依赖 direct-reply fallback,它只是运行时临时过渡兜底,不是正式回复机制。`,
|
|
173
173
|
'- 若运行时当前明确提示“没有待完成的跨对话回复义务”,说明这轮不是待你收口的跨对话回复义务;不要重复调用 `reply*`。',
|
|
174
174
|
],
|
|
175
175
|
en: [
|
|
@@ -178,7 +178,7 @@ function buildTellaskReplyMarkerScopePolicy(language, dialogScope) {
|
|
|
178
178
|
'- `tellaskBack` is only for asking the tellasker back; use it only when tellasker clarification / decision / missing input is required, or current team SOP cannot determine ownership. Do not use `tellaskBack` to send final results.',
|
|
179
179
|
'- If the current Side Dialog is unfinished, do not mechanically map “blocked / uncertain” to `tellaskBack`; when team SOP / role ownership already identifies the responsible owner, directly use `tellask` / `tellaskSessionless` for that owner instead of posting a plain-text progress update.',
|
|
180
180
|
`- ${(0, reply_prompt_copy_1.buildSideDialogCompletionRule)('en')}`,
|
|
181
|
-
`-
|
|
181
|
+
`- In the formal completion path, runtime marks ${runtimeMarkers.finalCompleted} and delivers to the tellasker only when runtime currently names an exact reply function and you reply through that named function; do not rely on direct-reply fallback, which is only a temporary runtime transition safeguard, not the formal reply mechanism.`,
|
|
182
182
|
'- If runtime currently tells you there is no active inter-dialog reply obligation, then this turn is not awaiting another inter-dialog closure from you; do not call `reply*` again.',
|
|
183
183
|
],
|
|
184
184
|
}),
|
package/dist/persistence.js
CHANGED
|
@@ -220,6 +220,67 @@ function normalizeGeneratingDisplayStateMismatch(dialogId, status, previous, lat
|
|
|
220
220
|
executionMarker: hasInterruptedExecutionMarker ? undefined : latest.executionMarker,
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
|
+
function hasActiveReplyObligationInAskerStackState(state) {
|
|
224
|
+
const top = state?.askerStack[state.askerStack.length - 1];
|
|
225
|
+
return top?.tellaskReplyObligation !== undefined;
|
|
226
|
+
}
|
|
227
|
+
function blockerDisplayState(args) {
|
|
228
|
+
if (args.hasQ4H && args.hasSideDialogs) {
|
|
229
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input_and_sideDialogs' } };
|
|
230
|
+
}
|
|
231
|
+
if (args.hasQ4H) {
|
|
232
|
+
return { kind: 'blocked', reason: { kind: 'needs_human_input' } };
|
|
233
|
+
}
|
|
234
|
+
if (args.hasSideDialogs) {
|
|
235
|
+
return { kind: 'blocked', reason: { kind: 'waiting_for_sideDialogs' } };
|
|
236
|
+
}
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
async function normalizeSideDialogIdleWhileReplyObligationPending(dialogId, status, previous, latest, askerStackState, context) {
|
|
240
|
+
if (status !== 'running' || dialogId.selfId === dialogId.rootId) {
|
|
241
|
+
return latest;
|
|
242
|
+
}
|
|
243
|
+
if (latest.displayState?.kind !== 'idle_waiting_user') {
|
|
244
|
+
return latest;
|
|
245
|
+
}
|
|
246
|
+
if (!hasActiveReplyObligationInAskerStackState(askerStackState)) {
|
|
247
|
+
return latest;
|
|
248
|
+
}
|
|
249
|
+
const blockerState = blockerDisplayState({
|
|
250
|
+
hasQ4H: (await DialogPersistence.loadQuestions4HumanState(dialogId, status)).length > 0,
|
|
251
|
+
hasSideDialogs: (await DialogPersistence.loadPendingSideDialogs(dialogId, status)).length > 0,
|
|
252
|
+
});
|
|
253
|
+
const top = askerStackState?.askerStack[askerStackState.askerStack.length - 1];
|
|
254
|
+
const healedDisplayState = blockerState ?? pendingReplyObligationDisplayState();
|
|
255
|
+
const healedExecutionMarker = healedDisplayState.kind === 'stopped' ? pendingReplyObligationExecutionMarker() : undefined;
|
|
256
|
+
emitInvariantWarning('Dialog latest projection invariant warning: sideDialog with active reply obligation attempted to enter idle displayState; healing from persistence facts', {
|
|
257
|
+
trigger: context.trigger,
|
|
258
|
+
mutationKind: context.mutationKind,
|
|
259
|
+
latestSource: context.latestSource,
|
|
260
|
+
latestWriteBackKey: context.latestWriteBackKey,
|
|
261
|
+
patchSummary: context.patchSummary,
|
|
262
|
+
dialogId: dialogId.valueOf(),
|
|
263
|
+
rootId: dialogId.rootId,
|
|
264
|
+
selfId: dialogId.selfId,
|
|
265
|
+
status,
|
|
266
|
+
targetCallId: top?.tellaskReplyObligation?.targetCallId ?? null,
|
|
267
|
+
blockedByQ4H: blockerState?.kind === 'blocked' && blockerState.reason.kind !== 'waiting_for_sideDialogs',
|
|
268
|
+
blockedBySideDialogs: blockerState?.kind === 'blocked' && blockerState.reason.kind !== 'needs_human_input',
|
|
269
|
+
before: summarizeLatestProjectionState(previous),
|
|
270
|
+
afterBeforeHealing: summarizeLatestProjectionState(latest),
|
|
271
|
+
healedTo: {
|
|
272
|
+
displayState: healedDisplayState,
|
|
273
|
+
executionMarker: healedExecutionMarker,
|
|
274
|
+
},
|
|
275
|
+
callStack: captureInvariantWarningStack(),
|
|
276
|
+
});
|
|
277
|
+
return {
|
|
278
|
+
...latest,
|
|
279
|
+
lastModified: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
280
|
+
displayState: healedDisplayState,
|
|
281
|
+
executionMarker: healedDisplayState.kind === 'stopped' ? healedExecutionMarker : undefined,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
223
284
|
const quarantiningMainDialogs = new Set();
|
|
224
285
|
const PERSISTABLE_DIALOG_STATUSES = ['running', 'completed', 'archived'];
|
|
225
286
|
const RUN_STATUS_DIR = 'run';
|
|
@@ -475,6 +536,8 @@ function parseDialogInterruptionReason(value) {
|
|
|
475
536
|
return { kind: 'server_restart' };
|
|
476
537
|
case 'pending_course_start':
|
|
477
538
|
return { kind: 'pending_course_start' };
|
|
539
|
+
case 'pending_reply_obligation':
|
|
540
|
+
return { kind: 'pending_reply_obligation' };
|
|
478
541
|
case 'fork_continue_ready':
|
|
479
542
|
return { kind: 'fork_continue_ready' };
|
|
480
543
|
case 'system_stop': {
|
|
@@ -509,6 +572,19 @@ function parseDialogInterruptionReason(value) {
|
|
|
509
572
|
return null;
|
|
510
573
|
}
|
|
511
574
|
}
|
|
575
|
+
function pendingReplyObligationDisplayState() {
|
|
576
|
+
return {
|
|
577
|
+
kind: 'stopped',
|
|
578
|
+
reason: { kind: 'pending_reply_obligation' },
|
|
579
|
+
continueEnabled: true,
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function pendingReplyObligationExecutionMarker() {
|
|
583
|
+
return {
|
|
584
|
+
kind: 'interrupted',
|
|
585
|
+
reason: { kind: 'pending_reply_obligation' },
|
|
586
|
+
};
|
|
587
|
+
}
|
|
512
588
|
function resolveStoppedContinueEnabled(reason) {
|
|
513
589
|
return (0, dialog_interruption_1.isInterruptionReasonManualResumeEligible)(reason);
|
|
514
590
|
}
|
|
@@ -1810,6 +1886,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
1810
1886
|
},
|
|
1811
1887
|
};
|
|
1812
1888
|
await this.appendEvent(askerDialog, parentCourse, sideDialogCreatedRecord);
|
|
1889
|
+
const initialSideDialogDisplayState = pendingReplyObligationDisplayState();
|
|
1813
1890
|
// Initialize latest.yaml via the mutation API (write-back will flush).
|
|
1814
1891
|
await DialogPersistence.mutateDialogLatest(sideDialogId, () => ({
|
|
1815
1892
|
kind: 'replace',
|
|
@@ -1820,7 +1897,8 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
1820
1897
|
messageCount: 0,
|
|
1821
1898
|
functionCallCount: 0,
|
|
1822
1899
|
sideDialogCount: 0,
|
|
1823
|
-
displayState:
|
|
1900
|
+
displayState: initialSideDialogDisplayState,
|
|
1901
|
+
executionMarker: pendingReplyObligationExecutionMarker(),
|
|
1824
1902
|
disableDiligencePush: false,
|
|
1825
1903
|
},
|
|
1826
1904
|
}));
|
|
@@ -1857,7 +1935,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
1857
1935
|
currentCourse: 1,
|
|
1858
1936
|
createdAt: nowTs,
|
|
1859
1937
|
lastModified: nowTs,
|
|
1860
|
-
displayState:
|
|
1938
|
+
displayState: initialSideDialogDisplayState,
|
|
1861
1939
|
sessionSlug: options.sessionSlug,
|
|
1862
1940
|
assignmentFromAsker: {
|
|
1863
1941
|
callName: options.callName,
|
|
@@ -6469,10 +6547,27 @@ class DialogPersistence {
|
|
|
6469
6547
|
lastModified: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
6470
6548
|
status: 'active',
|
|
6471
6549
|
};
|
|
6550
|
+
const askerStackState = status === 'running' && dialogId.selfId !== dialogId.rootId
|
|
6551
|
+
? await this.loadSideDialogAskerStackState(dialogId, status)
|
|
6552
|
+
: null;
|
|
6472
6553
|
const mutation = mutator(existing);
|
|
6554
|
+
const mutationContext = {
|
|
6555
|
+
trigger: 'mutateDialogLatest',
|
|
6556
|
+
mutationKind: mutation.kind,
|
|
6557
|
+
patchSummary: mutation.kind === 'patch'
|
|
6558
|
+
? summarizeLatestMutationPatch(mutation.patch)
|
|
6559
|
+
: mutation.kind === 'replace'
|
|
6560
|
+
? summarizeLatestProjectionState(mutation.next)
|
|
6561
|
+
: null,
|
|
6562
|
+
latestSource: staged ? 'staged' : latestFromDisk ? 'disk' : 'default_bootstrap',
|
|
6563
|
+
latestWriteBackKey: key,
|
|
6564
|
+
};
|
|
6473
6565
|
let updated;
|
|
6474
6566
|
if (mutation.kind === 'noop') {
|
|
6475
|
-
|
|
6567
|
+
updated = await normalizeSideDialogIdleWhileReplyObligationPending(dialogId, status, existing, existing, askerStackState, mutationContext);
|
|
6568
|
+
if (updated === existing) {
|
|
6569
|
+
return existing;
|
|
6570
|
+
}
|
|
6476
6571
|
}
|
|
6477
6572
|
else if (mutation.kind === 'replace') {
|
|
6478
6573
|
updated = {
|
|
@@ -6491,17 +6586,8 @@ class DialogPersistence {
|
|
|
6491
6586
|
const _exhaustive = mutation;
|
|
6492
6587
|
throw new Error(`Unhandled dialog latest mutation: ${String(_exhaustive)}`);
|
|
6493
6588
|
}
|
|
6494
|
-
updated = normalizeGeneratingDisplayStateMismatch(dialogId, status, existing, updated,
|
|
6495
|
-
|
|
6496
|
-
mutationKind: mutation.kind,
|
|
6497
|
-
patchSummary: mutation.kind === 'patch'
|
|
6498
|
-
? summarizeLatestMutationPatch(mutation.patch)
|
|
6499
|
-
: mutation.kind === 'replace'
|
|
6500
|
-
? summarizeLatestProjectionState(mutation.next)
|
|
6501
|
-
: null,
|
|
6502
|
-
latestSource: staged ? 'staged' : latestFromDisk ? 'disk' : 'default_bootstrap',
|
|
6503
|
-
latestWriteBackKey: key,
|
|
6504
|
-
});
|
|
6589
|
+
updated = normalizeGeneratingDisplayStateMismatch(dialogId, status, existing, updated, mutationContext);
|
|
6590
|
+
updated = await normalizeSideDialogIdleWhileReplyObligationPending(dialogId, status, existing, updated, askerStackState, mutationContext);
|
|
6505
6591
|
this.assertMainDialogWriteBackNotCanceled(effectiveCancellationToken, 'mutateDialogLatest:before-stage');
|
|
6506
6592
|
const pending = this.latestWriteBack.get(key);
|
|
6507
6593
|
if (!pending) {
|