dominds 0.6.2 → 0.6.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 (149) hide show
  1. package/dist/access-control.js +2 -2
  2. package/dist/agent-priming.js +826 -92
  3. package/dist/cli/read.js +406 -12
  4. package/dist/dialog.js +4 -0
  5. package/dist/docs/design.md +1 -0
  6. package/dist/docs/design.zh.md +1 -0
  7. package/dist/docs/dialog-system.md +12 -7
  8. package/dist/docs/dialog-system.zh.md +7 -3
  9. package/dist/docs/dominds-agent-priming.md +10 -1
  10. package/dist/docs/dominds-agent-priming.zh.md +9 -1
  11. package/dist/docs/dominds-terminology.md +8 -8
  12. package/dist/docs/fbr-implementation.md +77 -0
  13. package/dist/docs/fbr-implementation.zh.md +77 -0
  14. package/dist/docs/fbr.md +142 -141
  15. package/dist/docs/fbr.zh.md +129 -123
  16. package/dist/docs/keep-going.zh.md +162 -0
  17. package/dist/docs/showing-by-doing.md +208 -0
  18. package/dist/docs/showing-by-doing.zh.md +177 -0
  19. package/dist/docs/tellask-collab.md +250 -0
  20. package/dist/docs/tellask-collab.zh.md +254 -0
  21. package/dist/docs/txt-editing-tools.md +2 -2
  22. package/dist/docs/txt-editing-tools.zh.md +2 -2
  23. package/dist/llm/defaults.yaml +82 -4
  24. package/dist/llm/driver.js +280 -104
  25. package/dist/llm/gen/codex.js +49 -2
  26. package/dist/log.js +385 -30
  27. package/dist/mcp/supervisor.js +113 -40
  28. package/dist/minds/builtin/pangu/persona.zh.md +2 -2
  29. package/dist/minds/load.js +49 -284
  30. package/dist/minds/minds-i18n.js +2 -2
  31. package/dist/minds/promptdocs.js +263 -0
  32. package/dist/minds/system-prompt-parts.js +231 -0
  33. package/dist/minds/system-prompt.js +190 -223
  34. package/dist/persistence.js +66 -1
  35. package/dist/server/websocket-handler.js +14 -0
  36. package/dist/shared/diligence.js +40 -6
  37. package/dist/shared/utils/inter-dialog-format.js +3 -5
  38. package/dist/showing-by-doing.js +34 -31
  39. package/dist/snippets/README.en.md +3 -0
  40. package/dist/static/assets/{_baseUniq-C9vbtHF9.js → _baseUniq-C7IpU2Uk.js} +2 -2
  41. package/dist/static/assets/{_baseUniq-C9vbtHF9.js.map → _baseUniq-C7IpU2Uk.js.map} +1 -1
  42. package/dist/static/assets/{arc-hulXG01i.js → arc-1bhQqjON.js} +2 -2
  43. package/dist/static/assets/{arc-hulXG01i.js.map → arc-1bhQqjON.js.map} +1 -1
  44. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DdLIAMT5.js → architectureDiagram-VXUJARFQ-CkEi1QpB.js} +6 -6
  45. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DdLIAMT5.js.map → architectureDiagram-VXUJARFQ-CkEi1QpB.js.map} +1 -1
  46. package/dist/static/assets/{blockDiagram-VD42YOAC-DACsx66C.js → blockDiagram-VD42YOAC-DaBQ5-pY.js} +7 -7
  47. package/dist/static/assets/{blockDiagram-VD42YOAC-DACsx66C.js.map → blockDiagram-VD42YOAC-DaBQ5-pY.js.map} +1 -1
  48. package/dist/static/assets/{c4Diagram-YG6GDRKO-Cd5xZlLy.js → c4Diagram-YG6GDRKO-ChUgpgkP.js} +3 -3
  49. package/dist/static/assets/{c4Diagram-YG6GDRKO-Cd5xZlLy.js.map → c4Diagram-YG6GDRKO-ChUgpgkP.js.map} +1 -1
  50. package/dist/static/assets/{channel-NQehis0Z.js → channel-CxvmwllM.js} +2 -2
  51. package/dist/static/assets/{channel-NQehis0Z.js.map → channel-CxvmwllM.js.map} +1 -1
  52. package/dist/static/assets/{chunk-4BX2VUAB-DZDPl76b.js → chunk-4BX2VUAB-CKsrU2yk.js} +2 -2
  53. package/dist/static/assets/{chunk-4BX2VUAB-DZDPl76b.js.map → chunk-4BX2VUAB-CKsrU2yk.js.map} +1 -1
  54. package/dist/static/assets/{chunk-55IACEB6-CFSRDUbl.js → chunk-55IACEB6-BAau9SFt.js} +2 -2
  55. package/dist/static/assets/{chunk-55IACEB6-CFSRDUbl.js.map → chunk-55IACEB6-BAau9SFt.js.map} +1 -1
  56. package/dist/static/assets/{chunk-B4BG7PRW-BqQQ9M_z.js → chunk-B4BG7PRW--IiJ7W1m.js} +5 -5
  57. package/dist/static/assets/{chunk-B4BG7PRW-BqQQ9M_z.js.map → chunk-B4BG7PRW--IiJ7W1m.js.map} +1 -1
  58. package/dist/static/assets/{chunk-DI55MBZ5-FiFzz1Gh.js → chunk-DI55MBZ5-B83KrPQj.js} +4 -4
  59. package/dist/static/assets/{chunk-DI55MBZ5-FiFzz1Gh.js.map → chunk-DI55MBZ5-B83KrPQj.js.map} +1 -1
  60. package/dist/static/assets/{chunk-FMBD7UC4-DqqtCyWK.js → chunk-FMBD7UC4-BlDXzeza.js} +2 -2
  61. package/dist/static/assets/{chunk-FMBD7UC4-DqqtCyWK.js.map → chunk-FMBD7UC4-BlDXzeza.js.map} +1 -1
  62. package/dist/static/assets/{chunk-QN33PNHL-F0laQQ-J.js → chunk-QN33PNHL-B596W_v7.js} +2 -2
  63. package/dist/static/assets/{chunk-QN33PNHL-F0laQQ-J.js.map → chunk-QN33PNHL-B596W_v7.js.map} +1 -1
  64. package/dist/static/assets/{chunk-QZHKN3VN-CWhEZPaV.js → chunk-QZHKN3VN-UBBCxgBb.js} +2 -2
  65. package/dist/static/assets/{chunk-QZHKN3VN-CWhEZPaV.js.map → chunk-QZHKN3VN-UBBCxgBb.js.map} +1 -1
  66. package/dist/static/assets/{chunk-TZMSLE5B-Dx9cnwUy.js → chunk-TZMSLE5B-D-wCX2wJ.js} +2 -2
  67. package/dist/static/assets/{chunk-TZMSLE5B-Dx9cnwUy.js.map → chunk-TZMSLE5B-D-wCX2wJ.js.map} +1 -1
  68. package/dist/static/assets/{classDiagram-2ON5EDUG-Dp-dyEGy.js → classDiagram-2ON5EDUG-DvtmzPcu.js} +6 -6
  69. package/dist/static/assets/{classDiagram-2ON5EDUG-Dp-dyEGy.js.map → classDiagram-2ON5EDUG-DvtmzPcu.js.map} +1 -1
  70. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-Dp-dyEGy.js → classDiagram-v2-WZHVMYZB-DvtmzPcu.js} +6 -6
  71. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-Dp-dyEGy.js.map → classDiagram-v2-WZHVMYZB-DvtmzPcu.js.map} +1 -1
  72. package/dist/static/assets/{clone-C6mKvxs5.js → clone-DgJ0ZR-k.js} +2 -2
  73. package/dist/static/assets/{clone-C6mKvxs5.js.map → clone-DgJ0ZR-k.js.map} +1 -1
  74. package/dist/static/assets/{cose-bilkent-S5V4N54A-Dbwh3GoX.js → cose-bilkent-S5V4N54A-DXMyFQvy.js} +2 -2
  75. package/dist/static/assets/{cose-bilkent-S5V4N54A-Dbwh3GoX.js.map → cose-bilkent-S5V4N54A-DXMyFQvy.js.map} +1 -1
  76. package/dist/static/assets/{dagre-6UL2VRFP-BD_6e0Uk.js → dagre-6UL2VRFP-BdaUG-j_.js} +7 -7
  77. package/dist/static/assets/{dagre-6UL2VRFP-BD_6e0Uk.js.map → dagre-6UL2VRFP-BdaUG-j_.js.map} +1 -1
  78. package/dist/static/assets/{diagram-PSM6KHXK-BWt7Q59-.js → diagram-PSM6KHXK-NLiqKBzn.js} +7 -7
  79. package/dist/static/assets/{diagram-PSM6KHXK-BWt7Q59-.js.map → diagram-PSM6KHXK-NLiqKBzn.js.map} +1 -1
  80. package/dist/static/assets/{diagram-QEK2KX5R-D0BvBR_a.js → diagram-QEK2KX5R-D-0fyvY_.js} +6 -6
  81. package/dist/static/assets/{diagram-QEK2KX5R-D0BvBR_a.js.map → diagram-QEK2KX5R-D-0fyvY_.js.map} +1 -1
  82. package/dist/static/assets/{diagram-S2PKOQOG-D8uRdKXp.js → diagram-S2PKOQOG-BQ_FU59m.js} +6 -6
  83. package/dist/static/assets/{diagram-S2PKOQOG-D8uRdKXp.js.map → diagram-S2PKOQOG-BQ_FU59m.js.map} +1 -1
  84. package/dist/static/assets/{erDiagram-Q2GNP2WA-CQoifjFq.js → erDiagram-Q2GNP2WA-DyftKeuC.js} +5 -5
  85. package/dist/static/assets/{erDiagram-Q2GNP2WA-CQoifjFq.js.map → erDiagram-Q2GNP2WA-DyftKeuC.js.map} +1 -1
  86. package/dist/static/assets/{flowDiagram-NV44I4VS-CGhdeaG8.js → flowDiagram-NV44I4VS-9SGefONA.js} +6 -6
  87. package/dist/static/assets/{flowDiagram-NV44I4VS-CGhdeaG8.js.map → flowDiagram-NV44I4VS-9SGefONA.js.map} +1 -1
  88. package/dist/static/assets/{ganttDiagram-JELNMOA3-D8W0wb9H.js → ganttDiagram-JELNMOA3-k_WLhf-r.js} +3 -3
  89. package/dist/static/assets/{ganttDiagram-JELNMOA3-D8W0wb9H.js.map → ganttDiagram-JELNMOA3-k_WLhf-r.js.map} +1 -1
  90. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-ChHni_jP.js → gitGraphDiagram-NY62KEGX-3eoLlCOY.js} +7 -7
  91. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-ChHni_jP.js.map → gitGraphDiagram-NY62KEGX-3eoLlCOY.js.map} +1 -1
  92. package/dist/static/assets/{graph-BWoi_FgC.js → graph-vUevIs4s.js} +3 -3
  93. package/dist/static/assets/{graph-BWoi_FgC.js.map → graph-vUevIs4s.js.map} +1 -1
  94. package/dist/static/assets/{index-th_praGg.js → index-BNBG2CE1.js} +399 -68
  95. package/dist/static/assets/index-BNBG2CE1.js.map +1 -0
  96. package/dist/static/assets/{infoDiagram-WHAUD3N6-B_XKKZTV.js → infoDiagram-WHAUD3N6-CwEhVxkU.js} +5 -5
  97. package/dist/static/assets/{infoDiagram-WHAUD3N6-B_XKKZTV.js.map → infoDiagram-WHAUD3N6-CwEhVxkU.js.map} +1 -1
  98. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-ChGuQ6T9.js → journeyDiagram-XKPGCS4Q-Dtdq4G4Q.js} +5 -5
  99. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-ChGuQ6T9.js.map → journeyDiagram-XKPGCS4Q-Dtdq4G4Q.js.map} +1 -1
  100. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BjWe623u.js → kanban-definition-3W4ZIXB7-Bli-AycJ.js} +3 -3
  101. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BjWe623u.js.map → kanban-definition-3W4ZIXB7-Bli-AycJ.js.map} +1 -1
  102. package/dist/static/assets/{layout-BPyT310w.js → layout-CGlA8c09.js} +5 -5
  103. package/dist/static/assets/{layout-BPyT310w.js.map → layout-CGlA8c09.js.map} +1 -1
  104. package/dist/static/assets/{linear-xUsVjXWq.js → linear-Da2jDWL3.js} +2 -2
  105. package/dist/static/assets/{linear-xUsVjXWq.js.map → linear-Da2jDWL3.js.map} +1 -1
  106. package/dist/static/assets/{min-xFt7zeOd.js → min-Co741hTV.js} +3 -3
  107. package/dist/static/assets/{min-xFt7zeOd.js.map → min-Co741hTV.js.map} +1 -1
  108. package/dist/static/assets/{mindmap-definition-VGOIOE7T-DT_dvf2c.js → mindmap-definition-VGOIOE7T-DvkIjoq8.js} +4 -4
  109. package/dist/static/assets/{mindmap-definition-VGOIOE7T-DT_dvf2c.js.map → mindmap-definition-VGOIOE7T-DvkIjoq8.js.map} +1 -1
  110. package/dist/static/assets/{pieDiagram-ADFJNKIX-B1DQ-OaG.js → pieDiagram-ADFJNKIX-BGuGhTu8.js} +7 -7
  111. package/dist/static/assets/{pieDiagram-ADFJNKIX-B1DQ-OaG.js.map → pieDiagram-ADFJNKIX-BGuGhTu8.js.map} +1 -1
  112. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-IHqyr3iT.js → quadrantDiagram-AYHSOK5B-DAZcrJMg.js} +3 -3
  113. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-IHqyr3iT.js.map → quadrantDiagram-AYHSOK5B-DAZcrJMg.js.map} +1 -1
  114. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CKBpht7B.js → requirementDiagram-UZGBJVZJ-CXN0DxZs.js} +4 -4
  115. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CKBpht7B.js.map → requirementDiagram-UZGBJVZJ-CXN0DxZs.js.map} +1 -1
  116. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-D2uGjv3i.js → sankeyDiagram-TZEHDZUN-B7-yAePZ.js} +2 -2
  117. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-D2uGjv3i.js.map → sankeyDiagram-TZEHDZUN-B7-yAePZ.js.map} +1 -1
  118. package/dist/static/assets/{sequenceDiagram-WL72ISMW-wLFRhAKd.js → sequenceDiagram-WL72ISMW-DfBNY6h_.js} +4 -4
  119. package/dist/static/assets/{sequenceDiagram-WL72ISMW-wLFRhAKd.js.map → sequenceDiagram-WL72ISMW-DfBNY6h_.js.map} +1 -1
  120. package/dist/static/assets/{stateDiagram-FKZM4ZOC-BFGQTbx5.js → stateDiagram-FKZM4ZOC-BLo1xRVY.js} +9 -9
  121. package/dist/static/assets/{stateDiagram-FKZM4ZOC-BFGQTbx5.js.map → stateDiagram-FKZM4ZOC-BLo1xRVY.js.map} +1 -1
  122. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-DF7AjJuk.js → stateDiagram-v2-4FDKWEC3-Dq7MAD0I.js} +5 -5
  123. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-DF7AjJuk.js.map → stateDiagram-v2-4FDKWEC3-Dq7MAD0I.js.map} +1 -1
  124. package/dist/static/assets/{timeline-definition-IT6M3QCI-ChHFOb0o.js → timeline-definition-IT6M3QCI-ySWyBF3b.js} +3 -3
  125. package/dist/static/assets/{timeline-definition-IT6M3QCI-ChHFOb0o.js.map → timeline-definition-IT6M3QCI-ySWyBF3b.js.map} +1 -1
  126. package/dist/static/assets/{treemap-KMMF4GRG-BxaNvQU4.js → treemap-KMMF4GRG-DOp4sqOh.js} +4 -4
  127. package/dist/static/assets/{treemap-KMMF4GRG-BxaNvQU4.js.map → treemap-KMMF4GRG-DOp4sqOh.js.map} +1 -1
  128. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CrNKeY_-.js → xychartDiagram-PRI3JC2R-vkmh67qb.js} +3 -3
  129. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CrNKeY_-.js.map → xychartDiagram-PRI3JC2R-vkmh67qb.js.map} +1 -1
  130. package/dist/static/index.html +1 -1
  131. package/dist/team.js +29 -6
  132. package/dist/tool.js +56 -0
  133. package/dist/tools/builtins.js +4 -2
  134. package/dist/tools/context-health.js +7 -7
  135. package/dist/tools/os.js +267 -30
  136. package/dist/tools/pending-tellask-reminder.js +185 -0
  137. package/dist/tools/plan.js +1 -0
  138. package/dist/tools/ripgrep.js +145 -4
  139. package/dist/tools/shell-tools.js +21 -0
  140. package/dist/tools/team-mgmt.js +4 -4
  141. package/dist/tools/toolset-manual.js +74 -0
  142. package/dist/utils/task-doc.js +16 -16
  143. package/package.json +1 -1
  144. package/dist/minds/builtin/cmdr/persona.md +0 -3
  145. package/dist/minds/builtin/dijiang/knowledge.md +0 -287
  146. package/dist/minds/builtin/dijiang/persona.md +0 -7
  147. package/dist/static/assets/index-th_praGg.js.map +0 -1
  148. package/dist/static/testing/dom-observation-utils.js +0 -425
  149. package/dist/static/testing/e2e-test-helper.js +0 -3119
@@ -54,6 +54,7 @@ const server_runtime_1 = require("./server-runtime");
54
54
  const tool_names_1 = require("./tool-names");
55
55
  const log = (0, log_1.createLogger)('mcp/supervisor');
56
56
  const MCP_YAML_PATH = path.join('.minds', 'mcp.yaml');
57
+ const MCP_TOOL_CALL_PROBLEM_PREFIX = 'mcp/tool_call_error/';
57
58
  const serverStateById = new Map();
58
59
  const toolOwnerByName = new Map();
59
60
  const toolsetOwnerByName = new Map();
@@ -150,41 +151,54 @@ class McpServerDispatch {
150
151
  }
151
152
  }
152
153
  async callToolForDialog(dlg, mcpToolName, args) {
154
+ const serverId = this.serverId;
155
+ const withActionableError = async (fn) => {
156
+ try {
157
+ const raw = await fn();
158
+ const out = await materializeMcpToolCallOutput({
159
+ dlg,
160
+ serverId,
161
+ toolName: mcpToolName,
162
+ raw,
163
+ });
164
+ clearMcpToolCallProblem(serverId);
165
+ return out;
166
+ }
167
+ catch (err) {
168
+ const workLanguage = (0, runtime_language_1.getWorkLanguage)();
169
+ const errorText = err instanceof Error ? err.message : String(err);
170
+ upsertMcpToolCallProblem({
171
+ serverId,
172
+ toolName: mcpToolName,
173
+ errorText,
174
+ });
175
+ const msg = workLanguage === 'zh'
176
+ ? `MCP 工具调用失败(详见 Problems 面板):${serverId}.${mcpToolName}: ${errorText}`
177
+ : `MCP tool call failed (see Problems panel): ${serverId}.${mcpToolName}: ${errorText}`;
178
+ const wrapped = new Error(msg);
179
+ // Attach the original error for debugging without relying on ErrorOptions typing.
180
+ wrapped.cause = err;
181
+ throw wrapped;
182
+ }
183
+ };
153
184
  if (this.cfg.truelyStateless) {
154
- if (!this.sharedRuntime) {
185
+ const sharedRuntime = this.sharedRuntime;
186
+ if (!sharedRuntime) {
155
187
  throw new Error(`MCP server '${this.serverId}' missing shared runtime`);
156
188
  }
157
- const raw = await this.sharedRuntime.callToolRaw(mcpToolName, args);
158
- return await materializeMcpToolCallOutput({
159
- dlg,
160
- serverId: this.serverId,
161
- toolName: mcpToolName,
162
- raw,
163
- });
189
+ return await withActionableError(async () => await sharedRuntime.callToolRaw(mcpToolName, args));
164
190
  }
165
191
  const dialogKey = dlg.id.key();
166
192
  const existing = this.leasesByDialogKey.get(dialogKey);
167
193
  if (existing) {
168
194
  this.attachLeaseReminder(dlg);
169
- const raw = await existing.callToolRaw(mcpToolName, args);
170
- return await materializeMcpToolCallOutput({
171
- dlg,
172
- serverId: this.serverId,
173
- toolName: mcpToolName,
174
- raw,
175
- });
195
+ return await withActionableError(async () => await existing.callToolRaw(mcpToolName, args));
176
196
  }
177
197
  if (this.stopRequested) {
178
198
  const oneShot = await this.connectNewLeaseRuntime();
179
199
  this.attachLeaseReminder(dlg);
180
200
  try {
181
- const raw = await oneShot.callToolRaw(mcpToolName, args);
182
- return await materializeMcpToolCallOutput({
183
- dlg,
184
- serverId: this.serverId,
185
- toolName: mcpToolName,
186
- raw,
187
- });
201
+ return await withActionableError(async () => await oneShot.callToolRaw(mcpToolName, args));
188
202
  }
189
203
  finally {
190
204
  oneShot.requestStop({ forceKillAfterMs: 3000 });
@@ -209,13 +223,7 @@ class McpServerDispatch {
209
223
  }
210
224
  const runtime = await init;
211
225
  this.attachLeaseReminder(dlg);
212
- const raw = await runtime.callToolRaw(mcpToolName, args);
213
- return await materializeMcpToolCallOutput({
214
- dlg,
215
- serverId: this.serverId,
216
- toolName: mcpToolName,
217
- raw,
218
- });
226
+ return await withActionableError(async () => await runtime.callToolRaw(mcpToolName, args));
219
227
  }
220
228
  async connectNewLeaseRuntime() {
221
229
  const serverId = this.serverId;
@@ -280,14 +288,28 @@ let mindsDirWatcher;
280
288
  let workspaceWatcher;
281
289
  let pollTimer;
282
290
  let debounceTimer;
283
- let lastSeenMtimeMs;
291
+ let lastSeenMcpYamlSig;
284
292
  let reloadChain = Promise.resolve();
293
+ let supervisorStarted = false;
285
294
  function startMcpSupervisor() {
295
+ if (supervisorStarted)
296
+ return;
297
+ supervisorStarted = true;
286
298
  reloadChain = reloadChain
287
299
  .then(async () => await reloadNow('startup'))
288
300
  .catch((err) => {
289
301
  log.warn('MCP initial load failed', err);
290
302
  });
303
+ // Initialize signature baseline (best-effort). This reduces false negatives in polling on filesystems
304
+ // with coarse mtime resolution.
305
+ reloadChain = reloadChain
306
+ .then(async () => {
307
+ const sig = await readMcpYamlSig();
308
+ lastSeenMcpYamlSig = sig;
309
+ })
310
+ .catch((err) => {
311
+ log.warn('MCP initial signature read failed', err);
312
+ });
291
313
  // Best-effort file watch (fast feedback). `.minds/` may be wiped/recreated during a dev session,
292
314
  // so watcher setup must be resilient and re-attempted at runtime.
293
315
  void ensureMindsDirWatcher('startup');
@@ -299,6 +321,7 @@ function startMcpSupervisor() {
299
321
  if (name !== '' && name !== path.dirname(MCP_YAML_PATH))
300
322
  return;
301
323
  void ensureMindsDirWatcher('rtws.watch');
324
+ scheduleReload('rtws.watch');
302
325
  });
303
326
  workspaceWatcher.on('error', () => {
304
327
  if (workspaceWatcher) {
@@ -333,6 +356,8 @@ function stopMcpSupervisor() {
333
356
  clearTimeout(debounceTimer);
334
357
  debounceTimer = undefined;
335
358
  }
359
+ lastSeenMcpYamlSig = undefined;
360
+ supervisorStarted = false;
336
361
  }
337
362
  function requestMcpServerRestart(serverId) {
338
363
  return new Promise((resolve) => {
@@ -416,25 +441,32 @@ function scheduleReload(reason) {
416
441
  });
417
442
  }, 200);
418
443
  }
419
- async function maybePollReload() {
420
- let mtimeMs;
444
+ async function readMcpYamlSig() {
421
445
  try {
422
446
  const st = await fs.promises.stat(MCP_YAML_PATH);
423
- mtimeMs = st.mtimeMs;
447
+ if (!st.isFile()) {
448
+ return `not_file/${st.size}/${st.mtimeMs}/${st.ctimeMs}`;
449
+ }
450
+ return `${st.size}/${st.mtimeMs}/${st.ctimeMs}`;
424
451
  }
425
452
  catch (err) {
426
453
  const code = isRecord(err) && 'code' in err ? err.code : undefined;
427
454
  if (code === 'ENOENT') {
428
- mtimeMs = 0;
429
- }
430
- else {
431
- return;
455
+ return 'missing';
432
456
  }
457
+ return 'error';
433
458
  }
434
- if (lastSeenMtimeMs === undefined || mtimeMs !== lastSeenMtimeMs) {
435
- lastSeenMtimeMs = mtimeMs;
436
- scheduleReload('poll');
459
+ }
460
+ async function maybePollReload() {
461
+ const sig = await readMcpYamlSig();
462
+ if (lastSeenMcpYamlSig === undefined) {
463
+ lastSeenMcpYamlSig = sig;
464
+ return;
437
465
  }
466
+ if (sig === lastSeenMcpYamlSig)
467
+ return;
468
+ lastSeenMcpYamlSig = sig;
469
+ scheduleReload('poll');
438
470
  }
439
471
  async function reloadNow(reason) {
440
472
  let rawText;
@@ -542,6 +574,47 @@ function upsertWorkspaceConfigProblem(errorText) {
542
574
  function clearWorkspaceConfigProblem() {
543
575
  (0, problems_1.removeProblemsByPrefix)('mcp/workspace_config_error');
544
576
  }
577
+ function upsertMcpToolCallProblem(args) {
578
+ const workLanguage = (0, runtime_language_1.getWorkLanguage)();
579
+ const normalizedErrorText = args.errorText.length > 10000 ? `${args.errorText.slice(0, 10000)}…` : args.errorText;
580
+ const hintLines = workLanguage === 'zh'
581
+ ? [
582
+ '建议排查:',
583
+ `- 先释放租约:mcp_release({"serverId":"${args.serverId}"})`,
584
+ `- 重新打开/关闭浏览器窗口,避免 Playwright persistent context 残留`,
585
+ `- 查看 ${MCP_YAML_PATH} 是否已加载且配置正确(Problems 面板 / 后端日志)`,
586
+ ]
587
+ : [
588
+ 'Suggested checks:',
589
+ `- Release the lease first: mcp_release({"serverId":"${args.serverId}"})`,
590
+ `- Close/reopen browser windows to avoid leftover Playwright persistent contexts`,
591
+ `- Verify ${MCP_YAML_PATH} is loaded and valid (Problems panel / backend logs)`,
592
+ ];
593
+ (0, problems_1.upsertProblem)({
594
+ kind: 'generic_problem',
595
+ source: 'system',
596
+ id: `${MCP_TOOL_CALL_PROBLEM_PREFIX}${sanitizePathSegment(args.serverId)}`,
597
+ severity: 'error',
598
+ timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
599
+ message: workLanguage === 'zh'
600
+ ? `MCP 工具调用失败:${args.serverId}.${args.toolName}`
601
+ : `MCP tool call failed: ${args.serverId}.${args.toolName}`,
602
+ detail: {
603
+ text: [
604
+ `serverId=${args.serverId}`,
605
+ `toolName=${args.toolName}`,
606
+ '',
607
+ 'error:',
608
+ normalizedErrorText,
609
+ '',
610
+ ...hintLines,
611
+ ].join('\n'),
612
+ },
613
+ });
614
+ }
615
+ function clearMcpToolCallProblem(serverId) {
616
+ (0, problems_1.removeProblemsByPrefix)(`${MCP_TOOL_CALL_PROBLEM_PREFIX}${sanitizePathSegment(serverId)}`);
617
+ }
545
618
  async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder, validServerIdsInYamlOrder, reason) {
546
619
  log.info(`Applying MCP rtws config (${reason})`);
547
620
  const invalidIds = new Set(invalidServers.map((s) => s.serverId));
@@ -46,7 +46,7 @@
46
46
 
47
47
  2. **经授权响应其他智能体**:收到@fuxi 以外智能体以 `!?@pangu` 从第 0 列开头的诉请时,**不做任何操作预判**,立即 `!?@fuxi` 发起授权确认;获@fuxi 授权后,按要求执行并同步结果;未获授权,直接拒绝并同步。
48
48
 
49
- 3. **通用执行要求**:若诉请模糊、存在潜在风险或超出自身操作边界,立即向发起方+@fuxi 同步确认细节;若诉请涉及 .minds/ 目录,直接@fuxi 并向发起方明确拒绝。
49
+ 3. **通用执行要求**:若诉请模糊、存在潜在风险或超出自身操作边界,立即向诉请者+@fuxi 同步确认细节;若诉请涉及 .minds/ 目录,直接@fuxi 并向诉请者明确拒绝。
50
50
 
51
51
  ### 二、开创性工作(唯一主动介入,先商后做)
52
52
 
@@ -80,7 +80,7 @@
80
80
 
81
81
  3. **与显在团队成员交流**:收到其@pangu 开头的诉请时,仅回复授权确认进展,不做操作承诺。
82
82
 
83
- 4. **交流频率**:执行诉请遇阻时立即以 `!?@<发起方>`+`!?@fuxi` 并列诉请,发现 rtws 问题时立即@fuxi。
83
+ 4. **交流频率**:执行诉请遇阻时立即以 `!?@<诉请者>`+`!?@fuxi` 并列诉请,发现 rtws 问题时立即@fuxi。
84
84
 
85
85
  ## 行动准则
86
86
 
@@ -8,133 +8,15 @@ const promises_1 = require("fs/promises");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const dialog_1 = require("../dialog");
10
10
  const log_1 = require("../log");
11
- const text_1 = require("../shared/i18n/text");
12
11
  const runtime_language_1 = require("../shared/runtime-language");
13
12
  const time_1 = require("../shared/utils/time");
14
13
  const team_1 = require("../team");
15
14
  const ctrl_1 = require("../tools/ctrl");
16
- const registry_1 = require("../tools/registry");
15
+ const shell_tools_1 = require("../tools/shell-tools");
16
+ const toolset_manual_1 = require("../tools/toolset-manual");
17
17
  const minds_i18n_1 = require("./minds-i18n");
18
18
  const system_prompt_1 = require("./system-prompt");
19
- const SHELL_TOOL_NAMES = ['shell_cmd', 'stop_daemon', 'get_daemon_output'];
20
- function isShellToolName(name) {
21
- return SHELL_TOOL_NAMES.includes(name);
22
- }
23
- function listShellSpecialistMemberIds(team) {
24
- const out = [];
25
- for (const id of team.shellSpecialists) {
26
- const member = team.getMember(id);
27
- if (!member)
28
- continue;
29
- if (member.hidden === true)
30
- continue;
31
- out.push(id);
32
- }
33
- return out;
34
- }
35
- function buildShellPolicyPrompt(options) {
36
- const { language, agentIsShellSpecialist, agentHasShellTools, agentHasReadonlyShell, shellSpecialistMemberIds, } = options;
37
- const title = language === 'zh' ? '### Shell 执行策略(重要)' : '### Shell Execution Policy (Important)';
38
- const shellSpecialists = shellSpecialistMemberIds.length > 0
39
- ? shellSpecialistMemberIds.map((id) => `@${id}`).join(', ')
40
- : language === 'zh'
41
- ? '(未配置 shell 专员)'
42
- : '(no shell specialists configured)';
43
- if (agentIsShellSpecialist && agentHasShellTools) {
44
- const body = language === 'zh'
45
- ? [
46
- '你是本队的 shell 专员,具备 shell 执行能力(高风险)。使用前必须先做风险识别与最小化:',
47
- '- 说明目的、预期输出/验证方式、预期工作目录与影响面。',
48
- '- 优先选择只读命令;写入/删除/网络/权限相关操作必须解释理由与安全边界。',
49
- '- 如果不确定命令后果,先提出更安全的替代方案或向人类/队友确认。',
50
- '',
51
- '当队友请求你执行命令时:请先复述你将执行的命令与风险边界,再执行,并按结构化格式回传 command/exit_code/stdout/stderr。',
52
- '',
53
- `本队 shell 专员列表:${shellSpecialists}`,
54
- ].join('\n')
55
- : [
56
- 'You are a designated shell specialist and have shell execution capability (high-risk). Before using it, do risk identification and minimize blast radius:',
57
- '- State intent, expected output/verification, expected working directory, and scope of impact.',
58
- '- Prefer read-only commands; for writes/deletes/network/privilege-related actions, justify and state safety boundaries.',
59
- '- If unsure about consequences, propose a safer alternative or confirm with a human/teammate first.',
60
- '',
61
- 'When teammates ask you to run commands: restate the exact command and guardrails, then execute, and report back with a structured receipt: command/exit_code/stdout/stderr.',
62
- '',
63
- `Shell specialists in this team: ${shellSpecialists}`,
64
- ].join('\n');
65
- return `${title}\n\n${body}`.trim();
66
- }
67
- if (agentIsShellSpecialist && !agentHasShellTools) {
68
- const body = language === 'zh'
69
- ? [
70
- '你被配置为 shell 专员,但当前没有可用的 shell 工具(团队配置错误)。',
71
- '在未修复配置前:不要声称自己执行过命令;如需验证,请让人类修复 team.yaml 或把 shell 能力授予正确的成员。',
72
- '',
73
- `本队 shell 专员列表:${shellSpecialists}`,
74
- ].join('\n')
75
- : [
76
- 'You are configured as a shell specialist, but you do not currently have shell tools available (team configuration error).',
77
- 'Until it is fixed: do not claim you ran any command; ask a human to fix team.yaml or grant shell tools to the correct specialist member.',
78
- '',
79
- `Shell specialists in this team: ${shellSpecialists}`,
80
- ].join('\n');
81
- return `${title}\n\n${body}`.trim();
82
- }
83
- const body = language === 'zh'
84
- ? agentHasReadonlyShell
85
- ? [
86
- '你不具备高权限 shell 工具(shell_cmd/stop_daemon/get_daemon_output)。',
87
- '你已被明确授权使用 `readonly_shell` 自行执行只读命令(仅允许白名单命令前缀):请直接调用,不要去寻找 shell 专员代跑。',
88
- '',
89
- '当你需要的命令不在白名单内,或需要写入/删除/网络/长时间运行/进程管理等高风险能力时:再转交给具备 shell 工具的专员队友,并提供充分理由与可审查的命令提案:',
90
- '- 你要达成的目标(why)',
91
- '- 建议命令(what)+ 预期工作目录(cwd)+ 预期输出/验证方式(how to verify)',
92
- '- 风险评估与安全边界(risk & guardrails)',
93
- `可转交的 shell 专员队友:${shellSpecialists}`,
94
- '',
95
- '重要:如果你打算让队友执行命令,请在同一条消息里给出完整的 tellask 诉请块(以第 0 列开头的 `!?@<shell-specialist>` 行),不要只说“我会请某人运行”。',
96
- '重要:在你看到 shell 专员的回执(command/exit_code/stdout/stderr)之前,不要声称“已运行/已通过/无错”。',
97
- ].join('\n')
98
- : [
99
- '你不具备 shell 工具(本环境仅 shell 专员可执行 shell):不要尝试“编造/假设”命令输出,也不要要求系统直接执行。',
100
- '当你确实需要 shell 执行时:请转交给具备 shell 能力的专员队友,并提供充分理由与可审查的命令提案:',
101
- '- 你要达成的目标(why)',
102
- '- 建议命令(what)+ 预期工作目录(cwd)+ 预期输出/验证方式(how to verify)',
103
- '- 风险评估与安全边界(risk & guardrails)',
104
- `可转交的 shell 专员队友:${shellSpecialists}`,
105
- '',
106
- '重要:如果你打算让队友执行命令,请在同一条消息里给出完整的 tellask 诉请块(以第 0 列开头的 `!?@<shell-specialist>` 行),不要只说“我会请某人运行”。',
107
- '重要:在你看到 shell 专员的回执(command/exit_code/stdout/stderr)之前,不要声称“已运行/已通过/无错”。',
108
- ].join('\n')
109
- : agentHasReadonlyShell
110
- ? [
111
- 'You do not have high-risk shell tools (shell_cmd/stop_daemon/get_daemon_output).',
112
- 'You are explicitly authorized to use `readonly_shell` yourself for read-only inspection via its small allowlist. Call it directly; do not go looking for a shell specialist to run it for you.',
113
- '',
114
- 'When the command you need is not in the allowlist, or you need high-risk capabilities like writes/deletes/network/long-running jobs/process management: delegate to a shell specialist teammate with a justified, reviewable proposal:',
115
- '- Goal (why)',
116
- '- Proposed command (what) + expected working directory (cwd) + expected output/verification (how to verify)',
117
- '- Risk assessment and guardrails (risk & guardrails)',
118
- '',
119
- `Shell specialist teammates: ${shellSpecialists}`,
120
- '',
121
- 'Important: if you intend to delegate, include the full tellask block (a column-0 `!?@<shell-specialist>` line) in the same message; do not just say “I will ask someone to run it”.',
122
- 'Important: do not claim “ran/passed/no errors” until you see the shell specialist’s receipt (command/exit_code/stdout/stderr).',
123
- ].join('\n')
124
- : [
125
- 'You do not have shell tools configured (shell execution is restricted to designated specialists): do not fabricate/assume command output, and do not ask the system to execute commands directly.',
126
- 'When you truly need shell execution, delegate to a shell specialist teammate with a justified, reviewable proposal:',
127
- '- Goal (why)',
128
- '- Proposed command (what) + expected working directory (cwd) + expected output/verification (how to verify)',
129
- '- Risk assessment and guardrails (risk & guardrails)',
130
- '',
131
- `Shell specialist teammates: ${shellSpecialists}`,
132
- '',
133
- 'Important: if you intend to delegate, include the full tellask block (a column-0 `!?@<shell-specialist>` line) in the same message; do not just say “I will ask someone to run it”.',
134
- 'Important: do not claim “ran/passed/no errors” until you see the shell specialist’s receipt (command/exit_code/stdout/stderr).',
135
- ].join('\n');
136
- return `${title}\n\n${body}`.trim();
137
- }
19
+ const system_prompt_parts_1 = require("./system-prompt-parts");
138
20
  async function readAgentMindResult(id, fn) {
139
21
  const mindFn = path_1.default.join('.minds', 'team', id, fn);
140
22
  try {
@@ -221,8 +103,9 @@ async function readMindsTextPreferred(options) {
221
103
  }
222
104
  return options.noFileDefault;
223
105
  }
224
- async function loadAgentMinds(agentId, dialog) {
106
+ async function loadAgentMinds(agentId, dialog, options) {
225
107
  const workingLanguage = (0, runtime_language_1.getWorkLanguage)();
108
+ const missingToolsetPolicy = options?.missingToolsetPolicy ?? 'warn';
226
109
  let team = await team_1.Team.load();
227
110
  const agent = agentId === undefined ? team.getDefaultResponder() : team.getMember(agentId);
228
111
  if (!agent)
@@ -260,10 +143,10 @@ async function loadAgentMinds(agentId, dialog) {
260
143
  // policy and may carry shell tools.
261
144
  const agentIsShellSpecialist = team.shellSpecialists.includes(agent.id) || agent.hidden === true;
262
145
  const baseAgentTools = (() => {
263
- const tools = agent.listTools();
146
+ const tools = agent.listTools({ onMissingToolset: missingToolsetPolicy });
264
147
  if (agentIsShellSpecialist)
265
148
  return tools;
266
- return tools.filter((t) => !(t.type === 'func' && typeof t.name === 'string' && isShellToolName(t.name)));
149
+ return tools.filter((t) => !(t.type === 'func' && typeof t.name === 'string' && (0, shell_tools_1.isShellToolName)(t.name)));
267
150
  })();
268
151
  // Inject intrinsic dialog control tools as function tools (available to all agents).
269
152
  const intrinsicFuncTools = [
@@ -288,38 +171,24 @@ async function loadAgentMinds(agentId, dialog) {
288
171
  }
289
172
  return out;
290
173
  })();
174
+ const toolsetNames = agent
175
+ .listResolvedToolsetNames({ onMissing: missingToolsetPolicy })
176
+ .filter((name) => {
177
+ if (name === 'os')
178
+ return agentIsShellSpecialist;
179
+ return true;
180
+ });
181
+ const manualTools = (0, toolset_manual_1.buildToolsetManualTools)({
182
+ toolsetNames,
183
+ existingToolNames: new Set(agentTools.map((t) => t.name)),
184
+ });
185
+ if (manualTools.tools.length > 0) {
186
+ agentTools.push(...manualTools.tools);
187
+ }
291
188
  const funcTools = agentTools.filter((t) => t.type === 'func');
292
- const agentHasShellTools = funcTools.some((t) => isShellToolName(t.name));
189
+ const agentHasShellTools = funcTools.some((t) => (0, shell_tools_1.isShellToolName)(t.name));
293
190
  const agentHasReadonlyShell = funcTools.some((t) => t.name === 'readonly_shell');
294
- const shellSpecialistMemberIds = listShellSpecialistMemberIds(team);
295
- const shellPolicyPrompt = buildShellPolicyPrompt({
296
- language: workingLanguage,
297
- agentIsShellSpecialist,
298
- agentHasShellTools,
299
- agentHasReadonlyShell,
300
- shellSpecialistMemberIds,
301
- });
302
- const toolsetPromptText = (() => {
303
- const toolsetNames = agent.listResolvedToolsetNames().filter((name) => {
304
- if (name === 'os')
305
- return agentIsShellSpecialist;
306
- return true;
307
- });
308
- const blocks = toolsetNames
309
- .map((toolsetName) => {
310
- const promptI18n = (0, registry_1.getToolsetPromptI18n)(toolsetName);
311
- const prompt = (0, text_1.getTextForLanguage)({ i18n: promptI18n, fallback: '' }, workingLanguage).trim();
312
- if (prompt === '')
313
- return '';
314
- const title = workingLanguage === 'zh'
315
- ? `### Toolset 提示:${toolsetName}`
316
- : `### Toolset prompt: ${toolsetName}`;
317
- return `${title}\n\n${prompt}`;
318
- })
319
- .filter((b) => b !== '');
320
- return blocks.join('\n\n');
321
- })();
322
- const memorySystemTitle = workingLanguage === 'zh' ? '### 记忆系统(重要)' : '### Memory System (Important)';
191
+ const shellSpecialistMemberIds = (0, shell_tools_1.listShellSpecialistMemberIds)(team);
323
192
  const TEAM_MEMORY_TOOL_NAMES = [
324
193
  'add_team_memory',
325
194
  'replace_team_memory',
@@ -342,145 +211,41 @@ async function loadAgentMinds(agentId, dialog) {
342
211
  const agentHasPersonalMemoryTools = funcTools.some((t) => isPersonalMemoryToolName(t.name));
343
212
  const isSubdialog = dialog !== undefined && dialog.supdialog !== undefined;
344
213
  const taskdocMaintainerId = dialog && dialog instanceof dialog_1.SubDialog ? dialog.rootDialog.agentId : agent.id;
345
- const memorySystemBody = (() => {
346
- if (workingLanguage === 'zh') {
347
- const teamMemoryLine = '- 团队记忆:稳定的团队约定/工程规约(跨任务共享)。';
348
- const personalMemoryLine = '- 个人记忆:稳定的个人习惯/偏好与职责域知识;可维护你职责范围内的“rtws 索引”(关键文档/代码的准确路径 + 必要要点),以减少重复读文件;不要记录具体任务状态。';
349
- return [
350
- '你的聊天记录与工具输出是临时信息:会快速累积、很快过时,并增加你的认知负担。在同一轮对话中,除了 `clear_mind` 以外你无法真正丢弃这些历史。',
351
- '`clear_mind` 会开启新一程对话(保留差遣牒、提醒项与记忆层),从而卸掉这部分认知负载并继续推进。因此你必须先把关键信息提炼到高价值载体:',
352
- '- 差遣牒(Taskdoc,`*.tsk/`):全队共享的任务契约(goals/constraints/progress);保持足够短,每轮都应可通读。',
353
- `- 更新差遣牒的任意分段时:每次调用会替换该分段全文;你必须先对照“上下文中注入的当前内容”做合并/压缩;禁止覆盖/抹掉他人条目;自己负责维护的条目必须标注责任人(例如 \`- [owner:@${agent.id}] ...\` 或用 \`### @${agent.id}\` 分块)。`,
354
- '- 其中 `progress` 是全队共享公告牌:用于“阶段性进度快照”(关键决策/当前状态/下一步),不是流水账。',
355
- '- 重要:差遣牒内容会被系统以内联形式注入到上下文中(本轮生成视角下即为最新)。需要回顾时请直接基于上下文里的差遣牒内容回顾与决策,不要试图用通用文件工具读取 `*.tsk/` 下的文件(会被拒绝)。',
356
- '- 约定:`constraints` 尽量只写任务特有的硬要求。系统提示/工具文档里已明确且由系统强制执行的通用规则(例如 `*.tsk/` 封装禁止通用文件工具)无需重复写入 `constraints.md`。',
357
- '- 提醒项(工作集):当前对话的高频工作记录/关键细节(偏私有,不作为全队公告);保持少量(常见 1–3 条),优先 `update_reminder` 压缩/合并,不再需要就 `delete_reminder`。',
358
- teamMemoryLine,
359
- personalMemoryLine,
360
- '',
361
- ...(isSubdialog
362
- ? [
363
- `你当前处于支线对话:此处不允许 \`change_mind\`。当你判断需要更新差遣牒(尤其是 progress 公告牌)时,请在合适时机直接诉请差遣牒维护人 \`@${taskdocMaintainerId}\` 执行更新,并给出你已合并好的“新全文/替换稿”(用于替换对应章节全文)。不要声称已更新,除非看到回执。`,
364
- ]
365
- : [
366
- '你当前处于主线对话:你负责综合维护全队共享差遣牒(尤其是 progress 公告牌)。当队友/支线对话提出更新建议时,及时合并、压缩并保持清晰。',
367
- ]),
368
- ...(agentHasTeamMemoryTools
369
- ? [
370
- '提示:你具备团队记忆工具(`add_team_memory` / `replace_team_memory` / `drop_team_memory` / `clear_team_memory`),可在必要时维护团队记忆(谨慎、少量、只写稳定约定)。',
371
- ]
372
- : []),
373
- ...(agentHasPersonalMemoryTools
374
- ? [
375
- '提示:你具备个人记忆工具(`add_memory` / `replace_memory` / `drop_memory` / `clear_memory`)。目标:维护你职责域的“rtws 索引”(关键文档/代码的准确路径 + 最小必要要点,如入口文件/关键符号/约定),让你在职责范围内尽量做到“0 次 ripgrep 就能开始干活”;一旦你修改了相关文件或发现记忆有过期/冲突,必须立刻用 `replace_memory` 把对应条目更新为最新事实。',
376
- ]
377
- : []),
378
- ...(isSubdialog
379
- ? [
380
- `工作流:先做事 → 再提炼(\`update_reminder\`;必要时整理差遣牒更新提案并诉请 \`@${taskdocMaintainerId}\` 合并写入)→ 然后 \`clear_mind\` 清空噪音。`,
381
- ]
382
- : [
383
- '工作流:先做事 → 再提炼(`update_reminder` + `change_mind(progress)`)→ 然后 `clear_mind` 清空噪音。',
384
- ]),
385
- '当 context health 变黄/红:立刻停止继续大实现/大阅读;先提炼,再 clear。',
386
- '不要把长日志/大段 tool output 直接塞进差遣牒;差遣牒只写结论+下一步;细节只保留必要摘录放提醒项。',
387
- ].join('\n');
388
- }
389
- const teamMemoryLine = '- Team memory: stable shared conventions (cross-task).';
390
- const personalMemoryLine = '- Personal memory: stable personal habits/preferences and responsibility-scope knowledge. Maintain a compact responsibility-area rtws index (exact key doc/code paths + minimal key facts) to reduce repeat file reads; do not store per-task state.';
391
- return [
392
- 'Dialog history and tool outputs are temporary: they accumulate quickly, become stale, and increase cognitive load. Within a course, you cannot truly drop that history except via `clear_mind`.',
393
- '`clear_mind` starts a new course while preserving Taskdoc, reminders, and memory layers. Therefore, before clearing, distill key information into durable layers:',
394
- '- Taskdoc (`*.tsk/`): team-shared task contract (goals/constraints/progress). Keep it small enough to read every course.',
395
- `- When updating any Taskdoc section: each call replaces the entire section; always start from the current injected content and merge/compress; do not overwrite other contributors; add an explicit owner tag for entries you maintain (e.g., \`- [owner:@${agent.id}] ...\` or a \`### @${agent.id}\` block).`,
396
- '- Taskdoc `progress` is the team’s shared bulletin board: distilled milestone snapshots (key decisions/current status/next steps), not raw logs.',
397
- '- Important: the Taskdoc content is injected inline into the context (the latest as of this generation). Review the injected Taskdoc instead of trying to read files under `*.tsk/` via general file tools (they will be rejected).',
398
- '- Convention: keep Taskdoc `constraints` focused on task-specific requirements. Do not duplicate global, system-enforced rules already stated in system prompt/tool docs (e.g. `.tsk/` encapsulation bans general file tools).',
399
- '- Reminders (working set): your high-frequency per-dialog worklog + critical details (not a team bulletin board); keep it small (often 1–3 items), prefer `update_reminder` to compress/merge; delete when obsolete.',
400
- teamMemoryLine,
401
- personalMemoryLine,
402
- '',
403
- ...(isSubdialog
404
- ? [
405
- `You are currently in a subdialog: \`change_mind\` is not allowed here. When Taskdoc should be updated (especially the shared progress bulletin board), tellask the Taskdoc maintainer \`@${taskdocMaintainerId}\` with a fully merged replacement draft (full-section replacement). Do not claim it is updated until you see a receipt.`,
406
- ]
407
- : [
408
- '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/subdialogs promptly and keep it concise.',
409
- ]),
410
- ...(agentHasTeamMemoryTools
411
- ? [
412
- '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.',
413
- ]
414
- : []),
415
- ...(agentHasPersonalMemoryTools
416
- ? [
417
- 'Hint: you have personal-memory tools (`add_memory` / `replace_memory` / `drop_memory` / `clear_memory`). Goal: maintain a compact responsibility-area rtws index (exact key doc/code paths + minimal key facts like entrypoints/key symbols/contracts) so you can start work with 0 ripgrep within your scope. If you changed those files or detect staleness/conflicts, immediately `replace_memory` to keep it accurate.',
418
- ]
419
- : []),
420
- ...(isSubdialog
421
- ? [
422
- `Workflow: do work → distill (\`update_reminder\`; when Taskdoc needs updates, draft a merged replacement and ask \`@${taskdocMaintainerId}\`) → then \`clear_mind\` to drop noise.`,
423
- ]
424
- : [
425
- 'Workflow: do work → distill (`update_reminder` + `change_mind(progress)`) → then `clear_mind` to drop noise.',
426
- ]),
427
- 'When context health turns yellow/red: treat it as a hard stop; distill first, then clear.',
428
- 'Do not paste long logs/tool outputs into Taskdoc; Taskdoc should record decisions + next steps; keep only essential excerpts in reminders.',
429
- ].join('\n');
430
- })();
431
- const memorySystemPrompt = `${memorySystemTitle}\n\n${memorySystemBody}`;
432
- const taskdocPolicyPrompt = (0, minds_i18n_1.taskdocCanonicalCopy)(workingLanguage);
433
- // Generate tool usage text (shell policy + memory system + toolset prompts).
434
- let toolUsageText;
435
- let funcToolUsageText = '';
436
- let funcToolRulesText = '';
437
- toolUsageText = (() => {
438
- const prefix = [shellPolicyPrompt, memorySystemPrompt, taskdocPolicyPrompt, toolsetPromptText]
439
- .filter((b) => b.trim() !== '')
440
- .join('\n\n');
441
- return prefix;
442
- })();
443
- if (funcTools.length > 0) {
444
- funcToolUsageText = funcTools
445
- .map((tool) => {
446
- // NOTE: Function-tool schemas may come from MCP and are treated as passthrough JSON Schema.
447
- // Runtime inspection is unavoidable here because this is purely for human-readable help text.
448
- const schema = tool.parameters;
449
- const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
450
- const requiredValue = schema['required'];
451
- const required = Array.isArray(requiredValue) && requiredValue.every((v) => typeof v === 'string')
452
- ? requiredValue
453
- : [];
454
- const req = required.length > 0 ? required.join(', ') : (0, minds_i18n_1.noneRequiredFieldsText)(workingLanguage);
455
- const propsValue = schema['properties'];
456
- const propsRecord = isRecord(propsValue) ? propsValue : {};
457
- const props = Object.entries(propsRecord)
458
- .map(([k, v]) => {
459
- const desc = isRecord(v) && 'description' in v && typeof v.description === 'string'
460
- ? v.description
461
- : 'parameter';
462
- return `- ${k}: ${desc}`;
463
- })
464
- .join('\n');
465
- const labels = (0, minds_i18n_1.funcToolUsageLabels)(workingLanguage);
466
- const toolDesc = (0, text_1.getTextForLanguage)({ i18n: tool.descriptionI18n, fallback: tool.description }, workingLanguage);
467
- return `#### ${labels.toolLabel}: ${tool.name}\n\n${toolDesc}\n\n- ${labels.invocationLabel}: ${labels.invocationBody}\n- ${labels.requiredLabel}: ${req}\n- ${labels.parametersLabel}:\n${props}`.trim();
468
- })
469
- .join('\n\n');
470
- funcToolRulesText = (0, minds_i18n_1.funcToolRulesText)(workingLanguage);
471
- }
214
+ const promptdocContext = {
215
+ language: workingLanguage,
216
+ agentId: agent.id,
217
+ isSubdialog,
218
+ taskdocMaintainerId,
219
+ agentHasTeamMemoryTools,
220
+ agentHasPersonalMemoryTools,
221
+ agentIsShellSpecialist,
222
+ agentHasShellTools,
223
+ agentHasReadonlyShell,
224
+ shellSpecialistMemberIds,
225
+ };
226
+ const policyText = [
227
+ (0, system_prompt_parts_1.buildShellPolicyPrompt)(promptdocContext),
228
+ (0, system_prompt_parts_1.buildMemorySystemPrompt)(promptdocContext),
229
+ (0, minds_i18n_1.taskdocCanonicalCopy)(workingLanguage),
230
+ ]
231
+ .filter((b) => b.trim() !== '')
232
+ .join('\n\n');
233
+ const intrinsicToolUsageText = (0, system_prompt_parts_1.buildIntrinsicToolUsageText)(workingLanguage, intrinsicFuncTools);
234
+ const toolsetManualIntro = (0, toolset_manual_1.formatToolsetManualIntro)(workingLanguage, manualTools.toolNames);
235
+ const funcToolRulesText = funcTools.length > 0 ? (0, minds_i18n_1.funcToolRulesText)(workingLanguage) : '';
472
236
  const systemPrompt = (0, system_prompt_1.buildSystemPrompt)({
473
237
  language: workingLanguage,
238
+ dialogScope: isSubdialog ? 'sideline' : 'mainline',
474
239
  agent,
475
240
  persona,
476
241
  knowledge,
477
242
  lessons,
478
243
  envIntro,
479
244
  teamIntro,
480
- toolUsageText,
481
- intrinsicToolInstructions: '',
482
- funcToolUsageText,
483
245
  funcToolRulesText,
246
+ policyText,
247
+ intrinsicToolUsageText,
248
+ toolsetManualIntro,
484
249
  });
485
250
  // composite this list by reading:
486
251
  // - .minds/memory/team_shared/**/*.md