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
@@ -13,6 +13,200 @@ const dynamicImport = new Function('specifier', 'return import(specifier)');
13
13
  function isRecord(v) {
14
14
  return typeof v === 'object' && v !== null && !Array.isArray(v);
15
15
  }
16
+ function isJsonPrimitive(value) {
17
+ return (typeof value === 'string' ||
18
+ typeof value === 'number' ||
19
+ typeof value === 'boolean' ||
20
+ value === null);
21
+ }
22
+ function isJsonValue(value) {
23
+ if (isJsonPrimitive(value))
24
+ return true;
25
+ if (Array.isArray(value))
26
+ return value.every((item) => isJsonValue(item));
27
+ if (!isRecord(value))
28
+ return false;
29
+ return Object.values(value).every((item) => isJsonValue(item));
30
+ }
31
+ function isToolCallOutput(value) {
32
+ if (typeof value === 'string')
33
+ return true;
34
+ if (!isRecord(value))
35
+ return false;
36
+ if (typeof value['content'] !== 'string')
37
+ return false;
38
+ const contentItems = value['contentItems'];
39
+ return contentItems === undefined || Array.isArray(contentItems);
40
+ }
41
+ function parseReminderRequest(value) {
42
+ if (!isRecord(value))
43
+ throw new Error('Invalid app tool reminder request: expected object');
44
+ const kind = value['kind'];
45
+ const ownerRef = value['ownerRef'];
46
+ if (typeof ownerRef !== 'string' || ownerRef.trim() === '') {
47
+ throw new Error('Invalid app tool reminder request: ownerRef required');
48
+ }
49
+ if (kind === 'delete') {
50
+ const meta = value['meta'];
51
+ if (meta !== undefined && !isJsonValue(meta)) {
52
+ throw new Error('Invalid app tool reminder request: delete.meta must be JSON-serializable');
53
+ }
54
+ return { kind: 'delete', ownerRef, meta };
55
+ }
56
+ if (kind === 'upsert') {
57
+ const content = value['content'];
58
+ if (typeof content !== 'string') {
59
+ throw new Error('Invalid app tool reminder request: upsert.content must be string');
60
+ }
61
+ const meta = value['meta'];
62
+ if (meta !== undefined && !isJsonValue(meta)) {
63
+ throw new Error('Invalid app tool reminder request: upsert.meta must be JSON-serializable');
64
+ }
65
+ const positionRaw = value['position'];
66
+ const position = positionRaw === undefined
67
+ ? undefined
68
+ : typeof positionRaw === 'number' && Number.isFinite(positionRaw)
69
+ ? Math.floor(positionRaw)
70
+ : null;
71
+ if (position === null) {
72
+ throw new Error('Invalid app tool reminder request: upsert.position must be finite number');
73
+ }
74
+ const echobackRaw = value['echoback'];
75
+ const echoback = echobackRaw === undefined ? undefined : typeof echobackRaw === 'boolean' ? echobackRaw : null;
76
+ if (echoback === null) {
77
+ throw new Error('Invalid app tool reminder request: upsert.echoback must be boolean');
78
+ }
79
+ return { kind: 'upsert', ownerRef, content, meta, position, echoback };
80
+ }
81
+ throw new Error(`Invalid app tool reminder request kind: ${String(kind)}`);
82
+ }
83
+ function parseDialogTargetRef(value) {
84
+ if (!isRecord(value))
85
+ throw new Error('Invalid dialog reminder target: expected object');
86
+ const dialogId = value['dialogId'];
87
+ if (typeof dialogId === 'string' && dialogId.trim() !== '') {
88
+ return { dialogId };
89
+ }
90
+ const agentId = value['agentId'];
91
+ if (typeof agentId !== 'string' || agentId.trim() === '') {
92
+ throw new Error('Invalid dialog reminder target: agentId required when dialogId is absent');
93
+ }
94
+ const rootDialogIdRaw = value['rootDialogId'];
95
+ const rootDialogId = rootDialogIdRaw === undefined
96
+ ? undefined
97
+ : typeof rootDialogIdRaw === 'string' && rootDialogIdRaw.trim() !== ''
98
+ ? rootDialogIdRaw
99
+ : null;
100
+ if (rootDialogId === null) {
101
+ throw new Error('Invalid dialog reminder target: rootDialogId must be non-empty string');
102
+ }
103
+ const sessionSlugRaw = value['sessionSlug'];
104
+ const sessionSlug = sessionSlugRaw === undefined
105
+ ? undefined
106
+ : typeof sessionSlugRaw === 'string' && sessionSlugRaw.trim() !== ''
107
+ ? sessionSlugRaw
108
+ : null;
109
+ if (sessionSlug === null) {
110
+ throw new Error('Invalid dialog reminder target: sessionSlug must be non-empty string');
111
+ }
112
+ return { agentId, rootDialogId, sessionSlug };
113
+ }
114
+ function parseDialogReminderRequestBatch(value) {
115
+ if (!isRecord(value))
116
+ throw new Error('Invalid dialog reminder request batch: expected object');
117
+ const reminderRequestsRaw = value['reminderRequests'];
118
+ if (!Array.isArray(reminderRequestsRaw)) {
119
+ throw new Error('Invalid dialog reminder request batch: reminderRequests must be an array');
120
+ }
121
+ return {
122
+ target: parseDialogTargetRef(value['target']),
123
+ reminderRequests: reminderRequestsRaw.map((request) => parseReminderRequest(request)),
124
+ };
125
+ }
126
+ function isReminderState(value) {
127
+ if (!isRecord(value))
128
+ return false;
129
+ if (typeof value['content'] !== 'string')
130
+ return false;
131
+ const meta = value['meta'];
132
+ if (meta !== undefined && !isJsonValue(meta))
133
+ return false;
134
+ const echoback = value['echoback'];
135
+ return echoback === undefined || typeof echoback === 'boolean';
136
+ }
137
+ function isReminderApplyResult(value) {
138
+ if (!isRecord(value))
139
+ return false;
140
+ const treatment = value['treatment'];
141
+ if (treatment === 'noop')
142
+ return true;
143
+ if (treatment === 'add') {
144
+ const position = value['position'];
145
+ return (isReminderState(value['reminder']) &&
146
+ (position === undefined || (typeof position === 'number' && Number.isFinite(position))));
147
+ }
148
+ if (treatment === 'update') {
149
+ return (typeof value['ownedIndex'] === 'number' &&
150
+ Number.isFinite(value['ownedIndex']) &&
151
+ isReminderState(value['reminder']));
152
+ }
153
+ if (treatment === 'delete') {
154
+ return typeof value['ownedIndex'] === 'number' && Number.isFinite(value['ownedIndex']);
155
+ }
156
+ return false;
157
+ }
158
+ function isReminderUpdateResult(value) {
159
+ if (!isRecord(value))
160
+ return false;
161
+ const treatment = value['treatment'];
162
+ if (treatment === 'drop' || treatment === 'keep') {
163
+ return true;
164
+ }
165
+ if (treatment !== 'update')
166
+ return false;
167
+ if (typeof value['updatedContent'] !== 'string')
168
+ return false;
169
+ const updatedMeta = value['updatedMeta'];
170
+ return updatedMeta === undefined || isJsonValue(updatedMeta);
171
+ }
172
+ function isChatMessage(value) {
173
+ if (!isRecord(value))
174
+ return false;
175
+ if (typeof value['type'] !== 'string')
176
+ return false;
177
+ if (typeof value['role'] !== 'string')
178
+ return false;
179
+ return true;
180
+ }
181
+ function normalizeToolResult(value) {
182
+ if (isToolCallOutput(value)) {
183
+ return { output: value };
184
+ }
185
+ if (!isRecord(value)) {
186
+ throw new Error('Invalid app tool result: expected ToolCallOutput or structured object');
187
+ }
188
+ const output = value['output'];
189
+ if (!isToolCallOutput(output)) {
190
+ throw new Error('Invalid app tool result: output must be ToolCallOutput');
191
+ }
192
+ const reminderRequestsRaw = value['reminderRequests'];
193
+ if (reminderRequestsRaw !== undefined && !Array.isArray(reminderRequestsRaw)) {
194
+ throw new Error('Invalid app tool result: reminderRequests must be an array');
195
+ }
196
+ const dialogReminderRequestsRaw = value['dialogReminderRequests'];
197
+ if (dialogReminderRequestsRaw !== undefined && !Array.isArray(dialogReminderRequestsRaw)) {
198
+ throw new Error('Invalid app tool result: dialogReminderRequests must be an array');
199
+ }
200
+ return {
201
+ output,
202
+ reminderRequests: reminderRequestsRaw === undefined
203
+ ? undefined
204
+ : reminderRequestsRaw.map((request) => parseReminderRequest(request)),
205
+ dialogReminderRequests: dialogReminderRequestsRaw === undefined
206
+ ? undefined
207
+ : dialogReminderRequestsRaw.map((batch) => parseDialogReminderRequestBatch(batch)),
208
+ };
209
+ }
16
210
  function send(msg) {
17
211
  if (typeof process.send !== 'function') {
18
212
  throw new Error(`apps-host: process.send is not available; must be started with child_process.fork (msg=${JSON.stringify(msg)})`);
@@ -22,6 +216,10 @@ function send(msg) {
22
216
  const runningApps = new Map();
23
217
  const toolHandlers = new Map();
24
218
  const runControlHandlers = new Map();
219
+ const reminderOwnerHandlers = new Map();
220
+ function buildReminderOwnerHandlerKey(appId, ownerRef) {
221
+ return `${appId}::${ownerRef}`;
222
+ }
25
223
  function pickExportedFactory(mod, exportName, moduleAbs) {
26
224
  if (isRecord(mod) && typeof mod[exportName] === 'function') {
27
225
  return mod[exportName];
@@ -51,6 +249,10 @@ function validateHostInstance(host, appId) {
51
249
  if (runControls !== undefined && !isRecord(runControls)) {
52
250
  throw new Error(`Invalid app host instance for '${appId}': runControls must be an object`);
53
251
  }
252
+ const reminderOwners = host['reminderOwners'];
253
+ if (reminderOwners !== undefined && !isRecord(reminderOwners)) {
254
+ throw new Error(`Invalid app host instance for '${appId}': reminderOwners must be an object`);
255
+ }
54
256
  const toolFns = tools;
55
257
  for (const [name, fn] of Object.entries(toolFns)) {
56
258
  if (typeof fn !== 'function') {
@@ -65,6 +267,23 @@ function validateHostInstance(host, appId) {
65
267
  }
66
268
  }
67
269
  }
270
+ if (reminderOwners !== undefined) {
271
+ const reminderOwnerFns = reminderOwners;
272
+ for (const [ownerRef, handler] of Object.entries(reminderOwnerFns)) {
273
+ if (!isRecord(handler)) {
274
+ throw new Error(`Invalid app host instance for '${appId}': reminderOwners['${ownerRef}'] must be an object`);
275
+ }
276
+ if (typeof handler['apply'] !== 'function') {
277
+ throw new Error(`Invalid app host instance for '${appId}': reminderOwners['${ownerRef}'].apply must be a function`);
278
+ }
279
+ if (typeof handler['updateReminder'] !== 'function') {
280
+ throw new Error(`Invalid app host instance for '${appId}': reminderOwners['${ownerRef}'].updateReminder must be a function`);
281
+ }
282
+ if (typeof handler['renderReminder'] !== 'function') {
283
+ throw new Error(`Invalid app host instance for '${appId}': reminderOwners['${ownerRef}'].renderReminder must be a function`);
284
+ }
285
+ }
286
+ }
68
287
  return host;
69
288
  }
70
289
  function isValidRunControlResult(result) {
@@ -113,6 +332,15 @@ async function initOnce(msg) {
113
332
  runControlHandlers.set(controlId, { appId, fn });
114
333
  }
115
334
  }
335
+ if (host.reminderOwners) {
336
+ for (const [ownerRef, fn] of Object.entries(host.reminderOwners)) {
337
+ const handlerKey = buildReminderOwnerHandlerKey(appId, ownerRef);
338
+ if (reminderOwnerHandlers.has(handlerKey)) {
339
+ throw new Error(`apps-host: duplicate reminder owner '${ownerRef}' for app '${appId}'`);
340
+ }
341
+ reminderOwnerHandlers.set(handlerKey, { appId, ownerRef, fn });
342
+ }
343
+ }
116
344
  let frontend = null;
117
345
  if (app.installJson.frontend) {
118
346
  if (!host.start) {
@@ -182,8 +410,15 @@ process.on('message', (raw) => {
182
410
  return;
183
411
  }
184
412
  try {
185
- const output = await found.fn(msg.args, msg.ctx);
186
- send({ type: 'tool_result', callId: msg.callId, ok: true, output });
413
+ const result = normalizeToolResult(await found.fn(msg.args, msg.ctx));
414
+ send({
415
+ type: 'tool_result',
416
+ callId: msg.callId,
417
+ ok: true,
418
+ output: result.output,
419
+ reminderRequests: result.reminderRequests,
420
+ dialogReminderRequests: result.dialogReminderRequests,
421
+ });
187
422
  }
188
423
  catch (err) {
189
424
  send({
@@ -229,6 +464,108 @@ process.on('message', (raw) => {
229
464
  }
230
465
  return;
231
466
  }
467
+ case 'reminder_apply': {
468
+ const found = reminderOwnerHandlers.get(buildReminderOwnerHandlerKey(msg.appId, msg.ownerRef));
469
+ if (!found) {
470
+ send({
471
+ type: 'reminder_apply_result',
472
+ callId: msg.callId,
473
+ ok: false,
474
+ errorText: `Unknown reminder owner: ${msg.appId}/${msg.ownerRef}`,
475
+ });
476
+ return;
477
+ }
478
+ try {
479
+ const result = await found.fn.apply(msg.request, msg.ctx);
480
+ if (!isReminderApplyResult(result)) {
481
+ send({
482
+ type: 'reminder_apply_result',
483
+ callId: msg.callId,
484
+ ok: false,
485
+ errorText: `Invalid reminder apply result shape: ${msg.appId}/${msg.ownerRef}`,
486
+ });
487
+ return;
488
+ }
489
+ send({ type: 'reminder_apply_result', callId: msg.callId, ok: true, result });
490
+ }
491
+ catch (err) {
492
+ send({
493
+ type: 'reminder_apply_result',
494
+ callId: msg.callId,
495
+ ok: false,
496
+ errorText: err instanceof Error ? err.message : String(err),
497
+ });
498
+ }
499
+ return;
500
+ }
501
+ case 'reminder_update': {
502
+ const found = reminderOwnerHandlers.get(buildReminderOwnerHandlerKey(msg.appId, msg.ownerRef));
503
+ if (!found) {
504
+ send({
505
+ type: 'reminder_update_result',
506
+ callId: msg.callId,
507
+ ok: false,
508
+ errorText: `Unknown reminder owner: ${msg.appId}/${msg.ownerRef}`,
509
+ });
510
+ return;
511
+ }
512
+ try {
513
+ const result = await found.fn.updateReminder(msg.ctx);
514
+ if (!isReminderUpdateResult(result)) {
515
+ send({
516
+ type: 'reminder_update_result',
517
+ callId: msg.callId,
518
+ ok: false,
519
+ errorText: `Invalid reminder update result shape: ${msg.appId}/${msg.ownerRef}`,
520
+ });
521
+ return;
522
+ }
523
+ send({ type: 'reminder_update_result', callId: msg.callId, ok: true, result });
524
+ }
525
+ catch (err) {
526
+ send({
527
+ type: 'reminder_update_result',
528
+ callId: msg.callId,
529
+ ok: false,
530
+ errorText: err instanceof Error ? err.message : String(err),
531
+ });
532
+ }
533
+ return;
534
+ }
535
+ case 'reminder_render': {
536
+ const found = reminderOwnerHandlers.get(buildReminderOwnerHandlerKey(msg.appId, msg.ownerRef));
537
+ if (!found) {
538
+ send({
539
+ type: 'reminder_render_result',
540
+ callId: msg.callId,
541
+ ok: false,
542
+ errorText: `Unknown reminder owner: ${msg.appId}/${msg.ownerRef}`,
543
+ });
544
+ return;
545
+ }
546
+ try {
547
+ const message = await found.fn.renderReminder(msg.ctx);
548
+ if (!isChatMessage(message)) {
549
+ send({
550
+ type: 'reminder_render_result',
551
+ callId: msg.callId,
552
+ ok: false,
553
+ errorText: `Invalid reminder render result shape: ${msg.appId}/${msg.ownerRef}`,
554
+ });
555
+ return;
556
+ }
557
+ send({ type: 'reminder_render_result', callId: msg.callId, ok: true, message });
558
+ }
559
+ catch (err) {
560
+ send({
561
+ type: 'reminder_render_result',
562
+ callId: msg.callId,
563
+ ok: false,
564
+ errorText: err instanceof Error ? err.message : String(err),
565
+ });
566
+ }
567
+ return;
568
+ }
232
569
  case 'shutdown':
233
570
  await shutdownAll();
234
571
  process.exit(0);