dominds 1.16.1 → 1.16.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-display-state.d.ts +7 -1
- package/dist/dialog-display-state.js +146 -20
- package/dist/dialog-fork.js +13 -5
- package/dist/dialog-global-registry.d.ts +5 -1
- package/dist/dialog-global-registry.js +45 -1
- package/dist/dialog-interruption.d.ts +18 -0
- package/dist/dialog-interruption.js +34 -0
- package/dist/docs/dominds-agent-collaboration.zh.md +401 -0
- package/dist/llm/api-quirks.d.ts +11 -0
- package/dist/llm/api-quirks.js +322 -24
- package/dist/llm/defaults.yaml +2 -1
- package/dist/llm/gen/mock.d.ts +1 -1
- package/dist/llm/gen/mock.js +12 -0
- package/dist/llm/gen/openai-compatible.d.ts +1 -1
- package/dist/llm/gen/openai-compatible.js +9 -1
- package/dist/llm/gen/openai.d.ts +1 -1
- package/dist/llm/gen/openai.js +16 -2
- package/dist/llm/gen.d.ts +10 -0
- package/dist/llm/gen.js +10 -0
- package/dist/llm/kernel-driver/drive.js +994 -866
- package/dist/llm/kernel-driver/flow.js +230 -177
- package/dist/llm/kernel-driver/loop.js +5 -0
- package/dist/llm/kernel-driver/runtime.d.ts +16 -2
- package/dist/llm/kernel-driver/runtime.js +75 -10
- package/dist/llm/stop-reason-i18n.d.ts +9 -0
- package/dist/llm/stop-reason-i18n.js +114 -0
- package/dist/persistence-errors.d.ts +26 -0
- package/dist/persistence-errors.js +68 -0
- package/dist/persistence.d.ts +119 -82
- package/dist/persistence.js +1055 -426
- package/dist/server/api-routes.js +174 -58
- package/dist/server/websocket-handler.js +125 -21
- package/dist/tools/team_mgmt.js +2 -2
- package/package.json +4 -4
- package/webapp/dist/assets/{_basePickBy-C0MXVhMo.js → _basePickBy-BJWCmtUm.js} +3 -3
- package/webapp/dist/assets/_basePickBy-BJWCmtUm.js.map +1 -0
- package/webapp/dist/assets/{_baseUniq-CRygl41M.js → _baseUniq-D6k_lGfs.js} +2 -2
- package/webapp/dist/assets/_baseUniq-D6k_lGfs.js.map +1 -0
- package/webapp/dist/assets/{arc-BeHJtnt2.js → arc-DYDaESgj.js} +2 -2
- package/webapp/dist/assets/arc-DYDaESgj.js.map +1 -0
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CGdo5TVi.js → architectureDiagram-VXUJARFQ-DZMT7dqc.js} +8 -26
- package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DZMT7dqc.js.map +1 -0
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-C59VaSGw.js → blockDiagram-VD42YOAC-CABpgVAa.js} +170 -187
- package/webapp/dist/assets/blockDiagram-VD42YOAC-CABpgVAa.js.map +1 -0
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-B3YCBmTx.js → c4Diagram-YG6GDRKO-COLZS8Ul.js} +4 -4
- package/webapp/dist/assets/c4Diagram-YG6GDRKO-COLZS8Ul.js.map +1 -0
- package/webapp/dist/assets/{channel-Dn4i8EAY.js → channel-CYFm9Cri.js} +2 -2
- package/webapp/dist/assets/channel-CYFm9Cri.js.map +1 -0
- package/webapp/dist/assets/{chunk-4BX2VUAB-CQbB3HlW.js → chunk-4BX2VUAB-CX_-XbaN.js} +2 -2
- package/webapp/dist/assets/chunk-4BX2VUAB-CX_-XbaN.js.map +1 -0
- package/webapp/dist/assets/{chunk-55IACEB6-CkQR_Qu9.js → chunk-55IACEB6-ByD-NdBC.js} +2 -2
- package/webapp/dist/assets/chunk-55IACEB6-ByD-NdBC.js.map +1 -0
- package/webapp/dist/assets/{chunk-WL4C6EOR-Bjl-j3bf.js → chunk-B4BG7PRW-BANemsDD.js} +121 -171
- package/webapp/dist/assets/chunk-B4BG7PRW-BANemsDD.js.map +1 -0
- package/webapp/dist/assets/{chunk-NQ4KR5QH-DBxY8LL2.js → chunk-DI55MBZ5-DV7sdJmQ.js} +7 -9
- package/webapp/dist/assets/chunk-DI55MBZ5-DV7sdJmQ.js.map +1 -0
- package/webapp/dist/assets/{chunk-FMBD7UC4-YSIOuaST.js → chunk-FMBD7UC4-DYGviJnf.js} +2 -2
- package/webapp/dist/assets/chunk-FMBD7UC4-DYGviJnf.js.map +1 -0
- package/webapp/dist/assets/{chunk-KX2RTZJC-DFiwgnFf.js → chunk-QN33PNHL-B8DWRL9f.js} +2 -2
- package/webapp/dist/assets/chunk-QN33PNHL-B8DWRL9f.js.map +1 -0
- package/webapp/dist/assets/{chunk-QZHKN3VN-BAdR6lLc.js → chunk-QZHKN3VN-B1aYIzMR.js} +2 -2
- package/webapp/dist/assets/chunk-QZHKN3VN-B1aYIzMR.js.map +1 -0
- package/webapp/dist/assets/{chunk-JSJVCQXG-CWDLRawz.js → chunk-TZMSLE5B-_HISzxl3.js} +6 -14
- package/webapp/dist/assets/chunk-TZMSLE5B-_HISzxl3.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-KBeS6WXD.js → classDiagram-2ON5EDUG-CpyYj1Rc.js} +6 -7
- package/webapp/dist/assets/classDiagram-2ON5EDUG-CpyYj1Rc.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-KBeS6WXD.js → classDiagram-v2-WZHVMYZB-CpyYj1Rc.js} +6 -7
- package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-CpyYj1Rc.js.map +1 -0
- package/webapp/dist/assets/{clone-C7-aS2vm.js → clone-B_9AxWIU.js} +2 -2
- package/webapp/dist/assets/clone-B_9AxWIU.js.map +1 -0
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-Bo5IsL-5.js → cose-bilkent-S5V4N54A-17ECLfPR.js} +2 -2
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-17ECLfPR.js.map +1 -0
- package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-C3FeHj7D.js → dagre-6UL2VRFP-DhRqcF1o.js} +7 -7
- package/webapp/dist/assets/dagre-6UL2VRFP-DhRqcF1o.js.map +1 -0
- package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-0HfiRW0u.js → diagram-PSM6KHXK-lpDT6Wwb.js} +10 -10
- package/webapp/dist/assets/diagram-PSM6KHXK-lpDT6Wwb.js.map +1 -0
- package/webapp/dist/assets/{diagram-IFDJBPK2-DJwh7SMO.js → diagram-QEK2KX5R-ohxbPpDH.js} +8 -9
- package/webapp/dist/assets/diagram-QEK2KX5R-ohxbPpDH.js.map +1 -0
- package/webapp/dist/assets/{diagram-P4PSJMXO-Y0RbvUZX.js → diagram-S2PKOQOG-DAFFGfch.js} +8 -8
- package/webapp/dist/assets/diagram-S2PKOQOG-DAFFGfch.js.map +1 -0
- package/webapp/dist/assets/{erDiagram-INFDFZHY-B183xyLa.js → erDiagram-Q2GNP2WA-BH-7rI43.js} +75 -96
- package/webapp/dist/assets/erDiagram-Q2GNP2WA-BH-7rI43.js.map +1 -0
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-C_BR3Y3J.js → flowDiagram-NV44I4VS-CdEjFbz4.js} +81 -98
- package/webapp/dist/assets/flowDiagram-NV44I4VS-CdEjFbz4.js.map +1 -0
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-CHLgkuJT.js → ganttDiagram-JELNMOA3-Cju2t-lK.js} +3 -28
- package/webapp/dist/assets/ganttDiagram-JELNMOA3-Cju2t-lK.js.map +1 -0
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D6C_HU1q.js → gitGraphDiagram-V2S2FVAM-CUJ5oxCg.js} +46 -38
- package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-CUJ5oxCg.js.map +1 -0
- package/webapp/dist/assets/graph-mhcc7ldf.js +425 -0
- package/webapp/dist/assets/graph-mhcc7ldf.js.map +1 -0
- package/webapp/dist/assets/{index-CLoNHmSQ.js → index-BLnM-uON.js} +2098 -1841
- package/webapp/dist/assets/{index-CLoNHmSQ.js.map → index-BLnM-uON.js.map} +1 -1
- package/webapp/dist/assets/{index-YaxF76or.css → index-xvYYeHuy.css} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-mnMS61NO.js → infoDiagram-HS3SLOUP-Df8p0okQ.js} +7 -7
- package/webapp/dist/assets/infoDiagram-HS3SLOUP-Df8p0okQ.js.map +1 -0
- package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BdeERn0r.js → journeyDiagram-XKPGCS4Q-BXMl8H-d.js} +5 -5
- package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-BXMl8H-d.js.map +1 -0
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-MLeCGcYg.js → kanban-definition-3W4ZIXB7-Cc5RwCEh.js} +3 -5
- package/webapp/dist/assets/kanban-definition-3W4ZIXB7-Cc5RwCEh.js.map +1 -0
- package/webapp/dist/assets/{layout-DY9VEQ9M.js → layout-BB2SvQcE.js} +5 -5
- package/webapp/dist/assets/layout-BB2SvQcE.js.map +1 -0
- package/webapp/dist/assets/{linear-D-T1xRsr.js → linear-Cj50lA0a.js} +2 -2
- package/webapp/dist/assets/linear-Cj50lA0a.js.map +1 -0
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CrVm8vj2.js → mindmap-definition-VGOIOE7T-BLBklJVX.js} +5 -7
- package/webapp/dist/assets/mindmap-definition-VGOIOE7T-BLBklJVX.js.map +1 -0
- package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-GtLLV0r1.js → pieDiagram-ADFJNKIX-BQrOgSc-.js} +8 -8
- package/webapp/dist/assets/pieDiagram-ADFJNKIX-BQrOgSc-.js.map +1 -0
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-BCgk_2LP.js → quadrantDiagram-AYHSOK5B-C62TxtsO.js} +3 -3
- package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-C62TxtsO.js.map +1 -0
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DYUKHWKR.js → requirementDiagram-UZGBJVZJ-Is6Q3osM.js} +6 -16
- package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-Is6Q3osM.js.map +1 -0
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CFAH8OaY.js → sankeyDiagram-TZEHDZUN-CCAW8Dr2.js} +2 -2
- package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-CCAW8Dr2.js.map +1 -0
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-BTnhbv6w.js → sequenceDiagram-WL72ISMW-DpODpbl6.js} +201 -601
- package/webapp/dist/assets/sequenceDiagram-WL72ISMW-DpODpbl6.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-DWUnJTwO.js → stateDiagram-FKZM4ZOC-B8LHaf5T.js} +9 -9
- package/webapp/dist/assets/stateDiagram-FKZM4ZOC-B8LHaf5T.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-B-fc52bp.js → stateDiagram-v2-4FDKWEC3-4FzTkpgz.js} +5 -5
- package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3-4FzTkpgz.js.map +1 -0
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-BMZ52QaG.js → timeline-definition-IT6M3QCI-Ckxc4qZe.js} +3 -3
- package/webapp/dist/assets/timeline-definition-IT6M3QCI-Ckxc4qZe.js.map +1 -0
- package/webapp/dist/assets/{treemap-KZPCXAKY-fgSrze0S.js → treemap-GDKQZRPO-QQa4vKMv.js} +24 -37
- package/webapp/dist/assets/treemap-GDKQZRPO-QQa4vKMv.js.map +1 -0
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-D6aviLtC.js → xychartDiagram-PRI3JC2R-Ba2uJcs6.js} +4 -4
- package/webapp/dist/assets/xychartDiagram-PRI3JC2R-Ba2uJcs6.js.map +1 -0
- package/webapp/dist/index.html +2 -2
- package/webapp/dist/assets/_basePickBy-C0MXVhMo.js.map +0 -1
- package/webapp/dist/assets/_baseUniq-CRygl41M.js.map +0 -1
- package/webapp/dist/assets/arc-BeHJtnt2.js.map +0 -1
- package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-CGdo5TVi.js.map +0 -1
- package/webapp/dist/assets/blockDiagram-WCTKOSBZ-C59VaSGw.js.map +0 -1
- package/webapp/dist/assets/c4Diagram-IC4MRINW-B3YCBmTx.js.map +0 -1
- package/webapp/dist/assets/channel-Dn4i8EAY.js.map +0 -1
- package/webapp/dist/assets/chunk-4BX2VUAB-CQbB3HlW.js.map +0 -1
- package/webapp/dist/assets/chunk-55IACEB6-CkQR_Qu9.js.map +0 -1
- package/webapp/dist/assets/chunk-FMBD7UC4-YSIOuaST.js.map +0 -1
- package/webapp/dist/assets/chunk-JSJVCQXG-CWDLRawz.js.map +0 -1
- package/webapp/dist/assets/chunk-KX2RTZJC-DFiwgnFf.js.map +0 -1
- package/webapp/dist/assets/chunk-NQ4KR5QH-DBxY8LL2.js.map +0 -1
- package/webapp/dist/assets/chunk-QZHKN3VN-BAdR6lLc.js.map +0 -1
- package/webapp/dist/assets/chunk-WL4C6EOR-Bjl-j3bf.js.map +0 -1
- package/webapp/dist/assets/classDiagram-VBA2DB6C-KBeS6WXD.js.map +0 -1
- package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-KBeS6WXD.js.map +0 -1
- package/webapp/dist/assets/clone-C7-aS2vm.js.map +0 -1
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-Bo5IsL-5.js.map +0 -1
- package/webapp/dist/assets/dagre-KLK3FWXG-C3FeHj7D.js.map +0 -1
- package/webapp/dist/assets/diagram-E7M64L7V-0HfiRW0u.js.map +0 -1
- package/webapp/dist/assets/diagram-IFDJBPK2-DJwh7SMO.js.map +0 -1
- package/webapp/dist/assets/diagram-P4PSJMXO-Y0RbvUZX.js.map +0 -1
- package/webapp/dist/assets/erDiagram-INFDFZHY-B183xyLa.js.map +0 -1
- package/webapp/dist/assets/flowDiagram-PKNHOUZH-C_BR3Y3J.js.map +0 -1
- package/webapp/dist/assets/ganttDiagram-A5KZAMGK-CHLgkuJT.js.map +0 -1
- package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-D6C_HU1q.js.map +0 -1
- package/webapp/dist/assets/graph-D0hgB-X8.js +0 -782
- package/webapp/dist/assets/graph-D0hgB-X8.js.map +0 -1
- package/webapp/dist/assets/infoDiagram-LFFYTUFH-mnMS61NO.js.map +0 -1
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-XFIJsnJj.js +0 -966
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-XFIJsnJj.js.map +0 -1
- package/webapp/dist/assets/journeyDiagram-4ABVD52K-BdeERn0r.js.map +0 -1
- package/webapp/dist/assets/kanban-definition-K7BYSVSG-MLeCGcYg.js.map +0 -1
- package/webapp/dist/assets/layout-DY9VEQ9M.js.map +0 -1
- package/webapp/dist/assets/linear-D-T1xRsr.js.map +0 -1
- package/webapp/dist/assets/mindmap-definition-YRQLILUH-CrVm8vj2.js.map +0 -1
- package/webapp/dist/assets/pieDiagram-SKSYHLDU-GtLLV0r1.js.map +0 -1
- package/webapp/dist/assets/quadrantDiagram-337W2JSQ-BCgk_2LP.js.map +0 -1
- package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-DYUKHWKR.js.map +0 -1
- package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-CFAH8OaY.js.map +0 -1
- package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-BTnhbv6w.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-RAJIS63D-DWUnJTwO.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-B-fc52bp.js.map +0 -1
- package/webapp/dist/assets/timeline-definition-YZTLITO2-BMZ52QaG.js.map +0 -1
- package/webapp/dist/assets/treemap-KZPCXAKY-fgSrze0S.js.map +0 -1
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-D5DmDY9l.js +0 -2487
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-D5DmDY9l.js.map +0 -1
- package/webapp/dist/assets/xychartDiagram-JWTSCODW-D6aviLtC.js.map +0 -1
|
@@ -34,7 +34,13 @@ export declare function broadcastRunControlCountsSnapshot(): Promise<void>;
|
|
|
34
34
|
export declare function hasActiveRun(dialogId: DialogID): boolean;
|
|
35
35
|
export declare function getActiveRunSignal(dialogId: DialogID): AbortSignal | undefined;
|
|
36
36
|
export declare function createActiveRun(dialogId: DialogID): AbortSignal;
|
|
37
|
-
export declare function clearActiveRun(dialogId: DialogID
|
|
37
|
+
export declare function clearActiveRun(dialogId: DialogID, options?: Readonly<{
|
|
38
|
+
notifyBackendLoop?: boolean;
|
|
39
|
+
}>): void;
|
|
40
|
+
export declare function clearRootDialogQuarantiningIfIdle(rootDialogId: DialogID): void;
|
|
41
|
+
export declare function markRootDialogQuarantining(rootDialogId: DialogID): void;
|
|
42
|
+
export declare function clearRootDialogQuarantining(rootDialogId: DialogID): void;
|
|
43
|
+
export declare function forceStopActiveRunsForRootDialog(rootDialogId: DialogID): Promise<void>;
|
|
38
44
|
export declare function getStopRequestedReason(dialogId: DialogID): StopRequestedReason | undefined;
|
|
39
45
|
export declare function loadDialogExecutionMarker(dialogId: DialogID, status?: 'running' | 'completed' | 'archived'): Promise<DialogExecutionMarker | undefined>;
|
|
40
46
|
export declare function setDialogExecutionMarker(dialogId: DialogID, executionMarker: DialogExecutionMarker | undefined): Promise<void>;
|
|
@@ -28,6 +28,10 @@ exports.hasActiveRun = hasActiveRun;
|
|
|
28
28
|
exports.getActiveRunSignal = getActiveRunSignal;
|
|
29
29
|
exports.createActiveRun = createActiveRun;
|
|
30
30
|
exports.clearActiveRun = clearActiveRun;
|
|
31
|
+
exports.clearRootDialogQuarantiningIfIdle = clearRootDialogQuarantiningIfIdle;
|
|
32
|
+
exports.markRootDialogQuarantining = markRootDialogQuarantining;
|
|
33
|
+
exports.clearRootDialogQuarantining = clearRootDialogQuarantining;
|
|
34
|
+
exports.forceStopActiveRunsForRootDialog = forceStopActiveRunsForRootDialog;
|
|
31
35
|
exports.getStopRequestedReason = getStopRequestedReason;
|
|
32
36
|
exports.loadDialogExecutionMarker = loadDialogExecutionMarker;
|
|
33
37
|
exports.setDialogExecutionMarker = setDialogExecutionMarker;
|
|
@@ -40,12 +44,16 @@ exports.requestInterruptDialog = requestInterruptDialog;
|
|
|
40
44
|
exports.requestEmergencyStopAll = requestEmergencyStopAll;
|
|
41
45
|
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
42
46
|
const dialog_1 = require("./dialog");
|
|
47
|
+
const dialog_global_registry_1 = require("./dialog-global-registry");
|
|
48
|
+
const dialog_interruption_1 = require("./dialog-interruption");
|
|
43
49
|
const evt_registry_1 = require("./evt-registry");
|
|
44
50
|
const log_1 = require("./log");
|
|
45
51
|
const persistence_1 = require("./persistence");
|
|
52
|
+
const persistence_errors_1 = require("./persistence-errors");
|
|
46
53
|
const log = (0, log_1.createLogger)('dialog-display-state');
|
|
47
54
|
let broadcastToClients;
|
|
48
55
|
const activeRunsByDialogKey = new Map();
|
|
56
|
+
const quarantiningRootDialogIds = new Set();
|
|
49
57
|
function setDisplayStateBroadcaster(fn) {
|
|
50
58
|
broadcastToClients = fn;
|
|
51
59
|
}
|
|
@@ -63,7 +71,7 @@ function syncRunControlCountsAfterActiveRunChange(trigger, dialogId) {
|
|
|
63
71
|
})();
|
|
64
72
|
}
|
|
65
73
|
function isStoppedReasonResumable(reason) {
|
|
66
|
-
return reason
|
|
74
|
+
return (0, dialog_interruption_1.isInterruptionReasonManualResumeEligible)(reason);
|
|
67
75
|
}
|
|
68
76
|
function isDisplayStateResumable(state) {
|
|
69
77
|
return state?.kind === 'stopped' && state.continueEnabled;
|
|
@@ -93,27 +101,49 @@ function shouldBroadcastRunControlCounts(previous, next) {
|
|
|
93
101
|
async function getRunControlCountsSnapshot() {
|
|
94
102
|
let proceeding = 0;
|
|
95
103
|
let resumable = 0;
|
|
96
|
-
const
|
|
104
|
+
const activeRunKeysByDialogKey = new Map(activeRunsByDialogKey.entries());
|
|
97
105
|
const seenDialogKeys = new Set();
|
|
98
106
|
const dialogIds = await persistence_1.DialogPersistence.listAllDialogIds('running');
|
|
99
107
|
for (const dialogId of dialogIds) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
try {
|
|
109
|
+
const dialogKey = dialogId.key();
|
|
110
|
+
seenDialogKeys.add(dialogKey);
|
|
111
|
+
if (quarantiningRootDialogIds.has(dialogId.rootId)) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
// listAllDialogIds() is intentionally a candidate scan. Per-dialog latest reads below may
|
|
115
|
+
// still quarantine one malformed dialog without invalidating the rest of the snapshot.
|
|
116
|
+
const activeRun = activeRunKeysByDialogKey.get(dialogKey);
|
|
117
|
+
if (activeRun) {
|
|
118
|
+
proceeding++;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const latest = await persistence_1.DialogPersistence.loadDialogLatest(dialogId, 'running');
|
|
122
|
+
if (latest?.generating === true) {
|
|
123
|
+
proceeding++;
|
|
124
|
+
}
|
|
125
|
+
else if (isDialogLatestResumable(latest)) {
|
|
126
|
+
resumable++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (!(0, persistence_errors_1.findDomindsPersistenceFileError)(error)) {
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
log.warn('Skipping malformed dialog during run-control snapshot rebuild', error, {
|
|
134
|
+
dialogId: dialogId.valueOf(),
|
|
135
|
+
});
|
|
106
136
|
continue;
|
|
107
137
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
138
|
+
}
|
|
139
|
+
for (const [dialogKey, activeRun] of activeRunKeysByDialogKey.entries()) {
|
|
140
|
+
if (!activeRun) {
|
|
141
|
+
continue;
|
|
111
142
|
}
|
|
112
|
-
|
|
113
|
-
|
|
143
|
+
const [rootId] = dialogKey.includes('#') ? dialogKey.split('#') : [dialogKey];
|
|
144
|
+
if (!rootId || quarantiningRootDialogIds.has(rootId)) {
|
|
145
|
+
continue;
|
|
114
146
|
}
|
|
115
|
-
}
|
|
116
|
-
for (const dialogKey of activeRunDialogKeys) {
|
|
117
147
|
if (!seenDialogKeys.has(dialogKey)) {
|
|
118
148
|
proceeding++;
|
|
119
149
|
}
|
|
@@ -149,12 +179,76 @@ function createActiveRun(dialogId) {
|
|
|
149
179
|
syncRunControlCountsAfterActiveRunChange('create_active_run', dialogId);
|
|
150
180
|
return run.abortController.signal;
|
|
151
181
|
}
|
|
152
|
-
function clearActiveRun(dialogId) {
|
|
182
|
+
function clearActiveRun(dialogId, options) {
|
|
153
183
|
const deleted = activeRunsByDialogKey.delete(dialogId.key());
|
|
154
|
-
if (!deleted)
|
|
184
|
+
if (!deleted) {
|
|
185
|
+
clearQuarantiningRootDialogIfIdle(dialogId.rootId);
|
|
155
186
|
return;
|
|
187
|
+
}
|
|
188
|
+
clearQuarantiningRootDialogIfIdle(dialogId.rootId);
|
|
189
|
+
if (dialogId.selfId === dialogId.rootId && options?.notifyBackendLoop !== false) {
|
|
190
|
+
dialog_global_registry_1.globalDialogRegistry.notifyActiveRunCleared(dialogId.rootId, {
|
|
191
|
+
source: 'dialog_display_state_active_run_clear',
|
|
192
|
+
reason: 'root_active_run_cleared',
|
|
193
|
+
});
|
|
194
|
+
}
|
|
156
195
|
syncRunControlCountsAfterActiveRunChange('clear_active_run', dialogId);
|
|
157
196
|
}
|
|
197
|
+
function clearQuarantiningRootDialogIfIdle(rootId) {
|
|
198
|
+
for (const key of activeRunsByDialogKey.keys()) {
|
|
199
|
+
const [candidateRootId] = key.includes('#') ? key.split('#') : [key];
|
|
200
|
+
if (candidateRootId === rootId) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
quarantiningRootDialogIds.delete(rootId);
|
|
205
|
+
}
|
|
206
|
+
function clearRootDialogQuarantiningIfIdle(rootDialogId) {
|
|
207
|
+
clearQuarantiningRootDialogIfIdle(rootDialogId.selfId);
|
|
208
|
+
}
|
|
209
|
+
function markRootDialogQuarantining(rootDialogId) {
|
|
210
|
+
quarantiningRootDialogIds.add(rootDialogId.selfId);
|
|
211
|
+
}
|
|
212
|
+
function clearRootDialogQuarantining(rootDialogId) {
|
|
213
|
+
quarantiningRootDialogIds.delete(rootDialogId.selfId);
|
|
214
|
+
}
|
|
215
|
+
async function forceStopActiveRunsForRootDialog(rootDialogId) {
|
|
216
|
+
for (const key of Array.from(activeRunsByDialogKey.keys())) {
|
|
217
|
+
const [rootId, selfId] = key.includes('#') ? key.split('#') : [key, key];
|
|
218
|
+
if (!rootId || !selfId)
|
|
219
|
+
continue;
|
|
220
|
+
if (rootId !== rootDialogId.selfId)
|
|
221
|
+
continue;
|
|
222
|
+
const dialogId = new dialog_1.DialogID(selfId, rootId);
|
|
223
|
+
const run = activeRunsByDialogKey.get(key);
|
|
224
|
+
if (!run)
|
|
225
|
+
continue;
|
|
226
|
+
if (!run.stopRequested) {
|
|
227
|
+
run.stopRequested = 'emergency_stop';
|
|
228
|
+
try {
|
|
229
|
+
await setDialogDisplayState(dialogId, {
|
|
230
|
+
kind: 'proceeding_stop_requested',
|
|
231
|
+
reason: 'emergency_stop',
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
log.warn('Failed to persist stop-requested state while forcing root dialog stop', error, {
|
|
236
|
+
dialogId: dialogId.valueOf(),
|
|
237
|
+
rootDialogId: rootDialogId.valueOf(),
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
run.abortController.abort();
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
log.warn('Failed to abort active run while forcing root dialog stop', error, {
|
|
246
|
+
dialogId: dialogId.valueOf(),
|
|
247
|
+
rootDialogId: rootDialogId.valueOf(),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
158
252
|
function getStopRequestedReason(dialogId) {
|
|
159
253
|
return activeRunsByDialogKey.get(dialogId.key())?.stopRequested;
|
|
160
254
|
}
|
|
@@ -350,10 +444,36 @@ async function computeIdleDisplayStateFromPersistence(dialogId) {
|
|
|
350
444
|
}
|
|
351
445
|
return { kind: 'idle_waiting_user' };
|
|
352
446
|
}
|
|
447
|
+
async function computeIdleDisplayStateForReconciliation(dialogId) {
|
|
448
|
+
try {
|
|
449
|
+
return await computeIdleDisplayStateFromPersistence(dialogId);
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
if (!(0, persistence_errors_1.findDomindsPersistenceFileError)(error)) {
|
|
453
|
+
throw error;
|
|
454
|
+
}
|
|
455
|
+
log.warn('Skipping malformed dialog during display-state idle reconstruction', error, {
|
|
456
|
+
dialogId: dialogId.valueOf(),
|
|
457
|
+
});
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
353
461
|
async function reconcileDisplayStatesAfterRestart() {
|
|
354
462
|
const dialogIds = await persistence_1.DialogPersistence.listAllDialogIds('running');
|
|
355
463
|
for (const dialogId of dialogIds) {
|
|
356
|
-
|
|
464
|
+
let latest;
|
|
465
|
+
try {
|
|
466
|
+
latest = await persistence_1.DialogPersistence.loadDialogLatest(dialogId, 'running');
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
if (!(0, persistence_errors_1.findDomindsPersistenceFileError)(error)) {
|
|
470
|
+
throw error;
|
|
471
|
+
}
|
|
472
|
+
log.warn('Skipping malformed dialog during display-state restart reconciliation', error, {
|
|
473
|
+
dialogId: dialogId.valueOf(),
|
|
474
|
+
});
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
357
477
|
const existing = latest?.displayState;
|
|
358
478
|
const existingMarker = latest?.executionMarker;
|
|
359
479
|
if (existingMarker && existingMarker.kind === 'dead' && dialogId.selfId !== dialogId.rootId) {
|
|
@@ -380,7 +500,10 @@ async function reconcileDisplayStatesAfterRestart() {
|
|
|
380
500
|
(existing !== undefined &&
|
|
381
501
|
(existing.kind === 'proceeding' || existing.kind === 'proceeding_stop_requested'));
|
|
382
502
|
if (wasProceeding) {
|
|
383
|
-
const nextIdle = await
|
|
503
|
+
const nextIdle = await computeIdleDisplayStateForReconciliation(dialogId);
|
|
504
|
+
if (!nextIdle) {
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
384
507
|
const next = nextIdle.kind === 'blocked'
|
|
385
508
|
? nextIdle
|
|
386
509
|
: {
|
|
@@ -406,7 +529,10 @@ async function reconcileDisplayStatesAfterRestart() {
|
|
|
406
529
|
continue;
|
|
407
530
|
}
|
|
408
531
|
if (!existing) {
|
|
409
|
-
const inferred = await
|
|
532
|
+
const inferred = await computeIdleDisplayStateForReconciliation(dialogId);
|
|
533
|
+
if (!inferred) {
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
410
536
|
try {
|
|
411
537
|
await persistence_1.DialogPersistence.mutateDialogLatest(dialogId, () => ({
|
|
412
538
|
kind: 'patch',
|
package/dist/dialog-fork.js
CHANGED
|
@@ -473,21 +473,29 @@ async function appendForkBaselineState(plan, baselineSubdialogCreatedRecords) {
|
|
|
473
473
|
}
|
|
474
474
|
async function persistForkPlan(args) {
|
|
475
475
|
const { plan } = args;
|
|
476
|
-
let rewrittenMetadata;
|
|
477
476
|
if (plan.targetId.selfId === plan.targetId.rootId) {
|
|
478
|
-
|
|
479
|
-
|
|
477
|
+
if (plan.metadata.supdialogId !== undefined ||
|
|
478
|
+
plan.metadata.sessionSlug !== undefined ||
|
|
479
|
+
plan.metadata.assignmentFromSup !== undefined) {
|
|
480
|
+
throw new Error(`fork root plan received subdialog metadata: ${plan.targetId.valueOf()}`);
|
|
481
|
+
}
|
|
482
|
+
const rewrittenMetadata = {
|
|
480
483
|
id: plan.targetId.selfId,
|
|
484
|
+
agentId: plan.metadata.agentId,
|
|
485
|
+
taskDocPath: plan.metadata.taskDocPath,
|
|
481
486
|
createdAt: args.now,
|
|
487
|
+
...(plan.metadata.priming ? { priming: plan.metadata.priming } : {}),
|
|
482
488
|
};
|
|
489
|
+
await persistence_1.DialogPersistence.saveRootDialogMetadata(plan.targetId, rewrittenMetadata, 'running');
|
|
483
490
|
}
|
|
484
491
|
else {
|
|
485
492
|
if (plan.metadata.supdialogId === undefined) {
|
|
486
493
|
throw new Error(`fork subdialog plan missing supdialog metadata: ${plan.targetId.valueOf()}`);
|
|
487
494
|
}
|
|
488
|
-
rewrittenMetadata = rewriteSubdialogMetadataForFork(plan.metadata, plan.sourceId.rootId, plan.targetId.rootId);
|
|
495
|
+
const rewrittenMetadata = rewriteSubdialogMetadataForFork(plan.metadata, plan.sourceId.rootId, plan.targetId.rootId);
|
|
496
|
+
await persistence_1.DialogPersistence.ensureSubdialogDirectory(plan.targetId, 'running');
|
|
497
|
+
await persistence_1.DialogPersistence.saveSubdialogMetadata(plan.targetId, rewrittenMetadata, 'running');
|
|
489
498
|
}
|
|
490
|
-
await persistence_1.DialogPersistence.saveDialogMetadata(plan.targetId, rewrittenMetadata, 'running');
|
|
491
499
|
for (const course of plan.retainedCourses) {
|
|
492
500
|
for (const event of course.events) {
|
|
493
501
|
await persistence_1.DialogPersistence.appendEvent(plan.targetId, course.course, rewriteRecordForFork(event, plan.targetId.rootId), 'running');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RootDialog } from './dialog';
|
|
2
2
|
export type DriveTriggerEvent = Readonly<{
|
|
3
3
|
type: 'drive_trigger_evt';
|
|
4
|
-
action: 'mark_needs_drive' | 'mark_not_needing_drive';
|
|
4
|
+
action: 'mark_needs_drive' | 'mark_not_needing_drive' | 'active_run_cleared';
|
|
5
5
|
rootId: string;
|
|
6
6
|
entryFound: boolean;
|
|
7
7
|
previousNeedsDrive: boolean | null;
|
|
@@ -28,6 +28,10 @@ declare class GlobalDialogRegistry {
|
|
|
28
28
|
waitForDriveTrigger(): Promise<DriveTriggerEvent>;
|
|
29
29
|
markNeedsDrive(rootId: string, meta?: DriveTriggerMeta): void;
|
|
30
30
|
markNotNeedingDrive(rootId: string, meta?: DriveTriggerMeta): void;
|
|
31
|
+
notifyActiveRunCleared(rootId: string, meta?: DriveTriggerMeta): void;
|
|
32
|
+
noteActiveRunBlockedQueuedDrive(rootId: string): void;
|
|
33
|
+
hasPendingActiveRunClearedWake(rootId: string): boolean;
|
|
34
|
+
isMarkedNeedingDrive(rootId: string): boolean;
|
|
31
35
|
getDialogsNeedingDrive(): RootDialog[];
|
|
32
36
|
getLastDriveTrigger(rootId: string): DriveTriggerEvent | undefined;
|
|
33
37
|
getAll(): RootDialog[];
|
|
@@ -29,7 +29,11 @@ class GlobalDialogRegistry {
|
|
|
29
29
|
if (existing) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
|
-
this.entries.set(rootDialog.id.rootId, {
|
|
32
|
+
this.entries.set(rootDialog.id.rootId, {
|
|
33
|
+
rootDialog,
|
|
34
|
+
needsDrive: false,
|
|
35
|
+
activeRunClearedWakePending: false,
|
|
36
|
+
});
|
|
33
37
|
void (async () => {
|
|
34
38
|
try {
|
|
35
39
|
const needsDrive = await persistence_1.DialogPersistence.getNeedsDrive(rootDialog.id);
|
|
@@ -82,6 +86,8 @@ class GlobalDialogRegistry {
|
|
|
82
86
|
const previousNeedsDrive = entry ? entry.needsDrive : null;
|
|
83
87
|
if (entry) {
|
|
84
88
|
entry.needsDrive = true;
|
|
89
|
+
// A fresh queueing trigger supersedes any earlier "wake me once active run clears" debt.
|
|
90
|
+
entry.activeRunClearedWakePending = false;
|
|
85
91
|
}
|
|
86
92
|
this.publishDriveTrigger({
|
|
87
93
|
action: 'mark_needs_drive',
|
|
@@ -101,6 +107,7 @@ class GlobalDialogRegistry {
|
|
|
101
107
|
const previousNeedsDrive = entry ? entry.needsDrive : null;
|
|
102
108
|
if (entry) {
|
|
103
109
|
entry.needsDrive = false;
|
|
110
|
+
entry.activeRunClearedWakePending = false;
|
|
104
111
|
}
|
|
105
112
|
this.publishDriveTrigger({
|
|
106
113
|
action: 'mark_not_needing_drive',
|
|
@@ -111,6 +118,43 @@ class GlobalDialogRegistry {
|
|
|
111
118
|
meta: triggerMeta,
|
|
112
119
|
});
|
|
113
120
|
}
|
|
121
|
+
notifyActiveRunCleared(rootId, meta) {
|
|
122
|
+
const triggerMeta = meta ?? {
|
|
123
|
+
source: 'unknown',
|
|
124
|
+
reason: 'unspecified',
|
|
125
|
+
};
|
|
126
|
+
const entry = this.entries.get(rootId);
|
|
127
|
+
if (!entry) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (!entry.activeRunClearedWakePending || !entry.needsDrive) {
|
|
131
|
+
entry.activeRunClearedWakePending = false;
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const currentNeedsDrive = entry ? entry.needsDrive : null;
|
|
135
|
+
entry.activeRunClearedWakePending = false;
|
|
136
|
+
this.publishDriveTrigger({
|
|
137
|
+
action: 'active_run_cleared',
|
|
138
|
+
rootId,
|
|
139
|
+
entryFound: true,
|
|
140
|
+
previousNeedsDrive: currentNeedsDrive,
|
|
141
|
+
nextNeedsDrive: entry.needsDrive,
|
|
142
|
+
meta: triggerMeta,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
noteActiveRunBlockedQueuedDrive(rootId) {
|
|
146
|
+
const entry = this.entries.get(rootId);
|
|
147
|
+
if (!entry || !entry.needsDrive) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
entry.activeRunClearedWakePending = true;
|
|
151
|
+
}
|
|
152
|
+
hasPendingActiveRunClearedWake(rootId) {
|
|
153
|
+
return this.entries.get(rootId)?.activeRunClearedWakePending === true;
|
|
154
|
+
}
|
|
155
|
+
isMarkedNeedingDrive(rootId) {
|
|
156
|
+
return this.entries.get(rootId)?.needsDrive === true;
|
|
157
|
+
}
|
|
114
158
|
getDialogsNeedingDrive() {
|
|
115
159
|
return Array.from(this.entries.values())
|
|
116
160
|
.filter((entry) => entry.needsDrive)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DialogInterruptionReason } from '@longrun-ai/kernel/types/display-state';
|
|
2
|
+
/**
|
|
3
|
+
* Decides whether a finalized stopped dialog should expose manual Continue.
|
|
4
|
+
*
|
|
5
|
+
* This only applies to the persisted/broadcast final stopped state after the driver has fully
|
|
6
|
+
* unwound and confirmed an interrupted terminal projection. Transient interruption markers and
|
|
7
|
+
* retry-stop progress events must stay disabled until that final stopped state is written. Do not
|
|
8
|
+
* "simplify" this by enabling Continue earlier: that would let the UI offer a resume action before
|
|
9
|
+
* the dialog is actually resumable again, reintroducing exactly the class of race/false-positive
|
|
10
|
+
* bugs this split is here to prevent.
|
|
11
|
+
*
|
|
12
|
+
* `llm_retry_stopped` is intentionally resumable here:
|
|
13
|
+
* - manual Continue starts a fresh drive invocation, which naturally resets per-run retry state
|
|
14
|
+
* and provider-quirk tracking state;
|
|
15
|
+
* - it does NOT reset process-wide adaptive smart-rate backoff, which is shared by
|
|
16
|
+
* provider/model and should keep protecting the system.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isInterruptionReasonManualResumeEligible(reason: DialogInterruptionReason): boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInterruptionReasonManualResumeEligible = isInterruptionReasonManualResumeEligible;
|
|
4
|
+
/**
|
|
5
|
+
* Decides whether a finalized stopped dialog should expose manual Continue.
|
|
6
|
+
*
|
|
7
|
+
* This only applies to the persisted/broadcast final stopped state after the driver has fully
|
|
8
|
+
* unwound and confirmed an interrupted terminal projection. Transient interruption markers and
|
|
9
|
+
* retry-stop progress events must stay disabled until that final stopped state is written. Do not
|
|
10
|
+
* "simplify" this by enabling Continue earlier: that would let the UI offer a resume action before
|
|
11
|
+
* the dialog is actually resumable again, reintroducing exactly the class of race/false-positive
|
|
12
|
+
* bugs this split is here to prevent.
|
|
13
|
+
*
|
|
14
|
+
* `llm_retry_stopped` is intentionally resumable here:
|
|
15
|
+
* - manual Continue starts a fresh drive invocation, which naturally resets per-run retry state
|
|
16
|
+
* and provider-quirk tracking state;
|
|
17
|
+
* - it does NOT reset process-wide adaptive smart-rate backoff, which is shared by
|
|
18
|
+
* provider/model and should keep protecting the system.
|
|
19
|
+
*/
|
|
20
|
+
function isInterruptionReasonManualResumeEligible(reason) {
|
|
21
|
+
switch (reason.kind) {
|
|
22
|
+
case 'user_stop':
|
|
23
|
+
case 'emergency_stop':
|
|
24
|
+
case 'server_restart':
|
|
25
|
+
case 'fork_continue_ready':
|
|
26
|
+
case 'system_stop':
|
|
27
|
+
case 'llm_retry_stopped':
|
|
28
|
+
return true;
|
|
29
|
+
default: {
|
|
30
|
+
const _exhaustive = reason;
|
|
31
|
+
return _exhaustive;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|