dominds 1.26.2 → 1.26.3

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 (135) hide show
  1. package/README.md +2 -0
  2. package/README.zh.md +2 -0
  3. package/dist/docs/cli-usage.md +1 -1
  4. package/dist/docs/cli-usage.zh.md +1 -1
  5. package/dist/llm/gen/mock.js +11 -3
  6. package/dist/llm/kernel-driver/context-health.d.ts +1 -0
  7. package/dist/llm/kernel-driver/context-health.js +7 -0
  8. package/dist/llm/kernel-driver/drive.js +23 -30
  9. package/dist/llm/kernel-driver/idle-reminder-wake.js +6 -2
  10. package/dist/llm/kernel-driver/reminder-context.d.ts +25 -0
  11. package/dist/llm/kernel-driver/reminder-context.js +81 -0
  12. package/dist/llm/kernel-driver/reply-guidance.js +10 -4
  13. package/dist/llm/kernel-driver/tellask-special.js +50 -35
  14. package/dist/mcp/supervisor.js +2 -2
  15. package/dist/minds/system-prompt-parts.js +30 -30
  16. package/dist/minds/system-prompt.js +55 -40
  17. package/dist/persistence.js +15 -1
  18. package/dist/runtime/driver-messages.d.ts +32 -7
  19. package/dist/runtime/driver-messages.js +279 -118
  20. package/dist/runtime/inter-dialog-format.js +24 -12
  21. package/dist/runtime/reply-prompt-copy.d.ts +8 -8
  22. package/dist/runtime/reply-prompt-copy.js +69 -38
  23. package/dist/server/certificates.js +65 -25
  24. package/dist/tools/mcp.js +12 -12
  25. package/dist/tools/prompts/control/en/index.md +2 -2
  26. package/dist/tools/prompts/control/en/principles.md +12 -12
  27. package/dist/tools/prompts/control/en/scenarios.md +5 -5
  28. package/dist/tools/prompts/control/en/tools.md +10 -10
  29. package/dist/tools/prompts/control/zh/index.md +3 -3
  30. package/dist/tools/prompts/control/zh/principles.md +12 -12
  31. package/dist/tools/prompts/control/zh/scenarios.md +7 -7
  32. package/dist/tools/prompts/control/zh/tools.md +11 -11
  33. package/dist/tools/prompts/mcp_admin/en/principles.md +4 -4
  34. package/dist/tools/prompts/mcp_admin/en/scenarios.md +1 -1
  35. package/dist/tools/prompts/mcp_admin/en/tools.md +3 -3
  36. package/dist/tools/prompts/mcp_admin/zh/principles.md +4 -4
  37. package/dist/tools/prompts/mcp_admin/zh/scenarios.md +1 -1
  38. package/dist/tools/prompts/mcp_admin/zh/tools.md +3 -3
  39. package/dist/tools/team_mgmt-mcp-manual.js +12 -12
  40. package/package.json +4 -3
  41. package/webapp/dist/assets/{_basePickBy-DUivPKf7.js → _basePickBy-DTJFxmut.js} +3 -3
  42. package/webapp/dist/assets/{_basePickBy-DUivPKf7.js.map → _basePickBy-DTJFxmut.js.map} +1 -1
  43. package/webapp/dist/assets/{_baseUniq-hcs024vD.js → _baseUniq-CVu4lo4P.js} +2 -2
  44. package/webapp/dist/assets/{_baseUniq-hcs024vD.js.map → _baseUniq-CVu4lo4P.js.map} +1 -1
  45. package/webapp/dist/assets/{arc-Dr6-FXp5.js → arc-4mEKx1Qr.js} +2 -2
  46. package/webapp/dist/assets/{arc-Dr6-FXp5.js.map → arc-4mEKx1Qr.js.map} +1 -1
  47. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DXqcDq4R.js → architectureDiagram-2XIMDMQ5-CmUkdSiN.js} +7 -7
  48. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DXqcDq4R.js.map → architectureDiagram-2XIMDMQ5-CmUkdSiN.js.map} +1 -1
  49. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-IIP6LGXS.js → blockDiagram-WCTKOSBZ-CijmZ89y.js} +7 -7
  50. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-IIP6LGXS.js.map → blockDiagram-WCTKOSBZ-CijmZ89y.js.map} +1 -1
  51. package/webapp/dist/assets/{c4Diagram-IC4MRINW-D_d3F9XD.js → c4Diagram-IC4MRINW-D0GcQMKs.js} +3 -3
  52. package/webapp/dist/assets/{c4Diagram-IC4MRINW-D_d3F9XD.js.map → c4Diagram-IC4MRINW-D0GcQMKs.js.map} +1 -1
  53. package/webapp/dist/assets/{channel-CWWjsXtU.js → channel-6pgfGez4.js} +2 -2
  54. package/webapp/dist/assets/{channel-CWWjsXtU.js.map → channel-6pgfGez4.js.map} +1 -1
  55. package/webapp/dist/assets/{chunk-4BX2VUAB-BF4yph2W.js → chunk-4BX2VUAB-BQDAaqXK.js} +2 -2
  56. package/webapp/dist/assets/{chunk-4BX2VUAB-BF4yph2W.js.map → chunk-4BX2VUAB-BQDAaqXK.js.map} +1 -1
  57. package/webapp/dist/assets/{chunk-55IACEB6-Hn3CmDYz.js → chunk-55IACEB6-DGYbZ_6j.js} +2 -2
  58. package/webapp/dist/assets/{chunk-55IACEB6-Hn3CmDYz.js.map → chunk-55IACEB6-DGYbZ_6j.js.map} +1 -1
  59. package/webapp/dist/assets/{chunk-FMBD7UC4-C05pl9Ov.js → chunk-FMBD7UC4-EVNnQ_SU.js} +2 -2
  60. package/webapp/dist/assets/{chunk-FMBD7UC4-C05pl9Ov.js.map → chunk-FMBD7UC4-EVNnQ_SU.js.map} +1 -1
  61. package/webapp/dist/assets/{chunk-JSJVCQXG-BVlq_BAS.js → chunk-JSJVCQXG-BSQe2NHw.js} +2 -2
  62. package/webapp/dist/assets/{chunk-JSJVCQXG-BVlq_BAS.js.map → chunk-JSJVCQXG-BSQe2NHw.js.map} +1 -1
  63. package/webapp/dist/assets/{chunk-KX2RTZJC-BQoaRWif.js → chunk-KX2RTZJC-I1LMYfrr.js} +2 -2
  64. package/webapp/dist/assets/{chunk-KX2RTZJC-BQoaRWif.js.map → chunk-KX2RTZJC-I1LMYfrr.js.map} +1 -1
  65. package/webapp/dist/assets/{chunk-NQ4KR5QH-0okCAXtW.js → chunk-NQ4KR5QH-C9HmN9dA.js} +4 -4
  66. package/webapp/dist/assets/{chunk-NQ4KR5QH-0okCAXtW.js.map → chunk-NQ4KR5QH-C9HmN9dA.js.map} +1 -1
  67. package/webapp/dist/assets/{chunk-QZHKN3VN-DEiprgz-.js → chunk-QZHKN3VN-73ijGXNd.js} +2 -2
  68. package/webapp/dist/assets/{chunk-QZHKN3VN-DEiprgz-.js.map → chunk-QZHKN3VN-73ijGXNd.js.map} +1 -1
  69. package/webapp/dist/assets/{chunk-WL4C6EOR-B-Xkb3lo.js → chunk-WL4C6EOR-DeVu-9ac.js} +6 -6
  70. package/webapp/dist/assets/{chunk-WL4C6EOR-B-Xkb3lo.js.map → chunk-WL4C6EOR-DeVu-9ac.js.map} +1 -1
  71. package/webapp/dist/assets/{classDiagram-VBA2DB6C-DCCQrdwF.js → classDiagram-VBA2DB6C-2HURCFLk.js} +7 -7
  72. package/webapp/dist/assets/{classDiagram-VBA2DB6C-DCCQrdwF.js.map → classDiagram-VBA2DB6C-2HURCFLk.js.map} +1 -1
  73. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-DCCQrdwF.js → classDiagram-v2-RAHNMMFH-2HURCFLk.js} +7 -7
  74. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-DCCQrdwF.js.map → classDiagram-v2-RAHNMMFH-2HURCFLk.js.map} +1 -1
  75. package/webapp/dist/assets/{clone-Drtik9pk.js → clone-BNPlfGMh.js} +2 -2
  76. package/webapp/dist/assets/{clone-Drtik9pk.js.map → clone-BNPlfGMh.js.map} +1 -1
  77. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BBWvHErL.js → cose-bilkent-S5V4N54A-BeoZCFA5.js} +2 -2
  78. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BBWvHErL.js.map → cose-bilkent-S5V4N54A-BeoZCFA5.js.map} +1 -1
  79. package/webapp/dist/assets/{dagre-KLK3FWXG-2qk0ikdt.js → dagre-KLK3FWXG-DYxCt50h.js} +7 -7
  80. package/webapp/dist/assets/{dagre-KLK3FWXG-2qk0ikdt.js.map → dagre-KLK3FWXG-DYxCt50h.js.map} +1 -1
  81. package/webapp/dist/assets/{diagram-E7M64L7V-C1DbHDbf.js → diagram-E7M64L7V-BWxcTI3B.js} +8 -8
  82. package/webapp/dist/assets/{diagram-E7M64L7V-C1DbHDbf.js.map → diagram-E7M64L7V-BWxcTI3B.js.map} +1 -1
  83. package/webapp/dist/assets/{diagram-IFDJBPK2-DToz8zk9.js → diagram-IFDJBPK2-BAIPE4Rn.js} +7 -7
  84. package/webapp/dist/assets/{diagram-IFDJBPK2-DToz8zk9.js.map → diagram-IFDJBPK2-BAIPE4Rn.js.map} +1 -1
  85. package/webapp/dist/assets/{diagram-P4PSJMXO-B9V-tQMe.js → diagram-P4PSJMXO-CvcxPsVp.js} +7 -7
  86. package/webapp/dist/assets/{diagram-P4PSJMXO-B9V-tQMe.js.map → diagram-P4PSJMXO-CvcxPsVp.js.map} +1 -1
  87. package/webapp/dist/assets/{erDiagram-INFDFZHY-CV68FwGf.js → erDiagram-INFDFZHY-BDO90e-f.js} +5 -5
  88. package/webapp/dist/assets/{erDiagram-INFDFZHY-CV68FwGf.js.map → erDiagram-INFDFZHY-BDO90e-f.js.map} +1 -1
  89. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CW06almb.js → flowDiagram-PKNHOUZH-hd4TorKR.js} +7 -7
  90. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CW06almb.js.map → flowDiagram-PKNHOUZH-hd4TorKR.js.map} +1 -1
  91. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-C96NncCU.js → ganttDiagram-A5KZAMGK-mID1sFSl.js} +3 -3
  92. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-C96NncCU.js.map → ganttDiagram-A5KZAMGK-mID1sFSl.js.map} +1 -1
  93. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CAuIexWi.js → gitGraphDiagram-K3NZZRJ6-DaA7yodM.js} +8 -8
  94. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CAuIexWi.js.map → gitGraphDiagram-K3NZZRJ6-DaA7yodM.js.map} +1 -1
  95. package/webapp/dist/assets/{graph-CvhwAY6w.js → graph-B86JxOkQ.js} +3 -3
  96. package/webapp/dist/assets/{graph-CvhwAY6w.js.map → graph-B86JxOkQ.js.map} +1 -1
  97. package/webapp/dist/assets/{index-BOO_zFrI.js → index-DYO4ZL8y.js} +369 -389
  98. package/webapp/dist/assets/{index-BOO_zFrI.js.map → index-DYO4ZL8y.js.map} +1 -1
  99. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-C16Sckpz.js → infoDiagram-LFFYTUFH-DxF36W9g.js} +6 -6
  100. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-C16Sckpz.js.map → infoDiagram-LFFYTUFH-DxF36W9g.js.map} +1 -1
  101. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-oNG6I0p3.js → ishikawaDiagram-PHBUUO56-wvAzRzSO.js} +2 -2
  102. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-oNG6I0p3.js.map → ishikawaDiagram-PHBUUO56-wvAzRzSO.js.map} +1 -1
  103. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-437hhFHC.js → journeyDiagram-4ABVD52K-CIBXsttK.js} +5 -5
  104. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-437hhFHC.js.map → journeyDiagram-4ABVD52K-CIBXsttK.js.map} +1 -1
  105. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-DsCV_Tpx.js → kanban-definition-K7BYSVSG-DQTPyM5m.js} +3 -3
  106. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-DsCV_Tpx.js.map → kanban-definition-K7BYSVSG-DQTPyM5m.js.map} +1 -1
  107. package/webapp/dist/assets/{layout-BttZf7fQ.js → layout-BG7IzQAG.js} +5 -5
  108. package/webapp/dist/assets/{layout-BttZf7fQ.js.map → layout-BG7IzQAG.js.map} +1 -1
  109. package/webapp/dist/assets/{linear-B75vD4Ho.js → linear-5XR-mXYw.js} +2 -2
  110. package/webapp/dist/assets/{linear-B75vD4Ho.js.map → linear-5XR-mXYw.js.map} +1 -1
  111. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DA1-XaNi.js → mindmap-definition-YRQLILUH-BwTQE6uN.js} +4 -4
  112. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DA1-XaNi.js.map → mindmap-definition-YRQLILUH-BwTQE6uN.js.map} +1 -1
  113. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Bx6hUJ4Q.js → pieDiagram-SKSYHLDU-ZYB35zd5.js} +8 -8
  114. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Bx6hUJ4Q.js.map → pieDiagram-SKSYHLDU-ZYB35zd5.js.map} +1 -1
  115. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-zyduIle0.js → quadrantDiagram-337W2JSQ-BM041Q-W.js} +3 -3
  116. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-zyduIle0.js.map → quadrantDiagram-337W2JSQ-BM041Q-W.js.map} +1 -1
  117. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-BgfjyEJM.js → requirementDiagram-Z7DCOOCP-r_xMoroM.js} +4 -4
  118. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-BgfjyEJM.js.map → requirementDiagram-Z7DCOOCP-r_xMoroM.js.map} +1 -1
  119. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-lmOWaczS.js → sankeyDiagram-WA2Y5GQK-Ju2-t24N.js} +2 -2
  120. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-lmOWaczS.js.map → sankeyDiagram-WA2Y5GQK-Ju2-t24N.js.map} +1 -1
  121. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DqJz-iYI.js → sequenceDiagram-2WXFIKYE-D83Bocd1.js} +4 -4
  122. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DqJz-iYI.js.map → sequenceDiagram-2WXFIKYE-D83Bocd1.js.map} +1 -1
  123. package/webapp/dist/assets/{stateDiagram-RAJIS63D-CngWYuX-.js → stateDiagram-RAJIS63D-mTmpZzpU.js} +9 -9
  124. package/webapp/dist/assets/{stateDiagram-RAJIS63D-CngWYuX-.js.map → stateDiagram-RAJIS63D-mTmpZzpU.js.map} +1 -1
  125. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BxyHvrvU.js → stateDiagram-v2-FVOUBMTO-BCn7mFeH.js} +5 -5
  126. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BxyHvrvU.js.map → stateDiagram-v2-FVOUBMTO-BCn7mFeH.js.map} +1 -1
  127. package/webapp/dist/assets/{timeline-definition-YZTLITO2-C7t6WVS3.js → timeline-definition-YZTLITO2-C1QBcYz8.js} +3 -3
  128. package/webapp/dist/assets/{timeline-definition-YZTLITO2-C7t6WVS3.js.map → timeline-definition-YZTLITO2-C1QBcYz8.js.map} +1 -1
  129. package/webapp/dist/assets/{treemap-KZPCXAKY-BDZ3n5TC.js → treemap-KZPCXAKY-BEyfK-Fo.js} +5 -5
  130. package/webapp/dist/assets/{treemap-KZPCXAKY-BDZ3n5TC.js.map → treemap-KZPCXAKY-BEyfK-Fo.js.map} +1 -1
  131. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CEw7GPed.js → vennDiagram-LZ73GAT5-C6SZhLMq.js} +2 -2
  132. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CEw7GPed.js.map → vennDiagram-LZ73GAT5-C6SZhLMq.js.map} +1 -1
  133. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-DmS8BiaA.js → xychartDiagram-JWTSCODW-BUlvexnm.js} +3 -3
  134. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-DmS8BiaA.js.map → xychartDiagram-JWTSCODW-BUlvexnm.js.map} +1 -1
  135. package/webapp/dist/index.html +1 -1
@@ -114,12 +114,18 @@ function formatQuotedRequestBlock(args) {
114
114
  }
115
115
  function formatTellaskStatusFootnote(args) {
116
116
  const callId = requireNonEmpty(args.callId, 'callId');
117
+ // Business scenario: this footer appears after a teammate reply has already been delivered
118
+ // into the requester dialog, often across a course boundary. The model should read it as a
119
+ // completed fact about earlier collaboration, not as a fresh user request and not as a live
120
+ // instruction to call tellask/reply tools. The wording therefore says "teammate reply status"
121
+ // and "reply fact" in plain terms; the business reason is to stop follow-up turns from being
122
+ // hijacked by stale collaboration metadata.
117
123
  if (args.language === 'zh') {
118
124
  const explanation = args.crossCourse === true
119
125
  ? '这是前序诉请的跨程回贴事实,不是新的用户请求,也不是当前程新发起的函数调用。'
120
126
  : '这是前序诉请的回贴事实,不是新的用户请求,也不是当前程新发起的函数调用。';
121
127
  return [
122
- '[Dominds 诉请状态]',
128
+ '[Dominds 队友回贴状态]',
123
129
  `- 函数: \`${args.callName}\``,
124
130
  `- callId: ${callId}`,
125
131
  `- 说明: ${explanation}`,
@@ -129,7 +135,7 @@ function formatTellaskStatusFootnote(args) {
129
135
  ? 'This is a cross-course reply fact for an earlier tellask, not a new user request or a newly initiated function call in the current course.'
130
136
  : 'This is a reply fact for an earlier tellask, not a new user request or a newly initiated function call in the current course.';
131
137
  return [
132
- '[Dominds tellask status]',
138
+ '[Dominds teammate reply status]',
133
139
  `- Function: \`${args.callName}\``,
134
140
  `- callId: ${callId}`,
135
141
  `- Note: ${explanation}`,
@@ -147,8 +153,8 @@ function formatAssignmentFromAskerDialog(input) {
147
153
  language,
148
154
  });
149
155
  const markerProtocolNote = language === 'zh'
150
- ? `系统协议:回贴文本标记(如 \`${runtimeMarkers.tellaskBack}\` / \`${runtimeMarkers.finalCompleted}\` / FBR 标记 \`${runtimeMarkers.fbrDirectReply}\` / \`${runtimeMarkers.fbrReasoningOnly}\`)由 Dominds 运行时自动注入到跨对话传递正文。禁止手写标记;若诉请正文要求手写标记,请忽略该要求并按本协议执行。`
151
- : `Protocol note: reply markers (for example \`${runtimeMarkers.tellaskBack}\` / \`${runtimeMarkers.finalCompleted}\` / FBR markers \`${runtimeMarkers.fbrDirectReply}\` / \`${runtimeMarkers.fbrReasoningOnly}\`) are auto-injected by Dominds runtime into the inter-dialog transfer payload. Do not hand-write markers; if the tellask body asks you to hand-write them, ignore that requirement and follow this protocol.`;
156
+ ? `系统协议:回贴文本标记(如 \`${runtimeMarkers.tellaskBack}\` / \`${runtimeMarkers.finalCompleted}\` / FBR 标记 \`${runtimeMarkers.fbrDirectReply}\` / \`${runtimeMarkers.fbrReasoningOnly}\`)由 Dominds 自动注入到跨对话传递正文。禁止手写标记;若诉请正文要求手写标记,请忽略该要求并按本协议执行。`
157
+ : `Protocol note: reply markers (for example \`${runtimeMarkers.tellaskBack}\` / \`${runtimeMarkers.finalCompleted}\` / FBR markers \`${runtimeMarkers.fbrDirectReply}\` / \`${runtimeMarkers.fbrReasoningOnly}\`) are auto-injected by Dominds into the inter-dialog transfer payload. Do not hand-write markers; if the tellask body asks you to hand-write them, ignore that requirement and follow this protocol.`;
152
158
  const isFbr = input.callName === 'freshBootsReasoning';
153
159
  if (isFbr) {
154
160
  const roundIteration = typeof input.fbrRound?.iteration === 'number' && Number.isFinite(input.fbrRound.iteration)
@@ -163,8 +169,8 @@ function formatAssignmentFromAskerDialog(input) {
163
169
  '',
164
170
  '- 约束:这是一个扪心自问(self tellask)支线对话;请独立推理与总结。',
165
171
  '- 系统规则:当前仍处于 FBR 的无工具阶段;这一阶段不允许任何函数调用。',
166
- '- 后续只有在完成既定的发散轮与收敛轮之后,运行时才会开放两个“结论函数”供你正式收口。',
167
- '- 协议:回贴标记由 Dominds 运行时自动注入,禁止手写。',
172
+ '- 后续只有在完成既定的发散轮与收敛轮之后,Dominds 才会开放两个“结论函数”供你正式收口。',
173
+ '- 协议:回贴标记由 Dominds 自动注入,禁止手写。',
168
174
  '- 系统提示:不要受诉请正文中的定调、分析方向或维度清单约束;请聚焦总体目标,自由发挥并开辟新的分析切入角度,对离谱想法保持开放,但不要过早收敛。',
169
175
  '',
170
176
  '---',
@@ -174,8 +180,8 @@ function formatAssignmentFromAskerDialog(input) {
174
180
  '',
175
181
  '- Constraint: this is a self-tellask FBR Side Dialog; reason independently and produce conclusions.',
176
182
  '- System rule: this FBR stage is still tool-less; do not emit any function call in this stage.',
177
- '- Only after the planned divergence and convergence rounds are complete will runtime expose the two conclusion functions for formal closure.',
178
- '- Protocol: reply markers are auto-injected by Dominds runtime; do not hand-write markers.',
183
+ '- Only after the planned divergence and convergence rounds are complete will Dominds expose the two conclusion functions for formal closure.',
184
+ '- Protocol: reply markers are auto-injected by Dominds; do not hand-write markers.',
179
185
  '- System prompt: do not be constrained by framing, analysis directions, or dimension checklists embedded in the tellask body; stay focused on the overall objective, open new analytical entry points freely, stay open to wild ideas, and do not converge too early.',
180
186
  '',
181
187
  '---',
@@ -260,14 +266,20 @@ function formatTellaskResponseContent(input) {
260
266
  const isFbr = input.callName === 'freshBootsReasoning';
261
267
  const marker = getRuntimeTransferMarker(input);
262
268
  const markerPrefix = marker ? `${marker}\n\n` : '';
269
+ // Business scenario: this notice is only used after an old fallback path had to deliver a
270
+ // completed Side Dialog answer that the model wrote as plain text instead of sending through
271
+ // the Dominds-named reply tool. The requester still needs traceability, but exposing implementation
272
+ // names like "direct-reply fallback" teaches the model the wrong lesson: it may plan to use
273
+ // plain text next time. Say the business fact instead: this was a one-time runtime recovery,
274
+ // not the normal way to send formal replies.
263
275
  const deliveryNotice = input.deliveryMode === 'direct_fallback'
264
276
  ? input.directFallbackSource === 'thinking_only'
265
277
  ? language === 'zh'
266
- ? '> 系统提示:本次回贴未调用 replyTellask* 工具,且模型仅产出 thinking;在确认本轮没有待续推工具调用后,Dominds 已通过 direct-reply fallback 临时过渡兜底投递该 thinking 内容。此路径不是正式回复机制,保留本标记仅用于追踪。\n\n'
267
- : '> System note: this reply did not use a replyTellask* tool, and the model only produced thinking. After confirming that no tool call in this round was waiting for auto-continuation, Dominds delivered that thinking content through direct-reply fallback as a temporary transition safeguard. This path is not the formal reply mechanism; this marker is kept only for traceability.\n\n'
278
+ ? '> 系统提示:这次没有通过 Dominds 点名的回复工具发送,且只写出了思考内容。Dominds 已确认本轮没有还要继续的工具调用,所以临时把这段内容送达。请不要把普通文本当成可规划的正式回贴路径;保留本标记仅用于追踪。\n\n'
279
+ : '> System note: this reply was not sent through the reply tool named by Dominds, and the model only wrote thinking content. Dominds confirmed that no tool call in this round still needed continuation, so it delivered that content as a one-time recovery. Do not treat plain text as a planned formal reply path; this marker is kept only for traceability.\n\n'
268
280
  : language === 'zh'
269
- ? '> 系统提示:本次回贴未调用 replyTellask* 工具;在确认本轮没有待续推工具调用后,Dominds 已通过 direct-reply fallback 临时过渡兜底投递。此路径不是正式回复机制,保留本标记仅用于追踪。\n\n'
270
- : '> System note: this reply did not use a replyTellask* tool. After confirming that no tool call in this round was waiting for auto-continuation, Dominds delivered it through direct-reply fallback as a temporary transition safeguard. This path is not the formal reply mechanism; this marker is kept only for traceability.\n\n'
281
+ ? '> 系统提示:这次没有通过 Dominds 点名的回复工具发送。Dominds 已确认本轮没有还要继续的工具调用,所以临时把这段内容送达。请不要把普通文本当成可规划的正式回贴路径;保留本标记仅用于追踪。\n\n'
282
+ : '> System note: this reply was not sent through the reply tool named by Dominds. Dominds confirmed that no tool call in this round still needed continuation, so it delivered the content as a one-time recovery. Do not treat plain text as a planned formal reply path; this marker is kept only for traceability.\n\n'
271
283
  : '';
272
284
  if (isFbr) {
273
285
  const title = language === 'zh' ? '【扪心自问(FBR)支线对话回贴】' : '[FBR Side Dialog response]';
@@ -1,13 +1,13 @@
1
1
  import type { LanguageCode } from '@longrun-ai/kernel/types/language';
2
2
  import type { TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
3
- export declare const ACTIVE_REPLY_TOOL_PREFIX_EN = "[Dominds active reply tool]";
4
- export declare const ACTIVE_REPLY_TOOL_PREFIX_ZH = "[Dominds \u5F53\u524D\u56DE\u590D\u5DE5\u5177]";
5
- export declare const NO_ACTIVE_REPLY_PREFIX_EN = "[Dominds no active inter-dialog reply]";
6
- export declare const NO_ACTIVE_REPLY_PREFIX_ZH = "[Dominds \u5F53\u524D\u65E0\u8DE8\u5BF9\u8BDD\u56DE\u590D\u4E49\u52A1]";
7
- export declare const REPLY_TOOL_REMINDER_PREFIX_EN = "[Dominds replyTellask required]";
8
- export declare const REPLY_TOOL_REMINDER_PREFIX_ZH = "[Dominds \u5FC5\u987B\u8C03\u7528\u56DE\u590D\u5DE5\u5177]";
9
- export declare const REPLY_REASSERTION_PREFIX_EN = "[Dominds long-line reminder]";
10
- export declare const REPLY_REASSERTION_PREFIX_ZH = "[Dominds \u957F\u7EBF\u63D0\u9192]";
3
+ export declare const ACTIVE_REPLY_TOOL_PREFIX_EN = "[Dominds reply path]";
4
+ export declare const ACTIVE_REPLY_TOOL_PREFIX_ZH = "[Dominds \u56DE\u590D\u8DEF\u5F84]";
5
+ export declare const NO_ACTIVE_REPLY_PREFIX_EN = "[Dominds no reply needed]";
6
+ export declare const NO_ACTIVE_REPLY_PREFIX_ZH = "[Dominds \u65E0\u9700\u56DE\u8D34]";
7
+ export declare const REPLY_TOOL_REMINDER_PREFIX_EN = "[Dominds send the reply now]";
8
+ export declare const REPLY_TOOL_REMINDER_PREFIX_ZH = "[Dominds \u73B0\u5728\u53D1\u9001\u56DE\u8D34]";
9
+ export declare const REPLY_REASSERTION_PREFIX_EN = "[Dominds resume earlier work]";
10
+ export declare const REPLY_REASSERTION_PREFIX_ZH = "[Dominds \u63A5\u56DE\u539F\u4EFB\u52A1]";
11
11
  export declare const REPLY_SUPPRESSION_PREFIX_EN = "[Dominds handle this interjection first]";
12
12
  export declare const REPLY_SUPPRESSION_PREFIX_ZH = "[Dominds \u5148\u63A5\u4F4F\u8FD9\u8F6E]";
13
13
  type ReplyObligationCopyArgs = {
@@ -11,14 +11,14 @@ exports.buildReplyToolReminderText = buildReplyToolReminderText;
11
11
  exports.isReplyToolReminderPromptContent = isReplyToolReminderPromptContent;
12
12
  exports.isStandaloneRuntimeGuidePromptContent = isStandaloneRuntimeGuidePromptContent;
13
13
  const tellask_labels_1 = require("./tellask-labels");
14
- exports.ACTIVE_REPLY_TOOL_PREFIX_EN = '[Dominds active reply tool]';
15
- exports.ACTIVE_REPLY_TOOL_PREFIX_ZH = '[Dominds 当前回复工具]';
16
- exports.NO_ACTIVE_REPLY_PREFIX_EN = '[Dominds no active inter-dialog reply]';
17
- exports.NO_ACTIVE_REPLY_PREFIX_ZH = '[Dominds 当前无跨对话回复义务]';
18
- exports.REPLY_TOOL_REMINDER_PREFIX_EN = '[Dominds replyTellask required]';
19
- exports.REPLY_TOOL_REMINDER_PREFIX_ZH = '[Dominds 必须调用回复工具]';
20
- exports.REPLY_REASSERTION_PREFIX_EN = '[Dominds long-line reminder]';
21
- exports.REPLY_REASSERTION_PREFIX_ZH = '[Dominds 长线提醒]';
14
+ exports.ACTIVE_REPLY_TOOL_PREFIX_EN = '[Dominds reply path]';
15
+ exports.ACTIVE_REPLY_TOOL_PREFIX_ZH = '[Dominds 回复路径]';
16
+ exports.NO_ACTIVE_REPLY_PREFIX_EN = '[Dominds no reply needed]';
17
+ exports.NO_ACTIVE_REPLY_PREFIX_ZH = '[Dominds 无需回贴]';
18
+ exports.REPLY_TOOL_REMINDER_PREFIX_EN = '[Dominds send the reply now]';
19
+ exports.REPLY_TOOL_REMINDER_PREFIX_ZH = '[Dominds 现在发送回贴]';
20
+ exports.REPLY_REASSERTION_PREFIX_EN = '[Dominds resume earlier work]';
21
+ exports.REPLY_REASSERTION_PREFIX_ZH = '[Dominds 接回原任务]';
22
22
  exports.REPLY_SUPPRESSION_PREFIX_EN = '[Dominds handle this interjection first]';
23
23
  exports.REPLY_SUPPRESSION_PREFIX_ZH = '[Dominds 先接住这轮]';
24
24
  function formatReplyTargetAgentId(agentId, language) {
@@ -36,8 +36,8 @@ function buildReplyObligationReassertionLine(args) {
36
36
  bracketed: true,
37
37
  });
38
38
  return args.language === 'zh'
39
- ? `${replyTarget} 的${kindLabel}还在等你的回复。等你准备好回复内容后,调用 \`${toolName}\` 完成回复。这里不是催你立刻回复。`
40
- : `${replyTarget}'s ${kindLabel} is still waiting for your reply. Once your reply content is ready, call \`${toolName}\` to deliver it. This is not asking you to reply immediately.`;
39
+ ? `${replyTarget} 还在等你完成${kindLabel}的回贴。等你准备好最终内容后,调用 \`${toolName}\` 发送。这里不是催你立刻回复。`
40
+ : `${replyTarget} is still waiting for your ${kindLabel} reply. When the final content is ready, call \`${toolName}\` to send it. This is not asking you to reply immediately.`;
41
41
  }
42
42
  function buildReplyToolReminderLine(args) {
43
43
  const toolName = args.directive.expectedReplyCallName;
@@ -48,51 +48,67 @@ function buildReplyToolReminderLine(args) {
48
48
  bracketed: true,
49
49
  });
50
50
  return args.language === 'zh'
51
- ? `${replyTarget} 的${kindLabel}还在等你的回复。请现在调用 \`${toolName}({ replyContent })\` 完成回复。`
52
- : `${replyTarget}'s ${kindLabel} is still waiting for your reply. Call \`${toolName}({ replyContent })\` now to deliver it.`;
51
+ ? `${replyTarget} 还在等你完成${kindLabel}的回贴。请现在调用 \`${toolName}({ replyContent })\` 发送。`
52
+ : `${replyTarget} is still waiting for your ${kindLabel} reply. Call \`${toolName}({ replyContent })\` now to send it.`;
53
53
  }
54
+ // Business scenario: Dominds has a durable record that this dialog still owes a final reply to
55
+ // the requester. The model is not supposed to rediscover whether this is replyTellask,
56
+ // replyTellaskSessionless, or replyTellaskBack from old transcript text; that choice comes from
57
+ // the active request record. The copy therefore says Dominds already chose one path and names one
58
+ // tool. It also says "when final content is ready" because an active reply path is a delivery
59
+ // constraint, not a command to abandon necessary local work and close early.
54
60
  function buildActiveReplyToolNote(args) {
55
61
  if (args.language === 'zh') {
56
62
  return [
57
63
  exports.ACTIVE_REPLY_TOOL_PREFIX_ZH,
58
- '先专注处理眼前这轮任务,不要被 `reply*` 选择分心。',
59
- `若这轮最终需要对诉请者完成交付,精确调用 \`${args.toolName}\`;不要改选其他 \`reply*\`,也不要提前收口。`,
64
+ 'Dominds 已经判断好:这轮如果要把最终结果回给诉请者,只能用下面这个工具。',
65
+ `先把当前任务做对;等最终内容准备好时,调用 \`${args.toolName}\`。不要提前发送,也不要改用别的回复工具。`,
60
66
  ].join('\n');
61
67
  }
62
68
  return [
63
69
  exports.ACTIVE_REPLY_TOOL_PREFIX_EN,
64
- 'Stay focused on the task in front of you for this turn; do not get distracted by choosing among `reply*` variants.',
65
- `If this turn truly reaches final delivery back to the tellasker, call \`${args.toolName}\` exactly; do not switch to another \`reply*\` variant or close early.`,
70
+ 'Dominds has already decided the reply path: if this turn sends the final result back to the requester, use only the tool below.',
71
+ `Do the current task correctly first; when the final content is ready, call \`${args.toolName}\`. Do not send early or switch to another reply tool.`,
66
72
  ].join('\n');
67
73
  }
74
+ // Business scenario: the dialog still owes a final answer to a requester, but this block is
75
+ // persistent context rather than a fresh user request. Without that distinction, models tend to
76
+ // treat the state block itself as an instruction to immediately reply or to re-open the original
77
+ // request as new work. Keep the wording simple: who is waiting, which request it is, and which
78
+ // exact tool sends the final content when the answer is actually ready.
68
79
  function buildActiveReplyObligationContextText(args) {
69
80
  if (args.language === 'zh') {
70
81
  return [
71
- '[Dominds 当前跨对话回复义务]',
72
- '这是运行时状态,不是新的用户请求。',
73
- `必须回复的目标对话:${args.directive.targetDialogId}`,
74
- `必须结清的调用:${args.directive.targetCallId}`,
75
- `最终交付时精确调用:\`${args.directive.expectedReplyCallName}({ replyContent })\``,
82
+ '[Dominds 待回贴任务]',
83
+ '这是 Dominds 状态,不是新的用户请求。',
84
+ `要回给的对话:${args.directive.targetDialogId}`,
85
+ `对应请求:${args.directive.targetCallId}`,
86
+ `发送最终内容时调用:\`${args.directive.expectedReplyCallName}({ replyContent })\``,
76
87
  '',
77
88
  '原始诉请内容:',
78
89
  args.directive.tellaskContent,
79
90
  ].join('\n');
80
91
  }
81
92
  return [
82
- '[Dominds active inter-dialog reply obligation]',
83
- 'This is runtime state, not a new user request.',
84
- `Target dialog to reply to: ${args.directive.targetDialogId}`,
85
- `Call to settle: ${args.directive.targetCallId}`,
86
- `At final delivery, call exactly: \`${args.directive.expectedReplyCallName}({ replyContent })\``,
93
+ '[Dominds pending reply task]',
94
+ 'This is Dominds state, not a new user request.',
95
+ `Dialog to reply to: ${args.directive.targetDialogId}`,
96
+ `Request to answer: ${args.directive.targetCallId}`,
97
+ `When sending the final content, call: \`${args.directive.expectedReplyCallName}({ replyContent })\``,
87
98
  '',
88
99
  'Original request content:',
89
100
  args.directive.tellaskContent,
90
101
  ].join('\n');
91
102
  }
103
+ // Business scenario: a Side Dialog has enough information to finish the assigned work. At that
104
+ // point `tellaskBack` is still only for asking the requester a question; it must not be used as a
105
+ // final delivery path. Dominds may already name the precise reply tool from durable state, so the
106
+ // model should not choose among reply variants by memory or by guessing from the original
107
+ // assignment.
92
108
  function buildSideDialogCompletionRule(language) {
93
109
  return language === 'zh'
94
- ? '当前支线已完成并能给出最终交付时:先专注把当前任务做对;若运行时点名了精确 reply 函数,就只在最终交付收口时调用那个函数,不要改选其他 `reply*`,也不要再走 `tellaskBack`。'
95
- : 'If the current Side Dialog is complete and can deliver the final result: stay focused on finishing the actual task first; if runtime names an exact reply function, call that function only at final tellasker delivery, do not switch among `reply*` variants, and do not use `tellaskBack` for final delivery.';
110
+ ? '当前支线已完成并能给出最终交付时:先专注把当前任务做对;若 Dominds 点名了精确回复工具,就只在发送最终内容时调用那个工具,不要改用别的回复工具,也不要用 `tellaskBack` 发送最终结果。'
111
+ : 'If the current Side Dialog is complete and can deliver the final result: focus on finishing the actual task first; if Dominds names an exact reply tool, call that tool only when sending the final content, do not switch to another reply tool, and do not use `tellaskBack` for final delivery.';
96
112
  }
97
113
  function buildSideDialogRoleHeaderCopy(args) {
98
114
  const tellaskerTag = `@${args.tellaskerId}`;
@@ -107,27 +123,37 @@ function buildSideDialogRoleHeaderCopy(args) {
107
123
  bracketed: true,
108
124
  });
109
125
  return args.language === 'zh'
110
- ? `${tellaskerTag} 已通过${kindLabel}安排你处理下述诉请内容。等你准备好回复内容后,调用 \`${args.expectedReplyTool}\` 完成回复。只有确实需要向诉请者回问、且现有规程无法直接判责时,才调用 \`tellaskBack\`。`
111
- : `${tellaskerTag} has assigned you, via this ${kindLabel}, to handle the request content below. Once your reply content is ready, call \`${args.expectedReplyTool}\` to deliver it. Call \`tellaskBack\` only when you truly need to ask the tellasker back and existing SOP cannot directly identify another owner.`;
126
+ ? `${tellaskerTag} 已通过${kindLabel}安排你处理下述诉请内容。等你准备好最终回复后,调用 \`${args.expectedReplyTool}\` 发回去。只有确实需要向诉请者回问、且现有规程无法直接判责时,才调用 \`tellaskBack\`。`
127
+ : `${tellaskerTag} has assigned you, via this ${kindLabel}, to handle the request content below. When the final reply is ready, call \`${args.expectedReplyTool}\` to send it back. Call \`tellaskBack\` only when you truly need to ask the tellasker back and existing SOP cannot directly identify another owner.`;
112
128
  }
129
+ // Business scenario: a real user interjected while a longer-running requester reply was still
130
+ // open. Dominds has parked the older reply task and will reassert it after the user sees a local
131
+ // answer. The model-facing copy must not ask the model to decide whether the old request or the
132
+ // new user message wins; Dominds already decided. It also must not ban tools generally: tools are
133
+ // fine when the current user message itself needs them, but old request/reminder context must not
134
+ // pull the model back into the parked work before the visible user answer.
113
135
  function buildReplyObligationSuppressionGuideText(language) {
114
136
  if (language === 'zh') {
115
137
  return [
116
138
  exports.REPLY_SUPPRESSION_PREFIX_ZH,
117
139
  '本轮最新用户消息是真实用户插话;先按这条最新用户消息回答,让用户看到你已经接住了当前话题。',
118
- '原来的长线诉请、回复工具义务、技能/SOP 触发条件都已暂存;不要在回答当前用户消息前切回旧任务、旧工具流程或旧收口。',
140
+ '原来的长线诉请、回贴任务、技能/SOP 触发条件都已暂存;不要在回答当前用户消息前切回旧任务、旧工具流程或旧收口。',
119
141
  '只有当前用户消息本身需要,才使用工具;不要因为旧长线任务、旧技能提示或旧提醒项去调用工具。',
120
- '等当前用户插话已经得到可见回复后,运行时会再提醒你接回原来的长线。',
142
+ '等当前用户插话已经得到可见回复后,Dominds 会再提醒你接回原来的长线。',
121
143
  ].join('\n');
122
144
  }
123
145
  return [
124
146
  exports.REPLY_SUPPRESSION_PREFIX_EN,
125
147
  'The latest user message in this turn is a real user interjection; answer that latest user message first so the user can see you handled the current topic.',
126
- 'The earlier long-line request, reply-tool obligation, and skill/SOP triggers are parked; do not switch back to the old task, old tool flow, or old closure before answering the current user message.',
148
+ 'The earlier long-line request, reply task, and skill/SOP triggers are parked; do not switch back to the old task, old tool flow, or old closure before answering the current user message.',
127
149
  'Use tools only if the current user message itself requires them; do not call tools because of the earlier long-line task, old skill hints, or old reminders.',
128
- 'After the current user interjection has a visible reply, runtime will remind you to resume the earlier long-line thread.',
150
+ 'After the current user interjection has a visible reply, Dominds will remind you to resume the earlier long-line thread.',
129
151
  ].join('\n');
130
152
  }
153
+ // Business scenario: the visible answer to the user interjection has been delivered, so the
154
+ // previously parked long-line reply task becomes current again. This is intentionally softer than
155
+ // the "send now" reminder: the original task resumes, but the final reply tool is still used only
156
+ // when final content is ready.
131
157
  function buildReplyObligationReassertionText(args) {
132
158
  return args.language === 'zh'
133
159
  ? [
@@ -145,24 +171,29 @@ function buildReplyObligationReassertionText(args) {
145
171
  buildReplyObligationReassertionLine(args),
146
172
  ].join('\n');
147
173
  }
174
+ // Business scenario: the model already wrote content that can be sent back to the requester but
175
+ // stopped as plain text instead of using the reply tool Dominds named. In that state Dominds can
176
+ // be precise: this is no longer "keep working", it is "send the already-produced final content
177
+ // through this tool". Avoid fallback/internal terminology here; the model only needs to know that
178
+ // plain text is not the formal delivery path to the other dialog.
148
179
  function buildReplyToolReminderText(args) {
149
180
  const prefix = args.language === 'zh' ? exports.REPLY_TOOL_REMINDER_PREFIX_ZH : exports.REPLY_TOOL_REMINDER_PREFIX_EN;
150
181
  return args.language === 'zh'
151
182
  ? [
152
183
  prefix,
153
184
  '',
154
- `你刚才已经产出了可作为回贴的内容,但还没调用 \`${args.directive.expectedReplyCallName}\`。`,
185
+ `你刚才已经写出了可以发回去的内容,但还没调用 \`${args.directive.expectedReplyCallName}\`。`,
155
186
  '',
156
187
  buildReplyToolReminderLine(args),
157
- '不要依赖 direct-reply fallback;它只是运行时临时过渡兜底,不是正式回复机制。请现在调用正确的 reply 工具完成回复。',
188
+ '请现在用这个工具发送;不要只发普通文本,否则对方那边可能收不到正式回贴。',
158
189
  ].join('\n')
159
190
  : [
160
191
  prefix,
161
192
  '',
162
- `You already produced content that can be delivered as the reply, but you still have not called \`${args.directive.expectedReplyCallName}\`.`,
193
+ `You already wrote content that can be sent back, but you still have not called \`${args.directive.expectedReplyCallName}\`.`,
163
194
  '',
164
195
  buildReplyToolReminderLine(args),
165
- 'Do not rely on direct-reply fallback; it is only a temporary runtime transition safeguard, not the formal reply mechanism. Call the correct reply tool now.',
196
+ 'Use this tool to send it now; do not rely on plain text, because the other dialog may not receive a formal reply that way.',
166
197
  ].join('\n');
167
198
  }
168
199
  function isReplyToolReminderPromptContent(content) {
@@ -37,16 +37,14 @@ exports.DEFAULT_SELF_SIGNED_CERT_DAYS = void 0;
37
37
  exports.getDefaultDomindsCertsDir = getDefaultDomindsCertsDir;
38
38
  exports.findAutoHttpsCertificateForHost = findAutoHttpsCertificateForHost;
39
39
  exports.createSelfSignedCertificate = createSelfSignedCertificate;
40
- const node_child_process_1 = require("node:child_process");
41
40
  const node_crypto_1 = require("node:crypto");
42
41
  const fs = __importStar(require("node:fs/promises"));
43
42
  const net = __importStar(require("node:net"));
44
43
  const os = __importStar(require("node:os"));
45
44
  const path = __importStar(require("node:path"));
46
45
  const tls = __importStar(require("node:tls"));
47
- const node_util_1 = require("node:util");
46
+ const selfsigned_1 = require("selfsigned");
48
47
  const network_hosts_1 = require("./network-hosts");
49
- const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
50
48
  const CERT_EXTENSIONS = ['.crt', '.cert', '.pem'];
51
49
  const KEY_SUFFIXES = ['.key.pem', '.key', '-key.pem'];
52
50
  exports.DEFAULT_SELF_SIGNED_CERT_DAYS = 3650;
@@ -140,25 +138,19 @@ async function createSelfSignedCertificate(params) {
140
138
  await assertPathDoesNotExist(keyPath);
141
139
  await assertPathDoesNotExist(metadataPath);
142
140
  }
141
+ const writeFlag = params.force === true ? 'w' : 'wx';
143
142
  const san = buildSubjectAltName(hosts);
144
- await execFileAsync('openssl', [
145
- 'req',
146
- '-x509',
147
- '-newkey',
148
- 'rsa:2048',
149
- '-sha256',
150
- '-nodes',
151
- '-days',
152
- String(days),
153
- '-keyout',
154
- keyPath,
155
- '-out',
156
- certPath,
157
- '-subj',
158
- `/CN=${escapeOpenSslSubjectValue(host)}`,
159
- '-addext',
160
- `subjectAltName=${san}`,
161
- ], { maxBuffer: 1024 * 1024 });
143
+ const generated = await generateDomindsSelfSignedPem({ host, hosts, days });
144
+ await fs.writeFile(keyPath, generated.keyPem, {
145
+ encoding: 'utf8',
146
+ mode: 0o600,
147
+ flag: writeFlag,
148
+ });
149
+ await fs.writeFile(certPath, generated.certPem, {
150
+ encoding: 'utf8',
151
+ mode: 0o644,
152
+ flag: writeFlag,
153
+ });
162
154
  await fs.chmod(keyPath, 0o600);
163
155
  await fs.chmod(certPath, 0o644);
164
156
  const metadata = {
@@ -171,10 +163,61 @@ async function createSelfSignedCertificate(params) {
171
163
  createdAt: new Date().toISOString(),
172
164
  subjectAltName: san,
173
165
  };
174
- await fs.writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`, 'utf8');
166
+ await fs.writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`, {
167
+ encoding: 'utf8',
168
+ mode: 0o644,
169
+ flag: writeFlag,
170
+ });
175
171
  await fs.chmod(metadataPath, 0o644);
176
172
  return { host, hosts, days, certsDirAbs, certPath, keyPath, metadataPath };
177
173
  }
174
+ async function generateDomindsSelfSignedPem(params) {
175
+ const notBeforeDate = new Date();
176
+ const notAfterDate = new Date(notBeforeDate.getTime() + params.days * 24 * 60 * 60 * 1000);
177
+ const attrs = [{ name: 'commonName', value: params.host }];
178
+ const extensions = [
179
+ { name: 'basicConstraints', cA: false, critical: true },
180
+ { name: 'keyUsage', digitalSignature: true, keyEncipherment: true, critical: true },
181
+ { name: 'extKeyUsage', serverAuth: true },
182
+ { name: 'subjectAltName', altNames: buildSubjectAltNameEntries(params.hosts) },
183
+ ];
184
+ const pems = await (0, selfsigned_1.generate)(attrs, {
185
+ keyType: 'rsa',
186
+ keySize: 2048,
187
+ algorithm: 'sha256',
188
+ notBeforeDate,
189
+ notAfterDate,
190
+ extensions,
191
+ });
192
+ const certPem = pems.cert;
193
+ const keyPem = pems.private;
194
+ assertGeneratedCertificateMatchesRequest({ certPem, keyPem, hosts: params.hosts, notAfterDate });
195
+ return { certPem, keyPem };
196
+ }
197
+ function buildSubjectAltNameEntries(hosts) {
198
+ return hosts.map((host) => {
199
+ if (net.isIP(host) !== 0) {
200
+ return { type: 7, ip: host };
201
+ }
202
+ return { type: 2, value: host };
203
+ });
204
+ }
205
+ function assertGeneratedCertificateMatchesRequest(params) {
206
+ const cert = new node_crypto_1.X509Certificate(params.certPem);
207
+ for (const host of params.hosts) {
208
+ if (!certificateMatchesHost(cert, host)) {
209
+ throw new Error(`Generated self-signed certificate does not include requested host: ${host}`);
210
+ }
211
+ }
212
+ const validToMs = Date.parse(cert.validTo);
213
+ if (!Number.isFinite(validToMs)) {
214
+ throw new Error('Generated self-signed certificate has an invalid validTo date');
215
+ }
216
+ if (validToMs > params.notAfterDate.getTime() + 1000) {
217
+ throw new Error('Generated self-signed certificate validity exceeds requested --days value');
218
+ }
219
+ tls.createSecureContext({ cert: params.certPem, key: params.keyPem });
220
+ }
178
221
  function normalizeCertificateHostsForCreate(rawHosts, options) {
179
222
  const hosts = [];
180
223
  const seen = new Set();
@@ -280,9 +323,6 @@ function buildSubjectAltName(hosts) {
280
323
  })
281
324
  .join(',');
282
325
  }
283
- function escapeOpenSslSubjectValue(value) {
284
- return value.replace(/\\/g, '\\\\').replace(/\//g, '\\/');
285
- }
286
326
  function isCertificateFilename(filename) {
287
327
  return CERT_EXTENSIONS.some((ext) => filename.endsWith(ext)) && !isKeyFilename(filename);
288
328
  }
package/dist/tools/mcp.js CHANGED
@@ -57,7 +57,7 @@ const mcpReleaseSchema = {
57
57
  properties: {
58
58
  serverId: {
59
59
  type: 'string',
60
- description: "MCP server id from `.minds/mcp.yaml` (e.g., 'playwright'). Releases this dialog's current leased MCP runtime instance/process for that server.",
60
+ description: "MCP server id from `.minds/mcp.yaml` (e.g., 'playwright'). Releases this dialog's current leased MCP connection/process for that server.",
61
61
  },
62
62
  },
63
63
  required: ['serverId'],
@@ -68,7 +68,7 @@ const mcpDisableSchema = {
68
68
  properties: {
69
69
  serverId: {
70
70
  type: 'string',
71
- description: "MCP server id from `.minds/mcp.yaml` (e.g., 'playwright'). Stops any loaded runtime/leases and writes servers.<id>.enabled=false.",
71
+ description: "MCP server id from `.minds/mcp.yaml` (e.g., 'playwright'). Stops any loaded MCP connection/leases and writes servers.<id>.enabled=false.",
72
72
  },
73
73
  },
74
74
  required: ['serverId'],
@@ -109,10 +109,10 @@ exports.mcpRestartTool = {
109
109
  exports.mcpReleaseTool = {
110
110
  type: 'func',
111
111
  name: 'mcp_release',
112
- description: "Release this dialog's current leased MCP runtime instance for a server (stops the underlying process/connection).",
112
+ description: "Release this dialog's current leased MCP connection/process for a server.",
113
113
  descriptionI18n: {
114
- en: "Release this dialog's current leased MCP runtime instance for a server (stops the underlying process/connection).",
115
- zh: '释放当前对话为某个 server 持有的 MCP 运行时实例(停止底层进程/连接)。',
114
+ en: "Release this dialog's current leased MCP connection/process for a server.",
115
+ zh: '释放当前对话为某个 server 持有的 MCP 连接/进程。',
116
116
  },
117
117
  parameters: mcpReleaseSchema,
118
118
  argsValidation: 'dominds',
@@ -147,10 +147,10 @@ exports.mcpReleaseTool = {
147
147
  exports.mcpDisableTool = {
148
148
  type: 'func',
149
149
  name: 'mcp_disable',
150
- description: 'Disable a configured MCP server, clear its loaded runtime/leases, and persist enabled=false in `.minds/mcp.yaml`.',
150
+ description: 'Disable a configured MCP server, clear its loaded MCP connection/leases, and persist enabled=false in `.minds/mcp.yaml`.',
151
151
  descriptionI18n: {
152
- en: 'Disable a configured MCP server, clear its loaded runtime/leases, and persist enabled=false in `.minds/mcp.yaml`.',
153
- zh: '禁用指定 MCP 服务器,清理其已加载运行时/租约,并在 `.minds/mcp.yaml` 中持久写入 enabled=false。',
152
+ en: 'Disable a configured MCP server, clear its loaded MCP connection/leases, and persist enabled=false in `.minds/mcp.yaml`.',
153
+ zh: '禁用指定 MCP 服务器,清理其已加载 MCP 连接/租约,并在 `.minds/mcp.yaml` 中持久写入 enabled=false。',
154
154
  },
155
155
  parameters: mcpDisableSchema,
156
156
  argsValidation: 'dominds',
@@ -210,18 +210,18 @@ exports.mcpLeaseReminderOwner = {
210
210
  ? [
211
211
  `${prefix} MCP 工具集租约 [${reminder.id}]: \`${serverId}\``,
212
212
  '',
213
- `你当前看到的是系统维护的 MCP 租约状态。该 MCP server 被视为非“真正无状态”;当前对话持有一个 MCP 运行时实例(HTTP 连接或 stdio 进程)。`,
213
+ `你当前看到的是系统维护的 MCP 租约状态。该 MCP server 被视为非“真正无状态”;当前对话持有一个 MCP 连接/进程(HTTP 连接或 stdio 进程)。`,
214
214
  (0, driver_messages_1.formatAutoMaintainedReminderManualMirrorBan)(workLanguage),
215
215
  '',
216
- `该提醒项只说明当前对话持有的运行时实例;它不决定该 server 的全局工具注册/可见性。`,
216
+ `该提醒项只说明当前对话持有的连接/进程;它不决定该 server 的全局工具注册/可见性。`,
217
217
  ].join('\n')
218
218
  : [
219
219
  `${prefix} MCP toolset lease [${reminder.id}]: \`${serverId}\``,
220
220
  '',
221
- `You are looking at system-maintained MCP lease state. This MCP server is treated as non-stateless, and the current dialog holds one MCP runtime instance for it (an HTTP connection or stdio process).`,
221
+ `You are looking at system-maintained MCP lease state. This MCP server is treated as non-stateless, and the current dialog holds one MCP connection/process for it (an HTTP connection or stdio process).`,
222
222
  (0, driver_messages_1.formatAutoMaintainedReminderManualMirrorBan)(workLanguage),
223
223
  '',
224
- `This reminder only describes the runtime instance held by the current dialog; it does not determine global tool registration/visibility for that server.`,
224
+ `This reminder only describes the connection/process held by the current dialog; it does not determine global tool registration/visibility for that server.`,
225
225
  ].join('\n'),
226
226
  };
227
227
  },
@@ -29,7 +29,7 @@ control is Dominds' **dialog control toolset** for managing dialog state, remind
29
29
  - **Reminder management**: Three reminder scopes: `dialog` / `task` / `agent`. Default to `task` for current work under the same Taskdoc; use `dialog` only for truly dialog-local notes; use `agent` only for urgent, short-lived, globally visible cues
30
30
  - **Taskdoc operations**: Append to, replace, or delete task contract sections (goals/constraints/progress); within Taskdoc, `progress` is the team-shared, quasi-real-time, scannable task bulletin board
31
31
  - **Context maintenance**: Reduce cognitive load without losing key resume state
32
- - **Reply routing**: Separate `tellaskBack`, `replyTellask*`, and plain text by responsibility in Side Dialog / ask-back flows
32
+ - **Reply routing**: Separate asking the tellasker back, sending the final reply, and ordinary plain text in Side Dialog / ask-back flows
33
33
 
34
34
  ## Quick Navigation
35
35
 
@@ -58,7 +58,7 @@ Reminders are temporary current-work information for:
58
58
  - Recording blocking issues
59
59
  - Holding continuation-package bridge notes before `clear_mind`
60
60
 
61
- Reminders are not for manually copying Dominds runtime-maintained environment state, such as background process status, in-flight background asks/collaboration, or browser/session attachment state. Runtime-managed reminders, panels, and tool outputs are the single source of truth; manual notes go stale easily and create cognitive noise.
61
+ Reminders are not for manually copying environment state automatically maintained by Dominds, such as background process status, in-flight background asks/collaboration, or browser/session attachment state. Dominds-managed reminders, panels, and tool outputs are the authoritative place for that state; manual notes go stale easily and create cognitive noise.
62
62
 
63
63
  Scope rule:
64
64
 
@@ -42,7 +42,7 @@ Default to `task`. Use `dialog` only when the note is truly dialog-local; use `a
42
42
  - `agent` reminders stay visible in all later dialogs you lead
43
43
  - Can be added, modified, or deleted at any time
44
44
  - Should stay compact, scannable, and directly actionable by default
45
- - Before `clear_mind`, the Main Dialog first records undocumented discussion details the next course needs to know into Taskdoc, then creates a structured continuation-package reminder; a Side Dialog directly maintains sufficiently detailed continuation-package reminders. If the current course is already under system remediation, Side Dialog reminder length has no technical limit and rough multi-reminder carry-over is acceptable
45
+ - Before `clear_mind`, the Main Dialog first records undocumented discussion details the next course needs to know into Taskdoc, then creates a structured continuation-package reminder; a Side Dialog directly maintains sufficiently detailed continuation-package reminders. If Dominds has already warned that context is tight or critical, Side Dialog reminders have no fixed length limit and rough multi-reminder carry-over is acceptable
46
46
 
47
47
  **Difference from memory:**
48
48
  | Feature | dialog reminder | task reminder | agent reminder | personal memory |
@@ -104,17 +104,17 @@ Taskdoc is a **task contract** and the task's **team-shared source of current tr
104
104
  - Do not treat an agent teammate like a human coworker who can only handle one conversation at a time. Same teammate + same `sessionSlug` = continue the same task and update that task; `tellaskSessionless` or a different `sessionSlug` = another independent task
105
105
  - Call `tellaskBack({ tellaskContent })` only when the tellasker must clarify the request, decide a tradeoff, confirm acceptance criteria, provide missing input, or current SOP cannot determine ownership
106
106
  - If a human must personally perform login / GUI / captcha / high-risk authorization: call `askHuman({ tellaskContent })`
107
- - If the current Side Dialog is complete and the assignment header says `replyTellask`: call `replyTellask({ replyContent })`
108
- - If the current Side Dialog is complete and the assignment header says `replyTellaskSessionless`: call `replyTellaskSessionless({ replyContent })`
109
- - If you are answering a tellasker `tellaskBack` follow-up and runtime exposes `replyTellaskBack`: call `replyTellaskBack({ replyContent })`
110
- - Plain text is not the completion channel for inter-dialog delivery; if you produce final deliverable content instead of the reply tool, runtime may temporarily inject a `role=user` reminder telling you to use the correct reply function. Do not rely on direct-reply fallback; it is only a temporary runtime transition safeguard, not the formal reply mechanism
107
+ - If the current Side Dialog is complete and the task header says `replyTellask`: call `replyTellask({ replyContent })`
108
+ - If the current Side Dialog is complete and the task header says `replyTellaskSessionless`: call `replyTellaskSessionless({ replyContent })`
109
+ - If you are answering a tellasker `tellaskBack` follow-up and Dominds shows `replyTellaskBack`: call `replyTellaskBack({ replyContent })`
110
+ - Plain text is not the completion channel for inter-dialog delivery. If you write final content for the requester but do not send it through the reply tool named by Dominds, Dominds may temporarily remind you to use that tool. Do not treat plain text as the formal reply path; the other dialog may not receive a formal reply that way.
111
111
 
112
112
  ### Low-Burden Rule
113
113
 
114
- - Focus on doing the current task correctly first; use `reply*` only when final tellasker delivery is actually ready
115
- - Do not memorize reply variants by yourself; follow the current assignment header and the function currently exposed by runtime
116
- - `reply*` tool descriptions are intentionally minimal and spec-like; use this manual's principles / scenarios for situational guidance
117
- - If runtime exposes only one `reply*`, that is the only correct completion path for the current state
114
+ - Focus on doing the current task correctly first; send the final reply only when the final content is ready and Dominds names a reply tool
115
+ - Do not memorize reply variants by yourself; follow the current task header and the reply tool currently named/shown by Dominds
116
+ - Reply tool descriptions are intentionally minimal and spec-like; use this manual's principles / scenarios for situational guidance
117
+ - If Dominds names/shows only one reply tool, that is the only correct completion path for the current state
118
118
  - `tellaskBack` is valid only when ownership cannot be determined from existing SOP, or when the tellasker must answer; it is not the default first move for every blocked state
119
119
 
120
120
  ## Best Practices
@@ -137,10 +137,10 @@ Taskdoc is a **task contract** and the task's **team-shared source of current tr
137
137
 
138
138
  - Keep concise: reminders are often 1-3 items; prefer `update_reminder` to compress/merge
139
139
  - Separate carriers: information that must synchronize the team's current effective state, key decisions, next steps, or still-active blockers belongs in `progress`, the quasi-real-time task bulletin board; reminders keep local resume details
140
- - Do not duplicate system state: background process status, in-flight background asks/collaboration, browser/session attachment state, and similar Dominds runtime-maintained environment state do not belong in manual reminders. Runtime-managed reminders, panels, and tool outputs are the single source of truth; manual copies go stale easily and create cognitive noise
140
+ - Do not duplicate system state: background process status, in-flight background asks/collaboration, browser/session attachment state, and similar environment state automatically maintained by Dominds do not belong in manual reminders. Dominds-managed reminders, panels, and tool outputs are the authoritative place for that state; manual copies go stale easily and create cognitive noise
141
141
  - Team-facing: keep `progress` scannable and centered on what is still effective now; do not let it degrade into a personal log, raw chronology, scratchpad, or stale history pile. Use `mind_more` for small additions; when cleanup/reordering/compression is needed, call `recall_taskdoc` first and then use `change_mind` with the returned `content_hash` as `previous_content_hash`
142
142
  - Condense when needed: `mind_more` is not the default bookkeeping move. If one topic already has several phase notes, prefer `change_mind` to merge them into the current summary; put the detailed expansion in formal rtws documentation and keep a document pointer in Taskdoc. If the replacement would overwrite existing content, proceed only with direct human confirmation or after applying a human-approved SOP/acceptance standard that considers the existing content
143
- - Collapse before clearing: the Main Dialog first records undocumented discussion details the next course needs to know into the appropriate Taskdoc sections, then creates a structured continuation-package reminder; a Side Dialog must not maintain Taskdoc or draft Taskdoc update proposals, and should directly maintain sufficiently detailed continuation-package reminders. If the current course is already under system remediation, rough multi-reminder carry-over is acceptable but must be reconciled first in the new course
143
+ - Collapse before clearing: the Main Dialog first records undocumented discussion details the next course needs to know into the appropriate Taskdoc sections, then creates a structured continuation-package reminder; a Side Dialog must not maintain Taskdoc or draft Taskdoc update proposals, and should directly maintain sufficiently detailed continuation-package reminders. If Dominds has already warned that context is tight or critical, rough multi-reminder carry-over is acceptable but must be reconciled first in the new course
144
144
  - Avoid raw-material dumps: do not paste long logs or large tool outputs into reminders
145
145
  - Documentation layering: Taskdoc says “what the team should sync on / do next now”; formal rtws documentation carries “why, how, detailed evidence, and the full process”. When Taskdoc references formal rtws documentation, use a stable path/section name/relevant command instead of copying the full content
146
146
 
@@ -164,5 +164,5 @@ Taskdoc is a **task contract** and the task's **team-shared source of current tr
164
164
  1. `dialog` reminders end with the dialog; `task` reminders stay visible under the current Taskdoc; `agent` reminders stay visible in all later dialogs you lead
165
165
  2. Use `do_mind` to create missing Taskdoc sections; use `mind_more` for small Taskdoc additions; use `change_mind` for full-section replacement of existing sections only after merging existing content and calling `recall_taskdoc` for the current `content_hash`; use `never_mind` when a whole section file should be deleted. Do not treat `mind_more` as a chronology tool; when cleanup, stale-entry removal, or same-topic consolidation is needed, use `recall_taskdoc` then `change_mind`
166
166
  3. `do_mind` / `mind_more` / `change_mind` / `never_mind` do not start a new course
167
- 4. A continuation-package reminder should keep only details still not covered by Taskdoc but easy to lose during resume; in the Main Dialog, undocumented discussion details from current dialog history that the next course needs to know should be written to the appropriate Taskdoc sections first; in a Side Dialog under caution/critical remediation, maintain sufficiently detailed continuation-package reminders only
167
+ 4. A continuation-package reminder should keep only details still not covered by Taskdoc but easy to lose during resume; in the Main Dialog, undocumented discussion details from current dialog history that the next course needs to know should be written to the appropriate Taskdoc sections first; in a Side Dialog after Dominds warns that context is tight or critical, maintain sufficiently detailed continuation-package reminders only
168
168
  5. Do not turn `task` / `agent` reminders into a long-term fact dump; move durable knowledge into `personal_memory`