dominds 1.24.3 → 1.24.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.
@@ -98,9 +98,6 @@ async function resolveTargetDialog(sourceDlg, target) {
98
98
  matches.push(dialog);
99
99
  };
100
100
  pushMatch(await ensureDialogLoadedBySelfId(sourceRoot, target.dialogId));
101
- for (const loadedRoot of dialog_global_registry_1.globalDialogRegistry.getAll()) {
102
- pushMatch(await ensureDialogLoadedBySelfId(loadedRoot, target.dialogId));
103
- }
104
101
  if (target.dialogId !== sourceRoot.id.rootId) {
105
102
  pushMatch(await ensureMainDialogLoaded(target.dialogId));
106
103
  }
@@ -255,10 +255,12 @@ function clearActiveRun(dialogId, options) {
255
255
  return;
256
256
  }
257
257
  clearQuarantiningMainDialogIfIdle(dialogId.rootId);
258
- if (dialogId.selfId === dialogId.rootId && options?.notifyBackendLoop !== false) {
258
+ if (options?.notifyBackendLoop !== false) {
259
259
  dialog_global_registry_1.globalDialogRegistry.notifyActiveRunCleared(dialogId.rootId, {
260
260
  source: 'dialog_display_state_active_run_clear',
261
- reason: 'root_active_run_cleared',
261
+ reason: dialogId.selfId === dialogId.rootId
262
+ ? 'root_active_run_cleared'
263
+ : 'sideDialog_active_run_cleared',
262
264
  });
263
265
  }
264
266
  syncRunControlCountsAfterActiveRunChange('clear_active_run', dialogId);
@@ -16,7 +16,18 @@ export type DriveTriggerMeta = Readonly<{
16
16
  }>;
17
17
  declare class GlobalDialogRegistry {
18
18
  private static instance;
19
+ /**
20
+ * Runtime-owned roots keyed by rootId.
21
+ *
22
+ * Do not add an API that enumerates this map for backend driving. A dialog becomes driveable only
23
+ * through an explicit business/runtime wake (`wakeDrive`, result arrival, active-run clear, etc.).
24
+ * Reintroducing "scan every loaded root and see what happens" makes hidden polling loops easy to
25
+ * create and obscures the business event that should own the next action.
26
+ */
19
27
  private readonly entries;
28
+ private readonly queuedRootIds;
29
+ private readonly queuedRootIdSet;
30
+ private queuedRootIdReadIndex;
20
31
  private readonly lastDriveTriggerByRootId;
21
32
  private readonly driveTriggerPubChan;
22
33
  private driveTriggerSubChan;
@@ -24,6 +35,9 @@ declare class GlobalDialogRegistry {
24
35
  get(rootId: string): MainDialog | undefined;
25
36
  register(mainDialog: MainDialog): void;
26
37
  unregister(rootId: string): void;
38
+ private enqueueRoot;
39
+ private compactQueuedRootsIfNeeded;
40
+ private compactSparseQueuedRootsIfNeeded;
27
41
  private publishDriveTrigger;
28
42
  waitForDriveTrigger(): Promise<DriveTriggerEvent>;
29
43
  wakeDrive(rootId: string, meta?: DriveTriggerMeta): void;
@@ -33,7 +47,7 @@ declare class GlobalDialogRegistry {
33
47
  hasPendingActiveRunClearedWake(rootId: string): boolean;
34
48
  isDriveWakeQueued(rootId: string): boolean;
35
49
  getLastDriveTrigger(rootId: string): DriveTriggerEvent | undefined;
36
- getAll(): MainDialog[];
50
+ consumeQueuedMainDialogs(): MainDialog[];
37
51
  get size(): number;
38
52
  }
39
53
  export declare const globalDialogRegistry: GlobalDialogRegistry;
@@ -8,7 +8,18 @@ const persistence_1 = require("./persistence");
8
8
  const log = (0, log_1.createLogger)('dialog-global-registry');
9
9
  class GlobalDialogRegistry {
10
10
  constructor() {
11
+ /**
12
+ * Runtime-owned roots keyed by rootId.
13
+ *
14
+ * Do not add an API that enumerates this map for backend driving. A dialog becomes driveable only
15
+ * through an explicit business/runtime wake (`wakeDrive`, result arrival, active-run clear, etc.).
16
+ * Reintroducing "scan every loaded root and see what happens" makes hidden polling loops easy to
17
+ * create and obscures the business event that should own the next action.
18
+ */
11
19
  this.entries = new Map();
20
+ this.queuedRootIds = [];
21
+ this.queuedRootIdSet = new Set();
22
+ this.queuedRootIdReadIndex = 0;
12
23
  this.lastDriveTriggerByRootId = new Map();
13
24
  this.driveTriggerPubChan = (0, evt_1.createPubChan)();
14
25
  this.driveTriggerSubChan = (0, evt_1.createSubChan)(this.driveTriggerPubChan);
@@ -60,9 +71,45 @@ class GlobalDialogRegistry {
60
71
  }
61
72
  unregister(rootId) {
62
73
  this.entries.delete(rootId);
74
+ this.queuedRootIdSet.delete(rootId);
63
75
  this.lastDriveTriggerByRootId.delete(rootId);
64
76
  (0, dialog_1.scheduleGlobalDialogMutexCleanupForRoot)(rootId);
65
77
  }
78
+ enqueueRoot(rootId) {
79
+ if (this.queuedRootIdSet.has(rootId)) {
80
+ return;
81
+ }
82
+ this.queuedRootIdSet.add(rootId);
83
+ this.queuedRootIds.push(rootId);
84
+ }
85
+ compactQueuedRootsIfNeeded() {
86
+ if (this.queuedRootIdReadIndex === 0) {
87
+ return;
88
+ }
89
+ if (this.queuedRootIdReadIndex < 256 &&
90
+ this.queuedRootIdReadIndex * 2 < this.queuedRootIds.length) {
91
+ return;
92
+ }
93
+ this.queuedRootIds.splice(0, this.queuedRootIdReadIndex);
94
+ this.queuedRootIdReadIndex = 0;
95
+ }
96
+ compactSparseQueuedRootsIfNeeded() {
97
+ if (this.queuedRootIds.length < 512) {
98
+ return;
99
+ }
100
+ if (this.queuedRootIdSet.size * 2 >= this.queuedRootIds.length - this.queuedRootIdReadIndex) {
101
+ return;
102
+ }
103
+ const compacted = [];
104
+ for (let index = this.queuedRootIdReadIndex; index < this.queuedRootIds.length; index += 1) {
105
+ const rootId = this.queuedRootIds[index];
106
+ if (rootId !== undefined && this.queuedRootIdSet.has(rootId)) {
107
+ compacted.push(rootId);
108
+ }
109
+ }
110
+ this.queuedRootIds.splice(0, this.queuedRootIds.length, ...compacted);
111
+ this.queuedRootIdReadIndex = 0;
112
+ }
66
113
  publishDriveTrigger(args) {
67
114
  const trigger = {
68
115
  type: 'drive_trigger_evt',
@@ -99,6 +146,7 @@ class GlobalDialogRegistry {
99
146
  entry.wakeQueued = true;
100
147
  // A fresh queueing trigger supersedes any earlier "wake me once active run clears" debt.
101
148
  entry.activeRunClearedWakePending = false;
149
+ this.enqueueRoot(rootId);
102
150
  }
103
151
  this.publishDriveTrigger({
104
152
  action: 'wake_drive',
@@ -119,6 +167,8 @@ class GlobalDialogRegistry {
119
167
  if (entry) {
120
168
  entry.wakeQueued = false;
121
169
  entry.activeRunClearedWakePending = false;
170
+ this.queuedRootIdSet.delete(rootId);
171
+ this.compactSparseQueuedRootsIfNeeded();
122
172
  }
123
173
  this.publishDriveTrigger({
124
174
  action: 'clear_drive_wake',
@@ -138,12 +188,14 @@ class GlobalDialogRegistry {
138
188
  if (!entry) {
139
189
  return;
140
190
  }
141
- if (!entry.activeRunClearedWakePending || !entry.wakeQueued) {
191
+ if (!entry.activeRunClearedWakePending) {
142
192
  entry.activeRunClearedWakePending = false;
143
193
  return;
144
194
  }
145
- const currentWakeQueued = entry ? entry.wakeQueued : null;
195
+ const currentWakeQueued = entry.wakeQueued;
146
196
  entry.activeRunClearedWakePending = false;
197
+ entry.wakeQueued = true;
198
+ this.enqueueRoot(rootId);
147
199
  this.publishDriveTrigger({
148
200
  action: 'active_run_cleared',
149
201
  rootId,
@@ -155,7 +207,7 @@ class GlobalDialogRegistry {
155
207
  }
156
208
  noteActiveRunBlockedQueuedDrive(rootId) {
157
209
  const entry = this.entries.get(rootId);
158
- if (!entry || !entry.wakeQueued) {
210
+ if (!entry) {
159
211
  return;
160
212
  }
161
213
  entry.activeRunClearedWakePending = true;
@@ -169,8 +221,24 @@ class GlobalDialogRegistry {
169
221
  getLastDriveTrigger(rootId) {
170
222
  return this.lastDriveTriggerByRootId.get(rootId);
171
223
  }
172
- getAll() {
173
- return Array.from(this.entries.values()).map((entry) => entry.mainDialog);
224
+ consumeQueuedMainDialogs() {
225
+ const queued = [];
226
+ while (this.queuedRootIdReadIndex < this.queuedRootIds.length) {
227
+ const rootId = this.queuedRootIds[this.queuedRootIdReadIndex];
228
+ this.queuedRootIdReadIndex += 1;
229
+ if (rootId === undefined || !this.queuedRootIdSet.has(rootId)) {
230
+ continue;
231
+ }
232
+ this.queuedRootIdSet.delete(rootId);
233
+ const entry = this.entries.get(rootId);
234
+ if (!entry) {
235
+ continue;
236
+ }
237
+ entry.wakeQueued = false;
238
+ queued.push(entry.mainDialog);
239
+ }
240
+ this.compactQueuedRootsIfNeeded();
241
+ return queued;
174
242
  }
175
243
  get size() {
176
244
  return this.entries.size;
package/dist/dialog.d.ts CHANGED
@@ -16,7 +16,7 @@ import type { ContextHealthSnapshot } from '@longrun-ai/kernel/types/context-hea
16
16
  import type { DialogEvent, NativeToolCallPayload, ReminderContent, WebSearchCallAction, WebSearchCallSource } from '@longrun-ai/kernel/types/dialog';
17
17
  import type { DialogCalleeReplyTarget, DialogQueuedDeferredQ4HAnswerState, DialogQueuedPromptState, DialogQueuedUserGenerationBoundaryState, DialogRunControlSpec, DialogRuntimePrompt, DialogUserPrompt, DriveIntent } from '@longrun-ai/kernel/types/drive-intent';
18
18
  import type { LanguageCode } from '@longrun-ai/kernel/types/language';
19
- import type { ActiveCalleesFile, CalleeCourseNumber, CalleeGenerationSeqNumber, CallSiteCourseNo, CallSiteGenseqNo, DialogAskerStackState, DialogLatestFile, DialogMetadataFile, HumanQuestion, ProviderData, ReasoningPayload, TellaskCallRecordName, TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
19
+ import type { ActiveCalleesFile, CalleeCourseNumber, CalleeGenerationSeqNumber, CallSiteCourseNo, CallSiteGenseqNo, DialogAskerStackState, DialogLatestFile, DialogMetadataFile, DialogNextStepTrigger, HumanQuestion, ProviderData, ReasoningPayload, TellaskCallRecordName, TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
20
20
  import { ChatMessage, FuncResultMsg, TellaskCarryoverMsg, TellaskResultMsg } from './llm/client';
21
21
  import type { ToolResultImageIngest, UserImageIngest } from './llm/gen';
22
22
  import type { JsonValue } from './tool';
@@ -413,7 +413,7 @@ export declare abstract class Dialog {
413
413
  calleeCourse?: CalleeCourseNumber;
414
414
  calleeGenseq?: CalleeGenerationSeqNumber;
415
415
  }): Promise<TellaskResultMsg | TellaskCarryoverMsg>;
416
- notifyGeneratingStart(msgId?: string): Promise<void>;
416
+ notifyGeneratingStart(msgId?: string): Promise<readonly DialogNextStepTrigger[]>;
417
417
  notifyGeneratingFinish(contextHealth?: ContextHealthSnapshot, llmGenModel?: string): Promise<void>;
418
418
  streamError(error: string): Promise<void>;
419
419
  thinkingStart(): Promise<void>;
@@ -600,7 +600,7 @@ export declare abstract class DialogStore {
600
600
  /**
601
601
  * Notify start of LLM generation lifecycle (generating_start_evt)
602
602
  */
603
- notifyGeneratingStart(_dialog: Dialog, _msgId?: string): Promise<void>;
603
+ notifyGeneratingStart(_dialog: Dialog, _msgId?: string): Promise<readonly DialogNextStepTrigger[]>;
604
604
  /**
605
605
  * Notify end of LLM generation lifecycle (generating_finish_evt)
606
606
  */
package/dist/dialog.js CHANGED
@@ -1498,7 +1498,7 @@ class Dialog {
1498
1498
  // Mark generation as started with the actual genseq
1499
1499
  // This ensures sideDialog_final_response_evt waits for both user_text and generating_start_evt
1500
1500
  this.markGenerationStarted();
1501
- await this.dlgStore.notifyGeneratingStart(this, msgId);
1501
+ return this.dlgStore.notifyGeneratingStart(this, msgId);
1502
1502
  }
1503
1503
  async notifyGeneratingFinish(contextHealth, llmGenModel) {
1504
1504
  if (contextHealth) {
@@ -1958,7 +1958,9 @@ class DialogStore {
1958
1958
  /**
1959
1959
  * Notify start of LLM generation lifecycle (generating_start_evt)
1960
1960
  */
1961
- async notifyGeneratingStart(_dialog, _msgId) { }
1961
+ async notifyGeneratingStart(_dialog, _msgId) {
1962
+ return [];
1963
+ }
1962
1964
  /**
1963
1965
  * Notify end of LLM generation lifecycle (generating_finish_evt)
1964
1966
  */
@@ -67,6 +67,8 @@ const reply_prompt_copy_1 = require("../../runtime/reply-prompt-copy");
67
67
  const gen_1 = require("../gen");
68
68
  const stop_reason_i18n_1 = require("../stop-reason-i18n");
69
69
  const RUNTIME_PROMPT_WRAPPER_PREFIXES = [
70
+ '[System notice] Context state: 🔴 critical; user interjection received',
71
+ '【系统提示】 上下文状态:🔴 告急;收到用户插话',
70
72
  reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_EN,
71
73
  reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_ZH,
72
74
  reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_EN,
@@ -138,6 +138,40 @@ function buildInterruptedFuncResult(args) {
138
138
  genseq: args.callGenseq,
139
139
  };
140
140
  }
141
+ function sameDialogBusinessContinuation(left, right) {
142
+ if (left.kind !== right.kind)
143
+ return false;
144
+ switch (left.kind) {
145
+ case 'none':
146
+ return true;
147
+ case 'inter_dialog_reply': {
148
+ if (right.kind !== 'inter_dialog_reply')
149
+ return false;
150
+ return (sameTellaskReplyDirective(left.tellaskReplyDirective, right.tellaskReplyDirective) &&
151
+ sameDialogCalleeReplyTarget(left.calleeDialogReplyTarget, right.calleeDialogReplyTarget));
152
+ }
153
+ default: {
154
+ const _exhaustive = left;
155
+ throw new Error(`Unhandled business continuation kind: ${String(_exhaustive)}`);
156
+ }
157
+ }
158
+ }
159
+ function sameTellaskReplyDirective(left, right) {
160
+ return (left.expectedReplyCallName === right.expectedReplyCallName &&
161
+ left.targetDialogId === right.targetDialogId &&
162
+ left.targetCallId === right.targetCallId &&
163
+ left.tellaskContent === right.tellaskContent);
164
+ }
165
+ function sameDialogCalleeReplyTarget(left, right) {
166
+ if (left === undefined || right === undefined) {
167
+ return left === right;
168
+ }
169
+ return (left.callerDialogId === right.callerDialogId &&
170
+ left.callType === right.callType &&
171
+ left.callId === right.callId &&
172
+ left.callSiteCourse === right.callSiteCourse &&
173
+ left.callSiteGenseq === right.callSiteGenseq);
174
+ }
141
175
  function isFbrSideDialog(dlg) {
142
176
  return dlg instanceof dialog_1.SideDialog && dlg.assignmentFromAsker.callName === 'freshBootsReasoning';
143
177
  }
@@ -1171,6 +1205,7 @@ async function upsertImmediateFollowupTrigger(args) {
1171
1205
  genseq: (0, storage_1.toCallSiteGenseqNo)(genseq),
1172
1206
  },
1173
1207
  reasons,
1208
+ continuation: args.continuation,
1174
1209
  });
1175
1210
  }
1176
1211
  function shouldImmediatelyFollowUpSuccessfulToolResult(tool) {
@@ -1753,20 +1788,20 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1753
1788
  const suppressDiligencePushForDrive = driveOptions?.suppressDiligencePush === true && dlg.disableDiligencePush;
1754
1789
  const abortSignal = (0, dialog_display_state_1.getActiveRunSignal)(dlg.id) ?? (0, dialog_display_state_1.createActiveRun)(dlg.id);
1755
1790
  let finalDisplayState;
1756
- let criticalUserInterjectionRuntimeGuide = driveOptions?.criticalUserInterjectionRuntimeGuide;
1757
1791
  let lastAssistantSayingContent = null;
1758
1792
  let lastAssistantSayingGenseq = null;
1759
1793
  let lastAssistantThinkingContent = null;
1760
1794
  let lastAssistantThinkingGenseq = null;
1761
1795
  let lastFunctionCallGenseq = null;
1762
1796
  let lastAssistantReplyTarget;
1797
+ let lastBusinessContinuation = { kind: 'none' };
1763
1798
  let fbrConclusion;
1764
1799
  let pubRemindersVer = dlg.remindersVer;
1765
1800
  let pendingPrompt = humanPrompt;
1766
1801
  let resolvingImmediateToolResultForUserPrompt = false;
1767
1802
  let resolvingImmediateToolResultUserPromptMsgId;
1768
- let criticalRemediationAppliedUserPromptMsgId = driveOptions?.criticalUserInterjectionRuntimeGuide !== undefined &&
1769
- humanPrompt?.origin === 'user'
1803
+ let criticalRemediationAppliedUserPromptMsgId = humanPrompt?.origin === 'user' &&
1804
+ (0, driver_messages_1.isAgentFacingCriticalUserInterjectionRemediationGuideContent)(humanPrompt.content)
1770
1805
  ? humanPrompt.msgId
1771
1806
  : undefined;
1772
1807
  let retryStoppedRecoveryPrompt;
@@ -1901,8 +1936,10 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1901
1936
  snapshot,
1902
1937
  hadUserPromptThisGen: currentGenerationBelongsToUserPrompt,
1903
1938
  hadUserPromptInImmediateToolChain: currentGenerationBelongsToUserToolChain,
1904
- userPromptCriticalRemediationAlreadyApplied: criticalRemediationAppliedUserPromptMsgId !== undefined &&
1905
- criticalRemediationAppliedUserPromptMsgId === currentUserPromptMsgId,
1939
+ userPromptCriticalRemediationAlreadyApplied: (criticalRemediationAppliedUserPromptMsgId !== undefined &&
1940
+ criticalRemediationAppliedUserPromptMsgId === currentUserPromptMsgId) ||
1941
+ (currentPendingPrompt?.origin === 'user' &&
1942
+ (0, driver_messages_1.isAgentFacingCriticalUserInterjectionRemediationGuideContent)(currentPendingPrompt.content)),
1906
1943
  canInjectPromptThisGen: !hasQueuedUpNext,
1907
1944
  cautionRemediationCadenceGenerations,
1908
1945
  criticalCountdownRemaining,
@@ -1925,13 +1962,13 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1925
1962
  skipTaskdocForThisDrive = false;
1926
1963
  }
1927
1964
  else if (healthDecision.reason === 'critical_user_prompt_remediation') {
1928
- const language = (0, work_language_1.getWorkLanguage)();
1929
- const dialogScope = dlg instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
1930
- criticalUserInterjectionRuntimeGuide =
1931
- (0, driver_messages_1.formatAgentFacingCriticalUserInterjectionRemediationGuide)(language, {
1932
- dialogScope,
1933
- promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
1965
+ if (currentPendingPrompt === undefined ||
1966
+ !(0, driver_messages_1.isAgentFacingCriticalUserInterjectionRemediationGuideContent)(currentPendingPrompt.content)) {
1967
+ log_1.log.warn('kernel-driver observed unwrapped critical user prompt; critical user interjection wrapping must happen at ingress', undefined, {
1968
+ dialogId: dlg.id.valueOf(),
1969
+ msgId: currentUserPromptMsgId ?? null,
1934
1970
  });
1971
+ }
1935
1972
  criticalRemediationAppliedUserPromptMsgId = currentUserPromptMsgId;
1936
1973
  }
1937
1974
  else if (!hasQueuedUpNext) {
@@ -1964,6 +2001,16 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1964
2001
  let llmGenModelForGen = model;
1965
2002
  const currentPrompt = pendingPrompt;
1966
2003
  const currentReplyTarget = currentPrompt?.calleeDialogReplyTarget;
2004
+ let currentBusinessContinuation = driveOptions?.businessContinuation ?? { kind: 'none' };
2005
+ if (currentPrompt?.tellaskReplyDirective !== undefined) {
2006
+ currentBusinessContinuation = {
2007
+ kind: 'inter_dialog_reply',
2008
+ tellaskReplyDirective: currentPrompt.tellaskReplyDirective,
2009
+ ...(currentPrompt.calleeDialogReplyTarget === undefined
2010
+ ? {}
2011
+ : { calleeDialogReplyTarget: currentPrompt.calleeDialogReplyTarget }),
2012
+ };
2013
+ }
1967
2014
  const currentFbrState = await loadDialogFbrState(dlg);
1968
2015
  let currentRuntimeGuideMsg;
1969
2016
  const currentPromptFromFbrState = currentPrompt !== undefined &&
@@ -1985,12 +2032,20 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1985
2032
  break;
1986
2033
  }
1987
2034
  }
1988
- await dlg.notifyGeneratingStart(currentPrompt?.msgId);
1989
- try {
1990
- if (criticalUserInterjectionRuntimeGuide !== undefined) {
1991
- await persistAndEmitRuntimeGuide(dlg, criticalUserInterjectionRuntimeGuide);
1992
- criticalUserInterjectionRuntimeGuide = undefined;
2035
+ const acceptedTriggers = await dlg.notifyGeneratingStart(currentPrompt?.msgId);
2036
+ for (const trigger of acceptedTriggers) {
2037
+ if (trigger.kind === 'followup' && trigger.continuation !== undefined) {
2038
+ if (currentBusinessContinuation.kind !== 'none' &&
2039
+ !sameDialogBusinessContinuation(currentBusinessContinuation, trigger.continuation)) {
2040
+ throw new Error(`Business continuation invariant violation: conflicting accepted followup continuations ` +
2041
+ `(dialog=${dlg.id.valueOf()}, course=${String(dlg.activeGenCourseOrUndefined ?? dlg.currentCourse)}, ` +
2042
+ `genseq=${String(dlg.activeGenSeq)}, triggerId=${trigger.triggerId})`);
2043
+ }
2044
+ currentBusinessContinuation = trigger.continuation;
1993
2045
  }
2046
+ }
2047
+ lastBusinessContinuation = currentBusinessContinuation;
2048
+ try {
1994
2049
  if (currentPrompt) {
1995
2050
  if (currentPrompt.skipTaskdoc === true) {
1996
2051
  skipTaskdocForThisDrive = true;
@@ -2682,6 +2737,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2682
2737
  lastAssistantThinkingGenseq,
2683
2738
  lastFunctionCallGenseq,
2684
2739
  lastAssistantReplyTarget,
2740
+ lastBusinessContinuation,
2685
2741
  };
2686
2742
  }
2687
2743
  const nextFbrState = (0, fbr_1.advanceFbrState)(persistedFbrState);
@@ -2871,6 +2927,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2871
2927
  routed,
2872
2928
  invalidFuncCallCount,
2873
2929
  streamedFuncCalls,
2930
+ continuation: currentBusinessContinuation,
2874
2931
  });
2875
2932
  resolvingImmediateToolResultForUserPrompt =
2876
2933
  currentGenerationBelongsToUserPrompt ||
@@ -3023,6 +3080,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3023
3080
  lastAssistantThinkingGenseq,
3024
3081
  lastFunctionCallGenseq,
3025
3082
  lastAssistantReplyTarget,
3083
+ lastBusinessContinuation,
3026
3084
  fbrConclusion,
3027
3085
  };
3028
3086
  }
@@ -416,6 +416,9 @@ async function clearStaleSideDialogRunControlForFinalResponse(args) {
416
416
  function hasResultArrivalTrigger(latest) {
417
417
  return latest?.nextStep.triggers.some((trigger) => trigger.kind === 'result_arrival') === true;
418
418
  }
419
+ function hasFollowupNextAction(latest) {
420
+ return latest?.nextStep.triggers.some((trigger) => trigger.kind === 'followup') === true;
421
+ }
419
422
  function hasCallerReviveEntitlement(dialog, driveOptions) {
420
423
  const entitlement = driveOptions?.noPromptSideDialogResumeEntitlement;
421
424
  if (!entitlement) {
@@ -527,9 +530,11 @@ async function inspectNoPromptSideDialogDrive(args) {
527
530
  (0, dialog_drive_work_1.hasRecoverableGenerationBeyondFinalResponse)(latest);
528
531
  const resolvedPendingSideDialogReplyEntitlement = hasResolvedPendingSideDialogReplyEntitlement(args.dialog, args.driveOptions);
529
532
  const resultArrivalTriggerPresent = hasResultArrivalTrigger(latest);
533
+ const followupNextActionPresent = hasFollowupNextAction(latest);
530
534
  const supplyResponseCallerReviveAllowed = hasCallerReviveEntitlement(args.dialog, args.driveOptions) &&
531
535
  (!resolvedPendingSideDialogReplyEntitlement || resultArrivalTriggerPresent);
532
- const backendLoopDurableWorkAllowed = source === 'kernel_driver_backend_loop' && resultArrivalTriggerPresent;
536
+ const backendLoopDurableWorkAllowed = source === 'kernel_driver_backend_loop' &&
537
+ (resultArrivalTriggerPresent || followupNextActionPresent);
533
538
  const finalResponseResultArrivalReviveAllowed = sideDialogFinalResponseCallId !== undefined &&
534
539
  ((resolvedPendingSideDialogReplyEntitlement && resultArrivalTriggerPresent) ||
535
540
  backendLoopDurableWorkAllowed ||
@@ -765,8 +770,38 @@ async function executeDriveRound(args) {
765
770
  let shouldRefreshDisplayStateAfterActiveRunCleared = false;
766
771
  let followUp;
767
772
  let driveResult;
768
- let calleeDialogReplyTarget;
769
- let activeTellaskReplyDirective;
773
+ let activeBusinessContinuation = driveOptions?.businessContinuation ?? { kind: 'none' };
774
+ const replyContinuationScope = {
775
+ refresh(continuation) {
776
+ activeBusinessContinuation = continuation;
777
+ },
778
+ directive() {
779
+ switch (activeBusinessContinuation.kind) {
780
+ case 'none':
781
+ return undefined;
782
+ case 'inter_dialog_reply':
783
+ return activeBusinessContinuation.tellaskReplyDirective;
784
+ default: {
785
+ const _exhaustive = activeBusinessContinuation;
786
+ throw new Error(`Unhandled business continuation kind: ${String(_exhaustive)}`);
787
+ }
788
+ }
789
+ },
790
+ target() {
791
+ switch (activeBusinessContinuation.kind) {
792
+ case 'none':
793
+ return undefined;
794
+ case 'inter_dialog_reply':
795
+ return activeBusinessContinuation.calleeDialogReplyTarget;
796
+ default: {
797
+ const _exhaustive = activeBusinessContinuation;
798
+ throw new Error(`Unhandled business continuation kind: ${String(_exhaustive)}`);
799
+ }
800
+ }
801
+ },
802
+ };
803
+ let calleeDialogReplyTarget = replyContinuationScope.target();
804
+ let activeTellaskReplyDirective = replyContinuationScope.directive();
770
805
  let activePromptWasReplyToolReminder = false;
771
806
  let shouldPauseAfterLocalUserInterjection = false;
772
807
  let resumeFromInterjectionPause = false;
@@ -997,18 +1032,23 @@ async function executeDriveRound(args) {
997
1032
  cautionRemediationCadenceGenerations = (0, context_health_1.resolveCautionRemediationCadenceGenerations)(providerCfg?.models[model]?.caution_remediation_cadence_generations);
998
1033
  }
999
1034
  const criticalCountdownRemaining = (0, context_health_1.resolveCriticalCountdownRemaining)(dialog.id.key(), snapshot);
1035
+ const userPromptContentForHealth = humanPrompt?.origin === 'user'
1036
+ ? humanPrompt.content
1037
+ : queuedUpNextBeforeHealth?.origin === 'user'
1038
+ ? queuedUpNextBeforeHealth.prompt
1039
+ : undefined;
1000
1040
  const healthDecision = (0, context_health_1.decideKernelDriverContextHealth)({
1001
1041
  dialogKey: dialog.id.key(),
1002
1042
  snapshot,
1003
1043
  hadUserPromptThisGen: isEffectiveUserPromptForContextHealth(humanPrompt) ||
1004
1044
  (humanPrompt === undefined && isQueuedUserPromptForContextHealth(queuedUpNextBeforeHealth)),
1005
- userPromptCriticalRemediationAlreadyApplied: false,
1045
+ userPromptCriticalRemediationAlreadyApplied: userPromptContentForHealth !== undefined &&
1046
+ (0, driver_messages_1.isAgentFacingCriticalUserInterjectionRemediationGuideContent)(userPromptContentForHealth),
1006
1047
  canInjectPromptThisGen: !hasQueuedUpNext,
1007
1048
  cautionRemediationCadenceGenerations,
1008
1049
  criticalCountdownRemaining,
1009
1050
  });
1010
1051
  let healthPrompt;
1011
- let criticalUserInterjectionRuntimeGuide;
1012
1052
  if (healthDecision.kind === 'continue') {
1013
1053
  if (healthDecision.reason === 'critical_force_new_course') {
1014
1054
  const language = (0, work_language_1.getWorkLanguage)();
@@ -1021,13 +1061,17 @@ async function executeDriveRound(args) {
1021
1061
  (0, context_health_1.resetContextHealthRoundState)(dialog.id.key());
1022
1062
  }
1023
1063
  else if (healthDecision.reason === 'critical_user_prompt_remediation') {
1024
- const language = (0, work_language_1.getWorkLanguage)();
1025
- const dialogScope = dialog instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
1026
- criticalUserInterjectionRuntimeGuide =
1027
- (0, driver_messages_1.formatAgentFacingCriticalUserInterjectionRemediationGuide)(language, {
1028
- dialogScope,
1029
- promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dialog.id.key()),
1064
+ if (userPromptContentForHealth === undefined ||
1065
+ !(0, driver_messages_1.isAgentFacingCriticalUserInterjectionRemediationGuideContent)(userPromptContentForHealth)) {
1066
+ log_1.log.warn('kernel-driver observed unwrapped critical user prompt; critical user interjection wrapping must happen at ingress', undefined, {
1067
+ dialogId: dialog.id.valueOf(),
1068
+ msgId: humanPrompt?.origin === 'user'
1069
+ ? humanPrompt.msgId
1070
+ : queuedUpNextBeforeHealth?.origin === 'user'
1071
+ ? queuedUpNextBeforeHealth.msgId
1072
+ : null,
1030
1073
  });
1074
+ }
1031
1075
  }
1032
1076
  else if (!hasQueuedUpNext) {
1033
1077
  const language = (0, work_language_1.getWorkLanguage)();
@@ -1092,7 +1136,17 @@ async function executeDriveRound(args) {
1092
1136
  throw new Error(`kernel-driver upNext invariant violation: expected queued prompt ${effectivePrompt?.msgId ?? 'unknown'} before drive`);
1093
1137
  }
1094
1138
  }
1095
- calleeDialogReplyTarget = effectivePrompt?.calleeDialogReplyTarget;
1139
+ if (effectivePrompt?.tellaskReplyDirective !== undefined) {
1140
+ replyContinuationScope.refresh({
1141
+ kind: 'inter_dialog_reply',
1142
+ tellaskReplyDirective: effectivePrompt.tellaskReplyDirective,
1143
+ ...(effectivePrompt.calleeDialogReplyTarget === undefined
1144
+ ? {}
1145
+ : { calleeDialogReplyTarget: effectivePrompt.calleeDialogReplyTarget }),
1146
+ });
1147
+ }
1148
+ calleeDialogReplyTarget =
1149
+ effectivePrompt?.calleeDialogReplyTarget ?? replyContinuationScope.target();
1096
1150
  const replyGuidance = await (0, reply_guidance_1.resolvePromptReplyGuidance)({
1097
1151
  dlg: dialog,
1098
1152
  prompt: effectivePrompt,
@@ -1110,7 +1164,8 @@ async function executeDriveRound(args) {
1110
1164
  !replyGuidance.isQ4HAnswerPrompt &&
1111
1165
  replyGuidance.suppressInterDialogReplyGuidance &&
1112
1166
  replyGuidance.deferredReplyReassertionDirective !== undefined;
1113
- activeTellaskReplyDirective = replyGuidance.activeReplyDirective;
1167
+ activeTellaskReplyDirective =
1168
+ replyGuidance.activeReplyDirective ?? replyContinuationScope.directive();
1114
1169
  activePromptWasReplyToolReminder = isReplyToolReminderPrompt(effectivePrompt);
1115
1170
  let activePromptCarriesReplyDirective = effectivePrompt?.tellaskReplyDirective !== undefined &&
1116
1171
  activeTellaskReplyDirective !== undefined &&
@@ -1119,19 +1174,10 @@ async function executeDriveRound(args) {
1119
1174
  if (effectivePrompt && effectivePrompt.userLanguageCode) {
1120
1175
  dialog.setLastUserLanguageCode(effectivePrompt.userLanguageCode);
1121
1176
  }
1122
- const coreDriveOptions = criticalUserInterjectionRuntimeGuide === undefined
1123
- ? driveOptions
1124
- : {
1125
- ...(driveOptions ?? {
1126
- source: driveSource,
1127
- reason: 'critical_user_prompt_remediation',
1128
- }),
1129
- criticalUserInterjectionRuntimeGuide,
1130
- };
1131
1177
  driveResult = await (0, drive_1.driveDialogStreamCore)(dialog, {
1132
1178
  scheduleDrive: args.scheduleDrive,
1133
1179
  driveDialog: args.driveDialog,
1134
- }, effectivePrompt, coreDriveOptions);
1180
+ }, effectivePrompt, driveOptions);
1135
1181
  const latestAfterCore = await persistence_1.DialogPersistence.loadDialogLatest(dialog.id, dialog.status);
1136
1182
  coreEndedInterrupted = latestAfterCore?.executionMarker?.kind === 'interrupted';
1137
1183
  await restoreAcceptedRootDriveWakeAfterDriveFailure({
@@ -1140,7 +1186,12 @@ async function executeDriveRound(args) {
1140
1186
  reason: 'core_stopped',
1141
1187
  hadRootDriveWakeBeforeCore,
1142
1188
  });
1143
- calleeDialogReplyTarget = driveResult.lastAssistantReplyTarget ?? calleeDialogReplyTarget;
1189
+ replyContinuationScope.refresh(driveResult.lastBusinessContinuation);
1190
+ calleeDialogReplyTarget =
1191
+ driveResult.lastAssistantReplyTarget ??
1192
+ replyContinuationScope.target() ??
1193
+ calleeDialogReplyTarget;
1194
+ activeTellaskReplyDirective = activeTellaskReplyDirective ?? replyContinuationScope.directive();
1144
1195
  interruptedBySignal = (0, dialog_display_state_1.getActiveRunSignal)(dialog.id)?.aborted === true;
1145
1196
  if (!interruptedBySignal) {
1146
1197
  const queuedFollowUp = dialog.takeUpNext();
@@ -1224,8 +1275,10 @@ async function executeDriveRound(args) {
1224
1275
  if (replyDirectiveForAssistantOutput !== undefined &&
1225
1276
  replyDirectiveForAssistantOutput.targetCallId !==
1226
1277
  activeTellaskReplyDirective?.targetCallId) {
1227
- // `driveDialogStreamCore` may already have consumed a queued assignment-update prompt
1228
- // inside the same drive, so rebind the tail decision to the assistant output target.
1278
+ // Business continuation identity should already come from the accepted next-step
1279
+ // trigger or the current runtime prompt. This branch only handles an explicit
1280
+ // assistant-output reply target surfaced by the core; do not broaden it into
1281
+ // transcript/assignment-anchor reconstruction.
1229
1282
  log_1.log.debug('kernel-driver rebound sideDialog reply directive to latest assistant output target', undefined, {
1230
1283
  dialogId: dialog.id.valueOf(),
1231
1284
  previousTargetCallId: activeTellaskReplyDirective?.targetCallId ?? null,
@@ -1409,11 +1462,20 @@ async function executeDriveRound(args) {
1409
1462
  if (followUp.kind === 'runtime_reply_reminder' ||
1410
1463
  followUp.kind === 'runtime_sideDialog_reply_reminder') {
1411
1464
  await queueReplyReminderFollowUp({ dialog, followUp });
1465
+ const businessContinuation = {
1466
+ kind: 'inter_dialog_reply',
1467
+ tellaskReplyDirective: followUp.tellaskReplyDirective,
1468
+ ...(followUp.kind === 'runtime_sideDialog_reply_reminder' &&
1469
+ followUp.calleeDialogReplyTarget !== undefined
1470
+ ? { calleeDialogReplyTarget: followUp.calleeDialogReplyTarget }
1471
+ : {}),
1472
+ };
1412
1473
  args.scheduleDrive(dialog, {
1413
1474
  waitInQue: true,
1414
1475
  driveOptions: {
1415
1476
  source: 'kernel_driver_follow_up',
1416
1477
  reason: 'follow_up_prompt',
1478
+ businessContinuation,
1417
1479
  },
1418
1480
  });
1419
1481
  return driveResult;