orkestrator 2.29.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 +172332 -153863
- package/package.json +5 -5
- package/resources/claude-bridge/dist/index.js +264 -195
- package/resources/codex-bridge/dist/index.js +343 -60
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orkestrator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.30.0-beta",
|
|
4
4
|
"description": "Run the Orkestrator backend service without the desktop application",
|
|
5
5
|
"homepage": "https://orkestrator.dev",
|
|
6
6
|
"repository": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"smoke:pack": "bun scripts/smoke-packed.ts",
|
|
32
32
|
"test": "bun run build && bun test --preload ../../tests/setup-node.ts tests --parallel",
|
|
33
33
|
"test:workspace": "bun test --preload ../../tests/setup-node.ts tests --only-failures ${ORKESTRATOR_TEST_TIMINGS_DIR:+--timings=$ORKESTRATOR_TEST_TIMINGS_DIR/cli.json --update-timings} --parallel=${ORKESTRATOR_TEST_WORKERS:-2}",
|
|
34
|
-
"typecheck": "
|
|
34
|
+
"typecheck": "bun check -p tsconfig.json"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@anthropic-ai/claude-agent-sdk": "0.3.309",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"sharp": "0.35.5"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@orkestrator/protocol": "2.
|
|
43
|
-
"@orkestrator/toolchain": "2.
|
|
42
|
+
"@orkestrator/protocol": "2.30.0-beta",
|
|
43
|
+
"@orkestrator/toolchain": "2.30.0-beta"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
|
-
"bun": ">=1.4.
|
|
46
|
+
"bun": ">=1.4.4"
|
|
47
47
|
},
|
|
48
48
|
"//dependencies": "Only modules scripts/build.ts leaves unbundled belong here; everything else is inlined into dist/ and resources/. tests/cli.test.ts derives this list from the built artifacts and fails if it drifts."
|
|
49
49
|
}
|
|
@@ -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;
|
|
@@ -13852,9 +13959,86 @@ function backgroundCommandInstruction(env) {
|
|
|
13852
13959
|
}
|
|
13853
13960
|
|
|
13854
13961
|
// ../../bridges/claude-bridge/src/services/claude-execution-sandbox.ts
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
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
|
+
}
|
|
13858
14042
|
if (policy?.sandbox !== "provider")
|
|
13859
14043
|
return;
|
|
13860
14044
|
return {
|
|
@@ -14789,7 +14973,9 @@ function claudeQueryOptions(turn, plan, turnFor, mcp) {
|
|
|
14789
14973
|
forwardSubagentText: true,
|
|
14790
14974
|
allowedTools,
|
|
14791
14975
|
...disallowedTools?.length ? { disallowedTools } : {},
|
|
14792
|
-
...policy?.sandbox === "provider" || coordinatorReadOnly ? {
|
|
14976
|
+
...policy?.sandbox === "provider" || coordinatorReadOnly ? {
|
|
14977
|
+
sandbox: claudeExecutionSandbox(policy, claudeAsksForApproval(policy, options), { cwd })
|
|
14978
|
+
} : {},
|
|
14793
14979
|
abortController,
|
|
14794
14980
|
...session.sdkSessionId ? { resume: session.sdkSessionId } : {
|
|
14795
14981
|
sessionId: sdkSessionIdFromBridgeId(session.id) ?? crypto.randomUUID()
|
|
@@ -14801,7 +14987,7 @@ function claudeQueryOptions(turn, plan, turnFor, mcp) {
|
|
|
14801
14987
|
systemPrompt: {
|
|
14802
14988
|
type: "preset",
|
|
14803
14989
|
preset: "claude_code",
|
|
14804
|
-
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." : [
|
|
14805
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.",
|
|
14806
14992
|
backgroundCommandInstruction(queryEnvironment),
|
|
14807
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.",
|
|
@@ -14866,6 +15052,34 @@ function observeClaudeMessage(diagnostics, message) {
|
|
|
14866
15052
|
}
|
|
14867
15053
|
}
|
|
14868
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
|
+
|
|
14869
15083
|
// ../../bridges/claude-bridge/src/services/session-manager-prompt-handlers/assistant.ts
|
|
14870
15084
|
function applyClaudeUsageReport(session, report) {
|
|
14871
15085
|
const previous = session.inProgressUsage ?? session.usage;
|
|
@@ -14924,10 +15138,13 @@ function handleAssistantMessage(turn, message) {
|
|
|
14924
15138
|
const receivedAt = new Date().toISOString();
|
|
14925
15139
|
const recordUnknownContentBlock = (blockType) => sessionHealth(session).recordUnknown(`block:${blockType}`);
|
|
14926
15140
|
const assistantError = message.error;
|
|
14927
|
-
if (assistantError === "authentication_failed")
|
|
15141
|
+
if (assistantError === "authentication_failed") {
|
|
14928
15142
|
noteClaudeAuthenticationFailure();
|
|
14929
|
-
|
|
15143
|
+
noteSessionLoginRefused(session, sessionId, typeof message.uuid === "string" ? message.uuid : crypto.randomUUID());
|
|
15144
|
+
} else if (!assistantError) {
|
|
14930
15145
|
noteClaudeAuthenticationWorked();
|
|
15146
|
+
setSessionAuthNotice(session, sessionId, undefined);
|
|
15147
|
+
}
|
|
14931
15148
|
const usageReport = message.usage_report;
|
|
14932
15149
|
if (usageReport) {
|
|
14933
15150
|
const usage = applyClaudeUsageReport(session, usageReport);
|
|
@@ -15212,6 +15429,16 @@ function handleAuthStatus(turn, message) {
|
|
|
15212
15429
|
severity: auth.error ? "error" : "info",
|
|
15213
15430
|
createdAt: new Date().toISOString()
|
|
15214
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);
|
|
15215
15442
|
}
|
|
15216
15443
|
function handleStreamEvent(turn, message) {
|
|
15217
15444
|
if (message.event?.type !== "ping") {
|
|
@@ -18014,7 +18241,8 @@ session.get("/:id", async (c) => {
|
|
|
18014
18241
|
completionBlockedByBackgroundTasks: sessionData.completionBlockedByBackgroundTasks === true,
|
|
18015
18242
|
rewindInProgress: sessionData.rewindInProgress === true,
|
|
18016
18243
|
...sessionData.commandInventoryState ? { commandRevision: sessionData.commandInventoryState.revision } : {},
|
|
18017
|
-
...readinessField()
|
|
18244
|
+
...readinessField(),
|
|
18245
|
+
...sessionData.authNotice ? { authNotice: sessionData.authNotice } : {}
|
|
18018
18246
|
});
|
|
18019
18247
|
});
|
|
18020
18248
|
function readinessField() {
|
|
@@ -19303,156 +19531,6 @@ mcp.get("/servers", async (c) => {
|
|
|
19303
19531
|
});
|
|
19304
19532
|
var mcp_default = mcp;
|
|
19305
19533
|
|
|
19306
|
-
// ../../bridges/claude-bridge/src/services/slash-commands.ts
|
|
19307
|
-
import { open as open3, readdir as readdir2, stat as stat4 } from "node:fs/promises";
|
|
19308
|
-
import { StringDecoder } from "node:string_decoder";
|
|
19309
|
-
import { join as join11, basename, dirname as dirname2 } from "node:path";
|
|
19310
|
-
var commandDescriptions = new Map;
|
|
19311
|
-
var MAX_COMMAND_DESCRIPTION_CACHE_ENTRIES = 512;
|
|
19312
|
-
function rememberCommandDescription(filePath, entry) {
|
|
19313
|
-
commandDescriptions.delete(filePath);
|
|
19314
|
-
commandDescriptions.set(filePath, entry);
|
|
19315
|
-
while (commandDescriptions.size > MAX_COMMAND_DESCRIPTION_CACHE_ENTRIES) {
|
|
19316
|
-
const oldest = commandDescriptions.keys().next();
|
|
19317
|
-
if (oldest.done)
|
|
19318
|
-
break;
|
|
19319
|
-
commandDescriptions.delete(oldest.value);
|
|
19320
|
-
}
|
|
19321
|
-
}
|
|
19322
|
-
var FRONTMATTER_READ_CHUNK_BYTES = 8 * 1024;
|
|
19323
|
-
var MAX_FRONTMATTER_READ_BYTES = 256 * 1024;
|
|
19324
|
-
function fingerprintOf2(stats) {
|
|
19325
|
-
return `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeMs}`;
|
|
19326
|
-
}
|
|
19327
|
-
function hasCompleteFrontmatter(content) {
|
|
19328
|
-
return /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/.test(content);
|
|
19329
|
-
}
|
|
19330
|
-
async function readFileFrontmatter(filePath) {
|
|
19331
|
-
const handle = await open3(filePath, "r");
|
|
19332
|
-
try {
|
|
19333
|
-
const decoder = new StringDecoder("utf8");
|
|
19334
|
-
let content = "";
|
|
19335
|
-
let position = 0;
|
|
19336
|
-
while (position < MAX_FRONTMATTER_READ_BYTES) {
|
|
19337
|
-
const readLength = Math.min(FRONTMATTER_READ_CHUNK_BYTES, MAX_FRONTMATTER_READ_BYTES - position);
|
|
19338
|
-
const buffer = Buffer.allocUnsafe(readLength);
|
|
19339
|
-
const { bytesRead } = await handle.read(buffer, 0, readLength, position);
|
|
19340
|
-
if (bytesRead === 0)
|
|
19341
|
-
break;
|
|
19342
|
-
position += bytesRead;
|
|
19343
|
-
content += decoder.write(buffer.subarray(0, bytesRead));
|
|
19344
|
-
if (position >= FRONTMATTER_READ_CHUNK_BYTES && !content.startsWith(`---
|
|
19345
|
-
`) && !content.startsWith(`---\r
|
|
19346
|
-
`) || hasCompleteFrontmatter(content)) {
|
|
19347
|
-
break;
|
|
19348
|
-
}
|
|
19349
|
-
}
|
|
19350
|
-
return content + decoder.end();
|
|
19351
|
-
} finally {
|
|
19352
|
-
await handle.close();
|
|
19353
|
-
}
|
|
19354
|
-
}
|
|
19355
|
-
async function readCommandDescription(filePath) {
|
|
19356
|
-
const fingerprint = fingerprintOf2(await stat4(filePath));
|
|
19357
|
-
const cached = commandDescriptions.get(filePath);
|
|
19358
|
-
if (cached && cached.fingerprint === fingerprint) {
|
|
19359
|
-
return cached.description;
|
|
19360
|
-
}
|
|
19361
|
-
const description = parseDescription(await readFileFrontmatter(filePath));
|
|
19362
|
-
rememberCommandDescription(filePath, { fingerprint, description });
|
|
19363
|
-
return description;
|
|
19364
|
-
}
|
|
19365
|
-
function pruneCommandDescriptionCache(commandsDir, livePaths) {
|
|
19366
|
-
for (const cachedPath of commandDescriptions.keys()) {
|
|
19367
|
-
if (dirname2(cachedPath) === commandsDir && !livePaths.has(cachedPath)) {
|
|
19368
|
-
commandDescriptions.delete(cachedPath);
|
|
19369
|
-
}
|
|
19370
|
-
}
|
|
19371
|
-
}
|
|
19372
|
-
var BUILTIN_COMMANDS = [
|
|
19373
|
-
"/clear - Clear conversation history",
|
|
19374
|
-
"/compact - Compact conversation to reduce tokens",
|
|
19375
|
-
"/context - Show current context",
|
|
19376
|
-
"/cost - Show token usage and cost",
|
|
19377
|
-
"/doctor - Check system health",
|
|
19378
|
-
"/goal - Set, view, or clear a completion goal",
|
|
19379
|
-
"/help - Show available commands",
|
|
19380
|
-
"/init - Re-initialize the session",
|
|
19381
|
-
"/logout - Log out of Claude",
|
|
19382
|
-
"/memory - Show memory usage",
|
|
19383
|
-
"/model - Show or change model",
|
|
19384
|
-
"/permissions - Manage permissions",
|
|
19385
|
-
"/review - Review recent changes",
|
|
19386
|
-
"/status - Show session status",
|
|
19387
|
-
"/vim - Toggle vim mode"
|
|
19388
|
-
];
|
|
19389
|
-
function parseDescription(content) {
|
|
19390
|
-
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
19391
|
-
if (!match?.[1])
|
|
19392
|
-
return;
|
|
19393
|
-
const frontmatter = match[1];
|
|
19394
|
-
const descMatch = frontmatter.match(/^description:\s*(?:"([^"]*?)"|'([^']*?)'|(.+?))\s*$/m);
|
|
19395
|
-
if (!descMatch)
|
|
19396
|
-
return;
|
|
19397
|
-
return (descMatch[1] ?? descMatch[2] ?? descMatch[3])?.trim();
|
|
19398
|
-
}
|
|
19399
|
-
async function scanCommandsDir(commandsDir, prefix) {
|
|
19400
|
-
let entries;
|
|
19401
|
-
try {
|
|
19402
|
-
entries = await readdir2(commandsDir);
|
|
19403
|
-
} catch {
|
|
19404
|
-
pruneCommandDescriptionCache(commandsDir, new Set);
|
|
19405
|
-
return [];
|
|
19406
|
-
}
|
|
19407
|
-
const commands = [];
|
|
19408
|
-
const livePaths = new Set;
|
|
19409
|
-
for (const entry of entries) {
|
|
19410
|
-
if (!entry.endsWith(".md"))
|
|
19411
|
-
continue;
|
|
19412
|
-
const name = basename(entry, ".md");
|
|
19413
|
-
const fullName = prefix ? `/${prefix}${name}` : `/${name}`;
|
|
19414
|
-
const commandPath = join11(commandsDir, entry);
|
|
19415
|
-
livePaths.add(commandPath);
|
|
19416
|
-
let description;
|
|
19417
|
-
try {
|
|
19418
|
-
description = await readCommandDescription(commandPath);
|
|
19419
|
-
} catch {}
|
|
19420
|
-
commands.push(description ? `${fullName} - ${description}` : fullName);
|
|
19421
|
-
}
|
|
19422
|
-
pruneCommandDescriptionCache(commandsDir, livePaths);
|
|
19423
|
-
return commands;
|
|
19424
|
-
}
|
|
19425
|
-
async function discoverSlashCommands(cwd) {
|
|
19426
|
-
const seen = new Set;
|
|
19427
|
-
const result = [];
|
|
19428
|
-
const addCommand = (cmd) => {
|
|
19429
|
-
const name = cmd.split(" - ")[0].trim().toLowerCase();
|
|
19430
|
-
if (!seen.has(name)) {
|
|
19431
|
-
seen.add(name);
|
|
19432
|
-
result.push(cmd);
|
|
19433
|
-
}
|
|
19434
|
-
};
|
|
19435
|
-
const repoCommands = await scanCommandsDir(join11(cwd, ".claude", "commands"), "");
|
|
19436
|
-
for (const cmd of repoCommands)
|
|
19437
|
-
addCommand(cmd);
|
|
19438
|
-
try {
|
|
19439
|
-
const plugins = await getMergedPlugins(cwd);
|
|
19440
|
-
for (const plugin of plugins) {
|
|
19441
|
-
const manifest = await readPluginManifest(plugin.path);
|
|
19442
|
-
const pluginName = manifest?.name || plugin.path.split("/").pop() || "unknown";
|
|
19443
|
-
const commandsDir = join11(plugin.path, "commands");
|
|
19444
|
-
const pluginCommands = await scanCommandsDir(commandsDir, `${pluginName}:`);
|
|
19445
|
-
for (const cmd of pluginCommands)
|
|
19446
|
-
addCommand(cmd);
|
|
19447
|
-
}
|
|
19448
|
-
} catch (error) {
|
|
19449
|
-
console.warn("[slash-commands] Failed to scan plugin commands:", error);
|
|
19450
|
-
}
|
|
19451
|
-
for (const cmd of BUILTIN_COMMANDS)
|
|
19452
|
-
addCommand(cmd);
|
|
19453
|
-
return result.sort((a, b) => a.localeCompare(b));
|
|
19454
|
-
}
|
|
19455
|
-
|
|
19456
19534
|
// ../../bridges/claude-bridge/src/routes/plugins.ts
|
|
19457
19535
|
var plugins = new Hono2;
|
|
19458
19536
|
plugins.get("/", async (c) => {
|
|
@@ -19468,21 +19546,12 @@ plugins.get("/", async (c) => {
|
|
|
19468
19546
|
return c.json({ error: error instanceof Error ? error.message : "Failed to get plugins" }, 500);
|
|
19469
19547
|
}
|
|
19470
19548
|
});
|
|
19471
|
-
plugins.get("/commands", async (c) => {
|
|
19472
|
-
try {
|
|
19473
|
-
const cwd = process.env.CWD || process.cwd();
|
|
19474
|
-
const commands = await discoverSlashCommands(cwd);
|
|
19475
|
-
return c.json({ commands });
|
|
19476
|
-
} catch (error) {
|
|
19477
|
-
console.error("[plugins] Error discovering slash commands:", error);
|
|
19478
|
-
return c.json({ error: error instanceof Error ? error.message : "Failed to discover slash commands" }, 500);
|
|
19479
|
-
}
|
|
19480
|
-
});
|
|
19481
19549
|
var plugins_default = plugins;
|
|
19482
19550
|
|
|
19483
19551
|
// ../protocol/src/parent-watchdog.ts
|
|
19484
19552
|
var PARENT_PID_ENV = "ORKESTRATOR_PARENT_PID";
|
|
19485
|
-
var
|
|
19553
|
+
var PARENT_WATCH_INTERVAL_MS = 1000;
|
|
19554
|
+
var DEFAULT_POLL_INTERVAL_MS = PARENT_WATCH_INTERVAL_MS;
|
|
19486
19555
|
function parseParentPid(value) {
|
|
19487
19556
|
if (!value)
|
|
19488
19557
|
return null;
|
|
@@ -21133,7 +21202,7 @@ compressTranscriptReads(app);
|
|
|
21133
21202
|
app.get("/global/auth-check", (c) => c.json({ status: "ok" }));
|
|
21134
21203
|
app.get("/global/auth", async (c) => c.json(await readClaudeAuthStatus()));
|
|
21135
21204
|
app.get("/global/usage", async (c) => c.json({ account: await readClaudePlanUsage() }));
|
|
21136
|
-
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));
|
|
21137
21206
|
app.post("/global/auth/logout", (c) => c.json({ error: "Claude sign-out is available from a terminal tab." }, 405));
|
|
21138
21207
|
app.post("/global/refresh-catalog", async (c) => {
|
|
21139
21208
|
await refreshClaudeCatalogs();
|