blun-king-cli 9.1.536 → 9.1.550

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 (117) hide show
  1. package/LIESMICH.txt +13 -869
  2. package/README.md +41 -833
  3. package/bin/assistant-message-offload-policy.cjs +3 -1
  4. package/bin/context-performance-policy.cjs +2 -5
  5. package/bin/context-pressure-policy.cjs +20 -0
  6. package/bin/cron-run-output.cjs +45 -0
  7. package/bin/cron-run-store.cjs +145 -0
  8. package/bin/durable-task-resume-policy.cjs +130 -0
  9. package/bin/durable-task-resume-runtime.cjs +117 -0
  10. package/bin/durable-task-resume-store.cjs +88 -0
  11. package/bin/editable-tool-approval-policy.cjs +540 -0
  12. package/bin/editable-tool-approval-runtime.cjs +99 -0
  13. package/bin/html-to-research-markdown.cjs +146 -0
  14. package/bin/programmatic-tool-runtime.mjs +330 -4
  15. package/bin/read-continuation-policy.cjs +36 -5
  16. package/bin/scoped-cron-run-policy.cjs +358 -0
  17. package/bin/startup-preferences.cjs +3 -3
  18. package/bin/structured-agent-swarm-output.cjs +325 -0
  19. package/bin/subagent-context-fork-policy.cjs +155 -0
  20. package/bin/subagent-skill-policy.cjs +204 -0
  21. package/bin/telegram-approval-relay.cjs +2 -1
  22. package/bin/tool-result-offload-policy.cjs +14 -1
  23. package/bin/update-notice.js +14 -18
  24. package/bin/user-message-offload-policy.cjs +3 -1
  25. package/blun.mjs +1089 -477
  26. package/codebase-index/README.md +12 -0
  27. package/codebase-index/codebase_index.py +129 -18
  28. package/package.json +23 -58
  29. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +89 -0
  30. package/telegram-plugin/dist/bridge.mjs +8 -1
  31. package/CHANGELOG.md +0 -321
  32. package/agent-spine-plugin/CHANGELOG.md +0 -406
  33. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  34. package/agent-spine-plugin/README.md +0 -344
  35. package/agent-spine-plugin/SECURITY.md +0 -47
  36. package/agent-spine-plugin/docs/acceptance.md +0 -61
  37. package/agent-spine-plugin/docs/architecture.md +0 -183
  38. package/agent-spine-plugin/docs/attention.md +0 -121
  39. package/agent-spine-plugin/docs/automatic-continuity.md +0 -79
  40. package/agent-spine-plugin/docs/channel-runtime.md +0 -92
  41. package/agent-spine-plugin/docs/coordination.md +0 -138
  42. package/agent-spine-plugin/docs/feed-transport.md +0 -99
  43. package/agent-spine-plugin/docs/gateway-runtime.md +0 -116
  44. package/agent-spine-plugin/docs/harness-reference.md +0 -45
  45. package/agent-spine-plugin/docs/host-integration.md +0 -129
  46. package/agent-spine-plugin/docs/https-transport.md +0 -116
  47. package/agent-spine-plugin/docs/learning.md +0 -133
  48. package/agent-spine-plugin/docs/object-transport.md +0 -93
  49. package/agent-spine-plugin/docs/peer-transport.md +0 -88
  50. package/agent-spine-plugin/docs/preflight-recall.md +0 -69
  51. package/agent-spine-plugin/docs/preservation-contract.md +0 -53
  52. package/agent-spine-plugin/docs/quality-gates.md +0 -50
  53. package/agent-spine-plugin/docs/relationships.md +0 -73
  54. package/agent-spine-plugin/docs/releasing.md +0 -83
  55. package/agent-spine-plugin/docs/roadmap.md +0 -307
  56. package/agent-spine-plugin/docs/selfstarter.md +0 -88
  57. package/agent-spine-plugin/docs/session-briefing.md +0 -74
  58. package/agent-spine-plugin/docs/shared-memory.md +0 -259
  59. package/agent-spine-plugin/docs/source-roots.md +0 -86
  60. package/agent-spine-plugin/docs/sqlite-transport.md +0 -76
  61. package/agent-spine-plugin/scripts/check-hosts.js +0 -195
  62. package/agent-spine-plugin/scripts/check-install.js +0 -569
  63. package/agent-spine-plugin/scripts/check-syntax.js +0 -29
  64. package/agent-spine-plugin/scripts/github-actions.js +0 -11
  65. package/agent-spine-plugin/scripts/release-check.js +0 -128
  66. package/agent-spine-plugin/scripts/run-acceptance.js +0 -19
  67. package/agent-spine-plugin/scripts/run-checks.js +0 -46
  68. package/agent-spine-plugin/scripts/run-tests-hermetic.js +0 -73
  69. package/agent-spine-plugin/spine-example/1-identity.md +0 -12
  70. package/agent-spine-plugin/spine-example/2-voice.md +0 -6
  71. package/agent-spine-plugin/spine-example/3-conduct.md +0 -8
  72. package/agent-spine-plugin/spine-example/4-history.md +0 -4
  73. package/bin/fredrik-glm-provider.cjs +0 -256
  74. package/bin/package-regression-policy.cjs +0 -77
  75. package/fredrik-glm-profile.toml.example +0 -26
  76. package/release-planned-removals.json +0 -15
  77. package/scripts/check-active-profile-plugin-startup.js +0 -36
  78. package/scripts/check-active-work-steer-regression.js +0 -46
  79. package/scripts/check-approval-observability-regression.js +0 -111
  80. package/scripts/check-approval-queue-shortcuts-regression.js +0 -65
  81. package/scripts/check-bundled-agent-spine-regression.js +0 -48
  82. package/scripts/check-codebase-search-packaging-regression.js +0 -92
  83. package/scripts/check-copy-command-regression.js +0 -74
  84. package/scripts/check-current-turn-read-pin-mutation-regression.js +0 -72
  85. package/scripts/check-current-turn-read-pin-regression.js +0 -94
  86. package/scripts/check-deepseek-native-max-regression.js +0 -49
  87. package/scripts/check-empty-response-effort-downgrade-regression.js +0 -48
  88. package/scripts/check-fredrik-glm-mutation-regression.js +0 -18
  89. package/scripts/check-fredrik-glm-regression.js +0 -169
  90. package/scripts/check-historical-tool-result-preview-regression.js +0 -77
  91. package/scripts/check-history-pressure-offload-regression.js +0 -77
  92. package/scripts/check-mcp-startup-wait-budget.js +0 -48
  93. package/scripts/check-package-regression.js +0 -38
  94. package/scripts/check-plugin-startup-regression.js +0 -53
  95. package/scripts/check-programmatic-context-isolation-regression.js +0 -193
  96. package/scripts/check-programmatic-tool-regression.js +0 -294
  97. package/scripts/check-queue-controls-regression.js +0 -189
  98. package/scripts/check-release-metadata.js +0 -103
  99. package/scripts/check-reload-agent-spine-regression.js +0 -76
  100. package/scripts/check-resume-replay-regression.js +0 -102
  101. package/scripts/check-session-cancel-regression.js +0 -43
  102. package/scripts/check-session-picker-resume-metrics-regression.js +0 -97
  103. package/scripts/check-session-start-hook-context-regression.js +0 -228
  104. package/scripts/check-shell-terminal-isolation-regression.js +0 -81
  105. package/scripts/check-slash-escape-regression.js +0 -89
  106. package/scripts/check-startup-swarm-command-regression.js +0 -24
  107. package/scripts/check-structured-subagent-output-regression.js +0 -331
  108. package/scripts/check-telegram-bridge-watchdog.js +0 -60
  109. package/scripts/check-telegram-direct-work-resume-regression.js +0 -53
  110. package/scripts/check-telegram-loop-exactly-once-regression.js +0 -71
  111. package/scripts/check-todo-loop-regression.js +0 -78
  112. package/scripts/check-todo-progress-regression.js +0 -416
  113. package/scripts/check-todo-recovery-catalog-regression.js +0 -50
  114. package/scripts/check-tool-schema-capacity-regression.js +0 -40
  115. package/scripts/programmatic-tool-runtime.test.mjs +0 -365
  116. package/scripts/structured-subagent-output.test.cjs +0 -170
  117. /package/{scripts → bin}/fix-node-pty-perms.js +0 -0
package/blun.mjs CHANGED
@@ -5,6 +5,7 @@ import { dirname as __cjsShimDirname } from 'node:path';
5
5
  const __filename = __cjsShimFileURLToPath(import.meta.url);
6
6
  const __dirname = __cjsShimDirname(__filename);
7
7
  import { createRequire } from "node:module";
8
+ const { htmlToResearchMarkdown } = createRequire(import.meta.url)("./bin/html-to-research-markdown.cjs");
8
9
  import telegramConsoleStatusPolicy from "./bin/telegram-console-status-policy.cjs";
9
10
  import cognitiveGoalAutostartPolicy from "./bin/cognitive-goal-autostart-policy.cjs";
10
11
  import cognitiveGoalTimeTriggerController from "./bin/cognitive-goal-time-trigger-controller.cjs";
@@ -16,7 +17,8 @@ import sessionScrollbackArchive from "./bin/session-scrollback-archive.cjs";
16
17
  import sessionReplayWindowPolicy from "./bin/session-replay-window-policy.cjs";
17
18
  import globPatternPolicy from "./bin/glob-pattern-policy.cjs";
18
19
  import userHomePathPolicy from "./bin/user-home-path-policy.cjs";
19
- import fredrikGlmProviderPolicy from "./bin/fredrik-glm-provider.cjs";
20
+ import editableToolApprovalPolicy from "./bin/editable-tool-approval-policy.cjs";
21
+ import editableToolApprovalRuntime from "./bin/editable-tool-approval-runtime.cjs";
20
22
  import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
21
23
  import * as fs$16 from "node:fs";
22
24
  import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
@@ -58,17 +60,13 @@ const { replayWindowStartIndex, resolveReplayActiveTurnCount } = sessionReplayWi
58
60
  const { globPatternError } = globPatternPolicy;
59
61
  const { unsupportedUserHomePathError } = userHomePathPolicy;
60
62
  const {
61
- PROVIDER_ID: FREDRIK_GLM_PROVIDER_ID,
62
- PROVIDER_TYPE: FREDRIK_GLM_PROVIDER_TYPE,
63
- MODEL_EFFORTS: FREDRIK_GLM_EFFORTS,
64
- configuredModels: configuredFredrikGlmModels,
65
- configuredProvider: configuredFredrikGlmProvider,
66
- isAllowedRuntimeAlias: isAllowedFredrikRuntimeAlias,
67
- isConfiguredAlias: isConfiguredFredrikGlmAlias,
68
- normalizeEffort: normalizeFredrikGlmEffort,
69
- requestControls: fredrikGlmRequestControls,
70
- readApiKeyFile: readFredrikGlmApiKeyFile
71
- } = fredrikGlmProviderPolicy;
63
+ buildApprovalEditedEvent,
64
+ canonicalEditedToolInputJson,
65
+ isEditableToolApprovalEligible,
66
+ parseEditedToolInputJson,
67
+ validateEditedApprovalDecision
68
+ } = editableToolApprovalPolicy;
69
+ const { buildEditedToolCallPlan } = editableToolApprovalRuntime;
72
70
  import { EventEmitter as EventEmitter$1 } from "node:events";
73
71
  import { StringDecoder } from "node:string_decoder";
74
72
  import co from "node:assert";
@@ -2733,7 +2731,6 @@ var init_blun = __esmMin((() => {
2733
2731
  _defaultHeaders;
2734
2732
  _generationKwargs;
2735
2733
  _supportEfforts;
2736
- _openAICompatible;
2737
2734
  _client;
2738
2735
  _clientFactory;
2739
2736
  _files;
@@ -2747,7 +2744,6 @@ var init_blun = __esmMin((() => {
2747
2744
  this._stream = options.stream ?? true;
2748
2745
  this._generationKwargs = { ...options.generationKwargs };
2749
2746
  this._supportEfforts = options.supportEfforts ?? [];
2750
- this._openAICompatible = options.openAICompatible === true;
2751
2747
  this._client = this._apiKey === void 0 ? void 0 : createFetchHttpClient({
2752
2748
  apiKey: this._apiKey,
2753
2749
  baseUrl: this._baseUrl,
@@ -2859,17 +2855,8 @@ var init_blun = __esmMin((() => {
2859
2855
  delete requestExtraBody["model"];
2860
2856
  delete requestExtraBody["messages"];
2861
2857
  if (!thinkingDisabled && thinking?.keep !== void 0) requestExtraBody["thinking"] = { keep: thinking.keep };
2862
- let reasoningRequested;
2863
- if (this._openAICompatible) {
2864
- delete requestKwargs["chat_template_kwargs"];
2865
- const controls = fredrikGlmRequestControls(effectiveThinkingEffort ?? "max");
2866
- requestExtraBody["thinking"] = controls.thinking;
2867
- requestExtraBody["reasoning_effort"] = controls.reasoning_effort;
2868
- reasoningRequested = true;
2869
- } else {
2870
- const effectiveTemplateKwargs = requestKwargs["chat_template_kwargs"];
2871
- reasoningRequested = typeof effectiveTemplateKwargs === "object" && effectiveTemplateKwargs !== null && effectiveTemplateKwargs.thinking === true;
2872
- }
2858
+ const effectiveTemplateKwargs = requestKwargs["chat_template_kwargs"];
2859
+ const reasoningRequested = typeof effectiveTemplateKwargs === "object" && effectiveTemplateKwargs !== null && effectiveTemplateKwargs.thinking === true;
2873
2860
  const createParams = {
2874
2861
  model: this._model,
2875
2862
  messages,
@@ -10013,7 +10000,7 @@ var init_schema = __esmMin((() => {
10013
10000
  init_matches_rule();
10014
10001
  init_errors$8();
10015
10002
  init_zod$1();
10016
- ProviderTypeSchema = union([literal("blun"), literal("openai_compatible")]);
10003
+ ProviderTypeSchema = literal("blun");
10017
10004
  OAuthRefSchema = object({
10018
10005
  storage: _enum(["file", "keyring"]),
10019
10006
  key: string().min(1),
@@ -10023,7 +10010,6 @@ var init_schema = __esmMin((() => {
10023
10010
  ProviderConfigSchema = object({
10024
10011
  type: ProviderTypeSchema,
10025
10012
  apiKey: string().optional(),
10026
- apiKeyFile: string().optional(),
10027
10013
  baseUrl: string().optional(),
10028
10014
  defaultModel: string().optional(),
10029
10015
  oauth: OAuthRefSchema.optional(),
@@ -14687,7 +14673,7 @@ async function refreshProviderModels(host, options = {}) {
14687
14673
  var BLUN_LOCAL_PROVIDER_NAME;
14688
14674
  var init_refreshProviderModels = __esmMin((() => {
14689
14675
  init_managed_blun();
14690
- BLUN_LOCAL_PROVIDER_NAME = "king-blun";
14676
+ BLUN_LOCAL_PROVIDER_NAME = "blun";
14691
14677
  }));
14692
14678
  //#endregion
14693
14679
  //#region ../../packages/oauth/src/index.ts
@@ -21405,7 +21391,10 @@ var init_flags = __esmMin((() => {
21405
21391
  var RawSubagentProfileSchema, RawAgentProfileSchema;
21406
21392
  var init_types$13 = __esmMin((() => {
21407
21393
  init_zod$1();
21408
- RawSubagentProfileSchema = object({ description: string().optional() });
21394
+ RawSubagentProfileSchema = object({
21395
+ description: string().optional(),
21396
+ skills: array(string()).optional()
21397
+ });
21409
21398
  RawAgentProfileSchema = object({
21410
21399
  extends: string().optional(),
21411
21400
  name: string().min(1),
@@ -28499,10 +28488,13 @@ function linkResolvedSubagents(mergedProfiles, resolvedProfiles) {
28499
28488
  for (const [ownerName, owner] of mergedProfiles) {
28500
28489
  if (owner.subagents === void 0) continue;
28501
28490
  const subagents = {};
28502
- for (const subagentName of Object.keys(owner.subagents)) {
28491
+ for (const [subagentName, subagentBinding] of Object.entries(owner.subagents)) {
28503
28492
  const target = resolvedProfiles.get(subagentName);
28504
28493
  if (target === void 0) throwMissingSubagent(ownerName, subagentName);
28505
- subagents[subagentName] = target;
28494
+ subagents[subagentName] = subagentBinding.skills === void 0 ? target : {
28495
+ ...target,
28496
+ subagentSkills: [...subagentBinding.skills]
28497
+ };
28506
28498
  }
28507
28499
  const resolved = resolvedProfiles.get(ownerName);
28508
28500
  if (resolved !== void 0) resolved.subagents = subagents;
@@ -28568,10 +28560,12 @@ var init_load = __esmMin((() => {
28568
28560
  //#region ../../packages/agent-core/src/profile/default/agent.yaml?raw
28569
28561
  var agent_default$1;
28570
28562
  var init_agent$3 = __esmMin((() => {
28571
- agent_default$1 = "name: agent\ndescription: Default BLUN King agent\n\nsystemPromptPath: ./system.md\npromptVars:\n roleAdditional: ''\n\ntools:\n - Read\n - Write\n - Edit\n - Grep\n - Glob\n - Bash\n - TaskList\n - TaskOutput\n - TaskUpdate\n - TaskStop\n - CronCreate\n - CronList\n - CronDelete\n - ReadMediaFile\n - TodoList\n - Skill\n - WebSearch\n - Agent\n - AgentSwarm\n - FetchURL\n - GenerateImage\n - GenerateVideo\n - GenerateSpeech\n - UnderstandImage\n - UnderstandVideo\n - DubVideo\n - LipSyncMedia\n - GetMedia\n - AskUserQuestion\n - MistakeRecord\n - CodebaseSearch\n - EnterPlanMode\n - ExitPlanMode\n - CreateGoal\n - GetGoal\n - SetGoalBudget\n - UpdateGoal\n - mcp__*\n\nsubagents:\n coder:\n description: General software engineering agent — the only subagent type with file-editing tools; use it for any delegated task that must modify code.\n explore:\n description: Fast codebase exploration with prompt-enforced read-only behavior.\n plan:\n description: Read-only implementation planning and architecture design.\n";
28563
+ agent_default$1 = "name: agent\ndescription: Default BLUN King agent\n\nsystemPromptPath: ./system.md\npromptVars:\n roleAdditional: ''\n\ntools:\n - Read\n - Write\n - Edit\n - Grep\n - Glob\n - Bash\n - TaskList\n - TaskOutput\n - TaskUpdate\n - TaskResume\n - TaskStop\n - CronCreate\n - CronList\n - CronDelete\n - ReadMediaFile\n - TodoList\n - Skill\n - WebSearch\n - Agent\n - AgentSwarm\n - FetchURL\n - GenerateImage\n - GenerateVideo\n - GenerateSpeech\n - UnderstandImage\n - UnderstandVideo\n - DubVideo\n - LipSyncMedia\n - GetMedia\n - AskUserQuestion\n - MistakeRecord\n - CodebaseSearch\n - EnterPlanMode\n - ExitPlanMode\n - CreateGoal\n - GetGoal\n - SetGoalBudget\n - UpdateGoal\n - mcp__*\n\nsubagents:\n coder:\n description: General software engineering agent — the only subagent type with file-editing tools; use it for any delegated task that must modify code.\n explore:\n description: Fast codebase exploration with prompt-enforced read-only behavior.\n plan:\n description: Read-only implementation planning and architecture design.\n";
28564
+ agent_default$1 = agent_default$1.replace(" plan:\n", " research:\n description: Read-only web and source research with an explicit two-skill allowlist.\n skills:\n - web-lesen\n - premortem\n plan:\n");
28572
28565
  agent_default$1 = agent_default$1.replace(" - Read\n", " - Read\n - ReadBatch\n");
28573
28566
  agent_default$1 = agent_default$1.replace(" - TodoList\n", " - TodoList\n - CompactConversation\n");
28574
28567
  agent_default$1 = agent_default$1.replace(" - CodebaseSearch\n", " - CodebaseSearch\n - ProgrammaticTool\n");
28568
+ agent_default$1 = agent_default$1.replace(" - CronList\n", " - CronList\n - CronRunList\n - CronRunOutput\n");
28575
28569
  }));
28576
28570
  //#endregion
28577
28571
  //#region ../../packages/agent-core/src/profile/default/coder.yaml?raw
@@ -28590,6 +28584,13 @@ var init_explore = __esmMin((() => {
28590
28584
  explore_default = explore_default.replace(" - ReadBatch\n", " - ReadBatch\n - ProgrammaticTool\n");
28591
28585
  }));
28592
28586
  //#endregion
28587
+ //#region ../../packages/agent-core/src/profile/default/research.yaml?raw
28588
+ var research_default;
28589
+ var init_research = __esmMin((() => {
28590
+ init_explore();
28591
+ research_default = explore_default.replace("name: explore\n", "name: research\n").replace("Fast agent specialized for exploring codebases.", "Read-only agent specialized for source and web research with profile-scoped skills.");
28592
+ }));
28593
+ //#endregion
28593
28594
  //#region ../../packages/agent-core/src/profile/default/init.md?raw
28594
28595
  var init_default$2;
28595
28596
  var init_init = __esmMin((() => {
@@ -28620,6 +28621,7 @@ var init_default$1 = __esmMin((() => {
28620
28621
  coder_default = coder_default.replace("\nwhenToUse:", "\nexcludedTools:\n - mcp__plugin-telegram_telegram__reply\n - mcp__plugin-telegram_telegram__react\n - mcp__plugin-telegram_telegram__edit_message\n - mcp__plugin-telegram_telegram__download_attachment\n\nwhenToUse:");
28621
28622
  init_explore();
28622
28623
  explore_default = explore_default.replace("\nwhenToUse:", "\nexcludedTools:\n - mcp__plugin-telegram_telegram__reply\n - mcp__plugin-telegram_telegram__react\n - mcp__plugin-telegram_telegram__edit_message\n - mcp__plugin-telegram_telegram__download_attachment\n\nwhenToUse:");
28624
+ init_research();
28623
28625
  init_init();
28624
28626
  init_plan$1();
28625
28627
  plan_default = plan_default.replace("\nwhenToUse:", "\nexcludedTools:\n - mcp__plugin-telegram_telegram__reply\n - mcp__plugin-telegram_telegram__react\n - mcp__plugin-telegram_telegram__edit_message\n - mcp__plugin-telegram_telegram__download_attachment\n\nwhenToUse:");
@@ -28630,6 +28632,7 @@ var init_default$1 = __esmMin((() => {
28630
28632
  "profile/default/agent.yaml": agent_default$1,
28631
28633
  "profile/default/coder.yaml": coder_default,
28632
28634
  "profile/default/explore.yaml": explore_default,
28635
+ "profile/default/research.yaml": research_default,
28633
28636
  "profile/default/plan.yaml": plan_default,
28634
28637
  "profile/default/system.md": system_default
28635
28638
  };
@@ -28638,6 +28641,7 @@ var init_default$1 = __esmMin((() => {
28638
28641
  "agent.yaml",
28639
28642
  "coder.yaml",
28640
28643
  "explore.yaml",
28644
+ "research.yaml",
28641
28645
  "plan.yaml"
28642
28646
  ].map((file) => `profile/default/${file}`), PROFILE_SOURCES);
28643
28647
  }));
@@ -29132,6 +29136,9 @@ var init_agent_task = __esmMin((() => {
29132
29136
  runInBackground;
29133
29137
  parentToolCallId;
29134
29138
  responseFormat;
29139
+ resumed;
29140
+ replacesTaskId;
29141
+ resumeRootTaskId;
29135
29142
  kind = "agent";
29136
29143
  idPrefix = "agent";
29137
29144
  agentId;
@@ -29145,6 +29152,9 @@ var init_agent_task = __esmMin((() => {
29145
29152
  this.runInBackground = options.runInBackground;
29146
29153
  this.parentToolCallId = options.parentToolCallId;
29147
29154
  this.responseFormat = options.responseFormat;
29155
+ this.resumed = options.resumed;
29156
+ this.replacesTaskId = options.replacesTaskId;
29157
+ this.resumeRootTaskId = options.resumeRootTaskId;
29148
29158
  this.agentId = handle.agentId;
29149
29159
  this.subagentType = handle.profileName;
29150
29160
  }
@@ -29197,7 +29207,10 @@ var init_agent_task = __esmMin((() => {
29197
29207
  timeoutMs: this.continuationTimeoutMs,
29198
29208
  kind: "agent",
29199
29209
  agentId: this.agentId,
29200
- subagentType: this.subagentType
29210
+ subagentType: this.subagentType,
29211
+ resumed: this.resumed,
29212
+ replacesTaskId: this.replacesTaskId,
29213
+ resumeRootTaskId: this.resumeRootTaskId
29201
29214
  };
29202
29215
  }
29203
29216
  };
@@ -29470,6 +29483,11 @@ function buildBackgroundTaskNotificationBody(info) {
29470
29483
  if (info.status === "completed") return baseLine;
29471
29484
  const agentId = info.agentId;
29472
29485
  if (agentId === void 0 || agentId === info.taskId) return baseLine;
29486
+ if (info.status === "lost") return `${baseLine}${[
29487
+ "",
29488
+ `To recover this interrupted background run explicitly, call TaskResume(task_id="${info.taskId}", prompt="Inspect the preserved state and continue without repeating completed side effects.", description="Resume ${info.description}").`,
29489
+ `TaskResume keeps agent_id "${agentId}" and its context, creates a new linked task_id, and never runs automatically at startup.`
29490
+ ].join("\n")}`;
29473
29491
  return `${baseLine}${[
29474
29492
  "",
29475
29493
  `To recover or continue this subagent, call Agent(resume="${agentId}", prompt="Pick up where you left off; redo the last tool call if its result was never observed.").`,
@@ -29478,7 +29496,7 @@ function buildBackgroundTaskNotificationBody(info) {
29478
29496
  "The subagent retains its full prior context across the restart, but any in-flight tool call lost its result and may need to be redone."
29479
29497
  ].join("\n")}`;
29480
29498
  }
29481
- var MAX_OUTPUT_BYTES$2, NOTIFICATION_FALLBACK_PREVIEW_BYTES, MAX_FOREGROUND_CAPTURE_BYTES, captureForegroundOutputChunk, createAbortOutcome, SIGTERM_GRACE_MS$1, USER_INTERRUPT_REASON$1, _ALPHABET, BackgroundManager;
29499
+ var MAX_OUTPUT_BYTES$2, NOTIFICATION_FALLBACK_PREVIEW_BYTES, MAX_FOREGROUND_CAPTURE_BYTES, captureForegroundOutputChunk, createAbortOutcome, DurableTaskResumeStore$1, decorateTaskInfo$1, SIGTERM_GRACE_MS$1, USER_INTERRUPT_REASON$1, _ALPHABET, BackgroundManager;
29482
29500
  var init_background = __esmMin((() => {
29483
29501
  init_dist$4();
29484
29502
  init_errors$4();
@@ -29494,13 +29512,17 @@ var init_background = __esmMin((() => {
29494
29512
  NOTIFICATION_FALLBACK_PREVIEW_BYTES = 3e3;
29495
29513
  ({ MAX_FOREGROUND_CAPTURE_BYTES, captureForegroundOutputChunk } = createRequire(import.meta.url)("./bin/foreground-output-capture-policy.cjs"));
29496
29514
  ({ createAbortOutcome } = createRequire(import.meta.url)("./bin/abort-listener-policy.cjs"));
29515
+ ({ DurableTaskResumeStore: DurableTaskResumeStore$1 } = createRequire(import.meta.url)("./bin/durable-task-resume-store.cjs"));
29516
+ ({ decorateTaskInfo: decorateTaskInfo$1 } = createRequire(import.meta.url)("./bin/durable-task-resume-policy.cjs"));
29497
29517
  SIGTERM_GRACE_MS$1 = 5e3;
29498
29518
  USER_INTERRUPT_REASON$1 = "Interrupted by user";
29499
29519
  _ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
29500
29520
  BackgroundManager = class {
29501
29521
  agent;
29502
29522
  persistence;
29523
+ resumeStore;
29503
29524
  tasks = /* @__PURE__ */ new Map();
29525
+ reservedTaskIds = /* @__PURE__ */ new Set();
29504
29526
  /**
29505
29527
  * Ghosts: tasks loaded from disk during reconcile that have no live
29506
29528
  * KaosProcess. They appear in `list()` / `getTask()` with status
@@ -29512,6 +29534,7 @@ var init_background = __esmMin((() => {
29512
29534
  constructor(agent, persistence) {
29513
29535
  this.agent = agent;
29514
29536
  this.persistence = persistence;
29537
+ this.resumeStore = persistence?.sessionDir ? new DurableTaskResumeStore$1(persistence.sessionDir) : void 0;
29515
29538
  }
29516
29539
  fireTerminalEffects(entry) {
29517
29540
  if (!this.isDetached(entry)) return;
@@ -29555,6 +29578,13 @@ var init_background = __esmMin((() => {
29555
29578
  isDetached(entry) {
29556
29579
  return entry.foregroundRelease === void 0;
29557
29580
  }
29581
+ reserveTaskId(prefix) {
29582
+ let taskId;
29583
+ do taskId = generateTaskId(prefix);
29584
+ while (this.tasks.has(taskId) || this.ghosts.has(taskId) || this.reservedTaskIds.has(taskId) || this.resumeStore?.list().some((intent) => intent.replacementTaskId === taskId));
29585
+ this.reservedTaskIds.add(taskId);
29586
+ return taskId;
29587
+ }
29558
29588
  registerTask(task, options = {}) {
29559
29589
  const detached = options.detached ?? true;
29560
29590
  const entryOptions = {
@@ -29564,7 +29594,10 @@ var init_background = __esmMin((() => {
29564
29594
  signal: detached ? void 0 : options.signal
29565
29595
  };
29566
29596
  this.assertCanRegister(detached);
29567
- const taskId = generateTaskId(task.idPrefix);
29597
+ const taskId = options.taskId ?? this.reserveTaskId(task.idPrefix);
29598
+ if (!VALID_TASK_ID$1.test(taskId)) throw new Error(`Invalid task id: "${taskId}"`);
29599
+ if (this.tasks.has(taskId) || this.ghosts.has(taskId)) throw new Error(`Task id already exists: ${taskId}`);
29600
+ this.reservedTaskIds.delete(taskId);
29568
29601
  const entry = {
29569
29602
  taskId,
29570
29603
  task,
@@ -29598,8 +29631,8 @@ var init_background = __esmMin((() => {
29598
29631
  /** Get info about a specific task. Falls back to reconcile ghosts. */
29599
29632
  getTask(taskId) {
29600
29633
  const entry = this.tasks.get(taskId);
29601
- if (entry !== void 0) return this.toInfo(entry);
29602
- return this.ghosts.get(taskId);
29634
+ const info = entry !== void 0 ? this.toInfo(entry) : this.ghosts.get(taskId);
29635
+ return decorateTaskInfo$1(info, this.resumeStore?.getBySourceTaskId(taskId));
29603
29636
  }
29604
29637
  updateAgentTask(taskId, message) {
29605
29638
  const entry = this.tasks.get(taskId);
@@ -29622,12 +29655,13 @@ var init_background = __esmMin((() => {
29622
29655
  list(activeOnly = true, limit) {
29623
29656
  const result = [];
29624
29657
  for (const entry of this.tasks.values()) {
29625
- const info = this.toInfo(entry);
29658
+ const info = decorateTaskInfo$1(this.toInfo(entry), this.resumeStore?.getBySourceTaskId(entry.taskId));
29626
29659
  if (!this.shouldListTask(info, activeOnly)) continue;
29627
29660
  result.push(info);
29628
29661
  if (limit !== void 0 && result.length >= limit) return result;
29629
29662
  }
29630
- if (!activeOnly) for (const ghost of this.ghosts.values()) {
29663
+ if (!activeOnly) for (const storedGhost of this.ghosts.values()) {
29664
+ const ghost = decorateTaskInfo$1(storedGhost, this.resumeStore?.getBySourceTaskId(storedGhost.taskId));
29631
29665
  if (!this.shouldListTask(ghost, activeOnly)) continue;
29632
29666
  result.push(ghost);
29633
29667
  if (limit !== void 0 && result.length >= limit) return result;
@@ -29775,6 +29809,7 @@ var init_background = __esmMin((() => {
29775
29809
  async loadFromDisk() {
29776
29810
  const persistence = this.persistence;
29777
29811
  if (persistence === void 0) return;
29812
+ await this.resumeStore?.load();
29778
29813
  this.ghosts.clear();
29779
29814
  const persisted = await persistence.listTasks();
29780
29815
  for (const t of persisted) {
@@ -29820,6 +29855,11 @@ var init_background = __esmMin((() => {
29820
29855
  entry.persistWriteQueue = entry.persistWriteQueue.then(() => persistence.writeTask(info)).catch(() => {});
29821
29856
  return entry.persistWriteQueue;
29822
29857
  }
29858
+ async awaitTaskPersisted(taskId) {
29859
+ const entry = this.tasks.get(taskId);
29860
+ if (entry === void 0) throw new Error(`Task not found: ${taskId}`);
29861
+ await entry.persistWriteQueue;
29862
+ }
29823
29863
  appendOutput(entry, chunk) {
29824
29864
  const capture = this.isDetached(entry) ? {
29825
29865
  capturedText: chunk,
@@ -30653,7 +30693,7 @@ var init_programmatic_tool = __esmMin((() => {
30653
30693
  PROGRAMMATIC_TOOL_NAME = "ProgrammaticTool";
30654
30694
  ProgrammaticTool = class {
30655
30695
  name = PROGRAMMATIC_TOOL_NAME;
30656
- description = "Run bounded JavaScript in an isolated QuickJS interpreter to coordinate several sequential BLUN tool calls without returning every intermediate value to the model context. Declare every callable tool explicitly with its current BLUN name and a JavaScript alias. Calls still pass through the normal schema, hook, permission, scheduler, event, and result pipeline; denied or unavailable tools fail inside the program. The interpreter has no host filesystem, network, process, package loader, clock, or dynamic eval. Return a JSON-serializable result and use the JSON state object only for explicit continuation.";
30696
+ description = "Run bounded JavaScript in an isolated QuickJS interpreter to coordinate several sequential BLUN tool calls without returning every intermediate value to the model context. Declare every callable tool explicitly with its current BLUN name and a JavaScript alias. Calls still pass through the normal schema, hook, permission, scheduler, event, and result pipeline; denied or unavailable tools fail inside the program. The interpreter has no host filesystem, network, process, package loader, clock, or dynamic eval. Use bounded console.log, console.warn, or console.error diagnostics when needed. Return a JSON-serializable result and use the JSON state object only for explicit continuation.";
30657
30697
  parameters = {
30658
30698
  type: "object",
30659
30699
  properties: {
@@ -30724,8 +30764,13 @@ var init_programmatic_tool = __esmMin((() => {
30724
30764
  if (context.invokeTool.stopTurn === true) result.stopTurn = true;
30725
30765
  return result;
30726
30766
  } catch (error) {
30767
+ const message = error instanceof Error ? error.message : String(error);
30768
+ const programmaticConsole = error && typeof error === "object" ? error.programmaticConsole : void 0;
30727
30769
  const result = {
30728
- output: error instanceof Error ? error.message : String(error),
30770
+ output: programmaticConsole ? JSON.stringify({
30771
+ error: message,
30772
+ console: programmaticConsole
30773
+ }) : message,
30729
30774
  isError: true
30730
30775
  };
30731
30776
  if (context.invokeTool.stopTurn === true) result.stopTurn = true;
@@ -75563,23 +75608,27 @@ var init_full = __esmMin((() => {
75563
75608
  const budget = this.strategy.compactionBudgetTokens;
75564
75609
  return budget !== void 0 && Number.isFinite(budget) && budget > 0 ? Math.floor(budget) : void 0;
75565
75610
  }
75566
- proactiveCompactionStatus() {
75567
- return proactiveCompactionEligibility({
75568
- usedTokens: this.estimateCurrentRequestTokens(),
75569
- budgetTokens: this.getCompactionBudgetTokens(),
75570
- hasShrinkableHistory: this.hasShrinkableHistory(this.agent.context.history),
75571
- isCompacting: this.isCompacting
75572
- });
75611
+ proactiveCompactionStatus(context = {}) {
75612
+ const usedTokens = this.estimateCurrentRequestTokens(context);
75613
+ return {
75614
+ ...proactiveCompactionEligibility({
75615
+ usedTokens,
75616
+ budgetTokens: this.getCompactionBudgetTokens(),
75617
+ hasShrinkableHistory: this.hasShrinkableHistory(this.agent.context.history),
75618
+ isCompacting: this.isCompacting
75619
+ }),
75620
+ usedTokens
75621
+ };
75573
75622
  }
75574
75623
  isProactiveCompactionEligible() {
75575
75624
  return this.proactiveCompactionStatus().eligible;
75576
75625
  }
75577
- requestProactiveCompaction() {
75578
- const status = this.proactiveCompactionStatus();
75626
+ requestProactiveCompaction(context = {}) {
75627
+ const status = this.proactiveCompactionStatus(context);
75579
75628
  if (!status.eligible) return status;
75580
75629
  this.proactiveCompactionRequested = true;
75581
75630
  this.agent.telemetry.track("proactive_compaction_requested", {
75582
- used_tokens: this.estimateCurrentRequestTokens(),
75631
+ used_tokens: status.usedTokens,
75583
75632
  threshold_tokens: status.thresholdTokens
75584
75633
  });
75585
75634
  return status;
@@ -75675,9 +75724,19 @@ var init_full = __esmMin((() => {
75675
75724
  const requestMessages = requestContext.messages ?? this.agent.context.messages;
75676
75725
  const projectedMessages = requestContext.additionalMessages === void 0 ? requestMessages : [...requestMessages, ...requestContext.additionalMessages];
75677
75726
  const requestTokens = this.estimateCurrentRequestTokens(requestContext);
75678
- const proactiveStatus = this.requestProactiveCompaction();
75727
+ const proactiveStatus = this.requestProactiveCompaction(requestContext);
75679
75728
  if (proactiveStatus.eligible) {
75680
75729
  this.proactiveCompactionRequested = false;
75730
+ this.agent.records.logRecord({
75731
+ type: "policy.intervention",
75732
+ policy: "proactive_compaction_trigger",
75733
+ location: "FullCompaction.beforeStep",
75734
+ size_before: this.estimateCurrentRequestTokens(),
75735
+ size_after: proactiveStatus.usedTokens,
75736
+ unit: "tokens",
75737
+ threshold_tokens: proactiveStatus.thresholdTokens,
75738
+ selected_tool_count: requestContext.tools?.length ?? 0
75739
+ });
75681
75740
  if (!this.compacting) this.beginAutoCompaction();
75682
75741
  await this.block(signal);
75683
75742
  }
@@ -76556,6 +76615,9 @@ function isValidCronTask(obj) {
76556
76615
  if (o["paused"] !== void 0 && typeof o["paused"] !== "boolean") return false;
76557
76616
  if (o["autoExpire"] !== void 0 && typeof o["autoExpire"] !== "boolean") return false;
76558
76617
  if (o["scheduleFromAt"] !== void 0 && (typeof o["scheduleFromAt"] !== "number" || !Number.isFinite(o["scheduleFromAt"]))) return false;
76618
+ if (o["allowedTools"] !== void 0 && (!Array.isArray(o["allowedTools"]) || !o["allowedTools"].every((name) => typeof name === "string"))) return false;
76619
+ if (o["allowedTools"] !== void 0 && typeof o["toolScopeDigest"] !== "string") return false;
76620
+ if (o["allowedTools"] === void 0 && o["toolScopeDigest"] !== void 0) return false;
76559
76621
  if (o["owner"] === "session-loop" && (typeof o["loopInterval"] !== "string" || o["loopInterval"].length === 0 || o["recurring"] === false || o["autoExpire"] !== false)) return false;
76560
76622
  return true;
76561
76623
  }
@@ -77333,7 +77395,7 @@ function hasUnfinishedTodoWork(agent) {
77333
77395
  const todos = agent.tools.storeData()["todo"];
77334
77396
  return Array.isArray(todos) && todos.some((todo) => todo?.status === "in_progress" || todo?.status === "pending");
77335
77397
  }
77336
- var STALE_THRESHOLD_MS, CronManager;
77398
+ var STALE_THRESHOLD_MS, normalizeCronAllowedTools, cronToolScopeForTask, filterToolsForCronScope, inheritedCronToolScope, createCronRunReceipt, buildCronFileCandidate, publicCronRunList, createCronRunStore, createMemoryCronRunStore, readCronFinalMessage, CronManager;
77337
77399
  var init_manager$3 = __esmMin((() => {
77338
77400
  init_clock();
77339
77401
  init_cron_fire_xml();
@@ -77341,6 +77403,17 @@ var init_manager$3 = __esmMin((() => {
77341
77403
  init_session_store$2();
77342
77404
  init_scheduler();
77343
77405
  init_telemetry_events();
77406
+ ({
77407
+ normalizeCronAllowedTools,
77408
+ cronToolScopeForTask,
77409
+ filterToolsForCronScope,
77410
+ inheritedCronToolScope,
77411
+ createCronRunReceipt,
77412
+ buildCronFileCandidate,
77413
+ publicCronRunList
77414
+ } = createRequire(import.meta.url)("./bin/scoped-cron-run-policy.cjs"));
77415
+ ({ createCronRunStore, createMemoryCronRunStore } = createRequire(import.meta.url)("./bin/cron-run-store.cjs"));
77416
+ ({ readCronFinalMessage } = createRequire(import.meta.url)("./bin/cron-run-output.cjs"));
77344
77417
  STALE_THRESHOLD_MS = 10080 * 60 * 1e3;
77345
77418
  CronManager = class {
77346
77419
  /** In-memory task store. Empty at construction; populated by
@@ -77376,6 +77449,11 @@ var init_manager$3 = __esmMin((() => {
77376
77449
  * later `blun resume` can reload via {@link loadFromDisk}.
77377
77450
  */
77378
77451
  persistStore;
77452
+ runStore;
77453
+ bufferedRuns = [];
77454
+ runByTurnId = /* @__PURE__ */ new Map();
77455
+ runAccumulators = /* @__PURE__ */ new Map();
77456
+ drainTimer = null;
77379
77457
  /**
77380
77458
  * Per-id serializer for persistence writes. Prevents a fast
77381
77459
  * `add` → `remove` sequence on the same id from racing each other on
@@ -77389,6 +77467,7 @@ var init_manager$3 = __esmMin((() => {
77389
77467
  this.store = new SessionCronStore();
77390
77468
  this.clocks = opts.clocks ?? resolveClockSources(process.env["BLUN_CRON_CLOCK"]) ?? SYSTEM_CLOCKS;
77391
77469
  this.persistStore = agent.homedir === void 0 ? void 0 : createCronPersistStore(agent.homedir);
77470
+ this.runStore = agent.homedir === void 0 ? createMemoryCronRunStore() : createCronRunStore(agent.homedir, { now: () => this.clocks.wallNow() });
77392
77471
  this.scheduler = createCronScheduler({
77393
77472
  clocks: this.clocks,
77394
77473
  source: () => this.store.list(),
@@ -77440,7 +77519,10 @@ var init_manager$3 = __esmMin((() => {
77440
77519
  */
77441
77520
  removeTasks(ids) {
77442
77521
  const removed = this.store.remove(ids);
77443
- for (const id of removed) this.persistEnqueue(id, () => this.persistStore.remove(id));
77522
+ for (const id of removed) {
77523
+ this.persistEnqueue(id, () => this.persistStore.remove(id));
77524
+ this.runStore.markJobDeletedById(id);
77525
+ }
77444
77526
  return removed;
77445
77527
  }
77446
77528
  updateTask(id, patch) {
@@ -77480,6 +77562,11 @@ var init_manager$3 = __esmMin((() => {
77480
77562
  * input, so a regenerated value would corrupt both.
77481
77563
  */
77482
77564
  async loadFromDisk() {
77565
+ const loadedRuns = this.runStore.load();
77566
+ for (const runId of loadedRuns.lostRunIds ?? []) {
77567
+ const receipt = this.runStore.get(runId);
77568
+ if (receipt !== void 0) this.emitRunTerminal(receipt);
77569
+ }
77483
77570
  if (this.persistStore === void 0) return;
77484
77571
  const tasks = await this.persistStore.list();
77485
77572
  this.store.clear();
@@ -77547,6 +77634,8 @@ var init_manager$3 = __esmMin((() => {
77547
77634
  * would be missing from the resume's `loadFromDisk()`.
77548
77635
  */
77549
77636
  async stop() {
77637
+ if (this.drainTimer !== null) clearTimeout(this.drainTimer);
77638
+ this.drainTimer = null;
77550
77639
  this.unbindSigusr1();
77551
77640
  await this.scheduler.stop();
77552
77641
  await this.flushPersist();
@@ -77612,24 +77701,49 @@ var init_manager$3 = __esmMin((() => {
77612
77701
  */
77613
77702
  handleFire(task, ctx) {
77614
77703
  const stale = this.isStale(task);
77704
+ const toolScope = cronToolScopeForTask(task);
77705
+ const runId = randomBytes(8).toString("hex");
77615
77706
  const origin = {
77616
77707
  kind: "cron_job",
77617
77708
  jobId: task.id,
77709
+ runId,
77618
77710
  cron: task.cron,
77619
77711
  recurring: task.recurring !== false,
77620
77712
  coalescedCount: ctx.coalescedCount,
77621
- stale
77713
+ stale,
77714
+ ...(toolScope.mode === "scoped" ? { toolScope } : {})
77622
77715
  };
77623
77716
  const content = [{
77624
77717
  type: "text",
77625
77718
  text: task.owner === "session-loop" ? renderSessionLoopWakeupXml(origin, task.prompt, task.loopInterval ?? "auto") : renderCronFireXml(origin, task.prompt)
77626
77719
  }];
77720
+ const receipt = createCronRunReceipt({
77721
+ runId,
77722
+ jobId: task.id,
77723
+ cron: task.cron,
77724
+ recurring: task.recurring !== false,
77725
+ stale,
77726
+ coalescedCount: ctx.coalescedCount,
77727
+ toolScopeDigest: toolScope.digest,
77728
+ firedAt: new Date(this.clocks.wallNow()).toISOString()
77729
+ });
77730
+ this.runStore.create(receipt);
77731
+ this.bufferedRuns.push({ runId, content, origin });
77732
+ this.runAccumulators.set(runId, {
77733
+ toolCalls: /* @__PURE__ */ new Map(),
77734
+ fileCandidates: /* @__PURE__ */ new Map(),
77735
+ outputs: [],
77736
+ finalStepId: null
77737
+ });
77738
+ this.agent.emitEvent({ type: "cron.fired", origin });
77627
77739
  this.agent.emitEvent({
77628
- type: "cron.fired",
77629
- origin,
77630
- prompt: task.prompt
77740
+ type: "cron.run.created",
77741
+ runId,
77742
+ jobId: task.id,
77743
+ coalescedCount: ctx.coalescedCount,
77744
+ toolScopeDigest: toolScope.digest
77631
77745
  });
77632
- const turnId = this.agent.turn.steer(content, origin);
77746
+ const turnId = this.launchBufferedRuns();
77633
77747
  this.agent.telemetry.track(CRON_FIRED, {
77634
77748
  recurring: task.recurring !== false,
77635
77749
  coalesced_count: ctx.coalescedCount,
@@ -77641,6 +77755,137 @@ var init_manager$3 = __esmMin((() => {
77641
77755
  this.emitDeleted(task.id);
77642
77756
  }
77643
77757
  }
77758
+ launchBufferedRuns() {
77759
+ if (this.bufferedRuns.length === 0) return null;
77760
+ if (this.agent.turn.hasActiveTurn || this.agent.fullCompaction.isCompacting) {
77761
+ this.scheduleBufferedRunDrain();
77762
+ return null;
77763
+ }
77764
+ const next = this.bufferedRuns.shift();
77765
+ const acceptance = this.agent.turn.promptWithAcceptance(next.content, next.origin);
77766
+ if (acceptance.accepted !== true || acceptance.turnId === null) {
77767
+ this.bufferedRuns.unshift(next);
77768
+ this.scheduleBufferedRunDrain();
77769
+ return null;
77770
+ }
77771
+ return acceptance.turnId;
77772
+ }
77773
+ scheduleBufferedRunDrain() {
77774
+ if (this.drainTimer !== null || this.bufferedRuns.length === 0) return;
77775
+ this.drainTimer = setTimeout(() => {
77776
+ this.drainTimer = null;
77777
+ this.launchBufferedRuns();
77778
+ }, 250);
77779
+ this.drainTimer.unref?.();
77780
+ }
77781
+ observeLoopEvent(turnId, event) {
77782
+ const runId = this.runByTurnId.get(turnId);
77783
+ if (runId === void 0) return;
77784
+ const accumulator = this.runAccumulators.get(runId);
77785
+ if (accumulator === void 0) return;
77786
+ if (event.type === "step.begin" && typeof event.uuid === "string") accumulator.finalStepId = event.uuid;
77787
+ if (event.type === "tool.call") {
77788
+ accumulator.toolCalls.set(event.toolCallId, { name: event.name, isError: false });
77789
+ const candidate = buildCronFileCandidate({
77790
+ toolName: event.name,
77791
+ toolCallId: event.toolCallId,
77792
+ display: event.display,
77793
+ workspaceRoot: this.agent.config.cwd,
77794
+ additionalRoots: this.agent.getAdditionalDirs(),
77795
+ pathExists: typeof event.display?.path === "string" && existsSync(event.display.path)
77796
+ });
77797
+ if (candidate !== null) accumulator.fileCandidates.set(event.toolCallId, candidate);
77798
+ }
77799
+ if (event.type === "tool.result") {
77800
+ const call = accumulator.toolCalls.get(event.toolCallId);
77801
+ if (call !== void 0) call.isError = event.result.isError === true;
77802
+ const candidate = accumulator.fileCandidates.get(event.toolCallId);
77803
+ if (candidate !== void 0 && event.result.isError !== true) accumulator.outputs.push(candidate);
77804
+ accumulator.fileCandidates.delete(event.toolCallId);
77805
+ }
77806
+ }
77807
+ observeAgentEvent(event) {
77808
+ if (event.type === "turn.started") {
77809
+ const runId = event.origin?.kind === "cron_job" && typeof event.origin.runId === "string" ? event.origin.runId : event.origin?.kind === "system_trigger" && typeof event.origin.cronRunId === "string" ? event.origin.cronRunId : void 0;
77810
+ if (runId === void 0) return;
77811
+ const receipt = this.runStore.get(runId);
77812
+ if (receipt?.status !== "buffered" && receipt?.status !== "running") return;
77813
+ this.runByTurnId.set(event.turnId, runId);
77814
+ if (receipt.status === "buffered") {
77815
+ const running = this.runStore.transition(runId, "running", {
77816
+ turnId: event.turnId,
77817
+ startedAt: new Date(this.clocks.wallNow()).toISOString()
77818
+ });
77819
+ this.agent.emitEvent({
77820
+ type: "cron.run.started",
77821
+ runId: running.runId,
77822
+ jobId: running.jobId,
77823
+ turnId: event.turnId
77824
+ });
77825
+ }
77826
+ return;
77827
+ }
77828
+ if (event.type !== "turn.ended") return;
77829
+ const runId = this.runByTurnId.get(event.turnId);
77830
+ if (runId === void 0) return;
77831
+ const accumulator = this.runAccumulators.get(runId);
77832
+ if (accumulator !== void 0) accumulator.lastTurnEnd = event;
77833
+ this.runByTurnId.delete(event.turnId);
77834
+ }
77835
+ observeRunWorkerEnded(runId, event) {
77836
+ const current = this.runStore.get(runId);
77837
+ if (current?.status !== "running" && current?.status !== "buffered") return;
77838
+ const accumulator = this.runAccumulators.get(runId) ?? {
77839
+ toolCalls: /* @__PURE__ */ new Map(),
77840
+ outputs: [],
77841
+ finalStepId: null
77842
+ };
77843
+ const status = event.reason === "cancelled" ? "cancelled" : event.reason === "failed" || event.reason === "filtered" ? "failed" : "completed";
77844
+ const terminal = this.runStore.transition(runId, status, {
77845
+ endedAt: new Date(this.clocks.wallNow()).toISOString(),
77846
+ toolCalls: [...accumulator.toolCalls.values()],
77847
+ outputs: accumulator.outputs,
77848
+ finalStepId: accumulator.finalStepId,
77849
+ error: status === "failed" ? {
77850
+ category: event.reason === "filtered" ? "policy" : "executor",
77851
+ code: event.error?.code ?? (event.reason === "filtered" ? "PROVIDER_FILTERED" : "TURN_FAILED")
77852
+ } : void 0
77853
+ });
77854
+ this.emitRunTerminal(terminal);
77855
+ this.runAccumulators.delete(runId);
77856
+ this.scheduleBufferedRunDrain();
77857
+ }
77858
+ observeRunWorkerFailed(runId) {
77859
+ this.observeRunWorkerEnded(runId, {
77860
+ reason: "failed",
77861
+ error: { code: "TURN_WORKER_FAILED" }
77862
+ });
77863
+ }
77864
+ emitRunTerminal(receipt) {
77865
+ const durationMs = receipt.startedAt === null || receipt.endedAt === null ? void 0 : Math.max(0, Date.parse(receipt.endedAt) - Date.parse(receipt.startedAt));
77866
+ this.agent.emitEvent({
77867
+ type: `cron.run.${receipt.status}`,
77868
+ runId: receipt.runId,
77869
+ jobId: receipt.jobId,
77870
+ durationMs,
77871
+ toolCalls: receipt.toolSummary.calls,
77872
+ toolErrors: receipt.toolSummary.errors,
77873
+ outputCount: receipt.outputs.length,
77874
+ errorCategory: receipt.error?.category
77875
+ });
77876
+ }
77877
+ listRuns(filters) {
77878
+ return publicCronRunList(this.runStore.list(), filters);
77879
+ }
77880
+ readRunOutput(runId) {
77881
+ const receipt = this.runStore.get(runId);
77882
+ if (receipt === void 0) return null;
77883
+ let finalMessage = null;
77884
+ if (receipt.finalMessageRef !== null && this.agent.homedir !== void 0) try {
77885
+ finalMessage = readCronFinalMessage(join$4(this.agent.homedir, "wire.jsonl"), receipt.finalMessageRef.stepId);
77886
+ } catch {}
77887
+ return { receipt, finalMessage };
77888
+ }
77644
77889
  /**
77645
77890
  * Reserved hook for an explicit "you missed N fires while offline"
77646
77891
  * banner. Today the scheduler's `coalescedCount` semantics already
@@ -78105,7 +78350,8 @@ var init_cron_create = __esmMin((() => {
78105
78350
  CronCreateInputSchema = object({
78106
78351
  cron: string().describe("5-field cron expression in local time: \"M H DoM Mon DoW\" (e.g. \"*/5 * * * *\" = every 5 minutes; \"30 14 28 2 *\" = Feb 28 at 2:30pm local — a pinned date like this repeats yearly unless you also pass recurring: false)."),
78107
78352
  prompt: string().min(1).max(MAX_PROMPT_BYTES).describe("The prompt to enqueue at each fire time. Limited to 8 KiB (UTF-8)."),
78108
- recurring: boolean$1().optional().default(true).describe("true (default) = fire on every cron match until deleted or auto-expired after 7 days. false = fire once at the next match, then auto-delete. Use false for \"remind me at X\" one-shot requests with pinned minute/hour/dom/month.")
78353
+ recurring: boolean$1().optional().default(true).describe("true (default) = fire on every cron match until deleted or auto-expired after 7 days. false = fire once at the next match, then auto-delete. Use false for \"remind me at X\" one-shot requests with pinned minute/hour/dom/month."),
78354
+ allowed_tools: array(string()).max(64).optional().describe("Optional exact tool names allowed in each isolated run. Omit for legacy behavior; an empty array allows no tools. Wildcards and unknown tools are rejected.")
78109
78355
  });
78110
78356
  CronCreateTool = class {
78111
78357
  manager;
@@ -78145,6 +78391,15 @@ var init_cron_create = __esmMin((() => {
78145
78391
  output: `Prompt exceeds ${String(MAX_PROMPT_BYTES)} bytes (got ${String(byteLen)}).`
78146
78392
  };
78147
78393
  const recurring = args.recurring !== false;
78394
+ let toolScope;
78395
+ try {
78396
+ toolScope = normalizeCronAllowedTools(args.allowed_tools, this.manager.agent.tools.loopTools);
78397
+ } catch (error) {
78398
+ return {
78399
+ isError: true,
78400
+ output: error instanceof Error ? error.message : String(error)
78401
+ };
78402
+ }
78148
78403
  if (!recurring) {
78149
78404
  const firstFire = computeNextCronRun(parsed, nowAtPrepare);
78150
78405
  if (firstFire !== null && firstFire - nowAtPrepare > ONE_SHOT_MAX_FUTURE_MS) return {
@@ -78157,7 +78412,8 @@ var init_cron_create = __esmMin((() => {
78157
78412
  approvalRule: literalRulePattern(this.name, JSON.stringify({
78158
78413
  cron: normalizedCron,
78159
78414
  prompt: args.prompt,
78160
- recurring
78415
+ recurring,
78416
+ ...(args.allowed_tools === void 0 ? {} : { allowed_tools: toolScope.names })
78161
78417
  })),
78162
78418
  execute: async () => {
78163
78419
  const nowMs = this.manager.clocks.wallNow();
@@ -78168,7 +78424,11 @@ var init_cron_create = __esmMin((() => {
78168
78424
  const task = this.manager.addTask({
78169
78425
  cron: normalizedCron,
78170
78426
  prompt: args.prompt,
78171
- recurring
78427
+ recurring,
78428
+ ...(toolScope.mode === "scoped" ? {
78429
+ allowedTools: toolScope.names,
78430
+ toolScopeDigest: toolScope.digest
78431
+ } : {})
78172
78432
  });
78173
78433
  const ideal = computeNextCronRun(parsed, nowMs);
78174
78434
  const nextFireAt = ideal === null ? null : recurring ? jitteredNextCronRunMs(task, parsed, ideal) : oneShotJitteredNextCronRunMs(task, ideal);
@@ -79135,6 +79395,14 @@ var init_context$2 = __esmMin((() => {
79135
79395
  keptHeadUserMessageCount,
79136
79396
  droppedCount: input.droppedCount
79137
79397
  };
79398
+ this.agent.records.logRecord({
79399
+ type: "policy.intervention",
79400
+ policy: "full_context_compaction",
79401
+ location: "AgentContext.applyCompaction",
79402
+ size_before: result.tokensBefore,
79403
+ size_after: result.tokensAfter,
79404
+ unit: "tokens"
79405
+ });
79138
79406
  this.agent.records.logRecord({
79139
79407
  type: "context.apply_compaction",
79140
79408
  ...result
@@ -79195,6 +79463,7 @@ var init_context$2 = __esmMin((() => {
79195
79463
  }
79196
79464
  project(messages, options) {
79197
79465
  const anomalies = [];
79466
+ const underPressure = toolResultOffloadPressureForAgent(this.agent);
79198
79467
  const userOffloaded = this.agent.userMessageOffload.compact(messages);
79199
79468
  const historicalMediaProjected = projectHistoricalMediaParts(userOffloaded);
79200
79469
  const historicalUserReferencesProjected = compactHistoricalPersistedUserMessageReferences(historicalMediaProjected);
@@ -79202,7 +79471,9 @@ var init_context$2 = __esmMin((() => {
79202
79471
  const historicalTelegramProjected = projectHistoricalUnaddressedTelegramMessages(duplicateUserMessagesProjected);
79203
79472
  const assistantOffloaded = this.agent.assistantMessageOffload.compact(historicalTelegramProjected);
79204
79473
  const repeatedAssistantProjected = projectRepeatedAssistantResponses(assistantOffloaded);
79205
- const result = project(this.agent.microCompaction.compact(compactHistoricalSuccessfulToolResults(dedupeRepeatedSuccessfulToolResults(repeatedAssistantProjected, this.agent.toolResultBatchOffload.compact(dedupeRecurringCronWakeups(dedupeRepeatedInjections(compactHistoricalSkillActivations(compactBaselineSkillInjections(repeatedAssistantProjected)))))))), {
79474
+ const batchProjected = this.agent.toolResultBatchOffload.compact(dedupeRecurringCronWakeups(dedupeRepeatedInjections(compactHistoricalSkillActivations(compactBaselineSkillInjections(repeatedAssistantProjected)))));
79475
+ const toolResultsProjected = compactHistoricalSuccessfulToolResults(dedupeRepeatedSuccessfulToolResults(repeatedAssistantProjected, batchProjected), { underPressure });
79476
+ const result = project(this.agent.microCompaction.compact(toolResultsProjected), {
79206
79477
  ...options,
79207
79478
  onAnomaly: (anomaly) => {
79208
79479
  anomalies.push(anomaly);
@@ -233897,9 +234168,9 @@ var init_plan_mode_guard_deny = __esmMin((() => {
233897
234168
  message: planModeWriteDeniedMessage(planFilePath)
233898
234169
  };
233899
234170
  }
233900
- if (toolName === "TaskStop") return {
234171
+ if (toolName === "TaskStop" || toolName === "TaskResume") return {
233901
234172
  kind: "deny",
233902
- message: "TaskStop is not available in plan mode. Call ExitPlanMode to exit plan mode before stopping a background task."
234173
+ message: `${toolName} is not available in plan mode. Call ExitPlanMode before changing background task execution.`
233903
234174
  };
233904
234175
  if (toolName === "CronCreate" || toolName === "CronDelete") return {
233905
234176
  kind: "deny",
@@ -234265,6 +234536,16 @@ var init_permission = __esmMin((() => {
234265
234536
  if (pattern === void 0) return;
234266
234537
  this.localSessionApprovalRulePatterns.add(pattern);
234267
234538
  }
234539
+ recordApprovalEdited(context, editedArgs) {
234540
+ const event = buildApprovalEditedEvent({
234541
+ turnId: Number(context.turnId),
234542
+ toolCallId: context.toolCall.id,
234543
+ toolName: context.toolCall.name,
234544
+ originalArgs: context.args,
234545
+ editedArgs
234546
+ });
234547
+ this.agent.records.logRecord(event);
234548
+ }
234268
234549
  get sessionApprovalRulePatterns() {
234269
234550
  return [...this.localSessionApprovalRulePatterns, ...this.parent?.sessionApprovalRulePatterns ?? []];
234270
234551
  }
@@ -234284,6 +234565,8 @@ var init_permission = __esmMin((() => {
234284
234565
  const { signal } = context;
234285
234566
  const id = context.toolCall.id;
234286
234567
  const name = context.toolCall.name;
234568
+ const approvalEditCount = Number.isSafeInteger(context.approvalEditCount) ? context.approvalEditCount : 0;
234569
+ const allowEdit = approvalEditCount === 0 && isEditableToolApprovalEligible(name);
234287
234570
  const display = context.execution.display ?? {
234288
234571
  kind: "generic",
234289
234572
  summary: context.execution.description ?? `Approve ${name}`,
@@ -234321,7 +234604,10 @@ var init_permission = __esmMin((() => {
234321
234604
  toolCallId: id,
234322
234605
  toolName: name,
234323
234606
  action,
234324
- display
234607
+ display,
234608
+ allowEdit,
234609
+ approvalEditCount,
234610
+ editableToolInput: allowEdit ? context.args : void 0
234325
234611
  }, { signal });
234326
234612
  } catch (error) {
234327
234613
  this.agent.telemetry.track("permission_approval_result", {
@@ -234349,6 +234635,19 @@ var init_permission = __esmMin((() => {
234349
234635
  return resolved === void 0 ? Promise.reject(error) : this.permissionPolicyResolutionToPrepare(resolved, context, policyName);
234350
234636
  }
234351
234637
  } else response = { decision: "approved" };
234638
+ let editedDecision;
234639
+ if (response.decision === "edited") try {
234640
+ editedDecision = validateEditedApprovalDecision({
234641
+ response,
234642
+ toolName: name,
234643
+ editCount: approvalEditCount
234644
+ });
234645
+ } catch (error) {
234646
+ response = {
234647
+ decision: "rejected",
234648
+ feedback: `Edited approval was rejected before tool preparation: ${error instanceof Error ? error.message : String(error)}`
234649
+ };
234650
+ }
234352
234651
  const sessionApprovalRule = response.decision === "approved" && response.scope === "session" ? context.execution.approvalRule : void 0;
234353
234652
  if (requestedApproval) this.agent.hooks?.fireAndForgetTrigger?.("PermissionResult", {
234354
234653
  matcherValue: name,
@@ -234363,13 +234662,14 @@ var init_permission = __esmMin((() => {
234363
234662
  selectedLabel: response.selectedLabel
234364
234663
  }
234365
234664
  });
234665
+ const approvalRecordResponse = response.decision === "edited" ? { decision: "edited" } : response;
234366
234666
  this.recordApprovalResult({
234367
234667
  turnId: Number(context.turnId),
234368
234668
  toolCallId: id,
234369
234669
  toolName: name,
234370
234670
  action,
234371
234671
  sessionApprovalRule,
234372
- result: response
234672
+ result: approvalRecordResponse
234373
234673
  });
234374
234674
  this.agent.telemetry.track("permission_approval_result", {
234375
234675
  policy_name: policyName ?? null,
@@ -234381,6 +234681,17 @@ var init_permission = __esmMin((() => {
234381
234681
  session_cache_written: sessionApprovalRule !== void 0,
234382
234682
  has_feedback: response.feedback !== void 0 && response.feedback.length > 0
234383
234683
  });
234684
+ if (response.decision === "edited" && editedDecision !== void 0) {
234685
+ let recorded = false;
234686
+ return { approvalEdit: {
234687
+ args: editedDecision.editedToolInput,
234688
+ record: (validatedArgs) => {
234689
+ if (recorded) throw new Error("Edited approval Wire event was already recorded");
234690
+ recorded = true;
234691
+ this.recordApprovalEdited(context, validatedArgs);
234692
+ }
234693
+ } };
234694
+ }
234384
234695
  const resolved = result.resolveApproval?.(response);
234385
234696
  if (resolved !== void 0) return this.permissionPolicyResolutionToPrepare(resolved, context, policyName);
234386
234697
  if (response.decision === "approved") return;
@@ -244306,7 +244617,7 @@ function validateExecutableToolArgs(tool, args) {
244306
244617
  }
244307
244618
  return validateToolArgs(validator, args);
244308
244619
  }
244309
- async function prepareToolCall(step, call) {
244620
+ async function prepareToolCall(step, call, approvalEditCount = 0) {
244310
244621
  const settleError = async (args, output, displayFields) => {
244311
244622
  await dispatchToolCall(step, call, args, displayFields);
244312
244623
  return { task: makeResolvedToolCallTask(makeErrorToolResult(call, args, output)) };
@@ -244341,10 +244652,31 @@ async function prepareToolCall(step, call) {
244341
244652
  const settleAborted = () => settleError(effectiveArgs, abortedToolOutput(call.toolName, step.signal), displayFields);
244342
244653
  if (step.signal.aborted) return settleAborted();
244343
244654
  if (execution.isError === true) return settleSynthetic(effectiveArgs, execution, displayFields);
244344
- const authorization = await runAuthorizeToolExecutionHook(step, call, effectiveArgs, execution);
244655
+ const authorization = await runAuthorizeToolExecutionHook(step, call, effectiveArgs, execution, approvalEditCount);
244345
244656
  if (step.signal.aborted) return settleAborted();
244346
244657
  if (authorization?.block === true) return settleError(effectiveArgs, authorization.reason ?? `Tool call "${call.toolName}" was blocked`, displayFields);
244347
244658
  if (authorization?.syntheticResult !== void 0) return settleSynthetic(effectiveArgs, authorization.syntheticResult, displayFields);
244659
+ if (authorization?.approvalEdit !== void 0) {
244660
+ let plan;
244661
+ try {
244662
+ plan = buildEditedToolCallPlan({
244663
+ step,
244664
+ call,
244665
+ editedArgs: authorization.approvalEdit.args,
244666
+ editCount: approvalEditCount,
244667
+ preflightToolCall
244668
+ });
244669
+ } catch (error) {
244670
+ return settleError(authorization.approvalEdit.args, `Edited approval could not be re-prepared: ${errorMessage$12(error)}`, displayFields);
244671
+ }
244672
+ if (plan.kind === "rejected") return settleError(plan.call.args, plan.output ?? `Edited args for tool "${call.toolName}" were rejected`, displayFields);
244673
+ try {
244674
+ authorization.approvalEdit.record(plan.call.args);
244675
+ } catch (error) {
244676
+ return settleError(plan.call.args, `Edited approval evidence could not be recorded: ${errorMessage$12(error)}`, displayFields);
244677
+ }
244678
+ return prepareToolCall(plan.step, plan.call, plan.editCount);
244679
+ }
244348
244680
  const executionMetadata = authorization?.executionMetadata ?? decision.metadata;
244349
244681
  await dispatchToolCall(step, call, effectiveArgs, displayFields);
244350
244682
  return {
@@ -244418,7 +244750,7 @@ async function runPrepareToolExecutionHook(step, call) {
244418
244750
  metadata: hookResult?.executionMetadata
244419
244751
  };
244420
244752
  }
244421
- async function runAuthorizeToolExecutionHook(step, call, args, execution) {
244753
+ async function runAuthorizeToolExecutionHook(step, call, args, execution, approvalEditCount = 0) {
244422
244754
  const { hooks, signal, turnId, currentStep, llm } = step;
244423
244755
  if (hooks?.authorizeToolExecution === void 0) return void 0;
244424
244756
  try {
@@ -244428,6 +244760,7 @@ async function runAuthorizeToolExecutionHook(step, call, args, execution) {
244428
244760
  tool: call.tool,
244429
244761
  args,
244430
244762
  execution,
244763
+ approvalEditCount,
244431
244764
  turnId,
244432
244765
  stepNumber: currentStep,
244433
244766
  signal,
@@ -245955,7 +246288,7 @@ var init_modelCatalog$2 = __esmMin((() => {
245955
246288
  function isVolatileEventType(type) {
245956
246289
  return volatileEventTypeSet.has(type);
245957
246290
  }
245958
- var MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, tokenUsageSchema, finishReasonSchema, usageStatusSchema, permissionModeSchema, skillSourceSchema, userPromptOriginSchema, skillActivationOriginSchema, pluginCommandOriginSchema, injectionOriginSchema, shellCommandOriginSchema, compactionSummaryOriginSchema, systemTriggerOriginSchema, agentCoreBackgroundTaskStatusSchema, backgroundTaskOriginSchema, cronJobOriginSchema, cronMissedOriginSchema, hookResultOriginSchema, retryOriginSchema, promptOriginSchema, goalStatusSchema, goalActorSchema, goalBudgetReportSchema, goalSnapshotSchema, goalChangeStatsSchema, goalChangeKindSchema, goalChangeSchema, blunErrorCodeSchema, blunErrorPayloadSchema, backgroundTaskInfoBaseSchema, processBackgroundTaskInfoSchema, agentBackgroundTaskInfoSchema, questionBackgroundTaskInfoSchema, backgroundTaskInfoSchema, compactionResultSchema, toolUpdateSchema, turnEndReasonSchema, agentStatusUpdatedEventSchema, sessionMetaUpdatedEventSchema, sessionCreatedEventSchema, workspaceCreatedEventSchema, workspaceUpdatedEventSchema, workspaceDeletedEventSchema, sessionStatusChangedEventSchema, modelCatalogChangedEventSchema, goalUpdatedEventSchema, skillActivatedEventSchema, pluginCommandActivatedEventSchema, errorEventSchema, warningEventSchema, turnStartedEventSchema, turnEndedEventSchema, turnStepStartedEventSchema, turnStepCompletedEventSchema, turnStepRetryingEventSchema, turnStepInterruptedEventSchema, assistantDeltaEventSchema, hookResultEventSchema, thinkingDeltaEventSchema, toolCallDeltaEventSchema, toolCallStartedEventSchema, toolProgressEventSchema, shellOutputEventSchema, shellStartedEventSchema, toolResultEventSchema, subagentSpawnedEventSchema, subagentStartedEventSchema, subagentSuspendedEventSchema, subagentCompletedEventSchema, subagentFailedEventSchema, compactionStartedEventSchema, compactionBlockedEventSchema, compactionCancelledEventSchema, compactionProgressEventSchema, compactionCompletedEventSchema, backgroundTaskStartedEventSchema, backgroundTaskTerminatedEventSchema, cronFiredEventSchema, attentionIntentSchema, attentionAuthorizedEventSchema, promptSubmittedEventSchema, toolListUpdatedReasonSchema, toolListUpdatedEventSchema, mcpServerStatusPayloadSchema, mcpServerStatusEventSchema, mediaDroppedEventSchema, agentEventSchema, eventSchema, VOLATILE_EVENT_TYPES, volatileEventTypeSet;
246291
+ var MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, tokenUsageSchema, finishReasonSchema, usageStatusSchema, permissionModeSchema, skillSourceSchema, userPromptOriginSchema, skillActivationOriginSchema, pluginCommandOriginSchema, injectionOriginSchema, shellCommandOriginSchema, compactionSummaryOriginSchema, cronToolScopeSchema, systemTriggerOriginSchema, agentCoreBackgroundTaskStatusSchema, backgroundTaskOriginSchema, cronJobOriginSchema, cronMissedOriginSchema, hookResultOriginSchema, retryOriginSchema, promptOriginSchema, goalStatusSchema, goalActorSchema, goalBudgetReportSchema, goalSnapshotSchema, goalChangeStatsSchema, goalChangeKindSchema, goalChangeSchema, blunErrorCodeSchema, blunErrorPayloadSchema, backgroundTaskInfoBaseSchema, processBackgroundTaskInfoSchema, agentBackgroundTaskInfoSchema, questionBackgroundTaskInfoSchema, backgroundTaskInfoSchema, compactionResultSchema, toolUpdateSchema, turnEndReasonSchema, agentStatusUpdatedEventSchema, sessionMetaUpdatedEventSchema, sessionCreatedEventSchema, workspaceCreatedEventSchema, workspaceUpdatedEventSchema, workspaceDeletedEventSchema, sessionStatusChangedEventSchema, modelCatalogChangedEventSchema, goalUpdatedEventSchema, skillActivatedEventSchema, pluginCommandActivatedEventSchema, errorEventSchema, warningEventSchema, turnStartedEventSchema, turnEndedEventSchema, turnStepStartedEventSchema, turnStepCompletedEventSchema, turnStepRetryingEventSchema, turnStepInterruptedEventSchema, assistantDeltaEventSchema, hookResultEventSchema, thinkingDeltaEventSchema, toolCallDeltaEventSchema, toolCallStartedEventSchema, toolProgressEventSchema, shellOutputEventSchema, shellStartedEventSchema, toolResultEventSchema, subagentSpawnedEventSchema, subagentStartedEventSchema, subagentSuspendedEventSchema, subagentCompletedEventSchema, subagentFailedEventSchema, compactionStartedEventSchema, compactionBlockedEventSchema, compactionCancelledEventSchema, compactionProgressEventSchema, compactionCompletedEventSchema, backgroundTaskStartedEventSchema, backgroundTaskTerminatedEventSchema, cronFiredEventSchema, cronRunCreatedEventSchema, cronRunStartedEventSchema, cronRunTerminalEventSchema, attentionIntentSchema, attentionAuthorizedEventSchema, promptSubmittedEventSchema, toolListUpdatedReasonSchema, toolListUpdatedEventSchema, mcpServerStatusPayloadSchema, mcpServerStatusEventSchema, mediaDroppedEventSchema, agentEventSchema, eventSchema, VOLATILE_EVENT_TYPES, volatileEventTypeSet;
245959
246292
  var init_events$1 = __esmMin((() => {
245960
246293
  init_zod$1();
245961
246294
  init_display();
@@ -246029,9 +246362,16 @@ var init_events$1 = __esmMin((() => {
246029
246362
  isError: boolean$1().optional()
246030
246363
  });
246031
246364
  compactionSummaryOriginSchema = object({ kind: literal("compaction_summary") });
246365
+ cronToolScopeSchema = object({
246366
+ mode: literal("scoped"),
246367
+ names: array(string()).max(64),
246368
+ digest: string()
246369
+ });
246032
246370
  systemTriggerOriginSchema = object({
246033
246371
  kind: literal("system_trigger"),
246034
- name: string()
246372
+ name: string(),
246373
+ cronRunId: string().optional(),
246374
+ toolScope: cronToolScopeSchema.optional()
246035
246375
  });
246036
246376
  agentCoreBackgroundTaskStatusSchema = _enum([
246037
246377
  "running",
@@ -246050,10 +246390,12 @@ var init_events$1 = __esmMin((() => {
246050
246390
  cronJobOriginSchema = object({
246051
246391
  kind: literal("cron_job"),
246052
246392
  jobId: string(),
246393
+ runId: string().optional(),
246053
246394
  cron: string(),
246054
246395
  recurring: boolean$1(),
246055
246396
  coalescedCount: number$1(),
246056
- stale: boolean$1()
246397
+ stale: boolean$1(),
246398
+ toolScope: cronToolScopeSchema.optional()
246057
246399
  });
246058
246400
  cronMissedOriginSchema = object({
246059
246401
  kind: literal("cron_missed"),
@@ -246066,7 +246408,8 @@ var init_events$1 = __esmMin((() => {
246066
246408
  });
246067
246409
  retryOriginSchema = object({
246068
246410
  kind: literal("retry"),
246069
- trigger: string().optional()
246411
+ trigger: string().optional(),
246412
+ toolScope: cronToolScopeSchema.optional()
246070
246413
  });
246071
246414
  promptOriginSchema = discriminatedUnion("kind", [
246072
246415
  userPromptOriginSchema,
@@ -246586,8 +246929,30 @@ var init_events$1 = __esmMin((() => {
246586
246929
  });
246587
246930
  cronFiredEventSchema = object({
246588
246931
  type: literal("cron.fired"),
246589
- origin: cronJobOriginSchema,
246590
- prompt: string()
246932
+ origin: cronJobOriginSchema
246933
+ });
246934
+ cronRunCreatedEventSchema = object({
246935
+ type: literal("cron.run.created"),
246936
+ runId: string(),
246937
+ jobId: string(),
246938
+ coalescedCount: number$1(),
246939
+ toolScopeDigest: string().nullable()
246940
+ });
246941
+ cronRunStartedEventSchema = object({
246942
+ type: literal("cron.run.started"),
246943
+ runId: string(),
246944
+ jobId: string(),
246945
+ turnId: number$1()
246946
+ });
246947
+ cronRunTerminalEventSchema = object({
246948
+ type: _enum(["cron.run.completed", "cron.run.failed", "cron.run.cancelled", "cron.run.lost"]),
246949
+ runId: string(),
246950
+ jobId: string(),
246951
+ durationMs: number$1().optional(),
246952
+ toolCalls: number$1(),
246953
+ toolErrors: number$1(),
246954
+ outputCount: number$1(),
246955
+ errorCategory: string().optional()
246591
246956
  });
246592
246957
  attentionIntentSchema = object({
246593
246958
  accepted: literal(true),
@@ -246701,6 +247066,9 @@ var init_events$1 = __esmMin((() => {
246701
247066
  backgroundTaskStartedEventSchema,
246702
247067
  backgroundTaskTerminatedEventSchema,
246703
247068
  cronFiredEventSchema,
247069
+ cronRunCreatedEventSchema,
247070
+ cronRunStartedEventSchema,
247071
+ cronRunTerminalEventSchema,
246704
247072
  attentionAuthorizedEventSchema,
246705
247073
  promptSubmittedEventSchema
246706
247074
  ]);
@@ -247246,7 +247614,8 @@ var init_approval$2 = __esmMin((() => {
247246
247614
  approvalDecisionSchema = _enum([
247247
247615
  "approved",
247248
247616
  "rejected",
247249
- "cancelled"
247617
+ "cancelled",
247618
+ "edited"
247250
247619
  ]);
247251
247620
  approvalScopeSchema = _enum(["session"]);
247252
247621
  approvalRequestSchema = object({
@@ -247257,6 +247626,7 @@ var init_approval$2 = __esmMin((() => {
247257
247626
  tool_name: string().min(1),
247258
247627
  action: string(),
247259
247628
  tool_input_display: unknown(),
247629
+ allow_edit: boolean$1().optional(),
247260
247630
  created_at: isoDateTimeSchema,
247261
247631
  expires_at: isoDateTimeSchema
247262
247632
  });
@@ -247264,7 +247634,8 @@ var init_approval$2 = __esmMin((() => {
247264
247634
  decision: approvalDecisionSchema,
247265
247635
  scope: approvalScopeSchema.optional(),
247266
247636
  feedback: string().optional(),
247267
- selected_label: string().optional()
247637
+ selected_label: string().optional(),
247638
+ edited_tool_input: unknown().optional()
247268
247639
  });
247269
247640
  }));
247270
247641
  //#endregion
@@ -251720,6 +252091,89 @@ var init_task_update = __esmMin((() => {
251720
252091
  };
251721
252092
  }));
251722
252093
  //#endregion
252094
+ //#region ../../packages/agent-core/src/tools/background/task-resume.ts
252095
+ var DurableTaskResumeRuntime$1, TaskResumeInputSchema, TaskResumeTool;
252096
+ var init_task_resume = __esmMin((() => {
252097
+ init_zod$1();
252098
+ init_input_schema();
252099
+ init_rule_match();
252100
+ init_agent_task();
252101
+ ({ DurableTaskResumeRuntime: DurableTaskResumeRuntime$1 } = createRequire(import.meta.url)("./bin/durable-task-resume-runtime.cjs"));
252102
+ TaskResumeInputSchema = object({
252103
+ task_id: string().trim().min(1).describe("The lost agent task ID, or completed TaskResume successor, to continue."),
252104
+ prompt: string().trim().min(1).max(32768).describe("New instructions for the preserved agent context."),
252105
+ description: string().trim().min(1).max(1024).describe("Short description for the replacement background task."),
252106
+ timeout_minutes: number$1().int().min(0).max(10080).optional().describe("Wall-clock continuation interval for the replacement run. Defaults to 240 minutes; 0 disables it for this run.")
252107
+ });
252108
+ TaskResumeTool = class {
252109
+ manager;
252110
+ subagentHost;
252111
+ runtime;
252112
+ name = "TaskResume";
252113
+ description = "Explicitly continue a recoverable background agent task after a process loss. This resumes the same agent and preserved context, but creates a new background task ID linked to the terminal source task. Only lost agent tasks and completed TaskResume successors are accepted. It never resumes automatically at startup.";
252114
+ parameters = toInputJsonSchema(TaskResumeInputSchema);
252115
+ constructor(manager, subagentHost) {
252116
+ this.manager = manager;
252117
+ this.subagentHost = subagentHost;
252118
+ this.runtime = new DurableTaskResumeRuntime$1({
252119
+ getTask: (taskId) => manager.getTask(taskId),
252120
+ getIntent: (taskId) => manager.resumeStore?.getBySourceTaskId(taskId),
252121
+ writeIntent: (intent) => manager.resumeStore.write(intent),
252122
+ markIntentStarted: (taskId, startedAt) => manager.resumeStore.markStarted(taskId, startedAt),
252123
+ reserveTaskId: (prefix) => manager.reserveTaskId(prefix),
252124
+ resumeAgent: (agentId, options) => subagentHost.resume(agentId, options),
252125
+ createTask: (handle, description, metadata) => new AgentBackgroundTask(handle, description, subagentHost, metadata.controller ?? new AbortController(), {
252126
+ timeoutMs: resolveSubagentTimeoutMs({ perRunMinutes: metadata.timeoutMinutes }),
252127
+ runInBackground: true,
252128
+ parentToolCallId: metadata.parentToolCallId,
252129
+ responseFormat: void 0,
252130
+ resumed: true,
252131
+ replacesTaskId: metadata.replacesTaskId,
252132
+ resumeRootTaskId: metadata.resumeRootTaskId
252133
+ }),
252134
+ registerTask: (task, options) => manager.registerTask(task, options),
252135
+ awaitTaskPersisted: (taskId) => manager.awaitTaskPersisted(taskId),
252136
+ emitEvent: (event) => manager.agent.emitEvent(event),
252137
+ now: () => Date.now()
252138
+ });
252139
+ }
252140
+ resolveExecution(args) {
252141
+ return {
252142
+ description: `Resuming agent task ${args.task_id}`,
252143
+ approvalRule: this.name,
252144
+ matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.task_id),
252145
+ execute: (ctx) => this.execute(args, ctx)
252146
+ };
252147
+ }
252148
+ async execute(args, { toolCallId, signal, turnId }) {
252149
+ const controller = new AbortController();
252150
+ try {
252151
+ signal.throwIfAborted();
252152
+ const result = await this.runtime.resume({
252153
+ taskId: args.task_id,
252154
+ prompt: args.prompt,
252155
+ description: args.description,
252156
+ timeoutMinutes: args.timeout_minutes,
252157
+ parentToolCallId: toolCallId,
252158
+ toolScope: this.subagentHost.toolScopeForTurn(Number(turnId)),
252159
+ controller,
252160
+ signal
252161
+ });
252162
+ return {
252163
+ output: `task_id: ${result.taskId}\nstatus: ${result.status}\nagent_id: ${result.agentId}\nreplaces_task_id: ${result.replacesTaskId}\nresume_root_task_id: ${result.resumeRootTaskId}\nresumed: true`,
252164
+ isError: false
252165
+ };
252166
+ } catch (error) {
252167
+ controller.abort();
252168
+ return {
252169
+ output: error instanceof Error ? error.message : String(error),
252170
+ isError: true
252171
+ };
252172
+ }
252173
+ }
252174
+ };
252175
+ }));
252176
+ //#endregion
251723
252177
  //#region ../../packages/agent-core/src/tools/background/task-stop.md?raw
251724
252178
  var task_stop_default;
251725
252179
  var init_task_stop$1 = __esmMin((() => {
@@ -251907,6 +252361,67 @@ var init_cron_list = __esmMin((() => {
251907
252361
  };
251908
252362
  }));
251909
252363
  //#endregion
252364
+ //#region ../../packages/agent-core/src/tools/cron/cron-runs.ts
252365
+ var CronRunListInputSchema, CronRunOutputInputSchema, CronRunListTool, CronRunOutputTool;
252366
+ var init_cron_runs = __esmMin((() => {
252367
+ init_zod$1();
252368
+ init_input_schema();
252369
+ CronRunListInputSchema = object({
252370
+ job_id: string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u).optional().describe("Optional cron job id filter."),
252371
+ status: string().regex(/^(buffered|running|completed|failed|cancelled|lost)$/u).optional().describe("Optional run status filter."),
252372
+ limit: number$1().int().min(1).max(100).optional().default(20).describe("Maximum number of newest run receipts.")
252373
+ }).strict();
252374
+ CronRunOutputInputSchema = object({
252375
+ run_id: string().regex(/^[0-9a-f]{16}$/u).describe("The 16-hex run id returned by CronRunList.")
252376
+ }).strict();
252377
+ CronRunListTool = class {
252378
+ manager;
252379
+ name = "CronRunList";
252380
+ description = "List bounded private receipts for cron runs in this session. Receipts contain lifecycle, tool counts, and output references, never prompts, thoughts, raw tool arguments, results, headers, or approval feedback.";
252381
+ parameters = toInputJsonSchema(CronRunListInputSchema);
252382
+ constructor(manager) {
252383
+ this.manager = manager;
252384
+ }
252385
+ resolveExecution(args) {
252386
+ return {
252387
+ description: "Listing private cron run receipts",
252388
+ approvalRule: this.name,
252389
+ execute: async () => {
252390
+ const runs = this.manager.listRuns({
252391
+ jobId: args.job_id,
252392
+ status: args.status,
252393
+ limit: args.limit
252394
+ });
252395
+ return { output: JSON.stringify({ runs }, null, 2), isError: false };
252396
+ }
252397
+ };
252398
+ }
252399
+ };
252400
+ CronRunOutputTool = class {
252401
+ manager;
252402
+ name = "CronRunOutput";
252403
+ description = "Read one private cron run receipt and its bounded final assistant message. Raw prompts, thoughts, tool arguments, tool results, headers, approvals, and Bash-inferred files are never returned.";
252404
+ parameters = toInputJsonSchema(CronRunOutputInputSchema);
252405
+ constructor(manager) {
252406
+ this.manager = manager;
252407
+ }
252408
+ resolveExecution(args) {
252409
+ return {
252410
+ description: `Reading private cron run ${args.run_id}`,
252411
+ approvalRule: this.name,
252412
+ execute: async () => {
252413
+ const run = this.manager.readRunOutput(args.run_id);
252414
+ if (run === null) return {
252415
+ output: `No cron run with id ${args.run_id} exists in this session.`,
252416
+ isError: true
252417
+ };
252418
+ return { output: JSON.stringify(run, null, 2), isError: false };
252419
+ }
252420
+ };
252421
+ }
252422
+ };
252423
+ }));
252424
+ //#endregion
251910
252425
  //#region ../../packages/agent-core/src/agent/permission/policies/deny-all.ts
251911
252426
  var DenyAllPermissionPolicy;
251912
252427
  var init_deny_all = __esmMin((() => {
@@ -252318,6 +252833,7 @@ var init_subagent_batch = __esmMin((() => {
252318
252833
  description: task.description,
252319
252834
  swarmIndex: task.swarmIndex,
252320
252835
  runInBackground: task.runInBackground,
252836
+ responseFormat: task.responseFormat,
252321
252837
  compactBeforeRetry: attempt.state.retryCount > 0,
252322
252838
  signal: attempt.controller.signal,
252323
252839
  onReady: () => {
@@ -252342,11 +252858,13 @@ var init_subagent_batch = __esmMin((() => {
252342
252858
  return this.failedAttemptOutcome(attempt, error);
252343
252859
  }
252344
252860
  attempt.state.agentId = handle.agentId;
252861
+ attempt.state.profileName = handle.profileName;
252345
252862
  try {
252346
252863
  const completion = await handle.completion;
252347
252864
  return {
252348
252865
  task,
252349
252866
  agentId: handle.agentId,
252867
+ profileName: handle.profileName,
252350
252868
  status: "completed",
252351
252869
  result: completion.result,
252352
252870
  usage: completion.usage
@@ -252370,6 +252888,7 @@ var init_subagent_batch = __esmMin((() => {
252370
252888
  return {
252371
252889
  task: attempt.state.task,
252372
252890
  agentId: attempt.state.agentId,
252891
+ profileName: attempt.state.profileName,
252373
252892
  status,
252374
252893
  state: attempt.state.agentId === void 0 ? "not_started" : "started",
252375
252894
  error: this.attemptErrorMessage(attempt, error, status)
@@ -252633,7 +253152,7 @@ async function runChildTurnToCompletion(child, signal) {
252633
253152
  }
252634
253153
  return completion.stopReason;
252635
253154
  }
252636
- async function completeChildTurnWithMaxTokensHandoff(child, signal) {
253155
+ async function completeChildTurnWithMaxTokensHandoff(child, signal, promptOrigin = SUBAGENT_PROMPT_ORIGIN) {
252637
253156
  let stopReason = await runChildTurnToCompletion(child, signal);
252638
253157
  let handoffAttempts = 0;
252639
253158
  while (shouldRequestSubagentHandoff(stopReason, handoffAttempts)) {
@@ -252642,7 +253161,7 @@ async function completeChildTurnWithMaxTokensHandoff(child, signal) {
252642
253161
  if (child.turn.prompt([{
252643
253162
  type: "text",
252644
253163
  text: SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT
252645
- }], SUBAGENT_PROMPT_ORIGIN) === null) throw new Error("Subagent could not start its max_tokens recovery handoff.");
253164
+ }], promptOrigin) === null) throw new Error("Subagent could not start its max_tokens recovery handoff.");
252646
253165
  stopReason = await runChildTurnToCompletion(child, signal);
252647
253166
  }
252648
253167
  if (stopReason === "max_tokens") throw new Error(buildSubagentMaxTokensFailure(lastAssistantText(child)));
@@ -252659,7 +253178,7 @@ function lastAssistantText(agent) {
252659
253178
  }
252660
253179
  return "";
252661
253180
  }
252662
- async function completeStructuredSubagentResult(child, childId, profileName, responseFormat, signal) {
253181
+ async function completeStructuredSubagentResult(child, childId, profileName, responseFormat, signal, promptOrigin = SUBAGENT_PROMPT_ORIGIN) {
252663
253182
  let validation = validateStructuredSubagentOutput(lastAssistantText(child), responseFormat);
252664
253183
  if (validation.validatorException === true) throw new Error(validation.error);
252665
253184
  if (!validation.ok) {
@@ -252667,8 +253186,8 @@ async function completeStructuredSubagentResult(child, childId, profileName, res
252667
253186
  if (child.turn.prompt([{
252668
253187
  type: "text",
252669
253188
  text: buildStructuredResponseRepairPrompt(responseFormat, validation.error)
252670
- }], SUBAGENT_PROMPT_ORIGIN) === null) throw new Error("Subagent could not start its structured-output repair turn.");
252671
- await completeChildTurnWithMaxTokensHandoff(child, signal);
253189
+ }], promptOrigin) === null) throw new Error("Subagent could not start its structured-output repair turn.");
253190
+ await completeChildTurnWithMaxTokensHandoff(child, signal, promptOrigin);
252672
253191
  signal.throwIfAborted();
252673
253192
  validation = validateStructuredSubagentOutput(lastAssistantText(child), responseFormat);
252674
253193
  if (validation.validatorException === true) throw new Error(validation.error);
@@ -252681,7 +253200,7 @@ function shouldSuppressQueuedAttemptFailureEvent(options, error) {
252681
253200
  if (isProviderRateLimitError(error)) return true;
252682
253201
  return isAbortError$4(error) || options.signal.aborted;
252683
253202
  }
252684
- var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, inheritSubagentAllowedTools, inheritSubagentLifecycleTools, STRUCTURED_SUBAGENT_OUTPUT_ERROR, prepareStructuredResponseFormat, validateStructuredSubagentOutput, buildStructuredResponseFormatReminder, buildStructuredResponseRepairPrompt, buildStructuredSubagentEnvelope, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, isSubagentMaxTokensTurnError, shouldRequestSubagentHandoff, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
253203
+ var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, inheritSubagentAllowedTools, inheritSubagentLifecycleTools, prepareSubagentSkillPolicy, profileWithSubagentSkillTools, restoreSubagentSkillPolicy, STRUCTURED_SUBAGENT_OUTPUT_ERROR, prepareStructuredResponseFormat, validateStructuredSubagentOutput, buildStructuredResponseFormatReminder, buildStructuredResponseRepairPrompt, buildStructuredSubagentEnvelope, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, isSubagentMaxTokensTurnError, shouldRequestSubagentHandoff, SUBAGENT_FORK_REMINDER, projectSubagentForkContext, resolveSubagentContextMode, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
252685
253204
  var init_subagent_host = __esmMin((() => {
252686
253205
  init_src$4();
252687
253206
  init_errors$8();
@@ -252696,6 +253215,8 @@ var init_subagent_host = __esmMin((() => {
252696
253215
  ({ DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation } = createRequire(import.meta.url)("./bin/subagent-timeout-policy.cjs"));
252697
253216
  ({ buildSubagentUsageDelta } = createRequire(import.meta.url)("./bin/subagent-usage-rollup-policy.cjs"));
252698
253217
  ({ inheritSubagentAllowedTools, inheritSubagentLifecycleTools } = createRequire(import.meta.url)("./bin/subagent-tool-policy.cjs"));
253218
+ ({ prepareSubagentSkillPolicy, profileWithSubagentSkillTools, restoreSubagentSkillPolicy } = createRequire(import.meta.url)("./bin/subagent-skill-policy.cjs"));
253219
+ ({ SUBAGENT_FORK_REMINDER, projectSubagentForkContext, resolveSubagentContextMode } = createRequire(import.meta.url)("./bin/subagent-context-fork-policy.cjs"));
252699
253220
  ({
252700
253221
  STRUCTURED_SUBAGENT_OUTPUT_ERROR,
252701
253222
  prepareStructuredResponseFormat,
@@ -252719,6 +253240,12 @@ var init_subagent_host = __esmMin((() => {
252719
253240
  kind: "system_trigger",
252720
253241
  name: "subagent"
252721
253242
  };
253243
+ function subagentPromptOrigin(toolScope) {
253244
+ return toolScope === void 0 ? SUBAGENT_PROMPT_ORIGIN : {
253245
+ ...SUBAGENT_PROMPT_ORIGIN,
253246
+ toolScope
253247
+ };
253248
+ }
252722
253249
  SIDE_QUESTION_SYSTEM_REMINDER = `
252723
253250
  This is a side-channel conversation with the user. You should answer user questions directly based on what you already know.
252724
253251
 
@@ -252757,21 +253284,37 @@ IMPORTANT:
252757
253284
  }
252758
253285
  return this.session.getReadyAgent(currentId);
252759
253286
  }
253287
+ toolScopeForTurn(turnId) {
253288
+ return inheritedCronToolScope(this.session.getReadyAgent(this.ownerAgentId)?.turn.toolScopeForTurn(turnId));
253289
+ }
253290
+ isRootAgent() {
253291
+ return this.session.metadata.agents[this.ownerAgentId]?.parentAgentId == null;
253292
+ }
252760
253293
  async spawn(options) {
252761
253294
  options.signal.throwIfAborted();
252762
253295
  const parent = await this.session.ensureAgentResumed(this.ownerAgentId);
253296
+ const contextMode = resolveSubagentContextMode({
253297
+ requested: options.contextMode,
253298
+ isRoot: this.isRootAgent()
253299
+ });
252763
253300
  const profile = this.resolveProfile(parent, options.profileName);
253301
+ const skillPolicy = prepareSubagentSkillPolicy(profile.subagentSkills, this.session.skills);
253302
+ const effectiveProfile = profileWithSubagentSkillTools(profile, skillPolicy);
252764
253303
  const { id, agent } = await this.session.createAgent({
252765
253304
  type: "sub",
252766
- generate: parent.rawGenerate
253305
+ generate: parent.rawGenerate,
253306
+ skillRegistry: skillPolicy.registry
252767
253307
  }, {
252768
253308
  parentAgentId: this.ownerAgentId,
252769
- swarmItem: options.swarmItem
253309
+ swarmItem: options.swarmItem,
253310
+ profileName: profile.name,
253311
+ skillPolicy: skillPolicy.metadata
252770
253312
  });
252771
253313
  const completion = this.runWithTrackedChildUsage(parent, agent, id, options, async (runOptions) => {
252772
253314
  this.emitSubagentSpawned(parent, id, profile.name, runOptions);
252773
253315
  try {
252774
- await this.configureChild(parent, agent, profile);
253316
+ await this.configureChild(parent, agent, effectiveProfile);
253317
+ if (contextMode === "fork") this.seedForkedContext(parent, agent);
252775
253318
  return await this.runPromptTurn(parent, id, agent, profile.name, runOptions);
252776
253319
  } catch (error) {
252777
253320
  this.emitSubagentFailed(parent, id, runOptions, error);
@@ -252845,7 +253388,7 @@ IMPORTANT:
252845
253388
  await child.fullCompaction.block(runOptions.signal);
252846
253389
  }
252847
253390
  this.emitSubagentStarted(parent, agentId);
252848
- if (child.turn.retry("agent-host") === null) throw new Error(`Agent instance "${agentId}" could not start a retry turn`);
253391
+ if (child.turn.retry("agent-host", runOptions.toolScope) === null) throw new Error(`Agent instance "${agentId}" could not start a retry turn`);
252849
253392
  this.observeFirstRequest(child, runOptions);
252850
253393
  return await this.waitForChildCompletion(parent, agentId, child, profileName, runOptions);
252851
253394
  } catch (error) {
@@ -252968,23 +253511,29 @@ IMPORTANT:
252968
253511
  const gitContext = await collectGitContext(child.kaos, child.config.cwd);
252969
253512
  if (gitContext) childPrompt = `${gitContext}\n\n${childPrompt}`;
252970
253513
  }
253514
+ if (options.systemReminder !== void 0) child.context.appendSystemReminder(options.systemReminder, {
253515
+ kind: "system_trigger",
253516
+ name: "durable_task_resume"
253517
+ });
252971
253518
  if (options.responseFormat !== void 0) child.context.appendSystemReminder(buildStructuredResponseFormatReminder(options.responseFormat), {
252972
253519
  kind: "system_trigger",
252973
253520
  name: "subagent_response_format"
252974
253521
  });
252975
253522
  this.emitSubagentStarted(parent, childId);
253523
+ const childOrigin = subagentPromptOrigin(options.toolScope);
252976
253524
  if (child.turn.prompt([{
252977
253525
  type: "text",
252978
253526
  text: childPrompt
252979
- }], SUBAGENT_PROMPT_ORIGIN) === null) throw new Error(`Agent instance "${childId}" could not start a turn`);
253527
+ }], childOrigin) === null) throw new Error(`Agent instance "${childId}" could not start a turn`);
252980
253528
  this.observeFirstRequest(child, options);
252981
253529
  return this.waitForChildCompletion(parent, childId, child, profileName, options);
252982
253530
  }
252983
253531
  async waitForChildCompletion(parent, childId, child, profileName, options) {
252984
- await completeChildTurnWithMaxTokensHandoff(child, options.signal);
253532
+ const childOrigin = subagentPromptOrigin(options.toolScope);
253533
+ await completeChildTurnWithMaxTokensHandoff(child, options.signal, childOrigin);
252985
253534
  let result;
252986
253535
  if (options.responseFormat !== void 0) {
252987
- const structuredResult = await completeStructuredSubagentResult(child, childId, profileName, options.responseFormat, options.signal);
253536
+ const structuredResult = await completeStructuredSubagentResult(child, childId, profileName, options.responseFormat, options.signal, childOrigin);
252988
253537
  result = buildStructuredSubagentEnvelope({
252989
253538
  agentId: childId,
252990
253539
  profileName,
@@ -253001,8 +253550,8 @@ IMPORTANT:
253001
253550
  child.turn.prompt([{
253002
253551
  type: "text",
253003
253552
  text: summary_continuation_default
253004
- }], SUBAGENT_PROMPT_ORIGIN);
253005
- await completeChildTurnWithMaxTokensHandoff(child, options.signal);
253553
+ }], childOrigin);
253554
+ await completeChildTurnWithMaxTokensHandoff(child, options.signal, childOrigin);
253006
253555
  result = lastAssistantText(child);
253007
253556
  }
253008
253557
  }
@@ -253029,10 +253578,22 @@ IMPORTANT:
253029
253578
  });
253030
253579
  const context = await prepareSystemPromptContext(this.session.systemContextKaos(child.kaos.getcwd()), this.session.options.blunHomeDir, { additionalDirs: child.getAdditionalDirs() });
253031
253580
  child.useProfile(profile, context, this.session.options.blunHomeDir);
253032
- child.tools.inheritUserTools(parent.tools);
253581
+ child.tools.inheritUserTools(parent.tools, /* @__PURE__ */ new Set(["Skill"]));
253033
253582
  inheritSubagentLifecycleTools(parent.tools, child.tools);
253034
253583
  inheritSubagentAllowedTools(parent.tools, child.tools);
253035
253584
  }
253585
+ seedForkedContext(parent, child) {
253586
+ const projection = projectSubagentForkContext(parent.context.history);
253587
+ child.context.useProjectedHistoryFrom({
253588
+ history: projection.messages,
253589
+ project: (history) => history
253590
+ });
253591
+ child.context.appendSystemReminder(SUBAGENT_FORK_REMINDER, {
253592
+ kind: "system_trigger",
253593
+ name: "subagent_context_fork"
253594
+ });
253595
+ return projection;
253596
+ }
253036
253597
  async triggerSubagentStart(parent, profileName, prompt, signal) {
253037
253598
  await parent.hooks?.trigger("SubagentStart", {
253038
253599
  matcherValue: profileName,
@@ -253064,10 +253625,11 @@ IMPORTANT:
253064
253625
  subagentId: childId,
253065
253626
  subagentName: profileName,
253066
253627
  parentToolCallId: options.parentToolCallId,
253067
- parentToolCallUuid: options.parentToolCallUuid,
253068
- parentAgentId: this.ownerAgentId,
253069
- description: options.description,
253070
- swarmIndex: options.swarmIndex,
253628
+ parentToolCallUuid: options.parentToolCallUuid,
253629
+ parentAgentId: this.ownerAgentId,
253630
+ description: options.description,
253631
+ contextMode: options.contextMode === "fork" ? "fork" : "isolated",
253632
+ swarmIndex: options.swarmIndex,
253071
253633
  runInBackground: options.runInBackground
253072
253634
  });
253073
253635
  parent.telemetry.track("subagent_created", {
@@ -253160,7 +253722,7 @@ function buildSubagentDescriptions(subagents) {
253160
253722
  return `${header}\n Tools: ${subagent.tools.join(", ")}`;
253161
253723
  }).join("\n");
253162
253724
  }
253163
- var AgentToolInputSchema, BACKGROUND_AGENT_UNAVAILABLE, AgentTool, USER_INTERRUPTED_SUBAGENT_MESSAGE, resolveSubagentRunMode;
253725
+ var AgentToolInputSchema, BACKGROUND_AGENT_UNAVAILABLE, SUBAGENT_CONTEXT_FORK_TOOL_DESCRIPTION, AgentTool, USER_INTERRUPTED_SUBAGENT_MESSAGE, resolveSubagentRunMode;
253164
253726
  var init_agent$1 = __esmMin((() => {
253165
253727
  init_zod$1();
253166
253728
  init_tool_access();
@@ -253174,6 +253736,7 @@ var init_agent$1 = __esmMin((() => {
253174
253736
  init_agent_background_enabled();
253175
253737
  init_agent$2();
253176
253738
  ({ resolveSubagentRunMode } = createRequire(import.meta.url)("./bin/subagent-parent-responsiveness.cjs"));
253739
+ SUBAGENT_CONTEXT_FORK_TOOL_DESCRIPTION = "The default context_mode=isolated starts with zero conversation context. For a new root-level subagent whose work genuinely depends on this exact conversation, context_mode=fork passes only a bounded, redacted projection of direct local user text and completed text-only assistant replies. It never passes private channel messages, system injections, attachments, tool calls, arguments, or results. The delegated prompt remains required and authoritative. Fork is unavailable when resuming and unavailable to nested subagents.";
253177
253740
  AgentToolInputSchema = preprocess((input) => {
253178
253741
  if (typeof input !== "object" || input === null || Array.isArray(input)) return input;
253179
253742
  const normalized = { ...input };
@@ -253186,6 +253749,7 @@ var init_agent$1 = __esmMin((() => {
253186
253749
  prompt: string().describe("Full task prompt for the subagent"),
253187
253750
  description: string().describe("Short task description (3-5 words) for UI display"),
253188
253751
  subagent_type: string().optional().describe("One of the available agent types (see \"Available agent types\" in this tool description). Defaults to \"coder\" when omitted."),
253752
+ context_mode: _enum(["isolated", "fork"]).optional().describe("Context boundary for a new subagent. Defaults to isolated. fork is root-only and passes a bounded redacted user/assistant projection without tools, private channels, system injections, attachments, or tool results."),
253189
253753
  resume: string().optional().describe("Optional agent ID to resume instead of creating a new instance. When set, do not also pass subagent_type — the resumed agent keeps its own type, and supplying both is rejected."),
253190
253754
  run_in_background: boolean$1().optional().describe("Compatibility option. Normal subagents run detached when task management is available. A response_format call requires this to be false or omitted and runs in the foreground for validation."),
253191
253755
  timeout_minutes: number$1().int().min(0).max(10080).optional().describe("Wall-clock interval before the same agent is continued automatically. Defaults to 240 minutes. Set 0 to disable the interval for this run."),
@@ -253217,7 +253781,7 @@ var init_agent$1 = __esmMin((() => {
253217
253781
  const log = options?.log;
253218
253782
  this.allowBackground = options?.allowBackground ?? true;
253219
253783
  const typeLines = buildSubagentDescriptions(subagents);
253220
- const baseDescription = `${agent_default}\n\n${this.allowBackground ? agent_background_enabled_default : agent_background_disabled_default}`;
253784
+ const baseDescription = `${agent_default}\n\n${SUBAGENT_CONTEXT_FORK_TOOL_DESCRIPTION}\n\n${this.allowBackground ? agent_background_enabled_default : agent_background_disabled_default}`;
253221
253785
  this.description = typeLines ? `${baseDescription}\n\nAvailable agent types (pass via subagent_type):\n${typeLines}` : baseDescription;
253222
253786
  this.log = log;
253223
253787
  }
@@ -253246,7 +253810,7 @@ var init_agent$1 = __esmMin((() => {
253246
253810
  execute: (ctx) => this.execution(args, ctx)
253247
253811
  };
253248
253812
  }
253249
- async execution(args, { toolCallId, signal }) {
253813
+ async execution(args, { toolCallId, signal, turnId }) {
253250
253814
  try {
253251
253815
  signal.throwIfAborted();
253252
253816
  if (args.response_format !== void 0 && args.run_in_background === true) return {
@@ -253269,6 +253833,19 @@ var init_agent$1 = __esmMin((() => {
253269
253833
  const runInBackground = responseFormat === void 0 ? resolvedRunMode.runInBackground : false;
253270
253834
  const requestedProfileName = args.subagent_type?.length ? args.subagent_type : void 0;
253271
253835
  const resumeAgentId = args.resume?.trim();
253836
+ let contextMode;
253837
+ try {
253838
+ contextMode = resolveSubagentContextMode({
253839
+ requested: args.context_mode,
253840
+ resume: resumeAgentId !== void 0 && resumeAgentId.length > 0,
253841
+ isRoot: this.subagentHost.isRootAgent()
253842
+ });
253843
+ } catch (error) {
253844
+ return {
253845
+ output: error instanceof Error ? error.message : String(error),
253846
+ isError: true
253847
+ };
253848
+ }
253272
253849
  if (resumeAgentId !== void 0 && resumeAgentId.length > 0 && requestedProfileName !== void 0) return {
253273
253850
  output: "Cannot set subagent_type when resuming an existing agent. Resume by agent id only.",
253274
253851
  isError: true
@@ -253289,6 +253866,8 @@ var init_agent$1 = __esmMin((() => {
253289
253866
  description: args.description,
253290
253867
  runInBackground,
253291
253868
  responseFormat,
253869
+ contextMode,
253870
+ toolScope: this.subagentHost.toolScopeForTurn(Number(turnId)),
253292
253871
  signal: controller.signal
253293
253872
  };
253294
253873
  let handle;
@@ -253365,7 +253944,7 @@ var init_agent$1 = __esmMin((() => {
253365
253944
  //#region ../../packages/agent-core/src/tools/builtin/collaboration/agent-swarm.md?raw
253366
253945
  var agent_swarm_default;
253367
253946
  var init_agent_swarm$1 = __esmMin((() => {
253368
- agent_swarm_default = "Launch multiple subagents from one prompt template, existing agent resumes, or both.\n\nUse AgentSwarm when many subagents should run the same kind of task over different inputs. The placeholder is exactly `{{item}}`. For example, with `prompt_template` set to `Review {{item}} for likely regressions.` and `items` set to `[\"src/a.ts\", \"src/b.ts\"]`, AgentSwarm launches two new subagents with those two concrete prompts. For a few differently-shaped tasks, make separate `Agent` calls in one message instead.\n\nUse `resume_agent_ids` to continue subagents that already exist from earlier work, such as ones that failed or timed out: map each agent id to the prompt for that resumed subagent (usually `continue` if no extra information is needed). You may combine `resume_agent_ids` with `items` in the same call to resume existing subagents and launch new ones. Do not duplicate resumed work in `items`.\n\nEach of these is enforced — a violation is rejected before any subagent starts: provide at least 2 `items` unless you pass `resume_agent_ids`; whenever `items` are present, `prompt_template` is required and must contain `{{item}}`; and the filled-in prompts must be distinct (two items that expand to the same prompt are rejected).\n\nUse enough subagents to keep the work focused and parallel. AgentSwarm supports up to 128 subagents, and launches are queued automatically, so it is safe to split large tasks into many clear, independent items.\n\nIf `AgentSwarm` is called, that call must be the only tool call in the response.\n";
253947
+ agent_swarm_default = "Launch multiple subagents from one prompt template, existing agent resumes, or both.\n\nUse AgentSwarm when many subagents should run the same kind of task over different inputs. The placeholder is exactly `{{item}}`. For example, with `prompt_template` set to `Review {{item}} for likely regressions.` and `items` set to `[\"src/a.ts\", \"src/b.ts\"]`, AgentSwarm launches two new subagents with those two concrete prompts. For a few differently-shaped tasks, make separate `Agent` calls in one message instead.\n\nUse `resume_agent_ids` to continue subagents that already exist from earlier work, such as ones that failed or timed out: map each agent id to the prompt for that resumed subagent (usually `continue` if no extra information is needed). You may combine `resume_agent_ids` with `items` in the same call to resume existing subagents and launch new ones. Do not duplicate resumed work in `items`.\n\nEach of these is enforced — a violation is rejected before any subagent starts: provide at least 2 `items` unless you pass `resume_agent_ids`; whenever `items` are present, `prompt_template` is required and must contain `{{item}}`; and the filled-in prompts must be distinct (two items that expand to the same prompt are rejected).\n\nUse enough subagents to keep the work focused and parallel. AgentSwarm supports up to 128 subagents, and launches are queued automatically, so it is safe to split large tasks into many clear, independent items.\n\nUse `response_format` when all children must return one shared bounded JSON shape. Each child is validated and repaired independently, and the final result is canonical task-order JSON. Omit it to retain the existing XML result format unchanged.\n\nIf `AgentSwarm` is called, that call must be the only tool call in the response.\n";
253369
253948
  }));
253370
253949
  //#endregion
253371
253950
  //#region ../../packages/agent-core/src/tools/builtin/collaboration/agent-swarm.ts
@@ -253448,13 +254027,14 @@ function renderSwarmSummary(completed, failed, aborted = 0) {
253448
254027
  function escapeXmlAttribute(value) {
253449
254028
  return value.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
253450
254029
  }
253451
- var DEFAULT_SUBAGENT_TYPE, PROMPT_TEMPLATE_PLACEHOLDER, MAX_AGENT_SWARM_SUBAGENTS, AgentSwarmToolInputSchema, AgentSwarmTool;
254030
+ var DEFAULT_SUBAGENT_TYPE, PROMPT_TEMPLATE_PLACEHOLDER, MAX_AGENT_SWARM_SUBAGENTS, renderStructuredSwarmResults, parseStructuredSwarmDisplay, structuredSwarmToolResult, AgentSwarmToolInputSchema, AgentSwarmTool;
253452
254031
  var init_agent_swarm = __esmMin((() => {
253453
254032
  init_zod$1();
253454
254033
  init_subagent_host();
253455
254034
  init_tool_access();
253456
254035
  init_input_schema();
253457
254036
  init_agent_swarm$1();
254037
+ ({ renderStructuredSwarmResults, parseStructuredSwarmDisplay, structuredSwarmToolResult } = createRequire(import.meta.url)("./bin/structured-agent-swarm-output.cjs"));
253458
254038
  DEFAULT_SUBAGENT_TYPE = "coder";
253459
254039
  PROMPT_TEMPLATE_PLACEHOLDER = "{{item}}";
253460
254040
  MAX_AGENT_SWARM_SUBAGENTS = 128;
@@ -253464,7 +254044,11 @@ var init_agent_swarm = __esmMin((() => {
253464
254044
  prompt_template: string().trim().min(1).optional().describe(`Prompt template for each subagent. The ${PROMPT_TEMPLATE_PLACEHOLDER} placeholder is replaced with each item value.`),
253465
254045
  items: array(string().trim().min(1)).max(MAX_AGENT_SWARM_SUBAGENTS).optional().describe(`Values used to fill ${PROMPT_TEMPLATE_PLACEHOLDER}. Each item launches one new subagent.`),
253466
254046
  resume_agent_ids: record(string().trim().min(1), string().trim().min(1)).optional().describe("Map of existing subagent agent_id to the prompt used to resume that subagent. These resumed subagents are launched before new item-based subagents."),
253467
- timeout_minutes: number$1().int().min(0).max(10080).optional().describe("Wall-clock interval before each same swarm agent is continued automatically. Defaults to 240 minutes. Set 0 to disable the interval for this run.")
254047
+ timeout_minutes: number$1().int().min(0).max(10080).optional().describe("Wall-clock interval before each same swarm agent is continued automatically. Defaults to 240 minutes. Set 0 to disable the interval for this run."),
254048
+ response_format: object({
254049
+ name: string().min(1).max(64).describe("Stable name for the shared structured result"),
254050
+ schema: record(string(), unknown()).describe("Restricted JSON Schema applied to every child result")
254051
+ }).optional().describe("Require one shared validated JSON object shape from every spawned or resumed swarm child.")
253468
254052
  }).strict();
253469
254053
  AgentSwarmTool = class {
253470
254054
  subagentHost;
@@ -253492,8 +254076,17 @@ var init_agent_swarm = __esmMin((() => {
253492
254076
  }
253493
254077
  async execution(args, context) {
253494
254078
  try {
254079
+ let responseFormat;
254080
+ if (args.response_format !== void 0) try {
254081
+ responseFormat = prepareStructuredResponseFormat(args.response_format, compileToolArgsValidator);
254082
+ } catch (error) {
254083
+ return {
254084
+ output: `Invalid response_format: ${error instanceof Error ? error.message : String(error)}`,
254085
+ isError: true
254086
+ };
254087
+ }
253495
254088
  this.swarmMode.enter("tool");
253496
- return { output: await this.runSwarm(args, context.signal, context.toolCallId) };
254089
+ return structuredSwarmToolResult(await this.runSwarm(args, context.signal, context.toolCallId, responseFormat, context.turnId));
253497
254090
  } catch (error) {
253498
254091
  return {
253499
254092
  output: error instanceof Error ? error.message : String(error),
@@ -253501,7 +254094,7 @@ var init_agent_swarm = __esmMin((() => {
253501
254094
  };
253502
254095
  }
253503
254096
  }
253504
- async runSwarm(args, signal, toolCallId) {
254097
+ async runSwarm(args, signal, toolCallId, responseFormat, turnId) {
253505
254098
  const profileName = normalizeOptionalString$2(args.subagent_type) ?? DEFAULT_SUBAGENT_TYPE;
253506
254099
  const tasks = createAgentSwarmSpecs(args, (agentId) => this.subagentHost.getSwarmItem(agentId)).map((spec) => {
253507
254100
  const descriptionName = spec.kind === "resume" ? "resume" : profileName;
@@ -253513,6 +254106,8 @@ var init_agent_swarm = __esmMin((() => {
253513
254106
  description: childDescription(args.description, spec.index, descriptionName),
253514
254107
  swarmIndex: spec.index,
253515
254108
  runInBackground: false,
254109
+ responseFormat,
254110
+ toolScope: this.subagentHost.toolScopeForTurn(Number(turnId)),
253516
254111
  swarmItem: spec.item,
253517
254112
  signal,
253518
254113
  timeout: resolveSubagentTimeoutMs({ perRunMinutes: args.timeout_minutes })
@@ -253527,10 +254122,11 @@ var init_agent_swarm = __esmMin((() => {
253527
254122
  kind: "spawn"
253528
254123
  };
253529
254124
  });
253530
- return renderSwarmResults((await this.subagentHost.runQueued(tasks)).map(({ task, ...result }) => ({
254125
+ const results = (await this.subagentHost.runQueued(tasks)).map(({ task, ...result }) => ({
253531
254126
  spec: task.data,
253532
254127
  ...result
253533
- })));
254128
+ }));
254129
+ return responseFormat === void 0 ? renderSwarmResults(results) : renderStructuredSwarmResults(results, responseFormat);
253534
254130
  }
253535
254131
  };
253536
254132
  }));
@@ -259646,7 +260242,7 @@ function renderLine(entry, lineEndingStyle) {
259646
260242
  function renderedLineBytes(renderedLine, isFirst) {
259647
260243
  return (isFirst ? 0 : 1) + Buffer.byteLength(renderedLine, "utf8");
259648
260244
  }
259649
- function renderEntries(entries, lineEndingStyle) {
260245
+ function renderEntries(entries, lineEndingStyle, maxBytes) {
259650
260246
  const renderedLines = [];
259651
260247
  const truncatedLineNumbers = [];
259652
260248
  let bytes = 0;
@@ -259654,14 +260250,14 @@ function renderEntries(entries, lineEndingStyle) {
259654
260250
  for (const entry of entries) {
259655
260251
  const rendered = renderLine(entry, lineEndingStyle);
259656
260252
  const lineBytes = renderedLineBytes(rendered.line, renderedLines.length === 0);
259657
- if (renderedLines.length > 0 && bytes + lineBytes > MAX_BYTES) {
260253
+ if (renderedLines.length > 0 && bytes + lineBytes > maxBytes) {
259658
260254
  maxBytesReached = true;
259659
260255
  break;
259660
260256
  }
259661
260257
  if (rendered.wasTruncated) truncatedLineNumbers.push(entry.lineNo);
259662
260258
  renderedLines.push(rendered.line);
259663
260259
  bytes += lineBytes;
259664
- if (bytes >= MAX_BYTES) {
260260
+ if (bytes >= maxBytes) {
259665
260261
  maxBytesReached = true;
259666
260262
  break;
259667
260263
  }
@@ -259692,7 +260288,7 @@ function containsNulByte(text) {
259692
260288
  function notReadableFileOutput(path) {
259693
260289
  return `"${path}" is not readable as UTF-8 text. If it is an image or video, use ReadMediaFile. For other binary formats, use Bash or an MCP tool if available.`;
259694
260290
  }
259695
- var MAX_LINES$1, MAX_LINE_LENGTH, MAX_BYTES, S_IFMT$1, S_IFREG, PositiveLineOffsetSchema, TailLineOffsetSchema, ReadInputSchema, ReadBatchInputSchema, READ_DESCRIPTION, READ_BATCH_DESCRIPTION, ReadTool, ReadBatchTool, readContinuationNotice, READ_MODEL_VISIBLE_BYTES, MAX_READ_BATCH_REQUESTS, readBatchAllFailed, renderReadBatchOutput;
260291
+ var MAX_LINES$1, MAX_LINE_LENGTH, S_IFMT$1, S_IFREG, PositiveLineOffsetSchema, TailLineOffsetSchema, ReadInputSchema, ReadBatchInputSchema, READ_DESCRIPTION, READ_BATCH_DESCRIPTION, ReadTool, ReadBatchTool, readContinuationNotice, readModelVisibleBytes, readModelVisibleLines, MAX_READ_BATCH_REQUESTS, readBatchAllFailed, renderReadBatchOutput;
259696
260292
  var init_read = __esmMin((() => {
259697
260293
  init_zod$1();
259698
260294
  init_tool_access();
@@ -259703,46 +260299,47 @@ var init_read = __esmMin((() => {
259703
260299
  init_rule_match();
259704
260300
  init_line_endings();
259705
260301
  init_read$1();
259706
- ({ readContinuationNotice, READ_MODEL_VISIBLE_BYTES } = createRequire(import.meta.url)("./bin/read-continuation-policy.cjs"));
260302
+ ({ readContinuationNotice, readModelVisibleBytes, readModelVisibleLines } = createRequire(import.meta.url)("./bin/read-continuation-policy.cjs"));
259707
260303
  ({ MAX_READ_BATCH_REQUESTS, readBatchAllFailed, renderReadBatchOutput } = createRequire(import.meta.url)("./bin/read-batch-policy.cjs"));
259708
260304
  MAX_LINES$1 = 1e3;
259709
260305
  MAX_LINE_LENGTH = 2e3;
259710
- MAX_BYTES = READ_MODEL_VISIBLE_BYTES;
259711
260306
  S_IFMT$1 = 61440;
259712
260307
  S_IFREG = 32768;
259713
260308
  PositiveLineOffsetSchema = number$1().int().min(1);
259714
- TailLineOffsetSchema = number$1().int().min(-MAX_LINES$1).max(-1);
260309
+ TailLineOffsetSchema = number$1().int().max(-1);
259715
260310
  ReadInputSchema = object({
259716
260311
  path: string().describe("Path to a text file. Relative paths resolve against the working directory; a path outside the working directory must be absolute. Directories are not supported; use `ls` via Bash for a known directory, or Glob for pattern search."),
259717
- line_offset: union([PositiveLineOffsetSchema, TailLineOffsetSchema]).optional().describe(`The line number to start reading from. Omit to start at line 1. Negative values read from the end of the file; the absolute value cannot exceed ${String(MAX_LINES$1)}.`),
259718
- n_lines: number$1().int().positive().optional().describe(`The number of lines to read; the tool also applies its internal cap. Omit to read up to the internal cap of ${String(MAX_LINES$1)} lines.`)
260312
+ line_offset: union([PositiveLineOffsetSchema, TailLineOffsetSchema]).optional().describe("The line number to start reading from. Omit to start at line 1. Negative values read backward from the end within the active context budget."),
260313
+ n_lines: number$1().int().positive().optional().describe("The number of lines for an explicit targeted range. Omit to read the complete file whenever the active context has room.")
259719
260314
  });
259720
260315
  ReadBatchInputSchema = object({ requests: array(ReadInputSchema).min(2).max(MAX_READ_BATCH_REQUESTS).describe(`Two to ${String(MAX_READ_BATCH_REQUESTS)} independent known text-file reads. Do not batch a read whose path or range depends on an earlier result.`) });
259721
260316
  object({
259722
260317
  content: string(),
259723
260318
  lineCount: number$1().int().nonnegative()
259724
260319
  });
260320
+ read_default = "Read a known UTF-8 text file. Invalid paths error; directories are unsupported. Relative paths use the working directory; outside paths must be absolute. Use Glob for unknown names, Grep for content, and ReadMediaFile for media.\n\nOmit `line_offset` and `n_lines` to read the complete file whenever the active context has room. Explicit ranges remain available for targeted inspection. Under real context pressure, a result is capped and names the exact next `line_offset`; continue from that line without gaps. Individual lines beyond {{ MAX_LINE_LENGTH }} characters are truncated. Negative `line_offset` reads from the end, up to {{ MAX_LINES }} lines. Issue independent Read calls together in one response when several files or ranges may be useful. Prefer ReadBatch when two or more independent paths or ranges are already known.\n\nSensitive files such as `.env` and credential stores are refused; templates and public keys remain readable. Only UTF-8 text without NUL bytes is accepted; use Bash or an MCP tool for other binaries.\n\nOutput is `<line-number>\\t<content>` per line. The trailing `<system>...</system>` block is status, not file content. Pure CRLF appears as LF and is preserved by Edit. Mixed or lone carriage returns appear as `\\r` and require exact `Edit.old_string` escapes.";
259725
260321
  READ_DESCRIPTION = renderPrompt(read_default, {
259726
260322
  MAX_LINES: MAX_LINES$1,
259727
- MAX_BYTES_KB: MAX_BYTES / 1024,
259728
- MAX_LINE_LENGTH
259729
- });
259730
- read_default = "Read a known UTF-8 text file. Invalid paths error; directories are unsupported. Relative paths use the working directory; outside paths must be absolute. Use Glob for unknown names, Grep for content, and ReadMediaFile for media.\n\nEach call returns at most {{ MAX_LINES }} lines or {{ MAX_BYTES_KB }} KB and truncates lines beyond {{ MAX_LINE_LENGTH }} characters. Page large files with 1-based `line_offset` and `n_lines`; omit `n_lines` for the cap. Negative `line_offset` reads from the end, up to {{ MAX_LINES }} lines. A capped result names the exact next `line_offset`. Issue independent Read calls together in one response when several files or ranges may be useful. Prefer ReadBatch when two or more independent paths or ranges are already known.\n\nSensitive files such as `.env` and credential stores are refused; templates and public keys remain readable. Only UTF-8 text without NUL bytes is accepted; use Bash or an MCP tool for other binaries.\n\nOutput is `<line-number>\\t<content>` per line. The trailing `<system>...</system>` block is status, not file content. Pure CRLF appears as LF and is preserved by Edit. Mixed or lone carriage returns appear as `\\r` and require exact `Edit.old_string` escapes.";
259731
- READ_DESCRIPTION = renderPrompt(read_default, {
259732
- MAX_LINES: MAX_LINES$1,
259733
- MAX_BYTES_KB: MAX_BYTES / 1024,
259734
260323
  MAX_LINE_LENGTH
259735
260324
  });
259736
260325
  READ_BATCH_DESCRIPTION = `Read ${String(MAX_READ_BATCH_REQUESTS)} or fewer independent known UTF-8 text files or ranges concurrently in one tool call. Use this instead of serial Read calls only when every path and range is already known and no later request depends on an earlier result. Each request uses the same path, sensitive-file, UTF-8, line, and byte rules as Read. Results remain in request order and identify partial failures individually.`;
259737
260326
  ReadTool = class {
259738
260327
  kaos;
259739
260328
  workspace;
260329
+ contextWindowState;
259740
260330
  name = "Read";
259741
260331
  description = READ_DESCRIPTION;
259742
260332
  parameters = toInputJsonSchema(ReadInputSchema);
259743
- constructor(kaos, workspace) {
260333
+ constructor(kaos, workspace, contextWindowState = () => ({})) {
259744
260334
  this.kaos = kaos;
259745
260335
  this.workspace = workspace;
260336
+ this.contextWindowState = contextWindowState;
260337
+ }
260338
+ modelVisibleBytes() {
260339
+ return readModelVisibleBytes(this.contextWindowState());
260340
+ }
260341
+ modelVisibleLines() {
260342
+ return readModelVisibleLines(this.contextWindowState());
259746
260343
  }
259747
260344
  resolveExecution(args) {
259748
260345
  const path = resolvePathAccessPath(args.path, {
@@ -259793,10 +260390,12 @@ var init_read = __esmMin((() => {
259793
260390
  output: notReadableFileOutput(args.path)
259794
260391
  };
259795
260392
  const lineOffset = args.line_offset ?? 1;
259796
- const requestedLines = args.n_lines ?? 1e3;
259797
- const effectiveLimit = Math.min(requestedLines, MAX_LINES$1);
259798
- if (lineOffset < 0) return await this.readTail(safePath, args.path, lineOffset, effectiveLimit, requestedLines);
259799
- return await this.readForward(safePath, args.path, lineOffset, effectiveLimit, requestedLines);
260393
+ const maxLines = this.modelVisibleLines();
260394
+ const requestedLines = args.n_lines ?? maxLines;
260395
+ const effectiveLimit = Math.min(requestedLines, maxLines);
260396
+ const maxBytes = this.modelVisibleBytes();
260397
+ if (lineOffset < 0) return await this.readTail(safePath, args.path, lineOffset, effectiveLimit, requestedLines, maxBytes, maxLines);
260398
+ return await this.readForward(safePath, args.path, lineOffset, effectiveLimit, requestedLines, maxBytes, maxLines);
259800
260399
  } catch (error) {
259801
260400
  if (isTextDecodeError(error)) return {
259802
260401
  isError: true,
@@ -259808,7 +260407,7 @@ var init_read = __esmMin((() => {
259808
260407
  };
259809
260408
  }
259810
260409
  }
259811
- async readForward(safePath, displayPath, lineOffset, effectiveLimit, requestedLines) {
260410
+ async readForward(safePath, displayPath, lineOffset, effectiveLimit, requestedLines, maxBytes, maxLines) {
259812
260411
  const rangeKaos = this.kaos;
259813
260412
  if (rangeKaos.scanTextFile !== void 0 && rangeKaos.readLineRange !== void 0) {
259814
260413
  const scan = await rangeKaos.scanTextFile(safePath);
@@ -259817,31 +260416,47 @@ var init_read = __esmMin((() => {
259817
260416
  output: notReadableFileOutput(displayPath)
259818
260417
  };
259819
260418
  const selectedEntries = [];
260419
+ const lineEndingStyle = lineEndingStyleFromFlags(scan.lineEndingFlags);
260420
+ let selectedBytes = 0;
260421
+ let maxBytesReached = false;
259820
260422
  let lineNo = lineOffset;
259821
260423
  for await (const rawLine of rangeKaos.readLineRange(safePath, {
259822
260424
  startLine: lineOffset,
259823
260425
  maxLines: effectiveLimit,
259824
260426
  errors: "strict"
259825
260427
  })) {
259826
- selectedEntries.push({
260428
+ const entry = {
259827
260429
  lineNo,
259828
260430
  rawContent: stripTrailingLf(rawLine)
259829
- });
260431
+ };
260432
+ const rendered = renderLine(entry, lineEndingStyle);
260433
+ const lineBytes = renderedLineBytes(rendered.line, selectedEntries.length === 0);
260434
+ if (selectedEntries.length > 0 && selectedBytes + lineBytes > maxBytes) {
260435
+ maxBytesReached = true;
260436
+ break;
260437
+ }
260438
+ selectedEntries.push(entry);
260439
+ selectedBytes += lineBytes;
259830
260440
  lineNo += 1;
260441
+ if (selectedBytes >= maxBytes) {
260442
+ maxBytesReached = true;
260443
+ break;
260444
+ }
259831
260445
  }
259832
- const lineEndingStyle = lineEndingStyleFromFlags(scan.lineEndingFlags);
259833
- const rendered = renderEntries(selectedEntries, lineEndingStyle);
260446
+ const rendered = renderEntries(selectedEntries, lineEndingStyle, maxBytes);
259834
260447
  return this.finishReadResult({
259835
260448
  renderedLines: rendered.renderedLines,
259836
260449
  truncatedLineNumbers: rendered.truncatedLineNumbers,
259837
- maxLinesReached: effectiveLimit >= 1e3 && lineOffset + 1e3 <= scan.totalLines,
259838
- maxBytesReached: rendered.maxBytesReached,
260450
+ maxLinesReached: effectiveLimit >= maxLines && lineOffset + maxLines <= scan.totalLines,
260451
+ maxBytesReached: maxBytesReached || rendered.maxBytesReached,
259839
260452
  lineEndingStyle,
259840
260453
  startLine: selectedEntries.length > 0 ? lineOffset : 0,
259841
260454
  totalLines: scan.totalLines,
259842
260455
  requestedLines,
259843
260456
  lineOffset,
259844
- effectiveLimit
260457
+ effectiveLimit,
260458
+ maxBytes,
260459
+ maxLines
259845
260460
  });
259846
260461
  }
259847
260462
  const selectedEntries = [];
@@ -259852,7 +260467,10 @@ var init_read = __esmMin((() => {
259852
260467
  };
259853
260468
  let currentLineNo = 0;
259854
260469
  let maxLinesReached = false;
260470
+ let maxBytesReached = false;
260471
+ let selectedBytes = 0;
259855
260472
  let collectionClosed = false;
260473
+ let closedByLines = false;
259856
260474
  for await (const rawLine of this.kaos.readLines(safePath, { errors: "strict" })) {
259857
260475
  if (containsNulByte(rawLine)) return {
259858
260476
  isError: true,
@@ -259861,38 +260479,56 @@ var init_read = __esmMin((() => {
259861
260479
  currentLineNo += 1;
259862
260480
  updateLineEndingFlags(flags, rawLine);
259863
260481
  if (collectionClosed) {
259864
- if (effectiveLimit >= 1e3 && currentLineNo >= lineOffset) maxLinesReached = true;
260482
+ if (closedByLines && effectiveLimit >= maxLines && currentLineNo >= lineOffset) maxLinesReached = true;
259865
260483
  continue;
259866
260484
  }
259867
260485
  if (currentLineNo < lineOffset) continue;
259868
260486
  if (selectedEntries.length >= effectiveLimit) {
259869
- if (effectiveLimit >= 1e3) maxLinesReached = true;
260487
+ if (effectiveLimit >= maxLines) maxLinesReached = true;
259870
260488
  collectionClosed = true;
260489
+ closedByLines = true;
259871
260490
  continue;
259872
260491
  }
259873
- selectedEntries.push({
260492
+ const entry = {
259874
260493
  lineNo: currentLineNo,
259875
260494
  rawContent: stripTrailingLf(rawLine)
259876
- });
259877
- if (selectedEntries.length >= effectiveLimit) collectionClosed = true;
260495
+ };
260496
+ const conservative = renderLine(entry, "mixed");
260497
+ const lineBytes = renderedLineBytes(conservative.line, selectedEntries.length === 0);
260498
+ if (selectedEntries.length > 0 && selectedBytes + lineBytes > maxBytes) {
260499
+ maxBytesReached = true;
260500
+ collectionClosed = true;
260501
+ continue;
260502
+ }
260503
+ selectedEntries.push(entry);
260504
+ selectedBytes += lineBytes;
260505
+ if (selectedEntries.length >= effectiveLimit) {
260506
+ collectionClosed = true;
260507
+ closedByLines = true;
260508
+ } else if (selectedBytes >= maxBytes) {
260509
+ maxBytesReached = true;
260510
+ collectionClosed = true;
260511
+ }
259878
260512
  }
259879
260513
  const lineEndingStyle = lineEndingStyleFromFlags(flags);
259880
- const rendered = renderEntries(selectedEntries, lineEndingStyle);
260514
+ const rendered = renderEntries(selectedEntries, lineEndingStyle, maxBytes);
259881
260515
  return this.finishReadResult({
259882
260516
  renderedLines: rendered.renderedLines,
259883
260517
  truncatedLineNumbers: rendered.truncatedLineNumbers,
259884
260518
  maxLinesReached,
259885
- maxBytesReached: rendered.maxBytesReached,
260519
+ maxBytesReached: maxBytesReached || rendered.maxBytesReached,
259886
260520
  lineEndingStyle,
259887
260521
  startLine: selectedEntries.length > 0 ? lineOffset : 0,
259888
260522
  totalLines: currentLineNo,
259889
260523
  requestedLines,
259890
260524
  lineOffset,
259891
- effectiveLimit
260525
+ effectiveLimit,
260526
+ maxBytes,
260527
+ maxLines
259892
260528
  });
259893
260529
  }
259894
- async readTail(safePath, displayPath, lineOffset, effectiveLimit, requestedLines) {
259895
- const tailCount = Math.abs(lineOffset);
260530
+ async readTail(safePath, displayPath, lineOffset, effectiveLimit, requestedLines, maxBytes, maxLines) {
260531
+ const tailCount = Math.min(Math.abs(lineOffset), maxLines);
259896
260532
  const rangeKaos = this.kaos;
259897
260533
  if (rangeKaos.scanTextFile !== void 0 && rangeKaos.readTailLines !== void 0) {
259898
260534
  const scan = await rangeKaos.scanTextFile(safePath);
@@ -259915,7 +260551,9 @@ var init_read = __esmMin((() => {
259915
260551
  lineEndingFlags: scan.lineEndingFlags,
259916
260552
  effectiveLimit,
259917
260553
  totalLines: scan.totalLines,
259918
- requestedLines
260554
+ requestedLines,
260555
+ maxBytes,
260556
+ maxLines
259919
260557
  });
259920
260558
  }
259921
260559
  const entries = [];
@@ -259943,7 +260581,9 @@ var init_read = __esmMin((() => {
259943
260581
  lineEndingFlags: flags,
259944
260582
  effectiveLimit,
259945
260583
  totalLines: currentLineNo,
259946
- requestedLines
260584
+ requestedLines,
260585
+ maxBytes,
260586
+ maxLines
259947
260587
  });
259948
260588
  }
259949
260589
  finishTailEntries(input) {
@@ -259957,7 +260597,7 @@ var init_read = __esmMin((() => {
259957
260597
  let totalBytes = 0;
259958
260598
  for (const [index, candidate] of renderedCandidates.entries()) totalBytes += renderedLineBytes(candidate.rendered.line, index === 0);
259959
260599
  let maxBytesReached = false;
259960
- if (totalBytes > MAX_BYTES) {
260600
+ if (totalBytes > input.maxBytes) {
259961
260601
  maxBytesReached = true;
259962
260602
  const kept = [];
259963
260603
  let bytes = 0;
@@ -259965,7 +260605,7 @@ var init_read = __esmMin((() => {
259965
260605
  const candidate = renderedCandidates[i];
259966
260606
  if (candidate === void 0) continue;
259967
260607
  const lineBytes = renderedLineBytes(candidate.rendered.line, kept.length === 0);
259968
- if (bytes + lineBytes > MAX_BYTES) break;
260608
+ if (bytes + lineBytes > input.maxBytes) break;
259969
260609
  kept.unshift(candidate);
259970
260610
  bytes += lineBytes;
259971
260611
  }
@@ -259985,7 +260625,9 @@ var init_read = __esmMin((() => {
259985
260625
  lineEndingStyle,
259986
260626
  startLine: renderedCandidates[0]?.entry.lineNo ?? 0,
259987
260627
  totalLines: input.totalLines,
259988
- requestedLines: input.requestedLines
260628
+ requestedLines: input.requestedLines,
260629
+ maxBytes: input.maxBytes,
260630
+ maxLines: input.maxLines
259989
260631
  });
259990
260632
  }
259991
260633
  finishReadResult(input) {
@@ -260000,8 +260642,8 @@ var init_read = __esmMin((() => {
260000
260642
  const lineCount = input.renderedLines.length;
260001
260643
  const parts = lineCount > 0 ? [`${String(lineCount)} ${lineCount === 1 ? "line" : "lines"} read from file starting from line ${String(input.startLine)}.`] : ["No lines read from file."];
260002
260644
  parts.push(`Total lines in file: ${String(input.totalLines)}.`);
260003
- if (input.maxLinesReached) parts.push(`Max ${String(MAX_LINES$1)} lines reached.`);
260004
- else if (input.maxBytesReached) parts.push(`Max ${String(MAX_BYTES)} bytes reached.`);
260645
+ if (input.maxLinesReached) parts.push(`Max ${String(input.maxLines)} lines reached.`);
260646
+ else if (input.maxBytesReached) parts.push(`Max ${String(input.maxBytes)} bytes reached.`);
260005
260647
  else if (lineCount < input.requestedLines) parts.push("End of file reached.");
260006
260648
  const continuationNotice = readContinuationNotice({
260007
260649
  ...input,
@@ -260020,10 +260662,10 @@ var init_read = __esmMin((() => {
260020
260662
  name = "ReadBatch";
260021
260663
  description = READ_BATCH_DESCRIPTION;
260022
260664
  parameters = toInputJsonSchema(ReadBatchInputSchema);
260023
- constructor(kaos, workspace) {
260665
+ constructor(kaos, workspace, contextWindowState) {
260024
260666
  this.kaos = kaos;
260025
260667
  this.workspace = workspace;
260026
- this.reader = new ReadTool(kaos, workspace);
260668
+ this.reader = new ReadTool(kaos, workspace, contextWindowState);
260027
260669
  }
260028
260670
  resolveExecution(args) {
260029
260671
  const items = args.requests.map((request) => ({
@@ -261418,7 +262060,7 @@ function renderHistoricalToolResultReference(toolName, toolCallId, text, outputP
261418
262060
  function safeToolResultFileStem(toolName, toolCallId) {
261419
262061
  return `${toolName}-${toolCallId}`.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80) || "tool-result";
261420
262062
  }
261421
- var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_HISTORICAL_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldKeepFreshToolResult, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, currentTurnReadToolResultIds, currentUserTurnStartIndex, dedupeRepeatedSuccessfulToolResults, readContinuationLineOffset, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
262063
+ var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_HISTORICAL_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldKeepFreshToolResult, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, currentTurnReadToolResultIds, currentUserTurnStartIndex, dedupeRepeatedSuccessfulToolResults, hasToolResultOffloadPressure, readContinuationLineOffset, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
261422
262064
  var init_tool_result_budget = __esmMin((() => {
261423
262065
  init_dist$6();
261424
262066
  const toolResultOffloadPolicy = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs");
@@ -261438,6 +262080,7 @@ var init_tool_result_budget = __esmMin((() => {
261438
262080
  currentUserTurnStartIndex = toolResultOffloadPolicy.currentUserTurnStartIndex;
261439
262081
  dedupeRepeatedSuccessfulToolResults = toolResultOffloadPolicy.dedupeRepeatedSuccessfulToolResults;
261440
262082
  freshToolResultIds = toolResultOffloadPolicy.freshToolResultIds;
262083
+ hasToolResultOffloadPressure = toolResultOffloadPolicy.hasToolResultOffloadPressure;
261441
262084
  readContinuationLineOffset = toolResultOffloadPolicy.readContinuationLineOffset;
261442
262085
  selectToolResultBatchOffloads = toolResultOffloadPolicy.selectToolResultBatchOffloads;
261443
262086
  selectHistoricalToolResultOffloads = toolResultOffloadPolicy.selectHistoricalToolResultOffloads;
@@ -261452,6 +262095,7 @@ var ToolResultBatchOffload = class {
261452
262095
  }
261453
262096
  async detect() {
261454
262097
  const history = this.agent.context.history;
262098
+ if (!toolResultOffloadPressureForAgent(this.agent)) return 0;
261455
262099
  const tailIds = freshToolResultIds(history);
261456
262100
  const pinnedReadIds = currentTurnReadToolResultIds(history);
261457
262101
  const recentStart = Math.max(0, history.length - TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES);
@@ -261534,6 +262178,7 @@ var ToolResultBatchOffload = class {
261534
262178
  });
261535
262179
  }
261536
262180
  compact(messages) {
262181
+ if (!toolResultOffloadPressureForAgent(this.agent)) return messages;
261537
262182
  const recentStart = Math.max(0, messages.length - TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES);
261538
262183
  let changed = false;
261539
262184
  const projected = messages.map((message, index) => {
@@ -261584,6 +262229,13 @@ var ToolResultBatchOffload = class {
261584
262229
  }
261585
262230
  }
261586
262231
  };
262232
+ function toolResultOffloadPressureForAgent(agent) {
262233
+ return hasToolResultOffloadPressure({ contextUsageRatio: contextUsageRatioForAgent(agent) });
262234
+ }
262235
+ function contextUsageRatioForAgent(agent) {
262236
+ const maxContextTokens = agent.fullCompaction.getEffectiveMaxContextTokens();
262237
+ return maxContextTokens > 0 ? agent.context.tokenCountWithPending / maxContextTokens : 1;
262238
+ }
261587
262239
  //#endregion
261588
262240
  //#region ../../packages/agent-core/src/agent/turn/user-message-offload.ts
261589
262241
  function persistableUserMessageText(message) {
@@ -261652,6 +262304,7 @@ var UserMessageOffload = class {
261652
262304
  if (this.agent.homedir === void 0) return 0;
261653
262305
  const currentTurnStart = currentUserTurnStartIndex(history);
261654
262306
  const totalHistoryChars = historyTextChars(history);
262307
+ const contextUsageRatio = contextUsageRatioForAgent(this.agent);
261655
262308
  let offloaded = 0;
261656
262309
  for (let historyIndex = 0; historyIndex < history.length; historyIndex++) {
261657
262310
  if (historyIndex === currentTurnStart) continue;
@@ -261663,7 +262316,8 @@ var UserMessageOffload = class {
261663
262316
  historyIndex,
261664
262317
  historyLength: history.length,
261665
262318
  historyChars: totalHistoryChars,
261666
- textChars: text.length
262319
+ textChars: text.length,
262320
+ contextUsageRatio
261667
262321
  });
261668
262322
  if (!immediateOversize && !historicalOversize) continue;
261669
262323
  const messageHash = userMessageOffloadHash(message, text);
@@ -261675,6 +262329,14 @@ var UserMessageOffload = class {
261675
262329
  type: "text",
261676
262330
  text: replacementText
261677
262331
  }, ...message.content.filter((part) => part.type !== "text")];
262332
+ this.agent.records.logRecord({
262333
+ type: "policy.intervention",
262334
+ policy: "user_message_offload",
262335
+ location: "UserMessageOffload.detect",
262336
+ size_before: text.length,
262337
+ size_after: replacementText.length,
262338
+ unit: "chars"
262339
+ });
261678
262340
  this.apply({
261679
262341
  messageHash,
261680
262342
  content,
@@ -261699,7 +262361,7 @@ var UserMessageOffload = class {
261699
262361
  });
261700
262362
  }
261701
262363
  compact(messages) {
261702
- if (this.replacements.size === 0) return messages;
262364
+ if (this.replacements.size === 0 || !toolResultOffloadPressureForAgent(this.agent)) return messages;
261703
262365
  return messages.map((message) => {
261704
262366
  const text = persistableUserMessageText(message);
261705
262367
  if (text === void 0) return message;
@@ -261786,6 +262448,7 @@ var AssistantMessageOffload = class {
261786
262448
  const history = this.agent.context.history;
261787
262449
  if (this.agent.homedir === void 0) return 0;
261788
262450
  const totalHistoryChars = historyTextChars(history);
262451
+ const contextUsageRatio = contextUsageRatioForAgent(this.agent);
261789
262452
  let offloaded = 0;
261790
262453
  for (let historyIndex = 0; historyIndex < history.length; historyIndex++) {
261791
262454
  const message = history[historyIndex];
@@ -261794,7 +262457,8 @@ var AssistantMessageOffload = class {
261794
262457
  historyIndex,
261795
262458
  historyLength: history.length,
261796
262459
  historyChars: totalHistoryChars,
261797
- textChars: text.length
262460
+ textChars: text.length,
262461
+ contextUsageRatio
261798
262462
  })) continue;
261799
262463
  const messageHash = assistantMessageOffloadHash(message, text);
261800
262464
  if (this.replacements.has(messageHash)) continue;
@@ -261805,6 +262469,14 @@ var AssistantMessageOffload = class {
261805
262469
  type: "text",
261806
262470
  text: replacementText
261807
262471
  }, ...message.content.filter((part) => part.type !== "text")];
262472
+ this.agent.records.logRecord({
262473
+ type: "policy.intervention",
262474
+ policy: "assistant_message_offload",
262475
+ location: "AssistantMessageOffload.detect",
262476
+ size_before: text.length,
262477
+ size_after: replacementText.length,
262478
+ unit: "chars"
262479
+ });
261808
262480
  this.apply({
261809
262481
  messageHash,
261810
262482
  content,
@@ -261829,6 +262501,7 @@ var AssistantMessageOffload = class {
261829
262501
  });
261830
262502
  }
261831
262503
  compact(messages) {
262504
+ const underPressure = toolResultOffloadPressureForAgent(this.agent);
261832
262505
  const completedToolCallIds = new Set(messages.filter((message) => message?.role === "tool" && message.toolCallId !== void 0).map((message) => message.toolCallId));
261833
262506
  const totalHistoryChars = historyTextChars(messages);
261834
262507
  let changed = false;
@@ -261858,7 +262531,7 @@ var AssistantMessageOffload = class {
261858
262531
  }
261859
262532
  const text = persistableAssistantMessageText(message);
261860
262533
  if (text === void 0) return message;
261861
- const replacement = this.replacements.get(assistantMessageOffloadHash(message, text));
262534
+ const replacement = underPressure ? this.replacements.get(assistantMessageOffloadHash(message, text)) : void 0;
261862
262535
  if (replacement === void 0) return message;
261863
262536
  changed = true;
261864
262537
  return { ...message, content: replacement.content };
@@ -261885,6 +262558,17 @@ function blunExtractText(content) {
261885
262558
  if (Array.isArray(content)) return content.map((c) => typeof c === "string" ? c : c && typeof c === "object" && "text" in c && typeof c.text === "string" ? c.text : "").join(" ");
261886
262559
  return "";
261887
262560
  }
262561
+ function blunRepeatActiveTurnPrompt(history, input, stepNumber) {
262562
+ if (stepNumber <= 1) return history;
262563
+ const prompt = blunExtractText(input);
262564
+ if (prompt.length === 0) return history;
262565
+ return [...history, {
262566
+ role: "user",
262567
+ content: [{ type: "text", text: `<active-task-reminder>\nThe active user task is repeated verbatim below. Continue from the current work state; do not restart completed work.\n\n${prompt}\n</active-task-reminder>` }],
262568
+ toolCalls: [],
262569
+ origin: { kind: "injection", variant: "active_turn_prompt" }
262570
+ }];
262571
+ }
261888
262572
  /**
261889
262573
  * BLUN: decide whether a turn should carry the full tool set. Small-context models
261890
262574
  * (e.g. King on an 8k window) lose their identity/language when all tool schemas
@@ -262263,6 +262947,15 @@ var init_turn = __esmMin((() => {
262263
262947
  kind: "system_trigger",
262264
262948
  name: "goal_continuation"
262265
262949
  };
262950
+ function goalContinuationOrigin(origin) {
262951
+ const cronRunId = origin?.kind === "cron_job" ? origin.runId : origin?.cronRunId;
262952
+ if (cronRunId === void 0 && origin?.toolScope === void 0) return GOAL_CONTINUATION_ORIGIN;
262953
+ return {
262954
+ ...GOAL_CONTINUATION_ORIGIN,
262955
+ ...(cronRunId === void 0 ? {} : { cronRunId }),
262956
+ ...(origin?.toolScope === void 0 ? {} : { toolScope: origin.toolScope })
262957
+ };
262958
+ }
262266
262959
  GOAL_COMPLETION_REMINDER_NAME = "goal_completion";
262267
262960
  GOAL_BLOCKED_REMINDER_NAME = "goal_blocked";
262268
262961
  GOAL_RATE_LIMIT_PAUSE_REASON = "Paused after provider rate limit";
@@ -262310,6 +263003,7 @@ var init_turn = __esmMin((() => {
262310
263003
  stepToolCallKeys = /* @__PURE__ */ new Map();
262311
263004
  telemetryModeByTurn = /* @__PURE__ */ new Map();
262312
263005
  currentStepByTurn = /* @__PURE__ */ new Map();
263006
+ toolScopeByTurn = /* @__PURE__ */ new Map();
262313
263007
  interruptedTelemetryTurnIds = /* @__PURE__ */ new Set();
262314
263008
  stepFailureByTurn = /* @__PURE__ */ new Map();
262315
263009
  currentStep = 0;
@@ -262576,10 +263270,11 @@ var init_turn = __esmMin((() => {
262576
263270
  duplicate: false
262577
263271
  };
262578
263272
  }
262579
- retry(trigger) {
263273
+ retry(trigger, toolScope) {
262580
263274
  return this.prompt([], {
262581
263275
  kind: "retry",
262582
- trigger
263276
+ trigger,
263277
+ ...(toolScope === void 0 ? {} : { toolScope })
262583
263278
  });
262584
263279
  }
262585
263280
  launch(input, origin) {
@@ -262657,6 +263352,9 @@ var init_turn = __esmMin((() => {
262657
263352
  get hasActiveTurn() {
262658
263353
  return this.activeTurn !== null && this.activeTurn !== "resuming";
262659
263354
  }
263355
+ toolScopeForTurn(turnId) {
263356
+ return this.toolScopeByTurn.get(turnId);
263357
+ }
262660
263358
  ensureActiveTurn() {
262661
263359
  if (this.activeTurn === null || this.activeTurn === "resuming") throw new Error("No active turn");
262662
263360
  return this.activeTurn;
@@ -262768,15 +263466,23 @@ var init_turn = __esmMin((() => {
262768
263466
  */
262769
263467
  async turnWorker(firstTurnId, input, origin, signal) {
262770
263468
  const ownsActiveTurn = () => this.activeTurn !== null && this.activeTurn !== "resuming" && this.activeTurn.controller.signal === signal;
263469
+ let result;
262771
263470
  try {
262772
- if (this.agent.goal.getGoal().goal?.status === "active") return await this.driveGoal(firstTurnId, input, origin, signal);
262773
- const end = await this.runOneTurn(firstTurnId, input, origin, signal, true);
262774
- if (this.agent.goal.getGoal().goal?.status === "active" && end.event.reason !== "cancelled" && end.event.reason !== "failed" && end.event.reason !== "filtered") return await this.driveGoal(this.allocateTurnId(), [{
262775
- type: "text",
262776
- text: GOAL_CONTINUATION_PROMPT
262777
- }], GOAL_CONTINUATION_ORIGIN, signal);
262778
- return end;
263471
+ if (this.agent.goal.getGoal().goal?.status === "active") result = await this.driveGoal(firstTurnId, input, origin, signal);
263472
+ else {
263473
+ const end = await this.runOneTurn(firstTurnId, input, origin, signal, true);
263474
+ if (this.agent.goal.getGoal().goal?.status === "active" && end.event.reason !== "cancelled" && end.event.reason !== "failed" && end.event.reason !== "filtered") result = await this.driveGoal(this.allocateTurnId(), [{
263475
+ type: "text",
263476
+ text: GOAL_CONTINUATION_PROMPT
263477
+ }], goalContinuationOrigin(origin), signal);
263478
+ else result = end;
263479
+ }
263480
+ return result;
263481
+ } catch (error) {
263482
+ if (origin.kind === "cron_job" && typeof origin.runId === "string") this.agent.cron?.observeRunWorkerFailed(origin.runId);
263483
+ throw error;
262779
263484
  } finally {
263485
+ if (result !== void 0 && origin.kind === "cron_job" && typeof origin.runId === "string") this.agent.cron?.observeRunWorkerEnded(origin.runId, result.event);
262780
263486
  if (ownsActiveTurn()) this.activeTurn = null;
262781
263487
  }
262782
263488
  }
@@ -262830,7 +263536,7 @@ var init_turn = __esmMin((() => {
262830
263536
  type: "text",
262831
263537
  text: GOAL_CONTINUATION_PROMPT
262832
263538
  }];
262833
- turnOrigin = GOAL_CONTINUATION_ORIGIN;
263539
+ turnOrigin = goalContinuationOrigin(origin);
262834
263540
  }
262835
263541
  }
262836
263542
  async endGoalTurnWithoutModel(turnId, input, origin) {
@@ -262878,6 +263584,7 @@ var init_turn = __esmMin((() => {
262878
263584
  this.currentStepByTurn.set(turnId, 0);
262879
263585
  this.recordExternalReportSources(turnId, origin);
262880
263586
  const persistedOrigin = durablePromptOrigin(origin);
263587
+ if (persistedOrigin.toolScope !== void 0) this.toolScopeByTurn.set(turnId, persistedOrigin.toolScope);
262881
263588
  this.agent.telemetry.track("turn_started", {
262882
263589
  mode: telemetryMode,
262883
263590
  ...this.requestProviderProps()
@@ -262985,6 +263692,7 @@ var init_turn = __esmMin((() => {
262985
263692
  if (ended.reason !== "completed") this.trackTurnInterrupted(turnId, this.currentStepByTurn.get(turnId) ?? this.currentStep);
262986
263693
  this.telemetryModeByTurn.delete(turnId);
262987
263694
  this.currentStepByTurn.delete(turnId);
263695
+ this.toolScopeByTurn.delete(turnId);
262988
263696
  this.interruptedTelemetryTurnIds.delete(turnId);
262989
263697
  this.cognitiveActionEvidenceByTurn.delete(turnId);
262990
263698
  this.cognitiveExternalReportsByTurn.delete(turnId);
@@ -263082,13 +263790,14 @@ var init_turn = __esmMin((() => {
263082
263790
  let previousStepToolOutcome = "initial";
263083
263791
  let currentStepHadTool = false;
263084
263792
  let currentStepHadFailure = false;
263793
+ let currentLoopStep = 0;
263085
263794
  while (true) {
263086
263795
  signal.throwIfAborted();
263087
263796
  const model = this.agent.config.model;
263088
263797
  const loopControl = this.agent.blunConfig?.loopControl;
263089
263798
  let stopForGoalBudget = false;
263090
263799
  try {
263091
- const originTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools), origin);
263800
+ const originTools = filterToolsForCronScope(blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools), origin), origin.toolScope);
263092
263801
  const compactConversationTool = originTools.find((tool) => tool.name === "CompactConversation");
263093
263802
  const eligibleTools = originTools.filter((tool) => tool.name !== "CompactConversation" || this.agent.fullCompaction.isProactiveCompactionEligible());
263094
263803
  const turnRequiredToolNames = new Set(requiredToolNames);
@@ -263114,12 +263823,13 @@ var init_turn = __esmMin((() => {
263114
263823
  eligibleToolSchemaTokens: estimateTokensForTools(eligibleTools),
263115
263824
  selectedToolSchemaTokens: estimateTokensForTools(selectedTools)
263116
263825
  });
263826
+ const turnHistory = () => fastConversation ? turnThinkingEffort === "off" ? blunStandaloneConversationHistory(this.agent.context.history) : blunFastConversationHistory(this.agent.context.history) : origin.kind === "cron_job" && origin.recurring === true ? projectRecurringCronHistory(this.agent.context.history, origin.jobId) : personalMemoryRecall === void 0 ? this.agent.context.history : [...this.agent.context.history, personalMemoryRecall];
263117
263827
  return (await runTurn({
263118
263828
  turnId: String(turnId),
263119
263829
  signal,
263120
263830
  llm: turnLLM,
263121
- buildMessages: () => this.agent.context.project(fastConversation ? turnThinkingEffort === "off" ? blunStandaloneConversationHistory(this.agent.context.history) : blunFastConversationHistory(this.agent.context.history) : origin.kind === "cron_job" && origin.recurring === true ? projectRecurringCronHistory(this.agent.context.history, origin.jobId) : personalMemoryRecall === void 0 ? this.agent.context.history : [...this.agent.context.history, personalMemoryRecall], { dropOrphanResults: true }),
263122
- buildMessagesStrict: () => this.agent.context.project(fastConversation ? turnThinkingEffort === "off" ? blunStandaloneConversationHistory(this.agent.context.history) : blunFastConversationHistory(this.agent.context.history) : origin.kind === "cron_job" && origin.recurring === true ? projectRecurringCronHistory(this.agent.context.history, origin.jobId) : personalMemoryRecall === void 0 ? this.agent.context.history : [...this.agent.context.history, personalMemoryRecall], {
263831
+ buildMessages: () => this.agent.context.project(blunRepeatActiveTurnPrompt(turnHistory(), input, currentLoopStep), { dropOrphanResults: true }),
263832
+ buildMessagesStrict: () => this.agent.context.project(blunRepeatActiveTurnPrompt(turnHistory(), input, currentLoopStep), {
263123
263833
  synthesizeMissing: true,
263124
263834
  dropOrphanResults: true,
263125
263835
  dedupeDuplicateToolCalls: true,
@@ -263140,6 +263850,7 @@ var init_turn = __esmMin((() => {
263140
263850
  },
263141
263851
  hooks: {
263142
263852
  beforeStep: async ({ signal: stepSignal, stepNumber }) => {
263853
+ currentLoopStep = stepNumber;
263143
263854
  await this.agent.records.flush();
263144
263855
  await this.agent.toolResultBatchOffload.detect();
263145
263856
  this.agent.microCompaction.detect();
@@ -263377,6 +264088,7 @@ var init_turn = __esmMin((() => {
263377
264088
  buildDispatchEvent(turnId) {
263378
264089
  return createLoopEventDispatcher({
263379
264090
  appendTranscriptRecord: async (event) => {
264091
+ this.agent.cron?.observeLoopEvent(turnId, event);
263380
264092
  this.agent.context.appendLoopEvent(event);
263381
264093
  },
263382
264094
  emitLiveEvent: (event) => {
@@ -264434,7 +265146,7 @@ var init_codebase_search = __esmMin((() => {
264434
265146
  description: `Semantic search: ${args.query.length > 50 ? `${args.query.slice(0, 50)}…` : args.query}`,
264435
265147
  display: {
264436
265148
  kind: "command",
264437
- command: `python codebase_index.py query . "${args.query}" --top ${String(args.top)}`,
265149
+ command: `python codebase_index.py query . "${args.query}" --top ${String(args.top)} --model auto`,
264438
265150
  cwd: this.cwd,
264439
265151
  description: `Codebase semantic search`,
264440
265152
  language: "bash"
@@ -264454,7 +265166,9 @@ var init_codebase_search = __esmMin((() => {
264454
265166
  this.cwd,
264455
265167
  args.query,
264456
265168
  "--top",
264457
- String(args.top)
265169
+ String(args.top),
265170
+ "--model",
265171
+ "auto"
264458
265172
  ], {
264459
265173
  cwd: this.cwd,
264460
265174
  timeout: SCRIPT_TIMEOUT_MS,
@@ -265087,10 +265801,12 @@ var init_builtin = __esmMin((() => {
265087
265801
  init_task_list();
265088
265802
  init_task_output();
265089
265803
  init_task_update();
265804
+ init_task_resume();
265090
265805
  init_task_stop();
265091
265806
  init_cron_create();
265092
265807
  init_cron_delete();
265093
265808
  init_cron_list();
265809
+ init_cron_runs();
265094
265810
  init_agent$1();
265095
265811
  init_agent_swarm();
265096
265812
  init_ask_user();
@@ -265320,9 +266036,10 @@ var init_tool$1 = __esmMin((() => {
265320
266036
  hasUserTool(name) {
265321
266037
  return this.userTools.has(name);
265322
266038
  }
265323
- inheritUserTools(parent) {
266039
+ inheritUserTools(parent, excludedNames = /* @__PURE__ */ new Set()) {
265324
266040
  for (const tool of parent.userTools.values()) {
265325
266041
  if (!parent.enabledTools.has(tool.name)) continue;
266042
+ if (excludedNames.has(tool.name)) continue;
265326
266043
  this.registerUserTool({
265327
266044
  name: tool.name,
265328
266045
  description: tool.description,
@@ -265537,9 +266254,13 @@ var init_tool$1 = __esmMin((() => {
265537
266254
  }, this.agent.skills?.registry.getSkillRoots() ?? []);
265538
266255
  const allowBackground = this.enabledTools.has("TaskList") && this.enabledTools.has("TaskOutput") && this.enabledTools.has("TaskStop");
265539
266256
  const goalToolsEnabled = this.agent.type === "main";
266257
+ const readBudget = () => ({
266258
+ contextTokens: this.agent.context.tokenCountWithPending,
266259
+ maxContextTokens: this.agent.fullCompaction.getEffectiveMaxContextTokens()
266260
+ });
265540
266261
  this.builtinTools = new Map([
265541
- new ReadTool(kaos, workspace),
265542
- new ReadBatchTool(kaos, workspace),
266262
+ new ReadTool(kaos, workspace, readBudget),
266263
+ new ReadBatchTool(kaos, workspace, readBudget),
265543
266264
  new WriteTool(kaos, workspace, () => this.agent.context.history, toolServices?.lsp),
265544
266265
  new EditTool(kaos, workspace, () => this.agent.context.history, toolServices?.lsp),
265545
266266
  new GrepTool(kaos, workspace, this.agent.telemetry),
@@ -265559,9 +266280,12 @@ var init_tool$1 = __esmMin((() => {
265559
266280
  new TaskListTool(background),
265560
266281
  new TaskOutputTool(background),
265561
266282
  new TaskUpdateTool(background),
266283
+ this.agent.subagentHost && allowBackground && background.resumeStore && new TaskResumeTool(background, this.agent.subagentHost),
265562
266284
  new TaskStopTool(background),
265563
266285
  this.agent.cron && new CronCreateTool(this.agent.cron),
265564
266286
  this.agent.cron && new CronListTool(this.agent.cron),
266287
+ this.agent.cron && new CronRunListTool(this.agent.cron),
266288
+ this.agent.cron && new CronRunOutputTool(this.agent.cron),
265565
266289
  this.agent.cron && new CronDeleteTool(this.agent.cron),
265566
266290
  this.agent.skills?.registry.listInvocableSkills().length && new SkillTool(this.agent),
265567
266291
  this.agent.subagentHost && new AgentTool(this.agent.subagentHost, background, DEFAULT_AGENT_PROFILES["agent"]?.subagents, {
@@ -266008,7 +266732,7 @@ var init_agent = __esmMin((() => {
266008
266732
  ({ createEffectiveSystemPromptResolver } = createRequire(import.meta.url)("./bin/effective-system-prompt-cache-policy.cjs"));
266009
266733
  ({ resolveProviderIdleTimeoutMs } = createRequire(import.meta.url)("./bin/provider-idle-timeout-policy.cjs"));
266010
266734
  ({ capCompletionBudgetForAdaptiveEffort, capTurnCompletionTokens, selectThinkingEffortForBufferedSteer, selectThinkingEffortForWorkStep, selectThinkingEffortForTurn } = createRequire(import.meta.url)("./bin/turn-thinking-policy.cjs"));
266011
- PINNED_MODEL_ALIASES = new Set(["king-blun", "pruefstand"]);
266735
+ PINNED_MODEL_ALIASES = new Set(["blun/king"]);
266012
266736
  Agent$1 = class {
266013
266737
  type;
266014
266738
  _kaos;
@@ -266550,6 +267274,7 @@ var init_agent = __esmMin((() => {
266550
267274
  }
266551
267275
  emitEvent(event) {
266552
267276
  if (this.records.restoring) return;
267277
+ this.cron?.observeAgentEvent(event);
266553
267278
  return this.rpc?.emitEvent?.(event);
266554
267279
  }
266555
267280
  emitStatusUpdated() {
@@ -298410,7 +299135,9 @@ var init_session$1 = __esmMin((() => {
298410
299135
  homedir,
298411
299136
  type,
298412
299137
  parentAgentId,
298413
- swarmItem: options.swarmItem
299138
+ swarmItem: options.swarmItem,
299139
+ profileName: options.profileName,
299140
+ skillPolicy: options.skillPolicy
298414
299141
  };
298415
299142
  this.writeMetadata();
298416
299143
  }
@@ -298686,7 +299413,7 @@ var init_session$1 = __esmMin((() => {
298686
299413
  missingCapability: part.missingCapability
298687
299414
  });
298688
299415
  },
298689
- skills: this.skills,
299416
+ skills: config.skillRegistry === void 0 ? this.skills : config.skillRegistry,
298690
299417
  rpc: proxyWithExtraPayload(this.rpc, { agentId: id }),
298691
299418
  modelProvider: this.options.providerManager,
298692
299419
  hookEngine: config.hookEngine ?? this.hookEngine,
@@ -298751,9 +299478,16 @@ var init_session$1 = __esmMin((() => {
298751
299478
  const parentAgentId = meta.parentAgentId ?? null;
298752
299479
  const parent = parentAgentId === null ? void 0 : await this.resumeAgent(parentAgentId, [...stack, id]);
298753
299480
  try {
298754
- const agent = this.instantiateAgent(id, meta.homedir, meta.type, {}, parentAgentId);
299481
+ let restoredSkillPolicy;
299482
+ if (meta.type === "sub" && meta.skillPolicy !== void 0) {
299483
+ if (meta.profileName === void 0) throw new Error("SUBAGENT_SKILL_POLICY_CHANGED: persisted subagent profile is unavailable; spawn a new subagent");
299484
+ const persistedProfile = DEFAULT_AGENT_PROFILES[parent?.agent.config.profileName ?? "agent"]?.subagents?.[meta.profileName] ?? DEFAULT_AGENT_PROFILES["agent"]?.subagents?.[meta.profileName];
299485
+ if (persistedProfile === void 0) throw new Error("SUBAGENT_SKILL_POLICY_CHANGED: persisted subagent profile was not found; spawn a new subagent");
299486
+ restoredSkillPolicy = restoreSubagentSkillPolicy(persistedProfile.subagentSkills, meta.skillPolicy, this.skills);
299487
+ }
299488
+ const agent = this.instantiateAgent(id, meta.homedir, meta.type, restoredSkillPolicy === void 0 ? {} : { skillRegistry: restoredSkillPolicy.registry }, parentAgentId);
298755
299489
  const result = await agent.resume();
298756
- await this.restoreAgentProfileHandle(agent, meta, parent?.agent);
299490
+ await this.restoreAgentProfileHandle(agent, meta, parent?.agent, restoredSkillPolicy);
298757
299491
  this.ensureBaselineSkill(agent);
298758
299492
  agent.setRuntimeSystemPromptAppend(this.accountMemoryContext);
298759
299493
  this.agents.set(id, agent);
@@ -298766,18 +299500,33 @@ var init_session$1 = __esmMin((() => {
298766
299500
  throw error;
298767
299501
  }
298768
299502
  }
298769
- async restoreAgentProfileHandle(agent, meta, parentAgent) {
299503
+ async restoreAgentProfileHandle(agent, meta, parentAgent, restoredSkillPolicy) {
298770
299504
  if (agent.config.systemPrompt === "") return;
298771
- const profile = this.resolvePersistedProfile(agent, meta, parentAgent);
299505
+ let profile = this.resolvePersistedProfile(agent, meta, parentAgent);
298772
299506
  if (profile === void 0) return;
299507
+ if (restoredSkillPolicy !== void 0) profile = profileWithSubagentSkillTools(profile, restoredSkillPolicy);
298773
299508
  agent.setActiveProfile(profile, this.options.blunHomeDir);
298774
299509
  await agent.refreshSystemPrompt();
298775
299510
  }
298776
299511
  ensureBaselineSkill(agent) {
298777
- if (agent.skills?.ensureBaseline(BASELINE_SKILL_NAME) !== true) this.log.warn("baseline skill is unavailable", { skill: BASELINE_SKILL_NAME });
299512
+ const skill = this.skills.getSkill(BASELINE_SKILL_NAME);
299513
+ if (skill === void 0) {
299514
+ this.log.warn("baseline skill is unavailable", { skill: BASELINE_SKILL_NAME });
299515
+ return;
299516
+ }
299517
+ const variant = `${BASELINE_SKILL_ORIGIN_PREFIX}${skill.name}`;
299518
+ if (agent.context.history.some((message) => message.origin?.kind === "injection" && message.origin.variant === variant)) return;
299519
+ agent.context.appendSystemReminder(renderBaselineSkillPrompt({
299520
+ skillName: skill.name,
299521
+ skillSource: skill.source,
299522
+ skillDir: skill.dir
299523
+ }), {
299524
+ kind: "injection",
299525
+ variant
299526
+ });
298778
299527
  }
298779
299528
  resolvePersistedProfile(agent, meta, parentAgent) {
298780
- const profileName = agent.config.profileName;
299529
+ const profileName = meta.profileName ?? agent.config.profileName;
298781
299530
  if (profileName === void 0) return void 0;
298782
299531
  if (meta.type === "sub") return DEFAULT_AGENT_PROFILES[parentAgent?.config.profileName ?? "agent"]?.subagents?.[profileName] ?? DEFAULT_AGENT_PROFILES["agent"]?.subagents?.[profileName];
298783
299532
  return DEFAULT_AGENT_PROFILES[profileName];
@@ -313566,27 +314315,14 @@ var init_local_fetch_url = __esmMin((() => {
313566
314315
  kind: "passthrough"
313567
314316
  };
313568
314317
  return {
313569
- content: this.extractMainContent(body),
314318
+ content: this.extractMainContent(body, url),
313570
314319
  kind: "extracted"
313571
314320
  };
313572
314321
  }
313573
- extractMainContent(html) {
313574
- const primary = parseHTML(html);
313575
- try {
313576
- const article = new import_readability.Readability(primary.document, { charThreshold: 0 }).parse();
313577
- if (article !== null) {
313578
- const text = (article.textContent ?? "").trim();
313579
- if (text.length > 0) {
313580
- const title = (article.title ?? "").trim();
313581
- return title.length > 0 ? `# ${title}\n\n${text}` : text;
313582
- }
313583
- }
313584
- } catch {}
313585
- const { document } = parseHTML(html);
313586
- const titleText = (document.querySelector("title")?.textContent ?? "").trim();
313587
- const fallbackText = ((document.querySelector("article") ?? document.querySelector("main") ?? document.querySelector("body"))?.textContent ?? "").trim();
313588
- if (fallbackText.length === 0) throw new Error("Failed to extract meaningful content from the page. The page may require JavaScript to render.");
313589
- return titleText.length > 0 ? `# ${titleText}\n\n${fallbackText}` : fallbackText;
314322
+ extractMainContent(html, baseUrl) {
314323
+ const content = htmlToResearchMarkdown(html, baseUrl);
314324
+ if (content.length === 0) throw new Error("Failed to extract meaningful content from the page. The page may require JavaScript to render.");
314325
+ return content;
313590
314326
  }
313591
314327
  };
313592
314328
  }));
@@ -315079,17 +315815,7 @@ function resolveModelCapabilities(alias, provider) {
315079
315815
  };
315080
315816
  }
315081
315817
  function toKosongProviderConfig(provider, model, blunRequestHeaders, promptCacheKey, supportEfforts) {
315082
- assertSupportedProviderType(provider);
315083
- if (provider.type === FREDRIK_GLM_PROVIDER_TYPE) return {
315084
- type: "blun",
315085
- model,
315086
- baseUrl: provider.baseUrl,
315087
- apiKey: readFredrikGlmApiKeyFile(provider),
315088
- generationKwargs: { prompt_cache_key: promptCacheKey },
315089
- supportEfforts: [...FREDRIK_GLM_EFFORTS],
315090
- openAICompatible: true,
315091
- defaultHeaders: { "User-Agent": "BLUN-King/Fredrik-GLM" }
315092
- };
315818
+ assertBlunProviderType(provider);
315093
315819
  const envCustomHeaders = parseBlunCodeCustomHeaders();
315094
315820
  return {
315095
315821
  type: "blun",
@@ -315110,12 +315836,11 @@ function defaultHeadersField(headers) {
315110
315836
  return { defaultHeaders: { ...headers } };
315111
315837
  }
315112
315838
  function providerApiKey(provider) {
315113
- assertSupportedProviderType(provider);
315114
- if (provider.type === FREDRIK_GLM_PROVIDER_TYPE) return readFredrikGlmApiKeyFile(provider);
315839
+ assertBlunProviderType(provider);
315115
315840
  return providerValue(provider.apiKey, provider.env, "BLUN_API_KEY");
315116
315841
  }
315117
- function assertSupportedProviderType(provider) {
315118
- if (provider.type !== "blun" && provider.type !== FREDRIK_GLM_PROVIDER_TYPE) throw new BlunError(ErrorCodes.MODEL_CONFIG_INVALID, "Only approved BLUN Code provider types are supported.");
315842
+ function assertBlunProviderType(provider) {
315843
+ if (provider.type !== "blun") throw new BlunError(ErrorCodes.MODEL_CONFIG_INVALID, "Only the BLUN provider type is supported.");
315119
315844
  }
315120
315845
  function providerValue(configured, env, envKey) {
315121
315846
  return nonEmptyString$2(configured) ?? envValue(env, envKey);
@@ -315134,7 +315859,7 @@ var init_provider_manager = __esmMin((() => {
315134
315859
  init_config$4();
315135
315860
  init_errors$8();
315136
315861
  MANAGED_PROVIDER_NAME$2 = "managed:blun";
315137
- MANAGED_BLUN_MODEL_ALIASES$1 = new Set(["blun/king", "king-blun"]);
315862
+ MANAGED_BLUN_MODEL_ALIASES$1 = new Set(["blun/king"]);
315138
315863
  ProviderManager = class {
315139
315864
  options;
315140
315865
  runtimeModelContexts = /* @__PURE__ */ new Map();
@@ -315153,9 +315878,7 @@ var init_provider_manager = __esmMin((() => {
315153
315878
  if (providerName === void 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, `Model "${model}" must define a provider in config.toml.`);
315154
315879
  const providerConfig = this.config.providers[providerName];
315155
315880
  if (providerConfig === void 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" for model "${model}" is not configured.`);
315156
- assertSupportedProviderType(providerConfig);
315157
- if (providerConfig.type === FREDRIK_GLM_PROVIDER_TYPE && (providerName !== FREDRIK_GLM_PROVIDER_ID || !isConfiguredFredrikGlmAlias(model, alias))) throw new BlunError(ErrorCodes.CONFIG_INVALID, "Fredrik GLM provider aliases must match the approved profile-local model catalog.");
315158
- if (providerConfig.type !== FREDRIK_GLM_PROVIDER_TYPE && isConfiguredFredrikGlmAlias(model, alias)) throw new BlunError(ErrorCodes.CONFIG_INVALID, "Fredrik GLM aliases require the approved profile-local provider.");
315881
+ assertBlunProviderType(providerConfig);
315159
315882
  const runtimeContext = this.runtimeModelContexts.get(model);
315160
315883
  const maxContextSize = runtimeContext?.providerName === providerName && runtimeContext.model === alias.model ? runtimeContext.maxContextTokens : effectiveAlias.maxContextSize;
315161
315884
  if (!Number.isInteger(maxContextSize) || maxContextSize <= 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, `Model "${model}" must define a positive max_context_size in config.toml.`);
@@ -315169,7 +315892,7 @@ var init_provider_manager = __esmMin((() => {
315169
315892
  }, provider),
315170
315893
  alwaysThinking: (effectiveAlias.capabilities ?? []).some((c) => c.trim().toLowerCase() === "always_thinking"),
315171
315894
  maxOutputSize: effectiveAlias.maxOutputSize,
315172
- type: providerConfig.type
315895
+ type: "blun"
315173
315896
  };
315174
315897
  }
315175
315898
  setRuntimeModelContext(input) {
@@ -315177,7 +315900,7 @@ var init_provider_manager = __esmMin((() => {
315177
315900
  if (!Number.isSafeInteger(input.maxContextTokens) || input.maxContextTokens <= 0) throw new BlunError(ErrorCodes.CONFIG_INVALID, "Runtime model context must be a positive integer.");
315178
315901
  const alias = this.config.models?.[input.modelAlias];
315179
315902
  const providerName = alias?.provider ?? this.config.defaultProvider;
315180
- if (alias === void 0 || providerName !== input.providerName || alias.model !== input.model || providerName !== "managed:blun" && providerName !== "king-blun") throw new BlunError(ErrorCodes.CONFIG_INVALID, "Runtime model context does not match the configured internal BLUN model.");
315903
+ if (alias === void 0 || providerName !== input.providerName || alias.model !== input.model || providerName !== "managed:blun") throw new BlunError(ErrorCodes.CONFIG_INVALID, "Runtime model context does not match the configured BLUN model.");
315181
315904
  const previous = this.runtimeModelContexts.get(input.modelAlias);
315182
315905
  this.runtimeModelContexts.set(input.modelAlias, {
315183
315906
  providerName: input.providerName,
@@ -315189,7 +315912,7 @@ var init_provider_manager = __esmMin((() => {
315189
315912
  resolveAuth(model, options) {
315190
315913
  const { providerName } = this.resolveProviderConfig(model);
315191
315914
  const providerConfig = this.config.providers[providerName];
315192
- const apiKey = providerConfig?.type === "blun" ? providerApiKey(providerConfig) : void 0;
315915
+ const apiKey = providerConfig === void 0 ? void 0 : providerApiKey(providerConfig);
315193
315916
  const revocationStore = this.options.managedApiKeyRevocationStore;
315194
315917
  if (providerName === MANAGED_PROVIDER_NAME$2 && providerConfig?.oauth === void 0 && apiKey !== void 0 && revocationStore !== void 0) return this.resolveManagedApiKeyAuth(providerName, apiKey, revocationStore, options?.log);
315195
315918
  if (providerConfig?.oauth === void 0) return void 0;
@@ -319412,6 +320135,7 @@ function toBrokerRequest$1(req, params) {
319412
320135
  tool_name: req.toolName,
319413
320136
  action: req.action,
319414
320137
  tool_input_display: req.display,
320138
+ allow_edit: req.allowEdit === true ? true : void 0,
319415
320139
  created_at: params.createdAt,
319416
320140
  expires_at: params.expiresAt
319417
320141
  };
@@ -319426,7 +320150,8 @@ function toAgentCoreResponse$1(resp) {
319426
320150
  decision: resp.decision,
319427
320151
  scope: resp.scope,
319428
320152
  feedback: resp.feedback,
319429
- selectedLabel: resp.selected_label
320153
+ selectedLabel: resp.selected_label,
320154
+ edited_tool_input: resp.edited_tool_input
319430
320155
  };
319431
320156
  }
319432
320157
  var IApprovalService;
@@ -373133,16 +373858,18 @@ var PendingApproval = class {
373133
373858
  createdAt;
373134
373859
  expiresAt;
373135
373860
  protocolRequest;
373861
+ editContext;
373136
373862
  _resolveFn;
373137
373863
  _rejectFn;
373138
373864
  _settled = false;
373139
- constructor(approvalId, sessionId, toolCallId, createdAt, expiresAt, protocolRequest, _resolveFn, _rejectFn) {
373865
+ constructor(approvalId, sessionId, toolCallId, createdAt, expiresAt, protocolRequest, editContext, _resolveFn, _rejectFn) {
373140
373866
  this.approvalId = approvalId;
373141
373867
  this.sessionId = sessionId;
373142
373868
  this.toolCallId = toolCallId;
373143
373869
  this.createdAt = createdAt;
373144
373870
  this.expiresAt = expiresAt;
373145
373871
  this.protocolRequest = protocolRequest;
373872
+ this.editContext = editContext;
373146
373873
  this._resolveFn = _resolveFn;
373147
373874
  this._rejectFn = _rejectFn;
373148
373875
  }
@@ -373216,7 +373943,10 @@ let ApprovalService = class ApprovalService extends Disposable {
373216
373943
  toolCallId: req.toolCallId
373217
373944
  }, "approval requested");
373218
373945
  return new Promise((resolve, reject) => {
373219
- this._pending.set(approvalId, new PendingApproval(approvalId, req.sessionId, req.toolCallId, createdAt, expiresAt, protocolRequest, resolve, reject));
373946
+ this._pending.set(approvalId, new PendingApproval(approvalId, req.sessionId, req.toolCallId, createdAt, expiresAt, protocolRequest, {
373947
+ toolName: req.toolName,
373948
+ editCount: Number.isSafeInteger(req.approvalEditCount) ? req.approvalEditCount : 0
373949
+ }, resolve, reject));
373220
373950
  this._byToolCallId.set(req.toolCallId, approvalId);
373221
373951
  });
373222
373952
  }
@@ -373245,6 +373975,14 @@ let ApprovalService = class ApprovalService extends Disposable {
373245
373975
  isPending(approvalId) {
373246
373976
  return this._pending.has(approvalId);
373247
373977
  }
373978
+ getEditContext(approvalId) {
373979
+ const pending = this._pending.get(approvalId);
373980
+ if (!pending) return void 0;
373981
+ return {
373982
+ toolName: pending.editContext.toolName,
373983
+ editCount: pending.editContext.editCount
373984
+ };
373985
+ }
373248
373986
  listPending(sessionId) {
373249
373987
  return Array.from(this._pending.values()).filter((p) => p.sessionId === sessionId).map((p) => p.protocolRequest);
373250
373988
  }
@@ -373287,6 +374025,24 @@ const approvalParamsSchema = object({
373287
374025
  session_id: string().min(1),
373288
374026
  approval_id: string().min(1)
373289
374027
  });
374028
+ const EDITABLE_APPROVAL_RAW_BODY_LIMIT = 65536;
374029
+ async function captureEditableApprovalRawBody(req, reply, payload) {
374030
+ const chunks = [];
374031
+ let totalBytes = 0;
374032
+ for await (const chunk of payload) {
374033
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
374034
+ totalBytes += bytes.length;
374035
+ if (totalBytes > EDITABLE_APPROVAL_RAW_BODY_LIMIT) {
374036
+ const error = new Error("Approval response body exceeds the editable-input limit");
374037
+ error.statusCode = 413;
374038
+ throw error;
374039
+ }
374040
+ chunks.push(bytes);
374041
+ }
374042
+ const rawBody = Buffer.concat(chunks, totalBytes);
374043
+ req.editableApprovalRawBody = rawBody.toString("utf8");
374044
+ return Readable.from([rawBody]);
374045
+ }
373290
374046
  function registerApprovalsRoutes(app, ix) {
373291
374047
  const listRoute = defineRoute({
373292
374048
  method: "GET",
@@ -373331,7 +374087,27 @@ function registerApprovalsRoutes(app, ix) {
373331
374087
  reply.send(errEnvelope(ErrorCode$1.APPROVAL_NOT_FOUND, `approval ${approval_id} not found`, req.id));
373332
374088
  return;
373333
374089
  }
373334
- const inProc = toAgentCoreResponse$1(body);
374090
+ const editContext = broker.getEditContext(approval_id);
374091
+ if (editContext === void 0 || typeof req.editableApprovalRawBody !== "string") {
374092
+ reply.send(errEnvelope(ErrorCode$1.VALIDATION_FAILED, "approval response could not be validated from its raw JSON body", req.id));
374093
+ return;
374094
+ }
374095
+ let inProc;
374096
+ try {
374097
+ const rawResponse = parseEditedToolInputJson(req.editableApprovalRawBody);
374098
+ const normalized = validateEditedApprovalDecision({
374099
+ response: rawResponse,
374100
+ toolName: editContext.toolName,
374101
+ editCount: editContext.editCount
374102
+ });
374103
+ inProc = normalized.decision === "edited" ? {
374104
+ decision: "edited",
374105
+ edited_tool_input: normalized.editedToolInput
374106
+ } : normalized;
374107
+ } catch (error) {
374108
+ reply.send(errEnvelope(ErrorCode$1.VALIDATION_FAILED, error instanceof Error ? error.message : String(error), req.id));
374109
+ return;
374110
+ }
373335
374111
  broker.resolve(approval_id, inProc);
373336
374112
  broker.markResolved(approval_id);
373337
374113
  const result = {
@@ -373340,6 +374116,7 @@ function registerApprovalsRoutes(app, ix) {
373340
374116
  };
373341
374117
  reply.send(okEnvelope(result, req.id));
373342
374118
  });
374119
+ route.options.preParsing = captureEditableApprovalRawBody;
373343
374120
  app.post(route.path, route.options, route.handler);
373344
374121
  }
373345
374122
  //#endregion
@@ -404208,13 +404985,6 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
404208
404985
  completeArgs: swarmArgumentCompletions,
404209
404986
  availability: "idle-only"
404210
404987
  },
404211
- {
404212
- name: "model",
404213
- aliases: [],
404214
- descriptionKey: "command.model.description",
404215
- priority: 96,
404216
- availability: "always"
404217
- },
404218
404988
  {
404219
404989
  name: "effort",
404220
404990
  aliases: ["thinking"],
@@ -404666,6 +405436,7 @@ registerUiCatalogFragment({
404666
405436
  //#endregion
404667
405437
  //#region src/tui/commands/resolve.ts
404668
405438
  const LEGACY_EFFORT_COMMANDS = new Set([
405439
+ "model",
404669
405440
  "automodel",
404670
405441
  "router"
404671
405442
  ]);
@@ -417702,168 +418473,6 @@ function segmentsFor(model) {
417702
418473
  if (availability === "unsupported") return ["off"];
417703
418474
  return ["off", "on"];
417704
418475
  }
417705
- function fredrikSelectableModels(models) {
417706
- return Object.fromEntries(Object.entries(models).filter(([alias]) => isAllowedFredrikRuntimeAlias(alias, models)));
417707
- }
417708
- function fredrikProviderDisplayName(provider) {
417709
- if (provider === "managed:blun") return PRODUCT_NAME;
417710
- if (provider.startsWith("managed:")) return provider.slice(8);
417711
- return provider;
417712
- }
417713
- function fredrikCreateModelChoices(models) {
417714
- return Object.entries(fredrikSelectableModels(models)).map(([alias, configured]) => {
417715
- const model = effectiveModelAlias(configured);
417716
- const name = modelDisplayName$1(alias, model);
417717
- const provider = fredrikProviderDisplayName(model.provider);
417718
- return {
417719
- alias,
417720
- model,
417721
- name,
417722
- provider,
417723
- label: `${name} (${provider})`
417724
- };
417725
- });
417726
- }
417727
- function fredrikEffortLabel(effort) {
417728
- const label = effortDisplayLabel(effort);
417729
- if (label !== effort || effort.length === 0) return label;
417730
- return effort.charAt(0).toUpperCase() + effort.slice(1);
417731
- }
417732
- function fredrikDefaultThinkingEffort(model) {
417733
- if (thinkingAvailability(model) === "unsupported") return "off";
417734
- const efforts = effortsOf(model);
417735
- if (efforts.length > 0) return model.defaultEffort ?? efforts[Math.floor(efforts.length / 2)];
417736
- return "on";
417737
- }
417738
- function fredrikCommitEffort(choice, draft) {
417739
- if (draft === "on") return fredrikDefaultThinkingEffort(choice.model);
417740
- return draft;
417741
- }
417742
- var FredrikModelSelectorComponent = class extends Container {
417743
- focused = false;
417744
- opts;
417745
- list;
417746
- thinkingOverrides = /* @__PURE__ */ new Map();
417747
- ignoreSubmitTailUntil = Date.now() + 250;
417748
- constructor(opts) {
417749
- super();
417750
- this.opts = opts;
417751
- const choices = fredrikCreateModelChoices(opts.models);
417752
- const selectedIndex = choices.findIndex((choice) => choice.alias === (opts.selectedValue ?? opts.currentValue));
417753
- this.list = new SearchableList({
417754
- items: choices,
417755
- toSearchText: (choice) => choice.label,
417756
- initialIndex: Math.max(selectedIndex, 0),
417757
- searchable: opts.searchable === true
417758
- });
417759
- }
417760
- draftFor(choice) {
417761
- const override = this.thinkingOverrides.get(choice.alias);
417762
- if (override !== void 0) return override;
417763
- if (choice.alias === this.opts.currentValue) return this.opts.currentThinkingEffort;
417764
- const efforts = effortsOf(choice.model);
417765
- if (efforts.length > 0) {
417766
- const fallback = choice.model.defaultEffort ?? efforts[Math.floor(efforts.length / 2)];
417767
- if (fallback !== void 0 && efforts.includes(fallback)) return fallback;
417768
- return efforts[0];
417769
- }
417770
- return thinkingAvailability(choice.model) !== "unsupported" ? "on" : "off";
417771
- }
417772
- effectiveEffort(choice) {
417773
- const draft = this.draftFor(choice);
417774
- const segments = segmentsFor(choice.model);
417775
- return segments.includes(draft) ? draft : segments[0];
417776
- }
417777
- handleInput(data) {
417778
- if (isKeyRelease(data)) return;
417779
- if (Date.now() <= this.ignoreSubmitTailUntil && /^[\r\n]+$/.test(data)) return;
417780
- this.ignoreSubmitTailUntil = 0;
417781
- if (matchesKey(data, Key.escape)) {
417782
- if (this.list.clearQuery()) return;
417783
- this.opts.onCancel();
417784
- return;
417785
- }
417786
- if (this.list.handleKey(data)) return;
417787
- if (matchesKey(data, Key.left) || matchesKey(data, Key.right)) {
417788
- const selected = this.selectedChoice();
417789
- if (selected !== void 0) {
417790
- const segments = segmentsFor(selected.model);
417791
- if (segments.length > 1) {
417792
- const current = this.effectiveEffort(selected);
417793
- const index = segments.indexOf(current);
417794
- const delta = matchesKey(data, Key.left) ? -1 : 1;
417795
- const next = Math.max(0, Math.min(segments.length - 1, index + delta));
417796
- if (next !== index) this.thinkingOverrides.set(selected.alias, segments[next]);
417797
- }
417798
- }
417799
- return;
417800
- }
417801
- if (matchesKey(data, Key.enter)) {
417802
- const selected = this.selectedChoice();
417803
- if (selected === void 0) return;
417804
- this.opts.onSelect({
417805
- alias: selected.alias,
417806
- thinking: fredrikCommitEffort(selected, this.effectiveEffort(selected))
417807
- });
417808
- return;
417809
- }
417810
- if (matchesKey(data, Key.alt("s")) && this.opts.onSessionOnlySelect !== void 0) {
417811
- const selected = this.selectedChoice();
417812
- if (selected === void 0) return;
417813
- this.opts.onSessionOnlySelect({
417814
- alias: selected.alias,
417815
- thinking: fredrikCommitEffort(selected, this.effectiveEffort(selected))
417816
- });
417817
- }
417818
- }
417819
- render(width) {
417820
- const view = this.list.view();
417821
- const totalCount = Object.keys(fredrikSelectableModels(this.opts.models)).length;
417822
- const titleSuffix = this.opts.searchable === true && view.query.length === 0 ? currentTheme.fg("textMuted", ` (${uiText("model.typeToSearch")})`) : "";
417823
- const lines = [
417824
- currentTheme.fg("primary", "-".repeat(width)),
417825
- currentTheme.boldFg("primary", ` ${uiText("model.title")}`) + titleSuffix,
417826
- currentTheme.fg("textMuted", ` ${uiText("model.navigate")} | ${uiText("model.thinking")} (Left/Right) | Enter ${uiText("model.select")} | Esc ${uiText("model.cancel")}`),
417827
- ""
417828
- ];
417829
- if (view.query.length > 0) lines.push(currentTheme.fg("primary", ` ${uiText("model.search")}: `) + currentTheme.fg("text", view.query));
417830
- if (view.items.length === 0) lines.push(currentTheme.fg("textMuted", ` ${uiText("model.noMatches")}`));
417831
- for (let index = view.page.start; index < view.page.end; index++) {
417832
- const choice = view.items[index];
417833
- if (choice === void 0) continue;
417834
- const selected = index === view.selectedIndex;
417835
- const current = choice.alias === this.opts.currentValue;
417836
- const pointer = selected ? ">" : " ";
417837
- let line = currentTheme.fg(selected ? "primary" : "textDim", ` ${pointer} `);
417838
- line += selected ? currentTheme.boldFg("primary", choice.name) : currentTheme.fg("text", choice.name);
417839
- line += " " + currentTheme.fg("textMuted", choice.provider);
417840
- if (current) line += " " + currentTheme.fg("success", currentMark());
417841
- lines.push(line);
417842
- }
417843
- if (view.query.length > 0) lines.push("", currentTheme.fg("textMuted", ` ${String(view.items.length)} / ${String(totalCount)}`));
417844
- lines.push("");
417845
- const selected = this.selectedChoice();
417846
- if (selected !== void 0) {
417847
- lines.push(currentTheme.fg("textMuted", ` ${uiText("model.thinking")} (Left/Right ${uiText("model.toSwitch")})`));
417848
- lines.push(this.renderThinkingControl(selected));
417849
- }
417850
- lines.push("", currentTheme.fg("primary", "-".repeat(width)));
417851
- return lines.map((line) => truncateToWidth(line, width));
417852
- }
417853
- selectedChoice() {
417854
- return this.list.selected();
417855
- }
417856
- renderThinkingControl(choice) {
417857
- const segment = (label, active) => active ? currentTheme.boldFg("primary", `[ ${label} ]`) : currentTheme.fg("text", ` ${label} `);
417858
- const unavailable = (label) => currentTheme.fg("textMuted", ` ${label} (${uiText("model.unsupported")}) `);
417859
- const efforts = effortsOf(choice.model);
417860
- const availability = thinkingAvailability(choice.model);
417861
- if (efforts.length === 0 && availability === "always-on") return ` ${segment(uiText("model.on"), true)} ${unavailable(uiText("model.off"))}`;
417862
- if (efforts.length === 0 && availability === "unsupported") return ` ${unavailable(uiText("model.on"))} ${segment(uiText("model.off"), true)}`;
417863
- const active = this.effectiveEffort(choice);
417864
- return ` ${segmentsFor(choice.model).map((effort) => segment(fredrikEffortLabel(effort), effort === active)).join(" ")}`;
417865
- }
417866
- };
417867
418476
  //#endregion
417868
418477
  //#region src/tui/components/dialogs/permission-selector.ts
417869
418478
  function permissionOptions() {
@@ -421669,47 +422278,6 @@ async function handleThemeCommand(host, args) {
421669
422278
  }
421670
422279
  await applyThemeChoice(host, theme);
421671
422280
  }
421672
- function resolveFredrikModelArgument(models, raw) {
421673
- const query = raw.trim().toLowerCase();
421674
- if (query.length === 0) return void 0;
421675
- return Object.entries(models).filter(([alias]) => isAllowedFredrikRuntimeAlias(alias, models)).find(([alias, model]) => [alias, model.model, model.displayName].filter((value) => typeof value === "string").some((value) => value.toLowerCase() === query))?.[0];
421676
- }
421677
- function showFredrikModelPicker(host, selectedValue = host.state.appState.model) {
421678
- const models = fredrikSelectableModels(host.state.appState.availableModels);
421679
- host.mountEditorReplacement(new FredrikModelSelectorComponent({
421680
- models,
421681
- currentValue: host.state.appState.model,
421682
- selectedValue,
421683
- currentThinkingEffort: host.state.appState.thinkingEffort,
421684
- searchable: true,
421685
- onSelect: (selection) => {
421686
- host.restoreEditorAfter(() => performModelSwitch(host, selection.alias, selection.thinking, false));
421687
- },
421688
- onSessionOnlySelect: (selection) => {
421689
- host.restoreEditorAfter(() => performModelSwitch(host, selection.alias, selection.thinking, false));
421690
- },
421691
- onCancel: () => {
421692
- host.restoreEditor();
421693
- }
421694
- }));
421695
- }
421696
- async function handleModelCommand(host, args) {
421697
- if (host.session === void 0) {
421698
- host.showError(noActiveSessionMessage());
421699
- return;
421700
- }
421701
- const raw = args.trim();
421702
- if (raw.length === 0) {
421703
- showFredrikModelPicker(host);
421704
- return;
421705
- }
421706
- const alias = resolveFredrikModelArgument(host.state.appState.availableModels, raw);
421707
- if (alias === void 0) {
421708
- host.showError(uiText("config.model.unknownAlias", { alias: raw }));
421709
- return;
421710
- }
421711
- showFredrikModelPicker(host, alias);
421712
- }
421713
422281
  async function handleEffortCommand(host, args) {
421714
422282
  const alias = host.state.appState.model;
421715
422283
  const model = host.state.appState.availableModels[alias];
@@ -421741,7 +422309,7 @@ async function handleEffortCommand(host, args) {
421741
422309
  }));
421742
422310
  return;
421743
422311
  }
421744
- await performEffortSelection(host, alias, arg, !isConfiguredFredrikGlmAlias(alias, model));
422312
+ await performEffortSelection(host, alias, arg, true);
421745
422313
  }
421746
422314
  function showEffortPicker(host, model, segments) {
421747
422315
  const liveEffort = host.state.appState.thinkingEffort;
@@ -421752,7 +422320,7 @@ function showEffortPicker(host, model, segments) {
421752
422320
  currentValue,
421753
422321
  currentBlunSwarm: host.state.appState.swarmMode && host.state.appState.swarmModeEntry === "effort",
421754
422322
  onSelect: (effort) => {
421755
- host.restoreEditorAfter(() => performEffortSelection(host, alias, effort, !isConfiguredFredrikGlmAlias(alias, host.state.appState.availableModels[alias])));
422323
+ host.restoreEditorAfter(() => performEffortSelection(host, alias, effort, true));
421756
422324
  },
421757
422325
  onSessionOnlySelect: (effort) => {
421758
422326
  host.restoreEditorAfter(() => performEffortSelection(host, alias, effort, false));
@@ -432550,6 +433118,11 @@ function agentSwarmResultSummaryFromOutput(output) {
432550
433118
  };
432551
433119
  }
432552
433120
  function parseAgentSwarmResultStatuses(output) {
433121
+ const structured = parseStructuredSwarmDisplay(output);
433122
+ if (structured.recognized) return structured.statuses.map((entry) => ({
433123
+ ...entry,
433124
+ status: entry.status === "aborted" ? "cancelled" : entry.status
433125
+ }));
432553
433126
  const xmlStatuses = parseAgentSwarmXmlResultStatuses(output);
432554
433127
  if (xmlStatuses.length > 0) return xmlStatuses;
432555
433128
  return parseAgentSwarmLegacyResultStatuses(output);
@@ -497454,9 +498027,6 @@ async function handleBuiltInSlashCommand(host, name, args) {
497454
498027
  case "theme":
497455
498028
  await handleThemeCommand(host, args);
497456
498029
  return;
497457
- case "model":
497458
- await handleModelCommand(host, args);
497459
- return;
497460
498030
  case "effort":
497461
498031
  await handleEffortCommand(host, args);
497462
498032
  return;
@@ -499539,9 +500109,11 @@ registerUiCatalogFragment({
499539
500109
  "approval.search.scope": "scope: {scope}",
499540
500110
  "approval.backgroundTask": "{status} {kind} task {taskId}: {description}",
499541
500111
  "approval.hint.feedback": "Type feedback · ↵ submit.",
500112
+ "approval.hint.editArguments": "Enter the complete replacement JSON object · ↵ submit.",
499542
500113
  "approval.hint.main": "↑/↓ select · {numbers} choose · ↵ confirm{preview}",
499543
500114
  "approval.hint.preview": " · ctrl+e preview",
499544
500115
  "approval.choice.approveOnce": "Approve once",
500116
+ "approval.choice.editArguments": "Edit arguments (JSON)",
499545
500117
  "approval.choice.approveSession": "Approve for this session",
499546
500118
  "approval.choice.reject": "Reject",
499547
500119
  "approval.choice.rejectFeedback": "Reject with feedback",
@@ -499551,6 +500123,7 @@ registerUiCatalogFragment({
499551
500123
  "approval.transcript.approvedSession": "Approved for session",
499552
500124
  "approval.transcript.rejected": "Rejected",
499553
500125
  "approval.transcript.cancelled": "Cancelled",
500126
+ "approval.transcript.edited": "Arguments edited",
499554
500127
  "approval.transcript.action": "{decision}: {action}",
499555
500128
  "approval.transcript.actionWithFeedback": "{decision}: {action} — \"{feedback}\""
499556
500129
  },
@@ -499570,9 +500143,11 @@ registerUiCatalogFragment({
499570
500143
  "approval.search.scope": "Bereich: {scope}",
499571
500144
  "approval.backgroundTask": "Aufgabe {taskId} ({status}, {kind}): {description}",
499572
500145
  "approval.hint.feedback": "Feedback eingeben · ↵ absenden.",
500146
+ "approval.hint.editArguments": "Vollständiges Ersatz-JSON-Objekt eingeben · ↵ absenden.",
499573
500147
  "approval.hint.main": "↑/↓ auswählen · {numbers} wählen · ↵ bestätigen{preview}",
499574
500148
  "approval.hint.preview": " · ctrl+e Vorschau",
499575
500149
  "approval.choice.approveOnce": "Einmal genehmigen",
500150
+ "approval.choice.editArguments": "Argumente bearbeiten (JSON)",
499576
500151
  "approval.choice.approveSession": "Für diese Sitzung genehmigen",
499577
500152
  "approval.choice.reject": "Ablehnen",
499578
500153
  "approval.choice.rejectFeedback": "Ablehnen und Feedback geben",
@@ -499582,6 +500157,7 @@ registerUiCatalogFragment({
499582
500157
  "approval.transcript.approvedSession": "Für diese Sitzung genehmigt",
499583
500158
  "approval.transcript.rejected": "Abgelehnt",
499584
500159
  "approval.transcript.cancelled": "Abgebrochen",
500160
+ "approval.transcript.edited": "Argumente bearbeitet",
499585
500161
  "approval.transcript.action": "{decision}: {action}",
499586
500162
  "approval.transcript.actionWithFeedback": "{decision}: {action} – „{feedback}“"
499587
500163
  },
@@ -499601,9 +500177,11 @@ registerUiCatalogFragment({
499601
500177
  "approval.search.scope": "Ámbito: {scope}",
499602
500178
  "approval.backgroundTask": "Tarea {taskId} ({status}, {kind}): {description}",
499603
500179
  "approval.hint.feedback": "Escribe tus comentarios · ↵ enviar.",
500180
+ "approval.hint.editArguments": "Introduce el objeto JSON completo de sustitución · ↵ enviar.",
499604
500181
  "approval.hint.main": "↑/↓ seleccionar · {numbers} elegir · ↵ confirmar{preview}",
499605
500182
  "approval.hint.preview": " · ctrl+e vista previa",
499606
500183
  "approval.choice.approveOnce": "Aprobar una vez",
500184
+ "approval.choice.editArguments": "Editar argumentos (JSON)",
499607
500185
  "approval.choice.approveSession": "Aprobar durante esta sesión",
499608
500186
  "approval.choice.reject": "Rechazar",
499609
500187
  "approval.choice.rejectFeedback": "Rechazar y enviar comentarios",
@@ -499613,6 +500191,7 @@ registerUiCatalogFragment({
499613
500191
  "approval.transcript.approvedSession": "Aprobado durante esta sesión",
499614
500192
  "approval.transcript.rejected": "Rechazado",
499615
500193
  "approval.transcript.cancelled": "Cancelado",
500194
+ "approval.transcript.edited": "Argumentos modificados",
499616
500195
  "approval.transcript.action": "{decision}: {action}",
499617
500196
  "approval.transcript.actionWithFeedback": "{decision}: {action} — «{feedback}»"
499618
500197
  },
@@ -499632,9 +500211,11 @@ registerUiCatalogFragment({
499632
500211
  "approval.search.scope": "Portée : {scope}",
499633
500212
  "approval.backgroundTask": "Tâche {taskId} ({status}, {kind}) : {description}",
499634
500213
  "approval.hint.feedback": "Saisissez un commentaire · ↵ envoyer.",
500214
+ "approval.hint.editArguments": "Saisissez l’objet JSON de remplacement complet · ↵ envoyer.",
499635
500215
  "approval.hint.main": "↑/↓ sélectionner · {numbers} choisir · ↵ confirmer{preview}",
499636
500216
  "approval.hint.preview": " · ctrl+e aperçu",
499637
500217
  "approval.choice.approveOnce": "Approuver une fois",
500218
+ "approval.choice.editArguments": "Modifier les arguments (JSON)",
499638
500219
  "approval.choice.approveSession": "Approuver pour cette session",
499639
500220
  "approval.choice.reject": "Refuser",
499640
500221
  "approval.choice.rejectFeedback": "Refuser et ajouter un commentaire",
@@ -499644,6 +500225,7 @@ registerUiCatalogFragment({
499644
500225
  "approval.transcript.approvedSession": "Approuvé pour cette session",
499645
500226
  "approval.transcript.rejected": "Refusé",
499646
500227
  "approval.transcript.cancelled": "Annulé",
500228
+ "approval.transcript.edited": "Arguments modifiés",
499647
500229
  "approval.transcript.action": "{decision} : {action}",
499648
500230
  "approval.transcript.actionWithFeedback": "{decision} : {action} — « {feedback} »"
499649
500231
  },
@@ -499663,9 +500245,11 @@ registerUiCatalogFragment({
499663
500245
  "approval.search.scope": "Omfattning: {scope}",
499664
500246
  "approval.backgroundTask": "Uppgift {taskId} ({status}, {kind}): {description}",
499665
500247
  "approval.hint.feedback": "Skriv återkoppling · ↵ skicka.",
500248
+ "approval.hint.editArguments": "Ange hela JSON-objektet som ska ersätta det befintliga · ↵ skicka.",
499666
500249
  "approval.hint.main": "↑/↓ markera · {numbers} välj · ↵ bekräfta{preview}",
499667
500250
  "approval.hint.preview": " · ctrl+e förhandsgranska",
499668
500251
  "approval.choice.approveOnce": "Godkänn en gång",
500252
+ "approval.choice.editArguments": "Redigera argument (JSON)",
499669
500253
  "approval.choice.approveSession": "Godkänn för den här sessionen",
499670
500254
  "approval.choice.reject": "Avvisa",
499671
500255
  "approval.choice.rejectFeedback": "Avvisa och lämna återkoppling",
@@ -499675,6 +500259,7 @@ registerUiCatalogFragment({
499675
500259
  "approval.transcript.approvedSession": "Godkänt för den här sessionen",
499676
500260
  "approval.transcript.rejected": "Avvisat",
499677
500261
  "approval.transcript.cancelled": "Avbrutet",
500262
+ "approval.transcript.edited": "Argument redigerade",
499678
500263
  "approval.transcript.action": "{decision}: {action}",
499679
500264
  "approval.transcript.actionWithFeedback": "{decision}: {action} – ”{feedback}”"
499680
500265
  },
@@ -499858,7 +500443,7 @@ var ApprovalPanelComponent = class extends Container {
499858
500443
  if (!option) return;
499859
500444
  this.onResponse({
499860
500445
  response: option.response,
499861
- feedback: feedback || void 0,
500446
+ ...(option.input_kind === "edited_tool_input_json" ? { edited_tool_input_json: feedback } : { feedback: feedback || void 0 }),
499862
500447
  selected_label: option.selected_label
499863
500448
  });
499864
500449
  }
@@ -499868,6 +500453,7 @@ var ApprovalPanelComponent = class extends Container {
499868
500453
  if (option.requires_feedback === true) {
499869
500454
  this.selectedIndex = index;
499870
500455
  this.feedbackMode = true;
500456
+ if (option.input_kind === "edited_tool_input_json") this.feedbackInput.setValue(this.request.data.editable_tool_input_json ?? "{}");
499871
500457
  } else this.submit(index);
499872
500458
  }
499873
500459
  handleInput(data) {
@@ -499964,7 +500550,7 @@ var ApprovalPanelComponent = class extends Container {
499964
500550
  if (option.description !== void 0 && option.description.length > 0 && !(this.feedbackMode && option.requires_feedback === true && isSelected)) for (const descLine of wrapTextWithAnsi(option.description, Math.max(20, width - 7))) lines.push(indent(` ${dim(descLine)}`));
499965
500551
  }
499966
500552
  lines.push("");
499967
- if (this.feedbackMode) lines.push(indent(dim(uiText("approval.hint.feedback"))));
500553
+ if (this.feedbackMode) lines.push(indent(dim(uiText(this.choiceAt(this.selectedIndex)?.input_kind === "edited_tool_input_json" ? "approval.hint.editArguments" : "approval.hint.feedback"))));
499968
500554
  else {
499969
500555
  const expandHint = hasPreviewable ? uiText("approval.hint.preview") : "";
499970
500556
  lines.push(indent(dim(uiText("approval.hint.main", {
@@ -503221,12 +503807,18 @@ async function refreshAllProviderModels(host, options = {}) {
503221
503807
  }
503222
503808
  //#endregion
503223
503809
  //#region src/tui/reverse-rpc/approval/adapter.ts
503224
- function defaultApprovalChoices() {
503810
+ function defaultApprovalChoices(allowEdit = false) {
503225
503811
  return [
503226
503812
  {
503227
503813
  label: uiText("approval.choice.approveOnce"),
503228
503814
  response: "approved"
503229
503815
  },
503816
+ ...allowEdit ? [{
503817
+ label: uiText("approval.choice.editArguments"),
503818
+ response: "edited",
503819
+ requires_feedback: true,
503820
+ input_kind: "edited_tool_input_json"
503821
+ }] : [],
503230
503822
  {
503231
503823
  label: uiText("approval.choice.approveSession"),
503232
503824
  response: "approved_for_session"
@@ -503263,7 +503855,8 @@ function adaptApprovalRequest(event) {
503263
503855
  action: resolved.action ?? event.action,
503264
503856
  description: resolved.description,
503265
503857
  display: resolved.blocks,
503266
- choices: adaptChoices(event.toolName, event.display)
503858
+ choices: adaptChoices(event.toolName, event.display, event.allowEdit === true),
503859
+ editable_tool_input_json: event.allowEdit === true ? canonicalEditedToolInputJson(event.editableToolInput) : void 0
503267
503860
  };
503268
503861
  }
503269
503862
  function resolveDisplay(toolName, display, action) {
@@ -503367,6 +503960,10 @@ function inferFileOp(toolName) {
503367
503960
  return "read";
503368
503961
  }
503369
503962
  function adaptPanelResponse(response) {
503963
+ if (response.response === "edited") return {
503964
+ decision: "edited",
503965
+ edited_tool_input_json: response.edited_tool_input_json
503966
+ };
503370
503967
  if (response.response === "approved_for_session") return {
503371
503968
  decision: "approved",
503372
503969
  scope: "session",
@@ -503530,10 +504127,10 @@ function adaptDisplay(display) {
503530
504127
  default: return [];
503531
504128
  }
503532
504129
  }
503533
- function adaptChoices(toolName, display) {
504130
+ function adaptChoices(toolName, display, allowEdit = false) {
503534
504131
  if (toolName === "ExitPlanMode" || display.kind === "plan_review") return adaptPlanReviewChoices(display);
503535
504132
  if (display.kind === "goal_start") return adaptGoalStartChoices(display);
503536
- return defaultApprovalChoices();
504133
+ return defaultApprovalChoices(allowEdit);
503537
504134
  }
503538
504135
  function adaptGoalStartChoices(display) {
503539
504136
  return goalStartOptions(display.mode).map((option) => option.value === "cancel" ? {
@@ -503629,7 +504226,7 @@ function createApprovalRequestHandler(controller, onResponse, options = {}) {
503629
504226
  }).catch(() => {});
503630
504227
  }
503631
504228
  const response = await pending;
503632
- relay?.complete(response);
504229
+ relay?.complete(response.decision === "edited" ? { decision: "edited" } : response);
503633
504230
  onResponse?.(event, response);
503634
504231
  return response;
503635
504232
  } catch {
@@ -503676,10 +504273,7 @@ function applyManagedAccountContext(models, maxContextTokens) {
503676
504273
  maxContextSize: maxContextTokens
503677
504274
  } }
503678
504275
  };
503679
- return {
503680
- [BLUN_KING_MODEL_ALIAS]: king,
503681
- ...configuredFredrikGlmModels(models)
503682
- };
504276
+ return { [BLUN_KING_MODEL_ALIAS]: king };
503683
504277
  }
503684
504278
  function normalizeKingProductEffort(value) {
503685
504279
  if (value === "none" || value === "minimal" || value === "off") return "low";
@@ -503735,11 +504329,7 @@ function nextManagedQuotaWarning(windows, highestShown) {
503735
504329
  //#region src/tui/controllers/auth-flow.ts
503736
504330
  function managedProviderOnly(providers) {
503737
504331
  const managed = providers[DEFAULT_OAUTH_PROVIDER_NAME];
503738
- const fredrikGlm = configuredFredrikGlmProvider(providers);
503739
- return {
503740
- ...managed === void 0 ? {} : { [DEFAULT_OAUTH_PROVIDER_NAME]: managed },
503741
- ...fredrikGlm === void 0 ? {} : { [FREDRIK_GLM_PROVIDER_ID]: fredrikGlm }
503742
- };
504332
+ return managed === void 0 ? {} : { [DEFAULT_OAUTH_PROVIDER_NAME]: managed };
503743
504333
  }
503744
504334
  var AuthFlowController = class {
503745
504335
  host;
@@ -518668,6 +519258,10 @@ var BlunTUI = class {
518668
519258
  const sessionId = session.id;
518669
519259
  const autostartPrompt = autostart.observation === void 0 ? GOAL_CONTINUATION_PROMPT : `${GOAL_CONTINUATION_PROMPT}\n\n${autostart.observation}`;
518670
519260
  this.beginSessionRequest();
519261
+ this.setAppState({
519262
+ model: BLUN_KING_MODEL_ALIAS,
519263
+ modelFallbackAllowed: false
519264
+ });
518671
519265
  try {
518672
519266
  const result = await session.promptAccepted(autostartPrompt);
518673
519267
  if (!result.accepted && this.session?.id === sessionId) {
@@ -519704,6 +520298,10 @@ var BlunTUI = class {
519704
520298
  contextOnly: false
519705
520299
  };
519706
520300
  this.pendingChannelReplyGuard = installedGuard;
520301
+ this.setAppState({
520302
+ model: BLUN_KING_MODEL_ALIAS,
520303
+ modelFallbackAllowed: false
520304
+ });
519707
520305
  session.promptAccepted(options?.parts ?? input).then((result) => {
519708
520306
  if (result.duplicate === true) {
519709
520307
  this.traceTelegramDelivery?.({ stage: "committed", ...context.item.channelDeliveryTrace, route: "channel_command_prompt", reason: "duplicate" });
@@ -519767,6 +520365,10 @@ var BlunTUI = class {
519767
520365
  type: "text",
519768
520366
  text: focusedModelInput
519769
520367
  }, imagePart] : focusedModelInput;
520368
+ this.setAppState({
520369
+ model: BLUN_KING_MODEL_ALIAS,
520370
+ modelFallbackAllowed: false
520371
+ });
519770
520372
  session.promptAccepted(promptInput, channelPromptOrigin(channelReportSources)).then((result) => {
519771
520373
  if (result.duplicate === true) {
519772
520374
  this.traceTelegramDelivery?.({ stage: "committed", ...channelDeliveryTrace, route: "prompt", reason: "duplicate" });
@@ -519961,6 +520563,10 @@ var BlunTUI = class {
519961
520563
  return;
519962
520564
  }
519963
520565
  this.beginSessionRequest();
520566
+ this.setAppState({
520567
+ model: BLUN_KING_MODEL_ALIAS,
520568
+ modelFallbackAllowed: false
520569
+ });
519964
520570
  session.promptAccepted(TRUNCATED_REPLY_CONTINUATION_PROMPT).then((result) => {
519965
520571
  if (!result.accepted) this.failTruncatedChannelReplyRecovery(new Error("continuation prompt rejected"));
519966
520572
  }).catch((error) => {
@@ -520231,6 +520837,10 @@ var BlunTUI = class {
520231
520837
  });
520232
520838
  this.beginSessionRequest();
520233
520839
  const sdkInput = options?.parts ?? input;
520840
+ this.setAppState({
520841
+ model: BLUN_KING_MODEL_ALIAS,
520842
+ modelFallbackAllowed: false
520843
+ });
520234
520844
  session.promptAccepted(sdkInput).catch((error) => {
520235
520845
  finishPersonalMemoryRememberIntentTurn(session.id);
520236
520846
  const message = formatErrorMessage$2(error);
@@ -520345,19 +520955,18 @@ var BlunTUI = class {
520345
520955
  }
520346
520956
  }
520347
520957
  setAppState(patch) {
520348
- const managedAccountContextTokens = "managedAccountContextTokens" in patch ? patch.managedAccountContextTokens : this.state.appState.managedAccountContextTokens;
520349
- const availableModels = applyManagedAccountContext(patch.availableModels ?? this.state.appState.availableModels, isValidManagedContextTokens(managedAccountContextTokens) ? managedAccountContextTokens : void 0);
520350
- const allowedModel = (candidate) => typeof candidate === "string" && isAllowedFredrikRuntimeAlias(candidate, availableModels) ? candidate : BLUN_KING_MODEL_ALIAS;
520351
520958
  let effectivePatch = {
520352
520959
  ...patch,
520353
520960
  modelFallbackAllowed: false,
520354
- ..."model" in patch && patch.model?.trim().length ? { model: allowedModel(patch.model) } : {},
520355
- ..."activeResponderModel" in patch && patch.activeResponderModel != null ? { activeResponderModel: allowedModel(patch.activeResponderModel) } : {}
520961
+ ..."model" in patch && patch.model?.trim().length ? { model: BLUN_KING_MODEL_ALIAS } : {},
520962
+ ..."activeResponderModel" in patch && patch.activeResponderModel != null ? { activeResponderModel: BLUN_KING_MODEL_ALIAS } : {}
520356
520963
  };
520357
520964
  if ("availableModels" in patch || "managedAccountContextTokens" in patch) {
520358
- if (availableModels !== patch.availableModels) effectivePatch = {
520965
+ const managedAccountContextTokens = "managedAccountContextTokens" in patch ? patch.managedAccountContextTokens : this.state.appState.managedAccountContextTokens;
520966
+ const effectiveModels = applyManagedAccountContext(patch.availableModels ?? this.state.appState.availableModels, isValidManagedContextTokens(managedAccountContextTokens) ? managedAccountContextTokens : void 0);
520967
+ if (effectiveModels !== patch.availableModels) effectivePatch = {
520359
520968
  ...effectivePatch,
520360
- availableModels
520969
+ availableModels: effectiveModels
520361
520970
  };
520362
520971
  }
520363
520972
  if (!hasPatchChanges(this.state.appState, effectivePatch)) return;
@@ -520434,11 +521043,7 @@ var BlunTUI = class {
520434
521043
  return this.harness.createSession(options);
520435
521044
  }
520436
521045
  async setSession(session, options = {}) {
520437
- const resumedStatus = await session.getStatus();
520438
- if (!isAllowedFredrikRuntimeAlias(resumedStatus.model ?? BLUN_KING_MODEL_ALIAS, this.state.appState.availableModels)) {
520439
- await session.setModel(BLUN_KING_MODEL_ALIAS, { allowFallback: false });
520440
- this.showStatus(uiText("config.model.unknownAlias", { alias: resumedStatus.model ?? "" }), "warning");
520441
- }
521046
+ await session.setModel(BLUN_KING_MODEL_ALIAS, { allowFallback: false });
520442
521047
  await this.personalMemoryController.clear(this.session);
520443
521048
  const previous = this.unloadCurrentSession(approvalCancellationFeedback("switching_session"));
520444
521049
  await this.managedQuotaWarningPersistence;
@@ -520446,7 +521051,10 @@ var BlunTUI = class {
520446
521051
  resetChannelPreambleState(this.channelPreamble);
520447
521052
  this.session = session;
520448
521053
  this.managedQuotaWarningController.restore(session.id, managedQuotaWarningThresholdFromMetadata(session.getResumeState()?.sessionMetadata?.custom));
520449
- this.setAppState({ modelFallbackAllowed: false });
521054
+ this.setAppState({
521055
+ model: BLUN_KING_MODEL_ALIAS,
521056
+ modelFallbackAllowed: false
521057
+ });
520450
521058
  this.harness.setTelemetryContext({ sessionId: session.id });
520451
521059
  this.registerSessionHandlers(session);
520452
521060
  this.syncAdditionalDirs(session);
@@ -520458,7 +521066,7 @@ var BlunTUI = class {
520458
521066
  const [status, goalResult, loopResult] = await Promise.all([session.getStatus(), session.getGoal(), session.getLoop()]);
520459
521067
  this.setAppState({
520460
521068
  sessionId: session.id,
520461
- model: status.model ?? BLUN_KING_MODEL_ALIAS,
521069
+ model: BLUN_KING_MODEL_ALIAS,
520462
521070
  modelFallbackAllowed: false,
520463
521071
  activeResponderModel: null,
520464
521072
  thinkingEffort: status.thinkingEffort,
@@ -520678,6 +521286,7 @@ var BlunTUI = class {
520678
521286
  this.approvalController.cancelAll(approvalCancellationFeedback("reloading_session"));
520679
521287
  this.questionController.cancelAll("");
520680
521288
  this.resetSessionRuntime();
521289
+ await session.setModel(BLUN_KING_MODEL_ALIAS, { allowFallback: false });
520681
521290
  this.session = session;
520682
521291
  this.harness.setTelemetryContext({ sessionId: session.id });
520683
521292
  this.registerSessionHandlers(session);
@@ -520815,6 +521424,9 @@ var BlunTUI = class {
520815
521424
  case "cancelled":
520816
521425
  decision = uiText("approval.transcript.cancelled");
520817
521426
  break;
521427
+ case "edited":
521428
+ decision = uiText("approval.transcript.edited");
521429
+ break;
520818
521430
  }
520819
521431
  const content = response.feedback !== void 0 && response.feedback.length > 0 ? uiText("approval.transcript.actionWithFeedback", {
520820
521432
  decision,