orkestrator 2.31.0-beta → 2.32.0-beta

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orkestrator",
3
- "version": "2.31.0-beta",
3
+ "version": "2.32.0-beta",
4
4
  "description": "Run the Orkestrator backend service without the desktop application",
5
5
  "homepage": "https://orkestrator.dev",
6
6
  "repository": {
@@ -39,8 +39,8 @@
39
39
  "sharp": "0.35.5"
40
40
  },
41
41
  "devDependencies": {
42
- "@orkestrator/protocol": "2.31.0-beta",
43
- "@orkestrator/toolchain": "2.31.0-beta"
42
+ "@orkestrator/protocol": "2.32.0-beta",
43
+ "@orkestrator/toolchain": "2.32.0-beta"
44
44
  },
45
45
  "engines": {
46
46
  "bun": ">=1.4.4"
@@ -2529,6 +2529,10 @@ function claudeHome() {
2529
2529
  function claudeJsonPath() {
2530
2530
  return join(claudeHome(), ".claude.json");
2531
2531
  }
2532
+ function claudeUserSettingsPath() {
2533
+ const configDir = overrideHome === null ? process.env.CLAUDE_CONFIG_DIR?.trim() : undefined;
2534
+ return join(configDir || join(claudeHome(), ".claude"), "settings.json");
2535
+ }
2532
2536
  function claudePluginsDir() {
2533
2537
  return join(claudeHome(), ".claude", "plugins");
2534
2538
  }
@@ -2556,7 +2560,8 @@ function parseTurnInFlightMark(value) {
2556
2560
  return {
2557
2561
  bridgeInstanceId: record.bridgeInstanceId,
2558
2562
  pid: record.pid,
2559
- startedAt: record.startedAt
2563
+ startedAt: record.startedAt,
2564
+ ...typeof record.requestId === "string" && record.requestId.length > 0 && record.requestId.length <= 200 ? { requestId: record.requestId } : {}
2560
2565
  };
2561
2566
  }
2562
2567
  var MAX_SHELL_TASK_DETAILS = 256;
@@ -3799,7 +3804,7 @@ function remapInstalledPlugins(pluginsDir, installedPlugins, onUnsafe) {
3799
3804
  const pluginsRoot = path.resolve(pluginsDir);
3800
3805
  if (!isRecord(installedPlugins.plugins))
3801
3806
  return plugins;
3802
- for (const entries of Object.values(installedPlugins.plugins)) {
3807
+ for (const [installedId, entries] of Object.entries(installedPlugins.plugins)) {
3803
3808
  if (!Array.isArray(entries))
3804
3809
  continue;
3805
3810
  for (const entry of entries) {
@@ -3819,7 +3824,7 @@ function remapInstalledPlugins(pluginsDir, installedPlugins, onUnsafe) {
3819
3824
  } else {
3820
3825
  resolvedPath = installPath;
3821
3826
  }
3822
- plugins.push({ type: "local", path: resolvedPath });
3827
+ plugins.push({ type: "local", path: resolvedPath, installedId });
3823
3828
  }
3824
3829
  }
3825
3830
  return plugins;
@@ -3851,6 +3856,26 @@ function mergeClaudePluginLayers(layers, options) {
3851
3856
  return paths;
3852
3857
  }
3853
3858
  var INVALID_PLUGIN_NAME = new RegExp("[@:\\s/\\\\\\u0000-\\u001f\\u007f\\u200b-\\u200f\\u2028-\\u202e\\u2060-\\u2064\\ufeff]");
3859
+ var CLAUDE_PLUGIN_SETTING_SOURCES = ["local", "project", "user"];
3860
+ function claudeInstalledPluginIdEnablement(id, settings, loadedSources) {
3861
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3862
+ for (const source of ["local", "project", "user"]) {
3863
+ if (!loadedSources.includes(source))
3864
+ continue;
3865
+ const document = settings[source];
3866
+ const enabledPlugins = isRecord(document) ? document.enabledPlugins : undefined;
3867
+ if (!isRecord(enabledPlugins) || !Object.hasOwn(enabledPlugins, id))
3868
+ continue;
3869
+ return { enabled: enabledPlugins[id] === true, decidedBy: { source, key: id } };
3870
+ }
3871
+ return { enabled: false };
3872
+ }
3873
+ function enabledInstalledPlugins(plugins, settings, loadedSources) {
3874
+ return plugins.filter((plugin) => plugin.installedId === undefined || claudeInstalledPluginIdEnablement(plugin.installedId, settings, loadedSources).enabled);
3875
+ }
3876
+ function claudePluginSettingSources(settingSources) {
3877
+ return CLAUDE_PLUGIN_SETTING_SOURCES.filter((source) => settingSources.includes(source));
3878
+ }
3854
3879
 
3855
3880
  // ../../bridges/claude-bridge/src/services/json-file-cache.ts
3856
3881
  import { createHash as createHash4 } from "node:crypto";
@@ -3994,6 +4019,23 @@ async function loadCliInstalledPlugins() {
3994
4019
  }
3995
4020
  return remapInstalledPlugins2(pluginsDir, { plugins });
3996
4021
  }
4022
+ function pluginSettingsPath(source, cwd) {
4023
+ switch (source) {
4024
+ case "user":
4025
+ return claudeUserSettingsPath();
4026
+ case "project":
4027
+ return join3(cwd, ".claude", "settings.json");
4028
+ case "local":
4029
+ return join3(cwd, ".claude", "settings.local.json");
4030
+ }
4031
+ }
4032
+ async function loadPluginSettings(cwd, sources) {
4033
+ const entries = await Promise.all(sources.map(async (source) => {
4034
+ const enabledPlugins = await readJsonSliceCached(pluginSettingsPath(source, cwd), "enabledPlugins", (config) => config?.enabledPlugins ?? null);
4035
+ return [source, enabledPlugins === null ? undefined : { enabledPlugins }];
4036
+ }));
4037
+ return Object.fromEntries(entries);
4038
+ }
3997
4039
  function remapInstalledPlugins2(pluginsDir, installedPlugins) {
3998
4040
  return remapInstalledPlugins(pluginsDir, installedPlugins, (installPath) => console.warn(`[plugin-config] Skipping plugin with unsafe install path: "${installPath}"`));
3999
4041
  }
@@ -4016,17 +4058,27 @@ async function readPluginManifest(pluginPath) {
4016
4058
  function resolvePath(pluginPath, cwd) {
4017
4059
  return resolveClaudePluginPath(pluginPath, cwd, claudeHome());
4018
4060
  }
4019
- async function getMergedPlugins(cwd, includeProjectSources = true) {
4020
- const [global2, cliInstalled, projectGlobal, projectLocal] = await Promise.all([
4061
+ function defaultSettingSources(includeProjectSources) {
4062
+ return includeProjectSources ? ["user", "project"] : ["user"];
4063
+ }
4064
+ async function getMergedPlugins(cwd, includeProjectSources = true, settingSources = defaultSettingSources(includeProjectSources)) {
4065
+ const sources = claudePluginSettingSources(settingSources);
4066
+ const [global2, cliInstalled, projectGlobal, projectLocal, settings] = await Promise.all([
4021
4067
  loadGlobalPlugins(),
4022
4068
  loadCliInstalledPlugins(),
4023
4069
  includeProjectSources ? loadProjectOverridesFromGlobal(cwd) : [],
4024
- includeProjectSources ? loadProjectPlugins(cwd) : []
4070
+ includeProjectSources ? loadProjectPlugins(cwd) : [],
4071
+ loadPluginSettings(cwd, sources)
4025
4072
  ]);
4026
- return mergeClaudePluginLayers({ global: global2, cliInstalled, projectGlobal, projectLocal }, { cwd, home: claudeHome(), includeProjectSources }).map((path) => ({ type: "local", path }));
4027
- }
4028
- async function getPluginsForSdk(cwd, includeProjectSources = true) {
4029
- const configs = await getMergedPlugins(cwd, includeProjectSources);
4073
+ return mergeClaudePluginLayers({
4074
+ global: global2,
4075
+ cliInstalled: enabledInstalledPlugins(cliInstalled, settings, sources),
4076
+ projectGlobal,
4077
+ projectLocal
4078
+ }, { cwd, home: claudeHome(), includeProjectSources }).map((path) => ({ type: "local", path }));
4079
+ }
4080
+ async function getPluginsForSdk(cwd, includeProjectSources = true, settingSources = defaultSettingSources(includeProjectSources)) {
4081
+ const configs = await getMergedPlugins(cwd, includeProjectSources, settingSources);
4030
4082
  const validPlugins = [];
4031
4083
  for (const config of configs) {
4032
4084
  if (await pathExists(config.path)) {
@@ -4737,7 +4789,7 @@ function claudeReadOnlyAllowedTools(options) {
4737
4789
  }
4738
4790
  function claudeReadOnlySandbox(policy, options = {}) {
4739
4791
  return {
4740
- enabled: true,
4792
+ enabled: options.commandSandbox !== "unavailable",
4741
4793
  failIfUnavailable: options.commandSandbox !== "unavailable",
4742
4794
  autoAllowBashIfSandboxed: true,
4743
4795
  allowUnsandboxedCommands: false,
@@ -4985,7 +5037,7 @@ async function resolveClaudeDiscoveryConfig(sessionPolicy, inputs) {
4985
5037
  const policy = claudeTurnPolicy(sessionPolicy, inputs.readOnly);
4986
5038
  const cwd = claudeWorkspaceCwd();
4987
5039
  const settingSources = claudeSettingSources(policy, inputs.includeLocalSettings);
4988
- const plugins = await getPluginsForSdk(cwd, policy?.projectResources !== false);
5040
+ const plugins = await getPluginsForSdk(cwd, policy?.projectResources !== false, settingSources);
4989
5041
  return {
4990
5042
  cwd,
4991
5043
  settingSources,
@@ -6874,21 +6926,31 @@ function turnInFlight(session) {
6874
6926
  function syncTurnInFlightMark(session, options = {}) {
6875
6927
  if (session.deleting)
6876
6928
  return;
6929
+ if (options.started)
6930
+ session.turnInFlightRequestId = options.requestId;
6877
6931
  writeTurnInFlightMark(session, options.stopped !== true && turnInFlight(session), options.started);
6878
6932
  }
6879
6933
  function clearTurnInFlightMarkForClose(session) {
6880
6934
  writeTurnInFlightMark(session, false);
6881
6935
  }
6882
6936
  function writeTurnInFlightMark(session, wanted, claim = false) {
6883
- if (wanted === (session.turnInFlightMarked === true) && !(wanted && claim && !session.turnInFlightMarkOwned))
6937
+ const renamed = claim && session.turnInFlightMarkOwned === true && session.turnInFlightMarkRequestId !== session.turnInFlightRequestId;
6938
+ if (wanted === (session.turnInFlightMarked === true) && !(wanted && claim && (!session.turnInFlightMarkOwned || renamed)))
6884
6939
  return;
6885
6940
  const sdkSessionId = session.sdkSessionId ?? sdkSessionIdFromBridgeId(session.id);
6886
6941
  if (!sdkSessionId)
6887
6942
  return;
6888
6943
  session.turnInFlightMarked = wanted;
6889
6944
  session.turnInFlightMarkOwned = wanted;
6945
+ const requestId = wanted ? session.turnInFlightRequestId : undefined;
6946
+ session.turnInFlightMarkRequestId = requestId;
6890
6947
  const update = {
6891
- turnInFlight: wanted ? { bridgeInstanceId: BRIDGE_INSTANCE_ID, pid: process.pid, startedAt: Date.now() } : undefined
6948
+ turnInFlight: wanted ? {
6949
+ bridgeInstanceId: BRIDGE_INSTANCE_ID,
6950
+ pid: process.pid,
6951
+ startedAt: Date.now(),
6952
+ ...requestId ? { requestId } : {}
6953
+ } : undefined
6892
6954
  };
6893
6955
  updateSessionPreferences(sdkSessionId, update).catch((error) => {
6894
6956
  debugLog("[session-manager] Failed to record the turn-in-flight mark:", error instanceof Error ? error.message : String(error));
@@ -6907,6 +6969,7 @@ function restoredTurnInterruption(preferences) {
6907
6969
  status: "error",
6908
6970
  error: CLAUDE_RESTARTED_MID_TURN_MESSAGE,
6909
6971
  interruption: "restart",
6972
+ ...mark.requestId ? { interruptedRequestId: mark.requestId } : {},
6910
6973
  turnInFlightMarked: true
6911
6974
  };
6912
6975
  }
@@ -7481,6 +7544,13 @@ function claudeLaunchedProfile(session, options) {
7481
7544
  settingSources: JSON.stringify(claudeSettingSources(claudeTurnPolicy(session.executionPolicy, options?.readOnly), options?.includeLocalSettings))
7482
7545
  };
7483
7546
  }
7547
+ function claudeTurnSettingSources(session, options) {
7548
+ const policy = claudeTurnPolicy(session.executionPolicy, options?.readOnly);
7549
+ const running = openClaudeRuntime(session);
7550
+ if (options?.includeLocalSettings === undefined && running?.launch.settingSources !== undefined && !claudeLaunchConflict(running.launch, claudeLaunchProfile(session, options)))
7551
+ return JSON.parse(running.launch.settingSources);
7552
+ return claudeSettingSources(policy, options?.includeLocalSettings);
7553
+ }
7484
7554
  function assertClaudeRuntimeStaticAccepts(session, options) {
7485
7555
  const runtime = openClaudeRuntime(session);
7486
7556
  if (!runtime || !claudeRuntimeOwesWork(runtime))
@@ -7502,7 +7572,7 @@ async function assertClaudeRuntimeAccepts(session, options, resources) {
7502
7572
  if (!resources) {
7503
7573
  const policy = claudeTurnPolicy(session.executionPolicy, options?.readOnly);
7504
7574
  const [plugins, environment] = await Promise.all([
7505
- getPluginsForSdk(request.cwd, policy?.projectResources !== false),
7575
+ getPluginsForSdk(request.cwd, policy?.projectResources !== false, claudeTurnSettingSources(session, options)),
7506
7576
  runtimeEnvironmentForAgentQuery()
7507
7577
  ]);
7508
7578
  resources = claudeLaunchResourceProfile(plugins, environment);
@@ -11791,6 +11861,7 @@ function captureTurnStartup(session) {
11791
11861
  abortController: session.abortController,
11792
11862
  error: session.error,
11793
11863
  interruption: session.interruption,
11864
+ interruptedRequestId: session.interruptedRequestId,
11794
11865
  lastActivity: session.lastActivity,
11795
11866
  persistedMessagesLoaded: session.persistedMessagesLoaded,
11796
11867
  structuredOutput: session.structuredOutput,
@@ -11963,6 +12034,7 @@ async function applyPromptPlanMode(admission, planMode) {
11963
12034
  session.turnStartedAt = beforeStartup.turnStartedAt;
11964
12035
  session.error = beforeStartup.error;
11965
12036
  session.interruption = beforeStartup.interruption;
12037
+ session.interruptedRequestId = beforeStartup.interruptedRequestId;
11966
12038
  session.lastActivity = beforeStartup.lastActivity;
11967
12039
  session.persistedMessagesLoaded = beforeStartup.persistedMessagesLoaded;
11968
12040
  if (needsTranscriptHydration)
@@ -11983,6 +12055,7 @@ function beginPromptActivity(admission) {
11983
12055
  const { session, sessionId } = admission;
11984
12056
  session.error = undefined;
11985
12057
  session.interruption = undefined;
12058
+ session.interruptedRequestId = undefined;
11986
12059
  session.lastActivity = new Date;
11987
12060
  if (session.promptSuggestion !== undefined) {
11988
12061
  session.promptSuggestion = undefined;
@@ -14074,6 +14147,132 @@ function backgroundCommandInstruction(env) {
14074
14147
  // ../../bridges/claude-bridge/src/services/claude-execution-sandbox.ts
14075
14148
  import { realpathSync } from "node:fs";
14076
14149
 
14150
+ // ../protocol/src/node/claude-linux-sandbox.ts
14151
+ import { spawnSync } from "node:child_process";
14152
+ import { accessSync, constants as constants2, existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
14153
+ import { delimiter as delimiter2, join as join11 } from "node:path";
14154
+ var CLAUDE_LINUX_SANDBOX_PROGRAMS = Object.freeze(["bwrap", "socat"]);
14155
+ var APPARMOR_BWRAP_PROFILE = "/etc/apparmor.d/bwrap-userns-restrict";
14156
+ var CLAUDE_LINUX_SANDBOX_PROBE_TIMEOUT_MS = 5000;
14157
+ var CLAUDE_LINUX_SANDBOX_PROBE_TTL_MS = 5 * 60000;
14158
+ var BWRAP_ARGS = Object.freeze([
14159
+ "--new-session",
14160
+ "--die-with-parent",
14161
+ "--unshare-user",
14162
+ "--unshare-pid",
14163
+ "--ro-bind",
14164
+ "/",
14165
+ "/",
14166
+ "--dev",
14167
+ "/dev",
14168
+ "--proc",
14169
+ "/proc",
14170
+ "--"
14171
+ ]);
14172
+ var NESTED_ARGS = Object.freeze([
14173
+ "unshare",
14174
+ "--user",
14175
+ "--map-root-user",
14176
+ "--pid",
14177
+ "--mount",
14178
+ "--fork",
14179
+ "--mount-proc",
14180
+ "true"
14181
+ ]);
14182
+ function executableOnPath(name, path = process.env.PATH) {
14183
+ for (const directory of (path ?? "").split(delimiter2)) {
14184
+ if (!directory)
14185
+ continue;
14186
+ try {
14187
+ accessSync(join11(directory, name), constants2.X_OK);
14188
+ return true;
14189
+ } catch {}
14190
+ }
14191
+ return false;
14192
+ }
14193
+ function runProbeCommand(command, args) {
14194
+ const result = spawnSync(command, [...args], {
14195
+ timeout: CLAUDE_LINUX_SANDBOX_PROBE_TIMEOUT_MS,
14196
+ killSignal: "SIGKILL",
14197
+ stdio: ["ignore", "ignore", "pipe"],
14198
+ encoding: "utf8",
14199
+ maxBuffer: 64 * 1024
14200
+ });
14201
+ if (result.error)
14202
+ return { ok: false, stderr: result.error.message };
14203
+ return { ok: result.status === 0, stderr: result.stderr ?? "" };
14204
+ }
14205
+ function appArmorBwrapProfileInstalled() {
14206
+ try {
14207
+ const enabled = readFileSync3("/sys/module/apparmor/parameters/enabled", "utf8");
14208
+ return enabled.trim().startsWith("Y") && existsSync2(APPARMOR_BWRAP_PROFILE);
14209
+ } catch {
14210
+ return false;
14211
+ }
14212
+ }
14213
+ function probeDetail(stderr) {
14214
+ const line = stderr.split(`
14215
+ `).map((entry) => entry.trim()).find(Boolean) ?? "no error output";
14216
+ return line.length > 200 ? `${line.slice(0, 199)}…` : line;
14217
+ }
14218
+ var UNAVAILABLE = "Claude's command sandbox cannot run commands on this host";
14219
+ function probeClaudeLinuxSandbox(dependencies = {}) {
14220
+ const onPath = dependencies.onPath ?? ((name) => executableOnPath(name));
14221
+ const run = dependencies.run ?? runProbeCommand;
14222
+ const appArmorBwrapProfile = dependencies.appArmorBwrapProfile ?? appArmorBwrapProfileInstalled;
14223
+ const missing = CLAUDE_LINUX_SANDBOX_PROGRAMS.filter((name) => !onPath(name));
14224
+ if (missing.length > 0) {
14225
+ return {
14226
+ available: false,
14227
+ failure: "missing-programs",
14228
+ reason: `${UNAVAILABLE}: the Claude CLI's Linux sandbox needs bubblewrap and socat on PATH, and ${missing.join(" and ")} ${missing.length === 1 ? "is" : "are"} missing. Install the bubblewrap and socat packages.`
14229
+ };
14230
+ }
14231
+ if (!onPath("unshare")) {
14232
+ return {
14233
+ available: false,
14234
+ failure: "probe-unavailable",
14235
+ reason: `${UNAVAILABLE}: whether a user namespace can be nested inside bubblewrap's, which the Claude CLI needs, could not be checked because unshare (util-linux) is not on PATH.`
14236
+ };
14237
+ }
14238
+ const nested = run("bwrap", [...BWRAP_ARGS, ...NESTED_ARGS]);
14239
+ if (nested.ok)
14240
+ return { available: true };
14241
+ const outer = run("bwrap", [...BWRAP_ARGS, "true"]);
14242
+ if (!outer.ok) {
14243
+ return {
14244
+ available: false,
14245
+ failure: "user-namespace",
14246
+ reason: `${UNAVAILABLE}: bubblewrap cannot create a user namespace (${probeDetail(outer.stderr)}). Unprivileged user namespaces are turned off or restricted here, for example by kernel.unprivileged_userns_clone, AppArmor's kernel.apparmor_restrict_unprivileged_userns, or a container's seccomp profile.`
14247
+ };
14248
+ }
14249
+ const detail = probeDetail(nested.stderr);
14250
+ if (appArmorBwrapProfile()) {
14251
+ return {
14252
+ available: false,
14253
+ failure: "nested-user-namespace",
14254
+ reason: `${UNAVAILABLE}: bubblewrap starts, but AppArmor's bwrap-userns-restrict profile strips capabilities from the user namespace the Claude CLI nests inside it, so every sandboxed command would fail (${detail}). Allow nested namespaces for bubblewrap with a local AppArmor profile, or remove bwrap-userns-restrict on a dedicated host; Orkestrator does not change AppArmor policy itself.`
14255
+ };
14256
+ }
14257
+ return {
14258
+ available: false,
14259
+ failure: "nested-user-namespace",
14260
+ reason: `${UNAVAILABLE}: bubblewrap starts, but a user namespace nested inside it is refused (${detail}), and the Claude CLI's command helper needs one, so every sandboxed command would fail. In a container this is usually the container's seccomp profile or missing capabilities.`
14261
+ };
14262
+ }
14263
+ var cached;
14264
+ var pinned;
14265
+ function claudeLinuxSandboxStatus(now = Date.now()) {
14266
+ if (pinned)
14267
+ return pinned;
14268
+ if (cached && now - cached.at >= 0 && now - cached.at < CLAUDE_LINUX_SANDBOX_PROBE_TTL_MS) {
14269
+ return cached.status;
14270
+ }
14271
+ const status = probeClaudeLinuxSandbox();
14272
+ cached = { status, at: now };
14273
+ return status;
14274
+ }
14275
+
14077
14276
  // ../protocol/src/coordinator.ts
14078
14277
  var COORDINATOR_COMMAND_SANDBOX_ENV = "ORKESTRATOR_COORDINATOR_COMMAND_SANDBOX";
14079
14278
  function coordinatorCommandSandboxFromEnv(env) {
@@ -14168,6 +14367,16 @@ function claudeExecutionSandbox(policy, asksForApproval, readOnly = {}) {
14168
14367
  }
14169
14368
  };
14170
14369
  }
14370
+ function claudeSandboxRefusal(policy, options = {}) {
14371
+ if ((options.platform ?? process.platform) !== "linux" || !policy)
14372
+ return;
14373
+ const launcher = "commandSandbox" in options ? options.commandSandbox : process.env[COORDINATOR_COMMAND_SANDBOX_ENV];
14374
+ const required = isCoordinatorReadOnlyPolicy(policy) ? launcher !== undefined && launcher !== "unavailable" : policy.sandbox === "provider";
14375
+ if (!required)
14376
+ return;
14377
+ const status = (options.linuxSandbox ?? claudeLinuxSandboxStatus)();
14378
+ return status.available ? undefined : status.reason;
14379
+ }
14171
14380
 
14172
14381
  // ../protocol/src/agent-interaction-deadline.ts
14173
14382
  var SYSTEM_CLOCK = {
@@ -14929,14 +15138,19 @@ async function resolveQueryPlan(turn, sdkTextPrompt, testHooks) {
14929
15138
  const effortLevel = options?.effort ?? "high";
14930
15139
  const cwd = claudeWorkspaceCwd();
14931
15140
  const policy = claudeTurnPolicy(session.executionPolicy, options?.readOnly);
15141
+ const sandboxRefusal = claudeSandboxRefusal(policy);
15142
+ if (sandboxRefusal)
15143
+ throw sessionOperationError("invalid", sandboxRefusal);
14932
15144
  session.commandDiscoveryInputs = {
14933
15145
  readOnly: options?.readOnly === true,
14934
15146
  includeLocalSettings: options?.includeLocalSettings === true
14935
15147
  };
14936
15148
  const includeProjectResources = policy?.projectResources !== false;
15149
+ const settingSources = claudeTurnSettingSources(session, options);
15150
+ session.commandDiscoveryInputs.includeLocalSettings = settingSources.includes("local");
14937
15151
  const [{ servers: mcpServers, names: mcpServerNames, revision: mcpConfigRevision }, plugins] = await Promise.all([
14938
15152
  getMcpRuntimeConfig(cwd, process.env, options?.agentMcp, mcpSourceScopeForPolicy(policy)),
14939
- getPluginsForSdk(cwd, includeProjectResources)
15153
+ getPluginsForSdk(cwd, includeProjectResources, settingSources)
14940
15154
  ]);
14941
15155
  turn.mcpServerNames = mcpServerNames;
14942
15156
  const mcpServerCount = Object.keys(mcpServers).length;
@@ -15001,6 +15215,7 @@ async function resolveQueryPlan(turn, sdkTextPrompt, testHooks) {
15001
15215
  });
15002
15216
  const mcpServersKey = createHash10("sha256").update(JSON.stringify(mcpServers)).digest("hex");
15003
15217
  return {
15218
+ settingSources,
15004
15219
  cwd,
15005
15220
  policy,
15006
15221
  effortLevel,
@@ -15111,7 +15326,7 @@ function claudeQueryOptions(turn, plan, turnFor, mcp) {
15111
15326
 
15112
15327
  `)
15113
15328
  },
15114
- settingSources: claudeSettingSources(policy, options?.includeLocalSettings),
15329
+ settingSources: plan.settingSources,
15115
15330
  ...(fastMode || ultracode) && {
15116
15331
  settings: {
15117
15332
  ...fastMode && { fastMode: true },
@@ -16639,6 +16854,7 @@ function endClaudeRuntime(runtime, failure) {
16639
16854
  session.status = "error";
16640
16855
  session.error = claudeProcessKilledMessage(killedBy);
16641
16856
  session.interruption = "restart";
16857
+ session.interruptedRequestId = session.turnInFlightRequestId;
16642
16858
  session.turnStartedAt = undefined;
16643
16859
  session.abortController = undefined;
16644
16860
  session.completionBlockedByBackgroundTasks = false;
@@ -16697,7 +16913,10 @@ async function prepareJoin(turn, plan, running) {
16697
16913
  const { session, options } = turn;
16698
16914
  const { mcpServers, plugins, sdkPrompt, queryEnvironment, liveSettings, mcpServersKey } = plan;
16699
16915
  const required = mcpServers[AGENT_MCP_SERVER_NAME] ? [AGENT_MCP_SERVER_NAME, ...options?.agentMcp?.design ? ["orkestrator-design"] : []] : [];
16700
- await assertClaudeRuntimeAccepts(session, options, claudeLaunchResourceProfile(plugins, queryEnvironment));
16916
+ await assertClaudeRuntimeAccepts(session, options, {
16917
+ ...claudeLaunchResourceProfile(plugins, queryEnvironment),
16918
+ settingSources: JSON.stringify(plan.settingSources)
16919
+ });
16701
16920
  session.queryControl = running.control;
16702
16921
  turn.queryIteratorControl = running.control;
16703
16922
  try {
@@ -16755,6 +16974,7 @@ function launchClaudeRuntime(turn, plan) {
16755
16974
  activeTaskIds: stream.activeTaskIds,
16756
16975
  launch: {
16757
16976
  ...claudeLaunchedProfile(session, options),
16977
+ settingSources: JSON.stringify(plan.settingSources),
16758
16978
  ...claudeLaunchResourceProfile(plugins, queryEnvironment)
16759
16979
  },
16760
16980
  mcpServers: mcpServersKey,
@@ -16791,7 +17011,7 @@ function markQueryStarted(turn, testHooks) {
16791
17011
  }, { once: true });
16792
17012
  session.finishTurnInputIfSettled = turn.finishTurnInputForThisTurn;
16793
17013
  turn.queryStarted = true;
16794
- syncTurnInFlightMark(session, { started: true });
17014
+ syncTurnInFlightMark(session, { started: true, requestId: turn.dispatchRequestId });
16795
17015
  testHooks?.onQueryStarted?.();
16796
17016
  readLiveCommandInventory(session, control);
16797
17017
  reportUltracodeRuntime(session, control);
@@ -16805,6 +17025,7 @@ function joinableRuntime(turn, plan) {
16805
17025
  return running;
16806
17026
  const requested = {
16807
17027
  ...claudeLaunchProfile(turn.session, turn.options),
17028
+ settingSources: JSON.stringify(plan.settingSources),
16808
17029
  ...claudeLaunchResourceProfile(plan.plugins, plan.queryEnvironment)
16809
17030
  };
16810
17031
  return claudeLaunchConflict(running.launch, requested) ? undefined : running;
@@ -16938,6 +17159,7 @@ function settleFailedTurn(turn, error) {
16938
17159
  session.abortController = turn.beforeStartup.abortController;
16939
17160
  session.error = turn.beforeStartup.error;
16940
17161
  session.interruption = turn.beforeStartup.interruption;
17162
+ session.interruptedRequestId = turn.beforeStartup.interruptedRequestId;
16941
17163
  session.inProgressUsage = turn.beforeStartup.inProgressUsage;
16942
17164
  session.inProgressUsageGeneration = turn.beforeStartup.inProgressUsageGeneration;
16943
17165
  const index = session.messages.indexOf(userMessage);
@@ -16966,6 +17188,7 @@ function settleFailedTurn(turn, error) {
16966
17188
  session.turnStartedAt = undefined;
16967
17189
  session.error = failure;
16968
17190
  session.interruption = killedBy ? "restart" : undefined;
17191
+ session.interruptedRequestId = killedBy ? turn.dispatchRequestId : undefined;
16969
17192
  session.abortController = undefined;
16970
17193
  session.completionBlockedByBackgroundTasks = false;
16971
17194
  cleanupPendingInteractions(sessionId);
@@ -18168,9 +18391,14 @@ function compressTranscriptReads(app) {
18168
18391
  function query3(c) {
18169
18392
  return (name) => c.req.query(name);
18170
18393
  }
18171
- function registerSessionTranscriptRoutes(app, generation) {
18172
- app.get("/:id/transcript", (c) => {
18394
+ function registerSessionTranscriptRoutes(app, generation, materialize) {
18395
+ app.get("/:id/transcript", async (c) => {
18173
18396
  const id = c.req.param("id");
18397
+ if (!peekSession(id)) {
18398
+ const resolved = await materialize(id);
18399
+ if (!resolved.ok)
18400
+ return c.json(resolved.body, resolved.status);
18401
+ }
18174
18402
  const read = claudeTranscriptSource(id, generation);
18175
18403
  if (!read)
18176
18404
  return c.json({ error: "Session not found" }, 404);
@@ -18337,7 +18565,10 @@ session.get("/:id", async (c) => {
18337
18565
  createdAt: sessionData.createdAt.toISOString(),
18338
18566
  lastActivity: sessionData.lastActivity.toISOString(),
18339
18567
  error: sessionData.error,
18340
- ...sessionData.status === "error" && sessionData.interruption ? { interruption: sessionData.interruption } : {},
18568
+ ...sessionData.status === "error" && sessionData.interruption ? {
18569
+ interruption: sessionData.interruption,
18570
+ ...sessionData.interruptedRequestId ? { interruptedRequestId: sessionData.interruptedRequestId } : {}
18571
+ } : {},
18341
18572
  structuredOutputRequestId: sessionData.structuredOutputRequestId,
18342
18573
  structuredOutput: sessionData.structuredOutput,
18343
18574
  contextUsage: sessionData.inProgressUsage ?? sessionData.usage,
@@ -18533,7 +18764,7 @@ session.get("/:id/messages", async (c) => {
18533
18764
  const limit = parseTranscriptTailLimit(c.req.query("limit") ?? null);
18534
18765
  return c.json(boundClaudeTranscriptResponse(messages, limit ?? undefined));
18535
18766
  });
18536
- registerSessionTranscriptRoutes(session, TRANSCRIPT_GENERATION);
18767
+ registerSessionTranscriptRoutes(session, TRANSCRIPT_GENERATION, (id) => resolveSession(id, "Failed to load session transcript"));
18537
18768
  session.post("/:id/prompt", async (c) => {
18538
18769
  const id = c.req.param("id");
18539
18770
  const resolved = await resolveSession(id, "Failed to send prompt");
@@ -18639,6 +18870,10 @@ session.post("/:id/prompt", async (c) => {
18639
18870
  await answerIdleSteerPrompt(sessionData, prompt, requestId);
18640
18871
  return c.json({ status: "accepted", requestId, local: true });
18641
18872
  }
18873
+ const sandboxRefusal = claudeSandboxRefusal(claudeTurnPolicy(sessionData.executionPolicy, typeof readOnly === "boolean" ? readOnly : undefined));
18874
+ if (sandboxRefusal) {
18875
+ return c.json({ error: sandboxRefusal, kind: "sandbox-unavailable" }, 422);
18876
+ }
18642
18877
  await assertClaudeRuntimeAccepts(sessionData, {
18643
18878
  ...typeof readOnly === "boolean" ? { readOnly } : {},
18644
18879
  agent,
@@ -18891,14 +19126,14 @@ session.get("/:id/runtime-health", (c) => {
18891
19126
  return c.json(sessionRuntimeHealthBody(peekSession(c.req.param("id"))));
18892
19127
  });
18893
19128
  session.get("/:id/dispatch", async (c) => {
18894
- const answer = (dispatch) => c.json({ dispatch });
19129
+ const answer = (dispatch, pending) => c.json({ dispatch, ...pending !== undefined ? { pending } : {} });
18895
19130
  const requestId = c.req.query("requestId")?.trim();
18896
19131
  if (!requestId)
18897
19132
  return answer("unknown");
18898
19133
  const id = c.req.param("id");
18899
19134
  const state = getPromptDispatchState(id, requestId);
18900
19135
  if (state === "processing" || state === "already-processed")
18901
- return answer("dispatched");
19136
+ return answer("dispatched", state === "processing");
18902
19137
  if (state === "new") {
18903
19138
  return answer(restoredDispatchClaimLost(peekSession(id), requestId) ? "lost" : "unknown");
18904
19139
  }
@@ -19741,7 +19976,7 @@ var X_ALREADY_SENT = "x-hono-already-sent";
19741
19976
 
19742
19977
  // ../../node_modules/.bun/@hono+node-server@2.1.5+c539cad7f494f5c9/node_modules/@hono/node-server/dist/index.mjs
19743
19978
  import { STATUS_CODES, ServerResponse, createServer } from "node:http";
19744
- import { Http2ServerRequest, constants as constants2 } from "node:http2";
19979
+ import { Http2ServerRequest, constants as constants3 } from "node:http2";
19745
19980
  import { Readable } from "node:stream";
19746
19981
 
19747
19982
  // ../../node_modules/.bun/hono@4.13.13/node_modules/hono/dist/helper/websocket/index.js
@@ -20660,7 +20895,7 @@ var drainIncoming = (incoming) => {
20660
20895
  incomingWithDrainState[incomingDraining] = true;
20661
20896
  if (incoming instanceof Http2ServerRequest) {
20662
20897
  try {
20663
- incoming.stream?.close?.(constants2.NGHTTP2_NO_ERROR);
20898
+ incoming.stream?.close?.(constants3.NGHTTP2_NO_ERROR);
20664
20899
  } catch {}
20665
20900
  return;
20666
20901
  }