dominds 1.4.2 → 1.5.1

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 (171) hide show
  1. package/README.md +24 -0
  2. package/README.zh.md +24 -0
  3. package/dist/apps/app-json.js +38 -3
  4. package/dist/apps/dialog-run-controls.js +4 -0
  5. package/dist/apps/enabled-apps.js +8 -1
  6. package/dist/apps/installed-file.js +207 -0
  7. package/dist/apps/run-app-json.js +6 -6
  8. package/dist/apps/runtime-port.js +91 -0
  9. package/dist/apps/runtime.js +316 -68
  10. package/dist/apps-host/client.js +153 -3
  11. package/dist/apps-host/host.js +339 -2
  12. package/dist/apps-host/ipc-types.js +215 -30
  13. package/dist/cli/install.js +21 -1
  14. package/dist/dialog-fork.js +608 -0
  15. package/dist/dialog.js +2 -2
  16. package/dist/docs/app-constitution.md +153 -2
  17. package/dist/docs/app-constitution.zh.md +153 -2
  18. package/dist/docs/dialog-persistence.md +31 -0
  19. package/dist/docs/dialog-persistence.zh.md +31 -0
  20. package/dist/docs/dialog-system.md +29 -0
  21. package/dist/docs/dialog-system.zh.md +29 -0
  22. package/dist/docs/kernel-app-architecture.md +286 -0
  23. package/dist/docs/kernel-app-architecture.zh.md +285 -0
  24. package/dist/llm/defaults.yaml +16 -0
  25. package/dist/llm/driver-entry.js +28 -0
  26. package/dist/llm/driver-v2/context-health.js +121 -0
  27. package/dist/llm/driver-v2/context.js +56 -0
  28. package/dist/llm/driver-v2/core.js +1545 -0
  29. package/dist/llm/driver-v2/index.js +26 -0
  30. package/dist/llm/driver-v2/orchestrator.js +158 -0
  31. package/dist/llm/driver-v2/policy.js +129 -0
  32. package/dist/llm/driver-v2/restore-dialog-hierarchy.js +73 -0
  33. package/dist/llm/driver-v2/round.js +366 -0
  34. package/dist/llm/driver-v2/runtime-utils.js +365 -0
  35. package/dist/llm/driver-v2/saying-events.js +20 -0
  36. package/dist/llm/driver-v2/subdialog-txn.js +42 -0
  37. package/dist/llm/driver-v2/supdialog-response.js +400 -0
  38. package/dist/llm/driver-v2/tellask-bridge.js +1148 -0
  39. package/dist/llm/driver-v2/types.js +10 -0
  40. package/dist/llm/driver-v2-ref-only/context-health.js +121 -0
  41. package/dist/llm/driver-v2-ref-only/context.js +17 -0
  42. package/dist/llm/driver-v2-ref-only/core.js +1710 -0
  43. package/dist/llm/driver-v2-ref-only/index.js +26 -0
  44. package/dist/llm/driver-v2-ref-only/orchestrator.js +158 -0
  45. package/dist/llm/driver-v2-ref-only/policy.js +129 -0
  46. package/dist/llm/driver-v2-ref-only/restore-dialog-hierarchy.js +73 -0
  47. package/dist/llm/driver-v2-ref-only/round.js +366 -0
  48. package/dist/llm/driver-v2-ref-only/runtime-utils.js +473 -0
  49. package/dist/llm/driver-v2-ref-only/saying-events.js +18 -0
  50. package/dist/llm/driver-v2-ref-only/subdialog-txn.js +42 -0
  51. package/dist/llm/driver-v2-ref-only/supdialog-response.js +453 -0
  52. package/dist/llm/driver-v2-ref-only/tellask-bridge.js +1178 -0
  53. package/dist/llm/driver-v2-ref-only/types.js +10 -0
  54. package/dist/llm/gen/anthropic.js +68 -15
  55. package/dist/llm/gen/codex.js +59 -10
  56. package/dist/llm/gen/openai-compatible.js +38 -9
  57. package/dist/llm/gen/openai.js +58 -11
  58. package/dist/llm/gen/tool-output-limit.js +50 -0
  59. package/dist/llm/kernel-driver/subdialog.js +8 -1
  60. package/dist/llm/kernel-driver/tellask-special.js +18 -3
  61. package/dist/minds/load.js +7 -0
  62. package/dist/persistence.js +190 -28
  63. package/dist/priming.js +20 -1
  64. package/dist/server/api-routes.js +82 -0
  65. package/dist/server/setup-routes.js +15 -0
  66. package/dist/static/assets/{_basePickBy-B2o4z1Hf.js → _basePickBy-C-nynT9f.js} +3 -3
  67. package/dist/static/assets/{_basePickBy-B2o4z1Hf.js.map → _basePickBy-C-nynT9f.js.map} +1 -1
  68. package/dist/static/assets/{_baseUniq-CLmcxjdl.js → _baseUniq-CiHd-eVT.js} +2 -2
  69. package/dist/static/assets/{_baseUniq-CLmcxjdl.js.map → _baseUniq-CiHd-eVT.js.map} +1 -1
  70. package/dist/static/assets/{arc-CymD_KN7.js → arc-_OJzDWy1.js} +2 -2
  71. package/dist/static/assets/{arc-CymD_KN7.js.map → arc-_OJzDWy1.js.map} +1 -1
  72. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DJQfSJUH.js → architectureDiagram-VXUJARFQ-CDEG85ub.js} +7 -7
  73. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DJQfSJUH.js.map → architectureDiagram-VXUJARFQ-CDEG85ub.js.map} +1 -1
  74. package/dist/static/assets/{blockDiagram-VD42YOAC-pHVz60D0.js → blockDiagram-VD42YOAC-1LzKVc5t.js} +7 -7
  75. package/dist/static/assets/{blockDiagram-VD42YOAC-pHVz60D0.js.map → blockDiagram-VD42YOAC-1LzKVc5t.js.map} +1 -1
  76. package/dist/static/assets/{c4Diagram-YG6GDRKO-B0WnCfAT.js → c4Diagram-YG6GDRKO-BzYnVyvY.js} +3 -3
  77. package/dist/static/assets/{c4Diagram-YG6GDRKO-B0WnCfAT.js.map → c4Diagram-YG6GDRKO-BzYnVyvY.js.map} +1 -1
  78. package/dist/static/assets/{channel-CX9BlKil.js → channel-VAEDAk9T.js} +2 -2
  79. package/dist/static/assets/{channel-CX9BlKil.js.map → channel-VAEDAk9T.js.map} +1 -1
  80. package/dist/static/assets/{chunk-4BX2VUAB-lXArRj3o.js → chunk-4BX2VUAB-D0r2u3mX.js} +2 -2
  81. package/dist/static/assets/{chunk-4BX2VUAB-lXArRj3o.js.map → chunk-4BX2VUAB-D0r2u3mX.js.map} +1 -1
  82. package/dist/static/assets/{chunk-55IACEB6-CdqwynH9.js → chunk-55IACEB6-Dkl8Xw7i.js} +2 -2
  83. package/dist/static/assets/{chunk-55IACEB6-CdqwynH9.js.map → chunk-55IACEB6-Dkl8Xw7i.js.map} +1 -1
  84. package/dist/static/assets/{chunk-B4BG7PRW-Y-uXcJst.js → chunk-B4BG7PRW-9sxsI8ns.js} +5 -5
  85. package/dist/static/assets/{chunk-B4BG7PRW-Y-uXcJst.js.map → chunk-B4BG7PRW-9sxsI8ns.js.map} +1 -1
  86. package/dist/static/assets/{chunk-DI55MBZ5-C5xSbRST.js → chunk-DI55MBZ5-AHaqkaLl.js} +4 -4
  87. package/dist/static/assets/{chunk-DI55MBZ5-C5xSbRST.js.map → chunk-DI55MBZ5-AHaqkaLl.js.map} +1 -1
  88. package/dist/static/assets/{chunk-FMBD7UC4-5uefwCjI.js → chunk-FMBD7UC4-NWDLDixD.js} +2 -2
  89. package/dist/static/assets/{chunk-FMBD7UC4-5uefwCjI.js.map → chunk-FMBD7UC4-NWDLDixD.js.map} +1 -1
  90. package/dist/static/assets/{chunk-QN33PNHL-DzWVcvpI.js → chunk-QN33PNHL-C2KeUqle.js} +2 -2
  91. package/dist/static/assets/{chunk-QN33PNHL-DzWVcvpI.js.map → chunk-QN33PNHL-C2KeUqle.js.map} +1 -1
  92. package/dist/static/assets/{chunk-QZHKN3VN-BrrvAZdP.js → chunk-QZHKN3VN-B6Eoxo5L.js} +2 -2
  93. package/dist/static/assets/{chunk-QZHKN3VN-BrrvAZdP.js.map → chunk-QZHKN3VN-B6Eoxo5L.js.map} +1 -1
  94. package/dist/static/assets/{chunk-TZMSLE5B-DyKOlPTY.js → chunk-TZMSLE5B-Bc-VyQon.js} +2 -2
  95. package/dist/static/assets/{chunk-TZMSLE5B-DyKOlPTY.js.map → chunk-TZMSLE5B-Bc-VyQon.js.map} +1 -1
  96. package/dist/static/assets/{classDiagram-2ON5EDUG-FCrnlCWC.js → classDiagram-2ON5EDUG-DmPfsN1H.js} +6 -6
  97. package/dist/static/assets/{classDiagram-2ON5EDUG-FCrnlCWC.js.map → classDiagram-2ON5EDUG-DmPfsN1H.js.map} +1 -1
  98. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-FCrnlCWC.js → classDiagram-v2-WZHVMYZB-DmPfsN1H.js} +6 -6
  99. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-FCrnlCWC.js.map → classDiagram-v2-WZHVMYZB-DmPfsN1H.js.map} +1 -1
  100. package/dist/static/assets/{clone-BlI81KqZ.js → clone-B1R4pLTW.js} +2 -2
  101. package/dist/static/assets/{clone-BlI81KqZ.js.map → clone-B1R4pLTW.js.map} +1 -1
  102. package/dist/static/assets/{cose-bilkent-S5V4N54A-yM7S2atz.js → cose-bilkent-S5V4N54A-CxY__sKv.js} +2 -2
  103. package/dist/static/assets/{cose-bilkent-S5V4N54A-yM7S2atz.js.map → cose-bilkent-S5V4N54A-CxY__sKv.js.map} +1 -1
  104. package/dist/static/assets/{dagre-6UL2VRFP-BcweuZHt.js → dagre-6UL2VRFP-CPkB5tQ0.js} +7 -7
  105. package/dist/static/assets/{dagre-6UL2VRFP-BcweuZHt.js.map → dagre-6UL2VRFP-CPkB5tQ0.js.map} +1 -1
  106. package/dist/static/assets/{diagram-PSM6KHXK-D4-QwLW1.js → diagram-PSM6KHXK-C6kCVpCz.js} +8 -8
  107. package/dist/static/assets/{diagram-PSM6KHXK-D4-QwLW1.js.map → diagram-PSM6KHXK-C6kCVpCz.js.map} +1 -1
  108. package/dist/static/assets/{diagram-QEK2KX5R-BVbuejJn.js → diagram-QEK2KX5R-BWF6htf1.js} +7 -7
  109. package/dist/static/assets/{diagram-QEK2KX5R-BVbuejJn.js.map → diagram-QEK2KX5R-BWF6htf1.js.map} +1 -1
  110. package/dist/static/assets/{diagram-S2PKOQOG-pB6N6Tq_.js → diagram-S2PKOQOG-lKGJH6O9.js} +7 -7
  111. package/dist/static/assets/{diagram-S2PKOQOG-pB6N6Tq_.js.map → diagram-S2PKOQOG-lKGJH6O9.js.map} +1 -1
  112. package/dist/static/assets/{erDiagram-Q2GNP2WA-DLKmthuw.js → erDiagram-Q2GNP2WA-DJ3YaFob.js} +5 -5
  113. package/dist/static/assets/{erDiagram-Q2GNP2WA-DLKmthuw.js.map → erDiagram-Q2GNP2WA-DJ3YaFob.js.map} +1 -1
  114. package/dist/static/assets/{flowDiagram-NV44I4VS-BsBhWukh.js → flowDiagram-NV44I4VS-h3eQwA3O.js} +6 -6
  115. package/dist/static/assets/{flowDiagram-NV44I4VS-BsBhWukh.js.map → flowDiagram-NV44I4VS-h3eQwA3O.js.map} +1 -1
  116. package/dist/static/assets/{ganttDiagram-JELNMOA3-Debz-J-C.js → ganttDiagram-JELNMOA3-BCbsDOF_.js} +3 -3
  117. package/dist/static/assets/{ganttDiagram-JELNMOA3-Debz-J-C.js.map → ganttDiagram-JELNMOA3-BCbsDOF_.js.map} +1 -1
  118. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-BnAPFBGR.js → gitGraphDiagram-V2S2FVAM-D0kX6h-T.js} +8 -8
  119. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-BnAPFBGR.js.map → gitGraphDiagram-V2S2FVAM-D0kX6h-T.js.map} +1 -1
  120. package/dist/static/assets/{graph-DbzWiBNK.js → graph-CZIEXp3A.js} +3 -3
  121. package/dist/static/assets/{graph-DbzWiBNK.js.map → graph-CZIEXp3A.js.map} +1 -1
  122. package/dist/static/assets/{index-B-8J28g7.js → index-vIzCTZQE.js} +156 -35
  123. package/dist/static/assets/index-vIzCTZQE.js.map +1 -0
  124. package/dist/static/assets/{infoDiagram-HS3SLOUP-CZ5hWoxV.js → infoDiagram-HS3SLOUP-DUNbcXxv.js} +6 -6
  125. package/dist/static/assets/{infoDiagram-HS3SLOUP-CZ5hWoxV.js.map → infoDiagram-HS3SLOUP-DUNbcXxv.js.map} +1 -1
  126. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CKN3oSxk.js → journeyDiagram-XKPGCS4Q-Cg_VhiqB.js} +5 -5
  127. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CKN3oSxk.js.map → journeyDiagram-XKPGCS4Q-Cg_VhiqB.js.map} +1 -1
  128. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BQCMklfJ.js → kanban-definition-3W4ZIXB7-DMVCZVFE.js} +3 -3
  129. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BQCMklfJ.js.map → kanban-definition-3W4ZIXB7-DMVCZVFE.js.map} +1 -1
  130. package/dist/static/assets/{layout-C5B58szc.js → layout-DoKTmwlM.js} +5 -5
  131. package/dist/static/assets/{layout-C5B58szc.js.map → layout-DoKTmwlM.js.map} +1 -1
  132. package/dist/static/assets/{linear-_32fut6G.js → linear-DFVlPfX6.js} +2 -2
  133. package/dist/static/assets/{linear-_32fut6G.js.map → linear-DFVlPfX6.js.map} +1 -1
  134. package/dist/static/assets/{mindmap-definition-VGOIOE7T-C_goMzjx.js → mindmap-definition-VGOIOE7T-l5K7agVV.js} +4 -4
  135. package/dist/static/assets/{mindmap-definition-VGOIOE7T-C_goMzjx.js.map → mindmap-definition-VGOIOE7T-l5K7agVV.js.map} +1 -1
  136. package/dist/static/assets/{pieDiagram-ADFJNKIX-BQ2n0cOB.js → pieDiagram-ADFJNKIX-BfQzSE-A.js} +8 -8
  137. package/dist/static/assets/{pieDiagram-ADFJNKIX-BQ2n0cOB.js.map → pieDiagram-ADFJNKIX-BfQzSE-A.js.map} +1 -1
  138. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-BLg7_neg.js → quadrantDiagram-AYHSOK5B-CJWvA5jc.js} +3 -3
  139. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-BLg7_neg.js.map → quadrantDiagram-AYHSOK5B-CJWvA5jc.js.map} +1 -1
  140. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DwkJt0zi.js → requirementDiagram-UZGBJVZJ-CeBbmqBK.js} +4 -4
  141. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DwkJt0zi.js.map → requirementDiagram-UZGBJVZJ-CeBbmqBK.js.map} +1 -1
  142. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DmxmatUB.js → sankeyDiagram-TZEHDZUN-JeUBTDxx.js} +2 -2
  143. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DmxmatUB.js.map → sankeyDiagram-TZEHDZUN-JeUBTDxx.js.map} +1 -1
  144. package/dist/static/assets/{sequenceDiagram-WL72ISMW-KHU_eApU.js → sequenceDiagram-WL72ISMW-Bd_7Pgc5.js} +4 -4
  145. package/dist/static/assets/{sequenceDiagram-WL72ISMW-KHU_eApU.js.map → sequenceDiagram-WL72ISMW-Bd_7Pgc5.js.map} +1 -1
  146. package/dist/static/assets/{stateDiagram-FKZM4ZOC-B3DBCxAL.js → stateDiagram-FKZM4ZOC-D_WyM3K1.js} +9 -9
  147. package/dist/static/assets/{stateDiagram-FKZM4ZOC-B3DBCxAL.js.map → stateDiagram-FKZM4ZOC-D_WyM3K1.js.map} +1 -1
  148. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C-uIk7gh.js → stateDiagram-v2-4FDKWEC3-Q_yh26yx.js} +5 -5
  149. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C-uIk7gh.js.map → stateDiagram-v2-4FDKWEC3-Q_yh26yx.js.map} +1 -1
  150. package/dist/static/assets/{timeline-definition-IT6M3QCI-SysEcQCC.js → timeline-definition-IT6M3QCI-Ca8mCFDg.js} +3 -3
  151. package/dist/static/assets/{timeline-definition-IT6M3QCI-SysEcQCC.js.map → timeline-definition-IT6M3QCI-Ca8mCFDg.js.map} +1 -1
  152. package/dist/static/assets/{treemap-GDKQZRPO-d0AbKEc4.js → treemap-GDKQZRPO-CyBvKC8o.js} +5 -5
  153. package/dist/static/assets/{treemap-GDKQZRPO-d0AbKEc4.js.map → treemap-GDKQZRPO-CyBvKC8o.js.map} +1 -1
  154. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CmSQMxUh.js → xychartDiagram-PRI3JC2R-DY0BLEdj.js} +3 -3
  155. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CmSQMxUh.js.map → xychartDiagram-PRI3JC2R-DY0BLEdj.js.map} +1 -1
  156. package/dist/static/index.html +1 -1
  157. package/dist/team.js +33 -4
  158. package/dist/tools/app-reminders.js +280 -0
  159. package/dist/tools/prompts/memory/en/errors.md +155 -0
  160. package/dist/tools/prompts/memory/en/index.md +47 -0
  161. package/dist/tools/prompts/memory/en/principles.md +79 -0
  162. package/dist/tools/prompts/memory/en/scenarios.md +174 -0
  163. package/dist/tools/prompts/memory/en/tools.md +154 -0
  164. package/dist/tools/prompts/memory/zh/errors.md +155 -0
  165. package/dist/tools/prompts/memory/zh/index.md +47 -0
  166. package/dist/tools/prompts/memory/zh/principles.md +79 -0
  167. package/dist/tools/prompts/memory/zh/scenarios.md +174 -0
  168. package/dist/tools/prompts/memory/zh/tools.md +154 -0
  169. package/dist/tools/ripgrep.js +197 -63
  170. package/package.json +2 -2
  171. package/dist/static/assets/index-B-8J28g7.js.map +0 -1
@@ -562,7 +562,12 @@ async function executeTellaskCall(dlg, agent, mentionList, body, callId, callbac
562
562
  callType: 'C',
563
563
  };
564
564
  await (0, subdialog_txn_1.withSubdialogTxnLock)(dlg.id, async () => {
565
- await persistence_1.DialogPersistence.appendPendingSubdialog(dlg.id, pendingRecord);
565
+ await persistence_1.DialogPersistence.appendPendingSubdialog(dlg.id, pendingRecord, {
566
+ rootCourse: dlg instanceof dialog_1.SubDialog ? dlg.rootDialog.currentCourse : dlg.currentCourse,
567
+ rootGenseq: dlg instanceof dialog_1.SubDialog
568
+ ? (dlg.rootDialog.activeGenSeqOrUndefined ?? 0)
569
+ : (dlg.activeGenSeqOrUndefined ?? 0),
570
+ });
566
571
  });
567
572
  await syncPendingTellaskReminderBestEffort(dlg, 'kernel-driver:executeTellaskCall:FBR-TypeC:appendPending:lastRound');
568
573
  }
@@ -785,7 +790,12 @@ async function executeTellaskCall(dlg, agent, mentionList, body, callId, callbac
785
790
  sessionSlug: parseResult.sessionSlug,
786
791
  };
787
792
  await (0, subdialog_txn_1.withSubdialogTxnLock)(dlg.id, async () => {
788
- await persistence_1.DialogPersistence.appendPendingSubdialog(dlg.id, pendingRecord);
793
+ await persistence_1.DialogPersistence.appendPendingSubdialog(dlg.id, pendingRecord, {
794
+ rootCourse: dlg instanceof dialog_1.SubDialog ? dlg.rootDialog.currentCourse : dlg.currentCourse,
795
+ rootGenseq: dlg instanceof dialog_1.SubDialog
796
+ ? (dlg.rootDialog.activeGenSeqOrUndefined ?? 0)
797
+ : (dlg.activeGenSeqOrUndefined ?? 0),
798
+ });
789
799
  });
790
800
  await syncPendingTellaskReminderBestEffort(dlg, 'kernel-driver:executeTellaskCall:TypeB-fallback:appendPending');
791
801
  const initPrompt = {
@@ -962,7 +972,12 @@ async function executeTellaskCall(dlg, agent, mentionList, body, callId, callbac
962
972
  callType: 'C',
963
973
  };
964
974
  await (0, subdialog_txn_1.withSubdialogTxnLock)(dlg.id, async () => {
965
- await persistence_1.DialogPersistence.appendPendingSubdialog(dlg.id, pendingRecord);
975
+ await persistence_1.DialogPersistence.appendPendingSubdialog(dlg.id, pendingRecord, {
976
+ rootCourse: dlg instanceof dialog_1.SubDialog ? dlg.rootDialog.currentCourse : dlg.currentCourse,
977
+ rootGenseq: dlg instanceof dialog_1.SubDialog
978
+ ? (dlg.rootDialog.activeGenSeqOrUndefined ?? 0)
979
+ : (dlg.activeGenSeqOrUndefined ?? 0),
980
+ });
966
981
  });
967
982
  await syncPendingTellaskReminderBestEffort(dlg, 'kernel-driver:executeTellaskCall:TypeC:appendPending');
968
983
  const initPrompt = {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.loadAgentMinds = loadAgentMinds;
7
7
  const promises_1 = require("fs/promises");
8
8
  const path_1 = __importDefault(require("path"));
9
+ const runtime_1 = require("../apps/runtime");
9
10
  const dialog_1 = require("../dialog");
10
11
  const log_1 = require("../log");
11
12
  const runtime_language_1 = require("../shared/runtime-language");
@@ -106,6 +107,12 @@ async function readMindsTextPreferred(options) {
106
107
  async function loadAgentMinds(agentId, dialog, options) {
107
108
  const workingLanguage = (0, runtime_language_1.getWorkLanguage)();
108
109
  const missingToolsetPolicy = options?.missingToolsetPolicy ?? 'warn';
110
+ try {
111
+ await (0, runtime_1.registerEnabledAppsToolProxies)({ rtwsRootAbs: process.cwd() });
112
+ }
113
+ catch (error) {
114
+ log_1.log.warn(`Failed to refresh enabled app tool proxies before loading agent minds: ${error instanceof Error ? error.message : String(error)}`);
115
+ }
109
116
  let team = await team_1.Team.load();
110
117
  const agent = agentId === undefined ? team.getDefaultResponder() : team.getMember(agentId);
111
118
  if (!agent)
@@ -59,6 +59,48 @@ function getErrorCode(error) {
59
59
  function isRecord(value) {
60
60
  return typeof value === 'object' && value !== null;
61
61
  }
62
+ function serializeReminderSnapshot(reminder) {
63
+ const persistedReminder = reminder;
64
+ return {
65
+ content: reminder.content,
66
+ ownerName: reminder.owner?.name,
67
+ meta: reminder.meta,
68
+ echoback: reminder.echoback,
69
+ createdAt: persistedReminder.createdAt ?? (0, time_1.formatUnifiedTimestamp)(new Date()),
70
+ priority: persistedReminder.priority ?? 'medium',
71
+ };
72
+ }
73
+ function cloneReminderSnapshot(snapshot) {
74
+ return {
75
+ content: snapshot.content,
76
+ ownerName: snapshot.ownerName,
77
+ meta: snapshot.meta,
78
+ echoback: snapshot.echoback,
79
+ createdAt: snapshot.createdAt,
80
+ priority: snapshot.priority,
81
+ };
82
+ }
83
+ function cloneRootGenerationAnchor(anchor) {
84
+ return {
85
+ rootCourse: anchor.rootCourse,
86
+ rootGenseq: anchor.rootGenseq,
87
+ };
88
+ }
89
+ function resolveRootGenerationAnchor(dialog) {
90
+ const rootDialog = dialog instanceof dialog_1.SubDialog ? dialog.rootDialog : dialog;
91
+ return {
92
+ rootCourse: rootDialog.currentCourse,
93
+ rootGenseq: rootDialog.activeGenSeqOrUndefined ?? 0,
94
+ };
95
+ }
96
+ function attachRootGenerationRef(dialog, record) {
97
+ const anchor = resolveRootGenerationAnchor(dialog);
98
+ return {
99
+ ...record,
100
+ rootCourse: anchor.rootCourse,
101
+ rootGenseq: anchor.rootGenseq,
102
+ };
103
+ }
62
104
  function isRootDialogMetadataFile(value) {
63
105
  if (!isRecord(value))
64
106
  return false;
@@ -459,6 +501,29 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
459
501
  };
460
502
  await DialogPersistence.saveSubdialogMetadata(subdialogId, metadata);
461
503
  await DialogPersistence.saveDialogMetadata(subdialogId, metadata);
504
+ const rootAnchor = resolveRootGenerationAnchor(supdialog);
505
+ const parentCourse = supdialog.activeGenCourseOrUndefined ?? supdialog.currentCourse;
506
+ const subdialogCreatedRecord = {
507
+ ts: nowTs,
508
+ type: 'subdialog_created_record',
509
+ ...cloneRootGenerationAnchor(rootAnchor),
510
+ subdialogId: subdialogId.selfId,
511
+ supdialogId: supdialog.id.selfId,
512
+ agentId: targetAgentId,
513
+ taskDocPath: supdialog.taskDocPath,
514
+ createdAt: nowTs,
515
+ sessionSlug: options.sessionSlug,
516
+ assignmentFromSup: {
517
+ callName: options.callName,
518
+ mentionList,
519
+ tellaskContent,
520
+ originMemberId: options.originMemberId,
521
+ callerDialogId: options.callerDialogId,
522
+ callId: options.callId,
523
+ collectiveTargets: options.collectiveTargets,
524
+ },
525
+ };
526
+ await this.appendEvent(supdialog, parentCourse, subdialogCreatedRecord);
462
527
  // Initialize latest.yaml via the mutation API (write-back will flush).
463
528
  await DialogPersistence.mutateDialogLatest(subdialogId, () => ({
464
529
  kind: 'replace',
@@ -474,7 +539,6 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
474
539
  },
475
540
  }));
476
541
  // Supdialog clarification context is persisted in subdialog metadata (supdialogCall)
477
- const parentCourse = await DialogPersistence.getCurrentCourseNumber(supdialog.id);
478
542
  const subdialogCreatedEvt = {
479
543
  type: 'subdialog_created_evt',
480
544
  dialog: {
@@ -537,7 +601,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
537
601
  contentItems: funcResult.contentItems,
538
602
  genseq: dialog.activeGenSeq,
539
603
  };
540
- await this.appendEvent(course, funcResultRecord);
604
+ await this.appendEvent(dialog, course, funcResultRecord);
541
605
  // Send event to frontend
542
606
  const funcResultEvt = {
543
607
  type: 'func_result_evt',
@@ -607,7 +671,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
607
671
  };
608
672
  }
609
673
  })();
610
- await this.appendEvent(course, ev);
674
+ await this.appendEvent(dialog, course, ev);
611
675
  // Emit TeammateCallResponseEvent WITH callId for UI correlation
612
676
  const toolResponseEvt = (() => {
613
677
  switch (callName) {
@@ -736,7 +800,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
736
800
  };
737
801
  }
738
802
  })();
739
- await this.appendEvent(course, ev);
803
+ await this.appendEvent(dialog, course, ev);
740
804
  const teammateResponseEvt = (() => {
741
805
  switch (callName) {
742
806
  case 'tellask':
@@ -811,8 +875,8 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
811
875
  /**
812
876
  * Append event to course JSONL file (delegate to DialogPersistence)
813
877
  */
814
- async appendEvent(course, event) {
815
- await DialogPersistence.appendEvent(this.dialogId, course, event);
878
+ async appendEvent(dialog, course, event) {
879
+ await DialogPersistence.appendEvent(this.dialogId, course, attachRootGenerationRef(dialog, event));
816
880
  }
817
881
  /**
818
882
  * Notify start of LLM generation for frontend bubble management
@@ -828,7 +892,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
828
892
  type: 'gen_start_record',
829
893
  genseq: genseq,
830
894
  };
831
- await this.appendEvent(course, ev);
895
+ await this.appendEvent(dialog, course, ev);
832
896
  // Emit generating_start_evt event
833
897
  // This event MUST be emitted and processed before any substream events
834
898
  // to ensure the frontend has created the generation bubble before receiving
@@ -867,7 +931,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
867
931
  contextHealth,
868
932
  llmGenModel,
869
933
  };
870
- await this.appendEvent(course, ev);
934
+ await this.appendEvent(dialog, course, ev);
871
935
  // Emit generating_finish_evt event (this was missing, causing double triggering issue)
872
936
  const genFinishEvt = {
873
937
  type: 'generating_finish_evt',
@@ -929,7 +993,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
929
993
  genseq: dialog.activeGenSeq,
930
994
  content: sayingContent,
931
995
  };
932
- await this.appendEvent(course, sayingMessageEvent);
996
+ await this.appendEvent(dialog, course, sayingMessageEvent);
933
997
  }
934
998
  const evt = {
935
999
  type: 'markdown_finish_evt',
@@ -976,7 +1040,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
976
1040
  content: thinkingContent,
977
1041
  reasoning: this.thinkingReasoning,
978
1042
  };
979
- await this.appendEvent(course, thinkingMessageEvent);
1043
+ await this.appendEvent(dialog, course, thinkingMessageEvent);
980
1044
  }
981
1045
  const thinkingFinishEvt = {
982
1046
  type: 'thinking_finish_evt',
@@ -1086,7 +1150,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1086
1150
  status: payload.status,
1087
1151
  action: payload.action,
1088
1152
  };
1089
- await this.appendEvent(course, record);
1153
+ await this.appendEvent(dialog, course, record);
1090
1154
  const evt = {
1091
1155
  type: 'web_search_call_evt',
1092
1156
  course,
@@ -1142,6 +1206,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1142
1206
  */
1143
1207
  async persistReminders(dialog, reminders) {
1144
1208
  await DialogPersistence._saveReminderState(this.dialogId, reminders);
1209
+ await DialogPersistence.appendRemindersReconciledRecord(this.dialogId, reminders, resolveRootGenerationAnchor(dialog), dialog.status);
1145
1210
  }
1146
1211
  /**
1147
1212
  * Persist a user message to storage
@@ -1178,7 +1243,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1178
1243
  userLanguageCode,
1179
1244
  q4hAnswerCallIds: normalizedQ4HAnswerCallIds,
1180
1245
  };
1181
- await this.appendEvent(course, humanEv);
1246
+ await this.appendEvent(dialog, course, humanEv);
1182
1247
  // Note: end_of_user_saying_evt is now emitted by llm/driver.ts after tellask calls complete
1183
1248
  }
1184
1249
  /**
@@ -1201,7 +1266,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1201
1266
  genseq,
1202
1267
  content: content || '',
1203
1268
  };
1204
- await this.appendEvent(course, event);
1269
+ await this.appendEvent(dialog, course, event);
1205
1270
  }
1206
1271
  async persistUiOnlyMarkdown(dialog, content, genseq) {
1207
1272
  const course = dialog.activeGenCourseOrUndefined ?? dialog.currentCourse;
@@ -1211,7 +1276,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1211
1276
  genseq,
1212
1277
  content: content || '',
1213
1278
  };
1214
- await this.appendEvent(course, ev);
1279
+ await this.appendEvent(dialog, course, ev);
1215
1280
  }
1216
1281
  /**
1217
1282
  * Persist a function call to storage
@@ -1226,7 +1291,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1226
1291
  name,
1227
1292
  arguments: arguments_,
1228
1293
  };
1229
- await this.appendEvent(course, funcCallEvent);
1294
+ await this.appendEvent(dialog, course, funcCallEvent);
1230
1295
  // NOTE: func_call_evt REMOVED - persistence uses FuncCallRecord directly
1231
1296
  // UI display uses func_call_requested_evt instead
1232
1297
  }
@@ -1235,6 +1300,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1235
1300
  */
1236
1301
  async updateQuestions4Human(dialog, questions) {
1237
1302
  await DialogPersistence._saveQuestions4HumanState(this.dialogId, questions);
1303
+ await DialogPersistence.appendQuestions4HumanReconciledRecord(this.dialogId, questions, resolveRootGenerationAnchor(dialog), dialog.status);
1238
1304
  }
1239
1305
  /**
1240
1306
  * Load Questions for Human state from storage
@@ -1259,8 +1325,14 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1259
1325
  sessionSlug: record.sessionSlug,
1260
1326
  }));
1261
1327
  }
1262
- async saveSubdialogRegistry(rootDialogId, entries, status) {
1328
+ async saveSubdialogRegistry(dialog, rootDialogId, entries, status) {
1263
1329
  await DialogPersistence.saveSubdialogRegistry(rootDialogId, entries, status);
1330
+ await DialogPersistence.appendSubdialogRegistryReconciledRecord(rootDialogId, entries.map((entry) => ({
1331
+ key: entry.key,
1332
+ subdialogId: entry.subdialogId.selfId,
1333
+ agentId: entry.agentId,
1334
+ sessionSlug: entry.sessionSlug,
1335
+ })), resolveRootGenerationAnchor(dialog), status);
1264
1336
  }
1265
1337
  async loadSubdialogRegistry(rootDialog, status) {
1266
1338
  const entries = await DialogPersistence.loadSubdialogRegistry(rootDialog.id, status);
@@ -1405,6 +1477,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1405
1477
  const previousCount = previousQuestions.length;
1406
1478
  if (previousCount > 0) {
1407
1479
  await DialogPersistence.clearQuestions4HumanState(dialog.id);
1480
+ await DialogPersistence.appendQuestions4HumanReconciledRecord(dialog.id, [], resolveRootGenerationAnchor(dialog), dialog.status);
1408
1481
  // Emit q4h_answered events for each removed question
1409
1482
  for (const q of previousQuestions) {
1410
1483
  const answeredEvent = {
@@ -1961,6 +2034,13 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
1961
2034
  }
1962
2035
  break;
1963
2036
  }
2037
+ case 'subdialog_created_record':
2038
+ case 'reminders_reconciled_record':
2039
+ case 'questions4human_reconciled_record':
2040
+ case 'pending_subdialogs_reconciled_record':
2041
+ case 'subdialog_registry_reconciled_record':
2042
+ case 'subdialog_responses_reconciled_record':
2043
+ break;
1964
2044
  case 'teammate_response_record': {
1965
2045
  // Handle teammate response events (separate bubble for @teammate tellasks)
1966
2046
  const mentionList = (() => {
@@ -2134,6 +2214,75 @@ class DialogPersistence {
2134
2214
  static getPendingSubdialogsWriteBackKey(rootDialogId, status) {
2135
2215
  return `${this.getDialogsRootDir()}|${status}|${rootDialogId.valueOf()}|pending-subdialogs`;
2136
2216
  }
2217
+ static clonePendingSubdialogRecords(records) {
2218
+ return records.map((record) => ({
2219
+ ...record,
2220
+ mentionList: record.mentionList ? [...record.mentionList] : undefined,
2221
+ }));
2222
+ }
2223
+ static cloneQuestions4Human(questions) {
2224
+ return questions.map((question) => ({
2225
+ ...question,
2226
+ remainingCallIds: question.remainingCallIds ? [...question.remainingCallIds] : undefined,
2227
+ callSiteRef: { ...question.callSiteRef },
2228
+ }));
2229
+ }
2230
+ static cloneRegistryEntries(entries) {
2231
+ return entries.map((entry) => ({
2232
+ ...entry,
2233
+ }));
2234
+ }
2235
+ static cloneSubdialogResponses(responses) {
2236
+ return responses.map((response) => ({
2237
+ ...response,
2238
+ mentionList: response.mentionList ? [...response.mentionList] : undefined,
2239
+ }));
2240
+ }
2241
+ static async appendRemindersReconciledRecord(dialogId, reminders, anchor, status) {
2242
+ const record = {
2243
+ ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
2244
+ type: 'reminders_reconciled_record',
2245
+ ...cloneRootGenerationAnchor(anchor),
2246
+ reminders: reminders.map((reminder) => serializeReminderSnapshot(reminder)),
2247
+ };
2248
+ await this.appendEvent(dialogId, anchor.rootCourse, record, status);
2249
+ }
2250
+ static async appendQuestions4HumanReconciledRecord(dialogId, questions, anchor, status) {
2251
+ const record = {
2252
+ ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
2253
+ type: 'questions4human_reconciled_record',
2254
+ ...cloneRootGenerationAnchor(anchor),
2255
+ questions: this.cloneQuestions4Human(questions),
2256
+ };
2257
+ await this.appendEvent(dialogId, anchor.rootCourse, record, status);
2258
+ }
2259
+ static async appendPendingSubdialogsReconciledRecord(dialogId, pendingSubdialogs, anchor, status) {
2260
+ const record = {
2261
+ ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
2262
+ type: 'pending_subdialogs_reconciled_record',
2263
+ ...cloneRootGenerationAnchor(anchor),
2264
+ pendingSubdialogs: this.clonePendingSubdialogRecords(pendingSubdialogs),
2265
+ };
2266
+ await this.appendEvent(dialogId, anchor.rootCourse, record, status);
2267
+ }
2268
+ static async appendSubdialogRegistryReconciledRecord(dialogId, entries, anchor, status) {
2269
+ const record = {
2270
+ ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
2271
+ type: 'subdialog_registry_reconciled_record',
2272
+ ...cloneRootGenerationAnchor(anchor),
2273
+ entries: this.cloneRegistryEntries(entries),
2274
+ };
2275
+ await this.appendEvent(dialogId, anchor.rootCourse, record, status);
2276
+ }
2277
+ static async appendSubdialogResponsesReconciledRecord(dialogId, responses, anchor, status) {
2278
+ const record = {
2279
+ ts: (0, time_1.formatUnifiedTimestamp)(new Date()),
2280
+ type: 'subdialog_responses_reconciled_record',
2281
+ ...cloneRootGenerationAnchor(anchor),
2282
+ responses: this.cloneSubdialogResponses(responses),
2283
+ };
2284
+ await this.appendEvent(dialogId, anchor.rootCourse, record, status);
2285
+ }
2137
2286
  /**
2138
2287
  * Get the base dialogs directory path
2139
2288
  */
@@ -3091,9 +3240,9 @@ class DialogPersistence {
3091
3240
  * Save pending subdialogs for Type A supply mechanism.
3092
3241
  * Tracks subdialogs that were created but not yet completed.
3093
3242
  */
3094
- static async savePendingSubdialogs(rootDialogId, pendingSubdialogs, status = 'running') {
3243
+ static async savePendingSubdialogs(rootDialogId, pendingSubdialogs, rootAnchor, status = 'running') {
3095
3244
  const next = pendingSubdialogs.map((r) => ({ ...r }));
3096
- await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'replace', records: next }), status);
3245
+ await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'replace', records: next }), rootAnchor, status);
3097
3246
  }
3098
3247
  /**
3099
3248
  * Load pending subdialogs for Type A supply mechanism.
@@ -3181,7 +3330,7 @@ class DialogPersistence {
3181
3330
  throw error;
3182
3331
  }
3183
3332
  }
3184
- static async mutatePendingSubdialogs(rootDialogId, mutator, status = 'running') {
3333
+ static async mutatePendingSubdialogs(rootDialogId, mutator, rootAnchor, status = 'running') {
3185
3334
  const key = this.getPendingSubdialogsWriteBackKey(rootDialogId, status);
3186
3335
  const mutex = this.getPendingSubdialogsWriteBackMutex(key);
3187
3336
  const release = await mutex.acquire();
@@ -3246,20 +3395,23 @@ class DialogPersistence {
3246
3395
  if (pending.kind === 'flushing')
3247
3396
  pending.dirty = true;
3248
3397
  }
3398
+ if (rootAnchor) {
3399
+ await this.appendPendingSubdialogsReconciledRecord(rootDialogId, nextRecords, rootAnchor, status);
3400
+ }
3249
3401
  return { previousRecords, records: nextRecords, removedRecords };
3250
3402
  }
3251
3403
  finally {
3252
3404
  release();
3253
3405
  }
3254
3406
  }
3255
- static async appendPendingSubdialog(rootDialogId, record, status = 'running') {
3256
- await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'append', record }), status);
3407
+ static async appendPendingSubdialog(rootDialogId, record, rootAnchor, status = 'running') {
3408
+ await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'append', record }), rootAnchor, status);
3257
3409
  }
3258
- static async removePendingSubdialog(rootDialogId, subdialogId, status = 'running') {
3259
- await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'removeBySubdialogId', subdialogId }), status);
3410
+ static async removePendingSubdialog(rootDialogId, subdialogId, rootAnchor, status = 'running') {
3411
+ await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'removeBySubdialogId', subdialogId }), rootAnchor, status);
3260
3412
  }
3261
- static async clearPendingSubdialogs(rootDialogId, status = 'running') {
3262
- await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'clear' }), status);
3413
+ static async clearPendingSubdialogs(rootDialogId, rootAnchor, status = 'running') {
3414
+ await this.mutatePendingSubdialogs(rootDialogId, () => ({ kind: 'clear' }), rootAnchor, status);
3263
3415
  }
3264
3416
  static async flushPendingSubdialogsWriteBack(key) {
3265
3417
  const mutex = this.getPendingSubdialogsWriteBackMutex(key);
@@ -3388,7 +3540,7 @@ class DialogPersistence {
3388
3540
  * Save subdialog responses for Type A supply mechanism.
3389
3541
  * Tracks responses from completed subdialogs.
3390
3542
  */
3391
- static async saveSubdialogResponses(rootDialogId, responses, status = 'running') {
3543
+ static async saveSubdialogResponses(rootDialogId, responses, rootAnchor, status = 'running') {
3392
3544
  try {
3393
3545
  const dialogPath = this.getDialogResponsesPath(rootDialogId, status);
3394
3546
  await fs.promises.mkdir(dialogPath, { recursive: true });
@@ -3398,6 +3550,9 @@ class DialogPersistence {
3398
3550
  const tempFile = path.join(dialogPath, `.${path.basename(filePath)}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`);
3399
3551
  await fs.promises.writeFile(tempFile, jsonContent, 'utf-8');
3400
3552
  await this.renameWithRetry(tempFile, filePath, jsonContent);
3553
+ if (rootAnchor) {
3554
+ await this.appendSubdialogResponsesReconciledRecord(rootDialogId, responses, rootAnchor, status);
3555
+ }
3401
3556
  }
3402
3557
  catch (error) {
3403
3558
  log_1.log.error(`Failed to save subdialog responses for dialog ${rootDialogId}:`, error);
@@ -3471,10 +3626,10 @@ class DialogPersistence {
3471
3626
  throw error;
3472
3627
  }
3473
3628
  }
3474
- static async appendSubdialogResponse(dialogId, response, status = 'running') {
3629
+ static async appendSubdialogResponse(dialogId, response, rootAnchor, status = 'running') {
3475
3630
  const existing = await this.loadSubdialogResponsesQueue(dialogId, status);
3476
3631
  existing.push(response);
3477
- await this.saveSubdialogResponses(dialogId, existing, status);
3632
+ await this.saveSubdialogResponses(dialogId, existing, rootAnchor, status);
3478
3633
  }
3479
3634
  static async takeSubdialogResponses(dialogId, status = 'running') {
3480
3635
  const dialogPath = this.getDialogResponsesPath(dialogId, status);
@@ -4240,6 +4395,13 @@ class DialogPersistence {
4240
4395
  // This record is UI navigation metadata for deep links in callee dialogs.
4241
4396
  // It does not contribute to model context or chat transcript reconstruction.
4242
4397
  break;
4398
+ case 'subdialog_created_record':
4399
+ case 'reminders_reconciled_record':
4400
+ case 'questions4human_reconciled_record':
4401
+ case 'pending_subdialogs_reconciled_record':
4402
+ case 'subdialog_registry_reconciled_record':
4403
+ case 'subdialog_responses_reconciled_record':
4404
+ break;
4243
4405
  default:
4244
4406
  log_1.log.warn(`Unknown event type in rebuildFromEvents`, undefined, { event });
4245
4407
  break;
package/dist/priming.js CHANGED
@@ -1656,6 +1656,13 @@ function stripTimestampFromRecord(event) {
1656
1656
  const { ts: _unusedTs, ...withoutTs } = event;
1657
1657
  return withoutTs;
1658
1658
  }
1659
+ case 'subdialog_created_record':
1660
+ case 'reminders_reconciled_record':
1661
+ case 'questions4human_reconciled_record':
1662
+ case 'pending_subdialogs_reconciled_record':
1663
+ case 'subdialog_registry_reconciled_record':
1664
+ case 'subdialog_responses_reconciled_record':
1665
+ throw new Error(`Record type ${event.type} is not supported in priming scripts`);
1659
1666
  default: {
1660
1667
  const _exhaustive = event;
1661
1668
  throw new Error(`Unhandled persisted record type: ${String(_exhaustive)}`);
@@ -1663,7 +1670,19 @@ function stripTimestampFromRecord(event) {
1663
1670
  }
1664
1671
  }
1665
1672
  function extractPrimingRecordsFromEvents(events) {
1666
- return events.map((event) => stripTimestampFromRecord(event));
1673
+ return events.flatMap((event) => {
1674
+ switch (event.type) {
1675
+ case 'subdialog_created_record':
1676
+ case 'reminders_reconciled_record':
1677
+ case 'questions4human_reconciled_record':
1678
+ case 'pending_subdialogs_reconciled_record':
1679
+ case 'subdialog_registry_reconciled_record':
1680
+ case 'subdialog_responses_reconciled_record':
1681
+ return [];
1682
+ default:
1683
+ return [stripTimestampFromRecord(event)];
1684
+ }
1685
+ });
1667
1686
  }
1668
1687
  async function saveDialogCourseAsIndividualPrimingScript(args) {
1669
1688
  const normalizedSlug = normalizeSlug(args.slug);
@@ -45,7 +45,9 @@ exports.handleApiRoute = handleApiRoute;
45
45
  */
46
46
  const promises_1 = __importDefault(require("fs/promises"));
47
47
  const path = __importStar(require("path"));
48
+ const runtime_1 = require("../apps/runtime");
48
49
  const dialog_1 = require("../dialog");
50
+ const dialog_fork_1 = require("../dialog-fork");
49
51
  const dialog_global_registry_1 = require("../dialog-global-registry");
50
52
  const dialog_run_state_1 = require("../dialog-run-state");
51
53
  const log_1 = require("../log");
@@ -1044,9 +1046,21 @@ async function handleApiRoute(req, res, pathname, context) {
1044
1046
  if (pathname === '/api/dialogs/move' && req.method === 'POST') {
1045
1047
  return await handleMoveDialogs(req, res, context);
1046
1048
  }
1049
+ if (pathname.startsWith('/api/dialogs/') &&
1050
+ pathname.endsWith('/fork') &&
1051
+ req.method === 'POST') {
1052
+ const parts = pathname.split('/');
1053
+ const rawRoot = parts[3];
1054
+ if (!rawRoot) {
1055
+ respondJson(res, 400, { success: false, error: 'Missing root dialog id' });
1056
+ return true;
1057
+ }
1058
+ return await handleForkDialog(req, res, context, rawRoot.replace(/%2F/g, '/'));
1059
+ }
1047
1060
  // Delete a dialog (root dialogs only for now)
1048
1061
  if (pathname.startsWith('/api/dialogs/') &&
1049
1062
  !pathname.endsWith('/hierarchy') &&
1063
+ !pathname.endsWith('/fork') &&
1050
1064
  req.method === 'DELETE') {
1051
1065
  const parts = pathname.split('/');
1052
1066
  const rawRoot = parts[3];
@@ -1606,6 +1620,7 @@ async function handleReadWorkspaceEntry(req, res) {
1606
1620
  }
1607
1621
  async function handleGetToolsRegistry(res) {
1608
1622
  try {
1623
+ await (0, runtime_1.registerEnabledAppsToolProxies)({ rtwsRootAbs: process.cwd() });
1609
1624
  const snapshot = (0, registry_snapshot_1.createToolsRegistrySnapshot)();
1610
1625
  res.writeHead(200, {
1611
1626
  'Content-Type': 'application/json',
@@ -1975,6 +1990,73 @@ async function handleCreateDialog(req, res, context) {
1975
1990
  return true;
1976
1991
  }
1977
1992
  }
1993
+ async function handleForkDialog(req, res, context, rootIdRaw) {
1994
+ try {
1995
+ const body = await readRequestBody(req);
1996
+ const parsed = JSON.parse(body);
1997
+ if (!isRecord(parsed)) {
1998
+ const payload = { success: false, error: 'Invalid JSON body' };
1999
+ respondJson(res, 400, payload);
2000
+ return true;
2001
+ }
2002
+ const courseRaw = parsed['course'];
2003
+ const genseqRaw = parsed['genseq'];
2004
+ const statusRaw = parsed['status'];
2005
+ const rootId = rootIdRaw.trim();
2006
+ const course = typeof courseRaw === 'number' && Number.isFinite(courseRaw) ? Math.floor(courseRaw) : 0;
2007
+ const genseq = typeof genseqRaw === 'number' && Number.isFinite(genseqRaw) ? Math.floor(genseqRaw) : 0;
2008
+ const status = parseDialogStatusKind(statusRaw) ?? 'running';
2009
+ if (rootId === '') {
2010
+ const payload = { success: false, error: 'rootId is required' };
2011
+ respondJson(res, 400, payload);
2012
+ return true;
2013
+ }
2014
+ if (course <= 0 || genseq <= 0) {
2015
+ const payload = {
2016
+ success: false,
2017
+ error: 'course and genseq must be positive integers',
2018
+ };
2019
+ respondJson(res, 400, payload);
2020
+ return true;
2021
+ }
2022
+ const result = await (0, dialog_fork_1.forkRootDialogTreeAtGeneration)({
2023
+ sourceRootId: rootId,
2024
+ sourceStatus: status,
2025
+ course,
2026
+ genseq,
2027
+ });
2028
+ const payload = {
2029
+ success: true,
2030
+ dialog: {
2031
+ rootId: result.rootId,
2032
+ selfId: result.selfId,
2033
+ agentId: result.agentId,
2034
+ agentName: result.agentId,
2035
+ taskDocPath: result.taskDocPath,
2036
+ status: 'running',
2037
+ },
2038
+ action: result.action,
2039
+ };
2040
+ respondJson(res, 201, payload);
2041
+ broadcastDialogCreates(context.clients, {
2042
+ type: 'dialogs_created',
2043
+ scope: { kind: 'root', rootId: result.rootId },
2044
+ status: 'running',
2045
+ createdRootIds: [result.rootId],
2046
+ timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
2047
+ });
2048
+ return true;
2049
+ }
2050
+ catch (error) {
2051
+ log.error('Error forking dialog:', error);
2052
+ const payload = {
2053
+ success: false,
2054
+ error: error instanceof Error ? error.message : 'Failed to fork dialog',
2055
+ };
2056
+ respondJson(res, 500, payload);
2057
+ return true;
2058
+ }
2059
+ }
1978
2060
  async function handleMoveDialogs(req, res, context) {
1979
2061
  try {
1980
2062
  const body = await readRequestBody(req);
@@ -371,11 +371,26 @@ function extractProminentEnumModelParams(modelParamOptions) {
371
371
  const defaultValue = typeof opt.default === 'string' && opt.values.includes(opt.default)
372
372
  ? opt.default
373
373
  : undefined;
374
+ const rawValueLabels = opt.value_labels;
375
+ let valueLabels;
376
+ if (rawValueLabels && typeof rawValueLabels === 'object' && !Array.isArray(rawValueLabels)) {
377
+ const next = {};
378
+ for (const [rawKey, rawLabel] of Object.entries(rawValueLabels)) {
379
+ if (!opt.values.includes(rawKey))
380
+ continue;
381
+ if (typeof rawLabel !== 'string' || rawLabel.length === 0)
382
+ continue;
383
+ next[rawKey] = rawLabel;
384
+ }
385
+ if (Object.keys(next).length > 0)
386
+ valueLabels = next;
387
+ }
374
388
  out.push({
375
389
  namespace,
376
390
  key,
377
391
  description: opt.description,
378
392
  values: opt.values,
393
+ ...(valueLabels ? { valueLabels } : {}),
379
394
  ...(defaultValue ? { defaultValue } : {}),
380
395
  });
381
396
  }