dominds 1.16.10 → 1.17.0

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 (108) hide show
  1. package/dist/dialog-display-state.js +22 -1
  2. package/dist/dialog-instance-registry.js +47 -0
  3. package/dist/dialog-interruption.d.ts +1 -0
  4. package/dist/dialog-interruption.js +19 -0
  5. package/dist/dialog.d.ts +2 -1
  6. package/dist/dialog.js +37 -1
  7. package/dist/llm/kernel-driver/drive.js +1 -0
  8. package/dist/llm/kernel-driver/flow.js +5 -3
  9. package/dist/llm/kernel-driver/loop.js +5 -2
  10. package/dist/persistence.d.ts +3 -1
  11. package/dist/persistence.js +174 -37
  12. package/dist/runtime/interjection-pause-stop.js +1 -1
  13. package/package.json +4 -4
  14. package/webapp/dist/assets/{_basePickBy-BKgfg72Q.js → _basePickBy-DCLDUO6G.js} +3 -3
  15. package/webapp/dist/assets/{_basePickBy-BKgfg72Q.js.map → _basePickBy-DCLDUO6G.js.map} +1 -1
  16. package/webapp/dist/assets/{_baseUniq-DKhs7H5s.js → _baseUniq-V58PJT8b.js} +2 -2
  17. package/webapp/dist/assets/{_baseUniq-DKhs7H5s.js.map → _baseUniq-V58PJT8b.js.map} +1 -1
  18. package/webapp/dist/assets/{arc-Tykg3Fx4.js → arc-6cLC3ft0.js} +2 -2
  19. package/webapp/dist/assets/{arc-Tykg3Fx4.js.map → arc-6cLC3ft0.js.map} +1 -1
  20. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-BAyn6_in.js → architectureDiagram-2XIMDMQ5-DZCDnc5k.js} +7 -7
  21. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-BAyn6_in.js.map → architectureDiagram-2XIMDMQ5-DZCDnc5k.js.map} +1 -1
  22. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CGbo6x6_.js → blockDiagram-WCTKOSBZ-B3x8CjfT.js} +7 -7
  23. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CGbo6x6_.js.map → blockDiagram-WCTKOSBZ-B3x8CjfT.js.map} +1 -1
  24. package/webapp/dist/assets/{c4Diagram-IC4MRINW-CUizxwo0.js → c4Diagram-IC4MRINW-BG5ES2pq.js} +3 -3
  25. package/webapp/dist/assets/{c4Diagram-IC4MRINW-CUizxwo0.js.map → c4Diagram-IC4MRINW-BG5ES2pq.js.map} +1 -1
  26. package/webapp/dist/assets/{channel-DvP7WrjO.js → channel-CKCjdwdQ.js} +2 -2
  27. package/webapp/dist/assets/{channel-DvP7WrjO.js.map → channel-CKCjdwdQ.js.map} +1 -1
  28. package/webapp/dist/assets/{chunk-4BX2VUAB-cgnNaqgV.js → chunk-4BX2VUAB-BMUaxm65.js} +2 -2
  29. package/webapp/dist/assets/{chunk-4BX2VUAB-cgnNaqgV.js.map → chunk-4BX2VUAB-BMUaxm65.js.map} +1 -1
  30. package/webapp/dist/assets/{chunk-55IACEB6-BEUsguTg.js → chunk-55IACEB6-CZLjFLTA.js} +2 -2
  31. package/webapp/dist/assets/{chunk-55IACEB6-BEUsguTg.js.map → chunk-55IACEB6-CZLjFLTA.js.map} +1 -1
  32. package/webapp/dist/assets/{chunk-FMBD7UC4-B2p0efxm.js → chunk-FMBD7UC4-C6OhtkjK.js} +2 -2
  33. package/webapp/dist/assets/{chunk-FMBD7UC4-B2p0efxm.js.map → chunk-FMBD7UC4-C6OhtkjK.js.map} +1 -1
  34. package/webapp/dist/assets/{chunk-JSJVCQXG-Bd09WM0B.js → chunk-JSJVCQXG-BL3lMwkX.js} +2 -2
  35. package/webapp/dist/assets/{chunk-JSJVCQXG-Bd09WM0B.js.map → chunk-JSJVCQXG-BL3lMwkX.js.map} +1 -1
  36. package/webapp/dist/assets/{chunk-KX2RTZJC-DaLNbvSI.js → chunk-KX2RTZJC-SieIRb1A.js} +2 -2
  37. package/webapp/dist/assets/{chunk-KX2RTZJC-DaLNbvSI.js.map → chunk-KX2RTZJC-SieIRb1A.js.map} +1 -1
  38. package/webapp/dist/assets/{chunk-NQ4KR5QH-6dsWbn61.js → chunk-NQ4KR5QH-Dj9V3OHv.js} +4 -4
  39. package/webapp/dist/assets/{chunk-NQ4KR5QH-6dsWbn61.js.map → chunk-NQ4KR5QH-Dj9V3OHv.js.map} +1 -1
  40. package/webapp/dist/assets/{chunk-QZHKN3VN-C0e1qWr4.js → chunk-QZHKN3VN-DPuk0WWI.js} +2 -2
  41. package/webapp/dist/assets/{chunk-QZHKN3VN-C0e1qWr4.js.map → chunk-QZHKN3VN-DPuk0WWI.js.map} +1 -1
  42. package/webapp/dist/assets/{chunk-WL4C6EOR-ChheG0OU.js → chunk-WL4C6EOR-COmZsUPA.js} +6 -6
  43. package/webapp/dist/assets/{chunk-WL4C6EOR-ChheG0OU.js.map → chunk-WL4C6EOR-COmZsUPA.js.map} +1 -1
  44. package/webapp/dist/assets/{classDiagram-VBA2DB6C-uUAnWHsS.js → classDiagram-VBA2DB6C-D0LskUiI.js} +7 -7
  45. package/webapp/dist/assets/{classDiagram-VBA2DB6C-uUAnWHsS.js.map → classDiagram-VBA2DB6C-D0LskUiI.js.map} +1 -1
  46. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-uUAnWHsS.js → classDiagram-v2-RAHNMMFH-D0LskUiI.js} +7 -7
  47. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-uUAnWHsS.js.map → classDiagram-v2-RAHNMMFH-D0LskUiI.js.map} +1 -1
  48. package/webapp/dist/assets/{clone-BiXgC0aE.js → clone-DF4VAArJ.js} +2 -2
  49. package/webapp/dist/assets/{clone-BiXgC0aE.js.map → clone-DF4VAArJ.js.map} +1 -1
  50. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-C-h7F7gA.js → cose-bilkent-S5V4N54A-BLS39Y5M.js} +2 -2
  51. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-C-h7F7gA.js.map → cose-bilkent-S5V4N54A-BLS39Y5M.js.map} +1 -1
  52. package/webapp/dist/assets/{dagre-KLK3FWXG-5B3k91Lo.js → dagre-KLK3FWXG-BNcB5hir.js} +7 -7
  53. package/webapp/dist/assets/{dagre-KLK3FWXG-5B3k91Lo.js.map → dagre-KLK3FWXG-BNcB5hir.js.map} +1 -1
  54. package/webapp/dist/assets/{diagram-E7M64L7V-CFtPXaNS.js → diagram-E7M64L7V-C1k_RR0F.js} +8 -8
  55. package/webapp/dist/assets/{diagram-E7M64L7V-CFtPXaNS.js.map → diagram-E7M64L7V-C1k_RR0F.js.map} +1 -1
  56. package/webapp/dist/assets/{diagram-IFDJBPK2-CUuPPDwe.js → diagram-IFDJBPK2-IbfvdUeO.js} +7 -7
  57. package/webapp/dist/assets/{diagram-IFDJBPK2-CUuPPDwe.js.map → diagram-IFDJBPK2-IbfvdUeO.js.map} +1 -1
  58. package/webapp/dist/assets/{diagram-P4PSJMXO-D7oYhsVm.js → diagram-P4PSJMXO-DMHGiNIM.js} +7 -7
  59. package/webapp/dist/assets/{diagram-P4PSJMXO-D7oYhsVm.js.map → diagram-P4PSJMXO-DMHGiNIM.js.map} +1 -1
  60. package/webapp/dist/assets/{erDiagram-INFDFZHY-DUDHdT_e.js → erDiagram-INFDFZHY-DdHLX_b6.js} +5 -5
  61. package/webapp/dist/assets/{erDiagram-INFDFZHY-DUDHdT_e.js.map → erDiagram-INFDFZHY-DdHLX_b6.js.map} +1 -1
  62. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CT7lC5J1.js → flowDiagram-PKNHOUZH-BfFizksz.js} +7 -7
  63. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-CT7lC5J1.js.map → flowDiagram-PKNHOUZH-BfFizksz.js.map} +1 -1
  64. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-BhlcqqDR.js → ganttDiagram-A5KZAMGK-CqevCVU5.js} +3 -3
  65. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-BhlcqqDR.js.map → ganttDiagram-A5KZAMGK-CqevCVU5.js.map} +1 -1
  66. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CYLYfqiB.js → gitGraphDiagram-K3NZZRJ6-BOOwupHL.js} +8 -8
  67. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-CYLYfqiB.js.map → gitGraphDiagram-K3NZZRJ6-BOOwupHL.js.map} +1 -1
  68. package/webapp/dist/assets/{graph-twAxd7MO.js → graph-nrSDteEc.js} +3 -3
  69. package/webapp/dist/assets/{graph-twAxd7MO.js.map → graph-nrSDteEc.js.map} +1 -1
  70. package/webapp/dist/assets/{index-Bc1jJvgU.js → index-Cakki4rP.js} +67 -61
  71. package/webapp/dist/assets/{index-Bc1jJvgU.js.map → index-Cakki4rP.js.map} +1 -1
  72. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-BAA1VoC0.js → infoDiagram-LFFYTUFH-D9wzGbBd.js} +6 -6
  73. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-BAA1VoC0.js.map → infoDiagram-LFFYTUFH-D9wzGbBd.js.map} +1 -1
  74. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-CyPvSx5W.js → ishikawaDiagram-PHBUUO56-Cw505dkV.js} +2 -2
  75. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-CyPvSx5W.js.map → ishikawaDiagram-PHBUUO56-Cw505dkV.js.map} +1 -1
  76. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-CbOLT63I.js → journeyDiagram-4ABVD52K-DB9-Kk7L.js} +5 -5
  77. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-CbOLT63I.js.map → journeyDiagram-4ABVD52K-DB9-Kk7L.js.map} +1 -1
  78. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-CUS-wMLR.js → kanban-definition-K7BYSVSG-D6f5d594.js} +3 -3
  79. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-CUS-wMLR.js.map → kanban-definition-K7BYSVSG-D6f5d594.js.map} +1 -1
  80. package/webapp/dist/assets/{layout-C0HW4ZHi.js → layout-C66Gu-9j.js} +5 -5
  81. package/webapp/dist/assets/{layout-C0HW4ZHi.js.map → layout-C66Gu-9j.js.map} +1 -1
  82. package/webapp/dist/assets/{linear-DNEgfkh6.js → linear-WEG-0mNF.js} +2 -2
  83. package/webapp/dist/assets/{linear-DNEgfkh6.js.map → linear-WEG-0mNF.js.map} +1 -1
  84. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-D5URwhNx.js → mindmap-definition-YRQLILUH-C5o4PZoW.js} +4 -4
  85. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-D5URwhNx.js.map → mindmap-definition-YRQLILUH-C5o4PZoW.js.map} +1 -1
  86. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-BQbBOUPk.js → pieDiagram-SKSYHLDU-CvE77iES.js} +8 -8
  87. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-BQbBOUPk.js.map → pieDiagram-SKSYHLDU-CvE77iES.js.map} +1 -1
  88. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_dFbPid.js → quadrantDiagram-337W2JSQ-0WD_Zxhv.js} +3 -3
  89. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_dFbPid.js.map → quadrantDiagram-337W2JSQ-0WD_Zxhv.js.map} +1 -1
  90. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-CtWDUSB3.js → requirementDiagram-Z7DCOOCP-VSa_hUdb.js} +4 -4
  91. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-CtWDUSB3.js.map → requirementDiagram-Z7DCOOCP-VSa_hUdb.js.map} +1 -1
  92. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CqRH7yj4.js → sankeyDiagram-WA2Y5GQK-vPNok4nN.js} +2 -2
  93. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CqRH7yj4.js.map → sankeyDiagram-WA2Y5GQK-vPNok4nN.js.map} +1 -1
  94. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-B1-5-5Qx.js → sequenceDiagram-2WXFIKYE-DX4cZf9x.js} +4 -4
  95. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-B1-5-5Qx.js.map → sequenceDiagram-2WXFIKYE-DX4cZf9x.js.map} +1 -1
  96. package/webapp/dist/assets/{stateDiagram-RAJIS63D-9krZSpaD.js → stateDiagram-RAJIS63D-nqNJSdDU.js} +9 -9
  97. package/webapp/dist/assets/{stateDiagram-RAJIS63D-9krZSpaD.js.map → stateDiagram-RAJIS63D-nqNJSdDU.js.map} +1 -1
  98. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DDLC-q0s.js → stateDiagram-v2-FVOUBMTO-BuZBSDCT.js} +5 -5
  99. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DDLC-q0s.js.map → stateDiagram-v2-FVOUBMTO-BuZBSDCT.js.map} +1 -1
  100. package/webapp/dist/assets/{timeline-definition-YZTLITO2-C64HbHNO.js → timeline-definition-YZTLITO2--gWaXe_R.js} +3 -3
  101. package/webapp/dist/assets/{timeline-definition-YZTLITO2-C64HbHNO.js.map → timeline-definition-YZTLITO2--gWaXe_R.js.map} +1 -1
  102. package/webapp/dist/assets/{treemap-KZPCXAKY-TEywEA7B.js → treemap-KZPCXAKY-CAx-L6KX.js} +5 -5
  103. package/webapp/dist/assets/{treemap-KZPCXAKY-TEywEA7B.js.map → treemap-KZPCXAKY-CAx-L6KX.js.map} +1 -1
  104. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CT9sZ6ft.js → vennDiagram-LZ73GAT5-BQD4mief.js} +2 -2
  105. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-CT9sZ6ft.js.map → vennDiagram-LZ73GAT5-BQD4mief.js.map} +1 -1
  106. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-CEAg_tiv.js → xychartDiagram-JWTSCODW-D-wcj8Yx.js} +3 -3
  107. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-CEAg_tiv.js.map → xychartDiagram-JWTSCODW-D-wcj8Yx.js.map} +1 -1
  108. package/webapp/dist/index.html +1 -1
@@ -417,6 +417,13 @@ async function computeIdleDisplayState(dlg) {
417
417
  continueEnabled: isStoppedReasonResumable(latest.executionMarker.reason),
418
418
  };
419
419
  }
420
+ if (latest?.pendingCourseStartPrompt) {
421
+ return {
422
+ kind: 'stopped',
423
+ reason: { kind: 'pending_course_start' },
424
+ continueEnabled: true,
425
+ };
426
+ }
420
427
  const hasQ4H = await dlg.hasPendingQ4H();
421
428
  const hasSubdialogs = await dlg.hasPendingSubdialogs();
422
429
  if (hasQ4H && hasSubdialogs) {
@@ -449,6 +456,13 @@ async function computeIdleDisplayStateFromPersistence(dialogId) {
449
456
  continueEnabled: isStoppedReasonResumable(latest.executionMarker.reason),
450
457
  };
451
458
  }
459
+ if (latest?.pendingCourseStartPrompt) {
460
+ return {
461
+ kind: 'stopped',
462
+ reason: { kind: 'pending_course_start' },
463
+ continueEnabled: true,
464
+ };
465
+ }
452
466
  const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
453
467
  const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(dialogId, 'running');
454
468
  const hasQ4H = q4h.length > 0;
@@ -502,6 +516,13 @@ async function refreshRunControlProjectionFromPersistenceFacts(dialogId, trigger
502
516
  continueEnabled: isStoppedReasonResumable(latest.executionMarker.reason),
503
517
  };
504
518
  }
519
+ if (latest.pendingCourseStartPrompt) {
520
+ return {
521
+ kind: 'stopped',
522
+ reason: { kind: 'pending_course_start' },
523
+ continueEnabled: true,
524
+ };
525
+ }
505
526
  const q4h = await persistence_1.DialogPersistence.loadQuestions4HumanState(dialogId, 'running');
506
527
  const pendingSubdialogs = await persistence_1.DialogPersistence.loadPendingSubdialogs(dialogId, 'running');
507
528
  const hasQ4H = q4h.length > 0;
@@ -605,7 +626,7 @@ async function reconcileDisplayStatesAfterRestart() {
605
626
  if (!nextIdle) {
606
627
  continue;
607
628
  }
608
- const next = nextIdle.kind === 'blocked'
629
+ const next = nextIdle.kind === 'blocked' || nextIdle.kind === 'stopped' || nextIdle.kind === 'dead'
609
630
  ? nextIdle
610
631
  : {
611
632
  kind: 'stopped',
@@ -24,6 +24,39 @@ function clampNonNegativeFiniteInt(value, fallback) {
24
24
  return fallback;
25
25
  return Math.max(0, Math.floor(value));
26
26
  }
27
+ async function resolvePendingCourseStartPromptForRestore(args) {
28
+ const pending = args.latest?.pendingCourseStartPrompt;
29
+ if (!pending) {
30
+ return { pendingCourseStartPrompt: undefined };
31
+ }
32
+ const alreadyPersisted = args.messages.some((message) => {
33
+ return message.type === 'prompting_msg' && message.msgId === pending.msgId;
34
+ });
35
+ if (alreadyPersisted) {
36
+ if (args.status === 'running') {
37
+ await persistence_1.DialogPersistence.clearPendingCourseStartPrompt(args.dialogId, pending.msgId, args.status);
38
+ }
39
+ return { pendingCourseStartPrompt: undefined };
40
+ }
41
+ return {
42
+ pendingCourseStartPrompt: {
43
+ content: pending.content,
44
+ msgId: pending.msgId,
45
+ grammar: 'markdown',
46
+ origin: 'runtime',
47
+ ...(pending.userLanguageCode === undefined
48
+ ? {}
49
+ : { userLanguageCode: pending.userLanguageCode }),
50
+ ...(pending.tellaskReplyDirective === undefined
51
+ ? {}
52
+ : { tellaskReplyDirective: pending.tellaskReplyDirective }),
53
+ ...(pending.skipTaskdoc === undefined ? {} : { skipTaskdoc: pending.skipTaskdoc }),
54
+ ...(pending.subdialogReplyTarget === undefined
55
+ ? {}
56
+ : { subdialogReplyTarget: pending.subdialogReplyTarget }),
57
+ },
58
+ };
59
+ }
27
60
  async function getOrRestoreRootDialog(rootId, status) {
28
61
  const existing = dialog_global_registry_1.globalDialogRegistry.get(rootId);
29
62
  if (existing) {
@@ -41,6 +74,12 @@ async function getOrRestoreRootDialog(rootId, status) {
41
74
  return undefined;
42
75
  }
43
76
  const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialogId, status);
77
+ const { pendingCourseStartPrompt } = await resolvePendingCourseStartPromptForRestore({
78
+ dialogId: rootDialogId,
79
+ status,
80
+ messages: rootState.messages,
81
+ latest,
82
+ });
44
83
  let diligencePushMax = diligence_1.DEFAULT_DILIGENCE_PUSH_MAX;
45
84
  try {
46
85
  const team = await team_1.Team.load();
@@ -56,6 +95,7 @@ async function getOrRestoreRootDialog(rootId, status) {
56
95
  reminders: rootState.reminders,
57
96
  currentCourse: rootState.currentCourse,
58
97
  contextHealth: rootState.contextHealth,
98
+ pendingCourseStartPrompt,
59
99
  });
60
100
  const persistedDisableDiligencePush = latest && typeof latest.disableDiligencePush === 'boolean'
61
101
  ? latest.disableDiligencePush
@@ -97,6 +137,12 @@ async function ensureDialogLoaded(rootDialog, targetId, status, visitedSelfIds =
97
137
  if (!state)
98
138
  return undefined;
99
139
  const latest = await persistence_1.DialogPersistence.loadDialogLatest(targetId, status);
140
+ const { pendingCourseStartPrompt } = await resolvePendingCourseStartPromptForRestore({
141
+ dialogId: targetId,
142
+ status,
143
+ messages: state.messages,
144
+ latest,
145
+ });
100
146
  const assignmentFromSup = state.metadata.assignmentFromSup;
101
147
  if (!assignmentFromSup)
102
148
  return undefined;
@@ -112,6 +158,7 @@ async function ensureDialogLoaded(rootDialog, targetId, status, visitedSelfIds =
112
158
  reminders: state.reminders,
113
159
  currentCourse: state.currentCourse,
114
160
  contextHealth: state.contextHealth,
161
+ pendingCourseStartPrompt,
115
162
  });
116
163
  subdialog.disableDiligencePush = latest?.disableDiligencePush ?? false;
117
164
  if (subdialog.sessionSlug) {
@@ -16,3 +16,4 @@ import type { DialogInterruptionReason } from '@longrun-ai/kernel/types/display-
16
16
  * provider/model and should keep protecting the system.
17
17
  */
18
18
  export declare function isInterruptionReasonManualResumeEligible(reason: DialogInterruptionReason): boolean;
19
+ export declare function doesInterruptionReasonRequireExplicitResume(reason: DialogInterruptionReason): boolean;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isInterruptionReasonManualResumeEligible = isInterruptionReasonManualResumeEligible;
4
+ exports.doesInterruptionReasonRequireExplicitResume = doesInterruptionReasonRequireExplicitResume;
4
5
  /**
5
6
  * Decides whether a finalized stopped dialog should expose manual Continue.
6
7
  *
@@ -22,6 +23,24 @@ function isInterruptionReasonManualResumeEligible(reason) {
22
23
  case 'user_stop':
23
24
  case 'emergency_stop':
24
25
  case 'server_restart':
26
+ case 'pending_course_start':
27
+ case 'fork_continue_ready':
28
+ case 'system_stop':
29
+ case 'llm_retry_stopped':
30
+ return true;
31
+ default: {
32
+ const _exhaustive = reason;
33
+ return _exhaustive;
34
+ }
35
+ }
36
+ }
37
+ function doesInterruptionReasonRequireExplicitResume(reason) {
38
+ switch (reason.kind) {
39
+ case 'pending_course_start':
40
+ return false;
41
+ case 'user_stop':
42
+ case 'emergency_stop':
43
+ case 'server_restart':
25
44
  case 'fork_continue_ready':
26
45
  case 'system_stop':
27
46
  case 'llm_retry_stopped':
package/dist/dialog.d.ts CHANGED
@@ -106,6 +106,7 @@ export interface DialogInitParams {
106
106
  createdAt?: string;
107
107
  updatedAt?: string;
108
108
  contextHealth?: ContextHealthSnapshot;
109
+ pendingCourseStartPrompt?: DialogPrompt;
109
110
  };
110
111
  }
111
112
  export type VisibleReminderTarget = Readonly<{
@@ -678,7 +679,7 @@ export declare abstract class DialogStore {
678
679
  /**
679
680
  * Start a new course in storage
680
681
  */
681
- startNewCourse(_dialog: Dialog, _newCoursePrompt: string): Promise<void>;
682
+ startNewCourse(_dialog: Dialog, _newCoursePrompt: DialogPrompt): Promise<void>;
682
683
  /**
683
684
  * Handle stream error
684
685
  */
package/dist/dialog.js CHANGED
@@ -67,6 +67,38 @@ function getGlobalDialogMutex(dialogId) {
67
67
  function compareVisibleReminderTargetOrder(a, b) {
68
68
  return (0, tool_1.compareReminderDisplayOrder)(a.reminder, b.reminder);
69
69
  }
70
+ function buildSubdialogAssignmentPromptMeta(subdialog) {
71
+ const assignment = subdialog.assignmentFromSup;
72
+ switch (assignment.callName) {
73
+ case 'tellask':
74
+ return {
75
+ tellaskReplyDirective: {
76
+ expectedReplyCallName: 'replyTellask',
77
+ targetCallId: assignment.callId,
78
+ tellaskContent: assignment.tellaskContent,
79
+ },
80
+ subdialogReplyTarget: {
81
+ ownerDialogId: assignment.callerDialogId,
82
+ callType: 'B',
83
+ callId: assignment.callId,
84
+ },
85
+ };
86
+ case 'tellaskSessionless':
87
+ case 'freshBootsReasoning':
88
+ return {
89
+ tellaskReplyDirective: {
90
+ expectedReplyCallName: 'replyTellaskSessionless',
91
+ targetCallId: assignment.callId,
92
+ tellaskContent: assignment.tellaskContent,
93
+ },
94
+ subdialogReplyTarget: {
95
+ ownerDialogId: assignment.callerDialogId,
96
+ callType: 'C',
97
+ callId: assignment.callId,
98
+ },
99
+ };
100
+ }
101
+ }
70
102
  /**
71
103
  * Abstract base class for all dialog types.
72
104
  * Contains common properties and methods shared between RootDialog and SubDialog.
@@ -132,6 +164,9 @@ class Dialog {
132
164
  this._lastUserLanguageCode = (0, work_language_1.getWorkLanguage)();
133
165
  this._lastContextHealth = initialState?.contextHealth;
134
166
  this._lastContextHealthGenseq = undefined;
167
+ if (initialState?.pendingCourseStartPrompt) {
168
+ this.setNewCourseStartPrompt(initialState.pendingCourseStartPrompt);
169
+ }
135
170
  this.resetCourseLanguageNotice();
136
171
  }
137
172
  setLastContextHealth(snapshot) {
@@ -844,6 +879,7 @@ class Dialog {
844
879
  grammar: 'markdown',
845
880
  userLanguageCode: this._lastUserLanguageCode,
846
881
  origin: 'runtime',
882
+ ...(this instanceof SubDialog ? buildSubdialogAssignmentPromptMeta(this) : {}),
847
883
  };
848
884
  const runControlSpec = options?.runControl ?? this._activeRunControlSpec;
849
885
  let nextPrompt = basePrompt;
@@ -863,7 +899,7 @@ class Dialog {
863
899
  await this.dlgStore.clearQuestions4Human(this);
864
900
  // Delegate to DialogStore for course start persistence
865
901
  if (this.dlgStore) {
866
- await this.dlgStore.startNewCourse(this, nextPrompt.content);
902
+ await this.dlgStore.startNewCourse(this, nextPrompt);
867
903
  }
868
904
  const storeCourse = this.dlgStore
869
905
  ? await this.dlgStore.loadCurrentCourse(this.id)
@@ -1465,6 +1465,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1465
1465
  content: replyGuidance.promptContent,
1466
1466
  });
1467
1467
  await dlg.persistUserMessage(replyGuidance.promptContent, currentPrompt.msgId, 'markdown', origin, persistedUserLanguageCode, q4hAnswerCallId, replyGuidance.persistedTellaskReplyDirective);
1468
+ await persistence_1.DialogPersistence.clearPendingCourseStartPrompt(dlg.id, currentPrompt.msgId, dlg.status);
1468
1469
  }
1469
1470
  if (renderPromptAsRuntimeGuideBubble) {
1470
1471
  (0, evt_registry_1.postDialogEvent)(dlg, {
@@ -6,6 +6,7 @@ const run_control_1 = require("../../apps/run-control");
6
6
  const dialog_1 = require("../../dialog");
7
7
  const dialog_display_state_1 = require("../../dialog-display-state");
8
8
  const dialog_global_registry_1 = require("../../dialog-global-registry");
9
+ const dialog_interruption_1 = require("../../dialog-interruption");
9
10
  const evt_registry_1 = require("../../evt-registry");
10
11
  const log_1 = require("../../log");
11
12
  const load_1 = require("../../minds/load");
@@ -415,6 +416,7 @@ async function executeDriveRound(args) {
415
416
  if (latest &&
416
417
  latest.executionMarker &&
417
418
  latest.executionMarker.kind === 'interrupted' &&
419
+ (0, dialog_interruption_1.doesInterruptionReasonRequireExplicitResume)(latest.executionMarker.reason) &&
418
420
  !allowResumeFromInterrupted) {
419
421
  log_1.log.debug('kernel-driver skip drive for interrupted dialog without explicit resume/user prompt', undefined, {
420
422
  dialogId: dialog.id.valueOf(),
@@ -473,7 +475,7 @@ async function executeDriveRound(args) {
473
475
  // `allowResumeFromInterrupted` covers multiple stop reasons, but the interjection-pause case
474
476
  // is semantically special. Clicking Continue here does NOT mean "blindly clear stopped and
475
477
  // drive". We must re-read the fresh persistence facts first because there are three distinct
476
- // true-source cases behind the same visible stopped panel:
478
+ // true-source cases behind the same visible resumption panel:
477
479
  // - no active reply obligation / not suspended anymore -> continue real driving now
478
480
  // - active reply obligation + suspended -> restore true blocked state
479
481
  // - active reply obligation + still proceeding entitlement (for example queued upNext) ->
@@ -634,10 +636,10 @@ async function executeDriveRound(args) {
634
636
  dlg: dialog,
635
637
  prompt: effectivePrompt,
636
638
  });
637
- // Only park into the special interjection stopped-panel state when this user turn has
639
+ // Only park into the special interjection resumption-panel state when this user turn has
638
640
  // suppressed a still-pending inter-dialog reply obligation that must be reasserted later.
639
641
  // User interjections without a parked original task should simply finish and fall back to the
640
- // dialog's true underlying state, without showing the special stopped panel.
642
+ // dialog's true underlying state, without showing the special resumption panel.
641
643
  //
642
644
  // Q4H answers are explicitly outside this branch even though they also come from the human.
643
645
  // They belong to the askHuman reply channel and must continue the suspended askHuman round,
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runBackendDriver = runBackendDriver;
4
4
  const dialog_display_state_1 = require("../../dialog-display-state");
5
5
  const dialog_global_registry_1 = require("../../dialog-global-registry");
6
+ const dialog_interruption_1 = require("../../dialog-interruption");
6
7
  const log_1 = require("../../log");
7
8
  const persistence_1 = require("../../persistence");
8
9
  const engine_1 = require("./engine");
@@ -25,10 +26,12 @@ async function driveQueuedDialogsOnce() {
25
26
  const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialog.id, 'running');
26
27
  const executionMarker = latest?.executionMarker;
27
28
  const stopRequested = (0, dialog_display_state_1.getStopRequestedReason)(rootDialog.id);
28
- if (executionMarker?.kind === 'interrupted' || stopRequested !== undefined) {
29
+ const interruptedRequiresExplicitResume = executionMarker?.kind === 'interrupted' &&
30
+ (0, dialog_interruption_1.doesInterruptionReasonRequireExplicitResume)(executionMarker.reason);
31
+ if (interruptedRequiresExplicitResume || stopRequested !== undefined) {
29
32
  dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId, {
30
33
  source: 'kernel_driver_backend_loop',
31
- reason: executionMarker?.kind === 'interrupted'
34
+ reason: interruptedRequiresExplicitResume
32
35
  ? 'execution_marker_blocked:interrupted'
33
36
  : `stop_requested:${stopRequested}`,
34
37
  });
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import type { ContextHealthSnapshot } from '@longrun-ai/kernel/types/context-health';
8
8
  import type { NativeToolCallPayload, WebSearchCallAction, WebSearchCallSource } from '@longrun-ai/kernel/types/dialog';
9
+ import type { DialogPrompt } from '@longrun-ai/kernel/types/drive-intent';
9
10
  import type { LanguageCode } from '@longrun-ai/kernel/types/language';
10
11
  import type { DialogLatestFile, DialogMetadataFile, HumanQuestion, PendingSubdialogStateRecord, PersistedDialogRecord, ProviderData, ReasoningPayload, ReconciledRecordWriteTarget, RootDialogMetadataFile, RootGenerationAnchor, SubdialogMetadataFile, SubdialogRegistryStateRecord, SubdialogResponseStateRecord, TellaskCallRecordName, TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
11
12
  import type { DialogsQuarantinedMessage, DialogStatusKind } from '@longrun-ai/kernel/types/wire';
@@ -126,7 +127,7 @@ export declare class DiskFileDialogStore extends DialogStore {
126
127
  /**
127
128
  * Start new course (append-only JSONL + exceptional reminder persistence)
128
129
  */
129
- startNewCourse(dialog: Dialog, _newCoursePrompt: string): Promise<void>;
130
+ startNewCourse(dialog: Dialog, newCoursePrompt: DialogPrompt): Promise<void>;
130
131
  /**
131
132
  * Persist reminder state (exceptional overwrite pattern)
132
133
  * Note: Event emission is handled by processReminderUpdates() in Dialog
@@ -561,6 +562,7 @@ export declare class DialogPersistence {
561
562
  private static flushLatestWriteBack;
562
563
  static setNeedsDrive(dialogId: DialogID, needsDrive: boolean, status?: DialogStatusKind): Promise<void>;
563
564
  static getNeedsDrive(dialogId: DialogID, status?: DialogStatusKind): Promise<boolean>;
565
+ static clearPendingCourseStartPrompt(dialogId: DialogID, msgId: string, status?: DialogStatusKind): Promise<void>;
564
566
  static setDeferredReplyReassertion(dialogId: DialogID, deferredReplyReassertion: DialogLatestFile['deferredReplyReassertion'], status?: DialogStatusKind): Promise<void>;
565
567
  static getDeferredReplyReassertion(dialogId: DialogID, status?: DialogStatusKind): Promise<DialogLatestFile['deferredReplyReassertion']>;
566
568
  /**
@@ -311,6 +311,8 @@ function parseDialogInterruptionReason(value) {
311
311
  return { kind: 'emergency_stop' };
312
312
  case 'server_restart':
313
313
  return { kind: 'server_restart' };
314
+ case 'pending_course_start':
315
+ return { kind: 'pending_course_start' };
314
316
  case 'fork_continue_ready':
315
317
  return { kind: 'fork_continue_ready' };
316
318
  case 'system_stop': {
@@ -837,6 +839,104 @@ function isSubdialogMetadataFile(value) {
837
839
  function isDialogMetadataFile(value) {
838
840
  return isRootDialogMetadataFile(value) || isSubdialogMetadataFile(value);
839
841
  }
842
+ function parseTellaskReplyDirective(value) {
843
+ if (!isRecord(value))
844
+ return null;
845
+ const expectedReplyCallName = value.expectedReplyCallName;
846
+ const targetCallId = value.targetCallId;
847
+ const tellaskContent = value.tellaskContent;
848
+ if (expectedReplyCallName !== 'replyTellask' &&
849
+ expectedReplyCallName !== 'replyTellaskSessionless' &&
850
+ expectedReplyCallName !== 'replyTellaskBack') {
851
+ return null;
852
+ }
853
+ if (typeof targetCallId !== 'string' || typeof tellaskContent !== 'string') {
854
+ return null;
855
+ }
856
+ if (expectedReplyCallName === 'replyTellaskBack') {
857
+ const targetDialogId = value.targetDialogId;
858
+ if (typeof targetDialogId !== 'string')
859
+ return null;
860
+ return {
861
+ expectedReplyCallName,
862
+ targetCallId,
863
+ targetDialogId,
864
+ tellaskContent,
865
+ };
866
+ }
867
+ return {
868
+ expectedReplyCallName,
869
+ targetCallId,
870
+ tellaskContent,
871
+ };
872
+ }
873
+ function parseDialogSubdialogReplyTarget(value) {
874
+ if (!isRecord(value))
875
+ return null;
876
+ const ownerDialogId = value.ownerDialogId;
877
+ const callType = value.callType;
878
+ const callId = value.callId;
879
+ if (typeof ownerDialogId !== 'string' || typeof callId !== 'string') {
880
+ return null;
881
+ }
882
+ if (callType !== 'A' && callType !== 'B' && callType !== 'C') {
883
+ return null;
884
+ }
885
+ return {
886
+ ownerDialogId,
887
+ callType,
888
+ callId,
889
+ };
890
+ }
891
+ function parseDialogPendingCourseStartPrompt(value) {
892
+ if (!isRecord(value))
893
+ return null;
894
+ if (typeof value.content !== 'string' || typeof value.msgId !== 'string') {
895
+ return null;
896
+ }
897
+ if (value.grammar !== 'markdown' || value.origin !== 'runtime') {
898
+ return null;
899
+ }
900
+ const userLanguageCodeRaw = value.userLanguageCode;
901
+ if (userLanguageCodeRaw !== undefined &&
902
+ (typeof userLanguageCodeRaw !== 'string' || !(0, language_1.isLanguageCode)(userLanguageCodeRaw))) {
903
+ return null;
904
+ }
905
+ const skipTaskdocRaw = value.skipTaskdoc;
906
+ if (skipTaskdocRaw !== undefined && typeof skipTaskdocRaw !== 'boolean') {
907
+ return null;
908
+ }
909
+ const tellaskReplyDirective = value.tellaskReplyDirective === undefined
910
+ ? undefined
911
+ : parseTellaskReplyDirective(value.tellaskReplyDirective);
912
+ if (value.tellaskReplyDirective !== undefined && tellaskReplyDirective === null) {
913
+ return null;
914
+ }
915
+ const subdialogReplyTarget = value.subdialogReplyTarget === undefined
916
+ ? undefined
917
+ : parseDialogSubdialogReplyTarget(value.subdialogReplyTarget);
918
+ if (value.subdialogReplyTarget !== undefined && subdialogReplyTarget === null) {
919
+ return null;
920
+ }
921
+ const userLanguageCode = userLanguageCodeRaw;
922
+ const skipTaskdoc = skipTaskdocRaw;
923
+ const normalizedTellaskReplyDirective = tellaskReplyDirective === null ? undefined : tellaskReplyDirective;
924
+ const normalizedSubdialogReplyTarget = subdialogReplyTarget === null ? undefined : subdialogReplyTarget;
925
+ return {
926
+ content: value.content,
927
+ msgId: value.msgId,
928
+ grammar: 'markdown',
929
+ origin: 'runtime',
930
+ ...(userLanguageCode === undefined ? {} : { userLanguageCode }),
931
+ ...(normalizedTellaskReplyDirective === undefined
932
+ ? {}
933
+ : { tellaskReplyDirective: normalizedTellaskReplyDirective }),
934
+ ...(skipTaskdoc === undefined ? {} : { skipTaskdoc }),
935
+ ...(normalizedSubdialogReplyTarget === undefined
936
+ ? {}
937
+ : { subdialogReplyTarget: normalizedSubdialogReplyTarget }),
938
+ };
939
+ }
840
940
  function parseDialogLatestFile(value) {
841
941
  if (!isRecord(value))
842
942
  return null;
@@ -1006,48 +1106,16 @@ function parseDialogLatestFile(value) {
1006
1106
  if (deferredReplyReassertionRaw.reason !== 'user_interjection_with_parked_original_task') {
1007
1107
  return null;
1008
1108
  }
1009
- const directiveRaw = deferredReplyReassertionRaw.directive;
1010
- if (!isRecord(directiveRaw))
1109
+ const directive = parseTellaskReplyDirective(deferredReplyReassertionRaw.directive);
1110
+ if (directive === null)
1011
1111
  return null;
1012
1112
  const resumeGuideSurfacedRaw = deferredReplyReassertionRaw.resumeGuideSurfaced;
1013
1113
  if (resumeGuideSurfacedRaw !== undefined && typeof resumeGuideSurfacedRaw !== 'boolean') {
1014
1114
  return null;
1015
1115
  }
1016
- const expectedReplyCallName = directiveRaw.expectedReplyCallName;
1017
- const targetCallId = directiveRaw.targetCallId;
1018
- const tellaskContent = directiveRaw.tellaskContent;
1019
- if (expectedReplyCallName !== 'replyTellask' &&
1020
- expectedReplyCallName !== 'replyTellaskSessionless' &&
1021
- expectedReplyCallName !== 'replyTellaskBack') {
1022
- return null;
1023
- }
1024
- if (typeof targetCallId !== 'string' || typeof tellaskContent !== 'string') {
1025
- return null;
1026
- }
1027
- if (expectedReplyCallName === 'replyTellaskBack') {
1028
- const targetDialogId = directiveRaw.targetDialogId;
1029
- if (typeof targetDialogId !== 'string')
1030
- return null;
1031
- return {
1032
- reason: 'user_interjection_with_parked_original_task',
1033
- directive: {
1034
- expectedReplyCallName,
1035
- targetCallId,
1036
- targetDialogId,
1037
- tellaskContent,
1038
- },
1039
- ...(resumeGuideSurfacedRaw === undefined
1040
- ? {}
1041
- : { resumeGuideSurfaced: resumeGuideSurfacedRaw }),
1042
- };
1043
- }
1044
1116
  return {
1045
1117
  reason: 'user_interjection_with_parked_original_task',
1046
- directive: {
1047
- expectedReplyCallName,
1048
- targetCallId,
1049
- tellaskContent,
1050
- },
1118
+ directive,
1051
1119
  ...(resumeGuideSurfacedRaw === undefined
1052
1120
  ? {}
1053
1121
  : { resumeGuideSurfaced: resumeGuideSurfacedRaw }),
@@ -1055,6 +1123,14 @@ function parseDialogLatestFile(value) {
1055
1123
  })();
1056
1124
  if (deferredReplyReassertion === null)
1057
1125
  return null;
1126
+ const pendingCourseStartPromptRaw = value.pendingCourseStartPrompt;
1127
+ const pendingCourseStartPrompt = (() => {
1128
+ if (pendingCourseStartPromptRaw === undefined)
1129
+ return undefined;
1130
+ return parseDialogPendingCourseStartPrompt(pendingCourseStartPromptRaw);
1131
+ })();
1132
+ if (pendingCourseStartPrompt === null)
1133
+ return null;
1058
1134
  return {
1059
1135
  currentCourse,
1060
1136
  lastModified: value.lastModified,
@@ -1068,6 +1144,7 @@ function parseDialogLatestFile(value) {
1068
1144
  executionMarker,
1069
1145
  fbrState,
1070
1146
  deferredReplyReassertion,
1147
+ pendingCourseStartPrompt,
1071
1148
  disableDiligencePush: value.disableDiligencePush,
1072
1149
  diligencePushRemainingBudget: value.diligencePushRemainingBudget,
1073
1150
  };
@@ -2070,16 +2147,49 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
2070
2147
  /**
2071
2148
  * Start new course (append-only JSONL + exceptional reminder persistence)
2072
2149
  */
2073
- async startNewCourse(dialog, _newCoursePrompt) {
2150
+ async startNewCourse(dialog, newCoursePrompt) {
2074
2151
  const previousCourse = dialog.currentCourse;
2075
2152
  const newCourse = previousCourse + 1;
2153
+ if (newCoursePrompt.origin !== 'runtime') {
2154
+ throw new Error(`startNewCourse invariant violation: pending new-course prompt must have runtime origin for dialog=${dialog.id.valueOf()}`);
2155
+ }
2076
2156
  // Persist reminders state for new course (exceptional overwrite)
2077
2157
  // Use the currently attached dialog's reminders to avoid stale state
2078
2158
  await this.persistReminders(dialog, dialog.reminders || []);
2079
2159
  // Update latest.yaml with new course (lastModified is set by persistence layer)
2080
2160
  await DialogPersistence.mutateDialogLatest(this.dialogId, () => ({
2081
2161
  kind: 'patch',
2082
- patch: { currentCourse: newCourse },
2162
+ patch: {
2163
+ currentCourse: newCourse,
2164
+ needsDrive: true,
2165
+ displayState: {
2166
+ kind: 'stopped',
2167
+ reason: { kind: 'pending_course_start' },
2168
+ continueEnabled: true,
2169
+ },
2170
+ executionMarker: {
2171
+ kind: 'interrupted',
2172
+ reason: { kind: 'pending_course_start' },
2173
+ },
2174
+ pendingCourseStartPrompt: {
2175
+ content: newCoursePrompt.content,
2176
+ msgId: newCoursePrompt.msgId,
2177
+ grammar: 'markdown',
2178
+ origin: 'runtime',
2179
+ ...(newCoursePrompt.userLanguageCode === undefined
2180
+ ? {}
2181
+ : { userLanguageCode: newCoursePrompt.userLanguageCode }),
2182
+ ...(newCoursePrompt.tellaskReplyDirective === undefined
2183
+ ? {}
2184
+ : { tellaskReplyDirective: newCoursePrompt.tellaskReplyDirective }),
2185
+ ...(newCoursePrompt.skipTaskdoc === undefined
2186
+ ? {}
2187
+ : { skipTaskdoc: newCoursePrompt.skipTaskdoc }),
2188
+ ...(newCoursePrompt.subdialogReplyTarget === undefined
2189
+ ? {}
2190
+ : { subdialogReplyTarget: newCoursePrompt.subdialogReplyTarget }),
2191
+ },
2192
+ },
2083
2193
  }));
2084
2194
  // Post course update event
2085
2195
  const courseUpdateEvt = {
@@ -5778,6 +5888,33 @@ class DialogPersistence {
5778
5888
  const latest = await this.loadDialogLatest(dialogId, status);
5779
5889
  return latest?.needsDrive === true;
5780
5890
  }
5891
+ static async clearPendingCourseStartPrompt(dialogId, msgId, status = 'running') {
5892
+ const normalizedMsgId = msgId.trim();
5893
+ if (normalizedMsgId === '') {
5894
+ throw new Error(`clearPendingCourseStartPrompt invariant violation: empty msgId for dialog=${dialogId.valueOf()}`);
5895
+ }
5896
+ await this.mutateDialogLatest(dialogId, (previous) => {
5897
+ const pending = previous.pendingCourseStartPrompt;
5898
+ if (!pending || pending.msgId !== normalizedMsgId) {
5899
+ return { kind: 'noop' };
5900
+ }
5901
+ return {
5902
+ kind: 'patch',
5903
+ patch: {
5904
+ pendingCourseStartPrompt: undefined,
5905
+ needsDrive: false,
5906
+ displayState: previous.displayState?.kind === 'stopped' &&
5907
+ previous.displayState.reason.kind === 'pending_course_start'
5908
+ ? { kind: 'idle_waiting_user' }
5909
+ : previous.displayState,
5910
+ executionMarker: previous.executionMarker?.kind === 'interrupted' &&
5911
+ previous.executionMarker.reason.kind === 'pending_course_start'
5912
+ ? undefined
5913
+ : previous.executionMarker,
5914
+ },
5915
+ };
5916
+ }, status);
5917
+ }
5781
5918
  static async setDeferredReplyReassertion(dialogId, deferredReplyReassertion, status = 'running') {
5782
5919
  await this.mutateDialogLatest(dialogId, () => ({ kind: 'patch', patch: { deferredReplyReassertion } }), status);
5783
5920
  }
@@ -10,7 +10,7 @@ const USER_INTERJECTION_PAUSE_STOP_DETAIL = 'user_interjection_pause_resume_orig
10
10
  //
11
11
  // Not every user interjection should use this reason. If there is no parked original task to
12
12
  // resume afterwards, the interjection should simply complete and the dialog should fall back to
13
- // its true underlying state without showing this stopped panel.
13
+ // its true underlying state without showing this resumption panel.
14
14
  //
15
15
  // In particular, askHuman answers are NOT "user interjections" for this purpose. A prompt carrying
16
16
  // a real `q4hAnswerCallId` belongs to the askHuman reply channel and must never be routed through
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dominds",
3
- "version": "1.16.10",
3
+ "version": "1.17.0",
4
4
  "description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
5
5
  "type": "commonjs",
6
6
  "publishConfig": {
@@ -52,9 +52,9 @@
52
52
  "ws": "^8.19.0",
53
53
  "yaml": "^2.8.2",
54
54
  "zod": "^4.3.6",
55
- "@longrun-ai/shell": "1.8.14",
56
- "@longrun-ai/kernel": "1.8.14",
57
- "@longrun-ai/codex-auth": "0.12.1"
55
+ "@longrun-ai/shell": "1.8.15",
56
+ "@longrun-ai/codex-auth": "0.12.1",
57
+ "@longrun-ai/kernel": "1.8.15"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^25.3.5",