orkestrator 2.34.5-beta → 2.35.1-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 +65 -12
- package/dist/main.js +62881 -59863
- package/package.json +3 -3
- package/resources/acp-bridge/dist/index.js +132 -36
- package/resources/claude-bridge/dist/index.js +594 -303
- package/resources/codex-bridge/dist/index.js +188 -73
- package/resources/cursor-bridge/dist/index.js +227 -38
- package/resources/cursor-bridge/runtime/install.json +1 -1
- package/resources/pi-bridge/dist/index.js +49 -0
- package/resources/pi-bridge/runtime/install.json +1 -1
|
@@ -4812,6 +4812,7 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
|
|
|
4812
4812
|
"stop_node_environment",
|
|
4813
4813
|
"stop_worker_turn",
|
|
4814
4814
|
"switch_provider_account",
|
|
4815
|
+
"set_account_auto_switch",
|
|
4815
4816
|
"transfer_files",
|
|
4816
4817
|
"update_schedule",
|
|
4817
4818
|
"update_ticket"
|
|
@@ -8864,6 +8865,8 @@ function claudeLaunchConflict(runtime, request) {
|
|
|
8864
8865
|
return "adaptive thinking";
|
|
8865
8866
|
if (request.bypassCapable && !runtime.bypassCapable)
|
|
8866
8867
|
return "bypass permission capability";
|
|
8868
|
+
if (request.repositoryInstructions !== undefined && runtime.repositoryInstructions !== request.repositoryInstructions)
|
|
8869
|
+
return "repository instructions";
|
|
8867
8870
|
if (request.plugins !== undefined && runtime.plugins !== request.plugins)
|
|
8868
8871
|
return "plugins";
|
|
8869
8872
|
if (request.credentials !== undefined && runtime.credentials !== request.credentials)
|
|
@@ -13686,7 +13689,11 @@ function claudeUserMcpQueryOptions(policy) {
|
|
|
13686
13689
|
async function loadScopedMcpServers(cwd, scope) {
|
|
13687
13690
|
if (scope === "none") {
|
|
13688
13691
|
const sources = { user: "excluded", project: "excluded" };
|
|
13689
|
-
return {
|
|
13692
|
+
return {
|
|
13693
|
+
configs: {},
|
|
13694
|
+
layers: new Map,
|
|
13695
|
+
revision: { fingerprint: revisionFingerprint(sources), sources, scope }
|
|
13696
|
+
};
|
|
13690
13697
|
}
|
|
13691
13698
|
const path = claudeJsonPath();
|
|
13692
13699
|
const [global2, projectGlobal, projectLocal] = await Promise.all([
|
|
@@ -13699,11 +13706,22 @@ async function loadScopedMcpServers(cwd, scope) {
|
|
|
13699
13706
|
...projectGlobal?.value,
|
|
13700
13707
|
...projectLocal?.value
|
|
13701
13708
|
};
|
|
13709
|
+
const layers = new Map;
|
|
13710
|
+
for (const name of Object.keys(global2.value ?? {}))
|
|
13711
|
+
layers.set(name, "user");
|
|
13712
|
+
for (const name of Object.keys(projectGlobal?.value ?? {}))
|
|
13713
|
+
layers.set(name, "local");
|
|
13714
|
+
for (const name of Object.keys(projectLocal?.value ?? {}))
|
|
13715
|
+
layers.set(name, "project");
|
|
13702
13716
|
const sources = {
|
|
13703
13717
|
user: sourceDigest(global2.digest),
|
|
13704
13718
|
project: projectLocal ? sourceDigest(projectLocal.digest) : "excluded"
|
|
13705
13719
|
};
|
|
13706
|
-
return {
|
|
13720
|
+
return {
|
|
13721
|
+
configs,
|
|
13722
|
+
layers,
|
|
13723
|
+
revision: { fingerprint: revisionFingerprint(sources), sources, scope }
|
|
13724
|
+
};
|
|
13707
13725
|
}
|
|
13708
13726
|
async function claudeAccountOnlyMcpServerNames(cwd, settingSources, declared, strictMcpConfig = false) {
|
|
13709
13727
|
const path = claudeAccountJsonPath();
|
|
@@ -13723,21 +13741,28 @@ async function getMcpRuntimeConfig(cwd, env = process.env, connection, sources =
|
|
|
13723
13741
|
const scoped = await loadScopedMcpServers(cwd, normalizeScope(sources));
|
|
13724
13742
|
const { revision } = scoped;
|
|
13725
13743
|
const configs = allowConfigured ? Object.fromEntries(Object.entries(scoped.configs).filter(([name]) => allowConfigured(name))) : scoped.configs;
|
|
13726
|
-
const agentServer = getOrkestratorAgentMcpServerFromConnection(connection) ?? getOrkestratorAgentMcpServer(env);
|
|
13727
13744
|
const servers = toSdkServers(configs);
|
|
13745
|
+
const layers = new Map(Array.from(scoped.layers).filter(([name]) => Object.hasOwn(servers, name)));
|
|
13746
|
+
const agentServer = getOrkestratorAgentMcpServerFromConnection(connection) ?? getOrkestratorAgentMcpServer(env);
|
|
13728
13747
|
if (agentServer) {
|
|
13729
13748
|
servers[AGENT_MCP_SERVER_NAME] = agentServer;
|
|
13730
|
-
|
|
13749
|
+
layers.set(AGENT_MCP_SERVER_NAME, "orkestrator");
|
|
13750
|
+
if (connection?.design) {
|
|
13731
13751
|
servers["orkestrator-design"] = {
|
|
13732
13752
|
...agentServer,
|
|
13733
13753
|
url: new URL("/design-mcp", agentServer.url).toString()
|
|
13734
13754
|
};
|
|
13755
|
+
layers.set("orkestrator-design", "orkestrator");
|
|
13756
|
+
}
|
|
13735
13757
|
}
|
|
13736
13758
|
const artifactServer = getOrkestratorArtifactMcpServer(connection);
|
|
13737
|
-
if (artifactServer)
|
|
13759
|
+
if (artifactServer) {
|
|
13738
13760
|
servers[ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME] = artifactServer;
|
|
13739
|
-
|
|
13761
|
+
layers.set(ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME, "orkestrator");
|
|
13762
|
+
} else {
|
|
13740
13763
|
delete servers[ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME];
|
|
13764
|
+
layers.delete(ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME);
|
|
13765
|
+
}
|
|
13741
13766
|
const research = normalizeScope(sources) === "none" ? coordinatorResearchMcpServersFromEnv(env) : [];
|
|
13742
13767
|
for (const server of research)
|
|
13743
13768
|
servers[server.name] = { type: "http", url: server.url };
|
|
@@ -13749,6 +13774,7 @@ async function getMcpRuntimeConfig(cwd, env = process.env, connection, sources =
|
|
|
13749
13774
|
...artifactServer ? [ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME] : [],
|
|
13750
13775
|
...research.map((server) => server.name)
|
|
13751
13776
|
]),
|
|
13777
|
+
layers,
|
|
13752
13778
|
revision
|
|
13753
13779
|
};
|
|
13754
13780
|
}
|
|
@@ -13756,6 +13782,384 @@ async function getMcpRuntimeConfig(cwd, env = process.env, connection, sources =
|
|
|
13756
13782
|
// ../../bridges/claude-bridge/src/services/session-manager-commands.ts
|
|
13757
13783
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
13758
13784
|
|
|
13785
|
+
// ../../bridges/claude-bridge/src/services/claude-model-catalog.ts
|
|
13786
|
+
import { homedir as homedir2 } from "node:os";
|
|
13787
|
+
import { join as join12 } from "node:path";
|
|
13788
|
+
import { stat as stat5 } from "node:fs/promises";
|
|
13789
|
+
|
|
13790
|
+
// ../../bridges/claude-bridge/src/services/live-claude-control.ts
|
|
13791
|
+
var LIVE_CLAUDE_READ_TIMEOUT_MS = 5000;
|
|
13792
|
+
function readsProbeSettings(settingSources) {
|
|
13793
|
+
if (settingSources === undefined)
|
|
13794
|
+
return false;
|
|
13795
|
+
try {
|
|
13796
|
+
const sources = JSON.parse(settingSources);
|
|
13797
|
+
return Array.isArray(sources) && ["user", "project", "local"].every((source) => sources.includes(source));
|
|
13798
|
+
} catch {
|
|
13799
|
+
return false;
|
|
13800
|
+
}
|
|
13801
|
+
}
|
|
13802
|
+
function liveClaudeControls() {
|
|
13803
|
+
const runtimes = [];
|
|
13804
|
+
for (const session of sessions.values()) {
|
|
13805
|
+
const runtime = session.claudeRuntime;
|
|
13806
|
+
if (runtime?.state !== "open" || runtime.abortController.signal.aborted)
|
|
13807
|
+
continue;
|
|
13808
|
+
if (session.queryControlDraining === runtime.control || session.deleting)
|
|
13809
|
+
continue;
|
|
13810
|
+
if (!readsProbeSettings(runtime.launch.settingSources))
|
|
13811
|
+
continue;
|
|
13812
|
+
runtimes.push(runtime);
|
|
13813
|
+
}
|
|
13814
|
+
return runtimes.sort((left, right) => right.lastFrameAt - left.lastFrameAt).map((runtime) => runtime.control);
|
|
13815
|
+
}
|
|
13816
|
+
async function readFromLiveClaude(read, timeoutMs = LIVE_CLAUDE_READ_TIMEOUT_MS) {
|
|
13817
|
+
for (const control of liveClaudeControls()) {
|
|
13818
|
+
let timer;
|
|
13819
|
+
try {
|
|
13820
|
+
const answer = read(control);
|
|
13821
|
+
if (answer === undefined)
|
|
13822
|
+
continue;
|
|
13823
|
+
answer.catch(() => {
|
|
13824
|
+
return;
|
|
13825
|
+
});
|
|
13826
|
+
const value = await Promise.race([
|
|
13827
|
+
answer,
|
|
13828
|
+
new Promise((resolve) => {
|
|
13829
|
+
timer = setTimeout(() => resolve(undefined), timeoutMs);
|
|
13830
|
+
})
|
|
13831
|
+
]);
|
|
13832
|
+
if (value !== undefined)
|
|
13833
|
+
return value;
|
|
13834
|
+
} catch (error) {
|
|
13835
|
+
debugLog("[live-claude-control] A running CLI could not answer:", error);
|
|
13836
|
+
} finally {
|
|
13837
|
+
clearTimeout(timer);
|
|
13838
|
+
}
|
|
13839
|
+
}
|
|
13840
|
+
return;
|
|
13841
|
+
}
|
|
13842
|
+
function liveInitializationResult(control) {
|
|
13843
|
+
if (typeof control.initializationResult !== "function")
|
|
13844
|
+
return;
|
|
13845
|
+
return control.initializationResult().then((result) => result && typeof result === "object" ? result : undefined);
|
|
13846
|
+
}
|
|
13847
|
+
|
|
13848
|
+
// ../../bridges/claude-bridge/src/services/claude-sign-in.ts
|
|
13849
|
+
var AUTH_CACHE_TTL_MS = 30000;
|
|
13850
|
+
var FAILED_AUTH_CACHE_TTL_MS = 5000;
|
|
13851
|
+
var CLAUDE_SIGN_IN = {
|
|
13852
|
+
kind: "terminal",
|
|
13853
|
+
hint: "Sign in to Claude from the sign-in card in this tab or from Settings → Claude."
|
|
13854
|
+
};
|
|
13855
|
+
var CLAUDE_SIGN_IN_REQUIRED_MESSAGE = "Claude isn't signed in. Sign in to Claude to keep working.";
|
|
13856
|
+
var authCache;
|
|
13857
|
+
var authRead;
|
|
13858
|
+
var authReadGeneration;
|
|
13859
|
+
var authRefreshPending = false;
|
|
13860
|
+
var authGeneration = 0;
|
|
13861
|
+
var turnAuthenticationFailedUntil = 0;
|
|
13862
|
+
var reuseLiveAccounts = true;
|
|
13863
|
+
function withTurnFailure(value) {
|
|
13864
|
+
return Date.now() < turnAuthenticationFailedUntil && value.state === "signed-in" ? { ...value, state: "expired" } : value;
|
|
13865
|
+
}
|
|
13866
|
+
function presentSource(value) {
|
|
13867
|
+
return value && value !== "none" ? value : undefined;
|
|
13868
|
+
}
|
|
13869
|
+
function normalizeClaudeAccount(account) {
|
|
13870
|
+
const source = presentSource(account.apiKeySource) ?? presentSource(account.tokenSource);
|
|
13871
|
+
const externalProvider = account.apiProvider && account.apiProvider !== "firstParty" ? account.apiProvider : undefined;
|
|
13872
|
+
const signedIn = Boolean(source || account.subscriptionType || account.organization || externalProvider);
|
|
13873
|
+
const label = account.organization || account.subscriptionType || externalProvider;
|
|
13874
|
+
return {
|
|
13875
|
+
state: signedIn ? "signed-in" : "needs-auth",
|
|
13876
|
+
...label ? {
|
|
13877
|
+
account: {
|
|
13878
|
+
label,
|
|
13879
|
+
...account.subscriptionType ? { plan: account.subscriptionType } : {}
|
|
13880
|
+
}
|
|
13881
|
+
} : {},
|
|
13882
|
+
signIn: CLAUDE_SIGN_IN,
|
|
13883
|
+
signOut: false
|
|
13884
|
+
};
|
|
13885
|
+
}
|
|
13886
|
+
function claudeAccountKey(status) {
|
|
13887
|
+
return JSON.stringify([status.state, status.account?.label, status.account?.plan]);
|
|
13888
|
+
}
|
|
13889
|
+
function claudeObservedAccountKey() {
|
|
13890
|
+
const value = authCache?.value;
|
|
13891
|
+
return value && value.state !== "unknown" ? claudeAccountKey(value) : undefined;
|
|
13892
|
+
}
|
|
13893
|
+
function liveSignedInAccount() {
|
|
13894
|
+
return readFromLiveClaude((control) => liveInitializationResult(control)?.then((result) => {
|
|
13895
|
+
const account = result?.account;
|
|
13896
|
+
if (!account || typeof account !== "object")
|
|
13897
|
+
return;
|
|
13898
|
+
const status = normalizeClaudeAccount(account);
|
|
13899
|
+
return status.state === "signed-in" ? status : undefined;
|
|
13900
|
+
}));
|
|
13901
|
+
}
|
|
13902
|
+
async function probeAccount() {
|
|
13903
|
+
if (reuseLiveAccounts) {
|
|
13904
|
+
const live = await liveSignedInAccount();
|
|
13905
|
+
if (live && reuseLiveAccounts)
|
|
13906
|
+
return live;
|
|
13907
|
+
}
|
|
13908
|
+
let probe;
|
|
13909
|
+
try {
|
|
13910
|
+
probe = controlOnlyQuery({
|
|
13911
|
+
cwd: process.env.CWD || process.cwd(),
|
|
13912
|
+
env: { ...process.env },
|
|
13913
|
+
...claudeExecutableOptions()
|
|
13914
|
+
});
|
|
13915
|
+
return normalizeClaudeAccount(await probe.accountInfo());
|
|
13916
|
+
} finally {
|
|
13917
|
+
await Promise.resolve(probe?.close()).catch(() => {
|
|
13918
|
+
return;
|
|
13919
|
+
});
|
|
13920
|
+
}
|
|
13921
|
+
}
|
|
13922
|
+
function readClaudeAuthStatus() {
|
|
13923
|
+
if (authCache && authCache.expiresAt > Date.now()) {
|
|
13924
|
+
return Promise.resolve(withTurnFailure(authCache.value));
|
|
13925
|
+
}
|
|
13926
|
+
if (authRead)
|
|
13927
|
+
return authRead;
|
|
13928
|
+
const generation = authGeneration;
|
|
13929
|
+
const read = probeAccount().then((value) => ({ value, ttl: AUTH_CACHE_TTL_MS }), () => ({
|
|
13930
|
+
value: {
|
|
13931
|
+
state: "unknown",
|
|
13932
|
+
signIn: CLAUDE_SIGN_IN,
|
|
13933
|
+
signOut: false
|
|
13934
|
+
},
|
|
13935
|
+
ttl: FAILED_AUTH_CACHE_TTL_MS
|
|
13936
|
+
})).then(({ value, ttl }) => {
|
|
13937
|
+
if (generation === authGeneration) {
|
|
13938
|
+
authCache = { expiresAt: Date.now() + ttl, value };
|
|
13939
|
+
}
|
|
13940
|
+
return withTurnFailure(value);
|
|
13941
|
+
}).finally(() => {
|
|
13942
|
+
if (authRead !== read)
|
|
13943
|
+
return;
|
|
13944
|
+
authRead = undefined;
|
|
13945
|
+
authReadGeneration = undefined;
|
|
13946
|
+
if (authRefreshPending) {
|
|
13947
|
+
authRefreshPending = false;
|
|
13948
|
+
readClaudeAuthStatus();
|
|
13949
|
+
}
|
|
13950
|
+
});
|
|
13951
|
+
authReadGeneration = generation;
|
|
13952
|
+
authRead = read;
|
|
13953
|
+
return read;
|
|
13954
|
+
}
|
|
13955
|
+
function noteClaudeAuthenticationFailure() {
|
|
13956
|
+
reuseLiveAccounts = false;
|
|
13957
|
+
turnAuthenticationFailedUntil = Date.now() + AUTH_CACHE_TTL_MS;
|
|
13958
|
+
authCache = undefined;
|
|
13959
|
+
if (authRead && authReadGeneration !== authGeneration)
|
|
13960
|
+
authRefreshPending = true;
|
|
13961
|
+
readClaudeAuthStatus();
|
|
13962
|
+
}
|
|
13963
|
+
function noteClaudeAuthenticationWorked() {
|
|
13964
|
+
reuseLiveAccounts = true;
|
|
13965
|
+
authGeneration += 1;
|
|
13966
|
+
authRefreshPending = false;
|
|
13967
|
+
turnAuthenticationFailedUntil = 0;
|
|
13968
|
+
if (authCache?.value.state === "needs-auth")
|
|
13969
|
+
authCache = undefined;
|
|
13970
|
+
}
|
|
13971
|
+
function claudeReadiness() {
|
|
13972
|
+
const cached = authCache;
|
|
13973
|
+
if (cached?.value.state !== "needs-auth")
|
|
13974
|
+
return;
|
|
13975
|
+
if (cached.expiresAt <= Date.now())
|
|
13976
|
+
readClaudeAuthStatus();
|
|
13977
|
+
return {
|
|
13978
|
+
state: "authentication-required",
|
|
13979
|
+
message: CLAUDE_SIGN_IN_REQUIRED_MESSAGE,
|
|
13980
|
+
signIn: CLAUDE_SIGN_IN
|
|
13981
|
+
};
|
|
13982
|
+
}
|
|
13983
|
+
|
|
13984
|
+
// ../../bridges/claude-bridge/src/services/claude-model-catalog.ts
|
|
13985
|
+
var CLAUDE_MODEL_CACHE_TTL_MS = 60 * 60000;
|
|
13986
|
+
var CLAUDE_MODEL_PROBE_TIMEOUT_MS = 25000;
|
|
13987
|
+
var remembered;
|
|
13988
|
+
var liveAnswers = new WeakMap;
|
|
13989
|
+
var invalidLiveAnswers = new WeakSet;
|
|
13990
|
+
var generation = 0;
|
|
13991
|
+
var probe;
|
|
13992
|
+
function invalidateClaudeModelCatalog() {
|
|
13993
|
+
for (const control of liveClaudeControls())
|
|
13994
|
+
invalidLiveAnswers.add(control);
|
|
13995
|
+
remembered = undefined;
|
|
13996
|
+
generation += 1;
|
|
13997
|
+
}
|
|
13998
|
+
function catalogModels(models) {
|
|
13999
|
+
return models.map((model) => ({
|
|
14000
|
+
id: model.value,
|
|
14001
|
+
resolvedModel: model.resolvedModel,
|
|
14002
|
+
name: model.displayName,
|
|
14003
|
+
description: model.description,
|
|
14004
|
+
supportsFastMode: model.supportsFastMode,
|
|
14005
|
+
supportsEffort: model.supportsEffort,
|
|
14006
|
+
supportedEffortLevels: model.supportedEffortLevels,
|
|
14007
|
+
supportsAdaptiveThinking: model.supportsAdaptiveThinking,
|
|
14008
|
+
supportsAutoMode: model.supportsAutoMode
|
|
14009
|
+
}));
|
|
14010
|
+
}
|
|
14011
|
+
async function claudeCliIdentity() {
|
|
14012
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join12(homedir2(), ".claude");
|
|
14013
|
+
const executable = process.env.CLAUDE_CLI_PATH?.trim();
|
|
14014
|
+
const resolved = executable ? Bun.which(executable, { PATH: process.env.PATH }) || executable : undefined;
|
|
14015
|
+
const cwd = process.env.CWD || process.cwd();
|
|
14016
|
+
const paths = [
|
|
14017
|
+
resolved,
|
|
14018
|
+
join12(configDir, "settings.json"),
|
|
14019
|
+
join12(cwd, ".claude/settings.json"),
|
|
14020
|
+
join12(cwd, ".claude/settings.local.json")
|
|
14021
|
+
];
|
|
14022
|
+
const files = await Promise.all(paths.map(async (path) => {
|
|
14023
|
+
const file = path ? await stat5(path).catch(() => {
|
|
14024
|
+
return;
|
|
14025
|
+
}) : undefined;
|
|
14026
|
+
return [path, file?.size, file?.mtimeMs, file?.ctimeMs];
|
|
14027
|
+
}));
|
|
14028
|
+
return JSON.stringify([configDir, cwd, files]);
|
|
14029
|
+
}
|
|
14030
|
+
function accountKeyOf(account) {
|
|
14031
|
+
if (!account || typeof account !== "object")
|
|
14032
|
+
return;
|
|
14033
|
+
return claudeAccountKey(normalizeClaudeAccount(account));
|
|
14034
|
+
}
|
|
14035
|
+
async function rememberModels(models, account, at = generation, cli, expiresAt) {
|
|
14036
|
+
if (!account || typeof account !== "object" || models.length === 0)
|
|
14037
|
+
return;
|
|
14038
|
+
const status = normalizeClaudeAccount(account);
|
|
14039
|
+
if (status.state !== "signed-in")
|
|
14040
|
+
return;
|
|
14041
|
+
const identity = cli ?? await claudeCliIdentity();
|
|
14042
|
+
if (at !== generation)
|
|
14043
|
+
return;
|
|
14044
|
+
remembered = {
|
|
14045
|
+
cli: identity,
|
|
14046
|
+
account: claudeAccountKey(status),
|
|
14047
|
+
models,
|
|
14048
|
+
expiresAt: expiresAt ?? Date.now() + CLAUDE_MODEL_CACHE_TTL_MS
|
|
14049
|
+
};
|
|
14050
|
+
}
|
|
14051
|
+
async function rememberedModels() {
|
|
14052
|
+
const entry = remembered;
|
|
14053
|
+
if (!entry || entry.expiresAt <= Date.now())
|
|
14054
|
+
return;
|
|
14055
|
+
const observed = claudeObservedAccountKey();
|
|
14056
|
+
if (observed !== undefined && observed !== entry.account)
|
|
14057
|
+
return;
|
|
14058
|
+
return entry.cli === await claudeCliIdentity() ? entry.models : undefined;
|
|
14059
|
+
}
|
|
14060
|
+
async function liveModels() {
|
|
14061
|
+
const observed = claudeObservedAccountKey();
|
|
14062
|
+
const at = generation;
|
|
14063
|
+
const cli = await claudeCliIdentity();
|
|
14064
|
+
return readFromLiveClaude(async (control) => {
|
|
14065
|
+
if (invalidLiveAnswers.has(control))
|
|
14066
|
+
return;
|
|
14067
|
+
let identity = liveAnswers.get(control);
|
|
14068
|
+
if (!identity) {
|
|
14069
|
+
identity = { cli, expiresAt: Date.now() + CLAUDE_MODEL_CACHE_TTL_MS };
|
|
14070
|
+
liveAnswers.set(control, identity);
|
|
14071
|
+
}
|
|
14072
|
+
if (identity.cli !== cli || identity.expiresAt <= Date.now())
|
|
14073
|
+
return;
|
|
14074
|
+
const result = await liveInitializationResult(control);
|
|
14075
|
+
if (at !== generation || invalidLiveAnswers.has(control))
|
|
14076
|
+
return;
|
|
14077
|
+
if (!Array.isArray(result?.models) || result.models.length === 0)
|
|
14078
|
+
return;
|
|
14079
|
+
const account = accountKeyOf(result.account);
|
|
14080
|
+
if (observed !== undefined && account !== undefined && account !== observed)
|
|
14081
|
+
return;
|
|
14082
|
+
return { models: result.models, account: result.account, at, ...identity };
|
|
14083
|
+
});
|
|
14084
|
+
}
|
|
14085
|
+
function fallbackCatalog() {
|
|
14086
|
+
return {
|
|
14087
|
+
source: "fallback",
|
|
14088
|
+
models: CLAUDE_FALLBACK_MODEL_CATALOG.map((model) => ({
|
|
14089
|
+
...model,
|
|
14090
|
+
...model.supportedEffortLevels ? { supportedEffortLevels: [...model.supportedEffortLevels] } : {}
|
|
14091
|
+
}))
|
|
14092
|
+
};
|
|
14093
|
+
}
|
|
14094
|
+
async function probeModels(at) {
|
|
14095
|
+
let q;
|
|
14096
|
+
let timer;
|
|
14097
|
+
try {
|
|
14098
|
+
const cwd = process.env.CWD || process.cwd();
|
|
14099
|
+
debugLog("[session-manager] Fetching supported models", { cwd });
|
|
14100
|
+
q = controlOnlyQuery({
|
|
14101
|
+
cwd,
|
|
14102
|
+
env: { ...process.env },
|
|
14103
|
+
...claudeExecutableOptions()
|
|
14104
|
+
});
|
|
14105
|
+
const control = q;
|
|
14106
|
+
const answer = Promise.all([
|
|
14107
|
+
control.supportedModels(),
|
|
14108
|
+
typeof control.accountInfo === "function" ? control.accountInfo().catch(() => {
|
|
14109
|
+
return;
|
|
14110
|
+
}) : undefined
|
|
14111
|
+
]);
|
|
14112
|
+
answer.catch(() => {
|
|
14113
|
+
return;
|
|
14114
|
+
});
|
|
14115
|
+
const [models, account] = await Promise.race([
|
|
14116
|
+
answer,
|
|
14117
|
+
new Promise((_resolve, reject) => {
|
|
14118
|
+
timer = setTimeout(() => reject(new Error("The model probe did not answer in time")), CLAUDE_MODEL_PROBE_TIMEOUT_MS);
|
|
14119
|
+
})
|
|
14120
|
+
]);
|
|
14121
|
+
debugLog("[session-manager] Supported models fetched", { count: models.length });
|
|
14122
|
+
await rememberModels(models, account, at);
|
|
14123
|
+
return { source: "sdk", models: catalogModels(models) };
|
|
14124
|
+
} catch (error) {
|
|
14125
|
+
console.error("[session-manager] Error fetching supported models:", error);
|
|
14126
|
+
return fallbackCatalog();
|
|
14127
|
+
} finally {
|
|
14128
|
+
clearTimeout(timer);
|
|
14129
|
+
if (q?.return) {
|
|
14130
|
+
try {
|
|
14131
|
+
await q.return();
|
|
14132
|
+
} catch (error) {
|
|
14133
|
+
debugLog("[session-manager] Failed to clean up model query:", error);
|
|
14134
|
+
}
|
|
14135
|
+
}
|
|
14136
|
+
}
|
|
14137
|
+
}
|
|
14138
|
+
function sharedProbe() {
|
|
14139
|
+
if (probe?.generation === generation)
|
|
14140
|
+
return probe.read;
|
|
14141
|
+
const read = probeModels(generation).finally(() => {
|
|
14142
|
+
if (probe?.read === read)
|
|
14143
|
+
probe = undefined;
|
|
14144
|
+
});
|
|
14145
|
+
probe = { generation, read };
|
|
14146
|
+
return read;
|
|
14147
|
+
}
|
|
14148
|
+
async function getAvailableModelCatalog() {
|
|
14149
|
+
const live = liveClaudeControls().length ? await liveModels() : undefined;
|
|
14150
|
+
if (live) {
|
|
14151
|
+
debugLog("[session-manager] Supported models read from a running CLI", {
|
|
14152
|
+
count: live.models.length
|
|
14153
|
+
});
|
|
14154
|
+
await rememberModels(live.models, live.account, live.at, live.cli, live.expiresAt);
|
|
14155
|
+
return { source: "sdk", models: catalogModels(live.models) };
|
|
14156
|
+
}
|
|
14157
|
+
const known = await rememberedModels();
|
|
14158
|
+
if (known)
|
|
14159
|
+
return { source: "sdk", models: catalogModels(known) };
|
|
14160
|
+
return sharedProbe();
|
|
14161
|
+
}
|
|
14162
|
+
|
|
13759
14163
|
// ../protocol/src/agent-command-catalogue.ts
|
|
13760
14164
|
var NATIVE_AGENT_COMMAND_CATALOGUE_VERSION = 1;
|
|
13761
14165
|
var COMMAND_CATALOGUE_LIMITS = Object.freeze({
|
|
@@ -14060,7 +14464,7 @@ function idleSteerPromptReply(prompt, agentLabel) {
|
|
|
14060
14464
|
|
|
14061
14465
|
// ../../bridges/claude-bridge/src/services/claude-terminal-commands.ts
|
|
14062
14466
|
import { mkdir as mkdir5, readFile as readFile6, rename as rename5, writeFile as writeFile5 } from "node:fs/promises";
|
|
14063
|
-
import { join as
|
|
14467
|
+
import { join as join13 } from "node:path";
|
|
14064
14468
|
var FILE_NAME = "terminal-slash-commands.json";
|
|
14065
14469
|
var MAX_VERSIONS = 4;
|
|
14066
14470
|
var MAX_NAMES = 512;
|
|
@@ -14071,7 +14475,7 @@ var dirty = false;
|
|
|
14071
14475
|
var entries = [];
|
|
14072
14476
|
var writes = Promise.resolve();
|
|
14073
14477
|
function filePath() {
|
|
14074
|
-
return
|
|
14478
|
+
return join13(claudeOrkestratorDir(), FILE_NAME);
|
|
14075
14479
|
}
|
|
14076
14480
|
function validVersion(value) {
|
|
14077
14481
|
return typeof value === "string" && value.length > 0 && value.length <= MAX_VERSION_LENGTH;
|
|
@@ -14118,89 +14522,31 @@ function recordTerminalSlashCommands(version, commands) {
|
|
|
14118
14522
|
const previous = entries.find((entry) => entry.version === version);
|
|
14119
14523
|
if (previous && JSON.stringify(previous.commands) === JSON.stringify(names) && !dirty)
|
|
14120
14524
|
return;
|
|
14121
|
-
dirty = true;
|
|
14122
|
-
entries = [
|
|
14123
|
-
{ version, commands: names },
|
|
14124
|
-
...entries.filter((entry) => entry.version !== version)
|
|
14125
|
-
].slice(0, MAX_VERSIONS);
|
|
14126
|
-
writes = writes.then(async () => {
|
|
14127
|
-
await load();
|
|
14128
|
-
const directory = claudeOrkestratorDir();
|
|
14129
|
-
await mkdir5(directory, { recursive: true });
|
|
14130
|
-
const target = filePath();
|
|
14131
|
-
const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
14132
|
-
const snapshot = entries;
|
|
14133
|
-
await writeFile5(temporary, `${JSON.stringify({ versions: snapshot })}
|
|
14134
|
-
`, {
|
|
14135
|
-
mode: 384
|
|
14136
|
-
});
|
|
14137
|
-
await rename5(temporary, target);
|
|
14138
|
-
if (entries === snapshot)
|
|
14139
|
-
dirty = false;
|
|
14140
|
-
}).catch(() => {});
|
|
14141
|
-
}
|
|
14142
|
-
|
|
14143
|
-
// ../../bridges/claude-bridge/src/services/session-manager-catalog.ts
|
|
14144
|
-
import { createHash as createHash10 } from "node:crypto";
|
|
14145
|
-
|
|
14146
|
-
// ../../bridges/claude-bridge/src/services/live-claude-control.ts
|
|
14147
|
-
var LIVE_CLAUDE_READ_TIMEOUT_MS = 5000;
|
|
14148
|
-
function readsProbeSettings(settingSources) {
|
|
14149
|
-
if (settingSources === undefined)
|
|
14150
|
-
return false;
|
|
14151
|
-
try {
|
|
14152
|
-
const sources = JSON.parse(settingSources);
|
|
14153
|
-
return Array.isArray(sources) && ["user", "project", "local"].every((source) => sources.includes(source));
|
|
14154
|
-
} catch {
|
|
14155
|
-
return false;
|
|
14156
|
-
}
|
|
14157
|
-
}
|
|
14158
|
-
function liveClaudeControls() {
|
|
14159
|
-
const runtimes = [];
|
|
14160
|
-
for (const session of sessions.values()) {
|
|
14161
|
-
const runtime = session.claudeRuntime;
|
|
14162
|
-
if (runtime?.state !== "open" || runtime.abortController.signal.aborted)
|
|
14163
|
-
continue;
|
|
14164
|
-
if (session.queryControlDraining === runtime.control || session.deleting)
|
|
14165
|
-
continue;
|
|
14166
|
-
if (!readsProbeSettings(runtime.launch.settingSources))
|
|
14167
|
-
continue;
|
|
14168
|
-
runtimes.push(runtime);
|
|
14169
|
-
}
|
|
14170
|
-
return runtimes.sort((left, right) => right.lastFrameAt - left.lastFrameAt).map((runtime) => runtime.control);
|
|
14171
|
-
}
|
|
14172
|
-
async function readFromLiveClaude(read, timeoutMs = LIVE_CLAUDE_READ_TIMEOUT_MS) {
|
|
14173
|
-
for (const control of liveClaudeControls()) {
|
|
14174
|
-
let timer;
|
|
14175
|
-
try {
|
|
14176
|
-
const answer = read(control);
|
|
14177
|
-
if (answer === undefined)
|
|
14178
|
-
continue;
|
|
14179
|
-
answer.catch(() => {
|
|
14180
|
-
return;
|
|
14181
|
-
});
|
|
14182
|
-
const value = await Promise.race([
|
|
14183
|
-
answer,
|
|
14184
|
-
new Promise((resolve) => {
|
|
14185
|
-
timer = setTimeout(() => resolve(undefined), timeoutMs);
|
|
14186
|
-
})
|
|
14187
|
-
]);
|
|
14188
|
-
if (value !== undefined)
|
|
14189
|
-
return value;
|
|
14190
|
-
} catch (error) {
|
|
14191
|
-
debugLog("[live-claude-control] A running CLI could not answer:", error);
|
|
14192
|
-
} finally {
|
|
14193
|
-
clearTimeout(timer);
|
|
14194
|
-
}
|
|
14195
|
-
}
|
|
14196
|
-
return;
|
|
14197
|
-
}
|
|
14198
|
-
function liveInitializationResult(control) {
|
|
14199
|
-
if (typeof control.initializationResult !== "function")
|
|
14200
|
-
return;
|
|
14201
|
-
return control.initializationResult().then((result) => result && typeof result === "object" ? result : undefined);
|
|
14525
|
+
dirty = true;
|
|
14526
|
+
entries = [
|
|
14527
|
+
{ version, commands: names },
|
|
14528
|
+
...entries.filter((entry) => entry.version !== version)
|
|
14529
|
+
].slice(0, MAX_VERSIONS);
|
|
14530
|
+
writes = writes.then(async () => {
|
|
14531
|
+
await load();
|
|
14532
|
+
const directory = claudeOrkestratorDir();
|
|
14533
|
+
await mkdir5(directory, { recursive: true });
|
|
14534
|
+
const target = filePath();
|
|
14535
|
+
const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
14536
|
+
const snapshot = entries;
|
|
14537
|
+
await writeFile5(temporary, `${JSON.stringify({ versions: snapshot })}
|
|
14538
|
+
`, {
|
|
14539
|
+
mode: 384
|
|
14540
|
+
});
|
|
14541
|
+
await rename5(temporary, target);
|
|
14542
|
+
if (entries === snapshot)
|
|
14543
|
+
dirty = false;
|
|
14544
|
+
}).catch(() => {});
|
|
14202
14545
|
}
|
|
14203
14546
|
|
|
14547
|
+
// ../../bridges/claude-bridge/src/services/session-manager-catalog.ts
|
|
14548
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
14549
|
+
|
|
14204
14550
|
// ../protocol/src/secret-redaction.ts
|
|
14205
14551
|
var TEXT_RULES = [
|
|
14206
14552
|
{
|
|
@@ -14237,7 +14583,11 @@ function redactSecrets(value) {
|
|
|
14237
14583
|
}
|
|
14238
14584
|
|
|
14239
14585
|
// ../../bridges/claude-bridge/src/services/mcp-runtime-status.ts
|
|
14240
|
-
|
|
14586
|
+
var FOREIGN_MCP_SOURCES = new Set(["plugin", "sdk", "claudeai"]);
|
|
14587
|
+
function mcpScope(scope, name, source, layers) {
|
|
14588
|
+
const layer = FOREIGN_MCP_SOURCES.has(source ?? "") ? undefined : layers?.get(name);
|
|
14589
|
+
if (layer)
|
|
14590
|
+
return layer;
|
|
14241
14591
|
if (name === "orkestrator")
|
|
14242
14592
|
return "orkestrator";
|
|
14243
14593
|
if (source?.includes("plugin") || scope?.includes("plugin"))
|
|
@@ -14259,145 +14609,16 @@ function mcpRuntimeState(status) {
|
|
|
14259
14609
|
return "unknown";
|
|
14260
14610
|
}
|
|
14261
14611
|
}
|
|
14262
|
-
function initMcpServerStatus(raw) {
|
|
14612
|
+
function initMcpServerStatus(raw, layers) {
|
|
14263
14613
|
const source = typeof raw.source === "string" ? raw.source : undefined;
|
|
14264
14614
|
return {
|
|
14265
14615
|
name: raw.name,
|
|
14266
14616
|
status: mcpRuntimeState(raw.status),
|
|
14267
|
-
...source ? { scope: mcpScope(source, raw.name) } : {},
|
|
14617
|
+
...source || layers?.has(raw.name) ? { scope: mcpScope(source, raw.name, source, layers) } : {},
|
|
14268
14618
|
...typeof raw.error === "string" && raw.error ? { error: raw.error } : {},
|
|
14269
14619
|
...Array.isArray(raw.tools) ? { tools: raw.tools.filter((tool) => typeof tool === "string") } : {}
|
|
14270
14620
|
};
|
|
14271
14621
|
}
|
|
14272
|
-
|
|
14273
|
-
// ../../bridges/claude-bridge/src/services/claude-sign-in.ts
|
|
14274
|
-
var AUTH_CACHE_TTL_MS = 30000;
|
|
14275
|
-
var FAILED_AUTH_CACHE_TTL_MS = 5000;
|
|
14276
|
-
var CLAUDE_SIGN_IN = {
|
|
14277
|
-
kind: "terminal",
|
|
14278
|
-
hint: "Sign in to Claude from the sign-in card in this tab or from Settings → Claude."
|
|
14279
|
-
};
|
|
14280
|
-
var CLAUDE_SIGN_IN_REQUIRED_MESSAGE = "Claude isn't signed in. Sign in to Claude to keep working.";
|
|
14281
|
-
var authCache;
|
|
14282
|
-
var authRead;
|
|
14283
|
-
var authReadGeneration;
|
|
14284
|
-
var authRefreshPending = false;
|
|
14285
|
-
var authGeneration = 0;
|
|
14286
|
-
var turnAuthenticationFailedUntil = 0;
|
|
14287
|
-
var reuseLiveAccounts = true;
|
|
14288
|
-
function withTurnFailure(value) {
|
|
14289
|
-
return Date.now() < turnAuthenticationFailedUntil && value.state === "signed-in" ? { ...value, state: "expired" } : value;
|
|
14290
|
-
}
|
|
14291
|
-
function presentSource(value) {
|
|
14292
|
-
return value && value !== "none" ? value : undefined;
|
|
14293
|
-
}
|
|
14294
|
-
function normalizeClaudeAccount(account) {
|
|
14295
|
-
const source = presentSource(account.apiKeySource) ?? presentSource(account.tokenSource);
|
|
14296
|
-
const externalProvider = account.apiProvider && account.apiProvider !== "firstParty" ? account.apiProvider : undefined;
|
|
14297
|
-
const signedIn = Boolean(source || account.subscriptionType || account.organization || externalProvider);
|
|
14298
|
-
const label = account.organization || account.subscriptionType || externalProvider;
|
|
14299
|
-
return {
|
|
14300
|
-
state: signedIn ? "signed-in" : "needs-auth",
|
|
14301
|
-
...label ? {
|
|
14302
|
-
account: {
|
|
14303
|
-
label,
|
|
14304
|
-
...account.subscriptionType ? { plan: account.subscriptionType } : {}
|
|
14305
|
-
}
|
|
14306
|
-
} : {},
|
|
14307
|
-
signIn: CLAUDE_SIGN_IN,
|
|
14308
|
-
signOut: false
|
|
14309
|
-
};
|
|
14310
|
-
}
|
|
14311
|
-
function liveSignedInAccount() {
|
|
14312
|
-
return readFromLiveClaude((control) => liveInitializationResult(control)?.then((result) => {
|
|
14313
|
-
const account = result?.account;
|
|
14314
|
-
if (!account || typeof account !== "object")
|
|
14315
|
-
return;
|
|
14316
|
-
const status = normalizeClaudeAccount(account);
|
|
14317
|
-
return status.state === "signed-in" ? status : undefined;
|
|
14318
|
-
}));
|
|
14319
|
-
}
|
|
14320
|
-
async function probeAccount() {
|
|
14321
|
-
if (reuseLiveAccounts) {
|
|
14322
|
-
const live = await liveSignedInAccount();
|
|
14323
|
-
if (live && reuseLiveAccounts)
|
|
14324
|
-
return live;
|
|
14325
|
-
}
|
|
14326
|
-
let probe;
|
|
14327
|
-
try {
|
|
14328
|
-
probe = controlOnlyQuery({
|
|
14329
|
-
cwd: process.env.CWD || process.cwd(),
|
|
14330
|
-
env: { ...process.env },
|
|
14331
|
-
...claudeExecutableOptions()
|
|
14332
|
-
});
|
|
14333
|
-
return normalizeClaudeAccount(await probe.accountInfo());
|
|
14334
|
-
} finally {
|
|
14335
|
-
await Promise.resolve(probe?.close()).catch(() => {
|
|
14336
|
-
return;
|
|
14337
|
-
});
|
|
14338
|
-
}
|
|
14339
|
-
}
|
|
14340
|
-
function readClaudeAuthStatus() {
|
|
14341
|
-
if (authCache && authCache.expiresAt > Date.now()) {
|
|
14342
|
-
return Promise.resolve(withTurnFailure(authCache.value));
|
|
14343
|
-
}
|
|
14344
|
-
if (authRead)
|
|
14345
|
-
return authRead;
|
|
14346
|
-
const generation = authGeneration;
|
|
14347
|
-
const read = probeAccount().then((value) => ({ value, ttl: AUTH_CACHE_TTL_MS }), () => ({
|
|
14348
|
-
value: {
|
|
14349
|
-
state: "unknown",
|
|
14350
|
-
signIn: CLAUDE_SIGN_IN,
|
|
14351
|
-
signOut: false
|
|
14352
|
-
},
|
|
14353
|
-
ttl: FAILED_AUTH_CACHE_TTL_MS
|
|
14354
|
-
})).then(({ value, ttl }) => {
|
|
14355
|
-
if (generation === authGeneration) {
|
|
14356
|
-
authCache = { expiresAt: Date.now() + ttl, value };
|
|
14357
|
-
}
|
|
14358
|
-
return withTurnFailure(value);
|
|
14359
|
-
}).finally(() => {
|
|
14360
|
-
if (authRead !== read)
|
|
14361
|
-
return;
|
|
14362
|
-
authRead = undefined;
|
|
14363
|
-
authReadGeneration = undefined;
|
|
14364
|
-
if (authRefreshPending) {
|
|
14365
|
-
authRefreshPending = false;
|
|
14366
|
-
readClaudeAuthStatus();
|
|
14367
|
-
}
|
|
14368
|
-
});
|
|
14369
|
-
authReadGeneration = generation;
|
|
14370
|
-
authRead = read;
|
|
14371
|
-
return read;
|
|
14372
|
-
}
|
|
14373
|
-
function noteClaudeAuthenticationFailure() {
|
|
14374
|
-
reuseLiveAccounts = false;
|
|
14375
|
-
turnAuthenticationFailedUntil = Date.now() + AUTH_CACHE_TTL_MS;
|
|
14376
|
-
authCache = undefined;
|
|
14377
|
-
if (authRead && authReadGeneration !== authGeneration)
|
|
14378
|
-
authRefreshPending = true;
|
|
14379
|
-
readClaudeAuthStatus();
|
|
14380
|
-
}
|
|
14381
|
-
function noteClaudeAuthenticationWorked() {
|
|
14382
|
-
reuseLiveAccounts = true;
|
|
14383
|
-
authGeneration += 1;
|
|
14384
|
-
authRefreshPending = false;
|
|
14385
|
-
turnAuthenticationFailedUntil = 0;
|
|
14386
|
-
if (authCache?.value.state === "needs-auth")
|
|
14387
|
-
authCache = undefined;
|
|
14388
|
-
}
|
|
14389
|
-
function claudeReadiness() {
|
|
14390
|
-
const cached = authCache;
|
|
14391
|
-
if (cached?.value.state !== "needs-auth")
|
|
14392
|
-
return;
|
|
14393
|
-
if (cached.expiresAt <= Date.now())
|
|
14394
|
-
readClaudeAuthStatus();
|
|
14395
|
-
return {
|
|
14396
|
-
state: "authentication-required",
|
|
14397
|
-
message: CLAUDE_SIGN_IN_REQUIRED_MESSAGE,
|
|
14398
|
-
signIn: CLAUDE_SIGN_IN
|
|
14399
|
-
};
|
|
14400
|
-
}
|
|
14401
14622
|
// ../../bridges/claude-bridge/src/services/session-manager-catalog.ts
|
|
14402
14623
|
function readableControl(session) {
|
|
14403
14624
|
if (!session)
|
|
@@ -14548,7 +14769,7 @@ function mcpTransport(status) {
|
|
|
14548
14769
|
function mcpError(error) {
|
|
14549
14770
|
return redactSecrets(error).slice(0, 2000);
|
|
14550
14771
|
}
|
|
14551
|
-
function normalizeMcp(status) {
|
|
14772
|
+
function normalizeMcp(status, layers) {
|
|
14552
14773
|
const mappedStatus = status.status === "pending" ? "connecting" : status.status;
|
|
14553
14774
|
const tools = (status.tools ?? []).map((tool) => tool.name).filter(Boolean).slice(0, 256);
|
|
14554
14775
|
const actions = status.status === "disabled" ? ["enable"] : status.status === "needs-auth" ? ["sign-in", "reconnect", "disable"] : ["reconnect", "disable"];
|
|
@@ -14557,7 +14778,7 @@ function normalizeMcp(status) {
|
|
|
14557
14778
|
id: status.name,
|
|
14558
14779
|
name: status.serverInfo?.name || status.name,
|
|
14559
14780
|
status: mappedStatus,
|
|
14560
|
-
scope: mcpScope(status.scope, status.name, status.source),
|
|
14781
|
+
scope: mcpScope(status.scope, status.name, status.source, layers),
|
|
14561
14782
|
...transport ? { transport } : {},
|
|
14562
14783
|
toolCount: tools.length,
|
|
14563
14784
|
...tools.length ? { tools } : {},
|
|
@@ -14565,18 +14786,11 @@ function normalizeMcp(status) {
|
|
|
14565
14786
|
actions
|
|
14566
14787
|
};
|
|
14567
14788
|
}
|
|
14568
|
-
|
|
14569
|
-
|
|
14570
|
-
|
|
14571
|
-
|
|
14572
|
-
|
|
14573
|
-
if (control?.mcpServerStatus) {
|
|
14574
|
-
try {
|
|
14575
|
-
session.mcpInventory = (await control.mcpServerStatus()).slice(0, 128).map(normalizeMcp);
|
|
14576
|
-
} catch (error) {
|
|
14577
|
-
rethrowUnlessClosedTransport(error);
|
|
14578
|
-
}
|
|
14579
|
-
} else if (!session.mcpInventory && session.initData?.mcpServers) {
|
|
14789
|
+
function liveMcpInventory(session, statuses) {
|
|
14790
|
+
return statuses.slice(0, 128).map((status) => normalizeMcp(status, session.mcpServerLayers));
|
|
14791
|
+
}
|
|
14792
|
+
function retainedMcpInventory(session) {
|
|
14793
|
+
if (!session.mcpInventory && session.initData?.mcpServers) {
|
|
14580
14794
|
session.mcpInventory = session.initData.mcpServers.slice(0, 128).map((server) => ({
|
|
14581
14795
|
id: server.name,
|
|
14582
14796
|
name: server.name,
|
|
@@ -14588,7 +14802,34 @@ async function readSessionMcpServers(sessionId) {
|
|
|
14588
14802
|
...server.error ? { error: mcpError(server.error) } : {}
|
|
14589
14803
|
}));
|
|
14590
14804
|
}
|
|
14591
|
-
return session.mcpInventory
|
|
14805
|
+
return session.mcpInventory;
|
|
14806
|
+
}
|
|
14807
|
+
function applyProbeMcpStatus(session, serverId, statuses) {
|
|
14808
|
+
const status = statuses.find((candidate) => candidate.name === serverId);
|
|
14809
|
+
if (!status)
|
|
14810
|
+
return;
|
|
14811
|
+
const inventory = retainedMcpInventory(session);
|
|
14812
|
+
session.mcpInventory = inventory?.map((row) => {
|
|
14813
|
+
if (row.id !== serverId)
|
|
14814
|
+
return row;
|
|
14815
|
+
const updated = normalizeMcp(status, session.mcpServerLayers);
|
|
14816
|
+
return { ...updated, scope: row.scope ?? updated.scope };
|
|
14817
|
+
});
|
|
14818
|
+
}
|
|
14819
|
+
async function readSessionMcpServers(sessionId) {
|
|
14820
|
+
const session = sessions.get(sessionId);
|
|
14821
|
+
if (!session)
|
|
14822
|
+
return [];
|
|
14823
|
+
const control = readableControl(session);
|
|
14824
|
+
if (control?.mcpServerStatus) {
|
|
14825
|
+
try {
|
|
14826
|
+
session.mcpInventory = liveMcpInventory(session, await control.mcpServerStatus());
|
|
14827
|
+
} catch (error) {
|
|
14828
|
+
rethrowUnlessClosedTransport(error);
|
|
14829
|
+
}
|
|
14830
|
+
return session.mcpInventory ?? [];
|
|
14831
|
+
}
|
|
14832
|
+
return retainedMcpInventory(session) ?? [];
|
|
14592
14833
|
}
|
|
14593
14834
|
async function performSessionMcpAction(sessionId, serverId, action) {
|
|
14594
14835
|
const session = sessions.get(sessionId);
|
|
@@ -14611,7 +14852,11 @@ async function performSessionMcpAction(sessionId, serverId, action) {
|
|
|
14611
14852
|
await control.reconnectMcpServer?.(serverId);
|
|
14612
14853
|
}
|
|
14613
14854
|
if (control.mcpServerStatus) {
|
|
14614
|
-
|
|
14855
|
+
const statuses = await control.mcpServerStatus();
|
|
14856
|
+
if (probe)
|
|
14857
|
+
applyProbeMcpStatus(session, serverId, statuses);
|
|
14858
|
+
else
|
|
14859
|
+
session.mcpInventory = liveMcpInventory(session, statuses);
|
|
14615
14860
|
}
|
|
14616
14861
|
return {};
|
|
14617
14862
|
} finally {
|
|
@@ -15232,6 +15477,7 @@ async function refreshClaudeCommandCatalogue(sessionId) {
|
|
|
15232
15477
|
}
|
|
15233
15478
|
}
|
|
15234
15479
|
async function refreshClaudeCatalogs() {
|
|
15480
|
+
invalidateClaudeModelCatalog();
|
|
15235
15481
|
const sessionIds = Array.from(sessions.keys()).slice(0, 128);
|
|
15236
15482
|
let next = 0;
|
|
15237
15483
|
await Promise.allSettled(Array.from({ length: Math.min(8, sessionIds.length) }, async () => {
|
|
@@ -15332,7 +15578,6 @@ function createClaudeRuntimeMcp(servers, declared, accountOnly = []) {
|
|
|
15332
15578
|
accountOnly: loadedOnlyByAccount
|
|
15333
15579
|
};
|
|
15334
15580
|
}
|
|
15335
|
-
var FOREIGN_SOURCES = new Set(["plugin", "sdk", "claudeai"]);
|
|
15336
15581
|
var MAX_REPORTED_STALE_SERVERS = 256;
|
|
15337
15582
|
function conflict(message) {
|
|
15338
15583
|
return sessionOperationError("conflict", message);
|
|
@@ -15387,7 +15632,7 @@ async function syncClaudeRuntimeMcp(runtime, next) {
|
|
|
15387
15632
|
runtime.mcpServers = "";
|
|
15388
15633
|
throw conflict("Claude required MCP server is not connected; retry the prompt");
|
|
15389
15634
|
}
|
|
15390
|
-
const stillRuns = (name) => statuses ? statuses.some((server) => server.name === name && server.status !== "disabled" && !
|
|
15635
|
+
const stillRuns = (name) => statuses ? statuses.some((server) => server.name === name && server.status !== "disabled" && !FOREIGN_MCP_SOURCES.has(server.source ?? "")) : !removed?.has(name);
|
|
15391
15636
|
for (const name of Array.from(mcp.stale)) {
|
|
15392
15637
|
if (next.names.has(name) || !stillRuns(name)) {
|
|
15393
15638
|
mcp.stale.delete(name);
|
|
@@ -15686,6 +15931,60 @@ function claudeArtifactServerTools(servers) {
|
|
|
15686
15931
|
return ARTIFACT_TOOL_NAMES.map((name) => `mcp__${ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME}__${name}`);
|
|
15687
15932
|
}
|
|
15688
15933
|
|
|
15934
|
+
// ../protocol/src/node/repository-instructions.ts
|
|
15935
|
+
import { open as open3, realpath as realpath3 } from "node:fs/promises";
|
|
15936
|
+
import { join as join14, relative as relative2, isAbsolute as isAbsolute4 } from "node:path";
|
|
15937
|
+
|
|
15938
|
+
// ../protocol/src/agent-system-instructions.ts
|
|
15939
|
+
var AGENT_IMAGE_PREVIEW_INSTRUCTION = "Orkestrator renders Markdown images inline in the transcript. When you show the user an image in your reply (a screenshot, rendered preview, or chart) using Markdown image syntax, reference it by its absolute path. In a managed worktree or container environment, save the file inside the working directory, preferably in a git-ignored folder so preview files stay out of the change set. Local image previews are limited to Orkestrator-managed workspace storage or the container's /workspace. Project-home checkouts are excluded from host preview reads, even when they are the working directory, so images saved there cannot be previewed from a local Markdown path. Paths outside previewable storage, such as /tmp, also show a placeholder.";
|
|
15940
|
+
var AGENT_DOCUMENT_INSTRUCTION = "When the user asks for a document (a report, design doc, plan, analysis, guide, or other writing to keep), prefer writing it as a Markdown file in a `docs/` folder at the root of the working directory, and tell the user the file's path. Project instructions (such as AGENTS.md or CLAUDE.md), local skills, and the user's own request take priority over this default when they say where or how to write documents.";
|
|
15941
|
+
var GENERAL_AGENT_INSTRUCTIONS = [
|
|
15942
|
+
AGENT_IMAGE_PREVIEW_INSTRUCTION,
|
|
15943
|
+
AGENT_DOCUMENT_INSTRUCTION
|
|
15944
|
+
];
|
|
15945
|
+
function agentSystemInstructions(providerSpecific = []) {
|
|
15946
|
+
return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
|
|
15947
|
+
|
|
15948
|
+
`);
|
|
15949
|
+
}
|
|
15950
|
+
var REPOSITORY_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
15951
|
+
function repositoryInstructionsBlock(path, content, truncated) {
|
|
15952
|
+
return [
|
|
15953
|
+
`# Repository instructions (${REPOSITORY_INSTRUCTIONS_FILE})`,
|
|
15954
|
+
`This session does not load the repository's ${REPOSITORY_INSTRUCTIONS_FILE} on its own, so Orkestrator includes it here. Follow it as project instructions. Contents of ${path}:`,
|
|
15955
|
+
content.trimEnd(),
|
|
15956
|
+
...truncated ? [
|
|
15957
|
+
`[${REPOSITORY_INSTRUCTIONS_FILE} is longer than this session can hold, so it is cut here. Read the rest from ${path} before relying on anything it may say.]`
|
|
15958
|
+
] : []
|
|
15959
|
+
].join(`
|
|
15960
|
+
|
|
15961
|
+
`);
|
|
15962
|
+
}
|
|
15963
|
+
|
|
15964
|
+
// ../protocol/src/node/repository-instructions.ts
|
|
15965
|
+
var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 256 * 1024;
|
|
15966
|
+
async function readRepositoryInstructions(cwd, maxBytes = MAX_REPOSITORY_INSTRUCTIONS_BYTES) {
|
|
15967
|
+
const path = join14(cwd, REPOSITORY_INSTRUCTIONS_FILE);
|
|
15968
|
+
try {
|
|
15969
|
+
const [root, target] = await Promise.all([realpath3(cwd), realpath3(path)]);
|
|
15970
|
+
const inside = relative2(root, target);
|
|
15971
|
+
if (!inside || inside.startsWith("..") || isAbsolute4(inside))
|
|
15972
|
+
return;
|
|
15973
|
+
const handle = await open3(target, "r");
|
|
15974
|
+
try {
|
|
15975
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
15976
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes + 1, 0);
|
|
15977
|
+
const truncated = bytesRead > maxBytes;
|
|
15978
|
+
const text = new TextDecoder().decode(buffer.subarray(0, Math.min(bytesRead, maxBytes))).replace(/�$/, "");
|
|
15979
|
+
return text.trim() ? repositoryInstructionsBlock(path, text, truncated) : undefined;
|
|
15980
|
+
} finally {
|
|
15981
|
+
await handle.close();
|
|
15982
|
+
}
|
|
15983
|
+
} catch {
|
|
15984
|
+
return;
|
|
15985
|
+
}
|
|
15986
|
+
}
|
|
15987
|
+
|
|
15689
15988
|
// ../protocol/src/claude-background-commands.ts
|
|
15690
15989
|
var CLAUDE_BASH_MAX_TIMEOUT_ENV = "BASH_MAX_TIMEOUT_MS";
|
|
15691
15990
|
var CLAUDE_BASH_DEFAULT_TIMEOUT_ENV = "BASH_DEFAULT_TIMEOUT_MS";
|
|
@@ -15734,6 +16033,17 @@ function backgroundCommandInstruction(env) {
|
|
|
15734
16033
|
return `Background shell commands in this session are stopped when they reach their timeout (${defaultText} by default, ${maxText} at most). Pass a longer \`timeout\` when a background command needs more than ${defaultText}. For a dev server or watcher that must keep running longer than ${maxText}, tell the user to start it in an Orkestrator terminal tab instead of running it yourself.`;
|
|
15735
16034
|
}
|
|
15736
16035
|
|
|
16036
|
+
// ../../bridges/claude-bridge/src/services/system-prompt-append.ts
|
|
16037
|
+
var READ_BEFORE_EDIT_INSTRUCTION = "IMPORTANT: You MUST read a file before editing or writing to it. The Edit and Write tools will fail if you have not first used the Read tool to read the file in this conversation. Always read files before attempting to modify them.";
|
|
16038
|
+
var CLAUDE_DOCS_INSTRUCTION = "Write a requested document as that Markdown file rather than as a Claude Doc or claude.ai artifact: Orkestrator cannot open those, so the user would never see it.";
|
|
16039
|
+
function claudeSystemPromptAppend(env) {
|
|
16040
|
+
return agentSystemInstructions([
|
|
16041
|
+
CLAUDE_DOCS_INSTRUCTION,
|
|
16042
|
+
READ_BEFORE_EDIT_INSTRUCTION,
|
|
16043
|
+
backgroundCommandInstruction(env)
|
|
16044
|
+
]);
|
|
16045
|
+
}
|
|
16046
|
+
|
|
15737
16047
|
// ../protocol/src/agent-interaction-deadline.ts
|
|
15738
16048
|
var SYSTEM_CLOCK = {
|
|
15739
16049
|
now: () => Date.now(),
|
|
@@ -16076,61 +16386,6 @@ function getSessionInitData(sessionId) {
|
|
|
16076
16386
|
const session = sessions.get(sessionId);
|
|
16077
16387
|
return session?.initData;
|
|
16078
16388
|
}
|
|
16079
|
-
function catalogModels(models) {
|
|
16080
|
-
return models.map((model) => ({
|
|
16081
|
-
id: model.value,
|
|
16082
|
-
resolvedModel: model.resolvedModel,
|
|
16083
|
-
name: model.displayName,
|
|
16084
|
-
description: model.description,
|
|
16085
|
-
supportsFastMode: model.supportsFastMode,
|
|
16086
|
-
supportsEffort: model.supportsEffort,
|
|
16087
|
-
supportedEffortLevels: model.supportedEffortLevels,
|
|
16088
|
-
supportsAdaptiveThinking: model.supportsAdaptiveThinking,
|
|
16089
|
-
supportsAutoMode: model.supportsAutoMode
|
|
16090
|
-
}));
|
|
16091
|
-
}
|
|
16092
|
-
function liveModels() {
|
|
16093
|
-
return readFromLiveClaude((control) => liveInitializationResult(control)?.then((result) => Array.isArray(result?.models) && result.models.length > 0 ? result.models : undefined));
|
|
16094
|
-
}
|
|
16095
|
-
async function getAvailableModelCatalog() {
|
|
16096
|
-
const live = await liveModels();
|
|
16097
|
-
if (live) {
|
|
16098
|
-
debugLog("[session-manager] Supported models read from a running CLI", {
|
|
16099
|
-
count: live.length
|
|
16100
|
-
});
|
|
16101
|
-
return { source: "sdk", models: catalogModels(live) };
|
|
16102
|
-
}
|
|
16103
|
-
let q;
|
|
16104
|
-
try {
|
|
16105
|
-
const cwd = process.env.CWD || process.cwd();
|
|
16106
|
-
debugLog("[session-manager] Fetching supported models", { cwd });
|
|
16107
|
-
q = controlOnlyQuery({
|
|
16108
|
-
cwd,
|
|
16109
|
-
env: { ...process.env },
|
|
16110
|
-
...claudeExecutableOptions()
|
|
16111
|
-
});
|
|
16112
|
-
const models = await q.supportedModels();
|
|
16113
|
-
debugLog("[session-manager] Supported models fetched", { count: models.length });
|
|
16114
|
-
return { source: "sdk", models: catalogModels(models) };
|
|
16115
|
-
} catch (error) {
|
|
16116
|
-
console.error("[session-manager] Error fetching supported models:", error);
|
|
16117
|
-
return {
|
|
16118
|
-
source: "fallback",
|
|
16119
|
-
models: CLAUDE_FALLBACK_MODEL_CATALOG.map((model) => ({
|
|
16120
|
-
...model,
|
|
16121
|
-
...model.supportedEffortLevels ? { supportedEffortLevels: [...model.supportedEffortLevels] } : {}
|
|
16122
|
-
}))
|
|
16123
|
-
};
|
|
16124
|
-
} finally {
|
|
16125
|
-
if (q?.return) {
|
|
16126
|
-
try {
|
|
16127
|
-
await q.return();
|
|
16128
|
-
} catch (error) {
|
|
16129
|
-
debugLog("[session-manager] Failed to clean up model query:", error);
|
|
16130
|
-
}
|
|
16131
|
-
}
|
|
16132
|
-
}
|
|
16133
|
-
}
|
|
16134
16389
|
async function getClaudeRuntimeVersions() {
|
|
16135
16390
|
let sdkVersion;
|
|
16136
16391
|
let bundledCliVersion;
|
|
@@ -16568,9 +16823,15 @@ async function resolveQueryPlan(turn, sdkTextPrompt, testHooks) {
|
|
|
16568
16823
|
};
|
|
16569
16824
|
const settingSources = claudeTurnSettingSources(session, options);
|
|
16570
16825
|
session.commandDiscoveryInputs.includeLocalSettings = settingSources.includes("local");
|
|
16826
|
+
const repositoryInstructions = options?.readOnly || policy?.id === "coordinator-read-only" || settingSources.includes("project") ? undefined : await readRepositoryInstructions(cwd);
|
|
16571
16827
|
const readOnlyCommandSandbox = isCoordinatorReadOnlyPolicy(policy) ? claudeReadOnlyCommandSandbox() : undefined;
|
|
16572
16828
|
const [
|
|
16573
|
-
{
|
|
16829
|
+
{
|
|
16830
|
+
servers: mcpServers,
|
|
16831
|
+
names: mcpServerNames,
|
|
16832
|
+
layers: mcpServerLayers,
|
|
16833
|
+
revision: mcpConfigRevision
|
|
16834
|
+
},
|
|
16574
16835
|
{ plugins, coordinatorSkills }
|
|
16575
16836
|
] = await Promise.all([
|
|
16576
16837
|
getMcpRuntimeConfig(cwd, process.env, options?.agentMcp, mcpSourceScopeForPolicy(policy), userMcpServerFilter(policy)),
|
|
@@ -16645,11 +16906,13 @@ async function resolveQueryPlan(turn, sdkTextPrompt, testHooks) {
|
|
|
16645
16906
|
const mcpServersKey = createHash11("sha256").update(JSON.stringify(mcpServers)).digest("hex");
|
|
16646
16907
|
return {
|
|
16647
16908
|
settingSources,
|
|
16909
|
+
repositoryInstructions,
|
|
16648
16910
|
cwd,
|
|
16649
16911
|
policy,
|
|
16650
16912
|
effortLevel,
|
|
16651
16913
|
mcpServers,
|
|
16652
16914
|
mcpServerNames,
|
|
16915
|
+
mcpServerLayers,
|
|
16653
16916
|
accountOnlyMcpServers,
|
|
16654
16917
|
mcpConfigRevision,
|
|
16655
16918
|
plugins,
|
|
@@ -16671,6 +16934,7 @@ async function resolveQueryPlan(turn, sdkTextPrompt, testHooks) {
|
|
|
16671
16934
|
}
|
|
16672
16935
|
function recordMcpConfigRevision(session, plan, mcp) {
|
|
16673
16936
|
const { mcpConfigRevision } = plan;
|
|
16937
|
+
session.mcpServerLayers = plan.mcpServerLayers;
|
|
16674
16938
|
if (!mcpConfigRevision)
|
|
16675
16939
|
return;
|
|
16676
16940
|
const staleServers = reportedStaleServers(mcp);
|
|
@@ -16753,11 +17017,9 @@ function claudeQueryOptions(turn, plan, turnFor, mcp) {
|
|
|
16753
17017
|
systemPrompt: {
|
|
16754
17018
|
type: "preset",
|
|
16755
17019
|
preset: "claude_code",
|
|
16756
|
-
append:
|
|
16757
|
-
"
|
|
16758
|
-
|
|
16759
|
-
"When the user asks for a document (a report, design doc, plan, analysis, guide, or other writing to keep), prefer writing it as a Markdown file in a `docs/` folder at the root of the working directory over creating a Claude Doc or claude.ai artifact, and tell the user the file's path. Project instructions (such as CLAUDE.md or AGENTS.md), local skills, and the user's own request take priority over this default when they say where or how to write documents.",
|
|
16760
|
-
"When you show the user an image in your reply (a screenshot, rendered preview, or chart) using Markdown image syntax, reference it by its absolute path. In a managed worktree or container environment, save the file inside the working directory, preferably in a git-ignored folder so preview files stay out of the change set. Local image previews are limited to Orkestrator-managed workspace storage or the container's /workspace. Project-home checkouts are excluded from host preview reads, even when they are the working directory, so images saved there cannot be previewed from a local Markdown path. Paths outside previewable storage, such as /tmp, also show a placeholder."
|
|
17020
|
+
append: [
|
|
17021
|
+
coordinatorReadOnly ? "You are a read-only coordinator. Inspect the checkout with reading tools and use the trusted research tools available for this turn. Delegate all mutations and artifact creation to worker environments through Orkestrator tools. Present findings directly in your response." : claudeSystemPromptAppend(queryEnvironment),
|
|
17022
|
+
...plan.repositoryInstructions ? [plan.repositoryInstructions] : []
|
|
16761
17023
|
].join(`
|
|
16762
17024
|
|
|
16763
17025
|
`)
|
|
@@ -17092,7 +17354,7 @@ async function handleInitMessage(turn, message) {
|
|
|
17092
17354
|
}
|
|
17093
17355
|
const allMcpServers = initMsg.mcp_servers || [];
|
|
17094
17356
|
const regularMcpServers = allMcpServers.filter((s) => !s.name?.startsWith("plugin:"));
|
|
17095
|
-
const mcpServerStatuses = regularMcpServers.map(initMcpServerStatus);
|
|
17357
|
+
const mcpServerStatuses = regularMcpServers.map((server) => initMcpServerStatus(server, session.mcpServerLayers));
|
|
17096
17358
|
const { statuses: pluginStatuses, errors: pluginErrors } = pluginStatusesFromInit(initMsg);
|
|
17097
17359
|
const previousPluginErrors = new Set(session.pluginErrorSignatures);
|
|
17098
17360
|
session.pluginErrorSignatures = pluginErrors.map(({ plugin, type, message, path, loaded }) => JSON.stringify([plugin, type, message, path, loaded]));
|
|
@@ -17279,6 +17541,28 @@ var LEAF_MESSAGE_HANDLERS = {
|
|
|
17279
17541
|
conversation_reset: handleConversationReset
|
|
17280
17542
|
};
|
|
17281
17543
|
|
|
17544
|
+
// ../protocol/src/agent-usage-limits.ts
|
|
17545
|
+
var USAGE_LIMIT_PATTERNS = [
|
|
17546
|
+
/usage[\s_-]?limit/i,
|
|
17547
|
+
/hit your (?:usage |session |weekly )?limit/i,
|
|
17548
|
+
/\b(?:5|five)[\s-]?hour limit\b/i,
|
|
17549
|
+
/\bweekly limit\b/i,
|
|
17550
|
+
/\b(?:usage|quota|credits?|allowance) (?:is |has been )?(?:exhausted|exceeded|used up)\b/i,
|
|
17551
|
+
/\bquota exceeded\b|\binsufficient_quota\b|\bout of (?:credits|usage)\b/i,
|
|
17552
|
+
/\bUSAGE_EXHAUSTED\b|\bPAYMENT_REQUIRED\b/,
|
|
17553
|
+
/\b(?:usage|plan|session|daily|weekly|monthly|go) limit reached\b/i
|
|
17554
|
+
];
|
|
17555
|
+
function classifyUsageLimitError(text) {
|
|
17556
|
+
if (typeof text !== "string" || !text.trim())
|
|
17557
|
+
return null;
|
|
17558
|
+
const bounded = text.slice(0, 2000);
|
|
17559
|
+
if (!USAGE_LIMIT_PATTERNS.some((pattern) => pattern.test(bounded)))
|
|
17560
|
+
return null;
|
|
17561
|
+
const reset = bounded.match(/\b(?:resets?|try again)(?:\s+(?:at|in|after))?\s+([^.\n·]{1,60})/i);
|
|
17562
|
+
const hint = reset?.[1]?.trim();
|
|
17563
|
+
return hint ? { resetHint: hint } : {};
|
|
17564
|
+
}
|
|
17565
|
+
|
|
17282
17566
|
// ../../bridges/claude-bridge/src/services/session-manager-prompt-handlers/result.ts
|
|
17283
17567
|
function claudeStartupFailureMessage(reason) {
|
|
17284
17568
|
switch (reason) {
|
|
@@ -17324,6 +17608,7 @@ function claudeStartupFailureMessage(reason) {
|
|
|
17324
17608
|
return "Claude requires a working command sandbox, and it cannot run here (for example, bubblewrap is missing or the platform is unsupported). Make the sandbox available or have the requirement changed, then retry.";
|
|
17325
17609
|
}
|
|
17326
17610
|
}
|
|
17611
|
+
var MAX_USAGE_LIMIT_ERROR_CHARS = 500;
|
|
17327
17612
|
var STOPPED_TERMINAL_REASONS = new Set([
|
|
17328
17613
|
"aborted_streaming",
|
|
17329
17614
|
"aborted_tools"
|
|
@@ -17456,8 +17741,9 @@ async function handleResultMessage(turn, message) {
|
|
|
17456
17741
|
isError: resultIsError
|
|
17457
17742
|
});
|
|
17458
17743
|
const startupFailure = resultMsg.startup_failure_reason ? claudeStartupFailureMessage(resultMsg.startup_failure_reason) : undefined;
|
|
17744
|
+
const usageLimit = resultMsg.subtype === "success" && classifyUsageLimitError(resultMsg.result) ? resultMsg.result.trim().slice(0, MAX_USAGE_LIMIT_ERROR_CHARS) : undefined;
|
|
17459
17745
|
const resultError = startupFailure || resultMsg.errors?.filter(Boolean).join(`
|
|
17460
|
-
`) || (resultMsg.subtype === "success" ? "Claude ended the turn on an API error." : `Claude query failed: ${resultMsg.subtype}`);
|
|
17746
|
+
`) || usageLimit || (resultMsg.subtype === "success" ? "Claude ended the turn on an API error." : `Claude query failed: ${resultMsg.subtype}`);
|
|
17461
17747
|
if (startupFailure) {
|
|
17462
17748
|
appendTranscriptNotice(session, sessionId, (event) => eventEmitter.emit(event), {
|
|
17463
17749
|
type: "status",
|
|
@@ -18389,7 +18675,8 @@ async function prepareJoin(turn, plan, running) {
|
|
|
18389
18675
|
const required = mcpServers[AGENT_MCP_SERVER_NAME] ? [AGENT_MCP_SERVER_NAME, ...options?.agentMcp?.design ? ["orkestrator-design"] : []] : [];
|
|
18390
18676
|
await assertClaudeRuntimeAccepts(session, options, {
|
|
18391
18677
|
...claudeLaunchResourceProfile(plugins, queryEnvironment),
|
|
18392
|
-
settingSources: JSON.stringify(plan.settingSources)
|
|
18678
|
+
settingSources: JSON.stringify(plan.settingSources),
|
|
18679
|
+
repositoryInstructions: plan.repositoryInstructions ?? ""
|
|
18393
18680
|
}, plan.readOnlyCommandSandbox);
|
|
18394
18681
|
session.queryControl = running.control;
|
|
18395
18682
|
turn.queryIteratorControl = running.control;
|
|
@@ -18449,6 +18736,7 @@ function launchClaudeRuntime(turn, plan) {
|
|
|
18449
18736
|
launch: {
|
|
18450
18737
|
...claudeLaunchedProfile(session, options, plan.readOnlyCommandSandbox),
|
|
18451
18738
|
settingSources: JSON.stringify(plan.settingSources),
|
|
18739
|
+
repositoryInstructions: plan.repositoryInstructions ?? "",
|
|
18452
18740
|
...claudeLaunchResourceProfile(plugins, queryEnvironment)
|
|
18453
18741
|
},
|
|
18454
18742
|
mcpServers: mcpServersKey,
|
|
@@ -18505,6 +18793,7 @@ function joinableRuntime(turn, plan) {
|
|
|
18505
18793
|
const requested = {
|
|
18506
18794
|
...claudeLaunchProfile(turn.session, turn.options, plan.readOnlyCommandSandbox),
|
|
18507
18795
|
settingSources: JSON.stringify(plan.settingSources),
|
|
18796
|
+
repositoryInstructions: plan.repositoryInstructions ?? "",
|
|
18508
18797
|
...claudeLaunchResourceProfile(plan.plugins, plan.queryEnvironment)
|
|
18509
18798
|
};
|
|
18510
18799
|
return claudeLaunchConflict(running.launch, requested) ? undefined : running;
|
|
@@ -18899,6 +19188,8 @@ async function settlesBy(work, deadline) {
|
|
|
18899
19188
|
// ../../bridges/claude-bridge/src/routes/config.ts
|
|
18900
19189
|
var config = new Hono2;
|
|
18901
19190
|
config.get("/models", async (c) => {
|
|
19191
|
+
if (c.req.query("forceRefresh") === "true")
|
|
19192
|
+
invalidateClaudeModelCatalog();
|
|
18902
19193
|
const startedAt = Date.now();
|
|
18903
19194
|
console.log("[config] /models requested");
|
|
18904
19195
|
const [{ models, source }, versions] = await Promise.all([
|