dominds 1.20.2 → 1.20.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +4 -4
  2. package/README.zh.md +2 -2
  3. package/dist/access-control.js +2 -2
  4. package/dist/cli/webui.d.ts +1 -1
  5. package/dist/cli/webui.js +29 -9
  6. package/dist/docs/OEC-philosophy.md +1 -1
  7. package/dist/docs/cli-usage.md +2 -1
  8. package/dist/docs/cli-usage.zh.md +6 -3
  9. package/dist/docs/context-health.md +2 -2
  10. package/dist/docs/context-health.zh.md +2 -2
  11. package/dist/docs/design.md +3 -3
  12. package/dist/docs/design.zh.md +3 -3
  13. package/dist/docs/dialog-system.md +18 -10
  14. package/dist/docs/dialog-system.zh.md +18 -10
  15. package/dist/docs/dominds-terminology.md +4 -4
  16. package/dist/docs/encapsulated-taskdoc.md +17 -10
  17. package/dist/docs/encapsulated-taskdoc.zh.md +18 -11
  18. package/dist/minds/load.js +15 -4
  19. package/dist/minds/minds-i18n.js +2 -2
  20. package/dist/minds/system-prompt-parts.js +11 -11
  21. package/dist/runtime/driver-messages.js +8 -4
  22. package/dist/server/api-routes.js +65 -0
  23. package/dist/server/port-selection.d.ts +19 -0
  24. package/dist/server/port-selection.js +57 -0
  25. package/dist/server/server-core.d.ts +2 -2
  26. package/dist/server/server-core.js +21 -7
  27. package/dist/server/static-server.js +1 -0
  28. package/dist/server.d.ts +3 -0
  29. package/dist/server.js +109 -44
  30. package/dist/team.d.ts +2 -3
  31. package/dist/team.js +17 -4
  32. package/dist/tools/builtins.js +5 -0
  33. package/dist/tools/ctrl.d.ts +11 -7
  34. package/dist/tools/ctrl.js +248 -34
  35. package/dist/tools/prompts/control/en/errors.md +2 -2
  36. package/dist/tools/prompts/control/en/index.md +1 -1
  37. package/dist/tools/prompts/control/en/principles.md +14 -12
  38. package/dist/tools/prompts/control/en/tools.md +40 -6
  39. package/dist/tools/prompts/control/zh/errors.md +2 -2
  40. package/dist/tools/prompts/control/zh/index.md +1 -1
  41. package/dist/tools/prompts/control/zh/principles.md +14 -12
  42. package/dist/tools/prompts/control/zh/tools.md +40 -6
  43. package/dist/tools/prompts/personal_memory/en/principles.md +1 -1
  44. package/dist/tools/prompts/personal_memory/zh/principles.md +1 -1
  45. package/dist/tools/prompts/team_memory/en/principles.md +1 -1
  46. package/dist/tools/prompts/team_memory/zh/principles.md +1 -1
  47. package/dist/tools/registry.d.ts +6 -0
  48. package/dist/tools/team_mgmt.js +5 -5
  49. package/dist/utils/task-package.d.ts +24 -1
  50. package/dist/utils/task-package.js +80 -5
  51. package/dist/utils/taskdoc-search-worker-client.d.ts +12 -0
  52. package/dist/utils/taskdoc-search-worker-client.js +320 -0
  53. package/dist/utils/taskdoc-search-worker.d.ts +1 -0
  54. package/dist/utils/taskdoc-search-worker.js +42 -0
  55. package/dist/utils/taskdoc-search.d.ts +28 -7
  56. package/dist/utils/taskdoc-search.js +62 -15
  57. package/dist/utils/taskdoc.js +60 -22
  58. package/package.json +3 -3
  59. package/webapp/dist/assets/{_basePickBy-B7M9Q0Fa.js → _basePickBy-BrC49DPW.js} +3 -3
  60. package/webapp/dist/assets/{_basePickBy-B7M9Q0Fa.js.map → _basePickBy-BrC49DPW.js.map} +1 -1
  61. package/webapp/dist/assets/{_baseUniq-DAeYoL6j.js → _baseUniq-C_Wcx-_S.js} +2 -2
  62. package/webapp/dist/assets/{_baseUniq-DAeYoL6j.js.map → _baseUniq-C_Wcx-_S.js.map} +1 -1
  63. package/webapp/dist/assets/{arc-Bh4nDbNR.js → arc-X5iIdpx0.js} +2 -2
  64. package/webapp/dist/assets/{arc-Bh4nDbNR.js.map → arc-X5iIdpx0.js.map} +1 -1
  65. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CxqmdsIm.js → architectureDiagram-2XIMDMQ5-DFfhMGkT.js} +7 -7
  66. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CxqmdsIm.js.map → architectureDiagram-2XIMDMQ5-DFfhMGkT.js.map} +1 -1
  67. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CxIWLtpt.js → blockDiagram-WCTKOSBZ-BAt4BaxZ.js} +7 -7
  68. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CxIWLtpt.js.map → blockDiagram-WCTKOSBZ-BAt4BaxZ.js.map} +1 -1
  69. package/webapp/dist/assets/{c4Diagram-IC4MRINW-1qErOIgG.js → c4Diagram-IC4MRINW-BYxKH5AA.js} +3 -3
  70. package/webapp/dist/assets/{c4Diagram-IC4MRINW-1qErOIgG.js.map → c4Diagram-IC4MRINW-BYxKH5AA.js.map} +1 -1
  71. package/webapp/dist/assets/{channel-DkgZHNUe.js → channel-CuYhL59H.js} +2 -2
  72. package/webapp/dist/assets/{channel-DkgZHNUe.js.map → channel-CuYhL59H.js.map} +1 -1
  73. package/webapp/dist/assets/{chunk-4BX2VUAB-BmdMbU9v.js → chunk-4BX2VUAB-Ch1PfLiD.js} +2 -2
  74. package/webapp/dist/assets/{chunk-4BX2VUAB-BmdMbU9v.js.map → chunk-4BX2VUAB-Ch1PfLiD.js.map} +1 -1
  75. package/webapp/dist/assets/{chunk-55IACEB6-D6LDTDBy.js → chunk-55IACEB6-B3rzakPd.js} +2 -2
  76. package/webapp/dist/assets/{chunk-55IACEB6-D6LDTDBy.js.map → chunk-55IACEB6-B3rzakPd.js.map} +1 -1
  77. package/webapp/dist/assets/{chunk-FMBD7UC4-C-BdCe4C.js → chunk-FMBD7UC4-CCZWJRJ5.js} +2 -2
  78. package/webapp/dist/assets/{chunk-FMBD7UC4-C-BdCe4C.js.map → chunk-FMBD7UC4-CCZWJRJ5.js.map} +1 -1
  79. package/webapp/dist/assets/{chunk-JSJVCQXG-WA_BLIm9.js → chunk-JSJVCQXG-Dqd_MOPD.js} +2 -2
  80. package/webapp/dist/assets/{chunk-JSJVCQXG-WA_BLIm9.js.map → chunk-JSJVCQXG-Dqd_MOPD.js.map} +1 -1
  81. package/webapp/dist/assets/{chunk-KX2RTZJC-CA7sDJO5.js → chunk-KX2RTZJC-DOpPZD_q.js} +2 -2
  82. package/webapp/dist/assets/{chunk-KX2RTZJC-CA7sDJO5.js.map → chunk-KX2RTZJC-DOpPZD_q.js.map} +1 -1
  83. package/webapp/dist/assets/{chunk-NQ4KR5QH-wlvxalE3.js → chunk-NQ4KR5QH-CUj2LNV0.js} +4 -4
  84. package/webapp/dist/assets/{chunk-NQ4KR5QH-wlvxalE3.js.map → chunk-NQ4KR5QH-CUj2LNV0.js.map} +1 -1
  85. package/webapp/dist/assets/{chunk-QZHKN3VN-Bo1VMcph.js → chunk-QZHKN3VN-DXeWDyzh.js} +2 -2
  86. package/webapp/dist/assets/{chunk-QZHKN3VN-Bo1VMcph.js.map → chunk-QZHKN3VN-DXeWDyzh.js.map} +1 -1
  87. package/webapp/dist/assets/{chunk-WL4C6EOR-B-Pk44be.js → chunk-WL4C6EOR-CqTowzs6.js} +6 -6
  88. package/webapp/dist/assets/{chunk-WL4C6EOR-B-Pk44be.js.map → chunk-WL4C6EOR-CqTowzs6.js.map} +1 -1
  89. package/webapp/dist/assets/{classDiagram-VBA2DB6C-BqKuyb49.js → classDiagram-VBA2DB6C-CvsxEN3D.js} +7 -7
  90. package/webapp/dist/assets/{classDiagram-VBA2DB6C-BqKuyb49.js.map → classDiagram-VBA2DB6C-CvsxEN3D.js.map} +1 -1
  91. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BqKuyb49.js → classDiagram-v2-RAHNMMFH-CvsxEN3D.js} +7 -7
  92. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BqKuyb49.js.map → classDiagram-v2-RAHNMMFH-CvsxEN3D.js.map} +1 -1
  93. package/webapp/dist/assets/{clone-BX5z8WVZ.js → clone-PGWIYNYc.js} +2 -2
  94. package/webapp/dist/assets/{clone-BX5z8WVZ.js.map → clone-PGWIYNYc.js.map} +1 -1
  95. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-B-s11SgN.js → cose-bilkent-S5V4N54A-Cf8RR_8j.js} +2 -2
  96. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-B-s11SgN.js.map → cose-bilkent-S5V4N54A-Cf8RR_8j.js.map} +1 -1
  97. package/webapp/dist/assets/{dagre-KLK3FWXG-DmQFV2qK.js → dagre-KLK3FWXG-C1yQDg-6.js} +7 -7
  98. package/webapp/dist/assets/{dagre-KLK3FWXG-DmQFV2qK.js.map → dagre-KLK3FWXG-C1yQDg-6.js.map} +1 -1
  99. package/webapp/dist/assets/{diagram-E7M64L7V-QRaBfST8.js → diagram-E7M64L7V-CrT4qBJh.js} +8 -8
  100. package/webapp/dist/assets/{diagram-E7M64L7V-QRaBfST8.js.map → diagram-E7M64L7V-CrT4qBJh.js.map} +1 -1
  101. package/webapp/dist/assets/{diagram-IFDJBPK2-lrWn1Obo.js → diagram-IFDJBPK2-B8WaCOcr.js} +7 -7
  102. package/webapp/dist/assets/{diagram-IFDJBPK2-lrWn1Obo.js.map → diagram-IFDJBPK2-B8WaCOcr.js.map} +1 -1
  103. package/webapp/dist/assets/{diagram-P4PSJMXO-sTU7Hh-Y.js → diagram-P4PSJMXO-BCZeNfu_.js} +7 -7
  104. package/webapp/dist/assets/{diagram-P4PSJMXO-sTU7Hh-Y.js.map → diagram-P4PSJMXO-BCZeNfu_.js.map} +1 -1
  105. package/webapp/dist/assets/{erDiagram-INFDFZHY-Cx6jc9Wq.js → erDiagram-INFDFZHY-BrYt0-mW.js} +5 -5
  106. package/webapp/dist/assets/{erDiagram-INFDFZHY-Cx6jc9Wq.js.map → erDiagram-INFDFZHY-BrYt0-mW.js.map} +1 -1
  107. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-DfGI49Dz.js → flowDiagram-PKNHOUZH-8lZ5d5y-.js} +7 -7
  108. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-DfGI49Dz.js.map → flowDiagram-PKNHOUZH-8lZ5d5y-.js.map} +1 -1
  109. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-nrcHWWaM.js → ganttDiagram-A5KZAMGK-CQ8pOLf-.js} +3 -3
  110. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-nrcHWWaM.js.map → ganttDiagram-A5KZAMGK-CQ8pOLf-.js.map} +1 -1
  111. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D8ivAqd6.js → gitGraphDiagram-K3NZZRJ6-aOTOe0HP.js} +8 -8
  112. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D8ivAqd6.js.map → gitGraphDiagram-K3NZZRJ6-aOTOe0HP.js.map} +1 -1
  113. package/webapp/dist/assets/{graph-R5G-y8tB.js → graph-CyMR1egR.js} +3 -3
  114. package/webapp/dist/assets/{graph-R5G-y8tB.js.map → graph-CyMR1egR.js.map} +1 -1
  115. package/webapp/dist/assets/{index--fy89xGh.js → index-B9TTmMv-.js} +550 -134
  116. package/webapp/dist/assets/index-B9TTmMv-.js.map +1 -0
  117. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-PIoZHr7s.js → infoDiagram-LFFYTUFH-CXR9XjRe.js} +6 -6
  118. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-PIoZHr7s.js.map → infoDiagram-LFFYTUFH-CXR9XjRe.js.map} +1 -1
  119. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-oCM-LYk1.js → ishikawaDiagram-PHBUUO56-zwe-cqRW.js} +2 -2
  120. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-oCM-LYk1.js.map → ishikawaDiagram-PHBUUO56-zwe-cqRW.js.map} +1 -1
  121. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C2qidjQ5.js → journeyDiagram-4ABVD52K-BV-8X5hz.js} +5 -5
  122. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C2qidjQ5.js.map → journeyDiagram-4ABVD52K-BV-8X5hz.js.map} +1 -1
  123. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Du0TC8WS.js → kanban-definition-K7BYSVSG-E3W-szUv.js} +3 -3
  124. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Du0TC8WS.js.map → kanban-definition-K7BYSVSG-E3W-szUv.js.map} +1 -1
  125. package/webapp/dist/assets/{layout-VmEo1OEB.js → layout-DvIjuV8I.js} +5 -5
  126. package/webapp/dist/assets/{layout-VmEo1OEB.js.map → layout-DvIjuV8I.js.map} +1 -1
  127. package/webapp/dist/assets/{linear-B662YHAc.js → linear-C-SIS0ki.js} +2 -2
  128. package/webapp/dist/assets/{linear-B662YHAc.js.map → linear-C-SIS0ki.js.map} +1 -1
  129. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-D7arZj95.js → mindmap-definition-YRQLILUH-wigkPJ2B.js} +4 -4
  130. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-D7arZj95.js.map → mindmap-definition-YRQLILUH-wigkPJ2B.js.map} +1 -1
  131. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DvjPP4PA.js → pieDiagram-SKSYHLDU-BKrYJ0LE.js} +8 -8
  132. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DvjPP4PA.js.map → pieDiagram-SKSYHLDU-BKrYJ0LE.js.map} +1 -1
  133. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_JUGMj_.js → quadrantDiagram-337W2JSQ-fjwd0gVY.js} +3 -3
  134. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_JUGMj_.js.map → quadrantDiagram-337W2JSQ-fjwd0gVY.js.map} +1 -1
  135. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DF0mpvE3.js → requirementDiagram-Z7DCOOCP-vgTMObSA.js} +4 -4
  136. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DF0mpvE3.js.map → requirementDiagram-Z7DCOOCP-vgTMObSA.js.map} +1 -1
  137. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CoXlxv00.js → sankeyDiagram-WA2Y5GQK-B-ZV3LF7.js} +2 -2
  138. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CoXlxv00.js.map → sankeyDiagram-WA2Y5GQK-B-ZV3LF7.js.map} +1 -1
  139. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DYqT5Pg7.js → sequenceDiagram-2WXFIKYE-DPhZYHhW.js} +4 -4
  140. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DYqT5Pg7.js.map → sequenceDiagram-2WXFIKYE-DPhZYHhW.js.map} +1 -1
  141. package/webapp/dist/assets/{stateDiagram-RAJIS63D-D9b1mN8-.js → stateDiagram-RAJIS63D-DLsw3SC8.js} +9 -9
  142. package/webapp/dist/assets/{stateDiagram-RAJIS63D-D9b1mN8-.js.map → stateDiagram-RAJIS63D-DLsw3SC8.js.map} +1 -1
  143. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DNzgudL_.js → stateDiagram-v2-FVOUBMTO-DqXB3dNs.js} +5 -5
  144. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DNzgudL_.js.map → stateDiagram-v2-FVOUBMTO-DqXB3dNs.js.map} +1 -1
  145. package/webapp/dist/assets/{timeline-definition-YZTLITO2-CkyKUY7A.js → timeline-definition-YZTLITO2-BFSqlDfo.js} +3 -3
  146. package/webapp/dist/assets/{timeline-definition-YZTLITO2-CkyKUY7A.js.map → timeline-definition-YZTLITO2-BFSqlDfo.js.map} +1 -1
  147. package/webapp/dist/assets/{treemap-KZPCXAKY-CZd09kF-.js → treemap-KZPCXAKY-sdfq6mHG.js} +5 -5
  148. package/webapp/dist/assets/{treemap-KZPCXAKY-CZd09kF-.js.map → treemap-KZPCXAKY-sdfq6mHG.js.map} +1 -1
  149. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BxVF5Olo.js → vennDiagram-LZ73GAT5-D7Cioksz.js} +2 -2
  150. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BxVF5Olo.js.map → vennDiagram-LZ73GAT5-D7Cioksz.js.map} +1 -1
  151. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-BRwRloPc.js → xychartDiagram-JWTSCODW-No65aXqH.js} +3 -3
  152. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-BRwRloPc.js.map → xychartDiagram-JWTSCODW-No65aXqH.js.map} +1 -1
  153. package/webapp/dist/index.html +1 -1
  154. package/webapp/dist/assets/index--fy89xGh.js.map +0 -1
@@ -147,7 +147,7 @@ Dominds 必须从任务包构造一个**有效差遣牒**用于提示词和 UI
147
147
  **差遣牒封装与访问限制**
148
148
 
149
149
  - 任何 `.tsk/` 目录及其子路径(`**/*.tsk/**`)都是封装状态:禁止使用任何通用文件工具读取/写入/列目录(例如 `read_file` / `write_file` / `list_dir` 等)。
150
- - 更新差遣牒只能使用函数工具 `change_mind`(按章节整段替换;顶层用 `selector`,额外章节用 `category + selector`)。
150
+ - 更新差遣牒只能使用显式差遣牒函数工具:`do_mind` 创建新章节,`mind_more` 向已有章节追加少量条目,`change_mind` 替换已有章节,`never_mind` 删除章节。
151
151
  - 读取"不会自动注入上下文"的额外章节,只能使用函数工具 `recall_taskdoc({ category, selector })`。
152
152
 
153
153
  **差遣牒自动注入规则(系统提示)**
@@ -163,7 +163,7 @@ Dominds 必须从任务包构造一个**有效差遣牒**用于提示词和 UI
163
163
  **Taskdoc encapsulation & access restrictions**
164
164
 
165
165
  - Any `.tsk/` directory and its subpaths (`**/*.tsk/**`) are encapsulated state: general file tools MUST NOT read/write/list them (e.g. `read_file` / `write_file` / `list_dir`).
166
- - Taskdoc updates MUST go through the function tool `change_mind` (whole-section replace; use top-level `selector`, or `category + selector` for extra sections).
166
+ - Taskdoc updates MUST go through explicit Taskdoc function tools: `do_mind` creates a new section, `mind_more` appends small entries to an existing section, `change_mind` replaces an existing section, and `never_mind` deletes a section.
167
167
  - To read extra sections that are NOT auto-injected, use the function tool `recall_taskdoc({ category, selector })`.
168
168
 
169
169
  **Taskdoc auto-injection rules (system prompt)**
@@ -179,21 +179,26 @@ Dominds 必须从任务包构造一个**有效差遣牒**用于提示词和 UI
179
179
  - 有效差遣牒必须是确定性的(除了上述框架之外没有隐藏的重新格式化)。
180
180
  - 允许空部分,但文件仍然存在。
181
181
 
182
- ## `change_mind` 语义(不开启新一程对话)
182
+ ## 差遣牒变更语义(不开启新一程对话)
183
183
 
184
- 函数工具 `change_mind` 通过**替换其整个内容**来更新任务包的**恰好一个**部分文件。
184
+ 差遣牒变更函数工具每次只影响任务包的**恰好一个**章节文件:
185
+
186
+ - `do_mind` 创建新章节文件;如果目标已存在,必须失败。
187
+ - `mind_more` 追加条目,不会自动去重或改写旧内容。
188
+ - `change_mind` 替换已有章节文件;如果目标不存在,必须失败。
189
+ - `never_mind` 删除已有章节文件。
185
190
 
186
191
  关键点:
187
192
 
188
- - `change_mind` 不开启新一程对话。
193
+ - 差遣牒变更工具不开启新一程对话。
189
194
  - 如需开启新一程对话,请单独调用函数工具 `clear_mind({ "reminder_content": "<接续包>" })`(或其他对话过程控制机制)。
190
195
  - 建议:包含一个有效的接续包,以便智能体在下一程对话流畅接续。
191
196
 
192
197
  ### 参数(当前)
193
198
 
194
- `change_mind` 通过**替换其整个内容**来更新**恰好一个**差遣牒分段。
199
+ `do_mind` 和 `change_mind` 都定位**恰好一个**差遣牒分段。
195
200
 
196
- 它接受:
201
+ 它们接受:
197
202
 
198
203
  - `selector`(必需)
199
204
  - `content`(必需)
@@ -240,7 +245,7 @@ recall_taskdoc({ category, selector })
240
245
  示例(bearinmind):
241
246
 
242
247
  ```text
243
- 使用函数工具 `change_mind` 调用:
248
+ 使用函数工具 `do_mind` 调用:
244
249
  { "selector": "grants", "category": "bearinmind", "content": "- Allowed: ...\n- Disallowed: ...\n" }
245
250
  ```
246
251
 
@@ -262,18 +267,20 @@ recall_taskdoc({ category, selector })
262
267
 
263
268
  - `(category, selector)` 对必须根据上述保留选择器规则有效;其他任何内容都是错误。
264
269
  - 正文被视为不透明的 markdown 文本;不暗示部分修补/差异语义。
265
- - 成功的 `change_mind` 会立即更新任务包,并对以下内容可见:
270
+ - 成功的差遣牒变更会立即更新任务包,并对以下内容可见:
266
271
  - 当前对话
267
272
  - 对话树中的所有支线对话/队友
268
273
  - 任何观察的 WebUI 客户端
269
274
 
270
275
  ### 失败情况(非穷尽)
271
276
 
272
- 如果满足以下条件,`change_mind` 必须被拒绝:
277
+ 如果满足以下条件,差遣牒变更必须被拒绝:
273
278
 
274
279
  - 选择器缺失或无效。
275
280
  - 正文缺失(仅当明确支持时才允许空正文;v1 应拒绝空正文以防止错误)。
276
281
  - 调用尝试定位定义集之外的文件。
282
+ - `do_mind` 指向已存在的章节。
283
+ - `change_mind` 指向不存在的章节。
277
284
 
278
285
  ## 文件工具封装策略(`**/*.tsk/`)
279
286
 
@@ -286,7 +293,7 @@ recall_taskdoc({ category, selector })
286
293
  理由:
287
294
 
288
295
  - 防止通过通用文件操作进行意外编辑。
289
- - 强制通过明确的、有语义的操作(`change_mind`)进行差遣牒变更。
296
+ - 强制通过明确的、有语义的操作(`do_mind`、`mind_more`、`change_mind`、`never_mind`)进行差遣牒变更。
290
297
  - 避免智能体"好心"地在没有明确意图的情况下重写任务约束这类提示词/控制流陷阱。
291
298
 
292
299
  系统提示词(和向智能体展示的任何工具文档)必须明确说明此限制。
@@ -26,6 +26,12 @@ const toolset_manual_1 = require("../tools/toolset-manual");
26
26
  const minds_i18n_1 = require("./minds-i18n");
27
27
  const system_prompt_1 = require("./system-prompt");
28
28
  const system_prompt_parts_1 = require("./system-prompt-parts");
29
+ const TASKDOC_MUTATION_TOOL_NAMES = new Set([
30
+ ctrl_1.doMindTool.name,
31
+ ctrl_1.mindMoreTool.name,
32
+ ctrl_1.changeMindTool.name,
33
+ ctrl_1.neverMindTool.name,
34
+ ]);
29
35
  async function readAgentMindResult(id, fn, source) {
30
36
  const mindFn = source === 'rtws'
31
37
  ? path_1.default.join('.minds', 'team', id, fn)
@@ -190,8 +196,8 @@ async function loadAgentMinds(agentId, dialog, options) {
190
196
  });
191
197
  // Introduction of all team members (mark "(self)" for the current agent)
192
198
  const teamIntro = (0, system_prompt_1.formatTeamIntro)(team, agent.id, workingLanguage);
193
- // Compose tool list from member's resolved toolsets and tools + built-in human tool
194
- // Get base tools from agent (excluding intrinsic dialog control tools which are always injected)
199
+ // Compose tool list from member's resolved toolsets and tools + built-in human tool.
200
+ // Get base tools from agent; runtime injects allowed intrinsic dialog-control tools afterward.
195
201
  // shell_specialists is intended for visible teammates only. Hidden members are exempt from this
196
202
  // policy and may carry shell tools.
197
203
  const agentIsShellSpecialist = team.shellSpecialists.includes(agent.id) || agent.hidden === true;
@@ -210,7 +216,7 @@ async function loadAgentMinds(agentId, dialog, options) {
210
216
  return tools;
211
217
  return tools.filter((t) => !(t.type === 'func' && typeof t.name === 'string' && (0, shell_tools_1.isShellToolName)(t.name)));
212
218
  })();
213
- // Inject intrinsic dialog control tools as function tools (available to all agents).
219
+ // Inject intrinsic dialog-control tools as function tools according to dialog scope.
214
220
  const intrinsicFuncTools = [
215
221
  ctrl_1.addReminderTool,
216
222
  ctrl_1.deleteReminderTool,
@@ -220,9 +226,12 @@ async function loadAgentMinds(agentId, dialog, options) {
220
226
  ];
221
227
  // Taskdoc mutation tools are only available in main dialogs (not sideDialogs).
222
228
  if (dialog === undefined || dialog.askerDialog === undefined) {
229
+ intrinsicFuncTools.push(ctrl_1.doMindTool);
223
230
  intrinsicFuncTools.push(ctrl_1.mindMoreTool);
224
231
  intrinsicFuncTools.push(ctrl_1.changeMindTool);
232
+ intrinsicFuncTools.push(ctrl_1.neverMindTool);
225
233
  }
234
+ const shouldHideTaskdocMutationTools = dialog !== undefined && dialog.askerDialog !== undefined;
226
235
  const agentTools = (() => {
227
236
  const out = [...baseAgentTools];
228
237
  const seenNames = new Set(out.map((t) => t.name));
@@ -232,7 +241,9 @@ async function loadAgentMinds(agentId, dialog, options) {
232
241
  seenNames.add(t.name);
233
242
  }
234
243
  }
235
- return out;
244
+ if (!shouldHideTaskdocMutationTools)
245
+ return out;
246
+ return out.filter((t) => !TASKDOC_MUTATION_TOOL_NAMES.has(t.name));
236
247
  })();
237
248
  const toolsetNames = agent
238
249
  .listResolvedToolsetNames({
@@ -54,7 +54,7 @@ function taskdocCanonicalCopy(language) {
54
54
  '**Taskdoc 封装与访问限制**',
55
55
  '',
56
56
  '- 任何 `.tsk/` 目录及其子路径(`**/*.tsk/**`)都是封装状态:禁止使用任何通用文件工具读取/写入/列目录(例如 `read_file` / `write_file` / `list_dir` 等)。',
57
- '- 更新 Taskdoc 只能使用函数工具 `mind_more` / `change_mind`:少量新增用 `mind_more` 追加(默认 progress),需要删除陈旧项、重排或压缩时用 `change_mind` 整章替换。',
57
+ '- 更新 Taskdoc 只能使用函数工具 `do_mind` / `mind_more` / `change_mind` / `never_mind`:缺失章节用 `do_mind` 创建;少量新增用 `mind_more` 追加(默认 progress);需要删除陈旧项、重排或压缩时用 `change_mind` 整章替换;确需删除整章文件时用 `never_mind`。',
58
58
  '- 读取“不会自动注入上下文”的额外章节,只能使用函数工具 `recall_taskdoc({ category, selector })`。',
59
59
  '',
60
60
  '**Taskdoc 自动注入规则(系统提示)**',
@@ -70,7 +70,7 @@ function taskdocCanonicalCopy(language) {
70
70
  '**Taskdoc encapsulation & access restrictions**',
71
71
  '',
72
72
  '- Any `.tsk/` directory and its subpaths (`**/*.tsk/**`) are encapsulated state: general file tools MUST NOT read/write/list them (e.g. `read_file` / `write_file` / `list_dir`).',
73
- '- Taskdoc updates MUST go through `mind_more` / `change_mind`: use `mind_more` for small append-only additions (defaults to progress), and use `change_mind` for full-section replacement when cleanup, reordering, or compression is needed.',
73
+ '- Taskdoc updates MUST go through `do_mind` / `mind_more` / `change_mind` / `never_mind`: use `do_mind` to create missing sections, use `mind_more` for small append-only additions (defaults to progress), use `change_mind` for full-section replacement when cleanup, reordering, or compression is needed, and use `never_mind` when a whole section file should be deleted.',
74
74
  '- To read extra sections that are NOT auto-injected, use the function tool `recall_taskdoc({ category, selector })`.',
75
75
  '',
76
76
  '**Taskdoc auto-injection rules (system prompt)**',
@@ -148,11 +148,11 @@ function getMemoryPromptCopy(ctx) {
148
148
  const taskdocLogLineZh = ctx.contextHealthPromptMode === 'critical'
149
149
  ? ctx.isSideDialog
150
150
  ? '当前是告急处置态:支线对话不要维护差遣牒,也不要整理差遣牒更新提案;把当前对话历史中下一程需要知道的讨论细节、下一步、关键定位、运行/验证信息、临时路径/ID/样例输入和恢复依据写入接续包提醒项。提醒项长度没有技术限制,宁可完整一些;允许多条粗略提醒项求稳,但不要在当前程提前做“新一程清醒复核”。系统真正开启新一程后,第一步再复核整理:删除冗余、纠正偏激/失真思路,再收敛成高质量提醒项。'
151
- : '不要把长日志/大段 tool output 直接塞进差遣牒;差遣牒只写结论+下一步。当前是告急处置态:先检查当前对话历史里尚未落文档的讨论细节;能作为全队共享状态/决策/约束/目标的,主线直接用 `mind_more`/`change_mind` 写入差遣牒合适章节。接续包提醒项只留差遣牒仍未覆盖、但恢复工作容易丢的细节;本程允许先保留多条粗略提醒项求稳,但不要在当前程提前做“新一程清醒复核”。系统真正开启新一程后,第一步再复核整理:删除冗余、纠正偏激/失真思路,再收敛成高质量提醒项。'
151
+ : '不要把长日志/大段 tool output 直接塞进差遣牒;差遣牒只写结论+下一步。当前是告急处置态:先检查当前对话历史里尚未落文档的讨论细节;能作为全队共享状态/决策/约束/目标的,主线优先用 `do_mind` 新增章节保存;只有在确实需要改写已有章节、且已完成合并时,才用 `change_mind`。接续包提醒项只留差遣牒仍未覆盖、但恢复工作容易丢的细节;本程允许先保留多条粗略提醒项求稳,但不要在当前程提前做“新一程清醒复核”。系统真正开启新一程后,第一步再复核整理:删除冗余、纠正偏激/失真思路,再收敛成高质量提醒项。'
152
152
  : ctx.contextHealthPromptMode === 'caution'
153
153
  ? ctx.isSideDialog
154
154
  ? '当前是吃紧处置态:支线对话不要维护差遣牒,也不要整理差遣牒更新提案;把当前对话历史中下一程需要知道的讨论细节、下一步、关键定位、运行/验证信息、临时路径/ID/样例输入和恢复依据写入接续包提醒项。提醒项长度没有技术限制,宁可完整一些;若一时来不及,可先保留多条粗略提醒项过桥,但不要在当前程提前做“新一程清醒复核”。系统真正开启新一程后,第一步再复核整理:删除冗余、纠正偏激/失真思路,再收敛成高质量提醒项。'
155
- : '不要把长日志/大段 tool output 直接塞进差遣牒;差遣牒只写结论+下一步。当前是吃紧处置态:先检查当前对话历史里尚未落文档的讨论细节;能作为全队共享状态/决策/约束/目标的,主线直接用 `mind_more`/`change_mind` 写入差遣牒合适章节。接续包提醒项只留差遣牒仍未覆盖、但恢复工作容易丢的细节;若一时来不及,可先保留多条粗略提醒项过桥,但不要在当前程提前做“新一程清醒复核”。系统真正开启新一程后,第一步再复核整理:删除冗余、纠正偏激/失真思路,再收敛成高质量提醒项。'
155
+ : '不要把长日志/大段 tool output 直接塞进差遣牒;差遣牒只写结论+下一步。当前是吃紧处置态:先检查当前对话历史里尚未落文档的讨论细节;能作为全队共享状态/决策/约束/目标的,主线优先用 `do_mind` 新增章节保存;只有在确实需要改写已有章节、且已完成合并时,才用 `change_mind`。接续包提醒项只留差遣牒仍未覆盖、但恢复工作容易丢的细节;若一时来不及,可先保留多条粗略提醒项过桥,但不要在当前程提前做“新一程清醒复核”。系统真正开启新一程后,第一步再复核整理:删除冗余、纠正偏激/失真思路,再收敛成高质量提醒项。'
156
156
  : '不要把长日志/大段 tool output 直接塞进差遣牒;差遣牒只写结论+下一步;提醒项也只留可扫读摘录。接续包提醒项默认应保持结构化、便于快速恢复。';
157
157
  const contextHealthLineEn = ctx.contextHealthPromptMode === 'critical'
158
158
  ? ctx.isSideDialog
@@ -166,11 +166,11 @@ function getMemoryPromptCopy(ctx) {
166
166
  const taskdocLogLineEn = ctx.contextHealthPromptMode === 'critical'
167
167
  ? ctx.isSideDialog
168
168
  ? 'Current mode is critical remediation: in a Side Dialog, do not maintain Taskdoc and do not draft Taskdoc update proposals. Put discussion details from current dialog history that the next course needs to know, next actions, key pointers, run/verify info, volatile paths/IDs/sample inputs, and resume reasoning into continuation-package reminders. Reminder length has no technical limit, so prefer being complete. Rough multi-reminder bridge notes are acceptable in this course, but do not perform the new-course “clear-headed review” early. Once the system actually starts the new course, the first step is to review/rewrite them: remove redundancy, correct biased or distorted bridge notes, then compress them into high-quality reminders.'
169
- : 'Do not paste long logs/tool outputs into Taskdoc; Taskdoc should record decisions + next steps. Current mode is critical remediation: first review current-dialog discussion details not yet written into documentation. If they belong to team-shared state, decisions, constraints, or goals, write them to the appropriate Taskdoc section with `mind_more`/`change_mind`. Continuation-package reminders should keep only details still not covered by Taskdoc but easy to lose during resume. Rough multi-reminder bridge notes are acceptable in this course, but do not perform the new-course “clear-headed review” early. Once the system actually starts the new course, the first step is to review/rewrite them: remove redundancy, correct biased or distorted bridge notes, then compress them into high-quality reminders.'
169
+ : 'Do not paste long logs/tool outputs into Taskdoc; Taskdoc should record decisions + next steps. Current mode is critical remediation: first review current-dialog discussion details not yet written into documentation. If they belong to team-shared state, decisions, constraints, or goals, prefer creating a new section with `do_mind`; use `change_mind` only when an existing section truly needs rewriting and you have merged against the current content. Continuation-package reminders should keep only details still not covered by Taskdoc but easy to lose during resume. Rough multi-reminder bridge notes are acceptable in this course, but do not perform the new-course “clear-headed review” early. Once the system actually starts the new course, the first step is to review/rewrite them: remove redundancy, correct biased or distorted bridge notes, then compress them into high-quality reminders.'
170
170
  : ctx.contextHealthPromptMode === 'caution'
171
171
  ? ctx.isSideDialog
172
172
  ? 'Current mode is caution remediation: in a Side Dialog, do not maintain Taskdoc and do not draft Taskdoc update proposals. Put discussion details from current dialog history that the next course needs to know, next actions, key pointers, run/verify info, volatile paths/IDs/sample inputs, and resume reasoning into continuation-package reminders. Reminder length has no technical limit, so prefer being complete. If needed, rough multi-reminder bridge notes are acceptable, but do not perform the new-course “clear-headed review” early. Once the system actually starts the new course, the first step is to review/rewrite them: remove redundancy, correct biased or distorted bridge notes, then compress them into high-quality reminders.'
173
- : 'Do not paste long logs/tool outputs into Taskdoc; Taskdoc should record decisions + next steps. Current mode is caution remediation: first review current-dialog discussion details not yet written into documentation. If they belong to team-shared state, decisions, constraints, or goals, write them to the appropriate Taskdoc section with `mind_more`/`change_mind`. Continuation-package reminders should keep only details still not covered by Taskdoc but easy to lose during resume. If needed, rough multi-reminder bridge notes are acceptable, but do not perform the new-course “clear-headed review” early. Once the system actually starts the new course, the first step is to review/rewrite them: remove redundancy, correct biased or distorted bridge notes, then compress them into high-quality reminders.'
173
+ : 'Do not paste long logs/tool outputs into Taskdoc; Taskdoc should record decisions + next steps. Current mode is caution remediation: first review current-dialog discussion details not yet written into documentation. If they belong to team-shared state, decisions, constraints, or goals, prefer creating a new section with `do_mind`; use `change_mind` only when an existing section truly needs rewriting and you have merged against the current content. Continuation-package reminders should keep only details still not covered by Taskdoc but easy to lose during resume. If needed, rough multi-reminder bridge notes are acceptable, but do not perform the new-course “clear-headed review” early. Once the system actually starts the new course, the first step is to review/rewrite them: remove redundancy, correct biased or distorted bridge notes, then compress them into high-quality reminders.'
174
174
  : 'Do not paste long logs/tool outputs into Taskdoc; Taskdoc should record decisions + next steps; reminders should also keep only scannable excerpts. Keep continuation-package reminders structured and fast to resume from by default.';
175
175
  if (ctx.language === 'zh') {
176
176
  return {
@@ -181,7 +181,7 @@ function getMemoryPromptCopy(ctx) {
181
181
  taskdocSemanticsLine: '- 章节语义约定:`progress` 是全队共享、准实时、可扫读的任务公告牌,用来记录当前有效状态、关键决策、下一步与仍成立阻塞;不是流水账,也不是个人工作记录。`goals` / `constraints` 是较稳定的任务契约;每次更新都必须保留仍然有效的他人条目。',
182
182
  taskdocSectionReplaceLine: ctx.isSideDialog && ctx.contextHealthPromptMode !== 'normal'
183
183
  ? '- 当前处于支线对话的上下文健康处置态:本程不要维护差遣牒,也不要整理差遣牒更新提案;把下一程需要恢复的细节写入足够详尽的接续包提醒项。'
184
- : `- 更新差遣牒时:少量新增条目可用 \`mind_more\` 追加(默认 progress);需要删除陈旧项、重排结构或压缩时,用 \`change_mind\` 整章替换并先对照“上下文中注入的当前内容”做合并;禁止覆盖/抹掉他人条目;自己负责维护的条目必须标注责任人(例如 \`- [owner:@${ctx.agentId}] ...\` 或用 \`### @${ctx.agentId}\` 分块)。`,
184
+ : `- 更新差遣牒时:少量新增条目可用 \`mind_more\` 追加(默认 progress);缺失章节用 \`do_mind\` 创建;需要删除陈旧项、重排结构或压缩时,用 \`change_mind\` 整章替换并先对照“上下文中注入的当前内容”做合并;需要删除整章文件时用 \`never_mind\`;禁止覆盖/抹掉他人条目;自己负责维护的条目必须标注责任人(例如 \`- [owner:@${ctx.agentId}] ...\` 或用 \`### @${ctx.agentId}\` 分块)。`,
185
185
  progressLine: ctx.isSideDialog && ctx.contextHealthPromptMode !== 'normal'
186
186
  ? '- 当前处于支线对话的上下文健康处置态:本程不更新 `progress`;只把下一程接续所需信息写入提醒项。'
187
187
  : '- 更新 `progress` 时:它必须始终是可供全队扫读的完整当前快照,而不是只追加自己这一轮的零散笔记。',
@@ -193,7 +193,7 @@ function getMemoryPromptCopy(ctx) {
193
193
  teamMemoryLine: '- 团队记忆:稳定的团队约定/工程规约(跨任务共享)。',
194
194
  personalMemoryLine: '- 个人记忆:稳定的个人习惯/偏好与职责域知识;记忆会在每次生成时自动注入上下文,应保持少量且准确(关键文档/代码的精确路径 + 最小必要事实)。不要记录具体任务状态。',
195
195
  sideDialogDutyLine: ctx.contextHealthPromptMode === 'normal'
196
- ? `你当前处于支线对话:此处不允许 \`mind_more\` / \`change_mind\`。当你判断需要更新差遣牒(尤其是 progress 公告牌)时,请在合适时机直接诉请差遣牒维护人 \`@${ctx.taskdocMaintainerId}\` 执行更新,并给出要追加的条目或已合并好的“新全文/替换稿”。不要声称已更新,除非看到回执。`
196
+ ? `你当前处于支线对话:此处不允许 \`do_mind\` / \`mind_more\` / \`change_mind\` / \`never_mind\`。当你判断需要更新差遣牒(尤其是 progress 公告牌)时,请在合适时机直接诉请差遣牒维护人 \`@${ctx.taskdocMaintainerId}\` 执行更新,并给出要新增的章节、要追加的条目、已合并好的“新全文/替换稿”,或要删除的章节。不要声称已更新,除非看到回执。`
197
197
  : '你当前处于支线对话,且上下文已进入吃紧/告急处置态:本程不要维护差遣牒,也不要整理差遣牒更新提案。请把下一程需要恢复的讨论细节、定位、验证方式和临时信息写入足够详尽的接续包提醒项。',
198
198
  mainDialogDutyLine: '你当前处于主线对话:你负责综合维护全队共享差遣牒(尤其是 progress 公告牌)。当队友/支线对话提出更新建议时,及时合并、压缩并保持清晰。',
199
199
  teammateTellaskRoundDoneLine: `队友诉请重要语义:当你在诉请者上下文中收到带${runtimeMarkers.finalCompleted}标记的回贴,表示该轮诉请已经结束;对方不会继续执行同一轮诉请。此时如果目标未达成,“等待”是错误的:必须显式发起新一轮 tellask 才能继续推进。`,
@@ -202,7 +202,7 @@ function getMemoryPromptCopy(ctx) {
202
202
  sideDialogWorkflowLine: ctx.contextHealthPromptMode === 'normal'
203
203
  ? `工作流:先做事 → 再提炼(\`update_reminder\`;必要时整理差遣牒追加条目/更新提案并诉请 \`@${ctx.taskdocMaintainerId}\` 合并写入)→ 然后 \`clear_mind\` 清空噪音。`
204
204
  : '工作流:停止扩张上下文 → 维护足够详尽的接续包提醒项(`add_reminder` 或 `update_reminder`,长度没有技术限制)→ 然后 `clear_mind` 开启新一程。',
205
- mainDialogWorkflowLine: '工作流:先做事 → 再提炼(`update_reminder` + `mind_more(progress)`;需要压缩/删旧时用 `change_mind(progress)`)→ 然后 `clear_mind` 清空噪音。',
205
+ mainDialogWorkflowLine: '工作流:先做事 → 再提炼(`update_reminder` + `mind_more(progress)`;需要压缩/删旧时用 `change_mind(progress)`;要删除整章文件时用 `never_mind`)→ 然后 `clear_mind` 清空噪音。',
206
206
  contextHealthLine: contextHealthLineZh,
207
207
  taskdocLogLine: taskdocLogLineZh,
208
208
  };
@@ -215,7 +215,7 @@ function getMemoryPromptCopy(ctx) {
215
215
  taskdocSemanticsLine: '- Section semantics: `progress` is the team-shared, quasi-real-time, scannable task bulletin board for current effective state, key decisions, next steps, and still-active blockers; it is not a raw log or personal work record. `goals` / `constraints` are the more stable task contract; every update must preserve still-valid entries from others.',
216
216
  taskdocSectionReplaceLine: ctx.isSideDialog && ctx.contextHealthPromptMode !== 'normal'
217
217
  ? '- Current mode is context-health remediation in a Side Dialog: do not maintain Taskdoc and do not draft Taskdoc update proposals in this course; put resume-critical details into sufficiently detailed continuation-package reminders.'
218
- : `- When updating Taskdoc: use \`mind_more\` for small append-only additions (defaults to progress); when stale entries must be removed, reordered, or compressed, use \`change_mind\` for a full-section replacement based on the current injected content; do not overwrite other contributors; add an explicit owner tag for entries you maintain (e.g., \`- [owner:@${ctx.agentId}] ...\` or a \`### @${ctx.agentId}\` block).`,
218
+ : `- When updating Taskdoc: use \`mind_more\` for small append-only additions (defaults to progress); create missing sections with \`do_mind\`; when stale entries must be removed, reordered, or compressed, use \`change_mind\` for a full-section replacement based on the current injected content; when a whole section file should be removed, use \`never_mind\`; do not overwrite other contributors; add an explicit owner tag for entries you maintain (e.g., \`- [owner:@${ctx.agentId}] ...\` or a \`### @${ctx.agentId}\` block).`,
219
219
  progressLine: ctx.isSideDialog && ctx.contextHealthPromptMode !== 'normal'
220
220
  ? '- Current mode is context-health remediation in a Side Dialog: do not update `progress` in this course; put resume-critical information into reminders only.'
221
221
  : '- When updating `progress`, keep it as a complete, team-scannable current snapshot instead of appending only your own latest notes.',
@@ -227,16 +227,16 @@ function getMemoryPromptCopy(ctx) {
227
227
  teamMemoryLine: '- Team memory: stable shared conventions (cross-task).',
228
228
  personalMemoryLine: '- Personal memory: stable personal habits/preferences and responsibility-scope knowledge. Memory is automatically injected into context on each generation: keep it small and accurate (exact key doc/code paths + minimal key facts); do not store per-task state.',
229
229
  sideDialogDutyLine: ctx.contextHealthPromptMode === 'normal'
230
- ? `You are currently in a Side Dialog: \`mind_more\` / \`change_mind\` are not allowed here. When Taskdoc should be updated (especially the shared progress bulletin board), tellask the Taskdoc maintainer \`@${ctx.taskdocMaintainerId}\` with entries to append or a fully merged replacement draft. Do not claim it is updated until you see a receipt.`
230
+ ? `You are currently in a Side Dialog: \`do_mind\` / \`mind_more\` / \`change_mind\` / \`never_mind\` are not allowed here. When Taskdoc should be updated (especially the shared progress bulletin board), tellask the Taskdoc maintainer \`@${ctx.taskdocMaintainerId}\` with the new section to create, entries to append, a fully merged replacement draft, or the section to delete. Do not claim it is updated until you see a receipt.`
231
231
  : 'You are currently in a Side Dialog under caution/critical context-health remediation: do not maintain Taskdoc and do not draft Taskdoc update proposals in this course. Put discussion details, pointers, verification method, and volatile resume information into sufficiently detailed continuation-package reminders.',
232
232
  mainDialogDutyLine: 'You are currently in the Main Dialog: you are responsible for keeping the team-shared Taskdoc coherent and up to date (especially the progress bulletin board). Merge proposals from teammates/Side Dialogs promptly and keep it concise.',
233
233
  teammateTellaskRoundDoneLine: `Teammate Tellask semantics: when you receive a tellasker reply with the ${runtimeMarkers.finalCompleted} marker, that Tellask round is finished; the tellaskee will not keep executing the same call in the background. If the objective is not met, “waiting” is wrong: you must explicitly start a new Tellask round to continue.`,
234
234
  teamMemoryHintLine: 'Hint: you have team-memory tools (`add_team_memory` / `replace_team_memory` / `drop_team_memory` / `clear_team_memory`) and may maintain team memory when it is truly stable and worth sharing.',
235
235
  personalMemoryHintLine: `Hint: you have personal-memory tools (\`add_personal_memory\` / \`replace_personal_memory\` / \`drop_personal_memory\` / \`clear_personal_memory\`). Personal memory is private to the current agent and is automatically isolated under \`.minds/memory/individual/<member-id>/...\`; therefore \`path\` MUST NOT include your member id (do not write \`${ctx.agentId}/...\`). For first-time setup, just call \`add_personal_memory\`—the directory will be created automatically. Memory is automatically injected into context on each generation: keep it small, keep it accurate, and group facts that are updated together. Store stable facts (exact key paths + minimal contracts), not daily state/progress. If you changed those files or detect staleness/conflicts, immediately \`replace_personal_memory\` to keep it accurate.`,
236
236
  sideDialogWorkflowLine: ctx.contextHealthPromptMode === 'normal'
237
- ? `Workflow: do work → distill (\`update_reminder\`; when Taskdoc needs updates, draft append entries or a merged replacement and ask \`@${ctx.taskdocMaintainerId}\`) → then \`clear_mind\` to drop noise.`
237
+ ? `Workflow: do work → distill (\`update_reminder\`; when Taskdoc needs updates, draft append entries, a merged replacement, or a section deletion and ask \`@${ctx.taskdocMaintainerId}\`) → then \`clear_mind\` to drop noise.`
238
238
  : 'Workflow: stop expanding context → maintain sufficiently detailed continuation-package reminders (`add_reminder` or `update_reminder`, with no technical length limit) → then `clear_mind` to start a new course.',
239
- mainDialogWorkflowLine: 'Workflow: do work → distill (`update_reminder` + `mind_more(progress)`; use `change_mind(progress)` when compression/deletion is needed) → then `clear_mind` to drop noise.',
239
+ mainDialogWorkflowLine: 'Workflow: do work → distill (`update_reminder` + `mind_more(progress)`; use `change_mind(progress)` when compression/deletion is needed; use `never_mind` when removing a whole section file) → then `clear_mind` to drop noise.',
240
240
  contextHealthLine: contextHealthLineEn,
241
241
  taskdocLogLine: taskdocLogLineEn,
242
242
  };
@@ -406,7 +406,8 @@ function formatAgentFacingContextHealthV3RemediationGuide(language, args) {
406
406
  '当前已处于吃紧处置阶段:不要继续扩张上下文,也不要提前进入“按接续包做清醒复核”的模式;那是系统真正开启新一程后的第一步。当前程的目标是先把未落文档的讨论细节补进差遣牒,再把差遣牒仍未覆盖、但恢复工作会丢的信息带过桥;真正清理冗余、合并提醒项,放到新一程再做。然后主动 clear_mind,开启新一程对话继续工作。',
407
407
  '',
408
408
  '操作:',
409
- '- 先写差遣牒:mind_more({ "items": ["..."] });需要删旧/重排/压缩时改用 change_mind({ ... })',
409
+ '- 优先新增差遣牒章节保存讨论细节:do_mind({ "category": "<category>", "selector": "<selector>", "content": "..." })',
410
+ '- 只有在确实需要改写已有章节、且已对照当前差遣牒内容完成合并时,才更新:change_mind({ ... })',
410
411
  '- 优先新增过桥提醒项:add_reminder({ "content": "..." })',
411
412
  '- 只有在确实能就地复用现有提醒项、且不会额外增加当前程认知负担时,才更新:update_reminder({ "reminder_id": "<现有 reminder_id>", "content": "..." })',
412
413
  ].join('\n');
@@ -441,7 +442,8 @@ function formatAgentFacingContextHealthV3RemediationGuide(language, args) {
441
442
  '行动:你当前处于主线对话。尽快保住易丢信息,然后 clear_mind。当前处于告急处置阶段时,先把当前对话历史中尚未落实到文档、且下一程需要知会的讨论细节落到差遣牒合适章节。然后再把差遣牒仍未覆盖、但恢复工作会丢的信息新增提醒项带过桥;允许先保留多条粗略提醒项,甚至带一定冗余也可以,不必在当前程强行整理干净。',
442
443
  '',
443
444
  '操作:',
444
- '- 先写差遣牒:mind_more({ "items": ["..."] });需要删旧/重排/压缩时改用 change_mind({ ... })',
445
+ '- 优先新增差遣牒章节保存讨论细节:do_mind({ "category": "<category>", "selector": "<selector>", "content": "..." })',
446
+ '- 只有在确实需要改写已有章节、且已对照当前差遣牒内容完成合并时,才更新:change_mind({ ... })',
445
447
  '- 优先新增过桥提醒项:add_reminder({ "content": "..." })',
446
448
  '- 只有在确实能就地复用现有提醒项、且不会额外增加当前程认知负担时,才更新:update_reminder({ "reminder_id": "<现有 reminder_id>", "content": "..." })',
447
449
  '- clear_mind({})',
@@ -481,7 +483,8 @@ function formatAgentFacingContextHealthV3RemediationGuide(language, args) {
481
483
  'You are already in caution remediation for the current course, so do not keep expanding context and do not switch early into “clear-headed continuation-package review” mode; that is the first step only after the system actually starts the new course. In the current course, the goal is to first fill Taskdoc with undocumented discussion details, then carry forward details still not covered by Taskdoc; reminder cleanup and dedup belong to the new course. Then proactively clear_mind to start a new dialog course.',
482
484
  '',
483
485
  'Operations:',
484
- '- First write Taskdoc: mind_more({ "items": ["..."] }); use change_mind({ ... }) instead when deletion/reordering/compression is needed',
486
+ '- Prefer creating a new Taskdoc section for discussion details: do_mind({ "category": "<category>", "selector": "<selector>", "content": "..." })',
487
+ '- Only update when an existing section truly needs rewriting and you have merged against the current Taskdoc content: change_mind({ ... })',
485
488
  '- Prefer adding a bridge reminder first: add_reminder({ "content": "..." })',
486
489
  '- Only if an existing reminder is clearly the right place, and updating it would not add extra cognitive load in the current course: update_reminder({ "reminder_id": "<existing reminder_id>", "content": "..." })',
487
490
  ].join('\n');
@@ -516,7 +519,8 @@ function formatAgentFacingContextHealthV3RemediationGuide(language, args) {
516
519
  'Action: you are in the Main Dialog. Preserve easy-to-lose information, then clear_mind. In critical remediation, first record current-dialog discussion details that are not yet documented but the next course needs to know into the appropriate Taskdoc sections. Then add bridge reminders for information still not covered by Taskdoc but easy to lose. Multiple rough reminders, including some redundancy, are acceptable as a bridge; do not spend the current course forcing them into a clean final package.',
517
520
  '',
518
521
  'Operations:',
519
- '- First write Taskdoc: mind_more({ "items": ["..."] }); use change_mind({ ... }) instead when deletion/reordering/compression is needed',
522
+ '- Prefer creating a new Taskdoc section for discussion details: do_mind({ "category": "<category>", "selector": "<selector>", "content": "..." })',
523
+ '- Only update when an existing section truly needs rewriting and you have merged against the current Taskdoc content: change_mind({ ... })',
520
524
  '- Prefer adding a bridge reminder first: add_reminder({ "content": "..." })',
521
525
  '- Only if an existing reminder is clearly the right place, and updating it would not add extra cognitive load in the current course: update_reminder({ "reminder_id": "<existing reminder_id>", "content": "..." })',
522
526
  '- clear_mind({})',
@@ -45,6 +45,7 @@ exports.handleApiRoute = handleApiRoute;
45
45
  */
46
46
  const diligence_1 = require("@longrun-ai/kernel/diligence");
47
47
  const language_1 = require("@longrun-ai/kernel/types/language");
48
+ const html_1 = require("@longrun-ai/kernel/utils/html");
48
49
  const time_1 = require("@longrun-ai/kernel/utils/time");
49
50
  const promises_1 = __importDefault(require("fs/promises"));
50
51
  const path = __importStar(require("path"));
@@ -62,6 +63,7 @@ const team_1 = require("../team");
62
63
  const tool_availability_1 = require("../tool-availability");
63
64
  const id_1 = require("../utils/id");
64
65
  const taskdoc_search_1 = require("../utils/taskdoc-search");
66
+ const taskdoc_search_worker_client_1 = require("../utils/taskdoc-search-worker-client");
65
67
  const create_dialog_contract_1 = require("./create-dialog-contract");
66
68
  const dominds_self_update_1 = require("./dominds-self-update");
67
69
  const mime_types_1 = require("./mime-types");
@@ -1300,6 +1302,9 @@ async function handleApiRoute(req, res, pathname, context) {
1300
1302
  return await handleGetDialogArtifact(req, res, { rootId, selfId }, status);
1301
1303
  }
1302
1304
  // Taskdocs endpoint
1305
+ if (pathname === '/api/task-documents/suggestions' && req.method === 'GET') {
1306
+ return await handleGetTaskDocumentSuggestions(req, res);
1307
+ }
1303
1308
  if (pathname === '/api/task-documents' && req.method === 'GET') {
1304
1309
  return await handleGetTaskDocuments(res);
1305
1310
  }
@@ -2869,6 +2874,66 @@ async function handleGetTaskDocuments(res) {
2869
2874
  return true;
2870
2875
  }
2871
2876
  }
2877
+ function renderTaskDocumentSuggestionHtml(suggestions) {
2878
+ return suggestions
2879
+ .map((doc, index) => {
2880
+ const showName = doc.name.trim() !== '' && doc.name !== doc.relativePath;
2881
+ const nameHtml = showName ? `<div class="suggestion-name">${(0, html_1.escapeHtml)(doc.name)}</div>` : '';
2882
+ return `<div class="suggestion" data-index="${String(index)}"><div class="suggestion-path">${(0, html_1.escapeHtml)(doc.relativePath)}</div>${nameHtml}</div>`;
2883
+ })
2884
+ .join('');
2885
+ }
2886
+ async function handleGetTaskDocumentSuggestions(req, res) {
2887
+ try {
2888
+ const urlObj = new URL(req.url ?? '', 'http://127.0.0.1');
2889
+ const query = (urlObj.searchParams.get('q') ?? '').trim();
2890
+ const workerPayload = {
2891
+ rootDir: '.',
2892
+ query,
2893
+ limit: 50,
2894
+ };
2895
+ const requestKey = (0, taskdoc_search_worker_client_1.buildTaskDocumentSuggestionRequestKey)(workerPayload);
2896
+ const abortController = new AbortController();
2897
+ res.once('close', () => {
2898
+ if (!res.writableEnded)
2899
+ abortController.abort();
2900
+ });
2901
+ const result = await (0, taskdoc_search_worker_client_1.searchTaskDocumentSuggestionsInWorker)(workerPayload, {
2902
+ signal: abortController.signal,
2903
+ });
2904
+ if (abortController.signal.aborted || res.writableEnded)
2905
+ return true;
2906
+ if (result.kind === 'error') {
2907
+ log.error('Failed to search taskdoc suggestions', new Error(result.errorText), {
2908
+ query,
2909
+ });
2910
+ const payload = {
2911
+ success: false,
2912
+ error: result.errorText,
2913
+ };
2914
+ respondJson(res, 500, payload);
2915
+ return true;
2916
+ }
2917
+ const payload = {
2918
+ success: true,
2919
+ query,
2920
+ requestKey,
2921
+ suggestions: result.suggestions,
2922
+ html: renderTaskDocumentSuggestionHtml(result.suggestions),
2923
+ };
2924
+ respondJson(res, 200, payload);
2925
+ return true;
2926
+ }
2927
+ catch (error) {
2928
+ log.error('Failed to search taskdoc suggestions', error);
2929
+ const payload = {
2930
+ success: false,
2931
+ error: error instanceof Error ? error.message : 'Failed to search taskdoc suggestions',
2932
+ };
2933
+ respondJson(res, 500, payload);
2934
+ return true;
2935
+ }
2936
+ }
2872
2937
  /**
2873
2938
  * Helper function to read request body
2874
2939
  */
@@ -0,0 +1,19 @@
1
+ export declare const DEFAULT_WEBUI_PORT = 5666;
2
+ export declare const MIN_AUTO_WEBUI_PORT = 1024;
3
+ export type WebuiPortAutoDirection = 'down' | 'up';
4
+ export type ParsedPortSpec = {
5
+ port: number;
6
+ strictPort: boolean;
7
+ portAutoDirection: WebuiPortAutoDirection;
8
+ };
9
+ export declare function parseWebuiPortSpec(raw: string): ParsedPortSpec | null;
10
+ export declare function validateWebuiPort(port: number, context: string): void;
11
+ export declare function buildWebuiPortCandidates(params: {
12
+ preferredPort: number;
13
+ strictPort: boolean;
14
+ direction: WebuiPortAutoDirection;
15
+ }): number[];
16
+ export declare function formatWebuiPortScanBound(params: {
17
+ preferredPort: number;
18
+ direction: WebuiPortAutoDirection;
19
+ }): string;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MIN_AUTO_WEBUI_PORT = exports.DEFAULT_WEBUI_PORT = void 0;
4
+ exports.parseWebuiPortSpec = parseWebuiPortSpec;
5
+ exports.validateWebuiPort = validateWebuiPort;
6
+ exports.buildWebuiPortCandidates = buildWebuiPortCandidates;
7
+ exports.formatWebuiPortScanBound = formatWebuiPortScanBound;
8
+ exports.DEFAULT_WEBUI_PORT = 5666;
9
+ exports.MIN_AUTO_WEBUI_PORT = 1024;
10
+ function parseWebuiPortSpec(raw) {
11
+ let numericText = raw;
12
+ let strictPort = true;
13
+ let portAutoDirection = 'down';
14
+ if (raw.endsWith('+')) {
15
+ numericText = raw.slice(0, -1);
16
+ strictPort = false;
17
+ portAutoDirection = 'up';
18
+ }
19
+ else if (raw.endsWith('-')) {
20
+ numericText = raw.slice(0, -1);
21
+ strictPort = false;
22
+ portAutoDirection = 'down';
23
+ }
24
+ if (!/^[0-9]+$/.test(numericText))
25
+ return null;
26
+ const port = Number(numericText);
27
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
28
+ return null;
29
+ return { port, strictPort, portAutoDirection };
30
+ }
31
+ function validateWebuiPort(port, context) {
32
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
33
+ throw new Error(`${context} must be an integer in [0, 65535] (got ${String(port)})`);
34
+ }
35
+ }
36
+ function buildWebuiPortCandidates(params) {
37
+ validateWebuiPort(params.preferredPort, 'WebUI port');
38
+ if (params.strictPort || params.preferredPort === 0)
39
+ return [params.preferredPort];
40
+ const candidates = [params.preferredPort];
41
+ if (params.direction === 'down') {
42
+ for (let candidate = params.preferredPort - 1; candidate >= exports.MIN_AUTO_WEBUI_PORT; candidate -= 1) {
43
+ candidates.push(candidate);
44
+ }
45
+ }
46
+ else {
47
+ for (let candidate = params.preferredPort + 1; candidate <= 65535; candidate += 1) {
48
+ candidates.push(candidate);
49
+ }
50
+ }
51
+ return candidates;
52
+ }
53
+ function formatWebuiPortScanBound(params) {
54
+ return params.direction === 'down'
55
+ ? `down to ${Math.min(params.preferredPort, exports.MIN_AUTO_WEBUI_PORT)}`
56
+ : 'up to 65535';
57
+ }
@@ -46,9 +46,9 @@ export declare class HttpServerCore {
46
46
  private sendError;
47
47
  private sendUnauthorized;
48
48
  /**
49
- * Start the server - NO PORT FALLBACK, enforce specific port
49
+ * Start the server on the configured port.
50
50
  */
51
- start(): Promise<void>;
51
+ start(): Promise<number>;
52
52
  /**
53
53
  * Stop the server
54
54
  */
@@ -182,17 +182,31 @@ class HttpServerCore {
182
182
  res.end(JSON.stringify({ error: 'unauthorized' }));
183
183
  }
184
184
  /**
185
- * Start the server - NO PORT FALLBACK, enforce specific port
185
+ * Start the server on the configured port.
186
186
  */
187
187
  start() {
188
188
  return new Promise((resolve, reject) => {
189
- this.server.on('error', (error) => {
189
+ const cleanup = () => {
190
+ this.server.off('error', onError);
191
+ this.server.off('listening', onListening);
192
+ };
193
+ const onError = (error) => {
194
+ cleanup();
190
195
  reject(error);
191
- });
192
- this.server.listen(this.config.port, this.config.host, () => {
193
- log.debug(`Server listening on http://${this.config.host}:${this.config.port}`);
194
- resolve();
195
- });
196
+ };
197
+ const onListening = () => {
198
+ cleanup();
199
+ const address = this.server.address();
200
+ const actualPort = typeof address === 'object' && address !== null
201
+ ? address.port
202
+ : this.config.port;
203
+ this.config = { ...this.config, port: actualPort };
204
+ log.debug(`Server listening on http://${this.config.host}:${actualPort}`);
205
+ resolve(actualPort);
206
+ };
207
+ this.server.once('error', onError);
208
+ this.server.once('listening', onListening);
209
+ this.server.listen(this.config.port, this.config.host);
196
210
  });
197
211
  }
198
212
  /**
@@ -42,6 +42,7 @@ Available API endpoints:
42
42
  • GET /api/dialogs/:root/sideDialogs/:self/list-node - Get one dialog-list sideDialog node
43
43
  • GET /api/dialogs/:root/hierarchy - Get dialog hierarchy
44
44
  • GET /api/task-documents - Taskdoc listing
45
+ • GET /api/task-documents/suggestions?q=... - Worker-backed Taskdoc suggestions
45
46
 
46
47
  WebSocket endpoint: /ws
47
48
  Backend API endpoint: /api
package/dist/server.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AuthConfig } from './server/auth';
2
+ import { type WebuiPortAutoDirection } from './server/port-selection';
2
3
  import { HttpServerCore } from './server/server-core';
3
4
  import './tools/builtins';
4
5
  export type ServerOptions = {
@@ -6,6 +7,8 @@ export type ServerOptions = {
6
7
  host?: string;
7
8
  mode?: 'dev' | 'prod';
8
9
  startBackendDriver?: boolean;
10
+ strictPort?: boolean;
11
+ portAutoDirection?: WebuiPortAutoDirection;
9
12
  };
10
13
  export type StartedServer = {
11
14
  httpServer: HttpServerCore;