dominds 1.23.2 → 1.23.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/dist/dialog-display-state.js +112 -9
  2. package/dist/dialog.js +4 -0
  3. package/dist/docs/dialog-system.md +6 -2
  4. package/dist/docs/dialog-system.zh.md +5 -1
  5. package/dist/docs/diligence-push.md +27 -6
  6. package/dist/docs/diligence-push.zh.md +13 -6
  7. package/dist/docs/llm-provider-isolation.md +1 -1
  8. package/dist/docs/llm-provider-isolation.zh.md +1 -1
  9. package/dist/docs/tellask-revive-context-refactor.zh.md +13 -1
  10. package/dist/docs/volcengine-coding-plan-openai-compatible.zh.md +3 -2
  11. package/dist/llm/api-quirks.d.ts +1 -0
  12. package/dist/llm/api-quirks.js +35 -1
  13. package/dist/llm/defaults.yaml +6 -0
  14. package/dist/llm/gen/anthropic.js +6 -2
  15. package/dist/llm/gen/mock.js +44 -11
  16. package/dist/llm/gen/openai-compatible.d.ts +2 -1
  17. package/dist/llm/gen/openai-compatible.js +88 -20
  18. package/dist/llm/gen.d.ts +12 -0
  19. package/dist/llm/kernel-driver/context-health.d.ts +3 -4
  20. package/dist/llm/kernel-driver/context-health.js +5 -2
  21. package/dist/llm/kernel-driver/context.d.ts +4 -8
  22. package/dist/llm/kernel-driver/context.js +5 -25
  23. package/dist/llm/kernel-driver/drive.js +263 -59
  24. package/dist/llm/kernel-driver/engine.d.ts +1 -1
  25. package/dist/llm/kernel-driver/engine.js +5 -3
  26. package/dist/llm/kernel-driver/flow.js +162 -45
  27. package/dist/llm/kernel-driver/runtime.d.ts +12 -11
  28. package/dist/llm/kernel-driver/runtime.js +106 -18
  29. package/dist/llm/kernel-driver/sideDialog.d.ts +3 -0
  30. package/dist/llm/kernel-driver/sideDialog.js +4 -1
  31. package/dist/llm/kernel-driver/tellask-special.d.ts +1 -0
  32. package/dist/llm/kernel-driver/tellask-special.js +30 -30
  33. package/dist/llm/kernel-driver/types.d.ts +7 -3
  34. package/dist/log.js +35 -2
  35. package/dist/persistence.js +12 -1
  36. package/dist/recovery/reply-special.js +1 -1
  37. package/dist/runtime/driver-messages.d.ts +14 -1
  38. package/dist/runtime/driver-messages.js +116 -6
  39. package/dist/runtime/inter-dialog-format.d.ts +1 -0
  40. package/dist/runtime/inter-dialog-format.js +7 -3
  41. package/dist/server/websocket-handler.js +0 -1
  42. package/dist/tools/team_mgmt-manual.js +2 -2
  43. package/package.json +2 -2
  44. package/webapp/dist/assets/{_basePickBy-C3SVVywm.js → _basePickBy-DMD1UhXs.js} +3 -3
  45. package/webapp/dist/assets/{_basePickBy-C3SVVywm.js.map → _basePickBy-DMD1UhXs.js.map} +1 -1
  46. package/webapp/dist/assets/{_baseUniq-egNq6cCa.js → _baseUniq-CsE8Qvwt.js} +2 -2
  47. package/webapp/dist/assets/{_baseUniq-egNq6cCa.js.map → _baseUniq-CsE8Qvwt.js.map} +1 -1
  48. package/webapp/dist/assets/{arc-CASAlRvm.js → arc-0h8sV6e1.js} +2 -2
  49. package/webapp/dist/assets/{arc-CASAlRvm.js.map → arc-0h8sV6e1.js.map} +1 -1
  50. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-B6n5FQmS.js → architectureDiagram-2XIMDMQ5-BbMESECO.js} +7 -7
  51. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-B6n5FQmS.js.map → architectureDiagram-2XIMDMQ5-BbMESECO.js.map} +1 -1
  52. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-D2UGGjic.js → blockDiagram-WCTKOSBZ-DwkN-9a4.js} +7 -7
  53. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-D2UGGjic.js.map → blockDiagram-WCTKOSBZ-DwkN-9a4.js.map} +1 -1
  54. package/webapp/dist/assets/{c4Diagram-IC4MRINW-BOY_bQFP.js → c4Diagram-IC4MRINW-CGYONEh1.js} +3 -3
  55. package/webapp/dist/assets/{c4Diagram-IC4MRINW-BOY_bQFP.js.map → c4Diagram-IC4MRINW-CGYONEh1.js.map} +1 -1
  56. package/webapp/dist/assets/{channel-CZ_X09H1.js → channel-DbSJhm5-.js} +2 -2
  57. package/webapp/dist/assets/{channel-CZ_X09H1.js.map → channel-DbSJhm5-.js.map} +1 -1
  58. package/webapp/dist/assets/{chunk-4BX2VUAB-BIwyAzZQ.js → chunk-4BX2VUAB-D1inRfgf.js} +2 -2
  59. package/webapp/dist/assets/{chunk-4BX2VUAB-BIwyAzZQ.js.map → chunk-4BX2VUAB-D1inRfgf.js.map} +1 -1
  60. package/webapp/dist/assets/{chunk-55IACEB6-zSjTFoCX.js → chunk-55IACEB6-DL1IDg_h.js} +2 -2
  61. package/webapp/dist/assets/{chunk-55IACEB6-zSjTFoCX.js.map → chunk-55IACEB6-DL1IDg_h.js.map} +1 -1
  62. package/webapp/dist/assets/{chunk-FMBD7UC4-CTpuRfdB.js → chunk-FMBD7UC4-CugIlRDV.js} +2 -2
  63. package/webapp/dist/assets/{chunk-FMBD7UC4-CTpuRfdB.js.map → chunk-FMBD7UC4-CugIlRDV.js.map} +1 -1
  64. package/webapp/dist/assets/{chunk-JSJVCQXG-CJ3DM4in.js → chunk-JSJVCQXG-DKHSdeu1.js} +2 -2
  65. package/webapp/dist/assets/{chunk-JSJVCQXG-CJ3DM4in.js.map → chunk-JSJVCQXG-DKHSdeu1.js.map} +1 -1
  66. package/webapp/dist/assets/{chunk-KX2RTZJC-B97EakhO.js → chunk-KX2RTZJC-DCU9tkq6.js} +2 -2
  67. package/webapp/dist/assets/{chunk-KX2RTZJC-B97EakhO.js.map → chunk-KX2RTZJC-DCU9tkq6.js.map} +1 -1
  68. package/webapp/dist/assets/{chunk-NQ4KR5QH-5o1o5x0z.js → chunk-NQ4KR5QH-DN3O2s2M.js} +4 -4
  69. package/webapp/dist/assets/{chunk-NQ4KR5QH-5o1o5x0z.js.map → chunk-NQ4KR5QH-DN3O2s2M.js.map} +1 -1
  70. package/webapp/dist/assets/{chunk-QZHKN3VN-D33FSIEb.js → chunk-QZHKN3VN-e3ztIJg0.js} +2 -2
  71. package/webapp/dist/assets/{chunk-QZHKN3VN-D33FSIEb.js.map → chunk-QZHKN3VN-e3ztIJg0.js.map} +1 -1
  72. package/webapp/dist/assets/{chunk-WL4C6EOR-C2InqFin.js → chunk-WL4C6EOR-Dv907NPM.js} +6 -6
  73. package/webapp/dist/assets/{chunk-WL4C6EOR-C2InqFin.js.map → chunk-WL4C6EOR-Dv907NPM.js.map} +1 -1
  74. package/webapp/dist/assets/{classDiagram-VBA2DB6C-BfLZmK48.js → classDiagram-VBA2DB6C-DOTXtxYZ.js} +7 -7
  75. package/webapp/dist/assets/{classDiagram-VBA2DB6C-BfLZmK48.js.map → classDiagram-VBA2DB6C-DOTXtxYZ.js.map} +1 -1
  76. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BfLZmK48.js → classDiagram-v2-RAHNMMFH-DOTXtxYZ.js} +7 -7
  77. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BfLZmK48.js.map → classDiagram-v2-RAHNMMFH-DOTXtxYZ.js.map} +1 -1
  78. package/webapp/dist/assets/{clone-BSCHnHfl.js → clone-6lYQMWpu.js} +2 -2
  79. package/webapp/dist/assets/{clone-BSCHnHfl.js.map → clone-6lYQMWpu.js.map} +1 -1
  80. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CeQ1jAJJ.js → cose-bilkent-S5V4N54A-DoJeDXV0.js} +2 -2
  81. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CeQ1jAJJ.js.map → cose-bilkent-S5V4N54A-DoJeDXV0.js.map} +1 -1
  82. package/webapp/dist/assets/{dagre-KLK3FWXG-WUuNYzcK.js → dagre-KLK3FWXG-F_n_vhV9.js} +7 -7
  83. package/webapp/dist/assets/{dagre-KLK3FWXG-WUuNYzcK.js.map → dagre-KLK3FWXG-F_n_vhV9.js.map} +1 -1
  84. package/webapp/dist/assets/{diagram-E7M64L7V-jOVCIExP.js → diagram-E7M64L7V-Crwhgyjv.js} +8 -8
  85. package/webapp/dist/assets/{diagram-E7M64L7V-jOVCIExP.js.map → diagram-E7M64L7V-Crwhgyjv.js.map} +1 -1
  86. package/webapp/dist/assets/{diagram-IFDJBPK2-cCeQqotA.js → diagram-IFDJBPK2-CIt1nnn5.js} +7 -7
  87. package/webapp/dist/assets/{diagram-IFDJBPK2-cCeQqotA.js.map → diagram-IFDJBPK2-CIt1nnn5.js.map} +1 -1
  88. package/webapp/dist/assets/{diagram-P4PSJMXO-DjAYFRLv.js → diagram-P4PSJMXO-qowipEfV.js} +7 -7
  89. package/webapp/dist/assets/{diagram-P4PSJMXO-DjAYFRLv.js.map → diagram-P4PSJMXO-qowipEfV.js.map} +1 -1
  90. package/webapp/dist/assets/{erDiagram-INFDFZHY-Dl_6U5fV.js → erDiagram-INFDFZHY-DV2BcYNa.js} +5 -5
  91. package/webapp/dist/assets/{erDiagram-INFDFZHY-Dl_6U5fV.js.map → erDiagram-INFDFZHY-DV2BcYNa.js.map} +1 -1
  92. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-D80nrZ3S.js → flowDiagram-PKNHOUZH-CAbWV161.js} +7 -7
  93. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-D80nrZ3S.js.map → flowDiagram-PKNHOUZH-CAbWV161.js.map} +1 -1
  94. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-T3WdMrgj.js → ganttDiagram-A5KZAMGK-CfdR7FRr.js} +3 -3
  95. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-T3WdMrgj.js.map → ganttDiagram-A5KZAMGK-CfdR7FRr.js.map} +1 -1
  96. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-ifV-jkKL.js → gitGraphDiagram-K3NZZRJ6-DuJFTELz.js} +8 -8
  97. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-ifV-jkKL.js.map → gitGraphDiagram-K3NZZRJ6-DuJFTELz.js.map} +1 -1
  98. package/webapp/dist/assets/{graph-D5jmnb35.js → graph-cjRyzujT.js} +3 -3
  99. package/webapp/dist/assets/{graph-D5jmnb35.js.map → graph-cjRyzujT.js.map} +1 -1
  100. package/webapp/dist/assets/{index-CGbZlct2.js → index-DgfF56L4.js} +36 -36
  101. package/webapp/dist/assets/{index-CGbZlct2.js.map → index-DgfF56L4.js.map} +1 -1
  102. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-C340CY5x.js → infoDiagram-LFFYTUFH-3wx-7AdD.js} +6 -6
  103. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-C340CY5x.js.map → infoDiagram-LFFYTUFH-3wx-7AdD.js.map} +1 -1
  104. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-Bu4RsELK.js → ishikawaDiagram-PHBUUO56-g6CMb1Qc.js} +2 -2
  105. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-Bu4RsELK.js.map → ishikawaDiagram-PHBUUO56-g6CMb1Qc.js.map} +1 -1
  106. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-Dvv3ypKA.js → journeyDiagram-4ABVD52K-DdCcmOBO.js} +5 -5
  107. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-Dvv3ypKA.js.map → journeyDiagram-4ABVD52K-DdCcmOBO.js.map} +1 -1
  108. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-D_rsetjW.js → kanban-definition-K7BYSVSG-BFw2emGl.js} +3 -3
  109. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-D_rsetjW.js.map → kanban-definition-K7BYSVSG-BFw2emGl.js.map} +1 -1
  110. package/webapp/dist/assets/{layout-CLmOfwnS.js → layout-Clazq06r.js} +5 -5
  111. package/webapp/dist/assets/{layout-CLmOfwnS.js.map → layout-Clazq06r.js.map} +1 -1
  112. package/webapp/dist/assets/{linear-DFAmViqi.js → linear-jdsBGgvD.js} +2 -2
  113. package/webapp/dist/assets/{linear-DFAmViqi.js.map → linear-jdsBGgvD.js.map} +1 -1
  114. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-Ce3_czeS.js → mindmap-definition-YRQLILUH-DLSZrW6l.js} +4 -4
  115. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-Ce3_czeS.js.map → mindmap-definition-YRQLILUH-DLSZrW6l.js.map} +1 -1
  116. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-U6_un5Sc.js → pieDiagram-SKSYHLDU-Uj-Zpci6.js} +8 -8
  117. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-U6_un5Sc.js.map → pieDiagram-SKSYHLDU-Uj-Zpci6.js.map} +1 -1
  118. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DmVJQItS.js → quadrantDiagram-337W2JSQ-DO7Sl1nV.js} +3 -3
  119. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DmVJQItS.js.map → quadrantDiagram-337W2JSQ-DO7Sl1nV.js.map} +1 -1
  120. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-BkNhSY-g.js → requirementDiagram-Z7DCOOCP-WrurrDKQ.js} +4 -4
  121. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-BkNhSY-g.js.map → requirementDiagram-Z7DCOOCP-WrurrDKQ.js.map} +1 -1
  122. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-E3UEy5SX.js → sankeyDiagram-WA2Y5GQK-gcxbxuZB.js} +2 -2
  123. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-E3UEy5SX.js.map → sankeyDiagram-WA2Y5GQK-gcxbxuZB.js.map} +1 -1
  124. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-k0w9WKAO.js → sequenceDiagram-2WXFIKYE-B98U2Npa.js} +4 -4
  125. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-k0w9WKAO.js.map → sequenceDiagram-2WXFIKYE-B98U2Npa.js.map} +1 -1
  126. package/webapp/dist/assets/{stateDiagram-RAJIS63D-DRgdJrlx.js → stateDiagram-RAJIS63D-BUgfHMbd.js} +9 -9
  127. package/webapp/dist/assets/{stateDiagram-RAJIS63D-DRgdJrlx.js.map → stateDiagram-RAJIS63D-BUgfHMbd.js.map} +1 -1
  128. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-edtkX9x6.js → stateDiagram-v2-FVOUBMTO-C8gH0rSW.js} +5 -5
  129. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-edtkX9x6.js.map → stateDiagram-v2-FVOUBMTO-C8gH0rSW.js.map} +1 -1
  130. package/webapp/dist/assets/{timeline-definition-YZTLITO2-D0zyXyNL.js → timeline-definition-YZTLITO2-DnVikX3B.js} +3 -3
  131. package/webapp/dist/assets/{timeline-definition-YZTLITO2-D0zyXyNL.js.map → timeline-definition-YZTLITO2-DnVikX3B.js.map} +1 -1
  132. package/webapp/dist/assets/{treemap-KZPCXAKY-CglsYqbQ.js → treemap-KZPCXAKY-BjhjT1IM.js} +5 -5
  133. package/webapp/dist/assets/{treemap-KZPCXAKY-CglsYqbQ.js.map → treemap-KZPCXAKY-BjhjT1IM.js.map} +1 -1
  134. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DsUizzvt.js → vennDiagram-LZ73GAT5-CXjPMxrl.js} +2 -2
  135. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DsUizzvt.js.map → vennDiagram-LZ73GAT5-CXjPMxrl.js.map} +1 -1
  136. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-DvYQ4zKY.js → xychartDiagram-JWTSCODW-ByKmk3Cb.js} +3 -3
  137. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-DvYQ4zKY.js.map → xychartDiagram-JWTSCODW-ByKmk3Cb.js.map} +1 -1
  138. package/webapp/dist/index.html +1 -1
@@ -26,8 +26,46 @@ const tellask_special_1 = require("./tellask-special");
26
26
  function isReplyToolReminderPrompt(prompt) {
27
27
  return typeof prompt?.content === 'string' && (0, reply_prompt_copy_1.isReplyToolReminderPromptContent)(prompt.content);
28
28
  }
29
- function isIgnorablePostResponseAnchorTailEvent(type) {
30
- return type === 'tellask_reply_resolution_record' || type === 'gen_finish_record';
29
+ function hasQ4HAnswerCallId(callId) {
30
+ return typeof callId === 'string' && callId.trim() !== '';
31
+ }
32
+ function isEffectiveUserPromptForContextHealth(prompt) {
33
+ return prompt?.origin === 'user' && !hasQ4HAnswerCallId(prompt.q4hAnswerCallId);
34
+ }
35
+ function isQueuedUserPromptForContextHealth(prompt) {
36
+ return prompt?.kind === 'user_generation_boundary' && !hasQ4HAnswerCallId(prompt.q4hAnswerCallId);
37
+ }
38
+ function isNonIdleDisplayProjection(state) {
39
+ return state !== undefined && state.kind !== 'idle_waiting_user';
40
+ }
41
+ function resolveDirectFallbackResponse(args) {
42
+ if (args.driveResult.lastAssistantSayingContent !== null &&
43
+ args.driveResult.lastAssistantSayingContent.trim() !== '') {
44
+ if (typeof args.driveResult.lastAssistantSayingGenseq !== 'number' ||
45
+ !Number.isFinite(args.driveResult.lastAssistantSayingGenseq) ||
46
+ args.driveResult.lastAssistantSayingGenseq <= 0) {
47
+ throw new Error(`Direct reply fallback invariant violation: missing lastAssistantSayingGenseq for dialog=${args.dialog.id.valueOf()}`);
48
+ }
49
+ return {
50
+ responseText: args.driveResult.lastAssistantSayingContent,
51
+ responseGenseq: Math.floor(args.driveResult.lastAssistantSayingGenseq),
52
+ source: 'saying',
53
+ };
54
+ }
55
+ if (args.driveResult.lastAssistantThinkingContent !== null &&
56
+ args.driveResult.lastAssistantThinkingContent.trim() !== '') {
57
+ if (typeof args.driveResult.lastAssistantThinkingGenseq !== 'number' ||
58
+ !Number.isFinite(args.driveResult.lastAssistantThinkingGenseq) ||
59
+ args.driveResult.lastAssistantThinkingGenseq <= 0) {
60
+ throw new Error(`Direct reply fallback invariant violation: missing lastAssistantThinkingGenseq for dialog=${args.dialog.id.valueOf()}`);
61
+ }
62
+ return {
63
+ responseText: args.driveResult.lastAssistantThinkingContent,
64
+ responseGenseq: Math.floor(args.driveResult.lastAssistantThinkingGenseq),
65
+ source: 'thinking_only',
66
+ };
67
+ }
68
+ return undefined;
31
69
  }
32
70
  async function buildReplyToolReminderPrompt(args) {
33
71
  return (0, reply_prompt_copy_1.buildReplyToolReminderText)({
@@ -157,6 +195,36 @@ async function clearConsumedDeferredRootQueueIfIdle(dialog) {
157
195
  reason: 'root_idle_after_consuming_deferred_queue',
158
196
  });
159
197
  }
198
+ async function clearStaleSideDialogRunControlForFinalResponse(args) {
199
+ const latest = await persistence_1.DialogPersistence.loadDialogLatest(args.dialog.id, args.dialog.status);
200
+ if (!latest ||
201
+ (latest.needsDrive !== true &&
202
+ latest.generating !== true &&
203
+ latest.executionMarker?.kind !== 'interrupted' &&
204
+ !isNonIdleDisplayProjection(latest.displayState)) ||
205
+ latest.executionMarker?.kind === 'dead' ||
206
+ latest.pendingCourseStartPrompt) {
207
+ return {
208
+ cleared: false,
209
+ previousGenerating: latest?.generating ?? null,
210
+ previousNeedsDrive: latest?.needsDrive ?? null,
211
+ };
212
+ }
213
+ await persistence_1.DialogPersistence.mutateDialogLatest(args.dialog.id, () => ({
214
+ kind: 'patch',
215
+ patch: {
216
+ generating: false,
217
+ needsDrive: false,
218
+ displayState: { kind: 'idle_waiting_user' },
219
+ executionMarker: undefined,
220
+ },
221
+ }), args.dialog.status);
222
+ return {
223
+ cleared: true,
224
+ previousGenerating: latest.generating ?? null,
225
+ previousNeedsDrive: latest.needsDrive ?? null,
226
+ };
227
+ }
160
228
  function hasNoPromptSideDialogResumeEntitlement(dialog, driveOptions) {
161
229
  const entitlement = driveOptions?.noPromptSideDialogResumeEntitlement;
162
230
  if (!entitlement) {
@@ -259,20 +327,18 @@ async function inspectNoPromptSideDialogDrive(args) {
259
327
  const rawCourse = latest?.currentCourse ?? args.dialog.currentCourse;
260
328
  const currentCourse = Number.isFinite(rawCourse) && rawCourse > 0 ? Math.floor(rawCourse) : 1;
261
329
  const courseEvents = await persistence_1.DialogPersistence.loadCourseEvents(args.dialog.id, currentCourse, args.dialog.status);
262
- const rawLastEvent = (() => {
330
+ const rawLastTellaskAnchor = (() => {
263
331
  for (let index = courseEvents.length - 1; index >= 0; index -= 1) {
264
332
  const event = courseEvents[index];
265
- if (!isIgnorablePostResponseAnchorTailEvent(event.type)) {
333
+ if (event.type === 'tellask_anchor_record') {
266
334
  return event;
267
335
  }
268
336
  }
269
- return courseEvents[courseEvents.length - 1];
337
+ return undefined;
270
338
  })();
271
- const lastEvent = rawLastEvent?.type === 'tellask_anchor_record'
272
- ? { type: rawLastEvent.type, anchorRole: rawLastEvent.anchorRole }
273
- : rawLastEvent
274
- ? { type: rawLastEvent.type }
275
- : undefined;
339
+ const lastEvent = rawLastTellaskAnchor === undefined
340
+ ? undefined
341
+ : { type: rawLastTellaskAnchor.type, anchorRole: rawLastTellaskAnchor.anchorRole };
276
342
  const explicitInterruptedResumeAllowed = args.driveOptions?.allowResumeFromInterrupted === true &&
277
343
  latest?.executionMarker?.kind === 'interrupted';
278
344
  const inProgressGenerationResumeAllowed = args.driveOptions?.resumeInProgressGeneration === true;
@@ -370,6 +436,15 @@ async function maybeSurfaceDeferredReplyReassertionGuideForBlockedContinue(dialo
370
436
  // Do not "optimize" this into only an event or only a deferred prompt. The whole point is that
371
437
  // once blocked Continue is clicked, the guide becomes a first-class historical context fact and
372
438
  // later real driving should need no special duplicate reassertion path.
439
+ await surfaceRuntimeGuide(dialog, content);
440
+ await persistence_1.DialogPersistence.setDeferredReplyReassertion(dialog.id, {
441
+ reason: 'user_interjection_with_parked_original_task',
442
+ directive: deferredReplyReassertion.directive,
443
+ resumeGuideSurfaced: true,
444
+ }, dialog.status);
445
+ }
446
+ async function surfaceRuntimeGuide(dialog, content) {
447
+ const genseq = dialog.activeGenSeqOrUndefined ?? 1;
373
448
  await dialog.addChatMessages({
374
449
  type: 'transient_guide_msg',
375
450
  role: 'assistant',
@@ -382,11 +457,6 @@ async function maybeSurfaceDeferredReplyReassertionGuideForBlockedContinue(dialo
382
457
  genseq,
383
458
  content,
384
459
  });
385
- await persistence_1.DialogPersistence.setDeferredReplyReassertion(dialog.id, {
386
- reason: 'user_interjection_with_parked_original_task',
387
- directive: deferredReplyReassertion.directive,
388
- resumeGuideSurfaced: true,
389
- }, dialog.status);
390
460
  }
391
461
  async function resolveEffectivePrompt(dialog, humanPrompt) {
392
462
  if (humanPrompt) {
@@ -491,6 +561,29 @@ async function executeDriveRound(args) {
491
561
  latest.executionMarker.kind === 'dead') {
492
562
  return;
493
563
  }
564
+ if (dialog instanceof dialog_1.SideDialog && !dialog.hasUpNext()) {
565
+ const inspection = await inspectNoPromptSideDialogDrive({ dialog, driveOptions });
566
+ if (inspection.shouldReject && inspection.rejection === 'finalized_after_response_anchor') {
567
+ const cleanup = await clearStaleSideDialogRunControlForFinalResponse({ dialog });
568
+ log_1.log.warn('Dropped stale no-prompt sideDialog drive after final response anchor', undefined, {
569
+ dialogId: dialog.id.valueOf(),
570
+ rootId: dialog.id.rootId,
571
+ selfId: dialog.id.selfId,
572
+ source: inspection.source,
573
+ reason: driveOptions?.reason ?? null,
574
+ rejection: inspection.rejection,
575
+ allowResumeFromInterrupted: driveOptions?.allowResumeFromInterrupted === true,
576
+ displayState: inspection.displayState ?? null,
577
+ currentCourse: inspection.currentCourse,
578
+ lastEvent: inspection.lastEvent ?? null,
579
+ clearedStaleRunControl: cleanup.cleared,
580
+ previousGenerating: cleanup.previousGenerating,
581
+ previousNeedsDrive: cleanup.previousNeedsDrive,
582
+ waitInQue,
583
+ });
584
+ return;
585
+ }
586
+ }
494
587
  const stopRequested = (0, dialog_display_state_1.getStopRequestedReason)(dialog.id);
495
588
  if (stopRequested !== undefined) {
496
589
  log_1.log.debug('kernel-driver skip drive while stop request is still being processed', undefined, {
@@ -646,7 +739,8 @@ async function executeDriveRound(args) {
646
739
  throw new Error(`kernel-driver policy invariant violation: ${policyResult.detail}`);
647
740
  }
648
741
  const snapshot = dialog.getLastContextHealth();
649
- const hasQueuedUpNext = dialog.hasUpNext();
742
+ const queuedUpNextBeforeHealth = dialog.peekUpNext();
743
+ const hasQueuedUpNext = queuedUpNextBeforeHealth !== undefined;
650
744
  const provider = policy.effectiveAgent.provider ?? minds.team.memberDefaults.provider;
651
745
  const model = policy.effectiveAgent.model ?? minds.team.memberDefaults.model;
652
746
  let cautionRemediationCadenceGenerations = (0, context_health_1.resolveCautionRemediationCadenceGenerations)(undefined);
@@ -659,15 +753,15 @@ async function executeDriveRound(args) {
659
753
  const healthDecision = (0, context_health_1.decideKernelDriverContextHealth)({
660
754
  dialogKey: dialog.id.key(),
661
755
  snapshot,
662
- hadUserPromptThisGen: humanPrompt !== undefined,
756
+ hadUserPromptThisGen: isEffectiveUserPromptForContextHealth(humanPrompt) ||
757
+ (humanPrompt === undefined && isQueuedUserPromptForContextHealth(queuedUpNextBeforeHealth)),
758
+ userPromptCriticalRemediationAlreadyApplied: false,
663
759
  canInjectPromptThisGen: !hasQueuedUpNext,
664
760
  cautionRemediationCadenceGenerations,
665
761
  criticalCountdownRemaining,
666
762
  });
667
- if (healthDecision.kind === 'suspend') {
668
- return;
669
- }
670
763
  let healthPrompt;
764
+ let criticalUserInterjectionRuntimeGuide;
671
765
  if (healthDecision.kind === 'continue') {
672
766
  if (healthDecision.reason === 'critical_force_new_course') {
673
767
  const language = (0, work_language_1.getWorkLanguage)();
@@ -679,6 +773,15 @@ async function executeDriveRound(args) {
679
773
  dialog.setLastContextHealth({ kind: 'unavailable', reason: 'usage_unavailable' });
680
774
  (0, context_health_1.resetContextHealthRoundState)(dialog.id.key());
681
775
  }
776
+ else if (healthDecision.reason === 'critical_user_prompt_remediation') {
777
+ const language = (0, work_language_1.getWorkLanguage)();
778
+ const dialogScope = dialog instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
779
+ criticalUserInterjectionRuntimeGuide =
780
+ (0, driver_messages_1.formatAgentFacingCriticalUserInterjectionRemediationGuide)(language, {
781
+ dialogScope,
782
+ promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dialog.id.key()),
783
+ });
784
+ }
682
785
  else if (!hasQueuedUpNext) {
683
786
  const language = (0, work_language_1.getWorkLanguage)();
684
787
  const dialogScope = dialog instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
@@ -748,10 +851,19 @@ async function executeDriveRound(args) {
748
851
  if (effectivePrompt && effectivePrompt.userLanguageCode) {
749
852
  dialog.setLastUserLanguageCode(effectivePrompt.userLanguageCode);
750
853
  }
854
+ const coreDriveOptions = criticalUserInterjectionRuntimeGuide === undefined
855
+ ? driveOptions
856
+ : {
857
+ ...(driveOptions ?? {
858
+ source: driveSource,
859
+ reason: 'critical_user_prompt_remediation',
860
+ }),
861
+ criticalUserInterjectionRuntimeGuide,
862
+ };
751
863
  driveResult = await (0, drive_1.driveDialogStreamCore)(dialog, {
752
864
  scheduleDrive: args.scheduleDrive,
753
865
  driveDialog: args.driveDialog,
754
- }, effectivePrompt, driveOptions);
866
+ }, effectivePrompt, coreDriveOptions);
755
867
  sideDialogReplyTarget = driveResult.lastAssistantReplyTarget ?? sideDialogReplyTarget;
756
868
  interruptedBySignal = (0, dialog_display_state_1.getActiveRunSignal)(dialog.id)?.aborted === true;
757
869
  if (!interruptedBySignal) {
@@ -762,7 +874,8 @@ async function executeDriveRound(args) {
762
874
  if (dialog instanceof dialog_1.SideDialog &&
763
875
  driveResult &&
764
876
  !interruptedBySignal &&
765
- (driveResult.fbrConclusion !== undefined || driveResult.lastAssistantSayingContent !== null)) {
877
+ (driveResult.fbrConclusion !== undefined ||
878
+ resolveDirectFallbackResponse({ driveResult, dialog }) !== undefined)) {
766
879
  if (driveResult.fbrConclusion) {
767
880
  await (0, sideDialog_1.supplySideDialogResponseToAssignedAskerIfPendingV2)({
768
881
  sideDialog: dialog,
@@ -771,20 +884,23 @@ async function executeDriveRound(args) {
771
884
  scheduleDrive: args.scheduleDrive,
772
885
  });
773
886
  }
774
- else if (driveResult.lastAssistantSayingContent !== null) {
887
+ else {
888
+ const directFallbackResponse = resolveDirectFallbackResponse({ driveResult, dialog });
889
+ if (directFallbackResponse === undefined) {
890
+ throw new Error(`SideDialog response supply invariant violation: missing direct fallback response for dialog=${dialog.id.valueOf()}`);
891
+ }
775
892
  const hasInProgressFunctionCall = typeof driveResult.lastFunctionCallGenseq === 'number' &&
776
893
  Number.isFinite(driveResult.lastFunctionCallGenseq) &&
777
894
  driveResult.lastFunctionCallGenseq > 0 &&
778
- (typeof driveResult.lastAssistantSayingGenseq !== 'number' ||
779
- !Number.isFinite(driveResult.lastAssistantSayingGenseq) ||
780
- driveResult.lastAssistantSayingGenseq <= driveResult.lastFunctionCallGenseq);
895
+ directFallbackResponse.responseGenseq <= driveResult.lastFunctionCallGenseq;
781
896
  if (hasInProgressFunctionCall) {
782
897
  // Any function call means execution is still in-progress. Only supply when the tellaskee
783
898
  // has produced a newer assistant saying after the latest function call.
784
- log_1.log.debug('kernel-driver skip sideDialog response supply because latest saying is not after function calls', undefined, {
899
+ log_1.log.debug('kernel-driver skip sideDialog response supply because latest assistant output is not after function calls', undefined, {
785
900
  rootId: dialog.id.rootId,
786
901
  selfId: dialog.id.selfId,
787
- lastAssistantSayingGenseq: driveResult.lastAssistantSayingGenseq,
902
+ responseGenseq: directFallbackResponse.responseGenseq,
903
+ responseSource: directFallbackResponse.source,
788
904
  lastFunctionCallGenseq: driveResult.lastFunctionCallGenseq,
789
905
  });
790
906
  }
@@ -846,21 +962,16 @@ async function executeDriveRound(args) {
846
962
  });
847
963
  }
848
964
  else {
849
- if (typeof driveResult.lastAssistantSayingGenseq !== 'number' ||
850
- !Number.isFinite(driveResult.lastAssistantSayingGenseq) ||
851
- driveResult.lastAssistantSayingGenseq <= 0) {
852
- throw new Error(`SideDialog response supply invariant violation: missing lastAssistantSayingGenseq for dialog=${dialog.id.valueOf()}`);
853
- }
854
- const responseGenseq = Math.floor(driveResult.lastAssistantSayingGenseq);
855
965
  const directFallbackCallId = `direct-fallback-${(0, id_1.generateShortId)()}`;
856
966
  let supplied = false;
857
967
  if (sideDialogReplyTarget) {
858
968
  supplied = await (0, sideDialog_1.supplySideDialogResponseToSpecificAskerIfPendingV2)({
859
969
  sideDialog: dialog,
860
- responseText: driveResult.lastAssistantSayingContent,
861
- responseGenseq,
970
+ responseText: directFallbackResponse.responseText,
971
+ responseGenseq: directFallbackResponse.responseGenseq,
862
972
  target: sideDialogReplyTarget,
863
973
  deliveryMode: 'direct_fallback',
974
+ directFallbackSource: directFallbackResponse.source,
864
975
  replyResolution: {
865
976
  callId: directFallbackCallId,
866
977
  replyCallName: activeTellaskReplyDirective.expectedReplyCallName,
@@ -870,9 +981,10 @@ async function executeDriveRound(args) {
870
981
  if (!supplied) {
871
982
  supplied = await (0, sideDialog_1.supplySideDialogResponseToAssignedAskerIfPendingV2)({
872
983
  sideDialog: dialog,
873
- responseText: driveResult.lastAssistantSayingContent,
874
- responseGenseq,
984
+ responseText: directFallbackResponse.responseText,
985
+ responseGenseq: directFallbackResponse.responseGenseq,
875
986
  deliveryMode: 'direct_fallback',
987
+ directFallbackSource: directFallbackResponse.source,
876
988
  replyResolution: {
877
989
  callId: directFallbackCallId,
878
990
  replyCallName: activeTellaskReplyDirective.expectedReplyCallName,
@@ -884,9 +996,10 @@ async function executeDriveRound(args) {
884
996
  else {
885
997
  supplied = await (0, sideDialog_1.supplySideDialogResponseToAssignedAskerIfPendingV2)({
886
998
  sideDialog: dialog,
887
- responseText: driveResult.lastAssistantSayingContent,
888
- responseGenseq,
999
+ responseText: directFallbackResponse.responseText,
1000
+ responseGenseq: directFallbackResponse.responseGenseq,
889
1001
  deliveryMode: 'direct_fallback',
1002
+ directFallbackSource: directFallbackResponse.source,
890
1003
  replyResolution: {
891
1004
  callId: directFallbackCallId,
892
1005
  replyCallName: activeTellaskReplyDirective.expectedReplyCallName,
@@ -918,15 +1031,17 @@ async function executeDriveRound(args) {
918
1031
  if (!(dialog instanceof dialog_1.SideDialog) &&
919
1032
  driveResult &&
920
1033
  !interruptedBySignal &&
921
- driveResult.lastAssistantSayingContent !== null &&
1034
+ resolveDirectFallbackResponse({ driveResult, dialog }) !== undefined &&
922
1035
  activeTellaskReplyDirective?.expectedReplyCallName === 'replyTellaskBack' &&
923
1036
  followUp === undefined) {
1037
+ const directFallbackResponse = resolveDirectFallbackResponse({ driveResult, dialog });
1038
+ if (directFallbackResponse === undefined) {
1039
+ throw new Error(`replyTellaskBack fallback invariant violation: missing direct fallback response for dialog=${dialog.id.valueOf()}`);
1040
+ }
924
1041
  const hasInProgressFunctionCall = typeof driveResult.lastFunctionCallGenseq === 'number' &&
925
1042
  Number.isFinite(driveResult.lastFunctionCallGenseq) &&
926
1043
  driveResult.lastFunctionCallGenseq > 0 &&
927
- (typeof driveResult.lastAssistantSayingGenseq !== 'number' ||
928
- !Number.isFinite(driveResult.lastAssistantSayingGenseq) ||
929
- driveResult.lastAssistantSayingGenseq <= driveResult.lastFunctionCallGenseq);
1044
+ directFallbackResponse.responseGenseq <= driveResult.lastFunctionCallGenseq;
930
1045
  if (!hasInProgressFunctionCall) {
931
1046
  if (!activePromptWasReplyToolReminder) {
932
1047
  const language = (0, work_language_1.getWorkLanguage)();
@@ -952,12 +1067,13 @@ async function executeDriveRound(args) {
952
1067
  await (0, tellask_special_1.deliverTellaskBackReplyFromDirective)({
953
1068
  replyingDialog: dialog,
954
1069
  directive: activeTellaskReplyDirective,
955
- replyContent: driveResult.lastAssistantSayingContent,
1070
+ replyContent: directFallbackResponse.responseText,
956
1071
  callbacks: {
957
1072
  scheduleDrive: args.scheduleDrive,
958
1073
  driveDialog: args.driveDialog,
959
1074
  },
960
1075
  deliveryMode: 'direct_fallback',
1076
+ directFallbackSource: directFallbackResponse.source,
961
1077
  });
962
1078
  await dialog.appendTellaskReplyResolution({
963
1079
  callId: `direct-fallback-${(0, id_1.generateShortId)()}`,
@@ -1074,6 +1190,7 @@ async function executeDriveRound(args) {
1074
1190
  if (tailError !== undefined) {
1075
1191
  throw tailError;
1076
1192
  }
1193
+ return driveResult;
1077
1194
  }
1078
1195
  finally {
1079
1196
  if (activeRunPrimed && ownsActiveRun) {
@@ -4,7 +4,7 @@ import type { FuncTool, ToolArguments } from '../../tool';
4
4
  import { type LlmFailureQuirkHandlerSession } from '../api-quirks';
5
5
  import type { ProviderConfig } from '../client';
6
6
  import { type LlmFailureClassifier } from '../gen';
7
- import type { KernelDriverDiligencePrompt } from './types';
7
+ import type { KernelDriverPrompt } from './types';
8
8
  export declare class LlmRetryStoppedError extends Error {
9
9
  readonly reason: DialogLlmRetryExhaustedReason;
10
10
  constructor(reason: DialogLlmRetryExhaustedReason, message: string);
@@ -20,14 +20,7 @@ export declare class LlmRequestFailedError extends Error {
20
20
  i18nStopReason?: DialogDisplayTextI18n;
21
21
  });
22
22
  }
23
- export declare function maybePrepareDiligenceAutoContinuePrompt(options: {
24
- dlg: Dialog;
25
- isMainDialog: boolean;
26
- remainingBudget: number;
27
- diligencePushMax: number;
28
- suppressDiligencePush?: boolean;
29
- ignoreBudgetExhaustion?: boolean;
30
- }): Promise<{
23
+ type DiligencePromptPreparation = {
31
24
  kind: 'disabled';
32
25
  nextRemainingBudget: number;
33
26
  } | {
@@ -36,10 +29,17 @@ export declare function maybePrepareDiligenceAutoContinuePrompt(options: {
36
29
  nextRemainingBudget: number;
37
30
  } | {
38
31
  kind: 'prompt';
39
- prompt: KernelDriverDiligencePrompt;
32
+ prompt: KernelDriverPrompt;
40
33
  maxInjectCount: number;
41
34
  nextRemainingBudget: number;
42
- }>;
35
+ };
36
+ export declare function maybePrepareDiligenceAutoContinuePrompt(options: {
37
+ dlg: Dialog;
38
+ remainingBudget: number;
39
+ diligencePushMax: number;
40
+ suppressDiligencePush?: boolean;
41
+ ignoreBudgetExhaustion?: boolean;
42
+ }): Promise<DiligencePromptPreparation>;
43
43
  export declare function suspendForKeepGoingBudgetExhausted(options: {
44
44
  dlg: Dialog;
45
45
  maxInjectCount: number;
@@ -70,3 +70,4 @@ export declare function runLlmRequestWithRetry<T>(params: {
70
70
  onRetryStopped?: (reason: DialogLlmRetryExhaustedReason) => Promise<'continue' | 'stop'> | 'continue' | 'stop';
71
71
  doRequest: () => Promise<T>;
72
72
  }): Promise<T>;
73
+ export {};
@@ -43,8 +43,10 @@ const path = __importStar(require("path"));
43
43
  const diligence_1 = require("@longrun-ai/kernel/diligence");
44
44
  const id_1 = require("@longrun-ai/kernel/utils/id");
45
45
  const time_1 = require("@longrun-ai/kernel/utils/time");
46
+ const dialog_1 = require("../../dialog");
46
47
  const evt_registry_1 = require("../../evt-registry");
47
48
  const log_1 = require("../../log");
49
+ const persistence_1 = require("../../persistence");
48
50
  const problems_1 = require("../../problems");
49
51
  const driver_messages_1 = require("../../runtime/driver-messages");
50
52
  const work_language_1 = require("../../runtime/work-language");
@@ -121,29 +123,119 @@ async function resolveRtwsDiligenceConfig() {
121
123
  diligenceText: diligence_1.DILIGENCE_FALLBACK_TEXT[workLanguage],
122
124
  };
123
125
  }
126
+ function normalizeDiligenceRemainingBudget(remainingBudget) {
127
+ return typeof remainingBudget === 'number' && Number.isFinite(remainingBudget)
128
+ ? Math.max(0, Math.floor(remainingBudget))
129
+ : 0;
130
+ }
131
+ async function maybePrepareSideDialogDiligenceRecoveryPrompt(options) {
132
+ if (options.ignoreBudgetExhaustion !== true) {
133
+ return { kind: 'disabled', nextRemainingBudget: 0 };
134
+ }
135
+ if (options.dlg.disableDiligencePush || options.suppressDiligencePush === true) {
136
+ return {
137
+ kind: 'disabled',
138
+ nextRemainingBudget: normalizeDiligenceRemainingBudget(options.remainingBudget),
139
+ };
140
+ }
141
+ const assignment = options.dlg.assignmentFromAsker;
142
+ const activeReplyDirective = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(options.dlg.id, options.dlg.status);
143
+ if (!activeReplyDirective) {
144
+ return { kind: 'disabled', nextRemainingBudget: 0 };
145
+ }
146
+ const activeTargetCallId = activeReplyDirective.targetCallId.trim();
147
+ const activeTargetDialogId = activeReplyDirective.targetDialogId.trim();
148
+ const assignmentCallId = assignment.callId.trim();
149
+ const assignmentAskerDialogId = assignment.askerDialogId.trim();
150
+ if (activeTargetCallId === '' ||
151
+ activeTargetDialogId === '' ||
152
+ assignmentCallId === '' ||
153
+ assignmentAskerDialogId === '') {
154
+ throw new Error(`sideDialog diligence recovery invariant violation: empty reply/assignment correlation field for ${options.dlg.id.valueOf()}`);
155
+ }
156
+ const activeMatchesAssignment = activeTargetDialogId === assignmentAskerDialogId &&
157
+ activeTargetCallId === assignmentCallId &&
158
+ activeReplyDirective.tellaskContent === assignment.tellaskContent;
159
+ const activeReplyToolMatchesAssignment = (activeReplyDirective.expectedReplyCallName === 'replyTellask' &&
160
+ assignment.callName === 'tellask') ||
161
+ (activeReplyDirective.expectedReplyCallName === 'replyTellaskSessionless' &&
162
+ (assignment.callName === 'tellaskSessionless' ||
163
+ assignment.callName === 'freshBootsReasoning'));
164
+ if (activeReplyDirective.expectedReplyCallName !== 'replyTellaskBack' &&
165
+ (!activeMatchesAssignment || !activeReplyToolMatchesAssignment)) {
166
+ throw new Error(`sideDialog diligence recovery invariant violation: active reply obligation does not match current assignment for ${options.dlg.id.valueOf()}`);
167
+ }
168
+ const variant = (Math.floor(Math.random() * 3) % 3);
169
+ const commonPrompt = {
170
+ content: (0, driver_messages_1.formatSideDialogDiligenceAutoContinuePrompt)((0, work_language_1.getWorkLanguage)(), {
171
+ now: new Date(),
172
+ tellaskContent: activeReplyDirective.tellaskContent,
173
+ replyToolName: activeReplyDirective.expectedReplyCallName,
174
+ variant,
175
+ }),
176
+ msgId: (0, id_1.generateShortId)(),
177
+ grammar: 'markdown',
178
+ origin: 'runtime',
179
+ tellaskReplyDirective: activeReplyDirective,
180
+ };
181
+ if (activeReplyDirective.expectedReplyCallName === 'replyTellaskBack') {
182
+ const prompt = commonPrompt;
183
+ return {
184
+ kind: 'prompt',
185
+ prompt,
186
+ maxInjectCount: 0,
187
+ nextRemainingBudget: 0,
188
+ };
189
+ }
190
+ const prompt = {
191
+ ...commonPrompt,
192
+ sideDialogReplyTarget: {
193
+ ownerDialogId: assignment.askerDialogId,
194
+ callType: assignment.callName === 'tellask' ? 'B' : 'C',
195
+ callId: assignment.callId,
196
+ callSiteCourse: assignment.callSiteCourse,
197
+ callSiteGenseq: assignment.callSiteGenseq,
198
+ },
199
+ };
200
+ return {
201
+ kind: 'prompt',
202
+ prompt,
203
+ maxInjectCount: 0,
204
+ nextRemainingBudget: 0,
205
+ };
206
+ }
124
207
  async function maybePrepareDiligenceAutoContinuePrompt(options) {
125
- if (!options.isMainDialog) {
126
- return { kind: 'disabled', nextRemainingBudget: options.remainingBudget };
208
+ if (!(options.dlg instanceof dialog_1.MainDialog)) {
209
+ if (!(options.dlg instanceof dialog_1.SideDialog)) {
210
+ return {
211
+ kind: 'disabled',
212
+ nextRemainingBudget: normalizeDiligenceRemainingBudget(options.remainingBudget),
213
+ };
214
+ }
215
+ return await maybePrepareSideDialogDiligenceRecoveryPrompt({
216
+ dlg: options.dlg,
217
+ remainingBudget: options.remainingBudget,
218
+ suppressDiligencePush: options.suppressDiligencePush,
219
+ ignoreBudgetExhaustion: options.ignoreBudgetExhaustion,
220
+ });
127
221
  }
128
222
  if (options.dlg.disableDiligencePush || options.suppressDiligencePush === true) {
129
- const normalizedRemaining = typeof options.remainingBudget === 'number' && Number.isFinite(options.remainingBudget)
130
- ? Math.max(0, Math.floor(options.remainingBudget))
131
- : 0;
132
- return { kind: 'disabled', nextRemainingBudget: normalizedRemaining };
223
+ return {
224
+ kind: 'disabled',
225
+ nextRemainingBudget: normalizeDiligenceRemainingBudget(options.remainingBudget),
226
+ };
133
227
  }
134
228
  const resolved = await resolveRtwsDiligenceConfig();
135
229
  if (resolved.kind === 'disabled') {
136
- const normalizedRemaining = typeof options.remainingBudget === 'number' && Number.isFinite(options.remainingBudget)
137
- ? Math.max(0, Math.floor(options.remainingBudget))
138
- : 0;
139
- return { kind: 'disabled', nextRemainingBudget: normalizedRemaining };
230
+ return {
231
+ kind: 'disabled',
232
+ nextRemainingBudget: normalizeDiligenceRemainingBudget(options.remainingBudget),
233
+ };
140
234
  }
141
235
  const maxInjectCount = typeof options.diligencePushMax === 'number' && Number.isFinite(options.diligencePushMax)
142
236
  ? Math.floor(options.diligencePushMax)
143
237
  : 0;
144
- const normalizedRemaining = typeof options.remainingBudget === 'number' && Number.isFinite(options.remainingBudget)
145
- ? Math.max(0, Math.floor(options.remainingBudget))
146
- : 0;
238
+ const normalizedRemaining = normalizeDiligenceRemainingBudget(options.remainingBudget);
147
239
  const bypassBudget = options.ignoreBudgetExhaustion === true;
148
240
  // `diligencePushMax` is only the per-member default used when a dialog instance is created or
149
241
  // reset. Runtime business decisions must be based on this dialog's persisted remaining budget so
@@ -168,10 +260,6 @@ async function maybePrepareDiligenceAutoContinuePrompt(options) {
168
260
  nextRemainingBudget: 0,
169
261
  };
170
262
  }
171
- const currentRemaining = normalizedRemaining;
172
- if (currentRemaining < 1 && !bypassBudget) {
173
- return { kind: 'budget_exhausted', maxInjectCount, nextRemainingBudget: 0 };
174
- }
175
263
  const prompt = {
176
264
  content: (0, driver_messages_1.formatDiligenceAutoContinuePrompt)((0, work_language_1.getWorkLanguage)(), resolved.diligenceText),
177
265
  msgId: (0, id_1.generateShortId)(),
@@ -182,7 +270,7 @@ async function maybePrepareDiligenceAutoContinuePrompt(options) {
182
270
  kind: 'prompt',
183
271
  prompt,
184
272
  maxInjectCount,
185
- nextRemainingBudget: Math.max(0, currentRemaining - 1),
273
+ nextRemainingBudget: Math.max(0, normalizedRemaining - 1),
186
274
  };
187
275
  }
188
276
  async function suspendForKeepGoingBudgetExhausted(options) {
@@ -20,6 +20,7 @@ export declare function supplyResponseToAskerDialog(args: {
20
20
  callId?: string;
21
21
  status?: 'completed' | 'failed';
22
22
  deliveryMode?: 'reply_tool' | 'direct_fallback';
23
+ directFallbackSource?: 'saying' | 'thinking_only';
23
24
  replyResolution?: {
24
25
  callId: string;
25
26
  replyCallName: 'replyTellask' | 'replyTellaskSessionless' | 'replyTellaskBack';
@@ -38,6 +39,7 @@ export declare function supplySideDialogResponseToSpecificAskerIfPendingV2(args:
38
39
  responseGenseq: number;
39
40
  target: SideDialogReplyTarget;
40
41
  deliveryMode?: 'reply_tool' | 'direct_fallback';
42
+ directFallbackSource?: 'saying' | 'thinking_only';
41
43
  replyResolution?: {
42
44
  callId: string;
43
45
  replyCallName: 'replyTellask' | 'replyTellaskSessionless' | 'replyTellaskBack';
@@ -49,6 +51,7 @@ export declare function supplySideDialogResponseToAssignedAskerIfPendingV2(args:
49
51
  responseText: string;
50
52
  responseGenseq: number;
51
53
  deliveryMode?: 'reply_tool' | 'direct_fallback';
54
+ directFallbackSource?: 'saying' | 'thinking_only';
52
55
  replyResolution?: {
53
56
  callId: string;
54
57
  replyCallName: 'replyTellask' | 'replyTellaskSessionless' | 'replyTellaskBack';
@@ -149,7 +149,7 @@ async function resolveLatestAssignmentAnchorRef(args) {
149
149
  return undefined;
150
150
  }
151
151
  async function supplyResponseToAskerDialog(args) {
152
- const { parentDialog, sideDialogId, responseText, callType, callId, status = 'completed', deliveryMode = 'reply_tool', calleeResponseRef, askerCourseOverride, scheduleDrive, sideDialog: maybeSideDialog, } = args;
152
+ const { parentDialog, sideDialogId, responseText, callType, callId, status = 'completed', deliveryMode = 'reply_tool', directFallbackSource, calleeResponseRef, askerCourseOverride, scheduleDrive, sideDialog: maybeSideDialog, } = args;
153
153
  try {
154
154
  const result = await (0, sideDialog_txn_1.withSideDialogTxnLock)(parentDialog.id, async () => {
155
155
  const pendingSideDialogs = await persistence_1.DialogPersistence.loadPendingSideDialogs(parentDialog.id, parentDialog.status);
@@ -270,6 +270,7 @@ async function supplyResponseToAskerDialog(args) {
270
270
  responseBody: tellaskerResponseBody,
271
271
  status,
272
272
  deliveryMode,
273
+ directFallbackSource,
273
274
  language: (0, work_language_1.getWorkLanguage)(),
274
275
  });
275
276
  const carryoverCallSiteCourse = result.callSiteCourse;
@@ -594,6 +595,7 @@ async function supplySideDialogResponseToSpecificAskerIfPendingV2(args) {
594
595
  callId: target.callId,
595
596
  status: 'completed',
596
597
  deliveryMode: args.deliveryMode,
598
+ directFallbackSource: args.directFallbackSource,
597
599
  replyResolution: args.replyResolution,
598
600
  calleeResponseRef: { course: sideDialog.currentCourse, genseq: responseGenseq },
599
601
  scheduleDrive,
@@ -664,6 +666,7 @@ async function supplySideDialogResponseToAssignedAskerIfPendingV2(args) {
664
666
  callId: assignment.callId,
665
667
  status: 'completed',
666
668
  deliveryMode: args.deliveryMode,
669
+ directFallbackSource: args.directFallbackSource,
667
670
  replyResolution: args.replyResolution,
668
671
  calleeResponseRef: { course: sideDialog.currentCourse, genseq: responseGenseq },
669
672
  scheduleDrive,
@@ -78,6 +78,7 @@ export declare function deliverTellaskBackReplyFromDirective(args: {
78
78
  replyContent: string;
79
79
  callbacks: KernelDriverDriveCallbacks;
80
80
  deliveryMode?: 'reply_tool' | 'direct_fallback';
81
+ directFallbackSource?: 'saying' | 'thinking_only';
81
82
  }): Promise<TellaskBackReplyDeliveryResult>;
82
83
  export declare function recoverPendingReplyTellaskCalls(args: {
83
84
  dlg: Dialog;