dominds 1.9.4 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/dialog-fork.js +2 -0
  2. package/dist/dialog.d.ts +15 -3
  3. package/dist/dialog.js +12 -3
  4. package/dist/docs/team_mgmt-toolset.md +28 -25
  5. package/dist/docs/team_mgmt-toolset.zh.md +26 -23
  6. package/dist/llm/gen/mock.d.ts +2 -0
  7. package/dist/llm/gen/mock.js +74 -20
  8. package/dist/llm/kernel-driver/drive.js +165 -11
  9. package/dist/llm/kernel-driver/flow.js +177 -38
  10. package/dist/llm/kernel-driver/subdialog.d.ts +15 -0
  11. package/dist/llm/kernel-driver/subdialog.js +25 -1
  12. package/dist/llm/kernel-driver/tellask-special.d.ts +28 -2
  13. package/dist/llm/kernel-driver/tellask-special.js +372 -15
  14. package/dist/llm/kernel-driver/types.d.ts +2 -0
  15. package/dist/minds/system-prompt.js +18 -12
  16. package/dist/persistence.d.ts +7 -2
  17. package/dist/persistence.js +19 -1
  18. package/dist/priming.js +82 -0
  19. package/dist/runtime/driver-messages.js +23 -0
  20. package/dist/runtime/inter-dialog-format.d.ts +2 -0
  21. package/dist/runtime/inter-dialog-format.js +32 -4
  22. package/dist/server/api-routes.js +2 -2
  23. package/dist/server/snippets-routes.d.ts +2 -2
  24. package/dist/server/snippets-routes.js +21 -12
  25. package/dist/tools/builtins.js +0 -2
  26. package/dist/tools/ctrl.js +32 -10
  27. package/dist/tools/pending-tellask-reminder.js +14 -0
  28. package/dist/tools/prompts/control/en/index.md +8 -7
  29. package/dist/tools/prompts/control/en/principles.md +17 -0
  30. package/dist/tools/prompts/control/en/scenarios.md +54 -13
  31. package/dist/tools/prompts/control/en/tools.md +74 -2
  32. package/dist/tools/prompts/control/zh/index.md +8 -7
  33. package/dist/tools/prompts/control/zh/principles.md +17 -0
  34. package/dist/tools/prompts/control/zh/scenarios.md +53 -13
  35. package/dist/tools/prompts/control/zh/tools.md +72 -2
  36. package/dist/tools/team_mgmt.d.ts +2 -1
  37. package/dist/tools/team_mgmt.js +149 -194
  38. package/dist/tools/toolset-manual.js +67 -5
  39. package/package.json +2 -2
  40. package/webapp/dist/assets/{_basePickBy-D694K6Gh.js → _basePickBy-BTmAP1yh.js} +3 -3
  41. package/webapp/dist/assets/{_basePickBy-D694K6Gh.js.map → _basePickBy-BTmAP1yh.js.map} +1 -1
  42. package/webapp/dist/assets/{_baseUniq-ArneQk-G.js → _baseUniq-BkA36GAM.js} +2 -2
  43. package/webapp/dist/assets/{_baseUniq-ArneQk-G.js.map → _baseUniq-BkA36GAM.js.map} +1 -1
  44. package/webapp/dist/assets/{arc-8u9ipLr2.js → arc-BBz5hYKW.js} +2 -2
  45. package/webapp/dist/assets/{arc-8u9ipLr2.js.map → arc-BBz5hYKW.js.map} +1 -1
  46. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DFV-xGAa.js → architectureDiagram-2XIMDMQ5-CmJwv_ml.js} +7 -7
  47. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-DFV-xGAa.js.map → architectureDiagram-2XIMDMQ5-CmJwv_ml.js.map} +1 -1
  48. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-pk6LU06K.js → blockDiagram-WCTKOSBZ-Ts7Hwgip.js} +7 -7
  49. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-pk6LU06K.js.map → blockDiagram-WCTKOSBZ-Ts7Hwgip.js.map} +1 -1
  50. package/webapp/dist/assets/{c4Diagram-IC4MRINW-D4SBLYjK.js → c4Diagram-IC4MRINW-BqLDJw6g.js} +3 -3
  51. package/webapp/dist/assets/{c4Diagram-IC4MRINW-D4SBLYjK.js.map → c4Diagram-IC4MRINW-BqLDJw6g.js.map} +1 -1
  52. package/webapp/dist/assets/{channel-D8M5j8c2.js → channel-Dw01CGfa.js} +2 -2
  53. package/webapp/dist/assets/{channel-D8M5j8c2.js.map → channel-Dw01CGfa.js.map} +1 -1
  54. package/webapp/dist/assets/{chunk-4BX2VUAB-B-6IvMRI.js → chunk-4BX2VUAB-vYSDvcqd.js} +2 -2
  55. package/webapp/dist/assets/{chunk-4BX2VUAB-B-6IvMRI.js.map → chunk-4BX2VUAB-vYSDvcqd.js.map} +1 -1
  56. package/webapp/dist/assets/{chunk-55IACEB6-DjEvYtPp.js → chunk-55IACEB6-DtJVXukR.js} +2 -2
  57. package/webapp/dist/assets/{chunk-55IACEB6-DjEvYtPp.js.map → chunk-55IACEB6-DtJVXukR.js.map} +1 -1
  58. package/webapp/dist/assets/{chunk-FMBD7UC4-CrfwnW9e.js → chunk-FMBD7UC4-CQ54RPGO.js} +2 -2
  59. package/webapp/dist/assets/{chunk-FMBD7UC4-CrfwnW9e.js.map → chunk-FMBD7UC4-CQ54RPGO.js.map} +1 -1
  60. package/webapp/dist/assets/{chunk-JSJVCQXG-DroABPma.js → chunk-JSJVCQXG-BdacBw09.js} +2 -2
  61. package/webapp/dist/assets/{chunk-JSJVCQXG-DroABPma.js.map → chunk-JSJVCQXG-BdacBw09.js.map} +1 -1
  62. package/webapp/dist/assets/{chunk-KX2RTZJC--UaFwmvv.js → chunk-KX2RTZJC-DYdGOMBz.js} +2 -2
  63. package/webapp/dist/assets/{chunk-KX2RTZJC--UaFwmvv.js.map → chunk-KX2RTZJC-DYdGOMBz.js.map} +1 -1
  64. package/webapp/dist/assets/{chunk-NQ4KR5QH-hGQ1BQy3.js → chunk-NQ4KR5QH-CAkAZBmM.js} +4 -4
  65. package/webapp/dist/assets/{chunk-NQ4KR5QH-hGQ1BQy3.js.map → chunk-NQ4KR5QH-CAkAZBmM.js.map} +1 -1
  66. package/webapp/dist/assets/{chunk-QZHKN3VN-L1f-RVf4.js → chunk-QZHKN3VN-OzVsAi4S.js} +2 -2
  67. package/webapp/dist/assets/{chunk-QZHKN3VN-L1f-RVf4.js.map → chunk-QZHKN3VN-OzVsAi4S.js.map} +1 -1
  68. package/webapp/dist/assets/{chunk-WL4C6EOR-BS6MGl-Y.js → chunk-WL4C6EOR-fguokweJ.js} +6 -6
  69. package/webapp/dist/assets/{chunk-WL4C6EOR-BS6MGl-Y.js.map → chunk-WL4C6EOR-fguokweJ.js.map} +1 -1
  70. package/webapp/dist/assets/{classDiagram-VBA2DB6C-wDVeUi90.js → classDiagram-VBA2DB6C-QGMFe0Es.js} +7 -7
  71. package/webapp/dist/assets/{classDiagram-VBA2DB6C-wDVeUi90.js.map → classDiagram-VBA2DB6C-QGMFe0Es.js.map} +1 -1
  72. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-wDVeUi90.js → classDiagram-v2-RAHNMMFH-QGMFe0Es.js} +7 -7
  73. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-wDVeUi90.js.map → classDiagram-v2-RAHNMMFH-QGMFe0Es.js.map} +1 -1
  74. package/webapp/dist/assets/{clone-C2MtRhfG.js → clone-r2fKknvV.js} +2 -2
  75. package/webapp/dist/assets/{clone-C2MtRhfG.js.map → clone-r2fKknvV.js.map} +1 -1
  76. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CEf3Y19l.js → cose-bilkent-S5V4N54A-Cag1LFBF.js} +2 -2
  77. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CEf3Y19l.js.map → cose-bilkent-S5V4N54A-Cag1LFBF.js.map} +1 -1
  78. package/webapp/dist/assets/{dagre-KLK3FWXG-Dy_y44Tz.js → dagre-KLK3FWXG-BoRbJZ_3.js} +7 -7
  79. package/webapp/dist/assets/{dagre-KLK3FWXG-Dy_y44Tz.js.map → dagre-KLK3FWXG-BoRbJZ_3.js.map} +1 -1
  80. package/webapp/dist/assets/{diagram-E7M64L7V-Bvv5WU0i.js → diagram-E7M64L7V-C4LMoK7F.js} +8 -8
  81. package/webapp/dist/assets/{diagram-E7M64L7V-Bvv5WU0i.js.map → diagram-E7M64L7V-C4LMoK7F.js.map} +1 -1
  82. package/webapp/dist/assets/{diagram-IFDJBPK2-DgKslRxt.js → diagram-IFDJBPK2-Coi8p0U_.js} +7 -7
  83. package/webapp/dist/assets/{diagram-IFDJBPK2-DgKslRxt.js.map → diagram-IFDJBPK2-Coi8p0U_.js.map} +1 -1
  84. package/webapp/dist/assets/{diagram-P4PSJMXO-DKuN0W-K.js → diagram-P4PSJMXO-rYtOHq-X.js} +7 -7
  85. package/webapp/dist/assets/{diagram-P4PSJMXO-DKuN0W-K.js.map → diagram-P4PSJMXO-rYtOHq-X.js.map} +1 -1
  86. package/webapp/dist/assets/{erDiagram-INFDFZHY-Buc2e1H3.js → erDiagram-INFDFZHY-DdjP8gqj.js} +5 -5
  87. package/webapp/dist/assets/{erDiagram-INFDFZHY-Buc2e1H3.js.map → erDiagram-INFDFZHY-DdjP8gqj.js.map} +1 -1
  88. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-J69A4hB0.js → flowDiagram-PKNHOUZH-DgFoNe1-.js} +7 -7
  89. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-J69A4hB0.js.map → flowDiagram-PKNHOUZH-DgFoNe1-.js.map} +1 -1
  90. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-B_EUDSCl.js → ganttDiagram-A5KZAMGK-CMEzfhH3.js} +3 -3
  91. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-B_EUDSCl.js.map → ganttDiagram-A5KZAMGK-CMEzfhH3.js.map} +1 -1
  92. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-B1111A11.js → gitGraphDiagram-K3NZZRJ6-viKRvjr0.js} +8 -8
  93. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-B1111A11.js.map → gitGraphDiagram-K3NZZRJ6-viKRvjr0.js.map} +1 -1
  94. package/webapp/dist/assets/{graph-CdxqCYb0.js → graph-gVpOg_lE.js} +3 -3
  95. package/webapp/dist/assets/{graph-CdxqCYb0.js.map → graph-gVpOg_lE.js.map} +1 -1
  96. package/webapp/dist/assets/{index-BHe1oHIa.js → index-tcVhUj6_.js} +236 -99
  97. package/webapp/dist/assets/index-tcVhUj6_.js.map +1 -0
  98. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-B0NHDULu.js → infoDiagram-LFFYTUFH-P0b1XoV1.js} +6 -6
  99. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-B0NHDULu.js.map → infoDiagram-LFFYTUFH-P0b1XoV1.js.map} +1 -1
  100. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-zFZuCrGV.js → ishikawaDiagram-PHBUUO56-D40APktA.js} +2 -2
  101. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-zFZuCrGV.js.map → ishikawaDiagram-PHBUUO56-D40APktA.js.map} +1 -1
  102. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C-Y3JIvI.js → journeyDiagram-4ABVD52K-D6aNNJVd.js} +5 -5
  103. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C-Y3JIvI.js.map → journeyDiagram-4ABVD52K-D6aNNJVd.js.map} +1 -1
  104. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-CAWm_s77.js → kanban-definition-K7BYSVSG-DQKvYmMb.js} +3 -3
  105. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-CAWm_s77.js.map → kanban-definition-K7BYSVSG-DQKvYmMb.js.map} +1 -1
  106. package/webapp/dist/assets/{layout-DAf8AacP.js → layout-FpBDmPYH.js} +5 -5
  107. package/webapp/dist/assets/{layout-DAf8AacP.js.map → layout-FpBDmPYH.js.map} +1 -1
  108. package/webapp/dist/assets/{linear-5V_bWmGQ.js → linear-peqpVuLQ.js} +2 -2
  109. package/webapp/dist/assets/{linear-5V_bWmGQ.js.map → linear-peqpVuLQ.js.map} +1 -1
  110. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CbZFlmPZ.js → mindmap-definition-YRQLILUH-CwvIH34J.js} +4 -4
  111. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CbZFlmPZ.js.map → mindmap-definition-YRQLILUH-CwvIH34J.js.map} +1 -1
  112. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-BdjfUPSq.js → pieDiagram-SKSYHLDU-lM7j5Uhe.js} +8 -8
  113. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-BdjfUPSq.js.map → pieDiagram-SKSYHLDU-lM7j5Uhe.js.map} +1 -1
  114. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_roS40E.js → quadrantDiagram-337W2JSQ-D7UU9Dp-.js} +3 -3
  115. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_roS40E.js.map → quadrantDiagram-337W2JSQ-D7UU9Dp-.js.map} +1 -1
  116. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Cte4tBaS.js → requirementDiagram-Z7DCOOCP-CsJFJ-cl.js} +4 -4
  117. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-Cte4tBaS.js.map → requirementDiagram-Z7DCOOCP-CsJFJ-cl.js.map} +1 -1
  118. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-_7BuCxMO.js → sankeyDiagram-WA2Y5GQK-Dl4-eWCT.js} +2 -2
  119. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-_7BuCxMO.js.map → sankeyDiagram-WA2Y5GQK-Dl4-eWCT.js.map} +1 -1
  120. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DIrNFVXO.js → sequenceDiagram-2WXFIKYE-Bu3kNgJ9.js} +4 -4
  121. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DIrNFVXO.js.map → sequenceDiagram-2WXFIKYE-Bu3kNgJ9.js.map} +1 -1
  122. package/webapp/dist/assets/{stateDiagram-RAJIS63D-CleFEXbm.js → stateDiagram-RAJIS63D-CadfG4Au.js} +9 -9
  123. package/webapp/dist/assets/{stateDiagram-RAJIS63D-CleFEXbm.js.map → stateDiagram-RAJIS63D-CadfG4Au.js.map} +1 -1
  124. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BPhDPWWG.js → stateDiagram-v2-FVOUBMTO-CabV9tQH.js} +5 -5
  125. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BPhDPWWG.js.map → stateDiagram-v2-FVOUBMTO-CabV9tQH.js.map} +1 -1
  126. package/webapp/dist/assets/{timeline-definition-YZTLITO2-DrrU-OCU.js → timeline-definition-YZTLITO2-XqBsdE-B.js} +3 -3
  127. package/webapp/dist/assets/{timeline-definition-YZTLITO2-DrrU-OCU.js.map → timeline-definition-YZTLITO2-XqBsdE-B.js.map} +1 -1
  128. package/webapp/dist/assets/{treemap-KZPCXAKY-DShBAWxS.js → treemap-KZPCXAKY-Cc-MHIad.js} +5 -5
  129. package/webapp/dist/assets/{treemap-KZPCXAKY-DShBAWxS.js.map → treemap-KZPCXAKY-Cc-MHIad.js.map} +1 -1
  130. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DNQztUY0.js → vennDiagram-LZ73GAT5-DPu_jSWi.js} +2 -2
  131. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DNQztUY0.js.map → vennDiagram-LZ73GAT5-DPu_jSWi.js.map} +1 -1
  132. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-q8D6fe1E.js → xychartDiagram-JWTSCODW-8Dh_0DI4.js} +3 -3
  133. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-q8D6fe1E.js.map → xychartDiagram-JWTSCODW-8Dh_0DI4.js.map} +1 -1
  134. package/webapp/dist/index.html +1 -1
  135. package/webapp/dist/assets/index-BHe1oHIa.js.map +0 -1
@@ -106,6 +106,7 @@ function isPersistedMessageRecord(record) {
106
106
  return true;
107
107
  case 'web_search_call_record':
108
108
  case 'quest_for_sup_record':
109
+ case 'tellask_reply_resolution_record':
109
110
  case 'tellask_call_carryover_record':
110
111
  case 'tellask_call_anchor_record':
111
112
  case 'gen_start_record':
@@ -175,6 +176,7 @@ function rewriteRecordForFork(record, newRootId) {
175
176
  case 'human_text_record':
176
177
  case 'quest_for_sup_record':
177
178
  case 'tellask_call_result_record':
179
+ case 'tellask_reply_resolution_record':
178
180
  case 'tellask_call_carryover_record':
179
181
  case 'tellask_call_anchor_record':
180
182
  case 'tellask_response_record':
package/dist/dialog.d.ts CHANGED
@@ -16,7 +16,7 @@ import type { ContextHealthSnapshot } from '@longrun-ai/kernel/types/context-hea
16
16
  import type { DialogEvent, ReminderContent, WebSearchCallAction } from '@longrun-ai/kernel/types/dialog';
17
17
  import type { DialogPrompt, DialogRunControlSpec, DialogSubdialogReplyTarget, DriveIntent } from '@longrun-ai/kernel/types/drive-intent';
18
18
  import type { LanguageCode } from '@longrun-ai/kernel/types/language';
19
- import type { CalleeCourseNumber, CalleeGenerationSeqNumber, CallingCourseNumber, DialogMetadataFile, HumanQuestion, ProviderData, ReasoningPayload, ToolArguments as StoredToolArguments } from '@longrun-ai/kernel/types/storage';
19
+ import type { CalleeCourseNumber, CalleeGenerationSeqNumber, CallingCourseNumber, DialogMetadataFile, HumanQuestion, ProviderData, ReasoningPayload, ToolArguments as StoredToolArguments, TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
20
20
  import { ChatMessage, FuncResultMsg } from './llm/client';
21
21
  import type { JsonValue } from './tool';
22
22
  import { Reminder, ReminderOptions, ReminderOwner } from './tool';
@@ -35,6 +35,7 @@ type UpNextPromptState = {
35
35
  userLanguageCode?: LanguageCode;
36
36
  origin: 'user' | 'diligence_push' | 'runtime';
37
37
  q4hAnswerCallIds?: string[];
38
+ tellaskReplyDirective?: TellaskReplyDirective;
38
39
  skipTaskdoc?: boolean;
39
40
  subdialogReplyTarget?: DialogSubdialogReplyTarget;
40
41
  runControl?: DialogRunControlSpec;
@@ -328,6 +329,7 @@ export declare abstract class Dialog {
328
329
  grammar: 'markdown';
329
330
  userLanguageCode?: LanguageCode;
330
331
  q4hAnswerCallIds?: string[];
332
+ tellaskReplyDirective?: TellaskReplyDirective;
331
333
  skipTaskdoc?: boolean;
332
334
  subdialogReplyTarget?: DialogSubdialogReplyTarget;
333
335
  }): UpNextPromptState;
@@ -398,7 +400,12 @@ export declare abstract class Dialog {
398
400
  calleeGenseq?: CalleeGenerationSeqNumber;
399
401
  }): Promise<void>;
400
402
  updateQuestions4Human(questions: HumanQuestion[]): Promise<void>;
401
- persistUserMessage(content: string, msgId: string, grammar: 'markdown', origin: 'user' | 'diligence_push' | 'runtime' | undefined, userLanguageCode?: LanguageCode, q4hAnswerCallIds?: string[]): Promise<void>;
403
+ persistUserMessage(content: string, msgId: string, grammar: 'markdown', origin: 'user' | 'diligence_push' | 'runtime' | undefined, userLanguageCode?: LanguageCode, q4hAnswerCallIds?: string[], tellaskReplyDirective?: TellaskReplyDirective): Promise<void>;
404
+ appendTellaskReplyResolution(payload: {
405
+ callId: string;
406
+ replyCallName: 'replyTellask' | 'replyTellaskSessionless' | 'replyTellaskBack';
407
+ targetCallId: string;
408
+ }): Promise<void>;
402
409
  persistAgentMessage(content: string, genseq: number, type: 'thinking_msg' | 'saying_msg', provider_data?: ProviderData, reasoning?: ReasoningPayload): Promise<void>;
403
410
  persistUiOnlyMarkdown(content: string, genseq: number): Promise<void>;
404
411
  persistFunctionCall(id: string, name: string, arguments_: StoredToolArguments, genseq: number): Promise<void>;
@@ -614,7 +621,12 @@ export declare abstract class DialogStore {
614
621
  /**
615
622
  * Persist a user message to storage
616
623
  */
617
- persistUserMessage(_dialog: Dialog, _content: string, _msgId: string, _grammar: 'markdown', _origin: 'user' | 'diligence_push' | 'runtime' | undefined, _userLanguageCode?: LanguageCode, _q4hAnswerCallIds?: string[]): Promise<void>;
624
+ persistUserMessage(_dialog: Dialog, _content: string, _msgId: string, _grammar: 'markdown', _origin: 'user' | 'diligence_push' | 'runtime' | undefined, _userLanguageCode?: LanguageCode, _q4hAnswerCallIds?: string[], _tellaskReplyDirective?: TellaskReplyDirective): Promise<void>;
625
+ appendTellaskReplyResolution(_dialog: Dialog, _payload: {
626
+ callId: string;
627
+ replyCallName: 'replyTellask' | 'replyTellaskSessionless' | 'replyTellaskBack';
628
+ targetCallId: string;
629
+ }): Promise<void>;
618
630
  /**
619
631
  * Persist an assistant message to storage
620
632
  */
package/dist/dialog.js CHANGED
@@ -526,6 +526,7 @@ class Dialog {
526
526
  userLanguageCode: prompt.userLanguageCode,
527
527
  origin: prompt.origin,
528
528
  q4hAnswerCallIds: prompt.q4hAnswerCallIds,
529
+ tellaskReplyDirective: prompt.tellaskReplyDirective,
529
530
  skipTaskdoc: prompt.skipTaskdoc,
530
531
  subdialogReplyTarget: prompt.subdialogReplyTarget,
531
532
  runControl,
@@ -550,6 +551,7 @@ class Dialog {
550
551
  grammar: nextPrompt.grammar ?? 'markdown',
551
552
  userLanguageCode: nextPrompt.userLanguageCode,
552
553
  q4hAnswerCallIds: nextPrompt.q4hAnswerCallIds,
554
+ tellaskReplyDirective: nextPrompt.tellaskReplyDirective,
553
555
  skipTaskdoc: nextPrompt.skipTaskdoc,
554
556
  subdialogReplyTarget: nextPrompt.subdialogReplyTarget,
555
557
  },
@@ -612,6 +614,7 @@ class Dialog {
612
614
  userLanguageCode: state.userLanguageCode ?? this._lastUserLanguageCode,
613
615
  origin: state.origin,
614
616
  q4hAnswerCallIds: state.q4hAnswerCallIds,
617
+ tellaskReplyDirective: state.tellaskReplyDirective,
615
618
  skipTaskdoc: state.skipTaskdoc,
616
619
  subdialogReplyTarget: state.subdialogReplyTarget,
617
620
  },
@@ -688,6 +691,7 @@ class Dialog {
688
691
  userLanguageCode: options.userLanguageCode ?? this._lastUserLanguageCode,
689
692
  origin: 'runtime',
690
693
  q4hAnswerCallIds: options.q4hAnswerCallIds,
694
+ tellaskReplyDirective: options.tellaskReplyDirective,
691
695
  skipTaskdoc: options.skipTaskdoc,
692
696
  subdialogReplyTarget: options.subdialogReplyTarget,
693
697
  runControl: undefined,
@@ -702,6 +706,7 @@ class Dialog {
702
706
  grammar: options.grammar,
703
707
  userLanguageCode: options.userLanguageCode ?? existing.userLanguageCode ?? this._lastUserLanguageCode,
704
708
  q4hAnswerCallIds: this.mergePromptQ4HAnswerCallIds(existing.q4hAnswerCallIds, options.q4hAnswerCallIds),
709
+ tellaskReplyDirective: options.tellaskReplyDirective ?? existing.tellaskReplyDirective,
705
710
  skipTaskdoc: options.skipTaskdoc ?? existing.skipTaskdoc,
706
711
  subdialogReplyTarget: options.subdialogReplyTarget ?? existing.subdialogReplyTarget,
707
712
  runControl: undefined,
@@ -908,8 +913,11 @@ class Dialog {
908
913
  async updateQuestions4Human(questions) {
909
914
  return await this.dlgStore.updateQuestions4Human(this, questions);
910
915
  }
911
- async persistUserMessage(content, msgId, grammar, origin, userLanguageCode, q4hAnswerCallIds) {
912
- return await this.dlgStore.persistUserMessage(this, content, msgId, grammar, origin, userLanguageCode, q4hAnswerCallIds);
916
+ async persistUserMessage(content, msgId, grammar, origin, userLanguageCode, q4hAnswerCallIds, tellaskReplyDirective) {
917
+ return await this.dlgStore.persistUserMessage(this, content, msgId, grammar, origin, userLanguageCode, q4hAnswerCallIds, tellaskReplyDirective);
918
+ }
919
+ async appendTellaskReplyResolution(payload) {
920
+ await this.dlgStore.appendTellaskReplyResolution(this, payload);
913
921
  }
914
922
  async persistAgentMessage(content, genseq, type, provider_data, reasoning) {
915
923
  return await this.dlgStore.persistAgentMessage(this, content, genseq, type, provider_data, reasoning);
@@ -1307,7 +1315,8 @@ class DialogStore {
1307
1315
  /**
1308
1316
  * Persist a user message to storage
1309
1317
  */
1310
- async persistUserMessage(_dialog, _content, _msgId, _grammar, _origin, _userLanguageCode, _q4hAnswerCallIds) { }
1318
+ async persistUserMessage(_dialog, _content, _msgId, _grammar, _origin, _userLanguageCode, _q4hAnswerCallIds, _tellaskReplyDirective) { }
1319
+ async appendTellaskReplyResolution(_dialog, _payload) { }
1311
1320
  /**
1312
1321
  * Persist an assistant message to storage
1313
1322
  */
@@ -6,6 +6,9 @@ This document specifies a dedicated **team management toolset** whose only job i
6
6
  rtws’s “mindset” configuration files under `.minds/` (team roster, LLM providers, and agent
7
7
  minds files), without granting broad rtws access.
8
8
 
9
+ > Historical note: the runtime/manual entrypoint has since been unified to
10
+ > `man({ "toolsetId": "team_mgmt" })`, which now renders the authoritative handbook content.
11
+
9
12
  The outer repository root is the **rtws** (runtime workspace). All paths below are relative to the
10
13
  rtws root.
11
14
 
@@ -33,18 +36,18 @@ This document is a **design spec** for the new `team_mgmt` toolset. It is not so
33
36
  ever tell an agent to “look up” at runtime.
34
37
 
35
38
  Instead, the runtime “single source of truth” for team management guidance should be
36
- the function tool `team_mgmt_manual`.
39
+ `man({ "toolsetId": "team_mgmt" })`.
37
40
 
38
41
  Historically, some of the guidance lived in a legacy builtin “team manager” mind set inside the
39
42
  `dominds/` source tree. That legacy builtin is being removed. The runtime “single source of truth”
40
- should be the `team_mgmt_manual` tool output.
43
+ should be the `man({ "toolsetId": "team_mgmt" })` output.
41
44
 
42
45
  Planned change:
43
46
 
44
- - Add a new function tool `team_mgmt_manual` whose responses cover the team-management topics (file
45
- formats, workflows, safety).
47
+ - Route team-management handbook content through the generic `man` tool under
48
+ `man({ "toolsetId": "team_mgmt" })`, covering file formats, workflows, and safety.
46
49
  - Remove legacy builtin guidance to avoid duplication. If any stub remains, it must point to
47
- `team_mgmt_manual` (and not to this design document).
50
+ `man({ "toolsetId": "team_mgmt" })` (and not to this design document).
48
51
 
49
52
  Rationale:
50
53
 
@@ -82,7 +85,7 @@ The `team_mgmt` toolset mirrors a minimal subset of `fs`/`txt`, but **hard-scope
82
85
 
83
86
  ### Naming Conventions (Human / UI)
84
87
 
85
- - **Tools** use `snake_case` (underscore-separated) for tool IDs (e.g. `team_mgmt_manual`). Avoid
88
+ - **Tools** use `snake_case` (underscore-separated) for tool IDs (e.g. `team_mgmt_validate_team_cfg`). Avoid
86
89
  `kebab-case` aliases for tool IDs; if UX needs a friendlier label, treat that as presentation-only.
87
90
  - **Teammates** use either `kebab-case` (hyphen-separated) or an “internet name” (dot-separated).
88
91
  - This is a convention for docs/UI/readability only; do not enforce it via validation or other
@@ -111,7 +114,7 @@ Recommended tools (names are suggestions; use `snake_case` to match existing too
111
114
  | `team_mgmt_rm_dir` | `fs` | Delete directories under `.minds/` | `.minds/**` |
112
115
  | `team_mgmt_validate_priming_scripts` | new | Validate path constraints and script format under `.minds/priming/**.md` | `.minds/**` |
113
116
  | `team_mgmt_validate_team_cfg` | new | Validate `.minds/team.yaml` and publish issues to the Problems panel | `.minds/**` |
114
- | `team_mgmt_manual` | new | Built-in “how-to” manual (see below) | N/A |
117
+ | `man({ "toolsetId": "team_mgmt" })` | builtin | Handbook entrypoint for the `team_mgmt` toolset (see below) | N/A |
115
118
 
116
119
  Notes:
117
120
 
@@ -143,32 +146,32 @@ may not exist during bootstrap. A dedicated `team_mgmt` toolset:
143
146
  - Makes it easy to grant _just_ team management capabilities to an ad-hoc agent without full rtws
144
147
  access.
145
148
 
146
- ## `team_mgmt_manual`
149
+ ## Team Handbook via `man({ "toolsetId": "team_mgmt" })`
147
150
 
148
151
  We need a single in-chat manual tool so the team manager can reliably self-serve guidance without
149
152
  reading source code.
150
153
 
151
154
  ### Command shape
152
155
 
153
- - `team_mgmt_manual({ "topics": [] })` → show a short index (topics).
154
- - `team_mgmt_manual({ "topics": ["topics"] })` → list topics.
155
- - `team_mgmt_manual({ "topics": ["llm"] })` → how to manage `.minds/llm.yaml` (+ templates).
156
- - `team_mgmt_manual({ "topics": ["llm", "builtin-defaults"] })` → show builtin providers/models (from defaults).
157
- - `team_mgmt_manual({ "topics": ["mcp"] })` → how to manage `.minds/mcp.yaml` (+ templates).
158
- - `team_mgmt_manual({ "topics": ["mcp"] })` → how to manage `.minds/mcp.yaml` (transports, env/headers, tools whitelist/blacklist, naming transforms, hot reload, leasing).
159
- - `team_mgmt_manual({ "topics": ["mcp", "troubleshooting"] })` → common MCP failure modes and how to recover.
160
- - `team_mgmt_manual({ "topics": ["team"] })` → how to manage `.minds/team.yaml` (+ templates).
161
- - `team_mgmt_manual({ "topics": ["team", "member-properties"] })` → list supported member fields and meanings.
162
- - `team_mgmt_manual({ "topics": ["minds"] })` → how to manage `.minds/team/<id>/*.md` (persona/knowledge/lessons).
163
- - `team_mgmt_manual({ "topics": ["priming"] })` → how to manage startup scripts under `.minds/priming/*`.
164
- - `team_mgmt_manual({ "topics": ["permissions"] })` → how `read_dirs`/`write_dirs` and deny-lists work.
165
- - `team_mgmt_manual({ "topics": ["troubleshooting"] })` → common failure modes and how to recover.
156
+ - `man({ "toolsetId": "team_mgmt" })` → show a short index (topics).
157
+ - `man({ "toolsetId": "team_mgmt", "topics": ["topics"] })` → list topics.
158
+ - `man({ "toolsetId": "team_mgmt", "topics": ["llm"] })` → how to manage `.minds/llm.yaml` (+ templates).
159
+ - `man({ "toolsetId": "team_mgmt", "topics": ["llm", "builtin-defaults"] })` → show builtin providers/models (from defaults).
160
+ - `man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })` → how to manage `.minds/mcp.yaml` (+ templates).
161
+ - `man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })` → how to manage `.minds/mcp.yaml` (transports, env/headers, tools whitelist/blacklist, naming transforms, hot reload, leasing).
162
+ - `man({ "toolsetId": "team_mgmt", "topics": ["mcp", "troubleshooting"] })` → common MCP failure modes and how to recover.
163
+ - `man({ "toolsetId": "team_mgmt", "topics": ["team"] })` → how to manage `.minds/team.yaml` (+ templates).
164
+ - `man({ "toolsetId": "team_mgmt", "topics": ["team", "member-properties"] })` → list supported member fields and meanings.
165
+ - `man({ "toolsetId": "team_mgmt", "topics": ["minds"] })` → how to manage `.minds/team/<id>/*.md` (persona/knowledge/lessons).
166
+ - `man({ "toolsetId": "team_mgmt", "topics": ["priming"] })` → how to manage startup scripts under `.minds/priming/*`.
167
+ - `man({ "toolsetId": "team_mgmt", "topics": ["permissions"] })` → how `read_dirs`/`write_dirs` and deny-lists work.
168
+ - `man({ "toolsetId": "team_mgmt", "topics": ["troubleshooting"] })` → common failure modes and how to recover.
166
169
 
167
170
  The manual should accept **multiple** `topics` entries (a simple topic “path”); the tool should
168
171
  select the most specific match and fall back to the nearest parent when needed.
169
172
 
170
- If UX wants a friendlier label than `team_mgmt_manual`, treat that as presentation-only; the
171
- canonical tool ID remains `team_mgmt_manual`.
173
+ If UX wants a friendlier label than `man`, treat that as presentation-only; the
174
+ canonical runtime entrypoint remains `man({ "toolsetId": "team_mgmt" })`.
172
175
 
173
176
  ## Manual Coverage Requirements (legacy coverage)
174
177
 
@@ -209,12 +212,12 @@ This keeps the manual accurate when the framework changes, and avoids documentat
209
212
 
210
213
  Recommended sources by topic:
211
214
 
212
- - `team_mgmt_manual({ "topics": ["llm", "builtin-defaults"] })`
215
+ - `man({ "toolsetId": "team_mgmt", "topics": ["llm", "builtin-defaults"] })`
213
216
  - Load from the same installation resource the runtime uses for defaults:
214
217
  `dominds/main/llm/defaults.yaml` (via `__dirname` resolution in the backend build output).
215
218
  - Prefer reusing `LlmConfig.load()` and formatting its merged view, or adding a helper that returns
216
219
  both “defaults-only” and “merged” provider maps.
217
- - `team_mgmt_manual({ "topics": ["toolsets"] })` (if added)
220
+ - `man({ "toolsetId": "team_mgmt", "topics": ["toolsets"] })` (if added)
218
221
  - Load from the in-memory registries at runtime (`listToolsets()` / `listTools()` in
219
222
  `dominds/main/tools/registry.ts`), rather than maintaining a separate list.
220
223
 
@@ -4,6 +4,9 @@
4
4
 
5
5
  本文档指定了一个专用的**团队管理工具集**,其唯一职责是管理 rtws(运行时工作区)`.minds/` 下的"心智"配置文件(团队名单、LLM 提供商和智能体心智文件),而不授予广泛的运行时工作区访问权限。
6
6
 
7
+ > 历史说明:运行时/手册入口现已统一为
8
+ > `man({ "toolsetId": "team_mgmt" })`,它才是当前权威的团队管理手册入口。
9
+
7
10
  外部仓库根目录是 **rtws**(运行时工作区)。以下所有路径均相对于 rtws 根目录。
8
11
 
9
12
  ## 动机
@@ -25,14 +28,14 @@
25
28
 
26
29
  本文档是新的 `team_mgmt` 工具集的**设计规范**。这不是我们应该在运行时让智能体"查阅"的内容。
27
30
 
28
- 相反,运行时团队管理的"单一事实来源"应该是函数工具 `team_mgmt_manual` 的输出。
31
+ 相反,运行时团队管理的"单一事实来源"应该是 `man({ "toolsetId": "team_mgmt" })` 的输出。
29
32
 
30
- 历史上,部分指导内容位于 `dominds/` 源代码树中的传统内置"团队管理者"心智集中。该传统内置内容正在被移除。运行时的"单一事实来源"应该是 `team_mgmt_manual` 工具的输出。
33
+ 历史上,部分指导内容位于 `dominds/` 源代码树中的传统内置"团队管理者"心智集中。该传统内置内容正在被移除。运行时的"单一事实来源"应该是 `man({ "toolsetId": "team_mgmt" })` 的输出。
31
34
 
32
35
  计划变更:
33
36
 
34
- - 添加一个新的函数工具 `team_mgmt_manual`,其响应涵盖团队管理主题(文件格式、工作流、安全性)
35
- - 移除传统的内置指导以避免重复。如果保留任何存根,必须指向 `team_mgmt_manual`(而不是本文档)
37
+ - 通过通用 `man` 工具的 `man({ "toolsetId": "team_mgmt" })` 入口承载团队管理主题(文件格式、工作流、安全性)
38
+ - 移除传统的内置指导以避免重复。如果保留任何存根,必须指向 `man({ "toolsetId": "team_mgmt" })`(而不是本文档)
36
39
 
37
40
  理由:
38
41
 
@@ -67,7 +70,7 @@
67
70
 
68
71
  ### 命名约定(人类 / UI)
69
72
 
70
- - **工具**使用 `snake_case`(下划线分隔)作为工具 ID(例如 `team_mgmt_manual`)。避免为工具 ID 使用 `kebab-case` 别名;如果 UX 需要更友好的标签,将其视为仅展示层。
73
+ - **工具**使用 `snake_case`(下划线分隔)作为工具 ID(例如 `team_mgmt_validate_team_cfg`)。避免为工具 ID 使用 `kebab-case` 别名;如果 UX 需要更友好的标签,将其视为仅展示层。
71
74
  - **队友**使用 `kebab-case`(连字符分隔)或"互联网名称"(点分隔)。
72
75
  - 这只是文档/UI/可读性的约定;不要通过验证或其他技术机制强制执行。
73
76
 
@@ -94,7 +97,7 @@
94
97
  | `team_mgmt_rm_dir` | `fs` | 删除 `.minds/` 下的目录 | `.minds/**` |
95
98
  | `team_mgmt_validate_priming_scripts` | 新建 | 校验 `.minds/priming/**.md` 的路径约束与脚本格式 | `.minds/**` |
96
99
  | `team_mgmt_validate_team_cfg` | 新建 | 验证 `.minds/team.yaml` 并将问题发布到问题面板 | `.minds/**` |
97
- | `team_mgmt_manual` | 新建 | 内置"操作指南"手册(见下文) | N/A |
100
+ | `man({ "toolsetId": "team_mgmt" })` | 内置 | `team_mgmt` 工具集的手册入口(见下文) | N/A |
98
101
 
99
102
  注意:
100
103
 
@@ -117,29 +120,29 @@
117
120
  - 即使成员的目录允许/拒绝列表为空,也保持作用域边界
118
121
  - 便于授予临时智能体仅团队管理能力而无需完整的 rtws 访问
119
122
 
120
- ## `team_mgmt_manual`
123
+ ## 通过 `man({ "toolsetId": "team_mgmt" })` 查看团队手册
121
124
 
122
125
  我们需要单一的聊天内手册工具,以便团队管理者能够可靠地自助指导,而无需阅读源代码。
123
126
 
124
127
  ### 命令形状
125
128
 
126
- - `team_mgmt_manual({ "topics": [] })` → 显示简短索引(主题)
127
- - `team_mgmt_manual({ "topics": ["topics"] })` → 列出主题
128
- - `team_mgmt_manual({ "topics": ["llm"] })` → 如何管理 `.minds/llm.yaml`(+ 模板)
129
- - `team_mgmt_manual({ "topics": ["llm", "builtin-defaults"] })` → 显示内置提供商/模型(来自默认值)
130
- - `team_mgmt_manual({ "topics": ["mcp"] })` → 如何管理 `.minds/mcp.yaml`(+ 模板)
131
- - `team_mgmt_manual({ "topics": ["mcp"] })` → 如何管理 `.minds/mcp.yaml`(传输、env/headers、工具白名单/黑名单、命名转换、热重载、租赁)
132
- - `team_mgmt_manual({ "topics": ["mcp", "troubleshooting"] })` → 常见 MCP 故障模式及如何恢复
133
- - `team_mgmt_manual({ "topics": ["team"] })` → 如何管理 `.minds/team.yaml`(+ 模板)
134
- - `team_mgmt_manual({ "topics": ["team", "member-properties"] })` → 列出支持的成员字段及其含义
135
- - `team_mgmt_manual({ "topics": ["minds"] })` → 如何管理 `.minds/team/<id>/*.md`(persona/knowledge/lessons)
136
- - `team_mgmt_manual({ "topics": ["priming"] })` → 如何管理 `.minds/priming/*` 启动脚本(格式、维护、复用)
137
- - `team_mgmt_manual({ "topics": ["permissions"] })` → `read_dirs`/`write_dirs` 和拒绝列表如何工作
138
- - `team_mgmt_manual({ "topics": ["troubleshooting"] })` → 常见故障模式及如何恢复
129
+ - `man({ "toolsetId": "team_mgmt" })` → 显示简短索引(主题)
130
+ - `man({ "toolsetId": "team_mgmt", "topics": ["topics"] })` → 列出主题
131
+ - `man({ "toolsetId": "team_mgmt", "topics": ["llm"] })` → 如何管理 `.minds/llm.yaml`(+ 模板)
132
+ - `man({ "toolsetId": "team_mgmt", "topics": ["llm", "builtin-defaults"] })` → 显示内置提供商/模型(来自默认值)
133
+ - `man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })` → 如何管理 `.minds/mcp.yaml`(+ 模板)
134
+ - `man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })` → 如何管理 `.minds/mcp.yaml`(传输、env/headers、工具白名单/黑名单、命名转换、热重载、租赁)
135
+ - `man({ "toolsetId": "team_mgmt", "topics": ["mcp", "troubleshooting"] })` → 常见 MCP 故障模式及如何恢复
136
+ - `man({ "toolsetId": "team_mgmt", "topics": ["team"] })` → 如何管理 `.minds/team.yaml`(+ 模板)
137
+ - `man({ "toolsetId": "team_mgmt", "topics": ["team", "member-properties"] })` → 列出支持的成员字段及其含义
138
+ - `man({ "toolsetId": "team_mgmt", "topics": ["minds"] })` → 如何管理 `.minds/team/<id>/*.md`(persona/knowledge/lessons)
139
+ - `man({ "toolsetId": "team_mgmt", "topics": ["priming"] })` → 如何管理 `.minds/priming/*` 启动脚本(格式、维护、复用)
140
+ - `man({ "toolsetId": "team_mgmt", "topics": ["permissions"] })` → `read_dirs`/`write_dirs` 和拒绝列表如何工作
141
+ - `man({ "toolsetId": "team_mgmt", "topics": ["troubleshooting"] })` → 常见故障模式及如何恢复
139
142
 
140
143
  该手册应接受**多个**`topics` 条目(简单的主题"路径");工具应选择最具体的匹配,并在需要时回退到最近的父主题。
141
144
 
142
- 如果 UX 需要比 `team_mgmt_manual` 更友好的标签,将其视为仅展示层;规范的工具 ID 保持为 `team_mgmt_manual`。
145
+ 如果 UX 需要比 `man` 更友好的标签,将其视为仅展示层;规范的运行时入口保持为 `man({ "toolsetId": "team_mgmt" })`。
143
146
 
144
147
  ## 手册覆盖要求(传统覆盖)
145
148
 
@@ -172,10 +175,10 @@
172
175
 
173
176
  按主题推荐的来源:
174
177
 
175
- - `team_mgmt_manual({ "topics": ["llm", "builtin-defaults"] })`
178
+ - `man({ "toolsetId": "team_mgmt", "topics": ["llm", "builtin-defaults"] })`
176
179
  - 从运行时用于默认值的同一安装资源加载:`dominds/main/llm/defaults.yaml`(通过后端构建输出中的 `__dirname` 解析)
177
180
  - 优先重用 `LlmConfig.load()` 并格式化其合并视图,或添加一个返回"仅默认值"和"合并"提供商映射的助手
178
- - `team_mgmt_manual({ "topics": ["toolsets"] })`(如果添加)
181
+ - `man({ "toolsetId": "team_mgmt", "topics": ["toolsets"] })`(如果添加)
179
182
  - 在运行时从内存中注册表加载(`dominds/main/tools/registry.ts` 中的 `listToolsets()` / `listTools()`),而不是维护单独的列表
180
183
 
181
184
  将这些保持为**静态/手册文本**(而非动态加载):
@@ -64,6 +64,8 @@ export declare class MockGen implements LlmGenerator {
64
64
  private loadResponseDatabase;
65
65
  private responseMatchesContext;
66
66
  private normalizeFuncCallArgs;
67
+ private extractLastAssistantSaying;
68
+ private buildReplyToolReminderAutoResponse;
67
69
  /**
68
70
  * Find matching response using EXACT last message only.
69
71
  * NO fallback to message-only matching - if exact match fails, return null.
@@ -63,6 +63,10 @@ const promises_1 = __importDefault(require("fs/promises"));
63
63
  const path_1 = __importDefault(require("path"));
64
64
  const yaml_1 = __importDefault(require("yaml"));
65
65
  const log_1 = require("../../log");
66
+ const REPLY_TOOL_REMINDER_PREFIXES = [
67
+ '[Dominds replyTellask required]',
68
+ '[Dominds 必须调用回复工具]',
69
+ ];
66
70
  function normalizeDelayMs(value) {
67
71
  if (typeof value !== 'number' || !Number.isFinite(value))
68
72
  return 0;
@@ -251,6 +255,44 @@ class MockGen {
251
255
  }
252
256
  return JSON.stringify(args);
253
257
  }
258
+ extractLastAssistantSaying(context) {
259
+ for (let i = context.length - 1; i >= 0; i -= 1) {
260
+ const msg = context[i];
261
+ if (msg?.type !== 'saying_msg') {
262
+ continue;
263
+ }
264
+ const trimmed = msg.content.trim();
265
+ if (trimmed !== '') {
266
+ return trimmed;
267
+ }
268
+ }
269
+ return null;
270
+ }
271
+ buildReplyToolReminderAutoResponse(input, role, context) {
272
+ if (role !== 'user' ||
273
+ !REPLY_TOOL_REMINDER_PREFIXES.some((prefix) => input.startsWith(prefix))) {
274
+ return null;
275
+ }
276
+ const toolMatch = input.match(/`(replyTellask(?:Sessionless|Back)?)`/);
277
+ if (!toolMatch) {
278
+ return null;
279
+ }
280
+ const replyContent = this.extractLastAssistantSaying(context);
281
+ if (!replyContent) {
282
+ return null;
283
+ }
284
+ return {
285
+ message: input,
286
+ role,
287
+ response: '',
288
+ funcCalls: [
289
+ {
290
+ name: toolMatch[1],
291
+ arguments: { replyContent },
292
+ },
293
+ ],
294
+ };
295
+ }
254
296
  /**
255
297
  * Find matching response using EXACT last message only.
256
298
  * NO fallback to message-only matching - if exact match fails, return null.
@@ -300,7 +342,8 @@ responses:
300
342
  throw new Error('AbortError');
301
343
  }
302
344
  const db = await this.loadResponseDatabase(dbPath, modelName);
303
- const matched = this.findMatchingResponse(db, content, role, context);
345
+ const matched = this.findMatchingResponse(db, content, role, context) ??
346
+ this.buildReplyToolReminderAutoResponse(content, role, context);
304
347
  await delayWithAbort(matched?.delayMs ?? 0, abortSignal);
305
348
  await receiver.thinkingStart();
306
349
  await receiver.thinkingChunk(`[${modelName}] `);
@@ -358,19 +401,21 @@ responses:
358
401
  totalTokens: promptTokens + completionTokens,
359
402
  };
360
403
  }
361
- await receiver.sayingStart();
362
- const chunkDelayMs = normalizeDelayMs(matched?.chunkDelayMs ?? 0);
363
- const words = responseText.split(/(\s+)/);
364
- for (const word of words) {
365
- if (abortSignal?.aborted) {
366
- throw new Error('AbortError');
367
- }
368
- await receiver.sayingChunk(word);
369
- if (chunkDelayMs > 0) {
370
- await delayWithAbort(chunkDelayMs, abortSignal);
404
+ if (responseText !== '') {
405
+ await receiver.sayingStart();
406
+ const chunkDelayMs = normalizeDelayMs(matched?.chunkDelayMs ?? 0);
407
+ const words = responseText.split(/(\s+)/);
408
+ for (const word of words) {
409
+ if (abortSignal?.aborted) {
410
+ throw new Error('AbortError');
411
+ }
412
+ await receiver.sayingChunk(word);
413
+ if (chunkDelayMs > 0) {
414
+ await delayWithAbort(chunkDelayMs, abortSignal);
415
+ }
371
416
  }
417
+ await receiver.sayingFinish();
372
418
  }
373
- await receiver.sayingFinish();
374
419
  const funcCalls = matched?.funcCalls ?? [];
375
420
  for (let i = 0; i < funcCalls.length; i++) {
376
421
  const call = funcCalls[i];
@@ -396,7 +441,8 @@ responses:
396
441
  const { content, role } = this.resolveInputForMatching(context);
397
442
  try {
398
443
  const db = await this.loadResponseDatabase(dbPath, modelName);
399
- const matched = this.findMatchingResponse(db, content, role, context);
444
+ const matched = this.findMatchingResponse(db, content, role, context) ??
445
+ this.buildReplyToolReminderAutoResponse(content, role, context);
400
446
  await delayWithAbort(matched?.delayMs ?? 0, abortSignal);
401
447
  const responseText = matched?.response ?? this.makeFallbackResponse(dbPath, content, role, modelName);
402
448
  const thinking = {
@@ -405,12 +451,16 @@ responses:
405
451
  genseq,
406
452
  content: `[${modelName}] ${content.substring(0, 100)}`,
407
453
  };
408
- const saying = {
409
- type: 'saying_msg',
410
- role: 'assistant',
411
- genseq,
412
- content: matched?.streamError ? `❌ Mock Error: ${matched.streamError}` : responseText,
413
- };
454
+ const saying = matched?.streamError || responseText !== ''
455
+ ? {
456
+ type: 'saying_msg',
457
+ role: 'assistant',
458
+ genseq,
459
+ content: matched?.streamError
460
+ ? `❌ Mock Error: ${matched.streamError}`
461
+ : responseText,
462
+ }
463
+ : undefined;
414
464
  let usage = { kind: 'unavailable' };
415
465
  if (matched && matched.usageUnavailable === true) {
416
466
  usage = { kind: 'unavailable' };
@@ -474,7 +524,11 @@ responses:
474
524
  arguments: this.normalizeFuncCallArgs(call.arguments),
475
525
  };
476
526
  }) ?? [];
477
- return { messages: [thinking, saying, ...funcMsgs], usage, llmGenModel: modelName };
527
+ return {
528
+ messages: saying ? [thinking, saying, ...funcMsgs] : [thinking, ...funcMsgs],
529
+ usage,
530
+ llmGenModel: modelName,
531
+ };
478
532
  }
479
533
  catch (err) {
480
534
  const errMsg = err instanceof Error ? err.message : String(err);