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.
Files changed (173) hide show
  1. package/dist/cli/tui.js +2 -0
  2. package/dist/cli/webui.js +2 -0
  3. package/dist/cli.js +2 -0
  4. package/dist/dialog-display-state.js +6 -7
  5. package/dist/docs/dialog-system.md +15 -29
  6. package/dist/docs/dialog-system.zh.md +15 -29
  7. package/dist/evt-registry.js +2 -0
  8. package/dist/llm/kernel-driver/drive.js +137 -7
  9. package/dist/llm/kernel-driver/flow.js +46 -20
  10. package/dist/llm/kernel-driver/reply-guidance.js +5 -5
  11. package/dist/persistence-errors.d.ts +1 -1
  12. package/dist/persistence.d.ts +50 -1
  13. package/dist/persistence.js +549 -4
  14. package/dist/process-title.d.ts +2 -0
  15. package/dist/process-title.js +13 -0
  16. package/dist/runtime/driver-messages.d.ts +7 -1
  17. package/dist/runtime/driver-messages.js +33 -11
  18. package/dist/runtime/interjection-pause-stop.js +8 -7
  19. package/dist/server/api-routes.js +14 -0
  20. package/dist/server/dominds-self-update.d.ts +1 -0
  21. package/dist/server/dominds-self-update.js +17 -0
  22. package/dist/server/websocket-handler.js +73 -6
  23. package/dist/tools/cmd-runner-protocol.d.ts +1 -0
  24. package/dist/tools/cmd-runner-protocol.js +6 -0
  25. package/dist/tools/cmd-runner.js +1 -0
  26. package/dist/tools/os.d.ts +2 -4
  27. package/dist/tools/os.js +79 -4
  28. package/package.json +3 -3
  29. package/webapp/dist/assets/{_basePickBy-CbWZ8qnS.js → _basePickBy-fZ31r-iF.js} +3 -3
  30. package/webapp/dist/assets/_basePickBy-fZ31r-iF.js.map +1 -0
  31. package/webapp/dist/assets/{_baseUniq-IY-Vfzx1.js → _baseUniq-CI1keLoL.js} +2 -2
  32. package/webapp/dist/assets/_baseUniq-CI1keLoL.js.map +1 -0
  33. package/webapp/dist/assets/{arc--U2Vks6y.js → arc-1NeUqzoV.js} +2 -2
  34. package/webapp/dist/assets/arc-1NeUqzoV.js.map +1 -0
  35. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-DpryGqjy.js → architectureDiagram-2XIMDMQ5-C7SdzYIh.js} +26 -8
  36. package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-C7SdzYIh.js.map +1 -0
  37. package/webapp/dist/assets/{blockDiagram-VD42YOAC-TTufCfiE.js → blockDiagram-WCTKOSBZ-Cmpu3kIy.js} +187 -170
  38. package/webapp/dist/assets/blockDiagram-WCTKOSBZ-Cmpu3kIy.js.map +1 -0
  39. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-B4RPsw5H.js → c4Diagram-IC4MRINW-ChGTHIor.js} +4 -4
  40. package/webapp/dist/assets/c4Diagram-IC4MRINW-ChGTHIor.js.map +1 -0
  41. package/webapp/dist/assets/{channel-DAtGYJHZ.js → channel-ndS-XTQQ.js} +2 -2
  42. package/webapp/dist/assets/channel-ndS-XTQQ.js.map +1 -0
  43. package/webapp/dist/assets/{chunk-4BX2VUAB-JtO__vAF.js → chunk-4BX2VUAB-Cw5FtBd_.js} +2 -2
  44. package/webapp/dist/assets/chunk-4BX2VUAB-Cw5FtBd_.js.map +1 -0
  45. package/webapp/dist/assets/{chunk-55IACEB6-JMRC8yG1.js → chunk-55IACEB6-D3G71JdA.js} +2 -2
  46. package/webapp/dist/assets/chunk-55IACEB6-D3G71JdA.js.map +1 -0
  47. package/webapp/dist/assets/{chunk-FMBD7UC4-DFXKLjHC.js → chunk-FMBD7UC4-BcugPyy7.js} +2 -2
  48. package/webapp/dist/assets/chunk-FMBD7UC4-BcugPyy7.js.map +1 -0
  49. package/webapp/dist/assets/{chunk-TZMSLE5B-BaE4C244.js → chunk-JSJVCQXG-DvuxYuNq.js} +14 -6
  50. package/webapp/dist/assets/chunk-JSJVCQXG-DvuxYuNq.js.map +1 -0
  51. package/webapp/dist/assets/{chunk-QN33PNHL-BKzkeJ-b.js → chunk-KX2RTZJC-BQ42xd4s.js} +2 -2
  52. package/webapp/dist/assets/chunk-KX2RTZJC-BQ42xd4s.js.map +1 -0
  53. package/webapp/dist/assets/{chunk-DI55MBZ5-j9B4rifK.js → chunk-NQ4KR5QH-CGEMYTch.js} +9 -7
  54. package/webapp/dist/assets/chunk-NQ4KR5QH-CGEMYTch.js.map +1 -0
  55. package/webapp/dist/assets/{chunk-QZHKN3VN-DiZd3UNl.js → chunk-QZHKN3VN-CxNTVm5w.js} +2 -2
  56. package/webapp/dist/assets/chunk-QZHKN3VN-CxNTVm5w.js.map +1 -0
  57. package/webapp/dist/assets/{chunk-B4BG7PRW-BDIpf8Iz.js → chunk-WL4C6EOR-CIwdSg5q.js} +171 -121
  58. package/webapp/dist/assets/chunk-WL4C6EOR-CIwdSg5q.js.map +1 -0
  59. package/webapp/dist/assets/{classDiagram-2ON5EDUG-CNF8ZohD.js → classDiagram-VBA2DB6C-Dl05PJAP.js} +7 -6
  60. package/webapp/dist/assets/classDiagram-VBA2DB6C-Dl05PJAP.js.map +1 -0
  61. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-CNF8ZohD.js → classDiagram-v2-RAHNMMFH-Dl05PJAP.js} +7 -6
  62. package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-Dl05PJAP.js.map +1 -0
  63. package/webapp/dist/assets/{clone-Nq0Ko0Gv.js → clone-KCj1-QMr.js} +2 -2
  64. package/webapp/dist/assets/clone-KCj1-QMr.js.map +1 -0
  65. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-uHPLSeKv.js → cose-bilkent-S5V4N54A-BttciCz5.js} +2 -2
  66. package/webapp/dist/assets/cose-bilkent-S5V4N54A-BttciCz5.js.map +1 -0
  67. package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
  68. package/webapp/dist/assets/{dagre-6UL2VRFP-C1awWpU3.js → dagre-KLK3FWXG-Dm5yE9k2.js} +7 -7
  69. package/webapp/dist/assets/dagre-KLK3FWXG-Dm5yE9k2.js.map +1 -0
  70. package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
  71. package/webapp/dist/assets/{diagram-PSM6KHXK-Bf69p76M.js → diagram-E7M64L7V-C80ZsiBG.js} +10 -10
  72. package/webapp/dist/assets/diagram-E7M64L7V-C80ZsiBG.js.map +1 -0
  73. package/webapp/dist/assets/{diagram-QEK2KX5R-Bvlbx8Jp.js → diagram-IFDJBPK2-CqKidH4n.js} +9 -8
  74. package/webapp/dist/assets/diagram-IFDJBPK2-CqKidH4n.js.map +1 -0
  75. package/webapp/dist/assets/{diagram-S2PKOQOG-CGjGalBu.js → diagram-P4PSJMXO-EHVjfzUV.js} +8 -8
  76. package/webapp/dist/assets/diagram-P4PSJMXO-EHVjfzUV.js.map +1 -0
  77. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-Ds3qhwkG.js → erDiagram-INFDFZHY-7MrtsOIt.js} +96 -75
  78. package/webapp/dist/assets/erDiagram-INFDFZHY-7MrtsOIt.js.map +1 -0
  79. package/webapp/dist/assets/{flowDiagram-NV44I4VS-B1wDG_l5.js → flowDiagram-PKNHOUZH-D6hXqCy7.js} +98 -81
  80. package/webapp/dist/assets/flowDiagram-PKNHOUZH-D6hXqCy7.js.map +1 -0
  81. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-BwuYt2bO.js → ganttDiagram-A5KZAMGK-DLO0XCDk.js} +28 -3
  82. package/webapp/dist/assets/ganttDiagram-A5KZAMGK-DLO0XCDk.js.map +1 -0
  83. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-B2Tw773z.js → gitGraphDiagram-K3NZZRJ6-BmVD_nQP.js} +38 -46
  84. package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-BmVD_nQP.js.map +1 -0
  85. package/webapp/dist/assets/graph-DQTj8O0Q.js +782 -0
  86. package/webapp/dist/assets/graph-DQTj8O0Q.js.map +1 -0
  87. package/webapp/dist/assets/{index-yycTJNYb.css → index-BQoNJEGT.css} +1 -1
  88. package/webapp/dist/assets/{index-arD81Nnh.js → index-BXjq-k48.js} +1512 -1097
  89. package/webapp/dist/assets/{index-arD81Nnh.js.map → index-BXjq-k48.js.map} +1 -1
  90. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-C9_JKYhm.js → infoDiagram-LFFYTUFH-D2fqM9Fn.js} +7 -7
  91. package/webapp/dist/assets/infoDiagram-LFFYTUFH-D2fqM9Fn.js.map +1 -0
  92. package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
  93. package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-kp7lB6-f.js +966 -0
  94. package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-kp7lB6-f.js.map +1 -0
  95. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-BhZggYOL.js → journeyDiagram-4ABVD52K-DmbA52J-.js} +5 -5
  96. package/webapp/dist/assets/journeyDiagram-4ABVD52K-DmbA52J-.js.map +1 -0
  97. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-B-R2Xm4Y.js → kanban-definition-K7BYSVSG-DRUw-P-d.js} +5 -3
  98. package/webapp/dist/assets/kanban-definition-K7BYSVSG-DRUw-P-d.js.map +1 -0
  99. package/webapp/dist/assets/{layout-BzMatxDa.js → layout-BUoHHXzn.js} +5 -5
  100. package/webapp/dist/assets/layout-BUoHHXzn.js.map +1 -0
  101. package/webapp/dist/assets/{linear-BuuJkw_U.js → linear-xVSAq8rI.js} +2 -2
  102. package/webapp/dist/assets/linear-xVSAq8rI.js.map +1 -0
  103. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-BR7oDKBR.js → mindmap-definition-YRQLILUH-BcajbGmW.js} +7 -5
  104. package/webapp/dist/assets/mindmap-definition-YRQLILUH-BcajbGmW.js.map +1 -0
  105. package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
  106. package/webapp/dist/assets/{pieDiagram-ADFJNKIX--QWeT2vZ.js → pieDiagram-SKSYHLDU-Bu8kmCW6.js} +8 -8
  107. package/webapp/dist/assets/pieDiagram-SKSYHLDU-Bu8kmCW6.js.map +1 -0
  108. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-BpqtmN3r.js → quadrantDiagram-337W2JSQ-DIBSNUGa.js} +3 -3
  109. package/webapp/dist/assets/quadrantDiagram-337W2JSQ-DIBSNUGa.js.map +1 -0
  110. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-CIXjIi4F.js → requirementDiagram-Z7DCOOCP-CkrDkbBt.js} +16 -6
  111. package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-CkrDkbBt.js.map +1 -0
  112. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-DJIt7SRz.js → sankeyDiagram-WA2Y5GQK-BZ-1R8pc.js} +2 -2
  113. package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-BZ-1R8pc.js.map +1 -0
  114. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-BpDK1ROT.js → sequenceDiagram-2WXFIKYE-DYoNARdO.js} +601 -201
  115. package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-DYoNARdO.js.map +1 -0
  116. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-BoKGfmHf.js → stateDiagram-RAJIS63D-D9v19nvh.js} +9 -9
  117. package/webapp/dist/assets/stateDiagram-RAJIS63D-D9v19nvh.js.map +1 -0
  118. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3--haXC2JK.js → stateDiagram-v2-FVOUBMTO-BYw5ZwtH.js} +5 -5
  119. package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-BYw5ZwtH.js.map +1 -0
  120. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-BmSg3Hjf.js → timeline-definition-YZTLITO2-BT10dRIJ.js} +3 -3
  121. package/webapp/dist/assets/timeline-definition-YZTLITO2-BT10dRIJ.js.map +1 -0
  122. package/webapp/dist/assets/{treemap-GDKQZRPO-D9OuyDVA.js → treemap-KZPCXAKY-yPoPC5hc.js} +37 -24
  123. package/webapp/dist/assets/treemap-KZPCXAKY-yPoPC5hc.js.map +1 -0
  124. package/webapp/dist/assets/vennDiagram-LZ73GAT5-tryg3OaY.js +2487 -0
  125. package/webapp/dist/assets/vennDiagram-LZ73GAT5-tryg3OaY.js.map +1 -0
  126. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-CVqSvO_S.js → xychartDiagram-JWTSCODW-BWLUzo9S.js} +4 -4
  127. package/webapp/dist/assets/xychartDiagram-JWTSCODW-BWLUzo9S.js.map +1 -0
  128. package/webapp/dist/index.html +2 -2
  129. package/webapp/dist/assets/_basePickBy-CbWZ8qnS.js.map +0 -1
  130. package/webapp/dist/assets/_baseUniq-IY-Vfzx1.js.map +0 -1
  131. package/webapp/dist/assets/arc--U2Vks6y.js.map +0 -1
  132. package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DpryGqjy.js.map +0 -1
  133. package/webapp/dist/assets/blockDiagram-VD42YOAC-TTufCfiE.js.map +0 -1
  134. package/webapp/dist/assets/c4Diagram-YG6GDRKO-B4RPsw5H.js.map +0 -1
  135. package/webapp/dist/assets/channel-DAtGYJHZ.js.map +0 -1
  136. package/webapp/dist/assets/chunk-4BX2VUAB-JtO__vAF.js.map +0 -1
  137. package/webapp/dist/assets/chunk-55IACEB6-JMRC8yG1.js.map +0 -1
  138. package/webapp/dist/assets/chunk-B4BG7PRW-BDIpf8Iz.js.map +0 -1
  139. package/webapp/dist/assets/chunk-DI55MBZ5-j9B4rifK.js.map +0 -1
  140. package/webapp/dist/assets/chunk-FMBD7UC4-DFXKLjHC.js.map +0 -1
  141. package/webapp/dist/assets/chunk-QN33PNHL-BKzkeJ-b.js.map +0 -1
  142. package/webapp/dist/assets/chunk-QZHKN3VN-DiZd3UNl.js.map +0 -1
  143. package/webapp/dist/assets/chunk-TZMSLE5B-BaE4C244.js.map +0 -1
  144. package/webapp/dist/assets/classDiagram-2ON5EDUG-CNF8ZohD.js.map +0 -1
  145. package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-CNF8ZohD.js.map +0 -1
  146. package/webapp/dist/assets/clone-Nq0Ko0Gv.js.map +0 -1
  147. package/webapp/dist/assets/cose-bilkent-S5V4N54A-uHPLSeKv.js.map +0 -1
  148. package/webapp/dist/assets/dagre-6UL2VRFP-C1awWpU3.js.map +0 -1
  149. package/webapp/dist/assets/diagram-PSM6KHXK-Bf69p76M.js.map +0 -1
  150. package/webapp/dist/assets/diagram-QEK2KX5R-Bvlbx8Jp.js.map +0 -1
  151. package/webapp/dist/assets/diagram-S2PKOQOG-CGjGalBu.js.map +0 -1
  152. package/webapp/dist/assets/erDiagram-Q2GNP2WA-Ds3qhwkG.js.map +0 -1
  153. package/webapp/dist/assets/flowDiagram-NV44I4VS-B1wDG_l5.js.map +0 -1
  154. package/webapp/dist/assets/ganttDiagram-JELNMOA3-BwuYt2bO.js.map +0 -1
  155. package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-B2Tw773z.js.map +0 -1
  156. package/webapp/dist/assets/graph-CS_H7jBi.js +0 -425
  157. package/webapp/dist/assets/graph-CS_H7jBi.js.map +0 -1
  158. package/webapp/dist/assets/infoDiagram-HS3SLOUP-C9_JKYhm.js.map +0 -1
  159. package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-BhZggYOL.js.map +0 -1
  160. package/webapp/dist/assets/kanban-definition-3W4ZIXB7-B-R2Xm4Y.js.map +0 -1
  161. package/webapp/dist/assets/layout-BzMatxDa.js.map +0 -1
  162. package/webapp/dist/assets/linear-BuuJkw_U.js.map +0 -1
  163. package/webapp/dist/assets/mindmap-definition-VGOIOE7T-BR7oDKBR.js.map +0 -1
  164. package/webapp/dist/assets/pieDiagram-ADFJNKIX--QWeT2vZ.js.map +0 -1
  165. package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-BpqtmN3r.js.map +0 -1
  166. package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-CIXjIi4F.js.map +0 -1
  167. package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-DJIt7SRz.js.map +0 -1
  168. package/webapp/dist/assets/sequenceDiagram-WL72ISMW-BpDK1ROT.js.map +0 -1
  169. package/webapp/dist/assets/stateDiagram-FKZM4ZOC-BoKGfmHf.js.map +0 -1
  170. package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3--haXC2JK.js.map +0 -1
  171. package/webapp/dist/assets/timeline-definition-IT6M3QCI-BmSg3Hjf.js.map +0 -1
  172. package/webapp/dist/assets/treemap-GDKQZRPO-D9OuyDVA.js.map +0 -1
  173. package/webapp/dist/assets/xychartDiagram-PRI3JC2R-CVqSvO_S.js.map +0 -1
@@ -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
- await DialogPersistence.appendEvent(this.dialogId, course, attachRootGenerationRef(dialog, event));
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
- return this.parseDialogLatestYaml(content, latestFilePath);
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
- return this.parseDialogLatestYaml(content, latestFilePath);
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();
@@ -0,0 +1,2 @@
1
+ export declare function setProcessTitle(title: string): void;
2
+ export declare function setRtwsProcessTitle(rtwsRootAbs?: string): void;