@cabane/companion 0.6.151 → 0.6.153

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/cli.js CHANGED
@@ -1892,7 +1892,8 @@ var init_turn_request = __esm({
1892
1892
  type: z8.literal("stdio").optional(),
1893
1893
  command: z8.string(),
1894
1894
  args: z8.array(z8.string()).optional(),
1895
- env: z8.record(z8.string(), z8.string()).optional()
1895
+ env: z8.record(z8.string(), z8.string()).optional(),
1896
+ envFromEnv: z8.record(z8.string(), z8.string()).optional()
1896
1897
  }),
1897
1898
  z8.object({
1898
1899
  type: z8.literal("http"),
@@ -2439,6 +2440,22 @@ function headersResolvedFrom(server, secretEnv) {
2439
2440
  if (!server.headers && Object.keys(resolved).length === 0) return void 0;
2440
2441
  return { ...server.headers, ...resolved };
2441
2442
  }
2443
+ function envAsEnvReferences(server) {
2444
+ const refs = Object.entries(server.envFromEnv ?? {}).map(
2445
+ ([variable, envName]) => [variable, `\${${envName}}`]
2446
+ );
2447
+ if (!server.env && refs.length === 0) return void 0;
2448
+ return { ...server.env, ...Object.fromEntries(refs) };
2449
+ }
2450
+ function envResolvedFrom(server, secretEnv) {
2451
+ const resolved = {};
2452
+ for (const [variable, envName] of Object.entries(server.envFromEnv ?? {})) {
2453
+ const value = secretEnv?.[envName];
2454
+ if (value !== void 0) resolved[variable] = value;
2455
+ }
2456
+ if (!server.env && Object.keys(resolved).length === 0) return void 0;
2457
+ return { ...server.env, ...resolved };
2458
+ }
2442
2459
  var init_mcp_secret_env = __esm({
2443
2460
  "packages/agent-runtime/src/mcp-secret-env.ts"() {
2444
2461
  "use strict";
@@ -2600,7 +2617,9 @@ function buildClaudeCodeOptions(req, augment) {
2600
2617
  const headers = headersAsEnvReferences(server);
2601
2618
  userServers[name] = { ...rest, ...headers ? { headers } : {} };
2602
2619
  } else {
2603
- userServers[name] = server;
2620
+ const { envFromEnv: _refs, env: _env, ...rest } = server;
2621
+ const env = envAsEnvReferences(server);
2622
+ userServers[name] = { ...rest, ...env ? { env } : {} };
2604
2623
  }
2605
2624
  }
2606
2625
  const mcpServers = {
@@ -2690,7 +2709,12 @@ function buildClaudeCodeOptions(req, augment) {
2690
2709
  if (useCodingPreset) {
2691
2710
  options = {
2692
2711
  ...base,
2693
- systemPrompt: { type: "preset", preset: "claude_code", append: req.systemPrompt },
2712
+ systemPrompt: {
2713
+ type: "preset",
2714
+ preset: "claude_code",
2715
+ append: req.systemPrompt,
2716
+ snapshot: false
2717
+ },
2694
2718
  settingSources: ["project"],
2695
2719
  allowedTools,
2696
2720
  disallowedTools,
@@ -2699,7 +2723,7 @@ function buildClaudeCodeOptions(req, augment) {
2699
2723
  } else {
2700
2724
  options = {
2701
2725
  ...base,
2702
- systemPrompt: req.systemPrompt,
2726
+ systemPrompt: { type: "custom", prompt: req.systemPrompt, snapshot: false },
2703
2727
  allowedTools,
2704
2728
  disallowedTools,
2705
2729
  permissionMode: "bypassPermissions",
@@ -4101,8 +4125,10 @@ function buildRunSpec(req, resumeSessionId) {
4101
4125
  sendClientMessageId: resumeSessionId == null,
4102
4126
  ...dialect.agent ? { agent: dialect.agent } : {},
4103
4127
  mcp: buildMcp(req),
4128
+ // Every server this turn installs with a credential resolved into it: a remote one's
4129
+ // `headersFromEnv`, a stdio one's `envFromEnv`. None may take an operator-configured name.
4104
4130
  credentialServers: Object.entries(req.local.mcpServers ?? {}).filter(
4105
- ([, server]) => "url" in server && Object.keys(server.headersFromEnv ?? {}).length > 0
4131
+ ([, server]) => "url" in server ? Object.keys(server.headersFromEnv ?? {}).length > 0 : Object.keys(server.envFromEnv ?? {}).length > 0
4106
4132
  ).map(([name]) => name)
4107
4133
  };
4108
4134
  }
@@ -4131,10 +4157,11 @@ function buildMcp(req) {
4131
4157
  };
4132
4158
  } else if ("command" in server) {
4133
4159
  const command = [server.command, ...server.args ?? []];
4160
+ const environment = envResolvedFrom(server, req.local.secretEnv);
4134
4161
  mcp[name] = {
4135
4162
  type: "local",
4136
4163
  command,
4137
- ...server.env ? { environment: server.env } : {},
4164
+ ...environment ? { environment } : {},
4138
4165
  enabled: true
4139
4166
  };
4140
4167
  }
@@ -5421,9 +5448,20 @@ function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromp
5421
5448
  promptRidesInput,
5422
5449
  promptFingerprint,
5423
5450
  config: buildConfig(req, baseInstructionsFile),
5424
- secretEnv: req.local.secretEnv && Object.keys(req.local.secretEnv).length > 0 ? req.local.secretEnv : null
5451
+ secretEnv: codexSecretEnv(req)
5425
5452
  };
5426
5453
  }
5454
+ function codexSecretEnv(req) {
5455
+ const env = { ...req.local.secretEnv };
5456
+ for (const server of Object.values(req.local.mcpServers ?? {})) {
5457
+ if ("url" in server) continue;
5458
+ for (const [variable, envName] of Object.entries(server.envFromEnv ?? {})) {
5459
+ const value = req.local.secretEnv?.[envName];
5460
+ if (value !== void 0) env[variable] = value;
5461
+ }
5462
+ }
5463
+ return Object.keys(env).length > 0 ? env : null;
5464
+ }
5427
5465
  function buildInput(req, promptRidesInput) {
5428
5466
  const userText = req.content.filter((b) => b.type === "text").map((b) => b.text).join("\n\n");
5429
5467
  const body = userText.trim().length > 0 ? userText : req.prompt;
@@ -5452,10 +5490,12 @@ function buildConfig(req, baseInstructionsFile) {
5452
5490
  default_tools_approval_mode: "approve"
5453
5491
  };
5454
5492
  } else if ("command" in server) {
5493
+ const forwarded = Object.keys(server.envFromEnv ?? {}).sort();
5455
5494
  mcp_servers[name] = {
5456
5495
  command: server.command,
5457
5496
  ...server.args ? { args: server.args } : {},
5458
5497
  ...server.env ? { env: server.env } : {},
5498
+ ...forwarded.length > 0 ? { env_vars: forwarded } : {},
5459
5499
  default_tools_approval_mode: "approve"
5460
5500
  };
5461
5501
  }
@@ -7412,7 +7452,10 @@ var init_run_config = __esm({
7412
7452
  type: z15.literal("stdio").optional(),
7413
7453
  command: z15.string().min(1),
7414
7454
  args: z15.array(z15.string()).optional(),
7415
- env: z15.record(z15.string(), z15.string()).optional()
7455
+ env: z15.record(z15.string(), z15.string()).optional(),
7456
+ // Variable → the name of a `secretEnv` entry holding its value. Set by the server on a
7457
+ // room's shared browser, whose connect URL is a credential.
7458
+ envFromEnv: z15.record(z15.string(), z15.string()).optional()
7416
7459
  });
7417
7460
  mcpHttpServerSchema = z15.object({
7418
7461
  type: z15.literal("http"),
package/dist/runtime.js CHANGED
@@ -3355,7 +3355,8 @@ var resolvedMcpServerSchema = z8.union([
3355
3355
  type: z8.literal("stdio").optional(),
3356
3356
  command: z8.string(),
3357
3357
  args: z8.array(z8.string()).optional(),
3358
- env: z8.record(z8.string(), z8.string()).optional()
3358
+ env: z8.record(z8.string(), z8.string()).optional(),
3359
+ envFromEnv: z8.record(z8.string(), z8.string()).optional()
3359
3360
  }),
3360
3361
  z8.object({
3361
3362
  type: z8.literal("http"),
@@ -3857,6 +3858,22 @@ function headersResolvedFrom(server, secretEnv) {
3857
3858
  if (!server.headers && Object.keys(resolved).length === 0) return void 0;
3858
3859
  return { ...server.headers, ...resolved };
3859
3860
  }
3861
+ function envAsEnvReferences(server) {
3862
+ const refs = Object.entries(server.envFromEnv ?? {}).map(
3863
+ ([variable, envName]) => [variable, `\${${envName}}`]
3864
+ );
3865
+ if (!server.env && refs.length === 0) return void 0;
3866
+ return { ...server.env, ...Object.fromEntries(refs) };
3867
+ }
3868
+ function envResolvedFrom(server, secretEnv) {
3869
+ const resolved = {};
3870
+ for (const [variable, envName] of Object.entries(server.envFromEnv ?? {})) {
3871
+ const value = secretEnv?.[envName];
3872
+ if (value !== void 0) resolved[variable] = value;
3873
+ }
3874
+ if (!server.env && Object.keys(resolved).length === 0) return void 0;
3875
+ return { ...server.env, ...resolved };
3876
+ }
3860
3877
 
3861
3878
  // packages/agent-runtime/src/claude-code/policy.ts
3862
3879
  import { z as z10 } from "zod";
@@ -3998,7 +4015,9 @@ function buildClaudeCodeOptions(req, augment) {
3998
4015
  const headers = headersAsEnvReferences(server);
3999
4016
  userServers[name] = { ...rest, ...headers ? { headers } : {} };
4000
4017
  } else {
4001
- userServers[name] = server;
4018
+ const { envFromEnv: _refs, env: _env, ...rest } = server;
4019
+ const env = envAsEnvReferences(server);
4020
+ userServers[name] = { ...rest, ...env ? { env } : {} };
4002
4021
  }
4003
4022
  }
4004
4023
  const mcpServers = {
@@ -4088,7 +4107,12 @@ function buildClaudeCodeOptions(req, augment) {
4088
4107
  if (useCodingPreset) {
4089
4108
  options = {
4090
4109
  ...base,
4091
- systemPrompt: { type: "preset", preset: "claude_code", append: req.systemPrompt },
4110
+ systemPrompt: {
4111
+ type: "preset",
4112
+ preset: "claude_code",
4113
+ append: req.systemPrompt,
4114
+ snapshot: false
4115
+ },
4092
4116
  settingSources: ["project"],
4093
4117
  allowedTools,
4094
4118
  disallowedTools,
@@ -4097,7 +4121,7 @@ function buildClaudeCodeOptions(req, augment) {
4097
4121
  } else {
4098
4122
  options = {
4099
4123
  ...base,
4100
- systemPrompt: req.systemPrompt,
4124
+ systemPrompt: { type: "custom", prompt: req.systemPrompt, snapshot: false },
4101
4125
  allowedTools,
4102
4126
  disallowedTools,
4103
4127
  permissionMode: "bypassPermissions",
@@ -5409,8 +5433,10 @@ function buildRunSpec(req, resumeSessionId) {
5409
5433
  sendClientMessageId: resumeSessionId == null,
5410
5434
  ...dialect.agent ? { agent: dialect.agent } : {},
5411
5435
  mcp: buildMcp(req),
5436
+ // Every server this turn installs with a credential resolved into it: a remote one's
5437
+ // `headersFromEnv`, a stdio one's `envFromEnv`. None may take an operator-configured name.
5412
5438
  credentialServers: Object.entries(req.local.mcpServers ?? {}).filter(
5413
- ([, server]) => "url" in server && Object.keys(server.headersFromEnv ?? {}).length > 0
5439
+ ([, server]) => "url" in server ? Object.keys(server.headersFromEnv ?? {}).length > 0 : Object.keys(server.envFromEnv ?? {}).length > 0
5414
5440
  ).map(([name]) => name)
5415
5441
  };
5416
5442
  }
@@ -5439,10 +5465,11 @@ function buildMcp(req) {
5439
5465
  };
5440
5466
  } else if ("command" in server) {
5441
5467
  const command = [server.command, ...server.args ?? []];
5468
+ const environment = envResolvedFrom(server, req.local.secretEnv);
5442
5469
  mcp[name] = {
5443
5470
  type: "local",
5444
5471
  command,
5445
- ...server.env ? { environment: server.env } : {},
5472
+ ...environment ? { environment } : {},
5446
5473
  enabled: true
5447
5474
  };
5448
5475
  }
@@ -6651,9 +6678,20 @@ function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromp
6651
6678
  promptRidesInput,
6652
6679
  promptFingerprint,
6653
6680
  config: buildConfig(req, baseInstructionsFile),
6654
- secretEnv: req.local.secretEnv && Object.keys(req.local.secretEnv).length > 0 ? req.local.secretEnv : null
6681
+ secretEnv: codexSecretEnv(req)
6655
6682
  };
6656
6683
  }
6684
+ function codexSecretEnv(req) {
6685
+ const env = { ...req.local.secretEnv };
6686
+ for (const server of Object.values(req.local.mcpServers ?? {})) {
6687
+ if ("url" in server) continue;
6688
+ for (const [variable, envName] of Object.entries(server.envFromEnv ?? {})) {
6689
+ const value = req.local.secretEnv?.[envName];
6690
+ if (value !== void 0) env[variable] = value;
6691
+ }
6692
+ }
6693
+ return Object.keys(env).length > 0 ? env : null;
6694
+ }
6657
6695
  function buildInput(req, promptRidesInput) {
6658
6696
  const userText = req.content.filter((b) => b.type === "text").map((b) => b.text).join("\n\n");
6659
6697
  const body = userText.trim().length > 0 ? userText : req.prompt;
@@ -6682,10 +6720,12 @@ function buildConfig(req, baseInstructionsFile) {
6682
6720
  default_tools_approval_mode: "approve"
6683
6721
  };
6684
6722
  } else if ("command" in server) {
6723
+ const forwarded = Object.keys(server.envFromEnv ?? {}).sort();
6685
6724
  mcp_servers[name] = {
6686
6725
  command: server.command,
6687
6726
  ...server.args ? { args: server.args } : {},
6688
6727
  ...server.env ? { env: server.env } : {},
6728
+ ...forwarded.length > 0 ? { env_vars: forwarded } : {},
6689
6729
  default_tools_approval_mode: "approve"
6690
6730
  };
6691
6731
  }
@@ -8519,7 +8559,10 @@ var mcpStdioServerSchema = z15.object({
8519
8559
  type: z15.literal("stdio").optional(),
8520
8560
  command: z15.string().min(1),
8521
8561
  args: z15.array(z15.string()).optional(),
8522
- env: z15.record(z15.string(), z15.string()).optional()
8562
+ env: z15.record(z15.string(), z15.string()).optional(),
8563
+ // Variable → the name of a `secretEnv` entry holding its value. Set by the server on a
8564
+ // room's shared browser, whose connect URL is a credential.
8565
+ envFromEnv: z15.record(z15.string(), z15.string()).optional()
8523
8566
  });
8524
8567
  var mcpHttpServerSchema = z15.object({
8525
8568
  type: z15.literal("http"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.151",
3
+ "version": "0.6.153",
4
4
  "type": "module",
5
5
  "description": "The Cabane Companion (headless): connect a coding agent on your machine to your Cabane workspace as a responder — drive work against your own codebase, files, and MCP servers without putting any of it in Cabane.",
6
6
  "license": "UNLICENSED",