@integrity-labs/agt-cli 0.28.724 → 0.28.726

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.
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-CEC5KESY.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-LP7JOGZ5.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-XWPOUQMP.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-42GBPDC7.js.map
@@ -57,7 +57,7 @@ import {
57
57
  safeWriteJsonAtomic,
58
58
  setConfigHash,
59
59
  tripClass
60
- } from "../chunk-KOAHMMPZ.js";
60
+ } from "../chunk-Z3N7J2MG.js";
61
61
  import {
62
62
  getProjectDir as getProjectDir2,
63
63
  getReadyTasks,
@@ -90,8 +90,11 @@ import {
90
90
  isolationMode,
91
91
  log,
92
92
  mergeOpencodeConfigArtifact,
93
+ modelPolicyAuthComponent,
94
+ modelPolicyEgressDomains,
93
95
  paneLogPath,
94
96
  parseEnvIntegrations,
97
+ parseModelPolicy,
95
98
  prepareForRespawn,
96
99
  readChannelServerEnv,
97
100
  readDirectChatSessionState,
@@ -115,7 +118,7 @@ import {
115
118
  takeZombieDetection,
116
119
  toOpencodeModel,
117
120
  writeEgressAllowlist
118
- } from "../chunk-ATJU3SDV.js";
121
+ } from "../chunk-ZCTFF4PA.js";
119
122
  import {
120
123
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
121
124
  AnchorSessionClient,
@@ -2880,21 +2883,29 @@ var COMPONENT_ORDER = [
2880
2883
  "auth_mode",
2881
2884
  "anthropic_api_key_fingerprint",
2882
2885
  "claude_account_fingerprint",
2883
- "openrouter_fingerprint"
2886
+ "openrouter_fingerprint",
2887
+ // ENG-9483 slice 2: `<policyId>@<revision>` from modelPolicyAuthComponent.
2888
+ // Non-secret: a uuid the operator chose plus an integer they can see in the UI.
2889
+ "model_policy"
2884
2890
  ];
2891
+ var POLICY_TUPLE_SEPARATOR = "|policy=";
2885
2892
  function parseAuthTuple(tuple) {
2886
- const raw = typeof tuple === "string" ? tuple : "";
2893
+ const full = typeof tuple === "string" ? tuple : "";
2894
+ const sepAt = full.lastIndexOf(POLICY_TUPLE_SEPARATOR);
2895
+ const raw = sepAt === -1 ? full : full.slice(0, sepAt);
2896
+ const policy = sepAt === -1 ? null : full.slice(sepAt + POLICY_TUPLE_SEPARATOR.length) || ABSENT2;
2897
+ const withPolicy = (r) => policy === null ? r : { ...r, model_policy: policy };
2887
2898
  if (raw.startsWith("openrouter:")) {
2888
- return {
2899
+ return withPolicy({
2889
2900
  auth_mode: "openrouter",
2890
2901
  openrouter_fingerprint: raw.slice("openrouter:".length) || ABSENT2
2891
- };
2902
+ });
2892
2903
  }
2893
2904
  const parts = raw.split(":");
2894
2905
  if (parts.length < 2) {
2895
- return { auth_mode: raw || ABSENT2 };
2906
+ return withPolicy({ auth_mode: raw || ABSENT2 });
2896
2907
  }
2897
- return {
2908
+ return withPolicy({
2898
2909
  auth_mode: parts[0] || ABSENT2,
2899
2910
  anthropic_api_key_fingerprint: parts[1] || ABSENT2,
2900
2911
  // Omitted from the string when there is no signed-in account fingerprint
@@ -2902,7 +2913,19 @@ function parseAuthTuple(tuple) {
2902
2913
  // Recorded as the ABSENT sentinel so "account appeared" / "account
2903
2914
  // disappeared" is itself visible as a change.
2904
2915
  claude_account_fingerprint: parts[2] || ABSENT2
2905
- };
2916
+ });
2917
+ }
2918
+ function buildAuthTuple(input) {
2919
+ const {
2920
+ openRouterCredential,
2921
+ claudeAuthMode,
2922
+ anthropicApiKeyFingerprint,
2923
+ claudeAccountFingerprint,
2924
+ modelPolicyComponent
2925
+ } = input;
2926
+ const suffix = modelPolicyComponent ? `${POLICY_TUPLE_SEPARATOR}${modelPolicyComponent}` : "";
2927
+ if (openRouterCredential) return `openrouter:${openRouterCredential}${suffix}`;
2928
+ return `${claudeAuthMode}:${anthropicApiKeyFingerprint ?? ABSENT2}${claudeAccountFingerprint ? `:${claudeAccountFingerprint}` : ""}${suffix}`;
2906
2929
  }
2907
2930
  function diffAuthTuples(recorded, current) {
2908
2931
  const before = parseAuthTuple(recorded);
@@ -5138,6 +5161,16 @@ function slugToTitle(slug) {
5138
5161
  function escapeYamlDouble(value) {
5139
5162
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
5140
5163
  }
5164
+ function resolveIntegrationSkillLane(payload) {
5165
+ if (payload.integration_skills_manifest !== void 0 && payload.integration_skills === void 0) {
5166
+ return null;
5167
+ }
5168
+ return payload.integration_skills ?? payload.plugin_skills ?? [];
5169
+ }
5170
+ function planIntegrationSkillSweep(discovered, currentIds, desiredResolved) {
5171
+ if (!desiredResolved) return [];
5172
+ return [...discovered].filter((entry) => !currentIds.has(entry));
5173
+ }
5141
5174
  function groupSkillsByIntegration(skills) {
5142
5175
  const map = /* @__PURE__ */ new Map();
5143
5176
  for (const s of skills) {
@@ -5365,19 +5398,14 @@ function sweepSkillCache(cacheDir, now = Date.now()) {
5365
5398
  } catch {
5366
5399
  }
5367
5400
  }
5368
- async function resolveSkillsFromManifest(args) {
5369
- const { globals, shared, cacheDir, fetchContents, log: log2 } = args;
5401
+ async function collectBodies(hashes, cacheDir, fetchContents, lane, log2) {
5370
5402
  const bodies = /* @__PURE__ */ new Map();
5371
5403
  const missing = [];
5372
- for (const entry of [...globals, ...shared]) {
5373
- if (!entry.hash) {
5374
- log2?.(`[skills] manifest entry '${entry.code_name}' has no hash \u2014 skipping skill sync`);
5375
- return null;
5376
- }
5377
- if (bodies.has(entry.hash) || missing.includes(entry.hash)) continue;
5378
- const cached = readCachedSkill(cacheDir, entry.hash);
5379
- if (cached !== null) bodies.set(entry.hash, cached);
5380
- else missing.push(entry.hash);
5404
+ for (const hash of hashes) {
5405
+ if (bodies.has(hash) || missing.includes(hash)) continue;
5406
+ const cached = readCachedSkill(cacheDir, hash);
5407
+ if (cached !== null) bodies.set(hash, cached);
5408
+ else missing.push(hash);
5381
5409
  }
5382
5410
  for (let i = 0; i < missing.length; i += SKILL_FETCH_CHUNK) {
5383
5411
  const chunk2 = missing.slice(i, i + SKILL_FETCH_CHUNK);
@@ -5385,19 +5413,32 @@ async function resolveSkillsFromManifest(args) {
5385
5413
  for (const { hash, content } of await fetchContents(chunk2)) {
5386
5414
  const written = writeCachedSkill(cacheDir, hash, content);
5387
5415
  if (written === "mismatch") {
5388
- log2?.(`[skills] hash mismatch for ${hash} \u2014 skipping skill sync this poll`);
5416
+ log2?.(`[${lane}] hash mismatch for ${hash} \u2014 skipping skill sync this poll`);
5389
5417
  continue;
5390
5418
  }
5391
5419
  if (written === "write-failed") {
5392
- log2?.(`[skills] cache write failed for ${hash} \u2014 serving it uncached this poll`);
5420
+ log2?.(`[${lane}] cache write failed for ${hash} \u2014 serving it uncached this poll`);
5393
5421
  }
5394
5422
  bodies.set(hash, content);
5395
5423
  }
5396
5424
  } catch (err) {
5397
- log2?.(`[skills] fetch failed for ${chunk2.length} entries: ${err.message}`);
5425
+ log2?.(`[${lane}] fetch failed for ${chunk2.length} entries: ${err.message}`);
5398
5426
  }
5399
5427
  }
5400
5428
  sweepSkillCache(cacheDir);
5429
+ return bodies;
5430
+ }
5431
+ async function resolveSkillsFromManifest(args) {
5432
+ const { globals, shared, cacheDir, fetchContents, log: log2 } = args;
5433
+ const hashes = [];
5434
+ for (const entry of [...globals, ...shared]) {
5435
+ if (!entry.hash) {
5436
+ log2?.(`[skills] manifest entry '${entry.code_name}' has no hash \u2014 skipping skill sync`);
5437
+ return null;
5438
+ }
5439
+ hashes.push(entry.hash);
5440
+ }
5441
+ const bodies = await collectBodies(hashes, cacheDir, fetchContents, "skills", log2);
5401
5442
  const resolve2 = (entries) => {
5402
5443
  const out = [];
5403
5444
  for (const e of entries) {
@@ -5420,6 +5461,47 @@ async function resolveSkillsFromManifest(args) {
5420
5461
  }
5421
5462
  return { globals: resolvedGlobals, shared: resolvedShared };
5422
5463
  }
5464
+ async function resolveIntegrationSkillsFromManifest(args) {
5465
+ const { manifest, cacheDir, fetchContents, log: log2 } = args;
5466
+ const hashes = [];
5467
+ for (const entry of manifest) {
5468
+ if (entry.hash) {
5469
+ hashes.push(entry.hash);
5470
+ continue;
5471
+ }
5472
+ if (typeof entry.content !== "string") {
5473
+ log2?.(
5474
+ `[integration-skills] manifest entry '${entry.plugin_slug}/${entry.skill_id}' has neither hash nor content \u2014 skipping integration skill sync`
5475
+ );
5476
+ return null;
5477
+ }
5478
+ }
5479
+ const bodies = await collectBodies(
5480
+ hashes,
5481
+ cacheDir,
5482
+ fetchContents,
5483
+ "integration-skills",
5484
+ log2
5485
+ );
5486
+ const out = [];
5487
+ for (const e of manifest) {
5488
+ const content = e.hash ? bodies.get(e.hash) : e.content;
5489
+ if (content === void 0) {
5490
+ log2?.(
5491
+ "[integration-skills] one or more bodies unresolved \u2014 leaving on-disk integration skills untouched this poll"
5492
+ );
5493
+ return null;
5494
+ }
5495
+ out.push({
5496
+ plugin_slug: e.plugin_slug,
5497
+ ...e.integration_slug !== void 0 ? { integration_slug: e.integration_slug } : {},
5498
+ skill_id: e.skill_id,
5499
+ skill_name: e.skill_name,
5500
+ content
5501
+ });
5502
+ }
5503
+ return out;
5504
+ }
5423
5505
 
5424
5506
  // src/lib/channel-hash-cache.ts
5425
5507
  import { existsSync as existsSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync10 } from "fs";
@@ -12184,7 +12266,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
12184
12266
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
12185
12267
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
12186
12268
  async function channelInboundActivityAgeSecondsFor(codeName) {
12187
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-J3VB4U4W.js");
12269
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-TTHNHBBS.js");
12188
12270
  const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
12189
12271
  if (newest === null) return null;
12190
12272
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -12832,7 +12914,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
12832
12914
  var lastVersionCheckAt = 0;
12833
12915
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
12834
12916
  var lastResponsivenessProbeAt = 0;
12835
- var agtCliVersion = true ? "0.28.724" : "dev";
12917
+ var agtCliVersion = true ? "0.28.726" : "dev";
12836
12918
  function resolveBrewPath(execFileSync3) {
12837
12919
  try {
12838
12920
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -14359,7 +14441,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
14359
14441
  if (codeNames.length === 0) return;
14360
14442
  void (async () => {
14361
14443
  try {
14362
- const { collectDiagnostics } = await import("../persistent-session-CEC5KESY.js");
14444
+ const { collectDiagnostics } = await import("../persistent-session-LP7JOGZ5.js");
14363
14445
  await api.post("/host/heartbeat", {
14364
14446
  host_id: hostId,
14365
14447
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -14477,7 +14559,7 @@ async function pollCycleInner() {
14477
14559
  }
14478
14560
  try {
14479
14561
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
14480
- const { collectDiagnostics } = await import("../persistent-session-CEC5KESY.js");
14562
+ const { collectDiagnostics } = await import("../persistent-session-LP7JOGZ5.js");
14481
14563
  const diagCodeNames = [...agentState.persistentSessionAgents];
14482
14564
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
14483
14565
  let tailscaleHostname;
@@ -14646,7 +14728,7 @@ async function pollCycleInner() {
14646
14728
  collectPanelessActivityProbes,
14647
14729
  getResponsivenessIntervalMs,
14648
14730
  occupancyQualificationClassifications
14649
- } = await import("../responsiveness-probe-J3VB4U4W.js");
14731
+ } = await import("../responsiveness-probe-TTHNHBBS.js");
14650
14732
  const probeIntervalMs = getResponsivenessIntervalMs();
14651
14733
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
14652
14734
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -14756,7 +14838,7 @@ async function pollCycleInner() {
14756
14838
  collectResponsivenessProbes,
14757
14839
  livePendingInboundOldestAgeSeconds,
14758
14840
  parkPendingInbound
14759
- } = await import("../responsiveness-probe-J3VB4U4W.js");
14841
+ } = await import("../responsiveness-probe-TTHNHBBS.js");
14760
14842
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
14761
14843
  const wedgeNow = /* @__PURE__ */ new Date();
14762
14844
  const liveAgents = agentState.persistentSessionAgents;
@@ -15677,7 +15759,13 @@ async function processAgent(agent, agentStates, managedToolkits) {
15677
15759
  // ENG-9585: the same for the two root-skill lanes. A separate flag
15678
15760
  // because the two shipped in different CLI versions — an API that
15679
15761
  // understands one and not the other must still be able to answer.
15680
- skills_manifest: true
15762
+ skills_manifest: true,
15763
+ // ENG-9585: and the integration lane, a third flag for the same reason
15764
+ // one level sharper. A manager that sent `skills_manifest` but could not
15765
+ // decode THIS manifest would read the lane as empty and sweep every
15766
+ // integration skill folder off disk, so the flag has to name the exact
15767
+ // capability rather than the family.
15768
+ integration_skills_manifest: true
15681
15769
  });
15682
15770
  if (refreshData.knowledge_manifest) {
15683
15771
  const resolved = await resolveKnowledgeFromManifest({
@@ -15714,6 +15802,23 @@ async function processAgent(agent, agentStates, managedToolkits) {
15714
15802
  refreshData.shared_skills = resolvedSkills.shared;
15715
15803
  }
15716
15804
  }
15805
+ if (refreshData.integration_skills_manifest) {
15806
+ const resolvedIntegrationSkills = await resolveIntegrationSkillsFromManifest({
15807
+ manifest: refreshData.integration_skills_manifest,
15808
+ cacheDir: join40(config.configDir, "_skills"),
15809
+ fetchContents: async (hashes) => {
15810
+ const res = await api.post(
15811
+ "/host/skills/contents",
15812
+ { agent_id: agent.agent_id, hashes }
15813
+ );
15814
+ return res.contents ?? [];
15815
+ },
15816
+ log
15817
+ });
15818
+ if (resolvedIntegrationSkills) {
15819
+ refreshData.integration_skills = resolvedIntegrationSkills;
15820
+ }
15821
+ }
15717
15822
  } catch (err) {
15718
15823
  log(`Refresh failed for '${agent.code_name}': ${err.message}`);
15719
15824
  const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
@@ -16988,9 +17093,10 @@ async function processAgent(agent, agentStates, managedToolkits) {
16988
17093
  agent_id: agent.agent_id,
16989
17094
  knowledge_manifest: true,
16990
17095
  // Only `scheduled_tasks` is read here, so ask for the manifest shape on
16991
- // both lanes — nothing in this branch consumes a skill body, and the
17096
+ // every lane — nothing in this branch consumes a skill body, and the
16992
17097
  // skill lanes are the largest part of the payload being discarded.
16993
- skills_manifest: true
17098
+ skills_manifest: true,
17099
+ integration_skills_manifest: true
16994
17100
  });
16995
17101
  tasks = freshData.scheduled_tasks ?? tasks;
16996
17102
  }
@@ -17023,9 +17129,17 @@ async function processAgent(agent, agentStates, managedToolkits) {
17023
17129
  if (!slug) continue;
17024
17130
  contextBySlug.set(slug, { values: ctx.values ?? {}, overrides: (ctx.overrides ?? "").trim() });
17025
17131
  }
17026
- const integrationGroups = groupSkillsByIntegration(
17027
- refreshAny.integration_skills ?? refreshAny.plugin_skills ?? []
17028
- );
17132
+ const integrationSkillsInput = resolveIntegrationSkillLane({
17133
+ integration_skills: refreshAny.integration_skills,
17134
+ plugin_skills: refreshAny.plugin_skills,
17135
+ integration_skills_manifest: refreshAny.integration_skills_manifest
17136
+ });
17137
+ if (integrationSkillsInput === null) {
17138
+ log(
17139
+ `Integration skill manifest unresolved for '${agent.code_name}' \u2014 leaving integration skill folders untouched this poll`
17140
+ );
17141
+ }
17142
+ const integrationGroups = groupSkillsByIntegration(integrationSkillsInput ?? []);
17029
17143
  for (const [integrationSlug, scopes] of integrationGroups) {
17030
17144
  try {
17031
17145
  const integrationSkillId = `integration-${integrationSlug}`.replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
@@ -17104,10 +17218,12 @@ async function processAgent(agent, agentStates, managedToolkits) {
17104
17218
  });
17105
17219
  log(`Removed ${reason} '${entry}' for '${agent.code_name}' (framework=${frameworkId2})`);
17106
17220
  };
17107
- for (const entry of discoveredEntries) {
17108
- if (!currentIntegrationSkillIds.has(entry)) {
17109
- removeSkillFolder(entry, "orphaned skill folder");
17110
- }
17221
+ for (const entry of planIntegrationSkillSweep(
17222
+ discoveredEntries,
17223
+ currentIntegrationSkillIds,
17224
+ integrationSkillsInput !== null
17225
+ )) {
17226
+ removeSkillFolder(entry, "orphaned skill folder");
17111
17227
  }
17112
17228
  } catch (err) {
17113
17229
  log(`Integration skill cleanup failed for '${agent.code_name}': ${err.message}`);
@@ -17907,9 +18023,10 @@ var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
17907
18023
  var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
17908
18024
  var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
17909
18025
  var egressAllowlistBySession = /* @__PURE__ */ new Map();
17910
- function deriveEgressAllowlist(toolsRaw) {
18026
+ function deriveEgressAllowlist(toolsRaw, policy) {
17911
18027
  return buildEgressAllowlist(
17912
- toolsRaw ? extractFrontmatter(toolsRaw).frontmatter : null
18028
+ toolsRaw ? extractFrontmatter(toolsRaw).frontmatter : null,
18029
+ modelPolicyEgressDomains(policy)
17913
18030
  );
17914
18031
  }
17915
18032
  var egressAllowlistEqual = (a, b) => a.length === b.length && a.every((d, i) => d === b[i]);
@@ -18052,6 +18169,9 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
18052
18169
  smallFastModel: openRouterRaw.small_fast_model ?? null,
18053
18170
  fingerprint: openRouterRaw.fingerprint ?? null
18054
18171
  } : null;
18172
+ const modelPolicy = parseModelPolicy(
18173
+ refreshData.model_policy
18174
+ );
18055
18175
  let claudeAuthMode;
18056
18176
  let anthropicApiKey;
18057
18177
  let anthropicApiKeyFingerprint;
@@ -18153,7 +18273,13 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
18153
18273
  let dayRolloverForced = false;
18154
18274
  const claudeAccountFingerprint = !openRouterForAgent && claudeAuthMode === "subscription" ? await getClaudeAccountFingerprint() : null;
18155
18275
  noteClaudeAccountChange(codeName, claudeAccountFingerprint, log);
18156
- const currentAuthTuple = openRouterForAgent ? `openrouter:${openRouterForAgent.fingerprint ?? openRouterForAgent.model}` : `${claudeAuthMode}:${anthropicApiKeyFingerprint ?? "none"}${claudeAccountFingerprint ? `:${claudeAccountFingerprint}` : ""}`;
18276
+ const currentAuthTuple = buildAuthTuple({
18277
+ openRouterCredential: openRouterForAgent ? openRouterForAgent.fingerprint ?? openRouterForAgent.model : null,
18278
+ claudeAuthMode,
18279
+ anthropicApiKeyFingerprint,
18280
+ claudeAccountFingerprint,
18281
+ modelPolicyComponent: modelPolicyAuthComponent(modelPolicy)
18282
+ });
18157
18283
  const recordedAuthTuple = claudeAuthTupleBySession.get(codeName);
18158
18284
  if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && isSessionHealthy(codeName)) {
18159
18285
  const authTupleDiff = diffAuthTuples(recordedAuthTuple, currentAuthTuple);
@@ -18320,7 +18446,8 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash19("sha256")
18320
18446
  trackSessionRun(codeName, sessionRunResult.run_id);
18321
18447
  const spawnPrimaryModel = resolveModelChain(refreshData).primary ?? refreshData.agent?.["primary_model"] ?? null;
18322
18448
  const egressAllowlist = deriveEgressAllowlist(
18323
- refreshData.tools?.raw_content
18449
+ refreshData.tools?.raw_content,
18450
+ modelPolicy
18324
18451
  );
18325
18452
  egressAllowlistBySession.set(codeName, egressAllowlist);
18326
18453
  let perAgentApiKey = null;
@@ -18373,6 +18500,17 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash19("sha256")
18373
18500
  model: openRouterForAgent.model,
18374
18501
  smallFastModel: openRouterForAgent.smallFastModel
18375
18502
  } : null,
18503
+ // ENG-9483 slice 2 (ADR-0074). The SHAPE reaches the launcher; the
18504
+ // credential does not. `modelPolicyGatewayToken` is deliberately absent
18505
+ // (⇒ null) rather than wired to some plausible existing secret: slice 1's
18506
+ // resolver never selects `model_policy_bindings.credential`, and ENG-9481's
18507
+ // stored-key-vs-pass-through answer decides whether the credential is a
18508
+ // `gateway_token` (needing ANTHROPIC_CUSTOM_HEADERS, an at-rest secret this
18509
+ // tree does not have) or a plain `api_key` (which does not). Until then a
18510
+ // gateway binding resolves to `blocked` and the agent keeps its existing
18511
+ // auth — see resolveBindingCredential, the one function that changes when
18512
+ // that question is answered.
18513
+ modelPolicy,
18376
18514
  runId: sessionRunResult.run_id,
18377
18515
  agentTimezone,
18378
18516
  // ENG-6476: materialize the host-side reply-routing flags into the agent
@@ -18427,7 +18565,8 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash19("sha256")
18427
18565
  resetRestartCount(codeName);
18428
18566
  if (egressMode(codeName) === "allowlist") {
18429
18567
  const allowlist = deriveEgressAllowlist(
18430
- refreshData.tools?.raw_content
18568
+ refreshData.tools?.raw_content,
18569
+ modelPolicy
18431
18570
  );
18432
18571
  const prev = egressAllowlistBySession.get(codeName);
18433
18572
  if (!prev || !egressAllowlistEqual(prev, allowlist)) {
@@ -18770,7 +18909,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
18770
18909
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
18771
18910
  void (async () => {
18772
18911
  try {
18773
- const { collectDiagnostics } = await import("../persistent-session-CEC5KESY.js");
18912
+ const { collectDiagnostics } = await import("../persistent-session-LP7JOGZ5.js");
18774
18913
  await api.post("/host/heartbeat", {
18775
18914
  host_id: hostId,
18776
18915
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -18821,7 +18960,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
18821
18960
  }
18822
18961
  try {
18823
18962
  const hostId = await getHostId();
18824
- const { collectDiagnostics } = await import("../persistent-session-CEC5KESY.js");
18963
+ const { collectDiagnostics } = await import("../persistent-session-LP7JOGZ5.js");
18825
18964
  await api.post("/host/heartbeat", {
18826
18965
  host_id: hostId,
18827
18966
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -19453,7 +19592,7 @@ async function processClaudePairSessions(agents) {
19453
19592
  killPairSession,
19454
19593
  pairTmuxSession,
19455
19594
  finalizeClaudePairOnboarding
19456
- } = await import("../claude-pair-runtime-XWPOUQMP.js");
19595
+ } = await import("../claude-pair-runtime-42GBPDC7.js");
19457
19596
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
19458
19597
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
19459
19598
  const killed = await killPairSession(pairTmuxSession(pairId));