dominds 1.25.7 → 1.25.8

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 (106) hide show
  1. package/dist/dialog-display-state.js +81 -30
  2. package/dist/dialog-fork.js +2 -10
  3. package/dist/dialog-interruption.js +2 -1
  4. package/dist/dialog.d.ts +4 -0
  5. package/dist/dialog.js +14 -0
  6. package/dist/llm/gen/mock.d.ts +1 -0
  7. package/dist/llm/gen/mock.js +12 -0
  8. package/dist/llm/kernel-driver/flow.js +58 -17
  9. package/dist/llm/kernel-driver/runtime.d.ts +1 -1
  10. package/dist/llm/kernel-driver/runtime.js +12 -0
  11. package/dist/llm/kernel-driver/tellask-special.js +4 -0
  12. package/dist/persistence.d.ts +1 -0
  13. package/dist/persistence.js +82 -26
  14. package/dist/server/websocket-handler.js +8 -3
  15. package/package.json +3 -3
  16. package/webapp/dist/assets/{_basePickBy-Y5Q2L95x.js → _basePickBy-CATeRp8S.js} +3 -3
  17. package/webapp/dist/assets/{_basePickBy-Y5Q2L95x.js.map → _basePickBy-CATeRp8S.js.map} +1 -1
  18. package/webapp/dist/assets/{_baseUniq-Cj3ro8Ri.js → _baseUniq-CFRLPgeM.js} +2 -2
  19. package/webapp/dist/assets/{_baseUniq-Cj3ro8Ri.js.map → _baseUniq-CFRLPgeM.js.map} +1 -1
  20. package/webapp/dist/assets/{arc-Bz9VfJlg.js → arc-CB9bI1EY.js} +2 -2
  21. package/webapp/dist/assets/{arc-Bz9VfJlg.js.map → arc-CB9bI1EY.js.map} +1 -1
  22. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-Ce6_zDEY.js → architectureDiagram-VXUJARFQ-CCpiy2xw.js} +7 -7
  23. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-Ce6_zDEY.js.map → architectureDiagram-VXUJARFQ-CCpiy2xw.js.map} +1 -1
  24. package/webapp/dist/assets/{blockDiagram-VD42YOAC-DIEKjBVU.js → blockDiagram-VD42YOAC-DgzrbcBd.js} +7 -7
  25. package/webapp/dist/assets/{blockDiagram-VD42YOAC-DIEKjBVU.js.map → blockDiagram-VD42YOAC-DgzrbcBd.js.map} +1 -1
  26. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-CQpAPdOt.js → c4Diagram-YG6GDRKO-C0LCDSs6.js} +3 -3
  27. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-CQpAPdOt.js.map → c4Diagram-YG6GDRKO-C0LCDSs6.js.map} +1 -1
  28. package/webapp/dist/assets/{channel-C_7bziVU.js → channel-sKpY2JZ5.js} +2 -2
  29. package/webapp/dist/assets/{channel-C_7bziVU.js.map → channel-sKpY2JZ5.js.map} +1 -1
  30. package/webapp/dist/assets/{chunk-4BX2VUAB-CI07YP8x.js → chunk-4BX2VUAB-D9_yL_TQ.js} +2 -2
  31. package/webapp/dist/assets/{chunk-4BX2VUAB-CI07YP8x.js.map → chunk-4BX2VUAB-D9_yL_TQ.js.map} +1 -1
  32. package/webapp/dist/assets/{chunk-55IACEB6-CH-ZnQdW.js → chunk-55IACEB6-CTuUncSx.js} +2 -2
  33. package/webapp/dist/assets/{chunk-55IACEB6-CH-ZnQdW.js.map → chunk-55IACEB6-CTuUncSx.js.map} +1 -1
  34. package/webapp/dist/assets/{chunk-B4BG7PRW-B8XZmRWD.js → chunk-B4BG7PRW-Ceelj1iX.js} +5 -5
  35. package/webapp/dist/assets/{chunk-B4BG7PRW-B8XZmRWD.js.map → chunk-B4BG7PRW-Ceelj1iX.js.map} +1 -1
  36. package/webapp/dist/assets/{chunk-DI55MBZ5-BTJEMG8W.js → chunk-DI55MBZ5-BoHV50iw.js} +4 -4
  37. package/webapp/dist/assets/{chunk-DI55MBZ5-BTJEMG8W.js.map → chunk-DI55MBZ5-BoHV50iw.js.map} +1 -1
  38. package/webapp/dist/assets/{chunk-FMBD7UC4-u7Ho3qNZ.js → chunk-FMBD7UC4-CyCMHG2I.js} +2 -2
  39. package/webapp/dist/assets/{chunk-FMBD7UC4-u7Ho3qNZ.js.map → chunk-FMBD7UC4-CyCMHG2I.js.map} +1 -1
  40. package/webapp/dist/assets/{chunk-QN33PNHL-C-7kvetv.js → chunk-QN33PNHL-DPr_6BJj.js} +2 -2
  41. package/webapp/dist/assets/{chunk-QN33PNHL-C-7kvetv.js.map → chunk-QN33PNHL-DPr_6BJj.js.map} +1 -1
  42. package/webapp/dist/assets/{chunk-QZHKN3VN-Cutz7csQ.js → chunk-QZHKN3VN-B87nIEZP.js} +2 -2
  43. package/webapp/dist/assets/{chunk-QZHKN3VN-Cutz7csQ.js.map → chunk-QZHKN3VN-B87nIEZP.js.map} +1 -1
  44. package/webapp/dist/assets/{chunk-TZMSLE5B-b_LZteUW.js → chunk-TZMSLE5B-CEOLgAwG.js} +2 -2
  45. package/webapp/dist/assets/{chunk-TZMSLE5B-b_LZteUW.js.map → chunk-TZMSLE5B-CEOLgAwG.js.map} +1 -1
  46. package/webapp/dist/assets/{classDiagram-2ON5EDUG-CCGe8-bu.js → classDiagram-2ON5EDUG-OU3Rb0MK.js} +6 -6
  47. package/webapp/dist/assets/{classDiagram-2ON5EDUG-CCGe8-bu.js.map → classDiagram-2ON5EDUG-OU3Rb0MK.js.map} +1 -1
  48. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-CCGe8-bu.js → classDiagram-v2-WZHVMYZB-OU3Rb0MK.js} +6 -6
  49. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-CCGe8-bu.js.map → classDiagram-v2-WZHVMYZB-OU3Rb0MK.js.map} +1 -1
  50. package/webapp/dist/assets/{clone-CEpSMVek.js → clone-DPJ1e01h.js} +2 -2
  51. package/webapp/dist/assets/{clone-CEpSMVek.js.map → clone-DPJ1e01h.js.map} +1 -1
  52. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-JEt2Ncxk.js → cose-bilkent-S5V4N54A-Eb4tTnqa.js} +2 -2
  53. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-JEt2Ncxk.js.map → cose-bilkent-S5V4N54A-Eb4tTnqa.js.map} +1 -1
  54. package/webapp/dist/assets/{dagre-6UL2VRFP-dy6U1rpE.js → dagre-6UL2VRFP--wouwNZD.js} +7 -7
  55. package/webapp/dist/assets/{dagre-6UL2VRFP-dy6U1rpE.js.map → dagre-6UL2VRFP--wouwNZD.js.map} +1 -1
  56. package/webapp/dist/assets/{diagram-PSM6KHXK-u1RaCst_.js → diagram-PSM6KHXK-Da_Qnble.js} +8 -8
  57. package/webapp/dist/assets/{diagram-PSM6KHXK-u1RaCst_.js.map → diagram-PSM6KHXK-Da_Qnble.js.map} +1 -1
  58. package/webapp/dist/assets/{diagram-QEK2KX5R-Bm297BXQ.js → diagram-QEK2KX5R-BhOtufwo.js} +7 -7
  59. package/webapp/dist/assets/{diagram-QEK2KX5R-Bm297BXQ.js.map → diagram-QEK2KX5R-BhOtufwo.js.map} +1 -1
  60. package/webapp/dist/assets/{diagram-S2PKOQOG-B9Z57WnU.js → diagram-S2PKOQOG-k-LiSr-7.js} +7 -7
  61. package/webapp/dist/assets/{diagram-S2PKOQOG-B9Z57WnU.js.map → diagram-S2PKOQOG-k-LiSr-7.js.map} +1 -1
  62. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-CyXAp9Ik.js → erDiagram-Q2GNP2WA-DSTHWIXm.js} +5 -5
  63. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-CyXAp9Ik.js.map → erDiagram-Q2GNP2WA-DSTHWIXm.js.map} +1 -1
  64. package/webapp/dist/assets/{flowDiagram-NV44I4VS-ONR9JQsN.js → flowDiagram-NV44I4VS-BjS-xbaY.js} +6 -6
  65. package/webapp/dist/assets/{flowDiagram-NV44I4VS-ONR9JQsN.js.map → flowDiagram-NV44I4VS-BjS-xbaY.js.map} +1 -1
  66. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Coi5jLKz.js → ganttDiagram-JELNMOA3-DAgcUpJe.js} +3 -3
  67. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Coi5jLKz.js.map → ganttDiagram-JELNMOA3-DAgcUpJe.js.map} +1 -1
  68. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-BoLPKg9P.js → gitGraphDiagram-V2S2FVAM-i1vEkfoe.js} +8 -8
  69. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-BoLPKg9P.js.map → gitGraphDiagram-V2S2FVAM-i1vEkfoe.js.map} +1 -1
  70. package/webapp/dist/assets/{graph-DLwD58eC.js → graph-CxNIZAUJ.js} +3 -3
  71. package/webapp/dist/assets/{graph-DLwD58eC.js.map → graph-CxNIZAUJ.js.map} +1 -1
  72. package/webapp/dist/assets/{index-HwgQoWbn.js → index-piqwT9B7.js} +69 -38
  73. package/webapp/dist/assets/{index-HwgQoWbn.js.map → index-piqwT9B7.js.map} +1 -1
  74. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-BpEpEjG2.js → infoDiagram-HS3SLOUP-BH-Wj-38.js} +6 -6
  75. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-BpEpEjG2.js.map → infoDiagram-HS3SLOUP-BH-Wj-38.js.map} +1 -1
  76. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-C2HNBnMQ.js → journeyDiagram-XKPGCS4Q-B5c5iW9X.js} +5 -5
  77. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-C2HNBnMQ.js.map → journeyDiagram-XKPGCS4Q-B5c5iW9X.js.map} +1 -1
  78. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-DcELha9W.js → kanban-definition-3W4ZIXB7-fgYwmV5l.js} +3 -3
  79. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-DcELha9W.js.map → kanban-definition-3W4ZIXB7-fgYwmV5l.js.map} +1 -1
  80. package/webapp/dist/assets/{layout-Cyg7MRlM.js → layout-Dc9UeLis.js} +5 -5
  81. package/webapp/dist/assets/{layout-Cyg7MRlM.js.map → layout-Dc9UeLis.js.map} +1 -1
  82. package/webapp/dist/assets/{linear-pOIWL8hY.js → linear-DFqZ7yVr.js} +2 -2
  83. package/webapp/dist/assets/{linear-pOIWL8hY.js.map → linear-DFqZ7yVr.js.map} +1 -1
  84. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-BTyvfLY3.js → mindmap-definition-VGOIOE7T-CWXQmWf-.js} +4 -4
  85. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-BTyvfLY3.js.map → mindmap-definition-VGOIOE7T-CWXQmWf-.js.map} +1 -1
  86. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-D1CwcmEb.js → pieDiagram-ADFJNKIX-Dmm4opIx.js} +8 -8
  87. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-D1CwcmEb.js.map → pieDiagram-ADFJNKIX-Dmm4opIx.js.map} +1 -1
  88. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-DdlItwqV.js → quadrantDiagram-AYHSOK5B-L48S6y-Y.js} +3 -3
  89. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-DdlItwqV.js.map → quadrantDiagram-AYHSOK5B-L48S6y-Y.js.map} +1 -1
  90. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-B6AntBtK.js → requirementDiagram-UZGBJVZJ-uQa6qCTU.js} +4 -4
  91. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-B6AntBtK.js.map → requirementDiagram-UZGBJVZJ-uQa6qCTU.js.map} +1 -1
  92. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-Cb1skLgE.js → sankeyDiagram-TZEHDZUN-4wM4sZjA.js} +2 -2
  93. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-Cb1skLgE.js.map → sankeyDiagram-TZEHDZUN-4wM4sZjA.js.map} +1 -1
  94. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-BXtnapRV.js → sequenceDiagram-WL72ISMW-EZlETI0Q.js} +4 -4
  95. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-BXtnapRV.js.map → sequenceDiagram-WL72ISMW-EZlETI0Q.js.map} +1 -1
  96. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-BEJSYJxc.js → stateDiagram-FKZM4ZOC-CeCT7b7S.js} +9 -9
  97. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-BEJSYJxc.js.map → stateDiagram-FKZM4ZOC-CeCT7b7S.js.map} +1 -1
  98. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-YlQ0hGcy.js → stateDiagram-v2-4FDKWEC3-3oDsYGFz.js} +5 -5
  99. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-YlQ0hGcy.js.map → stateDiagram-v2-4FDKWEC3-3oDsYGFz.js.map} +1 -1
  100. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-BHzyY6Ip.js → timeline-definition-IT6M3QCI-9k0ahO0m.js} +3 -3
  101. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-BHzyY6Ip.js.map → timeline-definition-IT6M3QCI-9k0ahO0m.js.map} +1 -1
  102. package/webapp/dist/assets/{treemap-GDKQZRPO-BMYh8Nea.js → treemap-GDKQZRPO--DQUhriC.js} +5 -5
  103. package/webapp/dist/assets/{treemap-GDKQZRPO-BMYh8Nea.js.map → treemap-GDKQZRPO--DQUhriC.js.map} +1 -1
  104. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-C5vczZ0B.js → xychartDiagram-PRI3JC2R-VhFrAQO2.js} +3 -3
  105. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-C5vczZ0B.js.map → xychartDiagram-PRI3JC2R-VhFrAQO2.js.map} +1 -1
  106. package/webapp/dist/index.html +1 -1
@@ -97,21 +97,28 @@ function isNonIdleDisplayProjection(state) {
97
97
  function hasPendingNextStepTriggers(latest) {
98
98
  return (latest?.nextStep.triggers.length ?? 0) > 0;
99
99
  }
100
- function q4hSuspensionDisplayState(hasQ4H) {
100
+ function waitingHumanInputDisplayState(hasQ4H) {
101
101
  if (hasQ4H) {
102
102
  return { kind: 'blocked', reason: { kind: 'needs_human_input' } };
103
103
  }
104
104
  return undefined;
105
105
  }
106
+ async function waitingSideDialogDisplayState(dialogId, status, activeReplyObligation) {
107
+ if (status !== 'running' || activeReplyObligation === undefined) {
108
+ return undefined;
109
+ }
110
+ const activeCallees = await persistence_1.DialogPersistence.loadActiveCallees(dialogId, status);
111
+ const hasPendingSideDialog = activeCallees.batches.some((batch) => batch.callees.some((callee) => callee.status === 'pending'));
112
+ if (!hasPendingSideDialog) {
113
+ return undefined;
114
+ }
115
+ return { kind: 'waiting_side_dialog' };
116
+ }
106
117
  function pendingReplyObligationDisplayState(activeReplyObligation) {
107
118
  if (activeReplyObligation === undefined) {
108
119
  return undefined;
109
120
  }
110
- return {
111
- kind: 'stopped',
112
- reason: { kind: 'pending_reply_obligation' },
113
- continueEnabled: true,
114
- };
121
+ return { kind: 'proceeding' };
115
122
  }
116
123
  async function resolveSideDialogFinalResponseClosure(args) {
117
124
  if (!args.latest) {
@@ -215,7 +222,7 @@ async function getRunControlCountsSnapshot() {
215
222
  else if (latest?.executionMarker?.kind === 'interrupted' &&
216
223
  isStoppedReasonResumable(latest.executionMarker.reason)) {
217
224
  // Keep run-control counts aligned with actual Continue affordance:
218
- // - ordinary interrupted dialogs count as resumable only when no Q4H suspension remains
225
+ // - ordinary interrupted dialogs count as resumable only when no Q4H human-input wait remains
219
226
  // - legacy interjection-paused dialogs still count as resumable even if Q4H remains,
220
227
  // because Continue only re-evaluates the original task from fresh facts
221
228
  if ((0, interjection_pause_stop_1.isUserInterjectionPauseStopReason)(latest.executionMarker.reason)) {
@@ -433,28 +440,57 @@ async function setDialogDisplayState(dialogId, displayState, status = 'running')
433
440
  return;
434
441
  }
435
442
  if (status === 'running' && displayState.kind === 'idle_waiting_user') {
436
- const finalResponseClosure = await resolveSideDialogFinalResponseClosure({
443
+ const waitingHumanInput = waitingHumanInputDisplayState(latest?.userWait?.kind === 'awaiting_user_answer');
444
+ if (waitingHumanInput) {
445
+ nextDisplayState = waitingHumanInput;
446
+ log.warn('Redirecting idle displayState to waiting-human-input state', undefined, {
447
+ dialogId: dialogId.valueOf(),
448
+ rootId: dialogId.rootId,
449
+ selfId: dialogId.selfId,
450
+ status,
451
+ nextDisplayState,
452
+ previousDisplayState: latest?.displayState ?? null,
453
+ previousExecutionMarker: latest?.executionMarker ?? null,
454
+ });
455
+ }
456
+ else if (!(await settleFinalResponseClosureForIdleProjection(dialogId, await resolveSideDialogFinalResponseClosure({
437
457
  dialogId,
438
458
  latest,
439
- });
440
- const finalResponseClosedForIdle = await settleFinalResponseClosureForIdleProjection(dialogId, finalResponseClosure);
441
- if (!finalResponseClosedForIdle) {
459
+ })))) {
442
460
  const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(dialogId, status);
443
- const pendingReplyObligation = pendingReplyObligationDisplayState(activeReplyObligation);
444
- if (pendingReplyObligation) {
445
- nextDisplayState = pendingReplyObligation;
446
- log.warn('Redirecting idle displayState to pending reply obligation projection', undefined, {
461
+ const waitingSideDialog = await waitingSideDialogDisplayState(dialogId, status, activeReplyObligation);
462
+ if (waitingSideDialog) {
463
+ nextDisplayState = waitingSideDialog;
464
+ log.warn('Redirecting idle displayState to waiting-side-dialog state', undefined, {
447
465
  dialogId: dialogId.valueOf(),
448
466
  rootId: dialogId.rootId,
449
467
  selfId: dialogId.selfId,
450
468
  status,
469
+ nextDisplayState,
451
470
  targetCallId: activeReplyObligation?.targetCallId ?? null,
452
471
  targetDialogId: activeReplyObligation?.targetDialogId.valueOf() ?? null,
453
472
  previousDisplayState: latest?.displayState ?? null,
454
473
  previousExecutionMarker: latest?.executionMarker ?? null,
455
- sideDialogFinalResponseCallId: latest?.sideDialogFinalResponse?.callId ?? null,
456
474
  });
457
475
  }
476
+ else {
477
+ const pendingReplyObligation = pendingReplyObligationDisplayState(activeReplyObligation);
478
+ if (pendingReplyObligation) {
479
+ nextDisplayState = pendingReplyObligation;
480
+ log.warn('Redirecting idle displayState to active reply obligation state', undefined, {
481
+ dialogId: dialogId.valueOf(),
482
+ rootId: dialogId.rootId,
483
+ selfId: dialogId.selfId,
484
+ status,
485
+ nextDisplayState,
486
+ targetCallId: activeReplyObligation?.targetCallId ?? null,
487
+ targetDialogId: activeReplyObligation?.targetDialogId.valueOf() ?? null,
488
+ previousDisplayState: latest?.displayState ?? null,
489
+ previousExecutionMarker: latest?.executionMarker ?? null,
490
+ sideDialogFinalResponseCallId: latest?.sideDialogFinalResponse?.callId ?? null,
491
+ });
492
+ }
493
+ }
458
494
  }
459
495
  }
460
496
  }
@@ -498,7 +534,7 @@ async function setDialogDisplayState(dialogId, displayState, status = 'running')
498
534
  if (broadcastToClients) {
499
535
  broadcastToClients(typed);
500
536
  }
501
- if (shouldBroadcastRunControlCounts(previousDisplayState, displayState)) {
537
+ if (shouldBroadcastRunControlCounts(previousDisplayState, nextDisplayState)) {
502
538
  try {
503
539
  await broadcastRunControlCountsSnapshot();
504
540
  }
@@ -544,9 +580,9 @@ async function computeIdleDisplayState(dlg) {
544
580
  continueEnabled: true,
545
581
  };
546
582
  }
547
- const q4hSuspension = q4hSuspensionDisplayState(latest?.userWait?.kind === 'awaiting_user_answer');
548
- if (q4hSuspension) {
549
- return q4hSuspension;
583
+ const waitingHumanInput = waitingHumanInputDisplayState(latest?.userWait?.kind === 'awaiting_user_answer');
584
+ if (waitingHumanInput) {
585
+ return waitingHumanInput;
550
586
  }
551
587
  const finalResponseClosure = await resolveSideDialogFinalResponseClosure({
552
588
  dialogId: dlg.id,
@@ -556,6 +592,10 @@ async function computeIdleDisplayState(dlg) {
556
592
  return { kind: 'idle_waiting_user' };
557
593
  }
558
594
  const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(dlg.id, dlg.status);
595
+ const waitingSideDialog = await waitingSideDialogDisplayState(dlg.id, dlg.status, activeReplyObligation);
596
+ if (waitingSideDialog) {
597
+ return waitingSideDialog;
598
+ }
559
599
  const pendingReplyObligation = pendingReplyObligationDisplayState(activeReplyObligation);
560
600
  if (pendingReplyObligation) {
561
601
  return pendingReplyObligation;
@@ -589,15 +629,19 @@ async function computeIdleDisplayStateFromPersistence(dialogId) {
589
629
  continueEnabled: true,
590
630
  };
591
631
  }
592
- const q4hSuspension = q4hSuspensionDisplayState(latest?.userWait?.kind === 'awaiting_user_answer');
593
- if (q4hSuspension) {
594
- return q4hSuspension;
632
+ const waitingHumanInput = waitingHumanInputDisplayState(latest?.userWait?.kind === 'awaiting_user_answer');
633
+ if (waitingHumanInput) {
634
+ return waitingHumanInput;
595
635
  }
596
636
  const finalResponseClosure = await resolveSideDialogFinalResponseClosure({ dialogId, latest });
597
637
  if (await settleFinalResponseClosureForIdleProjection(dialogId, finalResponseClosure)) {
598
638
  return { kind: 'idle_waiting_user' };
599
639
  }
600
640
  const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(dialogId, 'running');
641
+ const waitingSideDialog = await waitingSideDialogDisplayState(dialogId, 'running', activeReplyObligation);
642
+ if (waitingSideDialog) {
643
+ return waitingSideDialog;
644
+ }
601
645
  const pendingReplyObligation = pendingReplyObligationDisplayState(activeReplyObligation);
602
646
  if (pendingReplyObligation) {
603
647
  return pendingReplyObligation;
@@ -681,15 +725,15 @@ async function refreshRunControlProjectionFromPersistenceFacts(dialogId, trigger
681
725
  (0, interjection_pause_stop_1.isUserInterjectionPauseStopReason)(latest.executionMarker.reason)) {
682
726
  // WARNING:
683
727
  // This is the one place where the projection intentionally preserves legacy
684
- // paused-interjection stopped state ahead of the current suspension facts. That is not a bug:
728
+ // paused-interjection stopped state ahead of the current wait facts. That is not a bug:
685
729
  // the UI may still need to show that the original task was paused even if the underlying
686
730
  // dialog is now waiting on Q4H.
687
731
  //
688
732
  // The true source-of-truth decision about what Continue should do next lives in `flow.ts`'s
689
733
  // resume path, which performs a fresh fact scan at resume time and then either restores the
690
- // Q4H suspension projection or keeps driving immediately.
734
+ // Q4H waiting-human-input state or keeps driving immediately.
691
735
  //
692
- // Do not "heal" this branch away by prioritizing suspension facts here; that would collapse the
736
+ // Do not "heal" this branch away by prioritizing wait facts here; that would collapse the
693
737
  // temporary interjection UX and make repeated interjection turns revert too early.
694
738
  return {
695
739
  kind: 'stopped',
@@ -704,15 +748,19 @@ async function refreshRunControlProjectionFromPersistenceFacts(dialogId, trigger
704
748
  continueEnabled: true,
705
749
  };
706
750
  }
707
- const q4hSuspension = q4hSuspensionDisplayState(latest.userWait?.kind === 'awaiting_user_answer');
708
- if (q4hSuspension) {
709
- return q4hSuspension;
751
+ const waitingHumanInput = waitingHumanInputDisplayState(latest.userWait?.kind === 'awaiting_user_answer');
752
+ if (waitingHumanInput) {
753
+ return waitingHumanInput;
710
754
  }
711
755
  const finalResponseClosure = await resolveSideDialogFinalResponseClosure({ dialogId, latest });
712
756
  if (await settleFinalResponseClosureForIdleProjection(dialogId, finalResponseClosure)) {
713
757
  return { kind: 'idle_waiting_user' };
714
758
  }
715
759
  const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(dialogId, 'running');
760
+ const waitingSideDialog = await waitingSideDialogDisplayState(dialogId, 'running', activeReplyObligation);
761
+ if (waitingSideDialog) {
762
+ return waitingSideDialog;
763
+ }
716
764
  const pendingReplyObligation = pendingReplyObligationDisplayState(activeReplyObligation);
717
765
  if (pendingReplyObligation) {
718
766
  return pendingReplyObligation;
@@ -860,7 +908,10 @@ async function reconcileDisplayStatesAfterRestart() {
860
908
  if (!nextIdle) {
861
909
  continue;
862
910
  }
863
- const next = nextIdle.kind === 'blocked' || nextIdle.kind === 'stopped' || nextIdle.kind === 'dead'
911
+ const next = nextIdle.kind === 'blocked' ||
912
+ nextIdle.kind === 'waiting_side_dialog' ||
913
+ nextIdle.kind === 'stopped' ||
914
+ nextIdle.kind === 'dead'
864
915
  ? nextIdle
865
916
  : {
866
917
  kind: 'stopped',
@@ -274,11 +274,7 @@ function countFunctionCalls(events) {
274
274
  function computeRootForkDisplayState(args) {
275
275
  const topFrame = args.askerStack?.askerStack[args.askerStack.askerStack.length - 1];
276
276
  if (topFrame?.tellaskReplyObligation !== undefined) {
277
- return {
278
- kind: 'stopped',
279
- reason: { kind: 'pending_reply_obligation' },
280
- continueEnabled: true,
281
- };
277
+ return { kind: 'proceeding' };
282
278
  }
283
279
  if (args.action.kind === 'draft_user_text') {
284
280
  return { kind: 'idle_waiting_user' };
@@ -292,11 +288,7 @@ function computeRootForkDisplayState(args) {
292
288
  function computeSideDialogForkDisplayState(askerStack) {
293
289
  const topFrame = askerStack?.askerStack[askerStack.askerStack.length - 1];
294
290
  if (topFrame?.tellaskReplyObligation !== undefined) {
295
- return {
296
- kind: 'stopped',
297
- reason: { kind: 'pending_reply_obligation' },
298
- continueEnabled: true,
299
- };
291
+ return { kind: 'proceeding' };
300
292
  }
301
293
  return { kind: 'idle_waiting_user' };
302
294
  }
@@ -25,11 +25,12 @@ function isInterruptionReasonManualResumeEligible(reason) {
25
25
  case 'emergency_stop':
26
26
  case 'server_restart':
27
27
  case 'pending_runtime_prompt':
28
- case 'pending_reply_obligation':
29
28
  case 'fork_continue_ready':
30
29
  case 'system_stop':
31
30
  case 'llm_retry_stopped':
32
31
  return true;
32
+ case 'pending_reply_obligation':
33
+ return false;
33
34
  default: {
34
35
  const _exhaustive = reason;
35
36
  return _exhaustive;
package/dist/dialog.d.ts CHANGED
@@ -375,6 +375,8 @@ export declare abstract class Dialog {
375
375
  hasQueuedPrompt(): boolean;
376
376
  peekQueuedPrompt(): DialogQueuedPromptState | undefined;
377
377
  takeQueuedPrompt(): DialogQueuedPromptState | undefined;
378
+ removeQueuedPromptByMsgId(msgId: string): boolean;
379
+ removeQueuedPromptsMatching(predicate: (prompt: DialogQueuedPromptState) => boolean): number;
378
380
  setActiveRunControlSpec(spec?: DialogRunControlSpec): void;
379
381
  getActiveRunControlSpec(): DialogRunControlSpec | undefined;
380
382
  setNewCourseHook(hook?: NewCourseHook): void;
@@ -459,6 +461,7 @@ export declare abstract class Dialog {
459
461
  persistFunctionCall(id: string, name: string, rawArgumentsText: string, genseq: number, rawId?: string): Promise<void>;
460
462
  persistTellaskCall(id: string, name: TellaskCallRecordName, rawArgumentsText: string, genseq: number, options?: {
461
463
  deliveryMode?: 'tellask_call_start' | 'func_call_requested';
464
+ replyDirective?: TellaskReplyDirective;
462
465
  }): Promise<void>;
463
466
  /**
464
467
  * Post sideDialog completion response to this dialog.
@@ -693,6 +696,7 @@ export declare abstract class DialogStore {
693
696
  persistFunctionCall(_dialog: Dialog, _id: string, _name: string, _rawArgumentsText: string, _genseq: number, _rawId?: string): Promise<void>;
694
697
  persistTellaskCall(_dialog: Dialog, _id: string, _name: TellaskCallRecordName, _rawArgumentsText: string, _genseq: number, _options?: {
695
698
  deliveryMode?: 'tellask_call_start' | 'func_call_requested';
699
+ replyDirective?: TellaskReplyDirective;
696
700
  }): Promise<void>;
697
701
  /**
698
702
  * Start a new course in storage
package/dist/dialog.js CHANGED
@@ -1186,6 +1186,20 @@ class Dialog {
1186
1186
  takeQueuedPrompt() {
1187
1187
  return this._queuedPrompts.shift();
1188
1188
  }
1189
+ removeQueuedPromptByMsgId(msgId) {
1190
+ const normalized = msgId.trim();
1191
+ if (normalized === '') {
1192
+ return false;
1193
+ }
1194
+ const before = this._queuedPrompts.length;
1195
+ this._queuedPrompts = this._queuedPrompts.filter((prompt) => prompt.msgId !== normalized);
1196
+ return this._queuedPrompts.length !== before;
1197
+ }
1198
+ removeQueuedPromptsMatching(predicate) {
1199
+ const before = this._queuedPrompts.length;
1200
+ this._queuedPrompts = this._queuedPrompts.filter((prompt) => !predicate(prompt));
1201
+ return before - this._queuedPrompts.length;
1202
+ }
1189
1203
  setActiveRunControlSpec(spec) {
1190
1204
  this._activeRunControlSpec = spec;
1191
1205
  }
@@ -65,6 +65,7 @@ export declare class MockGen implements LlmGenerator {
65
65
  private responseMatchesContext;
66
66
  private normalizeFuncCallArgs;
67
67
  private extractLastAssistantSaying;
68
+ private extractCurrentPromptMsgId;
68
69
  private buildReplyToolReminderAutoResponse;
69
70
  /**
70
71
  * Find matching response using EXACT last message only.
@@ -276,6 +276,16 @@ class MockGen {
276
276
  }
277
277
  return null;
278
278
  }
279
+ extractCurrentPromptMsgId(context) {
280
+ for (let index = context.length - 1; index >= 0; index -= 1) {
281
+ const msg = context[index];
282
+ if (msg?.type === 'prompting_msg') {
283
+ const trimmed = msg.msgId.trim();
284
+ return trimmed === '' ? undefined : trimmed;
285
+ }
286
+ }
287
+ return undefined;
288
+ }
279
289
  buildReplyToolReminderAutoResponse(input, role, context) {
280
290
  if (role !== 'user' || !(0, reply_prompt_copy_1.isReplyToolReminderPromptContent)(input)) {
281
291
  return null;
@@ -288,12 +298,14 @@ class MockGen {
288
298
  if (!replyContent) {
289
299
  return null;
290
300
  }
301
+ const promptMsgId = this.extractCurrentPromptMsgId(context);
291
302
  return {
292
303
  message: input,
293
304
  role,
294
305
  response: '',
295
306
  funcCalls: [
296
307
  {
308
+ id: promptMsgId ? `mock_reply_${promptMsgId}` : undefined,
297
309
  name: toolMatch[1],
298
310
  arguments: { replyContent },
299
311
  },
@@ -396,8 +396,7 @@ async function clearStaleSideDialogRunControlForFinalResponse(args) {
396
396
  latest.generating !== true &&
397
397
  latest.executionMarker?.kind !== 'interrupted' &&
398
398
  !isNonIdleDisplayProjection(latest.displayState)) ||
399
- latest.executionMarker?.kind === 'dead' ||
400
- latest.pendingRuntimePrompt) {
399
+ latest.executionMarker?.kind === 'dead') {
401
400
  return {
402
401
  cleared: false,
403
402
  previousGenerating: latest?.generating ?? null,
@@ -405,22 +404,31 @@ async function clearStaleSideDialogRunControlForFinalResponse(args) {
405
404
  };
406
405
  }
407
406
  const finalResponseCallId = latest.sideDialogFinalResponse?.callId.trim();
408
- if (finalResponseCallId !== undefined && finalResponseCallId !== '') {
409
- const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(args.dialog.id, args.dialog.status);
410
- if (activeReplyObligation?.targetCallId.trim() === finalResponseCallId) {
411
- await persistence_1.DialogPersistence.setActiveTellaskReplyObligation(args.dialog.id, undefined, args.dialog.status);
412
- }
407
+ if (finalResponseCallId === undefined || finalResponseCallId === '') {
408
+ return {
409
+ cleared: false,
410
+ previousGenerating: latest.generating ?? null,
411
+ previousNextStepTriggerCount: latest.nextStep.triggers.length,
412
+ };
413
413
  }
414
- const displayState = await (0, dialog_display_state_1.computeIdleDisplayState)(args.dialog);
414
+ const pendingRuntimePromptMsgId = latest.pendingRuntimePrompt?.msgId;
415
+ const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(args.dialog.id, args.dialog.status);
416
+ if (activeReplyObligation?.targetCallId.trim() === finalResponseCallId) {
417
+ await persistence_1.DialogPersistence.setActiveTellaskReplyObligation(args.dialog.id, undefined, args.dialog.status);
418
+ }
419
+ const displayState = { kind: 'idle_waiting_user' };
420
+ if (pendingRuntimePromptMsgId !== undefined) {
421
+ args.dialog.removeQueuedPromptByMsgId(pendingRuntimePromptMsgId);
422
+ }
423
+ args.dialog.removeQueuedPromptsMatching((prompt) => isPendingRuntimePromptFollowUp(prompt));
415
424
  await persistence_1.DialogPersistence.mutateDialogLatest(args.dialog.id, () => ({
416
425
  kind: 'patch',
417
426
  patch: {
418
427
  generating: false,
419
428
  nextStep: (0, dialog_latest_state_1.createEmptyDialogNextStepState)(),
429
+ pendingRuntimePrompt: undefined,
420
430
  displayState,
421
- executionMarker: displayState.kind === 'stopped'
422
- ? { kind: 'interrupted', reason: displayState.reason }
423
- : undefined,
431
+ executionMarker: undefined,
424
432
  },
425
433
  }), args.dialog.status);
426
434
  await persistence_1.DialogPersistence.removeWakeQueueEntriesForDialog(args.dialog.id, args.dialog.status);
@@ -912,6 +920,15 @@ async function inspectSideDialogBusinessContinuationDrive(args) {
912
920
  sideDialogFinalResponseCallId,
913
921
  };
914
922
  }
923
+ if (args.hasQueuedPrompt) {
924
+ return {
925
+ shouldReject: false,
926
+ source,
927
+ displayState,
928
+ currentCourse,
929
+ sideDialogFinalResponseCallId,
930
+ };
931
+ }
915
932
  if (requestedWorkReplyContinuation && args.requestedWorkReplyClaim.status !== 'claimed') {
916
933
  return {
917
934
  shouldReject: true,
@@ -1333,13 +1350,14 @@ async function executeDriveRound(args) {
1333
1350
  driveOptions,
1334
1351
  });
1335
1352
  }
1336
- if (!humanPrompt && dialog instanceof dialog_1.SideDialog && !dialog.hasQueuedPrompt()) {
1353
+ if (!humanPrompt && dialog instanceof dialog_1.SideDialog) {
1337
1354
  const inspection = await inspectSideDialogBusinessContinuationDrive({
1338
1355
  dialog,
1339
1356
  driveOptions,
1340
1357
  requestedWorkReplyClaim,
1341
1358
  replyDeliveryRecoveryClaim,
1342
1359
  toolFollowupClaim,
1360
+ hasQueuedPrompt: dialog.hasQueuedPrompt(),
1343
1361
  });
1344
1362
  if (inspection.shouldReject) {
1345
1363
  if (inspection.rejection === 'finalized_after_response_anchor') {
@@ -1662,6 +1680,23 @@ async function executeDriveRound(args) {
1662
1680
  if (!interruptedBySignal) {
1663
1681
  const queuedFollowUp = dialog.peekQueuedPrompt();
1664
1682
  if (queuedFollowUp && isPendingRuntimePromptFollowUp(queuedFollowUp)) {
1683
+ const claim = await claimPendingRuntimePromptForDrive({
1684
+ dialog,
1685
+ prompt: queuedFollowUp,
1686
+ });
1687
+ if (claim.status === 'stale') {
1688
+ const discarded = dialog.takeQueuedPrompt();
1689
+ if (!discarded || discarded.msgId !== queuedFollowUp.msgId) {
1690
+ throw new Error(`pending runtime prompt invariant violation: expected queued prompt ${queuedFollowUp.msgId} before stale discard after core`);
1691
+ }
1692
+ log_1.log.debug('kernel-driver dropped stale pending runtime prompt after core', undefined, {
1693
+ dialogId: dialog.id.valueOf(),
1694
+ rootId: dialog.id.rootId,
1695
+ selfId: dialog.id.selfId,
1696
+ msgId: queuedFollowUp.msgId,
1697
+ kind: queuedFollowUp.kind,
1698
+ });
1699
+ }
1665
1700
  followUp = undefined;
1666
1701
  }
1667
1702
  else if (queuedFollowUp && isQueuedReplyObligationContinuation(queuedFollowUp)) {
@@ -1881,11 +1916,11 @@ async function executeDriveRound(args) {
1881
1916
  driveResult &&
1882
1917
  !interruptedBySignal &&
1883
1918
  resolveDirectFallbackResponse({ driveResult, dialog }) !== undefined &&
1884
- activeTellaskReplyDirective?.expectedReplyCallName === 'replyTellaskBack' &&
1919
+ activeTellaskReplyDirective !== undefined &&
1885
1920
  followUp === undefined) {
1886
1921
  const directFallbackResponse = resolveDirectFallbackResponse({ driveResult, dialog });
1887
1922
  if (directFallbackResponse === undefined) {
1888
- throw new Error(`replyTellaskBack fallback invariant violation: missing direct fallback response for dialog=${dialog.id.valueOf()}`);
1923
+ throw new Error(`reply fallback invariant violation: missing direct fallback response for dialog=${dialog.id.valueOf()}`);
1889
1924
  }
1890
1925
  const hasInProgressFunctionCall = typeof driveResult.lastFunctionCallGenseq === 'number' &&
1891
1926
  Number.isFinite(driveResult.lastFunctionCallGenseq) &&
@@ -1909,12 +1944,18 @@ async function executeDriveRound(args) {
1909
1944
  userLanguageCode: language,
1910
1945
  tellaskReplyDirective: activeTellaskReplyDirective,
1911
1946
  };
1912
- log_1.log.debug('kernel-driver queued replyTellaskBack reminder prompt after plain reply', undefined, {
1947
+ log_1.log.debug('kernel-driver queued replyTellask reminder prompt after plain reply', undefined, {
1913
1948
  dialogId: dialog.id.valueOf(),
1949
+ expectedReplyCallName: activeTellaskReplyDirective.expectedReplyCallName,
1914
1950
  targetCallId: activeTellaskReplyDirective.targetCallId,
1915
1951
  });
1916
1952
  }
1917
1953
  else {
1954
+ if (activeTellaskReplyDirective.expectedReplyCallName !== 'replyTellaskBack') {
1955
+ throw new Error(`reply fallback invariant violation: unsupported non-sideDialog reply tool ` +
1956
+ `${activeTellaskReplyDirective.expectedReplyCallName} for dialog=${dialog.id.valueOf()}`);
1957
+ }
1958
+ const directFallbackCallId = `direct-fallback-${(0, id_1.generateShortId)()}`;
1918
1959
  await (0, tellask_special_1.deliverTellaskBackReplyFromDirective)({
1919
1960
  replyingDialog: dialog,
1920
1961
  directive: activeTellaskReplyDirective,
@@ -1927,8 +1968,8 @@ async function executeDriveRound(args) {
1927
1968
  directFallbackSource: directFallbackResponse.source,
1928
1969
  });
1929
1970
  await dialog.appendTellaskReplyResolution({
1930
- callId: `direct-fallback-${(0, id_1.generateShortId)()}`,
1931
- replyCallName: 'replyTellaskBack',
1971
+ callId: directFallbackCallId,
1972
+ replyCallName: activeTellaskReplyDirective.expectedReplyCallName,
1932
1973
  targetCallId: activeTellaskReplyDirective.targetCallId,
1933
1974
  });
1934
1975
  }
@@ -37,7 +37,7 @@ export type DiligenceAutoContinueGateDecision = {
37
37
  kind: 'allowed';
38
38
  } | {
39
39
  kind: 'blocked';
40
- reason: 'not_main_dialog' | 'active_run' | 'stop_requested' | 'execution_interrupted' | 'execution_dead' | 'q4h' | 'active_callee_dispatches';
40
+ reason: 'not_main_dialog' | 'active_run' | 'stop_requested' | 'execution_interrupted' | 'execution_dead' | 'q4h' | 'active_reply_obligation' | 'active_callee_dispatches';
41
41
  };
42
42
  export declare function evaluateDiligenceAutoContinueGate(options: {
43
43
  dlg: Dialog;
@@ -48,6 +48,7 @@ const dialog_1 = require("../../dialog");
48
48
  const dialog_display_state_1 = require("../../dialog-display-state");
49
49
  const evt_registry_1 = require("../../evt-registry");
50
50
  const log_1 = require("../../log");
51
+ const persistence_1 = require("../../persistence");
51
52
  const problems_1 = require("../../problems");
52
53
  const driver_messages_1 = require("../../runtime/driver-messages");
53
54
  const work_language_1 = require("../../runtime/work-language");
@@ -152,6 +153,10 @@ async function evaluateDiligenceAutoContinueGate(options) {
152
153
  if (!suspension.canDrive) {
153
154
  return { kind: 'blocked', reason: 'q4h' };
154
155
  }
156
+ const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(options.dlg.id, options.dlg.status);
157
+ if (activeReplyObligation !== undefined) {
158
+ return { kind: 'blocked', reason: 'active_reply_obligation' };
159
+ }
155
160
  if (suspension.backgroundCalleeDialogs) {
156
161
  return { kind: 'blocked', reason: 'active_callee_dispatches' };
157
162
  }
@@ -170,6 +175,13 @@ async function maybePrepareDiligenceAutoContinuePrompt(options) {
170
175
  nextRemainingBudget: normalizeDiligenceRemainingBudget(options.remainingBudget),
171
176
  };
172
177
  }
178
+ const activeReplyObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(options.dlg.id, options.dlg.status);
179
+ if (activeReplyObligation !== undefined) {
180
+ return {
181
+ kind: 'disabled',
182
+ nextRemainingBudget: normalizeDiligenceRemainingBudget(options.remainingBudget),
183
+ };
184
+ }
173
185
  const resolved = await resolveRtwsDiligenceConfig();
174
186
  if (resolved.kind === 'disabled') {
175
187
  return {
@@ -2301,6 +2301,10 @@ async function processTellaskFunctionRound(args) {
2301
2301
  deliveryMode: isReplyTellaskCallName(handled.call.callName)
2302
2302
  ? 'func_call_requested'
2303
2303
  : 'tellask_call_start',
2304
+ ...(isReplyTellaskCallName(handled.call.callName) &&
2305
+ args.activePromptReplyDirective !== undefined
2306
+ ? { replyDirective: args.activePromptReplyDirective }
2307
+ : {}),
2304
2308
  });
2305
2309
  tellaskCallMessages.push({
2306
2310
  type: 'func_call_msg',
@@ -159,6 +159,7 @@ export declare class DiskFileDialogStore extends DialogStore {
159
159
  persistFunctionCall(dialog: Dialog, id: string, name: string, rawArgumentsText: string, genseq: number, rawId?: string): Promise<void>;
160
160
  persistTellaskCall(dialog: Dialog, id: string, name: 'tellaskBack' | 'tellask' | 'tellaskSessionless' | 'replyTellask' | 'replyTellaskSessionless' | 'replyTellaskBack' | 'askHuman' | 'freshBootsReasoning', rawArgumentsText: string, genseq: number, options?: {
161
161
  deliveryMode?: 'tellask_call_start' | 'func_call_requested';
162
+ replyDirective?: TellaskReplyDirective;
162
163
  }): Promise<void>;
163
164
  /**
164
165
  * Update questions for human state (exceptional overwrite pattern)