dominds 1.19.3 → 1.20.2

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 (195) hide show
  1. package/README.md +1 -0
  2. package/dist/access-control.js +2 -2
  3. package/dist/dialog.d.ts +6 -1
  4. package/dist/dialog.js +13 -4
  5. package/dist/docs/context-health.md +39 -13
  6. package/dist/docs/context-health.zh.md +14 -7
  7. package/dist/docs/idle-reminder-wake.md +227 -0
  8. package/dist/docs/idle-reminder-wake.zh.md +227 -0
  9. package/dist/llm/client.d.ts +2 -0
  10. package/dist/llm/client.js +32 -2
  11. package/dist/llm/defaults.yaml +51 -10
  12. package/dist/llm/gen/codex.js +15 -0
  13. package/dist/llm/gen/failure-classifier.js +22 -1
  14. package/dist/llm/kernel-driver/drive.js +6 -0
  15. package/dist/llm/kernel-driver/flow.js +9 -0
  16. package/dist/llm/kernel-driver/idle-reminder-wake.d.ts +4 -0
  17. package/dist/llm/kernel-driver/idle-reminder-wake.js +351 -0
  18. package/dist/llm/kernel-driver/types.d.ts +1 -1
  19. package/dist/minds/load.js +2 -1
  20. package/dist/minds/minds-i18n.js +2 -2
  21. package/dist/minds/system-prompt-parts.js +56 -20
  22. package/dist/minds/system-prompt.js +10 -10
  23. package/dist/persistence.js +1 -1
  24. package/dist/runtime/driver-messages.d.ts +3 -0
  25. package/dist/runtime/driver-messages.js +91 -8
  26. package/dist/server/setup-routes.js +5 -5
  27. package/dist/tool.d.ts +8 -0
  28. package/dist/tools/builtins.js +4 -2
  29. package/dist/tools/ctrl.d.ts +2 -0
  30. package/dist/tools/ctrl.js +255 -68
  31. package/dist/tools/os.js +198 -0
  32. package/dist/tools/prompts/control/en/errors.md +2 -2
  33. package/dist/tools/prompts/control/en/index.md +1 -1
  34. package/dist/tools/prompts/control/en/principles.md +21 -14
  35. package/dist/tools/prompts/control/en/scenarios.md +12 -4
  36. package/dist/tools/prompts/control/en/tools.md +45 -5
  37. package/dist/tools/prompts/control/zh/errors.md +2 -2
  38. package/dist/tools/prompts/control/zh/index.md +1 -1
  39. package/dist/tools/prompts/control/zh/principles.md +21 -14
  40. package/dist/tools/prompts/control/zh/scenarios.md +10 -4
  41. package/dist/tools/prompts/control/zh/tools.md +40 -5
  42. package/dist/tools/prompts/personal_memory/en/principles.md +1 -1
  43. package/dist/tools/prompts/personal_memory/zh/principles.md +1 -1
  44. package/dist/tools/prompts/team_memory/en/principles.md +1 -1
  45. package/dist/tools/prompts/team_memory/zh/principles.md +1 -1
  46. package/dist/tools/team_mgmt.js +5 -8
  47. package/dist/utils/task-package.d.ts +7 -0
  48. package/dist/utils/task-package.js +65 -28
  49. package/dist/utils/taskdoc.js +21 -17
  50. package/package.json +4 -4
  51. package/webapp/dist/assets/{_basePickBy-Dnh413xT.js → _basePickBy-B7M9Q0Fa.js} +3 -3
  52. package/webapp/dist/assets/_basePickBy-B7M9Q0Fa.js.map +1 -0
  53. package/webapp/dist/assets/{_baseUniq-DWzYqpN_.js → _baseUniq-DAeYoL6j.js} +2 -2
  54. package/webapp/dist/assets/_baseUniq-DAeYoL6j.js.map +1 -0
  55. package/webapp/dist/assets/{arc-vfBkNCOx.js → arc-Bh4nDbNR.js} +2 -2
  56. package/webapp/dist/assets/arc-Bh4nDbNR.js.map +1 -0
  57. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-DiUEBXOa.js → architectureDiagram-2XIMDMQ5-CxqmdsIm.js} +26 -8
  58. package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-CxqmdsIm.js.map +1 -0
  59. package/webapp/dist/assets/{blockDiagram-VD42YOAC-BqK1KM2m.js → blockDiagram-WCTKOSBZ-CxIWLtpt.js} +187 -170
  60. package/webapp/dist/assets/blockDiagram-WCTKOSBZ-CxIWLtpt.js.map +1 -0
  61. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-ClHNu1Uo.js → c4Diagram-IC4MRINW-1qErOIgG.js} +4 -4
  62. package/webapp/dist/assets/c4Diagram-IC4MRINW-1qErOIgG.js.map +1 -0
  63. package/webapp/dist/assets/{channel-BbWLVc8W.js → channel-DkgZHNUe.js} +2 -2
  64. package/webapp/dist/assets/channel-DkgZHNUe.js.map +1 -0
  65. package/webapp/dist/assets/{chunk-4BX2VUAB-CItdSmZH.js → chunk-4BX2VUAB-BmdMbU9v.js} +2 -2
  66. package/webapp/dist/assets/chunk-4BX2VUAB-BmdMbU9v.js.map +1 -0
  67. package/webapp/dist/assets/{chunk-55IACEB6-DSCX9WCf.js → chunk-55IACEB6-D6LDTDBy.js} +2 -2
  68. package/webapp/dist/assets/chunk-55IACEB6-D6LDTDBy.js.map +1 -0
  69. package/webapp/dist/assets/{chunk-FMBD7UC4-BJ1vT2se.js → chunk-FMBD7UC4-C-BdCe4C.js} +2 -2
  70. package/webapp/dist/assets/chunk-FMBD7UC4-C-BdCe4C.js.map +1 -0
  71. package/webapp/dist/assets/{chunk-TZMSLE5B-D2g6Tj7Z.js → chunk-JSJVCQXG-WA_BLIm9.js} +14 -6
  72. package/webapp/dist/assets/chunk-JSJVCQXG-WA_BLIm9.js.map +1 -0
  73. package/webapp/dist/assets/{chunk-QN33PNHL-CGyezTSD.js → chunk-KX2RTZJC-CA7sDJO5.js} +2 -2
  74. package/webapp/dist/assets/chunk-KX2RTZJC-CA7sDJO5.js.map +1 -0
  75. package/webapp/dist/assets/{chunk-DI55MBZ5-CRMf6XZu.js → chunk-NQ4KR5QH-wlvxalE3.js} +9 -7
  76. package/webapp/dist/assets/chunk-NQ4KR5QH-wlvxalE3.js.map +1 -0
  77. package/webapp/dist/assets/{chunk-QZHKN3VN-9xs15j8C.js → chunk-QZHKN3VN-Bo1VMcph.js} +2 -2
  78. package/webapp/dist/assets/chunk-QZHKN3VN-Bo1VMcph.js.map +1 -0
  79. package/webapp/dist/assets/{chunk-B4BG7PRW-5CRXFeD9.js → chunk-WL4C6EOR-B-Pk44be.js} +171 -121
  80. package/webapp/dist/assets/chunk-WL4C6EOR-B-Pk44be.js.map +1 -0
  81. package/webapp/dist/assets/{classDiagram-2ON5EDUG-BQFGGJNm.js → classDiagram-VBA2DB6C-BqKuyb49.js} +7 -6
  82. package/webapp/dist/assets/classDiagram-VBA2DB6C-BqKuyb49.js.map +1 -0
  83. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-BQFGGJNm.js → classDiagram-v2-RAHNMMFH-BqKuyb49.js} +7 -6
  84. package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-BqKuyb49.js.map +1 -0
  85. package/webapp/dist/assets/{clone-DOfPd4cz.js → clone-BX5z8WVZ.js} +2 -2
  86. package/webapp/dist/assets/clone-BX5z8WVZ.js.map +1 -0
  87. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BYN-vqm8.js → cose-bilkent-S5V4N54A-B-s11SgN.js} +2 -2
  88. package/webapp/dist/assets/cose-bilkent-S5V4N54A-B-s11SgN.js.map +1 -0
  89. package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
  90. package/webapp/dist/assets/{dagre-6UL2VRFP-ClEaFABE.js → dagre-KLK3FWXG-DmQFV2qK.js} +7 -7
  91. package/webapp/dist/assets/dagre-KLK3FWXG-DmQFV2qK.js.map +1 -0
  92. package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
  93. package/webapp/dist/assets/{diagram-PSM6KHXK-CM4hLE_0.js → diagram-E7M64L7V-QRaBfST8.js} +10 -10
  94. package/webapp/dist/assets/diagram-E7M64L7V-QRaBfST8.js.map +1 -0
  95. package/webapp/dist/assets/{diagram-QEK2KX5R-BZjGFX-2.js → diagram-IFDJBPK2-lrWn1Obo.js} +9 -8
  96. package/webapp/dist/assets/diagram-IFDJBPK2-lrWn1Obo.js.map +1 -0
  97. package/webapp/dist/assets/{diagram-S2PKOQOG-Bvw01OOG.js → diagram-P4PSJMXO-sTU7Hh-Y.js} +8 -8
  98. package/webapp/dist/assets/diagram-P4PSJMXO-sTU7Hh-Y.js.map +1 -0
  99. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-ctHu5zQL.js → erDiagram-INFDFZHY-Cx6jc9Wq.js} +96 -75
  100. package/webapp/dist/assets/erDiagram-INFDFZHY-Cx6jc9Wq.js.map +1 -0
  101. package/webapp/dist/assets/{flowDiagram-NV44I4VS-m7ofIhri.js → flowDiagram-PKNHOUZH-DfGI49Dz.js} +98 -81
  102. package/webapp/dist/assets/flowDiagram-PKNHOUZH-DfGI49Dz.js.map +1 -0
  103. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-D9wS5Veb.js → ganttDiagram-A5KZAMGK-nrcHWWaM.js} +28 -3
  104. package/webapp/dist/assets/ganttDiagram-A5KZAMGK-nrcHWWaM.js.map +1 -0
  105. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-B86qqJx7.js → gitGraphDiagram-K3NZZRJ6-D8ivAqd6.js} +38 -46
  106. package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-D8ivAqd6.js.map +1 -0
  107. package/webapp/dist/assets/graph-R5G-y8tB.js +782 -0
  108. package/webapp/dist/assets/graph-R5G-y8tB.js.map +1 -0
  109. package/webapp/dist/assets/{index-tinPEZoH.js → index--fy89xGh.js} +1034 -1059
  110. package/webapp/dist/assets/{index-tinPEZoH.js.map → index--fy89xGh.js.map} +1 -1
  111. package/webapp/dist/assets/{index-BGdI3lWA.css → index-DZFkLLVz.css} +1 -1
  112. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-DwRPUctP.js → infoDiagram-LFFYTUFH-PIoZHr7s.js} +7 -7
  113. package/webapp/dist/assets/infoDiagram-LFFYTUFH-PIoZHr7s.js.map +1 -0
  114. package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
  115. package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-oCM-LYk1.js +966 -0
  116. package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-oCM-LYk1.js.map +1 -0
  117. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-B91ZO-ec.js → journeyDiagram-4ABVD52K-C2qidjQ5.js} +5 -5
  118. package/webapp/dist/assets/journeyDiagram-4ABVD52K-C2qidjQ5.js.map +1 -0
  119. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-CoogrZ07.js → kanban-definition-K7BYSVSG-Du0TC8WS.js} +5 -3
  120. package/webapp/dist/assets/kanban-definition-K7BYSVSG-Du0TC8WS.js.map +1 -0
  121. package/webapp/dist/assets/{layout-BrzQmqFJ.js → layout-VmEo1OEB.js} +5 -5
  122. package/webapp/dist/assets/layout-VmEo1OEB.js.map +1 -0
  123. package/webapp/dist/assets/{linear-C6H7K9Zy.js → linear-B662YHAc.js} +2 -2
  124. package/webapp/dist/assets/linear-B662YHAc.js.map +1 -0
  125. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-UDHZQkNZ.js → mindmap-definition-YRQLILUH-D7arZj95.js} +7 -5
  126. package/webapp/dist/assets/mindmap-definition-YRQLILUH-D7arZj95.js.map +1 -0
  127. package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
  128. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-M81uyQ1J.js → pieDiagram-SKSYHLDU-DvjPP4PA.js} +8 -8
  129. package/webapp/dist/assets/pieDiagram-SKSYHLDU-DvjPP4PA.js.map +1 -0
  130. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-ClzIh9Gb.js → quadrantDiagram-337W2JSQ-B_JUGMj_.js} +3 -3
  131. package/webapp/dist/assets/quadrantDiagram-337W2JSQ-B_JUGMj_.js.map +1 -0
  132. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-DLK3A-pn.js → requirementDiagram-Z7DCOOCP-DF0mpvE3.js} +16 -6
  133. package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-DF0mpvE3.js.map +1 -0
  134. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-CYqju8I1.js → sankeyDiagram-WA2Y5GQK-CoXlxv00.js} +2 -2
  135. package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-CoXlxv00.js.map +1 -0
  136. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-2guv6eOd.js → sequenceDiagram-2WXFIKYE-DYqT5Pg7.js} +601 -201
  137. package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-DYqT5Pg7.js.map +1 -0
  138. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-iujqSp0X.js → stateDiagram-RAJIS63D-D9b1mN8-.js} +9 -9
  139. package/webapp/dist/assets/stateDiagram-RAJIS63D-D9b1mN8-.js.map +1 -0
  140. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-BxzY81ky.js → stateDiagram-v2-FVOUBMTO-DNzgudL_.js} +5 -5
  141. package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-DNzgudL_.js.map +1 -0
  142. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-DjCFSC8d.js → timeline-definition-YZTLITO2-CkyKUY7A.js} +3 -3
  143. package/webapp/dist/assets/timeline-definition-YZTLITO2-CkyKUY7A.js.map +1 -0
  144. package/webapp/dist/assets/{treemap-GDKQZRPO-iaBzDWCP.js → treemap-KZPCXAKY-CZd09kF-.js} +37 -24
  145. package/webapp/dist/assets/treemap-KZPCXAKY-CZd09kF-.js.map +1 -0
  146. package/webapp/dist/assets/vennDiagram-LZ73GAT5-BxVF5Olo.js +2487 -0
  147. package/webapp/dist/assets/vennDiagram-LZ73GAT5-BxVF5Olo.js.map +1 -0
  148. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-R6Jl1c89.js → xychartDiagram-JWTSCODW-BRwRloPc.js} +4 -4
  149. package/webapp/dist/assets/xychartDiagram-JWTSCODW-BRwRloPc.js.map +1 -0
  150. package/webapp/dist/index.html +2 -2
  151. package/webapp/dist/assets/_basePickBy-Dnh413xT.js.map +0 -1
  152. package/webapp/dist/assets/_baseUniq-DWzYqpN_.js.map +0 -1
  153. package/webapp/dist/assets/arc-vfBkNCOx.js.map +0 -1
  154. package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DiUEBXOa.js.map +0 -1
  155. package/webapp/dist/assets/blockDiagram-VD42YOAC-BqK1KM2m.js.map +0 -1
  156. package/webapp/dist/assets/c4Diagram-YG6GDRKO-ClHNu1Uo.js.map +0 -1
  157. package/webapp/dist/assets/channel-BbWLVc8W.js.map +0 -1
  158. package/webapp/dist/assets/chunk-4BX2VUAB-CItdSmZH.js.map +0 -1
  159. package/webapp/dist/assets/chunk-55IACEB6-DSCX9WCf.js.map +0 -1
  160. package/webapp/dist/assets/chunk-B4BG7PRW-5CRXFeD9.js.map +0 -1
  161. package/webapp/dist/assets/chunk-DI55MBZ5-CRMf6XZu.js.map +0 -1
  162. package/webapp/dist/assets/chunk-FMBD7UC4-BJ1vT2se.js.map +0 -1
  163. package/webapp/dist/assets/chunk-QN33PNHL-CGyezTSD.js.map +0 -1
  164. package/webapp/dist/assets/chunk-QZHKN3VN-9xs15j8C.js.map +0 -1
  165. package/webapp/dist/assets/chunk-TZMSLE5B-D2g6Tj7Z.js.map +0 -1
  166. package/webapp/dist/assets/classDiagram-2ON5EDUG-BQFGGJNm.js.map +0 -1
  167. package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-BQFGGJNm.js.map +0 -1
  168. package/webapp/dist/assets/clone-DOfPd4cz.js.map +0 -1
  169. package/webapp/dist/assets/cose-bilkent-S5V4N54A-BYN-vqm8.js.map +0 -1
  170. package/webapp/dist/assets/dagre-6UL2VRFP-ClEaFABE.js.map +0 -1
  171. package/webapp/dist/assets/diagram-PSM6KHXK-CM4hLE_0.js.map +0 -1
  172. package/webapp/dist/assets/diagram-QEK2KX5R-BZjGFX-2.js.map +0 -1
  173. package/webapp/dist/assets/diagram-S2PKOQOG-Bvw01OOG.js.map +0 -1
  174. package/webapp/dist/assets/erDiagram-Q2GNP2WA-ctHu5zQL.js.map +0 -1
  175. package/webapp/dist/assets/flowDiagram-NV44I4VS-m7ofIhri.js.map +0 -1
  176. package/webapp/dist/assets/ganttDiagram-JELNMOA3-D9wS5Veb.js.map +0 -1
  177. package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-B86qqJx7.js.map +0 -1
  178. package/webapp/dist/assets/graph-u844GGQC.js +0 -425
  179. package/webapp/dist/assets/graph-u844GGQC.js.map +0 -1
  180. package/webapp/dist/assets/infoDiagram-HS3SLOUP-DwRPUctP.js.map +0 -1
  181. package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-B91ZO-ec.js.map +0 -1
  182. package/webapp/dist/assets/kanban-definition-3W4ZIXB7-CoogrZ07.js.map +0 -1
  183. package/webapp/dist/assets/layout-BrzQmqFJ.js.map +0 -1
  184. package/webapp/dist/assets/linear-C6H7K9Zy.js.map +0 -1
  185. package/webapp/dist/assets/mindmap-definition-VGOIOE7T-UDHZQkNZ.js.map +0 -1
  186. package/webapp/dist/assets/pieDiagram-ADFJNKIX-M81uyQ1J.js.map +0 -1
  187. package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-ClzIh9Gb.js.map +0 -1
  188. package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-DLK3A-pn.js.map +0 -1
  189. package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-CYqju8I1.js.map +0 -1
  190. package/webapp/dist/assets/sequenceDiagram-WL72ISMW-2guv6eOd.js.map +0 -1
  191. package/webapp/dist/assets/stateDiagram-FKZM4ZOC-iujqSp0X.js.map +0 -1
  192. package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3-BxzY81ky.js.map +0 -1
  193. package/webapp/dist/assets/timeline-definition-IT6M3QCI-DjCFSC8d.js.map +0 -1
  194. package/webapp/dist/assets/treemap-GDKQZRPO-iaBzDWCP.js.map +0 -1
  195. package/webapp/dist/assets/xychartDiagram-PRI3JC2R-R6Jl1c89.js.map +0 -1
@@ -0,0 +1,227 @@
1
+ # Idle reminder wake 设计
2
+
3
+ 英文版:[English](./idle-reminder-wake.md)
4
+
5
+ 本文定义一种 driver 级后台协程机制:当对话进入 `idle_waiting_user` 后,runtime 可以等待 reminder owner 产生的可唤醒事件;若事件到达时对话仍处于 idle,则把事件打包成一条 `role=user` 的系统提示消息,并继续驱动对话。
6
+
7
+ 本文是设计文档。它描述业务语义、owner 接口、取消模型与当前落地场景,不规定最终代码拆分。
8
+
9
+ ---
10
+
11
+ ## 背景
12
+
13
+ 现有 reminder owner 已负责维护提醒项的真实语义,例如 `shell_cmd` daemon reminder 能在下一次 reminder 更新时发现 daemon 已退出,并把提醒项更新为终态。
14
+
15
+ 但这条链路有一个缺口:如果 daemon 在对话 idle 期间退出,系统只会在下一次打开对话、显示 reminders 或新一轮 drive 时发现。对用户而言,长期运行的 shell 命令已经完成,但对话没有被自动唤醒,也不会主动说明进程已退出。
16
+
17
+ 这个问题不应由 `shell_cmd` 工具直接驱动对话解决。driver 是唯一应决定对话是否继续运行的组件;reminder owner 只负责解释自己拥有的 reminder 何时产生了值得唤醒模型的环境事件。
18
+
19
+ ---
20
+
21
+ ## 目标
22
+
23
+ - 在对话真正进入 `idle_waiting_user` 后,启动一个可取消的后台 await 协程。
24
+ - 允许 reminder owner 暴露“可唤醒事件”,例如 daemon exited。
25
+ - 事件到达时先短暂聚合,再形成一条 runtime `role=user` 系统提示消息。
26
+ - 若聚合完成后对话仍是 idle,使用普通 driver 路径继续驱动。
27
+ - 任意新的继续驱动动作都取消已有 idle await 协程。
28
+ - 保持 owner metadata 语义封装:framework 只按 owner 路由,不偷看 owner meta。
29
+ - 保证幂等:同一个环境事件不能重复插入系统提示。
30
+
31
+ ## 非目标
32
+
33
+ - 不把普通 reminder 内容变更都视为唤醒信号。
34
+ - 不让 reminder owner 直接调用 `driveDialogStream`。
35
+ - 不把 idle await 协程纳入 `activeRun`,以免 UI 把等待环境事件误判为 proceeding。
36
+ - 不在对话 blocked、stopped、dead 或 completed/archived 时自动唤醒。
37
+ - 不把 daemon stdout/stderr 的每次增长都作为唤醒事件;当前场景只处理 daemon lifecycle exit。
38
+
39
+ ---
40
+
41
+ ## 核心结论
42
+
43
+ ### 1. Driver 拥有 idle wake 生命周期
44
+
45
+ 当 `driveDialogStreamCore` 最终把 display state 设置为 `idle_waiting_user` 后,driver 外层启动一个 dialog-scoped idle wake task。
46
+
47
+ 该 task:
48
+
49
+ - 不持有 dialog mutex
50
+ - 不创建 active run
51
+ - 不改变 display state
52
+ - 只等待 owner 提供的 wake event
53
+ - 在新一轮 drive 开始前被取消
54
+
55
+ 这样可以保证“等待环境事件”不是“正在工作”,也不会抢占用户可见的运行控制语义。
56
+
57
+ ### 2. Reminder owner 只报告 wake event
58
+
59
+ `ReminderOwner` 增加可选接口:
60
+
61
+ ```ts
62
+ export type ReminderWakeEvent = Readonly<{
63
+ eventId: string;
64
+ reminderId: string;
65
+ content: string;
66
+ updatedContent?: string;
67
+ updatedMeta?: JsonValue;
68
+ }>;
69
+
70
+ export interface ReminderOwner {
71
+ readonly name: string;
72
+ updateReminder(dlg: Dialog, reminder: Reminder): Promise<ReminderUpdateResult>;
73
+ renderReminder(dlg: Dialog, reminder: Reminder): Promise<ChatMessage>;
74
+
75
+ waitForReminderWakeEvent?(
76
+ dlg: Dialog,
77
+ reminders: readonly Reminder[],
78
+ signal: AbortSignal,
79
+ ): Promise<ReminderWakeEvent | readonly ReminderWakeEvent[] | null>;
80
+ }
81
+ ```
82
+
83
+ `content` 是 owner 已经格式化好的系统提示正文,必须以 `【系统提示】` / `[System notice]` 开头。它不是用户真实输入,但当前 provider role 限制下会经 runtime prompt 路径持久化为 `role=user` 消息。
84
+
85
+ `eventId` 是 owner 范围内稳定幂等键。owner 必须能在 reminder meta 或 owner 自己的状态中记录该事件已经投递,防止重复 wake。
86
+
87
+ ### 3. 首个事件到达后进入短聚合窗口
88
+
89
+ driver 不应在第一个 wake event 到达后立刻 drive。它应:
90
+
91
+ 1. await 到第一个 wake event
92
+ 2. 打开一个约 500ms 的聚合窗口
93
+ 3. 收集同一 dialog 当前 idle wake task 下其它 owner/reminder 已经到达的 wake event
94
+ 4. 对收集到的事件做稳定排序与去重
95
+ 5. 打包形成一条 runtime prompt
96
+
97
+ 这样可以避免多个 daemon 在相近时间退出时连续触发多轮 drive。用户和模型看到的是一条合并的环境状态消息,而不是多条碎片化系统提示。
98
+
99
+ ### 4. Wake 后必须重新检查真实状态
100
+
101
+ 聚合窗口结束后,driver 必须重新从 persistence 检查:
102
+
103
+ - dialog 仍存在且 status 为 running
104
+ - display state 仍是 `idle_waiting_user`
105
+ - execution marker 不是 dead,也不是需要人工 resume 的 interrupted
106
+ - 没有 pending Q4H
107
+ - 没有 blocking pending sideDialog
108
+ - 当前没有 active run
109
+
110
+ 只有这些条件都满足,才允许以 wake prompt 继续驱动。否则丢弃本次 wake,并只保留 owner 的幂等/状态更新。
111
+
112
+ ### 5. 任意 drive 都取消 idle wake task
113
+
114
+ 进入任何新 drive 前,runtime 必须取消该 dialog 已存在的 idle wake task。包括:
115
+
116
+ - 用户发送新消息
117
+ - 手动 Continue / Resume All
118
+ - Q4H answer 恢复
119
+ - sideDialog response 恢复
120
+ - Diligence Push / 其它 runtime auto-drive
121
+ - 本机制自己的 wake drive
122
+
123
+ 取消后,旧 task 即使有 promise resolve,也不得产生副作用。
124
+
125
+ ---
126
+
127
+ ## Wake 消息格式
128
+
129
+ owner event 的 `content` 应聚焦事实,不给模型伪造用户诉求。
130
+
131
+ daemon exit 示例:
132
+
133
+ ```text
134
+ 【系统提示】
135
+ 后台进程已退出。这是 runtime 环境事件,不是新的用户指令。
136
+
137
+ - PID: 12345
138
+ - 命令: pnpm run build
139
+ - 退出状态: code 0, signal null
140
+
141
+ 请根据当前任务上下文判断是否需要查看最终 stdout/stderr 或向用户汇报结果;不要只回复“收到”。
142
+ ```
143
+
144
+ driver 聚合多条事件时,应保留每条事件的事实块,并加一个总前缀:
145
+
146
+ ```text
147
+ 【系统提示】
148
+ 以下是对话空闲期间发生的 runtime 环境事件。这些事件不是新的用户指令。
149
+
150
+ 1. 后台进程已退出 ...
151
+ 2. 后台进程已退出 ...
152
+
153
+ 请结合当前任务上下文继续推进;若这些事件不影响当前工作,不要发送占位式确认。
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Shell daemon exit 当前落地场景
159
+
160
+ `shellCmdReminderOwner` 实现 `waitForReminderWakeEvent`。
161
+
162
+ 语义:
163
+
164
+ - 只关注该 owner 拥有的 daemon reminders。
165
+ - 只在 daemon 从 running 进入 exited/gone 时产生 wake event。
166
+ - stdout/stderr 增长不产生 wake event。
167
+ - 如果 reminder meta 已标记对应 exit event 已投递,则返回 `null`。
168
+ - event 到达后,owner 同时提供终态 reminder 的 `updatedContent` / `updatedMeta`,由 driver 在投递 wake 前持久化。
169
+
170
+ 需要补充的 meta:
171
+
172
+ - `originRootId`:恢复 origin dialog 时必须知道 root。
173
+ - `originDialogId`:已有字段,继续表示 self id。
174
+ - `exitWakeEventId`:稳定事件 id,例如 `shellCmd:daemonExited:<pid>:<startTime>`。
175
+ - `exitWakeNotifiedAt`:该事件已被 runtime 采纳并投递的时间。
176
+
177
+ daemon runner 如果能提供可 await 的 exit 信号,应优先使用;如果当前只能通过本地 IPC 状态检查实现,轮询必须封装在 owner 内部,driver 不承担 daemon 专属扫描逻辑。
178
+
179
+ ---
180
+
181
+ ## 取消与并发模型
182
+
183
+ 每个 dialog 最多一个 idle wake task。
184
+
185
+ 建议 runtime 维护:
186
+
187
+ ```ts
188
+ type IdleReminderWakeTask = Readonly<{
189
+ dialogKey: string;
190
+ controller: AbortController;
191
+ startedAt: string;
192
+ }>;
193
+ ```
194
+
195
+ 新 drive preflight 的第一步取消旧 task。取消是幂等的。
196
+
197
+ idle wake task resolve 后也必须再次检查自己仍是当前 task;如果已经被替换或取消,直接返回。
198
+
199
+ ---
200
+
201
+ ## 崩溃恢复
202
+
203
+ idle wake task 本身不持久化。后端重启后不会恢复“正在等待”的 promise。
204
+
205
+ 恢复后的首次正常 driver/display/reminder 更新仍会修正 reminder 终态。若需要重启后也主动唤醒 idle dialog,可以补充“启动时对 running idle dialogs 重新安装 idle wake task”的 bootstrap。该能力不是当前机制闭环的必要条件。
206
+
207
+ ---
208
+
209
+ ## 观测与错误处理
210
+
211
+ owner wait 接口必须 loud by default:
212
+
213
+ - 非取消错误应 structured log,字段包含 `rootId`、`selfId`、`ownerName`、`reminderId`、`eventId`(若有)。
214
+ - owner 不得吞掉不合理状态,例如重复 event id 与不同内容冲突。
215
+ - driver 若发现聚合后的状态不允许 revive,应记录 debug/warn 级别诊断,但不应把被丢弃的 wake 作为用户可见消息。
216
+
217
+ ---
218
+
219
+ ## 实现顺序
220
+
221
+ 1. 增加 `ReminderWakeEvent` 与 `ReminderOwner.waitForReminderWakeEvent?` 类型。
222
+ 2. 增加 driver 侧 idle wake task 管理:start/cancel/race/500ms 聚合/状态复检。
223
+ 3. 在所有 drive 入口 preflight 取消该 dialog 的 idle wake task。
224
+ 4. 在 driver 最终落到 `idle_waiting_user` 后启动 idle wake task。
225
+ 5. 实现 `shellCmdReminderOwner` 的 daemon exit wake event。
226
+ 6. 为 daemon reminder meta 补充 `originRootId` 与 wake 幂等字段。
227
+ 7. 补测试:单 daemon 退出唤醒、多 daemon 500ms 聚合、用户消息取消、blocked 不唤醒、幂等不重复。
@@ -80,3 +80,5 @@ export declare class LlmConfig {
80
80
  export declare namespace LlmConfig {
81
81
  function load(): Promise<LlmConfig>;
82
82
  }
83
+ export declare function getBuiltinDefaultsYamlPath(): string;
84
+ export declare function readBuiltinDefaultsYamlRaw(): Promise<string>;
@@ -4,10 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LlmConfig = void 0;
7
+ exports.getBuiltinDefaultsYamlPath = getBuiltinDefaultsYamlPath;
8
+ exports.readBuiltinDefaultsYamlRaw = readBuiltinDefaultsYamlRaw;
7
9
  const promises_1 = __importDefault(require("fs/promises"));
8
10
  const path_1 = __importDefault(require("path"));
9
11
  const yaml_1 = __importDefault(require("yaml"));
10
12
  const log_1 = require("../log");
13
+ const BUILTIN_DEFAULTS_YAML_PATH = path_1.default.join(__dirname, 'defaults.yaml');
14
+ // Special-case cache: built-in defaults are immutable at runtime, so this file may be cached
15
+ // forever to survive dogfooding rebuild windows. Do not generalize this to rtws/user-editable files.
16
+ let builtinDefaultsYamlRawCache;
17
+ let builtinDefaultsYamlRawReadPromise;
11
18
  /**
12
19
  * LlmConfig
13
20
  *
@@ -28,8 +35,7 @@ exports.LlmConfig = LlmConfig;
28
35
  (function (LlmConfig) {
29
36
  async function load() {
30
37
  // Load default providers from YAML file
31
- const defaultsPath = path_1.default.join(__dirname, 'defaults.yaml');
32
- const rawDefaults = await promises_1.default.readFile(defaultsPath, 'utf-8');
38
+ const rawDefaults = await readBuiltinDefaultsYamlRaw();
33
39
  const parsedDefaults = yaml_1.default.parse(rawDefaults);
34
40
  if (!isRecord(parsedDefaults) || !isRecord(parsedDefaults.providers)) {
35
41
  throw new Error('Invalid defaults.yaml: expected providers object');
@@ -64,6 +70,30 @@ exports.LlmConfig = LlmConfig;
64
70
  }
65
71
  LlmConfig.load = load;
66
72
  })(LlmConfig || (exports.LlmConfig = LlmConfig = {}));
73
+ function getBuiltinDefaultsYamlPath() {
74
+ return BUILTIN_DEFAULTS_YAML_PATH;
75
+ }
76
+ async function readBuiltinDefaultsYamlRaw() {
77
+ if (builtinDefaultsYamlRawCache !== undefined)
78
+ return builtinDefaultsYamlRawCache;
79
+ if (builtinDefaultsYamlRawReadPromise === undefined) {
80
+ builtinDefaultsYamlRawReadPromise = promises_1.default
81
+ .readFile(BUILTIN_DEFAULTS_YAML_PATH, 'utf-8')
82
+ .then((raw) => {
83
+ const parsed = yaml_1.default.parse(raw);
84
+ if (!isRecord(parsed) || !isRecord(parsed.providers)) {
85
+ throw new Error('Invalid defaults.yaml: expected providers object');
86
+ }
87
+ builtinDefaultsYamlRawCache = raw;
88
+ return raw;
89
+ })
90
+ .catch((error) => {
91
+ builtinDefaultsYamlRawReadPromise = undefined;
92
+ throw error;
93
+ });
94
+ }
95
+ return builtinDefaultsYamlRawReadPromise;
96
+ }
67
97
  function isRecord(value) {
68
98
  return typeof value === 'object' && value !== null;
69
99
  }
@@ -100,6 +100,15 @@ providers:
100
100
  min: 1
101
101
  description: Provider-specific max tokens override.
102
102
  models:
103
+ gpt-5.5:
104
+ name: GPT-5.5
105
+ optimal_max_tokens: 200000
106
+ # Caution remediation reinjection cadence in generation turns (default: 10).
107
+ caution_remediation_cadence_generations: 10
108
+ context_length: 272000
109
+ input_length: 272000
110
+ output_length: 32768
111
+ context_window: '272K'
103
112
  gpt-5.4:
104
113
  name: GPT-5.4
105
114
  optimal_max_tokens: 200000
@@ -653,20 +662,34 @@ providers:
653
662
  type: boolean
654
663
  description: Supported via thinking field (budget_tokens is ignored by DeepSeek).
655
664
  models:
665
+ deepseek-v4-flash:
666
+ name: DeepSeek-V4-Flash
667
+ supports_image_input: false
668
+ context_length: 1000000
669
+ input_length: 1000000
670
+ output_length: 384000
671
+ context_window: '1M'
672
+ deepseek-v4-pro:
673
+ name: DeepSeek-V4-Pro
674
+ supports_image_input: false
675
+ context_length: 1000000
676
+ input_length: 1000000
677
+ output_length: 384000
678
+ context_window: '1M'
656
679
  deepseek-chat:
657
- name: DeepSeek-V3.2
680
+ name: DeepSeek-V4-Flash (non-thinking alias)
658
681
  supports_image_input: false
659
- context_length: 128000
660
- input_length: 128000
661
- output_length: 8192
662
- context_window: '128K'
682
+ context_length: 1000000
683
+ input_length: 1000000
684
+ output_length: 384000
685
+ context_window: '1M'
663
686
  deepseek-reasoner:
664
- name: DeepSeek-R1 (reasoner, V3.2 thinking mode)
687
+ name: DeepSeek-V4-Flash (thinking alias)
665
688
  supports_image_input: false
666
- context_length: 128000
667
- input_length: 128000
668
- output_length: 65536
669
- context_window: '128K'
689
+ context_length: 1000000
690
+ input_length: 1000000
691
+ output_length: 384000
692
+ context_window: '1M'
670
693
  aliyun-bailian:
671
694
  name: Aliyun Bailian Coding Plan
672
695
  apiType: anthropic
@@ -846,6 +869,24 @@ providers:
846
869
  min: 1
847
870
  description: Provider-specific max tokens override.
848
871
  models:
872
+ gpt-5.5:
873
+ name: GPT-5.5
874
+ optimal_max_tokens: 200000
875
+ # Caution remediation reinjection cadence in generation turns (default: 10).
876
+ caution_remediation_cadence_generations: 10
877
+ context_length: 272000
878
+ input_length: 272000
879
+ output_length: 32768
880
+ context_window: '272K'
881
+ gpt-5.5-pro:
882
+ name: GPT-5.5 Pro
883
+ optimal_max_tokens: 600000
884
+ # Caution remediation reinjection cadence in generation turns (default: 10).
885
+ caution_remediation_cadence_generations: 10
886
+ context_length: 1000000
887
+ input_length: 1000000
888
+ output_length: 128000
889
+ context_window: '1M'
849
890
  gpt-5.4:
850
891
  name: GPT-5.4
851
892
  optimal_max_tokens: 200000
@@ -654,6 +654,21 @@ class CodexGen {
654
654
  // NOTE: `@longrun-ai/codex-auth` is an ESM package (`"type": "module"`). The Dominds backend is
655
655
  // compiled as CommonJS, so Node.js requires a dynamic `import()` for runtime access here.
656
656
  const codexAuth = await Promise.resolve().then(() => __importStar(require('@longrun-ai/codex-auth')));
657
+ const authPreparation = codexAuth.prepareCodexFileAuth({
658
+ codexHome,
659
+ codexHomeEnvVar: providerConfig.apiKeyEnvVar,
660
+ providerName: `Dominds codex provider '${providerConfig.name}'`,
661
+ });
662
+ if (authPreparation.kind === 'action_required') {
663
+ throw new Error(codexAuth.formatCodexFileAuthActionRequired(authPreparation));
664
+ }
665
+ if (authPreparation.changedConfigToFile) {
666
+ log.info('Codex CLI auth storage switched to file mode for Dominds codex provider', undefined, {
667
+ codexHome: authPreparation.codexHome,
668
+ configPath: authPreparation.configPath,
669
+ previousStoreMode: authPreparation.previousStoreMode,
670
+ });
671
+ }
657
672
  const manager = new codexAuth.AuthManager({ codexHome });
658
673
  const client = await codexAuth.createChatGptClientFromManager(manager, {
659
674
  baseUrl: providerConfig.baseUrl,
@@ -234,6 +234,25 @@ function isOpenAiLikeRejectedFailure(error) {
234
234
  const status = readErrorStatus(error);
235
235
  return isHighConfidenceRejectedStatus(status);
236
236
  }
237
+ function isOpenAiLikeContextWindowRejectedFailure(args) {
238
+ if (args.lowerCode === 'context_length_exceeded') {
239
+ return true;
240
+ }
241
+ if (args.lowerMessage.includes('context window') &&
242
+ (args.lowerMessage.includes('exceeds') || args.lowerMessage.includes('exceeded'))) {
243
+ return true;
244
+ }
245
+ if (args.lowerMessage.includes('context limit exceeded')) {
246
+ return true;
247
+ }
248
+ if (args.lowerMessage.includes('maximum context length')) {
249
+ return true;
250
+ }
251
+ if (args.lowerMessage.includes('context_length_exceeded')) {
252
+ return true;
253
+ }
254
+ return args.lowerMessage.includes('too many tokens') && args.lowerMessage.includes('context');
255
+ }
237
256
  function isOpenAiLikeRateLimitFailure(error) {
238
257
  const lowerMessage = buildFailureMessage(error).toLowerCase();
239
258
  const status = readErrorStatus(error);
@@ -267,7 +286,9 @@ function classifyOpenAiLikeFailure(error) {
267
286
  const lowerMessage = message.toLowerCase();
268
287
  const status = readErrorStatus(error);
269
288
  const code = readErrorCode(error);
270
- if (isOpenAiLikeRejectedFailure(error)) {
289
+ const lowerCode = typeof code === 'string' ? code.trim().toLowerCase() : undefined;
290
+ if (isOpenAiLikeRejectedFailure(error) ||
291
+ isOpenAiLikeContextWindowRejectedFailure({ lowerMessage, lowerCode })) {
271
292
  return {
272
293
  kind: 'rejected',
273
294
  message,
@@ -1189,14 +1189,17 @@ async function maybeContinueWithHealthPromptBeforeDiligence(args) {
1189
1189
  return { kind: 'health_continue', prompt: nextPrompt, resetTaskdoc: true };
1190
1190
  }
1191
1191
  const language = (0, work_language_1.getWorkLanguage)();
1192
+ const dialogScope = dlg instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
1192
1193
  const guideText = healthDecision.reason === 'caution_soft_remediation'
1193
1194
  ? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1194
1195
  kind: 'caution',
1195
1196
  mode: 'soft',
1197
+ dialogScope,
1196
1198
  })
1197
1199
  : (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1198
1200
  kind: 'critical',
1199
1201
  mode: 'countdown',
1202
+ dialogScope,
1200
1203
  promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
1201
1204
  promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
1202
1205
  });
@@ -1381,14 +1384,17 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1381
1384
  }
1382
1385
  else if (!hasQueuedUpNext) {
1383
1386
  const language = (0, work_language_1.getWorkLanguage)();
1387
+ const dialogScope = dlg instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
1384
1388
  const guideText = healthDecision.reason === 'caution_soft_remediation'
1385
1389
  ? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1386
1390
  kind: 'caution',
1387
1391
  mode: 'soft',
1392
+ dialogScope,
1388
1393
  })
1389
1394
  : (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1390
1395
  kind: 'critical',
1391
1396
  mode: 'countdown',
1397
+ dialogScope,
1392
1398
  promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
1393
1399
  promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
1394
1400
  });
@@ -19,6 +19,7 @@ const client_1 = require("../client");
19
19
  const context_health_1 = require("./context-health");
20
20
  const drive_1 = require("./drive");
21
21
  const guardrails_1 = require("./guardrails");
22
+ const idle_reminder_wake_1 = require("./idle-reminder-wake");
22
23
  const reply_guidance_1 = require("./reply-guidance");
23
24
  const sideDialog_1 = require("./sideDialog");
24
25
  const tellask_special_1 = require("./tellask-special");
@@ -459,6 +460,7 @@ async function resolveEffectivePrompt(dialog, humanPrompt) {
459
460
  }
460
461
  async function executeDriveRound(args) {
461
462
  const [dialog, humanPrompt, waitInQue, driveOptions] = args.driveArgs;
463
+ (0, idle_reminder_wake_1.cancelIdleReminderWake)(dialog.id, driveOptions?.reason ?? 'drive_start');
462
464
  if (!waitInQue && dialog.isLocked()) {
463
465
  throw new Error('Dialog busy driven, see how it proceeded and try again.');
464
466
  }
@@ -681,14 +683,17 @@ async function executeDriveRound(args) {
681
683
  }
682
684
  else if (!hasQueuedUpNext) {
683
685
  const language = (0, work_language_1.getWorkLanguage)();
686
+ const dialogScope = dialog instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
684
687
  const guideText = healthDecision.reason === 'caution_soft_remediation'
685
688
  ? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
686
689
  kind: 'caution',
687
690
  mode: 'soft',
691
+ dialogScope,
688
692
  })
689
693
  : (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
690
694
  kind: 'critical',
691
695
  mode: 'countdown',
696
+ dialogScope,
692
697
  promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dialog.id.key()),
693
698
  promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
694
699
  });
@@ -1077,5 +1082,9 @@ async function executeDriveRound(args) {
1077
1082
  (0, dialog_display_state_1.clearActiveRun)(dialog.id);
1078
1083
  }
1079
1084
  release();
1085
+ (0, idle_reminder_wake_1.maybeStartIdleReminderWake)(dialog, {
1086
+ scheduleDrive: args.scheduleDrive,
1087
+ driveDialog: args.driveDialog,
1088
+ }, driveOptions?.reason ?? 'drive_finished');
1080
1089
  }
1081
1090
  }
@@ -0,0 +1,4 @@
1
+ import { Dialog, DialogID } from '../../dialog';
2
+ import type { KernelDriverDriveCallbacks } from './types';
3
+ export declare function cancelIdleReminderWake(dialogId: DialogID, reason: string): void;
4
+ export declare function maybeStartIdleReminderWake(dialog: Dialog, callbacks: KernelDriverDriveCallbacks, reason: string): void;