orkestrator 2.28.0-beta → 2.30.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 +956 -335
- package/dist/main.js +173539 -152085
- package/package.json +5 -5
- package/resources/claude-bridge/dist/index.js +276 -199
- package/resources/codex-bridge/dist/index.js +343 -60
|
@@ -4349,7 +4349,8 @@ var NATIVE_AGENT_COMMAND_CATALOGUE_ERROR_CODES = [
|
|
|
4349
4349
|
"rejected",
|
|
4350
4350
|
"malformed",
|
|
4351
4351
|
"too-large",
|
|
4352
|
-
"provider-error"
|
|
4352
|
+
"provider-error",
|
|
4353
|
+
"outdated-bridge"
|
|
4353
4354
|
];
|
|
4354
4355
|
var DEFAULT_NATIVE_AGENT_LIVE_WINDOW = {
|
|
4355
4356
|
messages: 100,
|
|
@@ -4495,6 +4496,7 @@ var READ_ONLY_COMMANDS = Object.freeze(new Set([
|
|
|
4495
4496
|
var MUTATING_ARGUMENTS = new Map([
|
|
4496
4497
|
["date", new Set(["-s", "--set"])],
|
|
4497
4498
|
["fd", new Set(["-x", "-X", "--exec", "--exec-batch"])],
|
|
4499
|
+
["file", new Set(["-C", "--compile"])],
|
|
4498
4500
|
[
|
|
4499
4501
|
"find",
|
|
4500
4502
|
new Set([
|
|
@@ -4509,9 +4511,48 @@ var MUTATING_ARGUMENTS = new Map([
|
|
|
4509
4511
|
"-okdir"
|
|
4510
4512
|
])
|
|
4511
4513
|
],
|
|
4514
|
+
["hostname", new Set(["-F", "--file", "-b", "--boot"])],
|
|
4512
4515
|
["rg", new Set(["--hostname-bin", "--pre"])],
|
|
4513
|
-
["sort", new Set(["-o", "--output"])],
|
|
4514
|
-
["yq", new Set(["-i", "--in-place", "--inplace"])]
|
|
4516
|
+
["sort", new Set(["-o", "--output", "-T", "--temporary-directory", "--compress-program"])],
|
|
4517
|
+
["yq", new Set(["-i", "--in-place", "--inplace", "-s", "--split-exp"])]
|
|
4518
|
+
]);
|
|
4519
|
+
var POSITIONAL_LIMITS = new Map([
|
|
4520
|
+
["hostname", { max: 0, valueOptions: new Set }],
|
|
4521
|
+
["uniq", { max: 1, valueOptions: new Set(["-f", "-s", "-w"]) }],
|
|
4522
|
+
[
|
|
4523
|
+
"xxd",
|
|
4524
|
+
{
|
|
4525
|
+
max: 1,
|
|
4526
|
+
valueOptions: new Set([
|
|
4527
|
+
"-c",
|
|
4528
|
+
"-cols",
|
|
4529
|
+
"-g",
|
|
4530
|
+
"-groupsize",
|
|
4531
|
+
"-l",
|
|
4532
|
+
"-len",
|
|
4533
|
+
"-n",
|
|
4534
|
+
"-name",
|
|
4535
|
+
"-o",
|
|
4536
|
+
"-offset",
|
|
4537
|
+
"-s",
|
|
4538
|
+
"-seek"
|
|
4539
|
+
])
|
|
4540
|
+
}
|
|
4541
|
+
]
|
|
4542
|
+
]);
|
|
4543
|
+
var OPTION_ALLOWLISTS = new Map([
|
|
4544
|
+
["awk", new Set(["-F", "-v", "--field-separator", "--assign"])]
|
|
4545
|
+
]);
|
|
4546
|
+
var GIT_MUTATING_ARGUMENTS = new Set([
|
|
4547
|
+
"--config-env",
|
|
4548
|
+
"--exec-path",
|
|
4549
|
+
"--ext-diff",
|
|
4550
|
+
"--filters",
|
|
4551
|
+
"--output",
|
|
4552
|
+
"--textconv"
|
|
4553
|
+
]);
|
|
4554
|
+
var GIT_SUBCOMMAND_MUTATING_ARGUMENTS = new Map([
|
|
4555
|
+
["grep", new Set(["-O", "--open-files-in-pager"])]
|
|
4515
4556
|
]);
|
|
4516
4557
|
var READ_ONLY_GIT_SUBCOMMANDS = Object.freeze(new Set([
|
|
4517
4558
|
"blame",
|
|
@@ -4521,7 +4562,6 @@ var READ_ONLY_GIT_SUBCOMMANDS = Object.freeze(new Set([
|
|
|
4521
4562
|
"grep",
|
|
4522
4563
|
"log",
|
|
4523
4564
|
"ls-files",
|
|
4524
|
-
"ls-remote",
|
|
4525
4565
|
"ls-tree",
|
|
4526
4566
|
"merge-base",
|
|
4527
4567
|
"name-rev",
|
|
@@ -4575,9 +4615,10 @@ var GIT_CONFIG_WRITE_FLAGS = Object.freeze(new Set([
|
|
|
4575
4615
|
]));
|
|
4576
4616
|
var GIT_CONFIG_READ_SUBCOMMANDS = Object.freeze(new Set(["get", "list"]));
|
|
4577
4617
|
var GIT_CONFIG_WRITE_SUBCOMMANDS = Object.freeze(new Set(["edit", "remove-section", "rename-section", "set", "unset"]));
|
|
4578
|
-
var GIT_REMOTE_READ_SUBCOMMANDS = Object.freeze(new Set(["get-url"
|
|
4618
|
+
var GIT_REMOTE_READ_SUBCOMMANDS = Object.freeze(new Set(["get-url"]));
|
|
4579
4619
|
function hasFlag(args, flags) {
|
|
4580
|
-
|
|
4620
|
+
const letters = [...flags].flatMap((flag) => /^-[A-Za-z0-9]$/.test(flag) ? [flag[1]] : []);
|
|
4621
|
+
return args.some((arg) => flags.has(arg) || flags.has(arg.split("=", 1)[0] ?? arg) || arg.startsWith("--") && [...flags].some((flag) => flag.startsWith("--") && flag.startsWith(arg.split("=", 1)[0])) || /^-[^-]/.test(arg) && letters.some((letter) => arg.slice(1).includes(letter)));
|
|
4581
4622
|
}
|
|
4582
4623
|
function listsRefsOnly(args) {
|
|
4583
4624
|
if (hasFlag(args, GIT_REF_WRITE_FLAGS))
|
|
@@ -4610,8 +4651,9 @@ var CONDITIONAL_GIT_SUBCOMMANDS = new Map([
|
|
|
4610
4651
|
],
|
|
4611
4652
|
["tag", listsRefsOnly]
|
|
4612
4653
|
]);
|
|
4613
|
-
var
|
|
4614
|
-
var
|
|
4654
|
+
var NETWORK_COMMANDS = new Set(["curl", "gh", "wget"]);
|
|
4655
|
+
var NETWORK_GIT_SUBCOMMANDS = new Set(["fetch", "ls-remote", "pull"]);
|
|
4656
|
+
var COMPOSITION_PATTERN = /[;&|><`$(){}\n\r'"\\*?[\]]|\bsudo\b|\bexec\b/;
|
|
4615
4657
|
function isCoordinatorReadOnlyPolicy(policy) {
|
|
4616
4658
|
return policy?.id === "coordinator-read-only";
|
|
4617
4659
|
}
|
|
@@ -4640,13 +4682,14 @@ function claudeReadOnlyAllowedTools(options) {
|
|
|
4640
4682
|
...(options.researchMcpServerNames ?? []).map((name) => `${claudeMcpToolPrefix(name)}*`)
|
|
4641
4683
|
];
|
|
4642
4684
|
}
|
|
4643
|
-
function claudeReadOnlySandbox(policy) {
|
|
4685
|
+
function claudeReadOnlySandbox(policy, options = {}) {
|
|
4644
4686
|
return {
|
|
4645
4687
|
enabled: true,
|
|
4646
|
-
failIfUnavailable:
|
|
4688
|
+
failIfUnavailable: options.commandSandbox !== "unavailable",
|
|
4647
4689
|
autoAllowBashIfSandboxed: true,
|
|
4648
4690
|
allowUnsandboxedCommands: false,
|
|
4649
4691
|
excludedCommands: [],
|
|
4692
|
+
filesystem: { denyWrite: [...new Set(options.workspaces ?? [])] },
|
|
4650
4693
|
network: {
|
|
4651
4694
|
allowLocalBinding: policy.networkAccess === "full",
|
|
4652
4695
|
strictAllowlist: true,
|
|
@@ -4658,32 +4701,54 @@ function isReadOnlyShellCommand(command) {
|
|
|
4658
4701
|
const trimmed = command.trim();
|
|
4659
4702
|
if (!trimmed)
|
|
4660
4703
|
return { allowed: true };
|
|
4661
|
-
if (COMPOSITION_PATTERN.test(trimmed)) {
|
|
4704
|
+
if (COMPOSITION_PATTERN.test(trimmed) || /(?:^|\s)~/.test(trimmed)) {
|
|
4662
4705
|
return {
|
|
4663
4706
|
allowed: false,
|
|
4664
|
-
reason: "Coordinator shells cannot use pipes, redirection, substitution or command chaining, because the command that runs would not be the one checked."
|
|
4707
|
+
reason: "Coordinator shells cannot use quotes, escapes, globs, pipes, redirection, substitution or command chaining, because the command that runs would not be the one checked."
|
|
4665
4708
|
};
|
|
4666
4709
|
}
|
|
4667
4710
|
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
4668
|
-
const
|
|
4669
|
-
if (!
|
|
4711
|
+
const first = tokens[0] ?? "";
|
|
4712
|
+
if (!first)
|
|
4670
4713
|
return { allowed: true };
|
|
4671
|
-
if (
|
|
4672
|
-
const subcommandIndex = tokens.findIndex((token, index) => index > 0 && !token.startsWith("-"));
|
|
4673
|
-
const subcommand = subcommandIndex > 0 ? tokens[subcommandIndex] : undefined;
|
|
4674
|
-
const args = subcommandIndex > 0 ? tokens.slice(subcommandIndex + 1) : [];
|
|
4675
|
-
const permitted = program === "git" ? subcommand !== undefined && (READ_ONLY_GIT_SUBCOMMANDS.has(subcommand) || (CONDITIONAL_GIT_SUBCOMMANDS.get(subcommand)?.(args) ?? false)) : subcommand !== undefined && READ_ONLY_GH_SUBCOMMANDS.has(subcommand);
|
|
4676
|
-
if (permitted)
|
|
4677
|
-
return { allowed: true };
|
|
4678
|
-
const described = [program, subcommand].filter(Boolean).join(" ");
|
|
4714
|
+
if (first.includes("/") || first.includes("\\")) {
|
|
4679
4715
|
return {
|
|
4680
4716
|
allowed: false,
|
|
4681
|
-
reason: `Coordinator
|
|
4717
|
+
reason: `Coordinator shells run reading programs by name only, so \`${first}\` is not available here. Use the program name, or delegate it to a worker environment.`
|
|
4682
4718
|
};
|
|
4683
4719
|
}
|
|
4720
|
+
const program = first;
|
|
4721
|
+
if (NETWORK_COMMANDS.has(program))
|
|
4722
|
+
return networkRefusal(program);
|
|
4723
|
+
if (program === "git") {
|
|
4724
|
+
const subcommandIndex = tokens.findIndex((token, index) => index > 0 && !token.startsWith("-"));
|
|
4725
|
+
const subcommand = subcommandIndex > 0 ? tokens[subcommandIndex] : undefined;
|
|
4726
|
+
const args = subcommandIndex > 0 ? tokens.slice(subcommandIndex + 1) : [];
|
|
4727
|
+
if (subcommand && (NETWORK_GIT_SUBCOMMANDS.has(subcommand) || subcommand === "remote" && args.some((arg) => arg === "show"))) {
|
|
4728
|
+
return networkRefusal(`git ${subcommand}`);
|
|
4729
|
+
}
|
|
4730
|
+
const permitted = subcommand !== undefined && (READ_ONLY_GIT_SUBCOMMANDS.has(subcommand) || (CONDITIONAL_GIT_SUBCOMMANDS.get(subcommand)?.(args) ?? false));
|
|
4731
|
+
const described = ["git", subcommand].filter(Boolean).join(" ");
|
|
4732
|
+
if (!permitted) {
|
|
4733
|
+
return {
|
|
4734
|
+
allowed: false,
|
|
4735
|
+
reason: `Coordinator is read-only, so \`${described}\` is not available here. Delegate it to a worker environment.`
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
if (hasFlag(tokens.slice(1), GIT_MUTATING_ARGUMENTS) || hasFlag(args, GIT_SUBCOMMAND_MUTATING_ARGUMENTS.get(subcommand) ?? new Set)) {
|
|
4739
|
+
return {
|
|
4740
|
+
allowed: false,
|
|
4741
|
+
reason: `Coordinator is read-only, so \`${described}\` cannot be used with an argument that writes a file or runs another program. Delegate it to a worker environment.`
|
|
4742
|
+
};
|
|
4743
|
+
}
|
|
4744
|
+
return { allowed: true };
|
|
4745
|
+
}
|
|
4684
4746
|
if (READ_ONLY_COMMANDS.has(program)) {
|
|
4747
|
+
const args = tokens.slice(1);
|
|
4685
4748
|
const mutating = MUTATING_ARGUMENTS.get(program);
|
|
4686
|
-
|
|
4749
|
+
const options = OPTION_ALLOWLISTS.get(program);
|
|
4750
|
+
const limit = POSITIONAL_LIMITS.get(program);
|
|
4751
|
+
if (mutating && hasFlag(args, mutating) || options && !optionsAllowed(args, options) || limit && positionalCount(args, limit.valueOptions) > limit.max) {
|
|
4687
4752
|
return {
|
|
4688
4753
|
allowed: false,
|
|
4689
4754
|
reason: `Coordinator is read-only, so \`${program}\` cannot be used with an argument that writes or runs another program. Delegate it to a worker environment.`
|
|
@@ -4696,6 +4761,48 @@ function isReadOnlyShellCommand(command) {
|
|
|
4696
4761
|
reason: `Coordinator is read-only, so \`${program}\` is not available here. Delegate commands that change the checkout to a worker environment.`
|
|
4697
4762
|
};
|
|
4698
4763
|
}
|
|
4764
|
+
function networkRefusal(described) {
|
|
4765
|
+
return {
|
|
4766
|
+
allowed: false,
|
|
4767
|
+
reason: `Coordinator commands have no network access, so \`${described}\` is not available here. Delegate it to a worker environment.`
|
|
4768
|
+
};
|
|
4769
|
+
}
|
|
4770
|
+
function optionsAllowed(args, allowed) {
|
|
4771
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
4772
|
+
const arg = args[index];
|
|
4773
|
+
if (arg === "--")
|
|
4774
|
+
return true;
|
|
4775
|
+
if (!arg.startsWith("-") || arg === "-")
|
|
4776
|
+
continue;
|
|
4777
|
+
if (allowed.has(arg)) {
|
|
4778
|
+
index += 1;
|
|
4779
|
+
continue;
|
|
4780
|
+
}
|
|
4781
|
+
const long = arg.startsWith("--") ? arg.split("=", 1)[0] : undefined;
|
|
4782
|
+
const attached = long ?? arg.slice(0, 2);
|
|
4783
|
+
if (!allowed.has(attached))
|
|
4784
|
+
return false;
|
|
4785
|
+
}
|
|
4786
|
+
return true;
|
|
4787
|
+
}
|
|
4788
|
+
function positionalCount(args, valueOptions) {
|
|
4789
|
+
let count = 0;
|
|
4790
|
+
let optionsEnded = false;
|
|
4791
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
4792
|
+
const arg = args[index];
|
|
4793
|
+
if (!optionsEnded && arg === "--") {
|
|
4794
|
+
optionsEnded = true;
|
|
4795
|
+
continue;
|
|
4796
|
+
}
|
|
4797
|
+
if (!optionsEnded && arg.startsWith("-") && arg !== "-") {
|
|
4798
|
+
if (valueOptions.has(arg))
|
|
4799
|
+
index += 1;
|
|
4800
|
+
continue;
|
|
4801
|
+
}
|
|
4802
|
+
count += 1;
|
|
4803
|
+
}
|
|
4804
|
+
return count;
|
|
4805
|
+
}
|
|
4699
4806
|
function deny(reason) {
|
|
4700
4807
|
return {
|
|
4701
4808
|
hookSpecificOutput: {
|
|
@@ -12585,7 +12692,7 @@ var AUTH_CACHE_TTL_MS = 30000;
|
|
|
12585
12692
|
var FAILED_AUTH_CACHE_TTL_MS = 5000;
|
|
12586
12693
|
var CLAUDE_SIGN_IN = {
|
|
12587
12694
|
kind: "terminal",
|
|
12588
|
-
hint: "
|
|
12695
|
+
hint: "Sign in to Claude from the sign-in card in this tab or from Settings → Claude."
|
|
12589
12696
|
};
|
|
12590
12697
|
var CLAUDE_SIGN_IN_REQUIRED_MESSAGE = "Claude isn't signed in. Sign in to Claude to keep working.";
|
|
12591
12698
|
var authCache;
|
|
@@ -12593,6 +12700,10 @@ var authRead;
|
|
|
12593
12700
|
var authReadGeneration;
|
|
12594
12701
|
var authRefreshPending = false;
|
|
12595
12702
|
var authGeneration = 0;
|
|
12703
|
+
var turnAuthenticationFailedUntil = 0;
|
|
12704
|
+
function withTurnFailure(value) {
|
|
12705
|
+
return Date.now() < turnAuthenticationFailedUntil && value.state === "signed-in" ? { ...value, state: "expired" } : value;
|
|
12706
|
+
}
|
|
12596
12707
|
function presentSource(value) {
|
|
12597
12708
|
return value && value !== "none" ? value : undefined;
|
|
12598
12709
|
}
|
|
@@ -12629,8 +12740,9 @@ async function probeAccount() {
|
|
|
12629
12740
|
}
|
|
12630
12741
|
}
|
|
12631
12742
|
function readClaudeAuthStatus() {
|
|
12632
|
-
if (authCache && authCache.expiresAt > Date.now())
|
|
12633
|
-
return Promise.resolve(authCache.value);
|
|
12743
|
+
if (authCache && authCache.expiresAt > Date.now()) {
|
|
12744
|
+
return Promise.resolve(withTurnFailure(authCache.value));
|
|
12745
|
+
}
|
|
12634
12746
|
if (authRead)
|
|
12635
12747
|
return authRead;
|
|
12636
12748
|
const generation = authGeneration;
|
|
@@ -12645,7 +12757,7 @@ function readClaudeAuthStatus() {
|
|
|
12645
12757
|
if (generation === authGeneration) {
|
|
12646
12758
|
authCache = { expiresAt: Date.now() + ttl, value };
|
|
12647
12759
|
}
|
|
12648
|
-
return value;
|
|
12760
|
+
return withTurnFailure(value);
|
|
12649
12761
|
}).finally(() => {
|
|
12650
12762
|
if (authRead !== read)
|
|
12651
12763
|
return;
|
|
@@ -12661,6 +12773,7 @@ function readClaudeAuthStatus() {
|
|
|
12661
12773
|
return read;
|
|
12662
12774
|
}
|
|
12663
12775
|
function noteClaudeAuthenticationFailure() {
|
|
12776
|
+
turnAuthenticationFailedUntil = Date.now() + AUTH_CACHE_TTL_MS;
|
|
12664
12777
|
authCache = undefined;
|
|
12665
12778
|
if (authRead && authReadGeneration !== authGeneration)
|
|
12666
12779
|
authRefreshPending = true;
|
|
@@ -12669,6 +12782,7 @@ function noteClaudeAuthenticationFailure() {
|
|
|
12669
12782
|
function noteClaudeAuthenticationWorked() {
|
|
12670
12783
|
authGeneration += 1;
|
|
12671
12784
|
authRefreshPending = false;
|
|
12785
|
+
turnAuthenticationFailedUntil = 0;
|
|
12672
12786
|
if (authCache?.value.state === "needs-auth")
|
|
12673
12787
|
authCache = undefined;
|
|
12674
12788
|
}
|
|
@@ -13845,9 +13959,86 @@ function backgroundCommandInstruction(env) {
|
|
|
13845
13959
|
}
|
|
13846
13960
|
|
|
13847
13961
|
// ../../bridges/claude-bridge/src/services/claude-execution-sandbox.ts
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13962
|
+
import { realpathSync } from "node:fs";
|
|
13963
|
+
|
|
13964
|
+
// ../protocol/src/coordinator.ts
|
|
13965
|
+
var COORDINATOR_COMMAND_SANDBOX_ENV = "ORKESTRATOR_COORDINATOR_COMMAND_SANDBOX";
|
|
13966
|
+
function coordinatorCommandSandboxFromEnv(env) {
|
|
13967
|
+
return env[COORDINATOR_COMMAND_SANDBOX_ENV] === "unavailable" ? "unavailable" : "required";
|
|
13968
|
+
}
|
|
13969
|
+
var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
|
|
13970
|
+
"ack_message",
|
|
13971
|
+
"add_ticket_comment",
|
|
13972
|
+
"address_multi_review",
|
|
13973
|
+
"adopt_workflow",
|
|
13974
|
+
"cancel_build_pipeline",
|
|
13975
|
+
"cancel_multi_review",
|
|
13976
|
+
"compare_project_files",
|
|
13977
|
+
"create_ticket",
|
|
13978
|
+
"get_build_pipeline",
|
|
13979
|
+
"get_environment",
|
|
13980
|
+
"get_launch_options",
|
|
13981
|
+
"get_message",
|
|
13982
|
+
"get_message_status",
|
|
13983
|
+
"get_multi_review",
|
|
13984
|
+
"get_repository_context",
|
|
13985
|
+
"get_tab_state",
|
|
13986
|
+
"get_tab_transcript",
|
|
13987
|
+
"get_ticket",
|
|
13988
|
+
"launch_environment",
|
|
13989
|
+
"launch_job",
|
|
13990
|
+
"launch_multi_review",
|
|
13991
|
+
"launch_node_environment",
|
|
13992
|
+
"list_agents",
|
|
13993
|
+
"list_environments",
|
|
13994
|
+
"list_mailboxes",
|
|
13995
|
+
"list_node_environments",
|
|
13996
|
+
"list_nodes",
|
|
13997
|
+
"list_projects",
|
|
13998
|
+
"list_tabs",
|
|
13999
|
+
"list_tickets",
|
|
14000
|
+
"list_workflows",
|
|
14001
|
+
"open_multi_review",
|
|
14002
|
+
"open_multi_review_fix",
|
|
14003
|
+
"pause_build_pipeline",
|
|
14004
|
+
"read_messages",
|
|
14005
|
+
"read_node_environment",
|
|
14006
|
+
"request_env_value_reveal",
|
|
14007
|
+
"request_environment_deletion",
|
|
14008
|
+
"request_project_file_update",
|
|
14009
|
+
"request_project_on_node",
|
|
14010
|
+
"resume_build_pipeline",
|
|
14011
|
+
"send_message",
|
|
14012
|
+
"send_node_message",
|
|
14013
|
+
"send_prompt_to_node_tab",
|
|
14014
|
+
"send_prompt_to_tab",
|
|
14015
|
+
"start_build_pipeline",
|
|
14016
|
+
"start_environment",
|
|
14017
|
+
"start_multi_review",
|
|
14018
|
+
"start_node_environment",
|
|
14019
|
+
"stop_environment",
|
|
14020
|
+
"stop_node_environment",
|
|
14021
|
+
"transfer_files",
|
|
14022
|
+
"update_ticket"
|
|
14023
|
+
]);
|
|
14024
|
+
|
|
14025
|
+
// ../../bridges/claude-bridge/src/services/claude-execution-sandbox.ts
|
|
14026
|
+
function claudeReadOnlyWorkspaces(cwd) {
|
|
14027
|
+
let resolved;
|
|
14028
|
+
try {
|
|
14029
|
+
resolved = realpathSync(cwd);
|
|
14030
|
+
} catch {
|
|
14031
|
+
resolved = undefined;
|
|
14032
|
+
}
|
|
14033
|
+
return [...new Set([cwd, ...resolved ? [resolved] : []])];
|
|
14034
|
+
}
|
|
14035
|
+
function claudeExecutionSandbox(policy, asksForApproval, readOnly = {}) {
|
|
14036
|
+
if (policy && isCoordinatorReadOnlyPolicy(policy)) {
|
|
14037
|
+
return claudeReadOnlySandbox(policy, {
|
|
14038
|
+
workspaces: claudeReadOnlyWorkspaces(readOnly.cwd ?? claudeWorkspaceCwd()),
|
|
14039
|
+
commandSandbox: readOnly.commandSandbox ?? coordinatorCommandSandboxFromEnv(process.env)
|
|
14040
|
+
});
|
|
14041
|
+
}
|
|
13851
14042
|
if (policy?.sandbox !== "provider")
|
|
13852
14043
|
return;
|
|
13853
14044
|
return {
|
|
@@ -14782,7 +14973,9 @@ function claudeQueryOptions(turn, plan, turnFor, mcp) {
|
|
|
14782
14973
|
forwardSubagentText: true,
|
|
14783
14974
|
allowedTools,
|
|
14784
14975
|
...disallowedTools?.length ? { disallowedTools } : {},
|
|
14785
|
-
...policy?.sandbox === "provider" || coordinatorReadOnly ? {
|
|
14976
|
+
...policy?.sandbox === "provider" || coordinatorReadOnly ? {
|
|
14977
|
+
sandbox: claudeExecutionSandbox(policy, claudeAsksForApproval(policy, options), { cwd })
|
|
14978
|
+
} : {},
|
|
14786
14979
|
abortController,
|
|
14787
14980
|
...session.sdkSessionId ? { resume: session.sdkSessionId } : {
|
|
14788
14981
|
sessionId: sdkSessionIdFromBridgeId(session.id) ?? crypto.randomUUID()
|
|
@@ -14794,10 +14987,11 @@ function claudeQueryOptions(turn, plan, turnFor, mcp) {
|
|
|
14794
14987
|
systemPrompt: {
|
|
14795
14988
|
type: "preset",
|
|
14796
14989
|
preset: "claude_code",
|
|
14797
|
-
append: [
|
|
14990
|
+
append: 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." : [
|
|
14798
14991
|
"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.",
|
|
14799
14992
|
backgroundCommandInstruction(queryEnvironment),
|
|
14800
|
-
"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."
|
|
14993
|
+
"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.",
|
|
14994
|
+
"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."
|
|
14801
14995
|
].join(`
|
|
14802
14996
|
|
|
14803
14997
|
`)
|
|
@@ -14858,6 +15052,34 @@ function observeClaudeMessage(diagnostics, message) {
|
|
|
14858
15052
|
}
|
|
14859
15053
|
}
|
|
14860
15054
|
|
|
15055
|
+
// ../../bridges/claude-bridge/src/services/session-auth-notice.ts
|
|
15056
|
+
var CLAUDE_LOGIN_REFUSED_MESSAGE = "Claude's login was refused. Sign in to Claude again to keep working.";
|
|
15057
|
+
var MAX_NOTICE_LENGTH = 500;
|
|
15058
|
+
function setSessionAuthNotice(session, sessionId, notice) {
|
|
15059
|
+
const previous = session.authNotice;
|
|
15060
|
+
if (!previous && !notice)
|
|
15061
|
+
return;
|
|
15062
|
+
if (previous && notice && previous.state === notice.state && previous.message === notice.message && previous.occurrenceId === notice.occurrenceId) {
|
|
15063
|
+
return;
|
|
15064
|
+
}
|
|
15065
|
+
session.authNotice = notice ? { ...notice, message: notice.message.slice(0, MAX_NOTICE_LENGTH) } : undefined;
|
|
15066
|
+
eventEmitter.emit({
|
|
15067
|
+
type: "session.updated",
|
|
15068
|
+
sessionId,
|
|
15069
|
+
data: { authNotice: session.authNotice ?? null }
|
|
15070
|
+
});
|
|
15071
|
+
}
|
|
15072
|
+
function noteSessionLoginRefused(session, sessionId, occurrenceId) {
|
|
15073
|
+
const current = session.authNotice;
|
|
15074
|
+
if (current?.state === "expired" && current.message === CLAUDE_LOGIN_REFUSED_MESSAGE)
|
|
15075
|
+
return;
|
|
15076
|
+
setSessionAuthNotice(session, sessionId, {
|
|
15077
|
+
state: "expired",
|
|
15078
|
+
message: CLAUDE_LOGIN_REFUSED_MESSAGE,
|
|
15079
|
+
occurrenceId
|
|
15080
|
+
});
|
|
15081
|
+
}
|
|
15082
|
+
|
|
14861
15083
|
// ../../bridges/claude-bridge/src/services/session-manager-prompt-handlers/assistant.ts
|
|
14862
15084
|
function applyClaudeUsageReport(session, report) {
|
|
14863
15085
|
const previous = session.inProgressUsage ?? session.usage;
|
|
@@ -14916,10 +15138,13 @@ function handleAssistantMessage(turn, message) {
|
|
|
14916
15138
|
const receivedAt = new Date().toISOString();
|
|
14917
15139
|
const recordUnknownContentBlock = (blockType) => sessionHealth(session).recordUnknown(`block:${blockType}`);
|
|
14918
15140
|
const assistantError = message.error;
|
|
14919
|
-
if (assistantError === "authentication_failed")
|
|
15141
|
+
if (assistantError === "authentication_failed") {
|
|
14920
15142
|
noteClaudeAuthenticationFailure();
|
|
14921
|
-
|
|
15143
|
+
noteSessionLoginRefused(session, sessionId, typeof message.uuid === "string" ? message.uuid : crypto.randomUUID());
|
|
15144
|
+
} else if (!assistantError) {
|
|
14922
15145
|
noteClaudeAuthenticationWorked();
|
|
15146
|
+
setSessionAuthNotice(session, sessionId, undefined);
|
|
15147
|
+
}
|
|
14923
15148
|
const usageReport = message.usage_report;
|
|
14924
15149
|
if (usageReport) {
|
|
14925
15150
|
const usage = applyClaudeUsageReport(session, usageReport);
|
|
@@ -15204,6 +15429,16 @@ function handleAuthStatus(turn, message) {
|
|
|
15204
15429
|
severity: auth.error ? "error" : "info",
|
|
15205
15430
|
createdAt: new Date().toISOString()
|
|
15206
15431
|
});
|
|
15432
|
+
const occurrenceId = typeof auth.uuid === "string" && auth.uuid ? auth.uuid : crypto.randomUUID();
|
|
15433
|
+
setSessionAuthNotice(session, sessionId, auth.error ? {
|
|
15434
|
+
state: "expired",
|
|
15435
|
+
message: `${content.slice(0, 300)}. Sign in to Claude again to keep working.`,
|
|
15436
|
+
occurrenceId
|
|
15437
|
+
} : auth.isAuthenticating ? {
|
|
15438
|
+
state: "needs-auth",
|
|
15439
|
+
message: "Claude is signing in again. Finish any sign-in it opened to continue.",
|
|
15440
|
+
occurrenceId
|
|
15441
|
+
} : undefined);
|
|
15207
15442
|
}
|
|
15208
15443
|
function handleStreamEvent(turn, message) {
|
|
15209
15444
|
if (message.event?.type !== "ping") {
|
|
@@ -18006,7 +18241,8 @@ session.get("/:id", async (c) => {
|
|
|
18006
18241
|
completionBlockedByBackgroundTasks: sessionData.completionBlockedByBackgroundTasks === true,
|
|
18007
18242
|
rewindInProgress: sessionData.rewindInProgress === true,
|
|
18008
18243
|
...sessionData.commandInventoryState ? { commandRevision: sessionData.commandInventoryState.revision } : {},
|
|
18009
|
-
...readinessField()
|
|
18244
|
+
...readinessField(),
|
|
18245
|
+
...sessionData.authNotice ? { authNotice: sessionData.authNotice } : {}
|
|
18010
18246
|
});
|
|
18011
18247
|
});
|
|
18012
18248
|
function readinessField() {
|
|
@@ -19295,156 +19531,6 @@ mcp.get("/servers", async (c) => {
|
|
|
19295
19531
|
});
|
|
19296
19532
|
var mcp_default = mcp;
|
|
19297
19533
|
|
|
19298
|
-
// ../../bridges/claude-bridge/src/services/slash-commands.ts
|
|
19299
|
-
import { open as open3, readdir as readdir2, stat as stat4 } from "node:fs/promises";
|
|
19300
|
-
import { StringDecoder } from "node:string_decoder";
|
|
19301
|
-
import { join as join11, basename, dirname as dirname2 } from "node:path";
|
|
19302
|
-
var commandDescriptions = new Map;
|
|
19303
|
-
var MAX_COMMAND_DESCRIPTION_CACHE_ENTRIES = 512;
|
|
19304
|
-
function rememberCommandDescription(filePath, entry) {
|
|
19305
|
-
commandDescriptions.delete(filePath);
|
|
19306
|
-
commandDescriptions.set(filePath, entry);
|
|
19307
|
-
while (commandDescriptions.size > MAX_COMMAND_DESCRIPTION_CACHE_ENTRIES) {
|
|
19308
|
-
const oldest = commandDescriptions.keys().next();
|
|
19309
|
-
if (oldest.done)
|
|
19310
|
-
break;
|
|
19311
|
-
commandDescriptions.delete(oldest.value);
|
|
19312
|
-
}
|
|
19313
|
-
}
|
|
19314
|
-
var FRONTMATTER_READ_CHUNK_BYTES = 8 * 1024;
|
|
19315
|
-
var MAX_FRONTMATTER_READ_BYTES = 256 * 1024;
|
|
19316
|
-
function fingerprintOf2(stats) {
|
|
19317
|
-
return `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeMs}`;
|
|
19318
|
-
}
|
|
19319
|
-
function hasCompleteFrontmatter(content) {
|
|
19320
|
-
return /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/.test(content);
|
|
19321
|
-
}
|
|
19322
|
-
async function readFileFrontmatter(filePath) {
|
|
19323
|
-
const handle = await open3(filePath, "r");
|
|
19324
|
-
try {
|
|
19325
|
-
const decoder = new StringDecoder("utf8");
|
|
19326
|
-
let content = "";
|
|
19327
|
-
let position = 0;
|
|
19328
|
-
while (position < MAX_FRONTMATTER_READ_BYTES) {
|
|
19329
|
-
const readLength = Math.min(FRONTMATTER_READ_CHUNK_BYTES, MAX_FRONTMATTER_READ_BYTES - position);
|
|
19330
|
-
const buffer = Buffer.allocUnsafe(readLength);
|
|
19331
|
-
const { bytesRead } = await handle.read(buffer, 0, readLength, position);
|
|
19332
|
-
if (bytesRead === 0)
|
|
19333
|
-
break;
|
|
19334
|
-
position += bytesRead;
|
|
19335
|
-
content += decoder.write(buffer.subarray(0, bytesRead));
|
|
19336
|
-
if (position >= FRONTMATTER_READ_CHUNK_BYTES && !content.startsWith(`---
|
|
19337
|
-
`) && !content.startsWith(`---\r
|
|
19338
|
-
`) || hasCompleteFrontmatter(content)) {
|
|
19339
|
-
break;
|
|
19340
|
-
}
|
|
19341
|
-
}
|
|
19342
|
-
return content + decoder.end();
|
|
19343
|
-
} finally {
|
|
19344
|
-
await handle.close();
|
|
19345
|
-
}
|
|
19346
|
-
}
|
|
19347
|
-
async function readCommandDescription(filePath) {
|
|
19348
|
-
const fingerprint = fingerprintOf2(await stat4(filePath));
|
|
19349
|
-
const cached = commandDescriptions.get(filePath);
|
|
19350
|
-
if (cached && cached.fingerprint === fingerprint) {
|
|
19351
|
-
return cached.description;
|
|
19352
|
-
}
|
|
19353
|
-
const description = parseDescription(await readFileFrontmatter(filePath));
|
|
19354
|
-
rememberCommandDescription(filePath, { fingerprint, description });
|
|
19355
|
-
return description;
|
|
19356
|
-
}
|
|
19357
|
-
function pruneCommandDescriptionCache(commandsDir, livePaths) {
|
|
19358
|
-
for (const cachedPath of commandDescriptions.keys()) {
|
|
19359
|
-
if (dirname2(cachedPath) === commandsDir && !livePaths.has(cachedPath)) {
|
|
19360
|
-
commandDescriptions.delete(cachedPath);
|
|
19361
|
-
}
|
|
19362
|
-
}
|
|
19363
|
-
}
|
|
19364
|
-
var BUILTIN_COMMANDS = [
|
|
19365
|
-
"/clear - Clear conversation history",
|
|
19366
|
-
"/compact - Compact conversation to reduce tokens",
|
|
19367
|
-
"/context - Show current context",
|
|
19368
|
-
"/cost - Show token usage and cost",
|
|
19369
|
-
"/doctor - Check system health",
|
|
19370
|
-
"/goal - Set, view, or clear a completion goal",
|
|
19371
|
-
"/help - Show available commands",
|
|
19372
|
-
"/init - Re-initialize the session",
|
|
19373
|
-
"/logout - Log out of Claude",
|
|
19374
|
-
"/memory - Show memory usage",
|
|
19375
|
-
"/model - Show or change model",
|
|
19376
|
-
"/permissions - Manage permissions",
|
|
19377
|
-
"/review - Review recent changes",
|
|
19378
|
-
"/status - Show session status",
|
|
19379
|
-
"/vim - Toggle vim mode"
|
|
19380
|
-
];
|
|
19381
|
-
function parseDescription(content) {
|
|
19382
|
-
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
19383
|
-
if (!match?.[1])
|
|
19384
|
-
return;
|
|
19385
|
-
const frontmatter = match[1];
|
|
19386
|
-
const descMatch = frontmatter.match(/^description:\s*(?:"([^"]*?)"|'([^']*?)'|(.+?))\s*$/m);
|
|
19387
|
-
if (!descMatch)
|
|
19388
|
-
return;
|
|
19389
|
-
return (descMatch[1] ?? descMatch[2] ?? descMatch[3])?.trim();
|
|
19390
|
-
}
|
|
19391
|
-
async function scanCommandsDir(commandsDir, prefix) {
|
|
19392
|
-
let entries;
|
|
19393
|
-
try {
|
|
19394
|
-
entries = await readdir2(commandsDir);
|
|
19395
|
-
} catch {
|
|
19396
|
-
pruneCommandDescriptionCache(commandsDir, new Set);
|
|
19397
|
-
return [];
|
|
19398
|
-
}
|
|
19399
|
-
const commands = [];
|
|
19400
|
-
const livePaths = new Set;
|
|
19401
|
-
for (const entry of entries) {
|
|
19402
|
-
if (!entry.endsWith(".md"))
|
|
19403
|
-
continue;
|
|
19404
|
-
const name = basename(entry, ".md");
|
|
19405
|
-
const fullName = prefix ? `/${prefix}${name}` : `/${name}`;
|
|
19406
|
-
const commandPath = join11(commandsDir, entry);
|
|
19407
|
-
livePaths.add(commandPath);
|
|
19408
|
-
let description;
|
|
19409
|
-
try {
|
|
19410
|
-
description = await readCommandDescription(commandPath);
|
|
19411
|
-
} catch {}
|
|
19412
|
-
commands.push(description ? `${fullName} - ${description}` : fullName);
|
|
19413
|
-
}
|
|
19414
|
-
pruneCommandDescriptionCache(commandsDir, livePaths);
|
|
19415
|
-
return commands;
|
|
19416
|
-
}
|
|
19417
|
-
async function discoverSlashCommands(cwd) {
|
|
19418
|
-
const seen = new Set;
|
|
19419
|
-
const result = [];
|
|
19420
|
-
const addCommand = (cmd) => {
|
|
19421
|
-
const name = cmd.split(" - ")[0].trim().toLowerCase();
|
|
19422
|
-
if (!seen.has(name)) {
|
|
19423
|
-
seen.add(name);
|
|
19424
|
-
result.push(cmd);
|
|
19425
|
-
}
|
|
19426
|
-
};
|
|
19427
|
-
const repoCommands = await scanCommandsDir(join11(cwd, ".claude", "commands"), "");
|
|
19428
|
-
for (const cmd of repoCommands)
|
|
19429
|
-
addCommand(cmd);
|
|
19430
|
-
try {
|
|
19431
|
-
const plugins = await getMergedPlugins(cwd);
|
|
19432
|
-
for (const plugin of plugins) {
|
|
19433
|
-
const manifest = await readPluginManifest(plugin.path);
|
|
19434
|
-
const pluginName = manifest?.name || plugin.path.split("/").pop() || "unknown";
|
|
19435
|
-
const commandsDir = join11(plugin.path, "commands");
|
|
19436
|
-
const pluginCommands = await scanCommandsDir(commandsDir, `${pluginName}:`);
|
|
19437
|
-
for (const cmd of pluginCommands)
|
|
19438
|
-
addCommand(cmd);
|
|
19439
|
-
}
|
|
19440
|
-
} catch (error) {
|
|
19441
|
-
console.warn("[slash-commands] Failed to scan plugin commands:", error);
|
|
19442
|
-
}
|
|
19443
|
-
for (const cmd of BUILTIN_COMMANDS)
|
|
19444
|
-
addCommand(cmd);
|
|
19445
|
-
return result.sort((a, b) => a.localeCompare(b));
|
|
19446
|
-
}
|
|
19447
|
-
|
|
19448
19534
|
// ../../bridges/claude-bridge/src/routes/plugins.ts
|
|
19449
19535
|
var plugins = new Hono2;
|
|
19450
19536
|
plugins.get("/", async (c) => {
|
|
@@ -19460,21 +19546,12 @@ plugins.get("/", async (c) => {
|
|
|
19460
19546
|
return c.json({ error: error instanceof Error ? error.message : "Failed to get plugins" }, 500);
|
|
19461
19547
|
}
|
|
19462
19548
|
});
|
|
19463
|
-
plugins.get("/commands", async (c) => {
|
|
19464
|
-
try {
|
|
19465
|
-
const cwd = process.env.CWD || process.cwd();
|
|
19466
|
-
const commands = await discoverSlashCommands(cwd);
|
|
19467
|
-
return c.json({ commands });
|
|
19468
|
-
} catch (error) {
|
|
19469
|
-
console.error("[plugins] Error discovering slash commands:", error);
|
|
19470
|
-
return c.json({ error: error instanceof Error ? error.message : "Failed to discover slash commands" }, 500);
|
|
19471
|
-
}
|
|
19472
|
-
});
|
|
19473
19549
|
var plugins_default = plugins;
|
|
19474
19550
|
|
|
19475
19551
|
// ../protocol/src/parent-watchdog.ts
|
|
19476
19552
|
var PARENT_PID_ENV = "ORKESTRATOR_PARENT_PID";
|
|
19477
|
-
var
|
|
19553
|
+
var PARENT_WATCH_INTERVAL_MS = 1000;
|
|
19554
|
+
var DEFAULT_POLL_INTERVAL_MS = PARENT_WATCH_INTERVAL_MS;
|
|
19478
19555
|
function parseParentPid(value) {
|
|
19479
19556
|
if (!value)
|
|
19480
19557
|
return null;
|
|
@@ -21125,7 +21202,7 @@ compressTranscriptReads(app);
|
|
|
21125
21202
|
app.get("/global/auth-check", (c) => c.json({ status: "ok" }));
|
|
21126
21203
|
app.get("/global/auth", async (c) => c.json(await readClaudeAuthStatus()));
|
|
21127
21204
|
app.get("/global/usage", async (c) => c.json({ account: await readClaudePlanUsage() }));
|
|
21128
|
-
app.post("/global/auth/login", (c) => c.json({ error: "
|
|
21205
|
+
app.post("/global/auth/login", (c) => c.json({ error: "Claude signs in from the sign-in card in its tab or from Settings → Claude." }, 405));
|
|
21129
21206
|
app.post("/global/auth/logout", (c) => c.json({ error: "Claude sign-out is available from a terminal tab." }, 405));
|
|
21130
21207
|
app.post("/global/refresh-catalog", async (c) => {
|
|
21131
21208
|
await refreshClaudeCatalogs();
|