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/dist/client.js +4 -2
- package/dist/main.js +4063 -3091
- package/package.json +3 -3
- package/resources/claude-bridge/dist/index.js +262 -27
- package/resources/codex-bridge/dist/index.js +406 -130
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orkestrator",
|
|
3
|
-
"version": "2.
|
|
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.
|
|
43
|
-
"@orkestrator/toolchain": "2.
|
|
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.
|
|
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
|
-
|
|
4020
|
-
|
|
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({
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
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:
|
|
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
|
-
|
|
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 ? {
|
|
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:
|
|
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,
|
|
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 ? {
|
|
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
|
|
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?.(
|
|
20898
|
+
incoming.stream?.close?.(constants3.NGHTTP2_NO_ERROR);
|
|
20664
20899
|
} catch {}
|
|
20665
20900
|
return;
|
|
20666
20901
|
}
|