@cabane/companion 0.6.152 → 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 = {
@@ -4106,8 +4125,10 @@ function buildRunSpec(req, resumeSessionId) {
4106
4125
  sendClientMessageId: resumeSessionId == null,
4107
4126
  ...dialect.agent ? { agent: dialect.agent } : {},
4108
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.
4109
4130
  credentialServers: Object.entries(req.local.mcpServers ?? {}).filter(
4110
- ([, 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
4111
4132
  ).map(([name]) => name)
4112
4133
  };
4113
4134
  }
@@ -4136,10 +4157,11 @@ function buildMcp(req) {
4136
4157
  };
4137
4158
  } else if ("command" in server) {
4138
4159
  const command = [server.command, ...server.args ?? []];
4160
+ const environment = envResolvedFrom(server, req.local.secretEnv);
4139
4161
  mcp[name] = {
4140
4162
  type: "local",
4141
4163
  command,
4142
- ...server.env ? { environment: server.env } : {},
4164
+ ...environment ? { environment } : {},
4143
4165
  enabled: true
4144
4166
  };
4145
4167
  }
@@ -5426,9 +5448,20 @@ function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromp
5426
5448
  promptRidesInput,
5427
5449
  promptFingerprint,
5428
5450
  config: buildConfig(req, baseInstructionsFile),
5429
- secretEnv: req.local.secretEnv && Object.keys(req.local.secretEnv).length > 0 ? req.local.secretEnv : null
5451
+ secretEnv: codexSecretEnv(req)
5430
5452
  };
5431
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
+ }
5432
5465
  function buildInput(req, promptRidesInput) {
5433
5466
  const userText = req.content.filter((b) => b.type === "text").map((b) => b.text).join("\n\n");
5434
5467
  const body = userText.trim().length > 0 ? userText : req.prompt;
@@ -5457,10 +5490,12 @@ function buildConfig(req, baseInstructionsFile) {
5457
5490
  default_tools_approval_mode: "approve"
5458
5491
  };
5459
5492
  } else if ("command" in server) {
5493
+ const forwarded = Object.keys(server.envFromEnv ?? {}).sort();
5460
5494
  mcp_servers[name] = {
5461
5495
  command: server.command,
5462
5496
  ...server.args ? { args: server.args } : {},
5463
5497
  ...server.env ? { env: server.env } : {},
5498
+ ...forwarded.length > 0 ? { env_vars: forwarded } : {},
5464
5499
  default_tools_approval_mode: "approve"
5465
5500
  };
5466
5501
  }
@@ -7417,7 +7452,10 @@ var init_run_config = __esm({
7417
7452
  type: z15.literal("stdio").optional(),
7418
7453
  command: z15.string().min(1),
7419
7454
  args: z15.array(z15.string()).optional(),
7420
- 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()
7421
7459
  });
7422
7460
  mcpHttpServerSchema = z15.object({
7423
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 = {
@@ -5414,8 +5433,10 @@ function buildRunSpec(req, resumeSessionId) {
5414
5433
  sendClientMessageId: resumeSessionId == null,
5415
5434
  ...dialect.agent ? { agent: dialect.agent } : {},
5416
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.
5417
5438
  credentialServers: Object.entries(req.local.mcpServers ?? {}).filter(
5418
- ([, 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
5419
5440
  ).map(([name]) => name)
5420
5441
  };
5421
5442
  }
@@ -5444,10 +5465,11 @@ function buildMcp(req) {
5444
5465
  };
5445
5466
  } else if ("command" in server) {
5446
5467
  const command = [server.command, ...server.args ?? []];
5468
+ const environment = envResolvedFrom(server, req.local.secretEnv);
5447
5469
  mcp[name] = {
5448
5470
  type: "local",
5449
5471
  command,
5450
- ...server.env ? { environment: server.env } : {},
5472
+ ...environment ? { environment } : {},
5451
5473
  enabled: true
5452
5474
  };
5453
5475
  }
@@ -6656,9 +6678,20 @@ function buildRunSpec2(req, resumeThreadId, instructionsFile = null, threadPromp
6656
6678
  promptRidesInput,
6657
6679
  promptFingerprint,
6658
6680
  config: buildConfig(req, baseInstructionsFile),
6659
- secretEnv: req.local.secretEnv && Object.keys(req.local.secretEnv).length > 0 ? req.local.secretEnv : null
6681
+ secretEnv: codexSecretEnv(req)
6660
6682
  };
6661
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
+ }
6662
6695
  function buildInput(req, promptRidesInput) {
6663
6696
  const userText = req.content.filter((b) => b.type === "text").map((b) => b.text).join("\n\n");
6664
6697
  const body = userText.trim().length > 0 ? userText : req.prompt;
@@ -6687,10 +6720,12 @@ function buildConfig(req, baseInstructionsFile) {
6687
6720
  default_tools_approval_mode: "approve"
6688
6721
  };
6689
6722
  } else if ("command" in server) {
6723
+ const forwarded = Object.keys(server.envFromEnv ?? {}).sort();
6690
6724
  mcp_servers[name] = {
6691
6725
  command: server.command,
6692
6726
  ...server.args ? { args: server.args } : {},
6693
6727
  ...server.env ? { env: server.env } : {},
6728
+ ...forwarded.length > 0 ? { env_vars: forwarded } : {},
6694
6729
  default_tools_approval_mode: "approve"
6695
6730
  };
6696
6731
  }
@@ -8524,7 +8559,10 @@ var mcpStdioServerSchema = z15.object({
8524
8559
  type: z15.literal("stdio").optional(),
8525
8560
  command: z15.string().min(1),
8526
8561
  args: z15.array(z15.string()).optional(),
8527
- 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()
8528
8566
  });
8529
8567
  var mcpHttpServerSchema = z15.object({
8530
8568
  type: z15.literal("http"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.152",
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",