@integrity-labs/agt-cli 0.27.70 → 0.27.72

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  claudeModelAlias,
3
3
  isClaudeFastMode
4
- } from "./chunk-KPD5KJY7.js";
4
+ } from "./chunk-5SWHKUL3.js";
5
5
  import {
6
6
  reapOrphanChannelMcps
7
7
  } from "./chunk-XWVM4KPK.js";
@@ -1179,6 +1179,7 @@ function writeAcpxConfig(config) {
1179
1179
 
1180
1180
  export {
1181
1181
  formatMissingVar,
1182
+ parseEnvIntegrations,
1182
1183
  probeMcpEnvSubstitution,
1183
1184
  sanitizeMcpJson,
1184
1185
  buildAllowedTools,
@@ -1209,4 +1210,4 @@ export {
1209
1210
  stopAllSessionsAndWait,
1210
1211
  getProjectDir
1211
1212
  };
1212
- //# sourceMappingURL=chunk-DA3KY3D2.js.map
1213
+ //# sourceMappingURL=chunk-7YM2F3DG.js.map
@@ -9,7 +9,7 @@ import {
9
9
  parseDeliveryTarget,
10
10
  registerFramework,
11
11
  wrapScheduledTaskPrompt
12
- } from "./chunk-KPD5KJY7.js";
12
+ } from "./chunk-5SWHKUL3.js";
13
13
 
14
14
  // ../../packages/core/dist/integrations/registry.js
15
15
  var INTEGRATION_REGISTRY = [
@@ -2358,6 +2358,68 @@ registerFramework(nemoClawAdapter);
2358
2358
 
2359
2359
  // ../../packages/core/dist/provisioning/mcp-config-guards.js
2360
2360
  import { chmodSync as chmodSync4, existsSync as existsSync4, readFileSync as readFileSync4, renameSync as renameSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3 } from "fs";
2361
+
2362
+ // ../../packages/core/dist/provisioning/mcp-secret-lint.js
2363
+ var LITERAL_SECRET_PATTERNS = [
2364
+ // Slack bot token — `xoxb-<workspace>-<...>`
2365
+ { name: "slack_bot_token", re: /^xoxb-/ },
2366
+ // Slack app-level token (Socket Mode) — `xapp-<...>`
2367
+ { name: "slack_app_token", re: /^xapp-/ },
2368
+ // AGT host API key — `tlk_<...>` (see claudecode-plugin-augmented README).
2369
+ { name: "agt_host_api_key", re: /^tlk_/ },
2370
+ // Composio / generic api-key prefix — `ak_<...>`
2371
+ { name: "composio_api_key", re: /^ak_/ },
2372
+ // Telegram bot token — `<10-digit bot id>:AAE<...>` (BotFather format).
2373
+ { name: "telegram_bot_token", re: /^\d{10}:AAE/ },
2374
+ // ENG-5901 extension beyond the original AC's five patterns: a literal
2375
+ // JWT (`eyJ...`) is the shape of a leaked AGT_API_KEY, which the
2376
+ // value-prefix patterns above would otherwise miss. Header values often
2377
+ // carry it behind `Bearer ` (or a copy-pasted `Authorization: Bearer `),
2378
+ // so those prefixes are optionally consumed (CodeRabbit #1731).
2379
+ // Templates (`Bearer ${AGT_API_KEY}`) and concrete non-secret values
2380
+ // (UUIDs, hosts) never put `eyJ` after the prefix, so this stays
2381
+ // false-positive-safe inside .mcp.json.
2382
+ { name: "jwt_agt_api_key", re: /^(?:authorization:\s*)?(?:bearer\s+)?eyJ[A-Za-z0-9_-]+\./i }
2383
+ ];
2384
+ function matchLiteralSecret(value) {
2385
+ for (const { name, re } of LITERAL_SECRET_PATTERNS) {
2386
+ if (re.test(value))
2387
+ return name;
2388
+ }
2389
+ return null;
2390
+ }
2391
+ function scanRecord(server, record, location, findings) {
2392
+ if (!record)
2393
+ return;
2394
+ for (const [field, value] of Object.entries(record)) {
2395
+ if (typeof value !== "string")
2396
+ continue;
2397
+ const pattern = matchLiteralSecret(value);
2398
+ if (pattern)
2399
+ findings.push({ server, field, location, pattern });
2400
+ }
2401
+ }
2402
+ function scanConfigForLiteralSecrets(config) {
2403
+ const findings = [];
2404
+ if (typeof config !== "object" || config === null)
2405
+ return findings;
2406
+ const servers = config.mcpServers;
2407
+ if (typeof servers !== "object" || servers === null)
2408
+ return findings;
2409
+ for (const [server, raw] of Object.entries(servers)) {
2410
+ if (typeof raw !== "object" || raw === null)
2411
+ continue;
2412
+ const entry = raw;
2413
+ scanRecord(server, entry.env, "env", findings);
2414
+ scanRecord(server, entry.headers, "header", findings);
2415
+ }
2416
+ return findings;
2417
+ }
2418
+ function formatLiteralSecretRejection(f) {
2419
+ return `[mcp-write] [literal-secret-rejected] field=${f.field} server=${f.server} location=${f.location} pattern=${f.pattern}`;
2420
+ }
2421
+
2422
+ // ../../packages/core/dist/provisioning/mcp-config-guards.js
2361
2423
  var MCP_FILE_MODE = 384;
2362
2424
  var REQUIRED_ENV_RULES_BY_SERVER = {
2363
2425
  "cloud-broker": [
@@ -2507,6 +2569,21 @@ function safeWriteMcpJson(path, config) {
2507
2569
  if (!validation.ok) {
2508
2570
  return { written: false, errors: validation.errors };
2509
2571
  }
2572
+ const secretFindings = scanConfigForLiteralSecrets(config);
2573
+ if (secretFindings.length > 0) {
2574
+ for (const f of secretFindings) {
2575
+ process.stderr.write(`${formatLiteralSecretRejection(f)}
2576
+ `);
2577
+ }
2578
+ return {
2579
+ written: false,
2580
+ errors: secretFindings.map((f) => ({
2581
+ kind: "literal_secret",
2582
+ server: f.server,
2583
+ message: `literal secret in ${f.location} field '${f.field}' (pattern ${f.pattern}); expected a \${VAR} template`
2584
+ }))
2585
+ };
2586
+ }
2510
2587
  safeWriteJsonAtomic(path, JSON.stringify(config, null, 2), { mode: MCP_FILE_MODE });
2511
2588
  return { written: true, errors: [] };
2512
2589
  }
@@ -3761,11 +3838,102 @@ function resolveTemplate(input, ctx) {
3761
3838
  return { value, omit };
3762
3839
  }
3763
3840
 
3841
+ // ../../packages/core/dist/provisioning/env-integrations-file.js
3842
+ function shellQuote(value) {
3843
+ return `'${value.replace(/'/g, `'\\''`)}'`;
3844
+ }
3845
+ var CHANNEL_SECRET_ENV_KEYS = [
3846
+ "SLACK_BOT_TOKEN",
3847
+ "SLACK_APP_TOKEN",
3848
+ "TELEGRAM_BOT_TOKEN",
3849
+ "MSTEAMS_CLIENT_SECRET"
3850
+ ];
3851
+ var MCP_SERVER_SECRET_ENV_KEYS = [
3852
+ "COMPOSIO_API_KEY",
3853
+ "PIPEDREAM_CLIENT_SECRET"
3854
+ ];
3855
+ var PRESERVED_ENV_KEYS = [
3856
+ ...CHANNEL_SECRET_ENV_KEYS,
3857
+ ...MCP_SERVER_SECRET_ENV_KEYS
3858
+ ];
3859
+ var HEADER = "# Augmented integrations \u2014 auto-generated, do not edit";
3860
+ function parseEnvFileEntries(content) {
3861
+ const out = /* @__PURE__ */ new Map();
3862
+ for (const line of content.split("\n")) {
3863
+ if (!line || line.startsWith("#") || !line.includes("="))
3864
+ continue;
3865
+ const eqIdx = line.indexOf("=");
3866
+ out.set(line.slice(0, eqIdx), line.slice(eqIdx + 1));
3867
+ }
3868
+ return out;
3869
+ }
3870
+ function renderEnvIntegrations(entries) {
3871
+ const lines = [HEADER];
3872
+ for (const [key, rendered] of entries)
3873
+ lines.push(`${key}=${rendered}`);
3874
+ return lines.join("\n") + "\n";
3875
+ }
3876
+ function mergeEnvIntegrationsContent(existing, args) {
3877
+ const current = existing === null ? /* @__PURE__ */ new Map() : parseEnvFileEntries(existing);
3878
+ let next;
3879
+ if (args.mode === "upsert") {
3880
+ next = new Map(current);
3881
+ for (const [key, raw] of Object.entries(args.updates)) {
3882
+ if (raw === null)
3883
+ next.delete(key);
3884
+ else
3885
+ next.set(key, shellQuote(raw));
3886
+ }
3887
+ } else {
3888
+ next = /* @__PURE__ */ new Map();
3889
+ for (const [key, raw] of Object.entries(args.updates)) {
3890
+ if (raw !== null)
3891
+ next.set(key, shellQuote(raw));
3892
+ }
3893
+ const preserve = args.preserveKeys ?? PRESERVED_ENV_KEYS;
3894
+ for (const key of preserve) {
3895
+ if (key in args.updates)
3896
+ continue;
3897
+ if (!next.has(key) && current.has(key)) {
3898
+ next.set(key, current.get(key));
3899
+ }
3900
+ }
3901
+ }
3902
+ return renderEnvIntegrations(next);
3903
+ }
3904
+
3764
3905
  // ../../packages/core/dist/provisioning/frameworks/claudecode/index.js
3765
3906
  var VALID_CODE_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
3766
3907
  var SECRET_FILE_MODE = 384;
3767
- function shellQuote(value) {
3768
- return `'${value.replace(/'/g, `'\\''`)}'`;
3908
+ function writeEnvIntegrationsForAgent(codeName, args) {
3909
+ const agentDir = getAgentDir(codeName);
3910
+ const envPath = join4(agentDir, ".env.integrations");
3911
+ let existing = null;
3912
+ try {
3913
+ existing = readFileSync5(envPath, "utf-8");
3914
+ } catch {
3915
+ }
3916
+ if (existing === null && Object.keys(args.updates).length === 0)
3917
+ return;
3918
+ const content = mergeEnvIntegrationsContent(existing, args);
3919
+ writeFileSync5(envPath, content, { mode: SECRET_FILE_MODE });
3920
+ try {
3921
+ chmodSync5(envPath, SECRET_FILE_MODE);
3922
+ } catch {
3923
+ }
3924
+ try {
3925
+ const projectDir = getProjectDir(codeName);
3926
+ mkdirSync4(projectDir, { recursive: true });
3927
+ const dest = join4(projectDir, ".env.integrations");
3928
+ writeFileSync5(dest, content, { mode: SECRET_FILE_MODE });
3929
+ try {
3930
+ chmodSync5(dest, SECRET_FILE_MODE);
3931
+ } catch {
3932
+ }
3933
+ } catch (err) {
3934
+ process.stderr.write(`[env-integrations] [mirror-write-failed] agent=${codeName} error=${err.message}
3935
+ `);
3936
+ }
3769
3937
  }
3770
3938
  function assertValidCodeName(codeName) {
3771
3939
  if (!VALID_CODE_NAME.test(codeName)) {
@@ -4070,14 +4238,23 @@ function deployArtifactsToProject(codeName, provisionDir) {
4070
4238
  return !(entry && typeof entry["url"] === "string" && entry["url"].startsWith("/"));
4071
4239
  }));
4072
4240
  projectMcp["mcpServers"] = { ...stripRelativeUrls(projectServers), ...stripRelativeUrls(agentServers) };
4073
- writeFileSync5(projectMcpPath, JSON.stringify(projectMcp, null, 2));
4241
+ writeFileSync5(projectMcpPath, JSON.stringify(projectMcp, null, 2), { mode: MCP_FILE_MODE });
4242
+ try {
4243
+ chmodSync5(projectMcpPath, MCP_FILE_MODE);
4244
+ } catch {
4245
+ }
4074
4246
  } catch {
4075
4247
  }
4076
4248
  const agentDir = getAgentDir(codeName);
4077
4249
  for (const envFile of [".env", ".env.integrations"]) {
4078
4250
  try {
4079
4251
  const content = readFileSync5(join4(agentDir, envFile), "utf-8");
4080
- writeFileSync5(join4(projectDir, envFile), content);
4252
+ const envDest = join4(projectDir, envFile);
4253
+ writeFileSync5(envDest, content, { mode: SECRET_FILE_MODE });
4254
+ try {
4255
+ chmodSync5(envDest, SECRET_FILE_MODE);
4256
+ } catch {
4257
+ }
4081
4258
  } catch {
4082
4259
  }
4083
4260
  }
@@ -4751,7 +4928,13 @@ function buildMcpJson(input) {
4751
4928
  args: [localMcpPath],
4752
4929
  env: {
4753
4930
  AGT_HOST: process.env["AGT_HOST"] ?? "",
4754
- AGT_API_KEY: process.env["AGT_API_KEY"] ?? "",
4931
+ // ENG-5901 Track D: templated — the manager exports AGT_API_KEY to
4932
+ // every spawn env (getApiKey()), and Claude Code substitutes at
4933
+ // MCP-launch (same contract as AGT_RUN_ID below). The impersonation
4934
+ // redeem path renders this server-side with no AGT_API_KEY in env;
4935
+ // impersonate-mcp-rewrite.ts treats the literal `${AGT_API_KEY}`
4936
+ // placeholder as fillable and swaps in the operator token.
4937
+ AGT_API_KEY: "${AGT_API_KEY}",
4755
4938
  AGT_AGENT_ID: input.agent.agent_id,
4756
4939
  AGT_AGENT_CODE_NAME: input.agent.code_name,
4757
4940
  // ENG-4561: Claude Code substitutes `${VAR}` in .mcp.json env values
@@ -5151,11 +5334,15 @@ ${sections}`
5151
5334
  const localTelegramChannel = join4(getHomeDir3(), ".augmented", "_mcp", "telegram-channel.js");
5152
5335
  const resolvedAgtHostForTelegram = process.env["AGT_HOST"]?.trim() || "https://api.augmented.team";
5153
5336
  const resolvedAgtApiKeyForTelegram = process.env["AGT_API_KEY"]?.trim();
5337
+ writeEnvIntegrationsForAgent(codeName, {
5338
+ mode: "upsert",
5339
+ updates: { TELEGRAM_BOT_TOKEN: botToken }
5340
+ });
5154
5341
  const telegramEnv = {
5155
- TELEGRAM_BOT_TOKEN: botToken,
5342
+ TELEGRAM_BOT_TOKEN: "${TELEGRAM_BOT_TOKEN}",
5156
5343
  AGT_AGENT_CODE_NAME: codeName,
5157
5344
  AGT_HOST: resolvedAgtHostForTelegram,
5158
- ...resolvedAgtApiKeyForTelegram ? { AGT_API_KEY: resolvedAgtApiKeyForTelegram } : {},
5345
+ ...resolvedAgtApiKeyForTelegram ? { AGT_API_KEY: "${AGT_API_KEY}" } : {},
5159
5346
  ...options?.agentId ? { AGT_AGENT_ID: options.agentId } : {},
5160
5347
  ...tzEnv
5161
5348
  };
@@ -5235,7 +5422,9 @@ ${sections}`
5235
5422
  ...blockKitAskUserEnabled ? { SLACK_BLOCK_KIT_ASK_USER_ENABLED: "true" } : {},
5236
5423
  ...blockKitDisabled ? { SLACK_BLOCK_KIT_DISABLED: "true" } : {},
5237
5424
  ...blockKitAskUserEnabled ? { AGT_HOST: resolvedAgtHost } : {},
5238
- ...blockKitAskUserEnabled && process.env["AGT_API_KEY"] ? { AGT_API_KEY: process.env["AGT_API_KEY"] } : {},
5425
+ // ENG-5901 Track D: template (manager exports the real value
5426
+ // to every spawn env); gate unchanged.
5427
+ ...blockKitAskUserEnabled && process.env["AGT_API_KEY"] ? { AGT_API_KEY: "${AGT_API_KEY}" } : {},
5239
5428
  ...blockKitAskUserEnabled && options?.agentId ? { AGT_AGENT_ID: options.agentId } : {}
5240
5429
  } : {};
5241
5430
  if (botToken) {
@@ -5264,16 +5453,26 @@ ${sections}`
5264
5453
  const slackResolvedAgtApiKey = process.env["AGT_API_KEY"]?.trim();
5265
5454
  const slackAgtAuthEnv = {
5266
5455
  AGT_HOST: resolvedAgtHost,
5267
- ...slackResolvedAgtApiKey ? { AGT_API_KEY: slackResolvedAgtApiKey } : {},
5456
+ // ENG-5901 Track D: template manager exports AGT_API_KEY to
5457
+ // every spawn env (getApiKey()); the gate still keys off the
5458
+ // manager actually having one.
5459
+ ...slackResolvedAgtApiKey ? { AGT_API_KEY: "${AGT_API_KEY}" } : {},
5268
5460
  ...options?.agentId ? { AGT_AGENT_ID: options.agentId } : {}
5269
5461
  };
5462
+ writeEnvIntegrationsForAgent(codeName, {
5463
+ mode: "upsert",
5464
+ updates: {
5465
+ SLACK_BOT_TOKEN: botToken,
5466
+ ...appToken ? { SLACK_APP_TOKEN: appToken } : {}
5467
+ }
5468
+ });
5270
5469
  const localSlackChannel = join4(getHomeDir3(), ".augmented", "_mcp", "slack-channel.js");
5271
5470
  const slackEntry = {
5272
5471
  command: existsSync5(localSlackChannel) ? "node" : "npx",
5273
5472
  args: existsSync5(localSlackChannel) ? [localSlackChannel] : ["-y", "@augmented/claude-code-channel-slack"],
5274
5473
  env: {
5275
- SLACK_BOT_TOKEN: botToken,
5276
- ...appToken ? { SLACK_APP_TOKEN: appToken } : {},
5474
+ SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}",
5475
+ ...appToken ? { SLACK_APP_TOKEN: "${SLACK_APP_TOKEN}" } : {},
5277
5476
  ...threadAutoFollow && threadAutoFollow !== "off" ? { SLACK_THREAD_AUTO_FOLLOW: threadAutoFollow } : {},
5278
5477
  // ENG-4464: only emit when non-default — `mention_only` is the
5279
5478
  // default in slack-response-mode.ts, so omitting keeps the env
@@ -5384,7 +5583,8 @@ ${sections}`
5384
5583
  ...oneshotBlockKitAskUserEnabled ? { SLACK_BLOCK_KIT_ASK_USER_ENABLED: "true" } : {},
5385
5584
  ...oneshotBlockKitDisabled ? { SLACK_BLOCK_KIT_DISABLED: "true" } : {},
5386
5585
  ...oneshotBlockKitAskUserEnabled ? { AGT_HOST: oneshotResolvedAgtHost } : {},
5387
- ...oneshotBlockKitAskUserEnabled && process.env["AGT_API_KEY"] ? { AGT_API_KEY: process.env["AGT_API_KEY"] } : {},
5586
+ // ENG-5901 Track D: template; manager spawn env carries the value.
5587
+ ...oneshotBlockKitAskUserEnabled && process.env["AGT_API_KEY"] ? { AGT_API_KEY: "${AGT_API_KEY}" } : {},
5388
5588
  ...oneshotBlockKitAskUserEnabled && options?.agentId ? { AGT_AGENT_ID: options.agentId } : {}
5389
5589
  } : {};
5390
5590
  const slackPeerEnv = {};
@@ -5417,16 +5617,24 @@ ${sections}`
5417
5617
  const slackAgtAuthEnv = {
5418
5618
  AGT_HOST: process.env["AGT_HOST"]?.trim() || "https://api.augmented.team",
5419
5619
  AGT_AGENT_CODE_NAME: codeName,
5420
- ...slackResolvedAgtApiKey ? { AGT_API_KEY: slackResolvedAgtApiKey } : {},
5620
+ // ENG-5901 Track D: template; manager spawn env carries the value.
5621
+ ...slackResolvedAgtApiKey ? { AGT_API_KEY: "${AGT_API_KEY}" } : {},
5421
5622
  ...options?.agentId ? { AGT_AGENT_ID: options.agentId } : {}
5422
5623
  };
5624
+ writeEnvIntegrationsForAgent(codeName, {
5625
+ mode: "upsert",
5626
+ updates: {
5627
+ SLACK_BOT_TOKEN: botToken,
5628
+ ...appToken ? { SLACK_APP_TOKEN: appToken } : {}
5629
+ }
5630
+ });
5423
5631
  if (isPersistent && existsSync5(localSlackChannel)) {
5424
5632
  mcpServers["slack"] = {
5425
5633
  command: "node",
5426
5634
  args: [localSlackChannel],
5427
5635
  env: {
5428
- SLACK_BOT_TOKEN: botToken,
5429
- ...appToken ? { SLACK_APP_TOKEN: appToken } : {},
5636
+ SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}",
5637
+ ...appToken ? { SLACK_APP_TOKEN: "${SLACK_APP_TOKEN}" } : {},
5430
5638
  ...slackAutoFollowEnv,
5431
5639
  ...slackResponseModeEnv,
5432
5640
  ...oneshotBlockKitEnv,
@@ -5440,8 +5648,8 @@ ${sections}`
5440
5648
  command: "npx",
5441
5649
  args: ["-y", "@augmented/claude-code-channel-slack"],
5442
5650
  env: {
5443
- SLACK_BOT_TOKEN: botToken,
5444
- ...appToken ? { SLACK_APP_TOKEN: appToken } : {},
5651
+ SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}",
5652
+ ...appToken ? { SLACK_APP_TOKEN: "${SLACK_APP_TOKEN}" } : {},
5445
5653
  ...slackAutoFollowEnv,
5446
5654
  ...slackResponseModeEnv,
5447
5655
  ...oneshotBlockKitEnv,
@@ -5478,12 +5686,17 @@ ${sections}`
5478
5686
  const msteamsAgtAuthEnv = {
5479
5687
  AGT_HOST: process.env["AGT_HOST"]?.trim() || "https://api.augmented.team",
5480
5688
  AGT_AGENT_CODE_NAME: codeName,
5481
- ...msResolvedAgtApiKey ? { AGT_API_KEY: msResolvedAgtApiKey } : {},
5689
+ // ENG-5901 Track D: template; manager spawn env carries the value.
5690
+ ...msResolvedAgtApiKey ? { AGT_API_KEY: "${AGT_API_KEY}" } : {},
5482
5691
  ...options?.agentId ? { AGT_AGENT_ID: options.agentId } : {}
5483
5692
  };
5693
+ writeEnvIntegrationsForAgent(codeName, {
5694
+ mode: "upsert",
5695
+ updates: { MSTEAMS_CLIENT_SECRET: clientSecret }
5696
+ });
5484
5697
  const teamsEnv = {
5485
5698
  MSTEAMS_APP_ID: appId,
5486
- MSTEAMS_CLIENT_SECRET: clientSecret,
5699
+ MSTEAMS_CLIENT_SECRET: "${MSTEAMS_CLIENT_SECRET}",
5487
5700
  MSTEAMS_TENANT_ID: tenantId,
5488
5701
  ...botObjectId ? { MSTEAMS_BOT_OBJECT_ID: botObjectId } : {},
5489
5702
  ...allowedTeamIds.length > 0 ? { MSTEAMS_ALLOWED_TEAMS: allowedTeamIds.join(",") } : {},
@@ -5601,19 +5814,19 @@ ${sections}`
5601
5814
  ...integration,
5602
5815
  credentials: decryptIntegrationCredentials(integration.credentials)
5603
5816
  }));
5604
- const envLines = ["# Augmented integrations \u2014 auto-generated, do not edit"];
5817
+ const envUpdates = {};
5605
5818
  for (const integration of decryptedIntegrations) {
5606
5819
  const prefix = integration.definition_id.toUpperCase().replace(/[^A-Z0-9]/g, "_");
5607
5820
  const creds = integration.credentials;
5608
5821
  if (integration.auth_type === "oauth2") {
5609
5822
  const accessToken = creds.access_token;
5610
5823
  if (accessToken) {
5611
- envLines.push(`${prefix}_ACCESS_TOKEN=${shellQuote(accessToken)}`);
5824
+ envUpdates[`${prefix}_ACCESS_TOKEN`] = accessToken;
5612
5825
  }
5613
5826
  } else if (integration.auth_type === "api_key") {
5614
5827
  const apiKey = creds.api_key;
5615
5828
  if (apiKey) {
5616
- envLines.push(`${prefix}_API_KEY=${shellQuote(apiKey)}`);
5829
+ envUpdates[`${prefix}_API_KEY`] = apiKey;
5617
5830
  }
5618
5831
  }
5619
5832
  if (integration.config) {
@@ -5622,7 +5835,7 @@ ${sections}`
5622
5835
  if (typeof value === "string" && value) {
5623
5836
  const upperKey = key.toUpperCase();
5624
5837
  const envKey = upperKey.startsWith(`${prefix}_`) ? upperKey : `${prefix}_${upperKey}`;
5625
- envLines.push(`${envKey}=${shellQuote(value)}`);
5838
+ envUpdates[envKey] = value;
5626
5839
  }
5627
5840
  }
5628
5841
  }
@@ -5633,16 +5846,15 @@ ${sections}`
5633
5846
  if (!defaults)
5634
5847
  continue;
5635
5848
  for (const [key, value] of Object.entries(defaults)) {
5636
- if (envLines.some((line) => line.startsWith(`${key}=`)))
5849
+ if (key in envUpdates)
5637
5850
  continue;
5638
- envLines.push(`${key}=${shellQuote(value)}`);
5851
+ envUpdates[key] = value;
5639
5852
  }
5640
5853
  }
5641
- if (envLines.length > 1) {
5642
- const envPath = join4(agentDir, ".env.integrations");
5643
- writeFileSync5(envPath, envLines.join("\n") + "\n");
5644
- chmodSync5(envPath, SECRET_FILE_MODE);
5645
- }
5854
+ writeEnvIntegrationsForAgent(codeName, {
5855
+ mode: "replace-preserving",
5856
+ updates: envUpdates
5857
+ });
5646
5858
  writeXurlStoreForIntegrations(decryptedIntegrations);
5647
5859
  for (const integration of decryptedIntegrations) {
5648
5860
  const def = INTEGRATION_REGISTRY.find((d) => d.id === integration.definition_id);
@@ -5763,7 +5975,12 @@ ${sections}`
5763
5975
  const envSrc = join4(agentDir2, ".env.integrations");
5764
5976
  try {
5765
5977
  const envContent = readFileSync5(envSrc, "utf-8");
5766
- writeFileSync5(join4(projectDir, ".env.integrations"), envContent);
5978
+ const envDest = join4(projectDir, ".env.integrations");
5979
+ writeFileSync5(envDest, envContent, { mode: SECRET_FILE_MODE });
5980
+ try {
5981
+ chmodSync5(envDest, SECRET_FILE_MODE);
5982
+ } catch {
5983
+ }
5767
5984
  } catch {
5768
5985
  }
5769
5986
  } catch {
@@ -5788,6 +6005,26 @@ ${sections}`
5788
6005
  let serverEntry;
5789
6006
  if ("url" in config) {
5790
6007
  serverEntry = buildUrlMcpServerEntry(config.url, config.headers, config.type);
6008
+ const hoisted = {};
6009
+ const entryHeaders = serverEntry.headers;
6010
+ if (entryHeaders) {
6011
+ const composioKey = entryHeaders["x-api-key"];
6012
+ if (composioKey && !composioKey.includes("${")) {
6013
+ hoisted["COMPOSIO_API_KEY"] = composioKey;
6014
+ entryHeaders["x-api-key"] = "${COMPOSIO_API_KEY}";
6015
+ }
6016
+ }
6017
+ const entryEnv = serverEntry.env;
6018
+ if (entryEnv) {
6019
+ const pdSecret = entryEnv["PIPEDREAM_CLIENT_SECRET"];
6020
+ if (pdSecret && !pdSecret.includes("${")) {
6021
+ hoisted["PIPEDREAM_CLIENT_SECRET"] = pdSecret;
6022
+ entryEnv["PIPEDREAM_CLIENT_SECRET"] = "${PIPEDREAM_CLIENT_SECRET}";
6023
+ }
6024
+ }
6025
+ if (Object.keys(hoisted).length > 0) {
6026
+ writeEnvIntegrationsForAgent(codeName, { mode: "upsert", updates: hoisted });
6027
+ }
5791
6028
  } else {
5792
6029
  serverEntry = { command: config.command };
5793
6030
  if (config.args?.length)
@@ -7213,6 +7450,7 @@ async function managerUninstallSystemUnitCommand() {
7213
7450
  export {
7214
7451
  getIntegration,
7215
7452
  extractCommandNotFound,
7453
+ LITERAL_SECRET_PATTERNS,
7216
7454
  safeWriteJsonAtomic,
7217
7455
  INTEGRATIONS_SECTION_START,
7218
7456
  INTEGRATIONS_SECTION_END,
@@ -7250,4 +7488,4 @@ export {
7250
7488
  managerInstallSystemUnitCommand,
7251
7489
  managerUninstallSystemUnitCommand
7252
7490
  };
7253
- //# sourceMappingURL=chunk-CM2FTSRM.js.map
7491
+ //# sourceMappingURL=chunk-IW6Q53DB.js.map