dominds 1.25.2 → 1.25.4
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/cli/tui.js +2 -0
- package/dist/cli/webui.js +2 -0
- package/dist/cli.js +2 -0
- package/dist/dialog-display-state.js +6 -7
- package/dist/docs/dialog-system.md +15 -29
- package/dist/docs/dialog-system.zh.md +15 -29
- package/dist/evt-registry.js +2 -0
- package/dist/llm/kernel-driver/drive.js +137 -7
- package/dist/llm/kernel-driver/flow.js +46 -20
- package/dist/llm/kernel-driver/reply-guidance.js +5 -5
- package/dist/persistence-errors.d.ts +1 -1
- package/dist/persistence.d.ts +50 -1
- package/dist/persistence.js +549 -4
- package/dist/process-title.d.ts +2 -0
- package/dist/process-title.js +13 -0
- package/dist/runtime/driver-messages.d.ts +7 -1
- package/dist/runtime/driver-messages.js +33 -11
- package/dist/runtime/interjection-pause-stop.js +8 -7
- package/dist/server/api-routes.js +14 -0
- package/dist/server/dominds-self-update.d.ts +1 -0
- package/dist/server/dominds-self-update.js +17 -0
- package/dist/server/websocket-handler.js +73 -6
- package/dist/tools/cmd-runner-protocol.d.ts +1 -0
- package/dist/tools/cmd-runner-protocol.js +6 -0
- package/dist/tools/cmd-runner.js +1 -0
- package/dist/tools/os.d.ts +2 -4
- package/dist/tools/os.js +79 -4
- package/package.json +3 -3
- package/webapp/dist/assets/{_basePickBy-CbWZ8qnS.js → _basePickBy-fZ31r-iF.js} +3 -3
- package/webapp/dist/assets/_basePickBy-fZ31r-iF.js.map +1 -0
- package/webapp/dist/assets/{_baseUniq-IY-Vfzx1.js → _baseUniq-CI1keLoL.js} +2 -2
- package/webapp/dist/assets/_baseUniq-CI1keLoL.js.map +1 -0
- package/webapp/dist/assets/{arc--U2Vks6y.js → arc-1NeUqzoV.js} +2 -2
- package/webapp/dist/assets/arc-1NeUqzoV.js.map +1 -0
- package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-DpryGqjy.js → architectureDiagram-2XIMDMQ5-C7SdzYIh.js} +26 -8
- package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-C7SdzYIh.js.map +1 -0
- package/webapp/dist/assets/{blockDiagram-VD42YOAC-TTufCfiE.js → blockDiagram-WCTKOSBZ-Cmpu3kIy.js} +187 -170
- package/webapp/dist/assets/blockDiagram-WCTKOSBZ-Cmpu3kIy.js.map +1 -0
- package/webapp/dist/assets/{c4Diagram-YG6GDRKO-B4RPsw5H.js → c4Diagram-IC4MRINW-ChGTHIor.js} +4 -4
- package/webapp/dist/assets/c4Diagram-IC4MRINW-ChGTHIor.js.map +1 -0
- package/webapp/dist/assets/{channel-DAtGYJHZ.js → channel-ndS-XTQQ.js} +2 -2
- package/webapp/dist/assets/channel-ndS-XTQQ.js.map +1 -0
- package/webapp/dist/assets/{chunk-4BX2VUAB-JtO__vAF.js → chunk-4BX2VUAB-Cw5FtBd_.js} +2 -2
- package/webapp/dist/assets/chunk-4BX2VUAB-Cw5FtBd_.js.map +1 -0
- package/webapp/dist/assets/{chunk-55IACEB6-JMRC8yG1.js → chunk-55IACEB6-D3G71JdA.js} +2 -2
- package/webapp/dist/assets/chunk-55IACEB6-D3G71JdA.js.map +1 -0
- package/webapp/dist/assets/{chunk-FMBD7UC4-DFXKLjHC.js → chunk-FMBD7UC4-BcugPyy7.js} +2 -2
- package/webapp/dist/assets/chunk-FMBD7UC4-BcugPyy7.js.map +1 -0
- package/webapp/dist/assets/{chunk-TZMSLE5B-BaE4C244.js → chunk-JSJVCQXG-DvuxYuNq.js} +14 -6
- package/webapp/dist/assets/chunk-JSJVCQXG-DvuxYuNq.js.map +1 -0
- package/webapp/dist/assets/{chunk-QN33PNHL-BKzkeJ-b.js → chunk-KX2RTZJC-BQ42xd4s.js} +2 -2
- package/webapp/dist/assets/chunk-KX2RTZJC-BQ42xd4s.js.map +1 -0
- package/webapp/dist/assets/{chunk-DI55MBZ5-j9B4rifK.js → chunk-NQ4KR5QH-CGEMYTch.js} +9 -7
- package/webapp/dist/assets/chunk-NQ4KR5QH-CGEMYTch.js.map +1 -0
- package/webapp/dist/assets/{chunk-QZHKN3VN-DiZd3UNl.js → chunk-QZHKN3VN-CxNTVm5w.js} +2 -2
- package/webapp/dist/assets/chunk-QZHKN3VN-CxNTVm5w.js.map +1 -0
- package/webapp/dist/assets/{chunk-B4BG7PRW-BDIpf8Iz.js → chunk-WL4C6EOR-CIwdSg5q.js} +171 -121
- package/webapp/dist/assets/chunk-WL4C6EOR-CIwdSg5q.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-2ON5EDUG-CNF8ZohD.js → classDiagram-VBA2DB6C-Dl05PJAP.js} +7 -6
- package/webapp/dist/assets/classDiagram-VBA2DB6C-Dl05PJAP.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-CNF8ZohD.js → classDiagram-v2-RAHNMMFH-Dl05PJAP.js} +7 -6
- package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-Dl05PJAP.js.map +1 -0
- package/webapp/dist/assets/{clone-Nq0Ko0Gv.js → clone-KCj1-QMr.js} +2 -2
- package/webapp/dist/assets/clone-KCj1-QMr.js.map +1 -0
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-uHPLSeKv.js → cose-bilkent-S5V4N54A-BttciCz5.js} +2 -2
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-BttciCz5.js.map +1 -0
- package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
- package/webapp/dist/assets/{dagre-6UL2VRFP-C1awWpU3.js → dagre-KLK3FWXG-Dm5yE9k2.js} +7 -7
- package/webapp/dist/assets/dagre-KLK3FWXG-Dm5yE9k2.js.map +1 -0
- package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
- package/webapp/dist/assets/{diagram-PSM6KHXK-Bf69p76M.js → diagram-E7M64L7V-C80ZsiBG.js} +10 -10
- package/webapp/dist/assets/diagram-E7M64L7V-C80ZsiBG.js.map +1 -0
- package/webapp/dist/assets/{diagram-QEK2KX5R-Bvlbx8Jp.js → diagram-IFDJBPK2-CqKidH4n.js} +9 -8
- package/webapp/dist/assets/diagram-IFDJBPK2-CqKidH4n.js.map +1 -0
- package/webapp/dist/assets/{diagram-S2PKOQOG-CGjGalBu.js → diagram-P4PSJMXO-EHVjfzUV.js} +8 -8
- package/webapp/dist/assets/diagram-P4PSJMXO-EHVjfzUV.js.map +1 -0
- package/webapp/dist/assets/{erDiagram-Q2GNP2WA-Ds3qhwkG.js → erDiagram-INFDFZHY-7MrtsOIt.js} +96 -75
- package/webapp/dist/assets/erDiagram-INFDFZHY-7MrtsOIt.js.map +1 -0
- package/webapp/dist/assets/{flowDiagram-NV44I4VS-B1wDG_l5.js → flowDiagram-PKNHOUZH-D6hXqCy7.js} +98 -81
- package/webapp/dist/assets/flowDiagram-PKNHOUZH-D6hXqCy7.js.map +1 -0
- package/webapp/dist/assets/{ganttDiagram-JELNMOA3-BwuYt2bO.js → ganttDiagram-A5KZAMGK-DLO0XCDk.js} +28 -3
- package/webapp/dist/assets/ganttDiagram-A5KZAMGK-DLO0XCDk.js.map +1 -0
- package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-B2Tw773z.js → gitGraphDiagram-K3NZZRJ6-BmVD_nQP.js} +38 -46
- package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-BmVD_nQP.js.map +1 -0
- package/webapp/dist/assets/graph-DQTj8O0Q.js +782 -0
- package/webapp/dist/assets/graph-DQTj8O0Q.js.map +1 -0
- package/webapp/dist/assets/{index-yycTJNYb.css → index-BQoNJEGT.css} +1 -1
- package/webapp/dist/assets/{index-arD81Nnh.js → index-BXjq-k48.js} +1512 -1097
- package/webapp/dist/assets/{index-arD81Nnh.js.map → index-BXjq-k48.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-HS3SLOUP-C9_JKYhm.js → infoDiagram-LFFYTUFH-D2fqM9Fn.js} +7 -7
- package/webapp/dist/assets/infoDiagram-LFFYTUFH-D2fqM9Fn.js.map +1 -0
- package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-kp7lB6-f.js +966 -0
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-kp7lB6-f.js.map +1 -0
- package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-BhZggYOL.js → journeyDiagram-4ABVD52K-DmbA52J-.js} +5 -5
- package/webapp/dist/assets/journeyDiagram-4ABVD52K-DmbA52J-.js.map +1 -0
- package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-B-R2Xm4Y.js → kanban-definition-K7BYSVSG-DRUw-P-d.js} +5 -3
- package/webapp/dist/assets/kanban-definition-K7BYSVSG-DRUw-P-d.js.map +1 -0
- package/webapp/dist/assets/{layout-BzMatxDa.js → layout-BUoHHXzn.js} +5 -5
- package/webapp/dist/assets/layout-BUoHHXzn.js.map +1 -0
- package/webapp/dist/assets/{linear-BuuJkw_U.js → linear-xVSAq8rI.js} +2 -2
- package/webapp/dist/assets/linear-xVSAq8rI.js.map +1 -0
- package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-BR7oDKBR.js → mindmap-definition-YRQLILUH-BcajbGmW.js} +7 -5
- package/webapp/dist/assets/mindmap-definition-YRQLILUH-BcajbGmW.js.map +1 -0
- package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
- package/webapp/dist/assets/{pieDiagram-ADFJNKIX--QWeT2vZ.js → pieDiagram-SKSYHLDU-Bu8kmCW6.js} +8 -8
- package/webapp/dist/assets/pieDiagram-SKSYHLDU-Bu8kmCW6.js.map +1 -0
- package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-BpqtmN3r.js → quadrantDiagram-337W2JSQ-DIBSNUGa.js} +3 -3
- package/webapp/dist/assets/quadrantDiagram-337W2JSQ-DIBSNUGa.js.map +1 -0
- package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-CIXjIi4F.js → requirementDiagram-Z7DCOOCP-CkrDkbBt.js} +16 -6
- package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-CkrDkbBt.js.map +1 -0
- package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-DJIt7SRz.js → sankeyDiagram-WA2Y5GQK-BZ-1R8pc.js} +2 -2
- package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-BZ-1R8pc.js.map +1 -0
- package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-BpDK1ROT.js → sequenceDiagram-2WXFIKYE-DYoNARdO.js} +601 -201
- package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-DYoNARdO.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-BoKGfmHf.js → stateDiagram-RAJIS63D-D9v19nvh.js} +9 -9
- package/webapp/dist/assets/stateDiagram-RAJIS63D-D9v19nvh.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3--haXC2JK.js → stateDiagram-v2-FVOUBMTO-BYw5ZwtH.js} +5 -5
- package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-BYw5ZwtH.js.map +1 -0
- package/webapp/dist/assets/{timeline-definition-IT6M3QCI-BmSg3Hjf.js → timeline-definition-YZTLITO2-BT10dRIJ.js} +3 -3
- package/webapp/dist/assets/timeline-definition-YZTLITO2-BT10dRIJ.js.map +1 -0
- package/webapp/dist/assets/{treemap-GDKQZRPO-D9OuyDVA.js → treemap-KZPCXAKY-yPoPC5hc.js} +37 -24
- package/webapp/dist/assets/treemap-KZPCXAKY-yPoPC5hc.js.map +1 -0
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-tryg3OaY.js +2487 -0
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-tryg3OaY.js.map +1 -0
- package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-CVqSvO_S.js → xychartDiagram-JWTSCODW-BWLUzo9S.js} +4 -4
- package/webapp/dist/assets/xychartDiagram-JWTSCODW-BWLUzo9S.js.map +1 -0
- package/webapp/dist/index.html +2 -2
- package/webapp/dist/assets/_basePickBy-CbWZ8qnS.js.map +0 -1
- package/webapp/dist/assets/_baseUniq-IY-Vfzx1.js.map +0 -1
- package/webapp/dist/assets/arc--U2Vks6y.js.map +0 -1
- package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DpryGqjy.js.map +0 -1
- package/webapp/dist/assets/blockDiagram-VD42YOAC-TTufCfiE.js.map +0 -1
- package/webapp/dist/assets/c4Diagram-YG6GDRKO-B4RPsw5H.js.map +0 -1
- package/webapp/dist/assets/channel-DAtGYJHZ.js.map +0 -1
- package/webapp/dist/assets/chunk-4BX2VUAB-JtO__vAF.js.map +0 -1
- package/webapp/dist/assets/chunk-55IACEB6-JMRC8yG1.js.map +0 -1
- package/webapp/dist/assets/chunk-B4BG7PRW-BDIpf8Iz.js.map +0 -1
- package/webapp/dist/assets/chunk-DI55MBZ5-j9B4rifK.js.map +0 -1
- package/webapp/dist/assets/chunk-FMBD7UC4-DFXKLjHC.js.map +0 -1
- package/webapp/dist/assets/chunk-QN33PNHL-BKzkeJ-b.js.map +0 -1
- package/webapp/dist/assets/chunk-QZHKN3VN-DiZd3UNl.js.map +0 -1
- package/webapp/dist/assets/chunk-TZMSLE5B-BaE4C244.js.map +0 -1
- package/webapp/dist/assets/classDiagram-2ON5EDUG-CNF8ZohD.js.map +0 -1
- package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-CNF8ZohD.js.map +0 -1
- package/webapp/dist/assets/clone-Nq0Ko0Gv.js.map +0 -1
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-uHPLSeKv.js.map +0 -1
- package/webapp/dist/assets/dagre-6UL2VRFP-C1awWpU3.js.map +0 -1
- package/webapp/dist/assets/diagram-PSM6KHXK-Bf69p76M.js.map +0 -1
- package/webapp/dist/assets/diagram-QEK2KX5R-Bvlbx8Jp.js.map +0 -1
- package/webapp/dist/assets/diagram-S2PKOQOG-CGjGalBu.js.map +0 -1
- package/webapp/dist/assets/erDiagram-Q2GNP2WA-Ds3qhwkG.js.map +0 -1
- package/webapp/dist/assets/flowDiagram-NV44I4VS-B1wDG_l5.js.map +0 -1
- package/webapp/dist/assets/ganttDiagram-JELNMOA3-BwuYt2bO.js.map +0 -1
- package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-B2Tw773z.js.map +0 -1
- package/webapp/dist/assets/graph-CS_H7jBi.js +0 -425
- package/webapp/dist/assets/graph-CS_H7jBi.js.map +0 -1
- package/webapp/dist/assets/infoDiagram-HS3SLOUP-C9_JKYhm.js.map +0 -1
- package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-BhZggYOL.js.map +0 -1
- package/webapp/dist/assets/kanban-definition-3W4ZIXB7-B-R2Xm4Y.js.map +0 -1
- package/webapp/dist/assets/layout-BzMatxDa.js.map +0 -1
- package/webapp/dist/assets/linear-BuuJkw_U.js.map +0 -1
- package/webapp/dist/assets/mindmap-definition-VGOIOE7T-BR7oDKBR.js.map +0 -1
- package/webapp/dist/assets/pieDiagram-ADFJNKIX--QWeT2vZ.js.map +0 -1
- package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-BpqtmN3r.js.map +0 -1
- package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-CIXjIi4F.js.map +0 -1
- package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-DJIt7SRz.js.map +0 -1
- package/webapp/dist/assets/sequenceDiagram-WL72ISMW-BpDK1ROT.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-FKZM4ZOC-BoKGfmHf.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3--haXC2JK.js.map +0 -1
- package/webapp/dist/assets/timeline-definition-IT6M3QCI-BmSg3Hjf.js.map +0 -1
- package/webapp/dist/assets/treemap-GDKQZRPO-D9OuyDVA.js.map +0 -1
- package/webapp/dist/assets/xychartDiagram-PRI3JC2R-CVqSvO_S.js.map +0 -1
package/dist/persistence.js
CHANGED
|
@@ -107,6 +107,9 @@ function summarizeLatestProjectionState(latest) {
|
|
|
107
107
|
tellaskResultCount: latest.tellaskResults.results.length,
|
|
108
108
|
latestAssignmentAnchor: latest.latestAssignmentAnchor ?? null,
|
|
109
109
|
sideDialogFinalResponse: latest.sideDialogFinalResponse ?? null,
|
|
110
|
+
pendingUserInterjectionReplyMsgId: latest.pendingUserInterjectionReply?.msgId ?? null,
|
|
111
|
+
pendingUserInterjectionReplyCourse: latest.pendingUserInterjectionReply?.course ?? null,
|
|
112
|
+
pendingUserInterjectionReplyGenseq: latest.pendingUserInterjectionReply?.genseq ?? null,
|
|
110
113
|
pendingRuntimePromptMsgId: latest.pendingRuntimePrompt?.msgId ?? null,
|
|
111
114
|
pendingRuntimePromptOrigin: latest.pendingRuntimePrompt?.origin ?? null,
|
|
112
115
|
pendingRuntimePromptGrammar: latest.pendingRuntimePrompt?.grammar ?? null,
|
|
@@ -145,6 +148,9 @@ function summarizeLatestMutationPatch(patch) {
|
|
|
145
148
|
tellaskResultCount: patch.tellaskResults?.results.length ?? null,
|
|
146
149
|
latestAssignmentAnchor: patch.latestAssignmentAnchor ?? null,
|
|
147
150
|
sideDialogFinalResponse: patch.sideDialogFinalResponse ?? null,
|
|
151
|
+
pendingUserInterjectionReplyMsgId: patch.pendingUserInterjectionReply?.msgId ?? null,
|
|
152
|
+
pendingUserInterjectionReplyCourse: patch.pendingUserInterjectionReply?.course ?? null,
|
|
153
|
+
pendingUserInterjectionReplyGenseq: patch.pendingUserInterjectionReply?.genseq ?? null,
|
|
148
154
|
pendingRuntimePromptMsgId: patch.pendingRuntimePrompt?.msgId ?? null,
|
|
149
155
|
pendingRuntimePromptOrigin: patch.pendingRuntimePrompt?.origin ?? null,
|
|
150
156
|
pendingRuntimePromptGrammar: patch.pendingRuntimePrompt?.grammar ?? null,
|
|
@@ -2090,6 +2096,32 @@ function parseDialogLatestFile(value) {
|
|
|
2090
2096
|
})();
|
|
2091
2097
|
if (sideDialogFinalResponse === null)
|
|
2092
2098
|
return null;
|
|
2099
|
+
const pendingUserInterjectionReplyRaw = value
|
|
2100
|
+
.pendingUserInterjectionReply;
|
|
2101
|
+
const pendingUserInterjectionReply = (() => {
|
|
2102
|
+
if (pendingUserInterjectionReplyRaw === undefined)
|
|
2103
|
+
return undefined;
|
|
2104
|
+
if (!isRecord(pendingUserInterjectionReplyRaw))
|
|
2105
|
+
return null;
|
|
2106
|
+
const msgId = pendingUserInterjectionReplyRaw.msgId;
|
|
2107
|
+
const course = pendingUserInterjectionReplyRaw.course;
|
|
2108
|
+
const genseq = pendingUserInterjectionReplyRaw.genseq;
|
|
2109
|
+
if (typeof msgId !== 'string' || msgId.trim() === '')
|
|
2110
|
+
return null;
|
|
2111
|
+
if (typeof course !== 'number' || !Number.isFinite(course) || Math.floor(course) <= 0) {
|
|
2112
|
+
return null;
|
|
2113
|
+
}
|
|
2114
|
+
if (typeof genseq !== 'number' || !Number.isFinite(genseq) || Math.floor(genseq) <= 0) {
|
|
2115
|
+
return null;
|
|
2116
|
+
}
|
|
2117
|
+
return {
|
|
2118
|
+
msgId,
|
|
2119
|
+
course: (0, storage_1.toDialogCourseNumber)(course),
|
|
2120
|
+
genseq: (0, storage_1.toCallSiteGenseqNo)(genseq),
|
|
2121
|
+
};
|
|
2122
|
+
})();
|
|
2123
|
+
if (pendingUserInterjectionReply === null)
|
|
2124
|
+
return null;
|
|
2093
2125
|
const latestAssignmentAnchorRaw = value.latestAssignmentAnchor;
|
|
2094
2126
|
const latestAssignmentAnchor = (() => {
|
|
2095
2127
|
if (latestAssignmentAnchorRaw === undefined)
|
|
@@ -2202,6 +2234,7 @@ function parseDialogLatestFile(value) {
|
|
|
2202
2234
|
sideDialogFinalResponse,
|
|
2203
2235
|
fbrState,
|
|
2204
2236
|
deferredReplyReassertion,
|
|
2237
|
+
pendingUserInterjectionReply,
|
|
2205
2238
|
pendingRuntimePrompt,
|
|
2206
2239
|
disableDiligencePush: value.disableDiligencePush,
|
|
2207
2240
|
diligencePushRemainingBudget: value.diligencePushRemainingBudget,
|
|
@@ -2346,6 +2379,48 @@ function isQuestions4HumanFile(value) {
|
|
|
2346
2379
|
return false;
|
|
2347
2380
|
return value.questions.every(isHumanQuestion);
|
|
2348
2381
|
}
|
|
2382
|
+
function isAnswerToHumanItem(value) {
|
|
2383
|
+
if (!isRecord(value))
|
|
2384
|
+
return false;
|
|
2385
|
+
if (typeof value.id !== 'string')
|
|
2386
|
+
return false;
|
|
2387
|
+
if (typeof value.content !== 'string')
|
|
2388
|
+
return false;
|
|
2389
|
+
if (typeof value.answeredAt !== 'string')
|
|
2390
|
+
return false;
|
|
2391
|
+
if (!isRecord(value.userInterjection))
|
|
2392
|
+
return false;
|
|
2393
|
+
if (typeof value.userInterjection.msgId !== 'string')
|
|
2394
|
+
return false;
|
|
2395
|
+
if (typeof value.userInterjection.course !== 'number')
|
|
2396
|
+
return false;
|
|
2397
|
+
if (!Number.isFinite(value.userInterjection.course))
|
|
2398
|
+
return false;
|
|
2399
|
+
if (typeof value.userInterjection.genseq !== 'number')
|
|
2400
|
+
return false;
|
|
2401
|
+
if (!Number.isFinite(value.userInterjection.genseq))
|
|
2402
|
+
return false;
|
|
2403
|
+
if (!isRecord(value.answerRef))
|
|
2404
|
+
return false;
|
|
2405
|
+
if (typeof value.answerRef.course !== 'number')
|
|
2406
|
+
return false;
|
|
2407
|
+
if (!Number.isFinite(value.answerRef.course))
|
|
2408
|
+
return false;
|
|
2409
|
+
if (typeof value.answerRef.genseq !== 'number')
|
|
2410
|
+
return false;
|
|
2411
|
+
if (!Number.isFinite(value.answerRef.genseq))
|
|
2412
|
+
return false;
|
|
2413
|
+
return true;
|
|
2414
|
+
}
|
|
2415
|
+
function isAnswersToHumanFile(value) {
|
|
2416
|
+
if (!isRecord(value))
|
|
2417
|
+
return false;
|
|
2418
|
+
if (!Array.isArray(value.answers))
|
|
2419
|
+
return false;
|
|
2420
|
+
if (typeof value.updatedAt !== 'string')
|
|
2421
|
+
return false;
|
|
2422
|
+
return value.answers.every(isAnswerToHumanItem);
|
|
2423
|
+
}
|
|
2349
2424
|
// Remove old type definitions - now using kernel/types/storage.ts
|
|
2350
2425
|
const id_1 = require("./utils/id");
|
|
2351
2426
|
function parseReplayTellaskCall(record) {
|
|
@@ -2760,7 +2835,8 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
2760
2835
|
* Append event to course JSONL file (delegate to DialogPersistence)
|
|
2761
2836
|
*/
|
|
2762
2837
|
async appendEvent(dialog, course, event) {
|
|
2763
|
-
|
|
2838
|
+
const rootedEvent = attachRootGenerationRef(dialog, event);
|
|
2839
|
+
await DialogPersistence.appendEvent(this.dialogId, course, rootedEvent);
|
|
2764
2840
|
}
|
|
2765
2841
|
async appendEvents(dialog, course, events) {
|
|
2766
2842
|
await DialogPersistence.appendEvents(this.dialogId, course, events.map((event) => attachRootGenerationRef(dialog, event)));
|
|
@@ -2779,6 +2855,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
2779
2855
|
ts: startedAt,
|
|
2780
2856
|
type: 'gen_start_record',
|
|
2781
2857
|
genseq: genseq,
|
|
2858
|
+
...(typeof msgId === 'string' && msgId.trim() !== '' ? { msgId } : {}),
|
|
2782
2859
|
};
|
|
2783
2860
|
await this.appendEvent(dialog, course, ev);
|
|
2784
2861
|
// Emit generating_start_evt event
|
|
@@ -4920,6 +4997,14 @@ class DialogPersistence {
|
|
|
4920
4997
|
this.q4hWriteBackMutexes.set(key, created);
|
|
4921
4998
|
return created;
|
|
4922
4999
|
}
|
|
5000
|
+
static getA2HWriteBackMutex(key) {
|
|
5001
|
+
const existing = this.a2hWriteBackMutexes.get(key);
|
|
5002
|
+
if (existing)
|
|
5003
|
+
return existing;
|
|
5004
|
+
const created = new async_fifo_mutex_1.AsyncFifoMutex();
|
|
5005
|
+
this.a2hWriteBackMutexes.set(key, created);
|
|
5006
|
+
return created;
|
|
5007
|
+
}
|
|
4923
5008
|
static getCourseAppendMutex(key) {
|
|
4924
5009
|
const existing = this.courseAppendMutexes.get(key);
|
|
4925
5010
|
if (existing)
|
|
@@ -4969,6 +5054,10 @@ class DialogPersistence {
|
|
|
4969
5054
|
// Include dialogs root dir to avoid cross-test/process.cwd collisions.
|
|
4970
5055
|
return `${this.getDialogsRootDir()}|${status}|${dialogId.valueOf()}|q4h`;
|
|
4971
5056
|
}
|
|
5057
|
+
static getA2HWriteBackKey(dialogId, status) {
|
|
5058
|
+
// Include dialogs root dir to avoid cross-test/process.cwd collisions.
|
|
5059
|
+
return `${this.getDialogsRootDir()}|${status}|${dialogId.valueOf()}|a2h`;
|
|
5060
|
+
}
|
|
4972
5061
|
static getActiveCalleesKey(dialogId, status) {
|
|
4973
5062
|
return `${this.getDialogsRootDir()}|${status}|${dialogId.valueOf()}|active-callees`;
|
|
4974
5063
|
}
|
|
@@ -5281,6 +5370,19 @@ class DialogPersistence {
|
|
|
5281
5370
|
this.q4hWriteBackMutexes.delete(key);
|
|
5282
5371
|
}
|
|
5283
5372
|
}
|
|
5373
|
+
for (const [key, entry] of this.a2hWriteBack.entries()) {
|
|
5374
|
+
if (!matchesMainDialogKey(key))
|
|
5375
|
+
continue;
|
|
5376
|
+
if (entry.kind === 'scheduled') {
|
|
5377
|
+
clearTimeout(entry.timer);
|
|
5378
|
+
}
|
|
5379
|
+
this.a2hWriteBack.delete(key);
|
|
5380
|
+
}
|
|
5381
|
+
for (const key of this.a2hWriteBackMutexes.keys()) {
|
|
5382
|
+
if (matchesMainDialogKey(key)) {
|
|
5383
|
+
this.a2hWriteBackMutexes.delete(key);
|
|
5384
|
+
}
|
|
5385
|
+
}
|
|
5284
5386
|
for (const key of this.activeCalleesMutexes.keys()) {
|
|
5285
5387
|
if (matchesMainDialogKey(key)) {
|
|
5286
5388
|
this.activeCalleesMutexes.delete(key);
|
|
@@ -6308,6 +6410,151 @@ class DialogPersistence {
|
|
|
6308
6410
|
removedQuestion: out.removedQuestion,
|
|
6309
6411
|
};
|
|
6310
6412
|
}
|
|
6413
|
+
static async loadAnswersToHumanState(dialogId, status = 'running') {
|
|
6414
|
+
const key = this.getA2HWriteBackKey(dialogId, status);
|
|
6415
|
+
const staged = this.a2hWriteBack.get(key);
|
|
6416
|
+
if (staged) {
|
|
6417
|
+
if (staged.state.kind === 'deleted')
|
|
6418
|
+
return [];
|
|
6419
|
+
return staged.state.file.answers;
|
|
6420
|
+
}
|
|
6421
|
+
try {
|
|
6422
|
+
return await this.loadAnswersToHumanStateFromDisk(dialogId, status);
|
|
6423
|
+
}
|
|
6424
|
+
catch (error) {
|
|
6425
|
+
await this.rethrowAfterQuarantiningDialogPersistenceProblem(dialogId, status, 'loadAnswersToHumanState', error);
|
|
6426
|
+
throw new Error('unreachable after loadAnswersToHumanState persistence rethrow');
|
|
6427
|
+
}
|
|
6428
|
+
}
|
|
6429
|
+
static async loadAnswersToHumanStateFromDisk(dialogId, status) {
|
|
6430
|
+
const dialogPath = this.getDialogEventsPath(dialogId, status);
|
|
6431
|
+
const answersFilePath = path.join(dialogPath, 'a2h.yaml');
|
|
6432
|
+
try {
|
|
6433
|
+
const content = await readPersistenceTextFile({
|
|
6434
|
+
filePath: answersFilePath,
|
|
6435
|
+
source: 'answers2human_state',
|
|
6436
|
+
format: 'yaml',
|
|
6437
|
+
});
|
|
6438
|
+
const parsed = parsePersistenceYaml({
|
|
6439
|
+
content,
|
|
6440
|
+
filePath: answersFilePath,
|
|
6441
|
+
source: 'answers2human_state',
|
|
6442
|
+
});
|
|
6443
|
+
if (!isAnswersToHumanFile(parsed)) {
|
|
6444
|
+
throw buildInvalidPersistenceFileError({
|
|
6445
|
+
source: 'answers2human_state',
|
|
6446
|
+
format: 'yaml',
|
|
6447
|
+
filePath: answersFilePath,
|
|
6448
|
+
});
|
|
6449
|
+
}
|
|
6450
|
+
return parsed.answers;
|
|
6451
|
+
}
|
|
6452
|
+
catch (error) {
|
|
6453
|
+
if (getErrorCode(error) === 'ENOENT')
|
|
6454
|
+
return [];
|
|
6455
|
+
throw error;
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
static async mutateAnswersToHumanState(dialogId, mutator, status = 'running') {
|
|
6459
|
+
const key = this.getA2HWriteBackKey(dialogId, status);
|
|
6460
|
+
const mutex = this.getA2HWriteBackMutex(key);
|
|
6461
|
+
const release = await mutex.acquire();
|
|
6462
|
+
try {
|
|
6463
|
+
const staged = this.a2hWriteBack.get(key);
|
|
6464
|
+
const previousAnswers = staged && staged.state.kind === 'file'
|
|
6465
|
+
? staged.state.file.answers
|
|
6466
|
+
: staged && staged.state.kind === 'deleted'
|
|
6467
|
+
? []
|
|
6468
|
+
: await this.loadAnswersToHumanStateFromDisk(dialogId, status);
|
|
6469
|
+
const mutation = mutator(previousAnswers);
|
|
6470
|
+
let removedAnswer;
|
|
6471
|
+
let nextState;
|
|
6472
|
+
let nextAnswers = previousAnswers;
|
|
6473
|
+
if (mutation.kind === 'noop') {
|
|
6474
|
+
return { previousAnswers, answers: previousAnswers };
|
|
6475
|
+
}
|
|
6476
|
+
else if (mutation.kind === 'append') {
|
|
6477
|
+
nextAnswers = [...previousAnswers, mutation.answer];
|
|
6478
|
+
}
|
|
6479
|
+
else if (mutation.kind === 'remove') {
|
|
6480
|
+
const idx = previousAnswers.findIndex((answer) => answer.id === mutation.answerId);
|
|
6481
|
+
if (idx === -1) {
|
|
6482
|
+
return { previousAnswers, answers: previousAnswers };
|
|
6483
|
+
}
|
|
6484
|
+
removedAnswer = previousAnswers[idx];
|
|
6485
|
+
nextAnswers = previousAnswers.filter((answer) => answer.id !== mutation.answerId);
|
|
6486
|
+
}
|
|
6487
|
+
else if (mutation.kind === 'replace') {
|
|
6488
|
+
nextAnswers = [...mutation.answers];
|
|
6489
|
+
}
|
|
6490
|
+
else if (mutation.kind === 'clear') {
|
|
6491
|
+
nextAnswers = [];
|
|
6492
|
+
}
|
|
6493
|
+
else {
|
|
6494
|
+
const _exhaustive = mutation;
|
|
6495
|
+
throw new Error(`Unhandled a2h mutation: ${String(_exhaustive)}`);
|
|
6496
|
+
}
|
|
6497
|
+
if (nextAnswers.length === 0) {
|
|
6498
|
+
nextState = { kind: 'deleted' };
|
|
6499
|
+
}
|
|
6500
|
+
else {
|
|
6501
|
+
nextState = {
|
|
6502
|
+
kind: 'file',
|
|
6503
|
+
file: { answers: nextAnswers, updatedAt: (0, time_1.formatUnifiedTimestamp)(new Date()) },
|
|
6504
|
+
};
|
|
6505
|
+
}
|
|
6506
|
+
const pending = this.a2hWriteBack.get(key);
|
|
6507
|
+
if (!pending) {
|
|
6508
|
+
const timer = setTimeout(() => {
|
|
6509
|
+
void this.flushA2HWriteBack(key);
|
|
6510
|
+
}, this.A2H_WRITEBACK_WINDOW_MS);
|
|
6511
|
+
this.a2hWriteBack.set(key, {
|
|
6512
|
+
kind: 'scheduled',
|
|
6513
|
+
dialogId,
|
|
6514
|
+
status,
|
|
6515
|
+
state: nextState,
|
|
6516
|
+
timer,
|
|
6517
|
+
});
|
|
6518
|
+
return { previousAnswers, answers: nextAnswers, removedAnswer };
|
|
6519
|
+
}
|
|
6520
|
+
pending.state = nextState;
|
|
6521
|
+
if (pending.kind === 'flushing') {
|
|
6522
|
+
pending.dirty = true;
|
|
6523
|
+
}
|
|
6524
|
+
return { previousAnswers, answers: nextAnswers, removedAnswer };
|
|
6525
|
+
}
|
|
6526
|
+
finally {
|
|
6527
|
+
release();
|
|
6528
|
+
}
|
|
6529
|
+
}
|
|
6530
|
+
static async appendAnswerToHumanState(dialogId, answer, status = 'running') {
|
|
6531
|
+
const answerId = answer.id.trim();
|
|
6532
|
+
if (answerId === '') {
|
|
6533
|
+
throw new Error(`A2H append invariant violation: empty answer id (dialog=${dialogId.valueOf()})`);
|
|
6534
|
+
}
|
|
6535
|
+
if (answer.content.trim() === '') {
|
|
6536
|
+
throw new Error(`A2H append invariant violation: empty answer content (dialog=${dialogId.valueOf()} answerId=${answer.id})`);
|
|
6537
|
+
}
|
|
6538
|
+
await this.mutateAnswersToHumanState(dialogId, (previousAnswers) => {
|
|
6539
|
+
const existing = previousAnswers.find((item) => item.id === answer.id);
|
|
6540
|
+
if (existing) {
|
|
6541
|
+
throw new Error(`A2H duplicate answer id violation: dialog=${dialogId.valueOf()} status=${status} answerId=${answer.id} existingAnsweredAt=${existing.answeredAt} incomingAnsweredAt=${answer.answeredAt}`);
|
|
6542
|
+
}
|
|
6543
|
+
return { kind: 'append', answer };
|
|
6544
|
+
}, status);
|
|
6545
|
+
await this.flushA2HWriteBack(this.getA2HWriteBackKey(dialogId, status));
|
|
6546
|
+
}
|
|
6547
|
+
static async acknowledgeAnswerToHumanState(dialogId, answerId, status = 'running') {
|
|
6548
|
+
const out = await this.mutateAnswersToHumanState(dialogId, () => ({ kind: 'remove', answerId }), status);
|
|
6549
|
+
if (out.removedAnswer !== undefined) {
|
|
6550
|
+
await this.flushA2HWriteBack(this.getA2HWriteBackKey(dialogId, status));
|
|
6551
|
+
}
|
|
6552
|
+
return {
|
|
6553
|
+
found: typeof out.removedAnswer !== 'undefined',
|
|
6554
|
+
remainingAnswers: out.answers,
|
|
6555
|
+
removedAnswer: out.removedAnswer,
|
|
6556
|
+
};
|
|
6557
|
+
}
|
|
6311
6558
|
static async flushQ4HWriteBack(key) {
|
|
6312
6559
|
const mutex = this.getQ4HWriteBackMutex(key);
|
|
6313
6560
|
let captured;
|
|
@@ -6427,6 +6674,125 @@ class DialogPersistence {
|
|
|
6427
6674
|
}
|
|
6428
6675
|
await this.renameWithRetry(tempFile, questionsFilePath, 5, cancellationToken);
|
|
6429
6676
|
}
|
|
6677
|
+
static async flushA2HWriteBack(key) {
|
|
6678
|
+
const mutex = this.getA2HWriteBackMutex(key);
|
|
6679
|
+
let captured;
|
|
6680
|
+
{
|
|
6681
|
+
const release = await mutex.acquire();
|
|
6682
|
+
try {
|
|
6683
|
+
const entry = this.a2hWriteBack.get(key);
|
|
6684
|
+
if (!entry)
|
|
6685
|
+
return;
|
|
6686
|
+
if (entry.kind === 'flushing')
|
|
6687
|
+
return;
|
|
6688
|
+
if (entry.kind !== 'scheduled')
|
|
6689
|
+
return;
|
|
6690
|
+
clearTimeout(entry.timer);
|
|
6691
|
+
const cancellationToken = this.createMainDialogWriteBackCancellationToken(entry.dialogId, entry.status);
|
|
6692
|
+
const inFlight = this.writeA2HStateToDisk(entry.dialogId, entry.state, entry.status, cancellationToken);
|
|
6693
|
+
captured = {
|
|
6694
|
+
dialogId: entry.dialogId,
|
|
6695
|
+
status: entry.status,
|
|
6696
|
+
stateToWrite: entry.state,
|
|
6697
|
+
inFlight,
|
|
6698
|
+
};
|
|
6699
|
+
this.a2hWriteBack.set(key, {
|
|
6700
|
+
kind: 'flushing',
|
|
6701
|
+
dialogId: entry.dialogId,
|
|
6702
|
+
status: entry.status,
|
|
6703
|
+
state: entry.state,
|
|
6704
|
+
dirty: false,
|
|
6705
|
+
inFlight,
|
|
6706
|
+
});
|
|
6707
|
+
}
|
|
6708
|
+
finally {
|
|
6709
|
+
release();
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
6712
|
+
if (!captured)
|
|
6713
|
+
return;
|
|
6714
|
+
try {
|
|
6715
|
+
await captured.inFlight;
|
|
6716
|
+
}
|
|
6717
|
+
catch (error) {
|
|
6718
|
+
const release = await mutex.acquire();
|
|
6719
|
+
try {
|
|
6720
|
+
const entry = this.a2hWriteBack.get(key);
|
|
6721
|
+
if (!entry)
|
|
6722
|
+
return;
|
|
6723
|
+
if (entry.kind !== 'flushing')
|
|
6724
|
+
return;
|
|
6725
|
+
if (entry.inFlight !== captured.inFlight)
|
|
6726
|
+
return;
|
|
6727
|
+
if (isDialogWriteBackCanceledError(error)) {
|
|
6728
|
+
this.a2hWriteBack.delete(key);
|
|
6729
|
+
return;
|
|
6730
|
+
}
|
|
6731
|
+
const timer = setTimeout(() => {
|
|
6732
|
+
void this.flushA2HWriteBack(key);
|
|
6733
|
+
}, this.A2H_WRITEBACK_WINDOW_MS);
|
|
6734
|
+
this.a2hWriteBack.set(key, {
|
|
6735
|
+
kind: 'scheduled',
|
|
6736
|
+
dialogId: entry.dialogId,
|
|
6737
|
+
status: entry.status,
|
|
6738
|
+
state: entry.state,
|
|
6739
|
+
timer,
|
|
6740
|
+
});
|
|
6741
|
+
}
|
|
6742
|
+
finally {
|
|
6743
|
+
release();
|
|
6744
|
+
}
|
|
6745
|
+
return;
|
|
6746
|
+
}
|
|
6747
|
+
const release = await mutex.acquire();
|
|
6748
|
+
try {
|
|
6749
|
+
const entry = this.a2hWriteBack.get(key);
|
|
6750
|
+
if (!entry)
|
|
6751
|
+
return;
|
|
6752
|
+
if (entry.kind !== 'flushing')
|
|
6753
|
+
return;
|
|
6754
|
+
if (entry.inFlight !== captured.inFlight)
|
|
6755
|
+
return;
|
|
6756
|
+
if (!entry.dirty) {
|
|
6757
|
+
this.a2hWriteBack.delete(key);
|
|
6758
|
+
return;
|
|
6759
|
+
}
|
|
6760
|
+
const timer = setTimeout(() => {
|
|
6761
|
+
void this.flushA2HWriteBack(key);
|
|
6762
|
+
}, this.A2H_WRITEBACK_WINDOW_MS);
|
|
6763
|
+
this.a2hWriteBack.set(key, {
|
|
6764
|
+
kind: 'scheduled',
|
|
6765
|
+
dialogId: entry.dialogId,
|
|
6766
|
+
status: entry.status,
|
|
6767
|
+
state: entry.state,
|
|
6768
|
+
timer,
|
|
6769
|
+
});
|
|
6770
|
+
}
|
|
6771
|
+
finally {
|
|
6772
|
+
release();
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
static async writeA2HStateToDisk(dialogId, state, status, cancellationToken) {
|
|
6776
|
+
if (cancellationToken) {
|
|
6777
|
+
this.assertMainDialogWriteBackNotCanceled(cancellationToken, 'writeA2HStateToDisk:start');
|
|
6778
|
+
}
|
|
6779
|
+
const dialogPath = this.getDialogEventsPath(dialogId, status);
|
|
6780
|
+
const answersFilePath = path.join(dialogPath, 'a2h.yaml');
|
|
6781
|
+
if (state.kind === 'deleted') {
|
|
6782
|
+
await fs.promises.rm(answersFilePath, { force: true });
|
|
6783
|
+
return;
|
|
6784
|
+
}
|
|
6785
|
+
const yamlContent = yaml.stringify(state.file);
|
|
6786
|
+
const tempFile = path.join(dialogPath, `.${path.basename(answersFilePath)}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`);
|
|
6787
|
+
try {
|
|
6788
|
+
await fs.promises.writeFile(tempFile, yamlContent, 'utf-8');
|
|
6789
|
+
}
|
|
6790
|
+
catch (error) {
|
|
6791
|
+
await this.rethrowWriteBackPathMissingAsCanceled(error, dialogPath, cancellationToken, 'writeA2HStateToDisk:write-temp');
|
|
6792
|
+
throw error;
|
|
6793
|
+
}
|
|
6794
|
+
await this.renameWithRetry(tempFile, answersFilePath, 5, cancellationToken);
|
|
6795
|
+
}
|
|
6430
6796
|
/**
|
|
6431
6797
|
* Load all Q4H questions from all running dialogs (for global Q4H display)
|
|
6432
6798
|
* Returns array of questions with their dialog context for frontend display
|
|
@@ -6466,6 +6832,47 @@ class DialogPersistence {
|
|
|
6466
6832
|
return [];
|
|
6467
6833
|
}
|
|
6468
6834
|
}
|
|
6835
|
+
static async loadAllA2HState() {
|
|
6836
|
+
try {
|
|
6837
|
+
const dialogIds = await this.listAllDialogIds('running');
|
|
6838
|
+
const allAnswers = [];
|
|
6839
|
+
for (const dialogIdObj of dialogIds) {
|
|
6840
|
+
try {
|
|
6841
|
+
const answers = await this.loadAnswersToHumanState(dialogIdObj, 'running');
|
|
6842
|
+
if (answers.length === 0) {
|
|
6843
|
+
continue;
|
|
6844
|
+
}
|
|
6845
|
+
const metadata = await this.loadDialogMetadata(dialogIdObj, 'running');
|
|
6846
|
+
if (!metadata) {
|
|
6847
|
+
continue;
|
|
6848
|
+
}
|
|
6849
|
+
for (const answer of answers) {
|
|
6850
|
+
allAnswers.push({
|
|
6851
|
+
...answer,
|
|
6852
|
+
selfId: dialogIdObj.selfId,
|
|
6853
|
+
rootId: dialogIdObj.rootId,
|
|
6854
|
+
agentId: metadata.agentId,
|
|
6855
|
+
taskDocPath: metadata.taskDocPath,
|
|
6856
|
+
});
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
catch (err) {
|
|
6860
|
+
log_1.log.warn(`Failed to load A2H for dialog ${dialogIdObj.valueOf()}:`, err);
|
|
6861
|
+
}
|
|
6862
|
+
}
|
|
6863
|
+
return allAnswers.sort((a, b) => {
|
|
6864
|
+
const ta = new Date(a.answeredAt).getTime();
|
|
6865
|
+
const tb = new Date(b.answeredAt).getTime();
|
|
6866
|
+
if (Number.isFinite(ta) && Number.isFinite(tb))
|
|
6867
|
+
return tb - ta;
|
|
6868
|
+
return b.answeredAt.localeCompare(a.answeredAt);
|
|
6869
|
+
});
|
|
6870
|
+
}
|
|
6871
|
+
catch (error) {
|
|
6872
|
+
log_1.log.error('Failed to load all A2H state:', error);
|
|
6873
|
+
return [];
|
|
6874
|
+
}
|
|
6875
|
+
}
|
|
6469
6876
|
static async clearQuestions4HumanState(dialogId, status = 'running') {
|
|
6470
6877
|
try {
|
|
6471
6878
|
const { previousQuestions } = await this.mutateQuestions4HumanState(dialogId, () => ({ kind: 'clear' }), status);
|
|
@@ -7126,6 +7533,9 @@ class DialogPersistence {
|
|
|
7126
7533
|
displayState: latest.displayState ?? null,
|
|
7127
7534
|
executionMarker: latest.executionMarker ?? null,
|
|
7128
7535
|
nextStepTriggers,
|
|
7536
|
+
pendingUserInterjectionReplyMsgId: latest.pendingUserInterjectionReply?.msgId ?? null,
|
|
7537
|
+
pendingUserInterjectionReplyCourse: latest.pendingUserInterjectionReply?.course ?? null,
|
|
7538
|
+
pendingUserInterjectionReplyGenseq: latest.pendingUserInterjectionReply?.genseq ?? null,
|
|
7129
7539
|
pendingRuntimePromptMsgId: latest.pendingRuntimePrompt?.msgId ?? null,
|
|
7130
7540
|
generationRunState: latest.generationRunState ?? null,
|
|
7131
7541
|
replyDelivery: latest.replyDelivery ?? null,
|
|
@@ -8260,7 +8670,7 @@ class DialogPersistence {
|
|
|
8260
8670
|
const key = this.getLatestWriteBackKey(dialogId, status);
|
|
8261
8671
|
const staged = this.latestWriteBack.get(key);
|
|
8262
8672
|
if (staged) {
|
|
8263
|
-
return staged.latest;
|
|
8673
|
+
return await this.normalizeDialogLatestPendingUserInterjectionReply(dialogId, status, staged.latest);
|
|
8264
8674
|
}
|
|
8265
8675
|
const dialogPath = this.getDialogEventsPath(dialogId, status);
|
|
8266
8676
|
const latestFilePath = path.join(dialogPath, 'latest.yaml');
|
|
@@ -8269,7 +8679,10 @@ class DialogPersistence {
|
|
|
8269
8679
|
source: 'dialog_latest',
|
|
8270
8680
|
format: 'yaml',
|
|
8271
8681
|
});
|
|
8272
|
-
|
|
8682
|
+
const parsed = this.parseDialogLatestYaml(content, latestFilePath);
|
|
8683
|
+
return parsed === null
|
|
8684
|
+
? null
|
|
8685
|
+
: await this.normalizeDialogLatestPendingUserInterjectionReply(dialogId, status, parsed);
|
|
8273
8686
|
}
|
|
8274
8687
|
catch (error) {
|
|
8275
8688
|
if (getErrorCode(error) === 'ENOENT') {
|
|
@@ -8393,7 +8806,10 @@ class DialogPersistence {
|
|
|
8393
8806
|
source: 'dialog_latest',
|
|
8394
8807
|
format: 'yaml',
|
|
8395
8808
|
});
|
|
8396
|
-
|
|
8809
|
+
const parsed = this.parseDialogLatestYaml(content, latestFilePath);
|
|
8810
|
+
return parsed === null
|
|
8811
|
+
? null
|
|
8812
|
+
: await this.normalizeDialogLatestPendingUserInterjectionReply(dialogId, status, parsed);
|
|
8397
8813
|
}
|
|
8398
8814
|
catch (error) {
|
|
8399
8815
|
if (getErrorCode(error) === 'ENOENT') {
|
|
@@ -8735,6 +9151,132 @@ class DialogPersistence {
|
|
|
8735
9151
|
static async loadCourseEvents(dialogId, course, status = 'running') {
|
|
8736
9152
|
return await this.readCourseEvents(dialogId, course, status);
|
|
8737
9153
|
}
|
|
9154
|
+
static resolvePendingUserInterjectionReplyFromCourseEvents(events, course) {
|
|
9155
|
+
let pendingUserInterjectionReply;
|
|
9156
|
+
let visibleReplySettled = false;
|
|
9157
|
+
for (const event of events) {
|
|
9158
|
+
if (event.type === 'human_text_record') {
|
|
9159
|
+
if (event.origin !== 'user')
|
|
9160
|
+
continue;
|
|
9161
|
+
if (typeof event.q4hAnswerCallId === 'string' && event.q4hAnswerCallId.trim() !== '') {
|
|
9162
|
+
continue;
|
|
9163
|
+
}
|
|
9164
|
+
pendingUserInterjectionReply = {
|
|
9165
|
+
msgId: event.msgId,
|
|
9166
|
+
course: (0, storage_1.toDialogCourseNumber)(course),
|
|
9167
|
+
genseq: (0, storage_1.toCallSiteGenseqNo)(event.genseq),
|
|
9168
|
+
};
|
|
9169
|
+
visibleReplySettled = false;
|
|
9170
|
+
continue;
|
|
9171
|
+
}
|
|
9172
|
+
if (pendingUserInterjectionReply === undefined) {
|
|
9173
|
+
continue;
|
|
9174
|
+
}
|
|
9175
|
+
if (event.type === 'agent_words_record') {
|
|
9176
|
+
visibleReplySettled = true;
|
|
9177
|
+
continue;
|
|
9178
|
+
}
|
|
9179
|
+
if (event.type === 'func_call_record' || event.type === 'tellask_call_record') {
|
|
9180
|
+
visibleReplySettled = false;
|
|
9181
|
+
}
|
|
9182
|
+
}
|
|
9183
|
+
return visibleReplySettled ? undefined : pendingUserInterjectionReply;
|
|
9184
|
+
}
|
|
9185
|
+
static resolveAnsweredUserInterjectionA2HFromCourseEvents(args) {
|
|
9186
|
+
let pendingUserInterjectionReply;
|
|
9187
|
+
let lastVisibleAnswer;
|
|
9188
|
+
let visibleReplySettled = false;
|
|
9189
|
+
for (const event of args.events) {
|
|
9190
|
+
if (event.type === 'human_text_record') {
|
|
9191
|
+
if (event.origin !== 'user')
|
|
9192
|
+
continue;
|
|
9193
|
+
if (typeof event.q4hAnswerCallId === 'string' && event.q4hAnswerCallId.trim() !== '') {
|
|
9194
|
+
continue;
|
|
9195
|
+
}
|
|
9196
|
+
pendingUserInterjectionReply = {
|
|
9197
|
+
msgId: event.msgId,
|
|
9198
|
+
course: (0, storage_1.toDialogCourseNumber)(args.course),
|
|
9199
|
+
genseq: (0, storage_1.toCallSiteGenseqNo)(event.genseq),
|
|
9200
|
+
};
|
|
9201
|
+
visibleReplySettled = false;
|
|
9202
|
+
lastVisibleAnswer = undefined;
|
|
9203
|
+
continue;
|
|
9204
|
+
}
|
|
9205
|
+
if (pendingUserInterjectionReply === undefined) {
|
|
9206
|
+
continue;
|
|
9207
|
+
}
|
|
9208
|
+
if (event.type === 'agent_words_record') {
|
|
9209
|
+
visibleReplySettled = true;
|
|
9210
|
+
lastVisibleAnswer = { content: event.content, genseq: event.genseq };
|
|
9211
|
+
continue;
|
|
9212
|
+
}
|
|
9213
|
+
if (event.type === 'func_call_record' || event.type === 'tellask_call_record') {
|
|
9214
|
+
visibleReplySettled = false;
|
|
9215
|
+
lastVisibleAnswer = undefined;
|
|
9216
|
+
}
|
|
9217
|
+
}
|
|
9218
|
+
if (!visibleReplySettled || pendingUserInterjectionReply === undefined || !lastVisibleAnswer) {
|
|
9219
|
+
return undefined;
|
|
9220
|
+
}
|
|
9221
|
+
if (pendingUserInterjectionReply.msgId !== args.pending?.msgId) {
|
|
9222
|
+
return undefined;
|
|
9223
|
+
}
|
|
9224
|
+
const answerIdSource = [
|
|
9225
|
+
args.dialogId.rootId,
|
|
9226
|
+
args.dialogId.selfId,
|
|
9227
|
+
`c${String(args.course)}`,
|
|
9228
|
+
`g${String(lastVisibleAnswer.genseq)}`,
|
|
9229
|
+
pendingUserInterjectionReply.msgId,
|
|
9230
|
+
].join('|');
|
|
9231
|
+
return {
|
|
9232
|
+
id: `a2h-${Buffer.from(answerIdSource).toString('base64url')}`,
|
|
9233
|
+
content: lastVisibleAnswer.content,
|
|
9234
|
+
answeredAt: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
9235
|
+
userInterjection: {
|
|
9236
|
+
msgId: pendingUserInterjectionReply.msgId,
|
|
9237
|
+
course: pendingUserInterjectionReply.course,
|
|
9238
|
+
genseq: pendingUserInterjectionReply.genseq,
|
|
9239
|
+
},
|
|
9240
|
+
answerRef: {
|
|
9241
|
+
course: (0, storage_1.toDialogCourseNumber)(args.course),
|
|
9242
|
+
genseq: (0, storage_1.toCallSiteGenseqNo)(lastVisibleAnswer.genseq),
|
|
9243
|
+
},
|
|
9244
|
+
};
|
|
9245
|
+
}
|
|
9246
|
+
static async normalizeDialogLatestPendingUserInterjectionReply(dialogId, status, latest) {
|
|
9247
|
+
if (latest.pendingUserInterjectionReply === undefined) {
|
|
9248
|
+
return latest;
|
|
9249
|
+
}
|
|
9250
|
+
const events = await this.readCourseEvents(dialogId, latest.currentCourse, status);
|
|
9251
|
+
const normalizedPending = this.resolvePendingUserInterjectionReplyFromCourseEvents(events, latest.currentCourse);
|
|
9252
|
+
if (normalizedPending === undefined) {
|
|
9253
|
+
const recoveredAnswer = this.resolveAnsweredUserInterjectionA2HFromCourseEvents({
|
|
9254
|
+
dialogId,
|
|
9255
|
+
events,
|
|
9256
|
+
course: latest.currentCourse,
|
|
9257
|
+
pending: latest.pendingUserInterjectionReply,
|
|
9258
|
+
});
|
|
9259
|
+
if (recoveredAnswer !== undefined) {
|
|
9260
|
+
const existingAnswers = await this.loadAnswersToHumanState(dialogId, status);
|
|
9261
|
+
if (!existingAnswers.some((item) => item.id === recoveredAnswer.id)) {
|
|
9262
|
+
await this.appendAnswerToHumanState(dialogId, recoveredAnswer, status);
|
|
9263
|
+
}
|
|
9264
|
+
return {
|
|
9265
|
+
...latest,
|
|
9266
|
+
pendingUserInterjectionReply: undefined,
|
|
9267
|
+
};
|
|
9268
|
+
}
|
|
9269
|
+
}
|
|
9270
|
+
if (normalizedPending?.msgId === latest.pendingUserInterjectionReply.msgId &&
|
|
9271
|
+
normalizedPending?.course === latest.pendingUserInterjectionReply.course &&
|
|
9272
|
+
normalizedPending?.genseq === latest.pendingUserInterjectionReply.genseq) {
|
|
9273
|
+
return latest;
|
|
9274
|
+
}
|
|
9275
|
+
return {
|
|
9276
|
+
...latest,
|
|
9277
|
+
pendingUserInterjectionReply: normalizedPending,
|
|
9278
|
+
};
|
|
9279
|
+
}
|
|
8738
9280
|
/**
|
|
8739
9281
|
* Reconstruct dialog state from JSONL events (optimized: only latest course needed).
|
|
8740
9282
|
*/
|
|
@@ -9094,10 +9636,13 @@ DialogPersistence.SIDE_DIALOGS_DIR = 'sideDialogs';
|
|
|
9094
9636
|
DialogPersistence.quarantinedMainDialogScopes = new Set();
|
|
9095
9637
|
DialogPersistence.LATEST_WRITEBACK_WINDOW_MS = 300;
|
|
9096
9638
|
DialogPersistence.Q4H_WRITEBACK_WINDOW_MS = 300;
|
|
9639
|
+
DialogPersistence.A2H_WRITEBACK_WINDOW_MS = 300;
|
|
9097
9640
|
DialogPersistence.latestWriteBackMutexes = new Map();
|
|
9098
9641
|
DialogPersistence.latestWriteBack = new Map();
|
|
9099
9642
|
DialogPersistence.q4hWriteBackMutexes = new Map();
|
|
9100
9643
|
DialogPersistence.q4hWriteBack = new Map();
|
|
9644
|
+
DialogPersistence.a2hWriteBackMutexes = new Map();
|
|
9645
|
+
DialogPersistence.a2hWriteBack = new Map();
|
|
9101
9646
|
DialogPersistence.activeCalleesMutexes = new Map();
|
|
9102
9647
|
DialogPersistence.wakeQueueMutexes = new Map();
|
|
9103
9648
|
DialogPersistence.backendDriveStallMutexes = new Map();
|