dominds 1.27.2 → 1.27.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/apps/runtime.js +3 -1
  2. package/dist/dialog-fork.js +2 -1
  3. package/dist/dialog-global-registry.d.ts +11 -1
  4. package/dist/dialog-global-registry.js +45 -0
  5. package/dist/dialog.d.ts +14 -5
  6. package/dist/dialog.js +114 -21
  7. package/dist/docs/daemon-cmd-runner.md +5 -0
  8. package/dist/docs/daemon-cmd-runner.zh.md +5 -0
  9. package/dist/llm/kernel-driver/drive.js +228 -49
  10. package/dist/llm/kernel-driver/fbr.d.ts +9 -0
  11. package/dist/llm/kernel-driver/fbr.js +186 -59
  12. package/dist/mcp/supervisor.js +4 -1
  13. package/dist/minds/load.js +1 -0
  14. package/dist/minds/system-prompt-parts.js +30 -30
  15. package/dist/persistence.js +83 -17
  16. package/dist/priming.js +2 -3
  17. package/dist/runtime/driver-messages.d.ts +9 -0
  18. package/dist/runtime/driver-messages.js +103 -33
  19. package/dist/runtime/shared-reminder-update-impact.d.ts +20 -0
  20. package/dist/runtime/shared-reminder-update-impact.js +110 -0
  21. package/dist/shared-reminders.js +2 -2
  22. package/dist/tool-availability.js +1 -0
  23. package/dist/tool.d.ts +7 -4
  24. package/dist/tool.js +10 -4
  25. package/dist/tools/app-reminders.js +4 -3
  26. package/dist/tools/builtins.js +2 -0
  27. package/dist/tools/cmd-runner-protocol.d.ts +6 -0
  28. package/dist/tools/cmd-runner-protocol.js +57 -2
  29. package/dist/tools/cmd-runner.js +83 -2
  30. package/dist/tools/ctrl.d.ts +2 -0
  31. package/dist/tools/ctrl.js +183 -6
  32. package/dist/tools/os.js +115 -14
  33. package/dist/tools/pending-tellask-reminder.js +1 -0
  34. package/dist/tools/process-kill.js +49 -0
  35. package/dist/tools/prompts/control/en/errors.md +1 -1
  36. package/dist/tools/prompts/control/en/index.md +4 -4
  37. package/dist/tools/prompts/control/en/principles.md +22 -21
  38. package/dist/tools/prompts/control/en/scenarios.md +10 -3
  39. package/dist/tools/prompts/control/en/tools.md +28 -5
  40. package/dist/tools/prompts/control/zh/errors.md +1 -1
  41. package/dist/tools/prompts/control/zh/index.md +4 -4
  42. package/dist/tools/prompts/control/zh/principles.md +21 -20
  43. package/dist/tools/prompts/control/zh/scenarios.md +10 -3
  44. package/dist/tools/prompts/control/zh/tools.md +28 -5
  45. package/dist/tools/prompts/os/en/tools.md +2 -0
  46. package/dist/tools/prompts/os/zh/tools.md +2 -0
  47. package/package.json +4 -4
@@ -46,6 +46,7 @@ const KERNEL_DRIVER_DEFAULT_RETRY_POLICY = {
46
46
  backoffMultiplier: 1.5,
47
47
  maxDelayMs: 30 * 60 * 1000, // 30 minutes
48
48
  };
49
+ const CLEAR_MIND_TOOL_NAME = 'clear_mind';
49
50
  const KERNEL_DRIVER_EMPTY_LLM_RESPONSE_ERROR_CODE = 'DOMINDS_LLM_EMPTY_RESPONSE';
50
51
  // Wrapper isolation boundary:
51
52
  // - Wrappers emit provider-native web-search events.
@@ -246,6 +247,35 @@ function buildKernelDriverFbrPrompt(dlg, state) {
246
247
  origin: 'runtime',
247
248
  };
248
249
  }
250
+ function resolveLatestModelOutputGenseq(dlg) {
251
+ for (let index = dlg.msgs.length - 1; index >= 0; index -= 1) {
252
+ const msg = dlg.msgs[index];
253
+ if (msg === undefined) {
254
+ continue;
255
+ }
256
+ switch (msg.type) {
257
+ case 'saying_msg':
258
+ case 'thinking_msg':
259
+ case 'func_call_msg': {
260
+ const genseq = Math.floor(msg.genseq);
261
+ if (Number.isFinite(genseq) && genseq > 0) {
262
+ return genseq;
263
+ }
264
+ break;
265
+ }
266
+ default:
267
+ break;
268
+ }
269
+ }
270
+ return undefined;
271
+ }
272
+ function resolveProgrammaticFbrConclusionGenseq(args) {
273
+ return (args.lastAssistantSayingGenseq ??
274
+ args.lastFunctionCallGenseq ??
275
+ resolveLatestModelOutputGenseq(args.dlg) ??
276
+ args.dlg.activeGenSeqOrUndefined ??
277
+ 1);
278
+ }
249
279
  function normalizeQ4HAnswerCallId(raw) {
250
280
  if (typeof raw !== 'string')
251
281
  return undefined;
@@ -329,38 +359,41 @@ async function maybeResolveAnsweredUserInterjection(args) {
329
359
  return undefined;
330
360
  }
331
361
  const course = args.dlg.activeGenCourseOrUndefined ?? args.dlg.currentCourse;
332
- const answerIdSource = [
333
- args.dlg.id.rootId,
334
- args.dlg.id.selfId,
335
- `c${String(course)}`,
336
- `g${String(args.assistantSayingGenseq)}`,
337
- pending.msgId,
338
- ].join('|');
339
- const answer = {
340
- id: `a2h-${Buffer.from(answerIdSource).toString('base64url')}`,
341
- content: args.assistantSayingContent,
342
- answeredAt: (0, time_1.formatUnifiedTimestamp)(new Date()),
343
- answerRef: {
344
- course,
345
- genseq: args.assistantSayingGenseq,
346
- },
347
- };
348
- const existingAnswers = await persistence_1.DialogPersistence.loadAnswersToHumanState(args.dlg.id, args.dlg.status);
349
- if (!existingAnswers.some((item) => item.id === answer.id)) {
350
- await persistence_1.DialogPersistence.appendAnswerToHumanState(args.dlg.id, answer, args.dlg.status);
351
- const metadata = await persistence_1.DialogPersistence.loadDialogMetadata(args.dlg.id, args.dlg.status);
352
- const taskDocPath = metadata?.taskDocPath ?? args.dlg.taskDocPath ?? '';
353
- const event = {
354
- type: 'new_a2h_answered',
355
- answer: {
356
- ...answer,
357
- selfId: args.dlg.id.selfId,
358
- rootId: args.dlg.id.rootId,
359
- agentId: metadata?.agentId ?? args.dlg.agentId,
360
- taskDocPath,
362
+ const answer = args.recordAnswerToHuman
363
+ ? {
364
+ id: `a2h-${Buffer.from([
365
+ args.dlg.id.rootId,
366
+ args.dlg.id.selfId,
367
+ `c${String(course)}`,
368
+ `g${String(args.assistantSayingGenseq)}`,
369
+ pending.msgId,
370
+ ].join('|')).toString('base64url')}`,
371
+ content: args.assistantSayingContent,
372
+ answeredAt: (0, time_1.formatUnifiedTimestamp)(new Date()),
373
+ answerRef: {
374
+ course,
375
+ genseq: args.assistantSayingGenseq,
361
376
  },
362
- };
363
- (0, evt_registry_1.postDialogEvent)(args.dlg, event);
377
+ }
378
+ : undefined;
379
+ if (answer !== undefined) {
380
+ const existingAnswers = await persistence_1.DialogPersistence.loadAnswersToHumanState(args.dlg.id, args.dlg.status);
381
+ if (!existingAnswers.some((item) => item.id === answer.id)) {
382
+ await persistence_1.DialogPersistence.appendAnswerToHumanState(args.dlg.id, answer, args.dlg.status);
383
+ const metadata = await persistence_1.DialogPersistence.loadDialogMetadata(args.dlg.id, args.dlg.status);
384
+ const taskDocPath = metadata?.taskDocPath ?? args.dlg.taskDocPath ?? '';
385
+ const event = {
386
+ type: 'new_a2h_answered',
387
+ answer: {
388
+ ...answer,
389
+ selfId: args.dlg.id.selfId,
390
+ rootId: args.dlg.id.rootId,
391
+ agentId: metadata?.agentId ?? args.dlg.agentId,
392
+ taskDocPath,
393
+ },
394
+ };
395
+ (0, evt_registry_1.postDialogEvent)(args.dlg, event);
396
+ }
364
397
  }
365
398
  await persistence_1.DialogPersistence.mutateDialogLatest(args.dlg.id, (previous) => {
366
399
  const previousPending = previous.pendingUserInterjectionReply;
@@ -748,9 +781,9 @@ function formatContextHealthLargeToolReturnUnavailable(args) {
748
781
  '',
749
782
  '不要再尝试获取各种大段的输出,都不会显示给你。现在先做两件事:',
750
783
  '1. 把需要回传给主线对话的结论、证据定位和风险整理清楚。',
751
- '2. 对于下一程恢复工作需要的信息,写入提醒项。',
784
+ '2. 用当前对话范围(scope=dialog)提醒项写明本路对话任务目标,并把下一程恢复当前支线工作需要的信息带过桥。',
752
785
  '',
753
- '然后尽快完成当前支线回复;如果你有 clear_mind({}),再调用它开启新一程。',
786
+ '然后调用 clear_mind({}) 开启新一程,并尽快完成当前支线回复。',
754
787
  '',
755
788
  `详情:本次返回约 ${approxBytes} 字节。`,
756
789
  ].join('\n');
@@ -760,7 +793,7 @@ function formatContextHealthLargeToolReturnUnavailable(args) {
760
793
  '',
761
794
  '不要再尝试获取各种大段的输出,都不会显示给你。现在先做两件事:',
762
795
  '1. 把下一程对话需要知道的此程细节信息写入差遣牒合适章节。',
763
- '2. 对于不适合差遣牒章节覆盖、但下一程恢复工作需要的信息写入提醒项。',
796
+ '2. 对于不适合差遣牒章节覆盖、但下一程恢复当前对话需要的信息,用当前对话范围(scope=dialog)提醒项写明本路对话任务目标并带过桥。',
764
797
  '',
765
798
  '然后调用 clear_mind({}) 开启新一程。',
766
799
  '',
@@ -773,9 +806,9 @@ function formatContextHealthLargeToolReturnUnavailable(args) {
773
806
  '',
774
807
  'Do not try again to fetch any kind of large output; it still will not be shown. Do two things now:',
775
808
  '1. Organize the conclusions, evidence pointers, and risks that need to go back to the Mainline dialog.',
776
- '2. Write any details needed to resume the next course into reminders.',
809
+ '2. Use current-dialog scoped (scope=dialog) reminders to state this dialog task goal and carry over the details needed to resume this Sideline dialog in the next course.',
777
810
  '',
778
- 'Then finish the current Sideline dialog reply as soon as possible; if you have clear_mind({}), call it to start a new course.',
811
+ 'Then call clear_mind({}) to start a new course, and finish the current Sideline dialog reply as soon as possible.',
779
812
  '',
780
813
  `Detail: this return was about ${approxBytes} bytes.`,
781
814
  ].join('\n');
@@ -785,7 +818,7 @@ function formatContextHealthLargeToolReturnUnavailable(args) {
785
818
  '',
786
819
  'Do not try again to fetch any kind of large output; it still will not be shown. Do two things now:',
787
820
  '1. Write the details from this course that the next course needs into the appropriate Taskdoc sections.',
788
- '2. Write information that does not fit a Taskdoc section, but is needed to resume the next course, into reminders.',
821
+ '2. For information that does not fit a Taskdoc section but is needed to resume this dialog in the next course, use current-dialog scoped (scope=dialog) reminders to state this dialog task goal and carry it over.',
789
822
  '',
790
823
  'Then call clear_mind({}) to start a new course.',
791
824
  '',
@@ -814,6 +847,9 @@ function countToolResultVisibleBytes(output) {
814
847
  return bytes;
815
848
  }
816
849
  function applyContextHealthToolResultVisibilityLimit(args) {
850
+ if (isFbrSideDialog(args.dlg)) {
851
+ return { output: args.output, largeReturnUnavailable: false };
852
+ }
817
853
  if ((0, context_health_1.getContextHealthRemediationLevel)(args.contextHealth) === undefined) {
818
854
  return { output: args.output, largeReturnUnavailable: false };
819
855
  }
@@ -1961,6 +1997,30 @@ function shouldImmediatelyFollowUpToolOutcome(tool, outcome) {
1961
1997
  }
1962
1998
  return shouldImmediatelyFollowUpSuccessfulToolResult(tool);
1963
1999
  }
2000
+ function isFailedToolOutcome(outcome) {
2001
+ return outcome === 'failure' || outcome === 'partial_failure';
2002
+ }
2003
+ function formatClearMindBlockedByFailedSiblingTools(failedTools) {
2004
+ const language = (0, work_language_1.getWorkLanguage)();
2005
+ const details = failedTools
2006
+ .map((tool) => `- ${tool.toolName} (callId=${tool.callId}, outcome=${String(tool.outcome)})`)
2007
+ .join('\n');
2008
+ return language === 'zh'
2009
+ ? [
2010
+ '错误:本轮 clear_mind 与其它工具一起调用,但其它工具返回了失败结果。',
2011
+ '',
2012
+ details,
2013
+ '',
2014
+ 'clear_mind 已拒绝开启新一程。请先确保其它工具调用正常完成(必要时修正参数、重试或处理失败),然后再次调用 clear_mind。',
2015
+ ].join('\n')
2016
+ : [
2017
+ 'Error: clear_mind was called in the same round as other tools, and at least one other tool returned a failure result.',
2018
+ '',
2019
+ details,
2020
+ '',
2021
+ 'clear_mind refused to start a new course. Ensure the other tool calls complete normally first (fix arguments, retry, or handle the failure), then call clear_mind again.',
2022
+ ].join('\n');
2023
+ }
1964
2024
  function trimOptionalCallId(value) {
1965
2025
  if (typeof value !== 'string')
1966
2026
  return undefined;
@@ -2133,7 +2193,7 @@ async function executeFunctionCalls(args) {
2133
2193
  throwIfAborted(args.abortSignal, args.dlg);
2134
2194
  await args.dlg.persistFunctionCall(prepared.func.id, prepared.func.name, prepared.argsStr, prepared.callGenseq, prepared.func.rawId);
2135
2195
  }
2136
- const functionPromises = preparedCalls.map(async ({ func, originalFunc, callGenseq, argsStr, tool, preparedInvocationArgs, }) => {
2196
+ const executePreparedCall = async ({ func, originalFunc, callGenseq, argsStr, tool, preparedInvocationArgs, }) => {
2137
2197
  let result;
2138
2198
  let outcome = 'success';
2139
2199
  let forceImmediateFollowup = false;
@@ -2226,8 +2286,54 @@ async function executeFunctionCalls(args) {
2226
2286
  throw rethrowError;
2227
2287
  }
2228
2288
  return { func, originalFunc, outcome, forceImmediateFollowup, result };
2229
- });
2230
- return await Promise.all(functionPromises);
2289
+ };
2290
+ const blockClearMindCall = async (prepared, failedTools) => {
2291
+ const output = (0, tool_1.toolFailure)(formatClearMindBlockedByFailedSiblingTools(failedTools));
2292
+ const result = {
2293
+ type: 'func_result_msg',
2294
+ id: prepared.func.id,
2295
+ rawId: prepared.func.rawId,
2296
+ effectiveId: prepared.func.effectiveId,
2297
+ name: prepared.func.name,
2298
+ content: output.content,
2299
+ role: 'tool',
2300
+ genseq: prepared.callGenseq,
2301
+ };
2302
+ await args.dlg.receiveFuncResult(result);
2303
+ return {
2304
+ func: prepared.func,
2305
+ originalFunc: prepared.originalFunc,
2306
+ outcome: output.outcome,
2307
+ forceImmediateFollowup: false,
2308
+ result,
2309
+ };
2310
+ };
2311
+ const clearMindCalls = preparedCalls.filter((call) => call.func.name === CLEAR_MIND_TOOL_NAME);
2312
+ const siblingCalls = preparedCalls.filter((call) => call.func.name !== CLEAR_MIND_TOOL_NAME);
2313
+ const failedPriorToolResults = args.failedPriorToolResults ?? [];
2314
+ if (clearMindCalls.length === 0 || siblingCalls.length === 0) {
2315
+ if (clearMindCalls.length > 0 && failedPriorToolResults.length > 0) {
2316
+ return await Promise.all(clearMindCalls.map((call) => blockClearMindCall(call, failedPriorToolResults)));
2317
+ }
2318
+ return await Promise.all(preparedCalls.map((call) => executePreparedCall(call)));
2319
+ }
2320
+ const siblingExecutions = await Promise.all(siblingCalls.map((call) => executePreparedCall(call)));
2321
+ const failedSiblingToolResults = [
2322
+ ...failedPriorToolResults,
2323
+ ...siblingExecutions
2324
+ .filter((execution) => isFailedToolOutcome(execution.outcome))
2325
+ .map((execution) => ({
2326
+ callId: execution.result.id,
2327
+ toolName: execution.result.name,
2328
+ outcome: execution.outcome,
2329
+ })),
2330
+ ];
2331
+ if (failedSiblingToolResults.length > 0) {
2332
+ const clearMindExecutions = await Promise.all(clearMindCalls.map((call) => blockClearMindCall(call, failedSiblingToolResults)));
2333
+ return [...siblingExecutions, ...clearMindExecutions];
2334
+ }
2335
+ const clearMindExecutions = await Promise.all(clearMindCalls.map((call) => executePreparedCall(call)));
2336
+ return [...siblingExecutions, ...clearMindExecutions];
2231
2337
  }
2232
2338
  async function executeFunctionRound(args) {
2233
2339
  if (args.funcCalls.length === 0) {
@@ -2270,6 +2376,17 @@ async function executeFunctionRound(args) {
2270
2376
  activePromptReplyDirective: args.activePromptReplyDirective,
2271
2377
  });
2272
2378
  throwIfAborted(args.abortSignal, args.dlg);
2379
+ const failedTellaskToolResults = tellaskRound.invalidTellaskCallIds.map((callId) => {
2380
+ const call = args.funcCalls.find((candidate) => candidate.id === callId);
2381
+ if (call === undefined) {
2382
+ throw new Error(`kernel-driver tellask result invariant violation: missing invalid tellask call '${callId}'`);
2383
+ }
2384
+ return {
2385
+ callId,
2386
+ toolName: call.name,
2387
+ outcome: 'failure',
2388
+ };
2389
+ });
2273
2390
  const genericExecutions = await executeFunctionCalls({
2274
2391
  dlg: args.dlg,
2275
2392
  agent: args.agent,
@@ -2277,6 +2394,7 @@ async function executeFunctionRound(args) {
2277
2394
  funcCalls: tellaskRound.normalCalls,
2278
2395
  abortSignal: args.abortSignal,
2279
2396
  contextHealthForToolResultVisibility: args.contextHealthForToolResultVisibility,
2397
+ failedPriorToolResults: failedTellaskToolResults,
2280
2398
  });
2281
2399
  const genericExecutionByOriginalCall = new Map(genericExecutions.map((execution) => [execution.originalFunc, execution]));
2282
2400
  const funcToolByName = new Map(args.agentTools
@@ -2602,8 +2720,41 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2602
2720
  for (;;) {
2603
2721
  genIterNo += 1;
2604
2722
  throwIfAborted(abortSignal, dlg);
2605
- const activeFbrState = await loadDialogFbrState(dlg);
2723
+ let activeFbrState = await loadDialogFbrState(dlg);
2606
2724
  if (isFbrSideDialog(dlg)) {
2725
+ const fbrContextHealthLevel = (0, context_health_1.getContextHealthRemediationLevel)(dlg.getLastContextHealth());
2726
+ if (activeFbrState !== undefined && fbrContextHealthLevel === 'critical') {
2727
+ log_1.log.warn('kernel-driver ending FBR with critical context fixed conclusion', undefined, {
2728
+ rootId: dlg.id.rootId,
2729
+ selfId: dlg.id.selfId,
2730
+ course: dlg.currentCourse,
2731
+ phase: activeFbrState.phase,
2732
+ iteration: activeFbrState.iteration,
2733
+ });
2734
+ fbrConclusion = {
2735
+ responseText: (0, fbr_1.buildProgrammaticFbrContextCriticalContent)({
2736
+ language: (0, work_language_1.getWorkLanguage)(),
2737
+ }),
2738
+ responseGenseq: resolveProgrammaticFbrConclusionGenseq({
2739
+ dlg,
2740
+ lastAssistantSayingGenseq,
2741
+ lastFunctionCallGenseq,
2742
+ }),
2743
+ replyResolutionCallId: `fbr-context-critical-${(0, id_1.generateShortId)()}`,
2744
+ };
2745
+ await persistDialogFbrState(dlg, undefined);
2746
+ dlg.setFbrConclusionToolsEnabled(false);
2747
+ finalDisplayState = await (0, dialog_display_state_1.computeIdleDisplayState)(dlg);
2748
+ break driveCoreLoop;
2749
+ }
2750
+ if (activeFbrState !== undefined &&
2751
+ fbrContextHealthLevel === 'caution' &&
2752
+ !(0, fbr_1.isFbrContextCautionFinalizationState)(activeFbrState) &&
2753
+ (pendingPrompt === undefined || pendingPrompt.origin === 'runtime')) {
2754
+ activeFbrState = (0, fbr_1.forceFbrContextCautionFinalizationState)(activeFbrState);
2755
+ await persistDialogFbrState(dlg, activeFbrState);
2756
+ pendingPrompt = buildKernelDriverFbrPrompt(dlg, activeFbrState);
2757
+ }
2607
2758
  dlg.setFbrConclusionToolsEnabled(activeFbrState !== undefined && (0, fbr_1.isFbrFinalizationState)(activeFbrState));
2608
2759
  if (pendingPrompt === undefined &&
2609
2760
  activeFbrState &&
@@ -2786,7 +2937,10 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2786
2937
  let currentRuntimeGuideMsg;
2787
2938
  const currentPromptFromFbrState = currentPrompt !== undefined &&
2788
2939
  currentFbrState !== undefined &&
2789
- currentFbrState.promptDelivered !== true;
2940
+ currentFbrState.promptDelivered !== true &&
2941
+ isFbrSideDialog(dlg) &&
2942
+ currentPrompt.origin === 'runtime' &&
2943
+ currentPrompt.content === buildKernelDriverFbrPrompt(dlg, currentFbrState).content;
2790
2944
  pendingPrompt = undefined;
2791
2945
  if (currentPrompt) {
2792
2946
  const diligenceSkipReason = await shouldSkipDiligencePromptBeforeGeneration({
@@ -3674,6 +3828,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3674
3828
  const currentRoundAnsweringGenseq = dlg.activeGenSeqOrUndefined;
3675
3829
  const hasCurrentRoundAnsweringOutput = currentRoundAnsweringGenseq !== undefined &&
3676
3830
  lastAssistantAnsweringGenseq === currentRoundAnsweringGenseq;
3831
+ let pendingVisibleUserInterjectionAnswer;
3677
3832
  if (userInterjectionMsgIdForVisibleAnswer !== undefined &&
3678
3833
  !hasCurrentRoundAnsweringOutput) {
3679
3834
  const streamedCurrentRoundSayingContent = batchOutputs.length === 0 &&
@@ -3684,14 +3839,25 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3684
3839
  lastAssistantSayingGenseq !== previousAssistantSayingGenseq
3685
3840
  ? lastAssistantSayingGenseq
3686
3841
  : null;
3687
- await maybeResolveAnsweredUserInterjection({
3688
- dlg,
3842
+ pendingVisibleUserInterjectionAnswer = {
3689
3843
  userPromptMsgId: userInterjectionMsgIdForVisibleAnswer,
3690
3844
  assistantSayingContent: currentRoundAssistantSayingContent ?? streamedCurrentRoundSayingContent,
3691
3845
  assistantSayingGenseq: currentRoundAssistantSayingGenseq ?? streamedCurrentRoundSayingGenseq,
3692
3846
  functionCallGenseqs: currentRoundFunctionCallGenseqs,
3693
- });
3847
+ };
3694
3848
  }
3849
+ const settleVisibleUserInterjectionAnswer = async (recordAnswerToHuman) => {
3850
+ const pendingAnswer = pendingVisibleUserInterjectionAnswer;
3851
+ if (pendingAnswer === undefined) {
3852
+ return;
3853
+ }
3854
+ pendingVisibleUserInterjectionAnswer = undefined;
3855
+ await maybeResolveAnsweredUserInterjection({
3856
+ dlg,
3857
+ ...pendingAnswer,
3858
+ recordAnswerToHuman,
3859
+ });
3860
+ };
3695
3861
  if (routed.tellaskToolOutputs.length > 0) {
3696
3862
  newMsgs.push(...routed.tellaskToolOutputs);
3697
3863
  }
@@ -3754,6 +3920,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3754
3920
  }
3755
3921
  await persistDialogFbrState(dlg, undefined);
3756
3922
  dlg.setFbrConclusionToolsEnabled(false);
3923
+ await settleVisibleUserInterjectionAnswer(false);
3757
3924
  break;
3758
3925
  }
3759
3926
  if (inspection.kind === 'rejected') {
@@ -3773,6 +3940,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3773
3940
  await persistDialogFbrState(dlg, nextFbrState);
3774
3941
  dlg.setFbrConclusionToolsEnabled((0, fbr_1.isFbrFinalizationState)(nextFbrState));
3775
3942
  pendingPrompt = buildKernelDriverFbrPrompt(dlg, nextFbrState);
3943
+ await settleVisibleUserInterjectionAnswer(true);
3776
3944
  continue;
3777
3945
  }
3778
3946
  fbrConclusion = {
@@ -3780,10 +3948,11 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3780
3948
  language: (0, work_language_1.getWorkLanguage)(),
3781
3949
  finalizationAttempts: persistedFbrState.effort,
3782
3950
  }),
3783
- responseGenseq: lastAssistantSayingGenseq ??
3784
- lastFunctionCallGenseq ??
3785
- dlg.activeGenSeqOrUndefined ??
3786
- 1,
3951
+ responseGenseq: resolveProgrammaticFbrConclusionGenseq({
3952
+ dlg,
3953
+ lastAssistantSayingGenseq,
3954
+ lastFunctionCallGenseq,
3955
+ }),
3787
3956
  replyResolutionCallId: `fbr-conclusion-${(0, id_1.generateShortId)()}`,
3788
3957
  };
3789
3958
  if (!isFbrSideDialog(dlg)) {
@@ -3791,6 +3960,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3791
3960
  }
3792
3961
  await persistDialogFbrState(dlg, undefined);
3793
3962
  dlg.setFbrConclusionToolsEnabled(false);
3963
+ await settleVisibleUserInterjectionAnswer(false);
3794
3964
  break;
3795
3965
  }
3796
3966
  if (routed.shouldStopAfterReplyTool) {
@@ -3810,12 +3980,14 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3810
3980
  call.name === 'replyTellaskBack')
3811
3981
  .map((call) => call.name),
3812
3982
  });
3983
+ await settleVisibleUserInterjectionAnswer(false);
3813
3984
  break;
3814
3985
  }
3815
3986
  const queuedNewCoursePrompt = await consumeQueuedNewCourseRuntimePromptForSameDrive(dlg);
3816
3987
  if (queuedNewCoursePrompt !== undefined) {
3817
3988
  pendingPrompt = queuedNewCoursePrompt;
3818
3989
  skipTaskdocForThisDrive = false;
3990
+ await settleVisibleUserInterjectionAnswer(true);
3819
3991
  continue;
3820
3992
  }
3821
3993
  // Start an immediate post-tool generation only when this round produced tool outputs that
@@ -3857,6 +4029,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3857
4029
  remindersVer: dlg.remindersVer,
3858
4030
  pubRemindersVer,
3859
4031
  });
4032
+ await settleVisibleUserInterjectionAnswer(true);
3860
4033
  break;
3861
4034
  }
3862
4035
  if (dlg.remindersVer > pubRemindersVer) {
@@ -3880,6 +4053,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3880
4053
  pubRemindersVer,
3881
4054
  });
3882
4055
  await preserveDiligenceBudgetAcrossQ4H(dlg);
4056
+ await settleVisibleUserInterjectionAnswer(false);
3883
4057
  break;
3884
4058
  }
3885
4059
  if (!shouldStartImmediatePostToolGeneration) {
@@ -3901,6 +4075,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3901
4075
  rootId: dlg.id.rootId,
3902
4076
  selfId: dlg.id.selfId,
3903
4077
  });
4078
+ await settleVisibleUserInterjectionAnswer(false);
3904
4079
  break;
3905
4080
  }
3906
4081
  const healthFirst = await maybeContinueWithHealthPromptBeforeDiligence({
@@ -3913,6 +4088,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3913
4088
  if (healthFirst.resetTaskdoc) {
3914
4089
  skipTaskdocForThisDrive = false;
3915
4090
  }
4091
+ await settleVisibleUserInterjectionAnswer(true);
3916
4092
  continue;
3917
4093
  }
3918
4094
  const next = await maybeContinueWithDiligencePrompt({
@@ -3922,6 +4098,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3922
4098
  });
3923
4099
  if (next.kind === 'continue') {
3924
4100
  pendingPrompt = next.prompt;
4101
+ await settleVisibleUserInterjectionAnswer(true);
3925
4102
  continue;
3926
4103
  }
3927
4104
  lastToolRoundStopDiagnostics = buildToolRoundStopDiagnostics({
@@ -3936,6 +4113,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3936
4113
  remindersVer: dlg.remindersVer,
3937
4114
  pubRemindersVer,
3938
4115
  });
4116
+ await settleVisibleUserInterjectionAnswer(false);
3939
4117
  break;
3940
4118
  }
3941
4119
  await repairMissingImmediateFollowupTrigger({
@@ -3950,6 +4128,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
3950
4128
  resolvingImmediateToolResultUserPromptMsgId = resolvingImmediateToolResultForUserPrompt
3951
4129
  ? currentUserPromptMsgId
3952
4130
  : undefined;
4131
+ await settleVisibleUserInterjectionAnswer(true);
3953
4132
  continue;
3954
4133
  }
3955
4134
  catch (err) {
@@ -32,6 +32,13 @@ export declare function buildFbrFinalizationPrompt(args: {
32
32
  total: number;
33
33
  language: LanguageCode;
34
34
  }): string;
35
+ export declare function buildFbrContextCautionFinalizationPrompt(args: {
36
+ attempt: number;
37
+ language: LanguageCode;
38
+ }): string;
39
+ export declare function buildProgrammaticFbrContextCriticalContent(args: {
40
+ language: LanguageCode;
41
+ }): string;
35
42
  export declare function buildProgrammaticFbrUnreasonableSituationContent(args: {
36
43
  language: LanguageCode;
37
44
  finalizationAttempts: number;
@@ -40,6 +47,8 @@ export declare function inspectFbrConclusionAttempt(messages: readonly ChatMessa
40
47
  export declare function createInitialFbrState(effort: number): DialogFbrState;
41
48
  export declare function markFbrPromptDelivered(state: DialogFbrState): DialogFbrState;
42
49
  export declare function isFbrFinalizationState(state: DialogFbrState): boolean;
50
+ export declare function isFbrContextCautionFinalizationState(state: DialogFbrState): boolean;
51
+ export declare function forceFbrContextCautionFinalizationState(state: DialogFbrState): DialogFbrState;
43
52
  export declare function advanceFbrState(state: DialogFbrState): DialogFbrState | undefined;
44
53
  export declare function buildFbrPromptForState(args: {
45
54
  state: DialogFbrState;