@algosuite/vo-mcp 0.2.0-beta.28 → 0.2.0-beta.29

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.
@@ -3001,6 +3001,62 @@ var init_windows_claude_launch = __esm({
3001
3001
  }
3002
3002
  });
3003
3003
 
3004
+ // ../../scripts/virtual-office/code-runner/claude-credential-choice.mjs
3005
+ function isTruthyFlag(v) {
3006
+ const s = String(v ?? "").trim().toLowerCase();
3007
+ return s === "1" || s === "true" || s === "yes" || s === "on";
3008
+ }
3009
+ function wantsLogin(env2) {
3010
+ return isTruthyFlag(env2[CLAUDE_PREFER_LOGIN_ENV]) || isTruthyFlag(env2[PREFER_LOGIN_ENV]);
3011
+ }
3012
+ function wantsKey(env2) {
3013
+ return isTruthyFlag(env2[CLAUDE_PREFER_KEY_ENV]) || isTruthyFlag(env2[PREFER_KEY_ENV]);
3014
+ }
3015
+ function classifyClaudeCredential(baseEnv = {}, { getKey, probeLogin } = {}) {
3016
+ const preferKey = wantsKey(baseEnv);
3017
+ if (!preferKey && wantsLogin(baseEnv)) {
3018
+ return { source: CLAUDE_CREDENTIAL_SOURCE.PREFER_LOGIN, key: null };
3019
+ }
3020
+ if (baseEnv.ANTHROPIC_API_KEY) {
3021
+ return { source: CLAUDE_CREDENTIAL_SOURCE.ENV_KEY, key: null };
3022
+ }
3023
+ const key = getKey();
3024
+ if (!key) {
3025
+ return { source: CLAUDE_CREDENTIAL_SOURCE.NO_KEY, key: null };
3026
+ }
3027
+ if (preferKey) {
3028
+ return { source: CLAUDE_CREDENTIAL_SOURCE.KEYCHAIN_PREFER_KEY, key };
3029
+ }
3030
+ if (probeLogin() === true) {
3031
+ return { source: CLAUDE_CREDENTIAL_SOURCE.SUBSCRIPTION_WINS, key: null };
3032
+ }
3033
+ return { source: CLAUDE_CREDENTIAL_SOURCE.KEYCHAIN, key };
3034
+ }
3035
+ var PREFER_LOGIN_ENV, CLAUDE_PREFER_LOGIN_ENV, PREFER_KEY_ENV, CLAUDE_PREFER_KEY_ENV, CLAUDE_CREDENTIAL_SOURCE;
3036
+ var init_claude_credential_choice = __esm({
3037
+ "../../scripts/virtual-office/code-runner/claude-credential-choice.mjs"() {
3038
+ "use strict";
3039
+ PREFER_LOGIN_ENV = "VO_RUNNER_PREFER_LOGIN";
3040
+ CLAUDE_PREFER_LOGIN_ENV = "VO_RUNNER_CLAUDE_PREFER_LOGIN";
3041
+ PREFER_KEY_ENV = "VO_RUNNER_PREFER_KEY";
3042
+ CLAUDE_PREFER_KEY_ENV = "VO_RUNNER_CLAUDE_PREFER_KEY";
3043
+ CLAUDE_CREDENTIAL_SOURCE = Object.freeze({
3044
+ /** PREFER_LOGIN set (and not overridden): any API key is ignored. */
3045
+ PREFER_LOGIN: "prefer_login",
3046
+ /** An explicit ANTHROPIC_API_KEY in the environment — the manual override. */
3047
+ ENV_KEY: "env_key",
3048
+ /** No key anywhere; the spawn falls through to the login session. */
3049
+ NO_KEY: "no_key",
3050
+ /** A stored key, used because the operator explicitly opted out of tier 1. */
3051
+ KEYCHAIN_PREFER_KEY: "keychain_prefer_key",
3052
+ /** A stored key exists but a proven live subscription outranks it. */
3053
+ SUBSCRIPTION_WINS: "subscription_wins",
3054
+ /** A stored key, used because no live subscription was proven. */
3055
+ KEYCHAIN: "keychain"
3056
+ });
3057
+ }
3058
+ });
3059
+
3004
3060
  // ../../scripts/virtual-office/code-runner/anthropic-key-store.mjs
3005
3061
  import { createRequire as createRequire2 } from "node:module";
3006
3062
  import { spawnSync as spawnSync2 } from "node:child_process";
@@ -3022,46 +3078,22 @@ function getAnthropicKey({ EntryCtor = defaultEntryCtor() } = {}) {
3022
3078
  return null;
3023
3079
  }
3024
3080
  }
3025
- function isTruthyFlag(v) {
3026
- const s = String(v ?? "").trim().toLowerCase();
3027
- return s === "1" || s === "true" || s === "yes" || s === "on";
3028
- }
3029
- function wantsLogin(env2) {
3030
- return isTruthyFlag(env2[CLAUDE_PREFER_LOGIN_ENV]) || isTruthyFlag(env2[PREFER_LOGIN_ENV]);
3031
- }
3032
- function wantsKey(env2) {
3033
- return isTruthyFlag(env2[CLAUDE_PREFER_KEY_ENV]) || isTruthyFlag(env2[PREFER_KEY_ENV]);
3034
- }
3035
3081
  function withAnthropicKey(baseEnv = {}, { getKey = getAnthropicKey, probeLogin = probeClaudeLoginState } = {}) {
3036
- const preferKey = wantsKey(baseEnv);
3037
- if (!preferKey && wantsLogin(baseEnv)) {
3038
- const next = { ...baseEnv };
3082
+ const { source, key } = classifyClaudeCredential(baseEnv, { getKey, probeLogin });
3083
+ const next = { ...baseEnv };
3084
+ if (source === CLAUDE_CREDENTIAL_SOURCE.PREFER_LOGIN) {
3039
3085
  delete next.ANTHROPIC_API_KEY;
3040
3086
  return next;
3041
3087
  }
3042
- if (baseEnv.ANTHROPIC_API_KEY) return { ...baseEnv };
3043
- const key = getKey();
3044
- if (!key) return { ...baseEnv };
3045
- if (!preferKey && probeLogin() === true) return { ...baseEnv };
3046
- return { ...baseEnv, ANTHROPIC_API_KEY: key };
3088
+ if (key !== null) next.ANTHROPIC_API_KEY = key;
3089
+ return next;
3047
3090
  }
3048
3091
  function claudeCostBasis(env2 = process.env) {
3049
3092
  return String(env2.ANTHROPIC_API_KEY || "").trim() ? "vendor_billed" : "subscription_api_equivalent";
3050
3093
  }
3051
3094
  function describeAnthropicAuthSource(baseEnv = {}, { getKey = getAnthropicKey, probeLogin = probeClaudeLoginState } = {}) {
3052
- const preferKey = wantsKey(baseEnv);
3053
- if (!preferKey && wantsLogin(baseEnv)) {
3054
- return "claude auth login (VO_RUNNER_PREFER_LOGIN set \u2014 any API key ignored)";
3055
- }
3056
- if (baseEnv.ANTHROPIC_API_KEY) return "ANTHROPIC_API_KEY from environment";
3057
- if (!getKey()) return "claude auth login session (no API key set)";
3058
- if (preferKey) {
3059
- return "ANTHROPIC_API_KEY from OS keychain (VO_RUNNER_PREFER_KEY set \u2014 subscription ignored)";
3060
- }
3061
- if (probeLogin() === true) {
3062
- return "claude auth login session (subscription beats the stored keychain key)";
3063
- }
3064
- return "ANTHROPIC_API_KEY from OS keychain";
3095
+ const { source } = classifyClaudeCredential(baseEnv, { getKey, probeLogin });
3096
+ return AUTH_SOURCE_DESCRIPTION[source];
3065
3097
  }
3066
3098
  function augmentAuthError(summary) {
3067
3099
  const s = String(summary ?? "");
@@ -3083,19 +3115,25 @@ function probeClaudeLoginState({
3083
3115
  return null;
3084
3116
  }
3085
3117
  }
3086
- var require2, KEY_SERVICE, KEY_ACCOUNT, _entryCtor, _loadTried, PREFER_LOGIN_ENV, CLAUDE_PREFER_LOGIN_ENV, PREFER_KEY_ENV, CLAUDE_PREFER_KEY_ENV, AUTH_ERROR_RE;
3118
+ var require2, KEY_SERVICE, KEY_ACCOUNT, _entryCtor, _loadTried, AUTH_SOURCE_DESCRIPTION, AUTH_ERROR_RE;
3087
3119
  var init_anthropic_key_store = __esm({
3088
3120
  "../../scripts/virtual-office/code-runner/anthropic-key-store.mjs"() {
3089
3121
  "use strict";
3090
3122
  init_windows_claude_launch();
3123
+ init_claude_credential_choice();
3124
+ init_claude_credential_choice();
3091
3125
  require2 = createRequire2(import.meta.url);
3092
3126
  KEY_SERVICE = "algosuite-vo";
3093
3127
  KEY_ACCOUNT = "anthropic-api-key";
3094
3128
  _loadTried = false;
3095
- PREFER_LOGIN_ENV = "VO_RUNNER_PREFER_LOGIN";
3096
- CLAUDE_PREFER_LOGIN_ENV = "VO_RUNNER_CLAUDE_PREFER_LOGIN";
3097
- PREFER_KEY_ENV = "VO_RUNNER_PREFER_KEY";
3098
- CLAUDE_PREFER_KEY_ENV = "VO_RUNNER_CLAUDE_PREFER_KEY";
3129
+ AUTH_SOURCE_DESCRIPTION = Object.freeze({
3130
+ [CLAUDE_CREDENTIAL_SOURCE.PREFER_LOGIN]: "claude auth login (VO_RUNNER_PREFER_LOGIN set \u2014 any API key ignored)",
3131
+ [CLAUDE_CREDENTIAL_SOURCE.ENV_KEY]: "ANTHROPIC_API_KEY from environment",
3132
+ [CLAUDE_CREDENTIAL_SOURCE.NO_KEY]: "claude auth login session (no API key set)",
3133
+ [CLAUDE_CREDENTIAL_SOURCE.KEYCHAIN_PREFER_KEY]: "ANTHROPIC_API_KEY from OS keychain (VO_RUNNER_PREFER_KEY set \u2014 subscription ignored)",
3134
+ [CLAUDE_CREDENTIAL_SOURCE.SUBSCRIPTION_WINS]: "claude auth login session (subscription beats the stored keychain key)",
3135
+ [CLAUDE_CREDENTIAL_SOURCE.KEYCHAIN]: "ANTHROPIC_API_KEY from OS keychain"
3136
+ });
3099
3137
  AUTH_ERROR_RE = /\b401\b|invalid[^.]{0,24}(authentication|credential)|authentication_error|unauthorized|not[ _-]?authenticated/i;
3100
3138
  }
3101
3139
  });
@@ -7443,6 +7481,13 @@ function makeUsageRow({
7443
7481
  }
7444
7482
  return row;
7445
7483
  }
7484
+ function readingAgeMs(row, nowMs = Date.now()) {
7485
+ const at = row && typeof row.captured_at === "string" ? row.captured_at : null;
7486
+ if (!at) return null;
7487
+ const ms = new Date(at).getTime();
7488
+ if (!Number.isFinite(ms)) return null;
7489
+ return Math.max(0, nowMs - ms);
7490
+ }
7446
7491
  var clampPct, readJson, ACCOUNT_KEY_SALT;
7447
7492
  var init_shared = __esm({
7448
7493
  "../../scripts/virtual-office/code-runner/account-usage/shared.mjs"() {
@@ -7463,8 +7508,17 @@ var init_shared = __esm({
7463
7508
  });
7464
7509
 
7465
7510
  // ../../scripts/virtual-office/code-runner/account-usage/claude.mjs
7511
+ import fs7 from "node:fs";
7466
7512
  import os3 from "node:os";
7467
7513
  import path14 from "node:path";
7514
+ function fileCaptureTime(filePath, explicit, statFn) {
7515
+ if (typeof explicit === "string" && explicit) return explicit;
7516
+ try {
7517
+ return statFn(filePath).mtime.toISOString();
7518
+ } catch {
7519
+ return null;
7520
+ }
7521
+ }
7468
7522
  function usageBaseUrl(env2 = process.env) {
7469
7523
  const raw = env2.ANTHROPIC_BASE_URL || "https://api.anthropic.com";
7470
7524
  return String(raw).replace(/\/+$/, "");
@@ -7570,7 +7624,12 @@ async function readClaudeOAuthUsage({
7570
7624
  clearTimeout(timer);
7571
7625
  }
7572
7626
  }
7573
- function readClaudeFileUsage({ homeDir = os3.homedir(), read: rawRead = readJson } = {}) {
7627
+ function readClaudeFileUsage({
7628
+ homeDir = os3.homedir(),
7629
+ read: rawRead = readJson,
7630
+ statFn = fs7.statSync,
7631
+ now = () => Date.now()
7632
+ } = {}) {
7574
7633
  const read = (p) => {
7575
7634
  try {
7576
7635
  return rawRead(p);
@@ -7579,31 +7638,39 @@ function readClaudeFileUsage({ homeDir = os3.homedir(), read: rawRead = readJson
7579
7638
  }
7580
7639
  };
7581
7640
  const accountId = readAccountId({ homeDir, read });
7582
- const status = read(path14.join(homeDir, ".claude", "claude-usage.json"));
7641
+ const fresh = (row) => {
7642
+ if (!row) return null;
7643
+ const age = readingAgeMs(row, now());
7644
+ if (age === null || age > MAX_FILE_AGE_MS) return null;
7645
+ return row;
7646
+ };
7647
+ const statusPath = path14.join(homeDir, ".claude", "claude-usage.json");
7648
+ const status = read(statusPath);
7583
7649
  if (status && (status.seven_day || status.five_hour)) {
7584
- const row = makeUsageRow({
7650
+ const row = fresh(makeUsageRow({
7585
7651
  agent: "claude",
7586
7652
  source: "statusline",
7587
- capturedAt: typeof status.capturedAt === "string" ? status.capturedAt : null,
7653
+ capturedAt: fileCaptureTime(statusPath, status.capturedAt, statFn),
7588
7654
  accountId,
7589
7655
  sevenDay: status.seven_day?.used_percentage,
7590
7656
  fiveHour: status.five_hour?.used_percentage,
7591
7657
  sevenDayResetsAt: status.seven_day?.resets_at ?? null,
7592
7658
  fiveHourResetsAt: status.five_hour?.resets_at ?? null
7593
- });
7659
+ }));
7594
7660
  if (row) return row;
7595
7661
  }
7596
- const weekly = read(path14.join(homeDir, ".claude", "claude-weekly-usage.json"));
7662
+ const weeklyPath = path14.join(homeDir, ".claude", "claude-weekly-usage.json");
7663
+ const weekly = read(weeklyPath);
7597
7664
  if (weekly) {
7598
- const row = makeUsageRow({
7665
+ const row = fresh(makeUsageRow({
7599
7666
  agent: "claude",
7600
7667
  source: "file",
7601
- capturedAt: typeof weekly.capturedAt === "string" ? weekly.capturedAt : null,
7668
+ capturedAt: fileCaptureTime(weeklyPath, weekly.capturedAt, statFn),
7602
7669
  accountId,
7603
7670
  sevenDay: weekly.sevenDayPct,
7604
7671
  fiveHour: weekly.fiveHourPct,
7605
7672
  sevenDayResetsAt: weekly.sevenDayResetsAt ?? null
7606
- });
7673
+ }));
7607
7674
  if (row) return row;
7608
7675
  }
7609
7676
  return null;
@@ -7616,11 +7683,12 @@ async function readClaudeUsage(opts = {}) {
7616
7683
  }
7617
7684
  return readClaudeFileUsage(opts);
7618
7685
  }
7619
- var USAGE_PATH, OAUTH_BETA, DEFAULT_TIMEOUT_MS;
7686
+ var MAX_FILE_AGE_MS, USAGE_PATH, OAUTH_BETA, DEFAULT_TIMEOUT_MS;
7620
7687
  var init_claude = __esm({
7621
7688
  "../../scripts/virtual-office/code-runner/account-usage/claude.mjs"() {
7622
7689
  "use strict";
7623
7690
  init_shared();
7691
+ MAX_FILE_AGE_MS = 6 * 60 * 60 * 1e3;
7624
7692
  USAGE_PATH = "/api/oauth/usage";
7625
7693
  OAUTH_BETA = "oauth-2025-04-20";
7626
7694
  DEFAULT_TIMEOUT_MS = 5e3;
@@ -9043,7 +9111,7 @@ var init_effort_mode_config = __esm({
9043
9111
  });
9044
9112
 
9045
9113
  // ../../scripts/virtual-office/model-registry.mjs
9046
- import fs7 from "node:fs";
9114
+ import fs8 from "node:fs";
9047
9115
  import path15 from "node:path";
9048
9116
  import { fileURLToPath as fileURLToPath4 } from "node:url";
9049
9117
  function uniqueModels(models = []) {
@@ -9156,9 +9224,9 @@ async function fetchGoogleModels(fetchImpl, env2 = process.env) {
9156
9224
  return (data?.models || []).map((model) => normalizeCatalogModel({ ...model, provider: "google", source: "google" })).filter(Boolean);
9157
9225
  }
9158
9226
  function readCache(cacheFile = DEFAULT_CACHE_FILE, nowMs = Date.now(), ttlMs = DEFAULT_TTL_MS3) {
9159
- if (!fs7.existsSync(cacheFile)) return null;
9227
+ if (!fs8.existsSync(cacheFile)) return null;
9160
9228
  try {
9161
- const parsed = JSON.parse(fs7.readFileSync(cacheFile, "utf-8"));
9229
+ const parsed = JSON.parse(fs8.readFileSync(cacheFile, "utf-8"));
9162
9230
  if (nowMs - Number(parsed.checkedAtMs || 0) > ttlMs) return null;
9163
9231
  if (!Array.isArray(parsed.models)) return null;
9164
9232
  return parsed;
@@ -9167,8 +9235,8 @@ function readCache(cacheFile = DEFAULT_CACHE_FILE, nowMs = Date.now(), ttlMs = D
9167
9235
  }
9168
9236
  }
9169
9237
  function writeCache(cacheFile = DEFAULT_CACHE_FILE, payload) {
9170
- fs7.mkdirSync(path15.dirname(cacheFile), { recursive: true });
9171
- fs7.writeFileSync(cacheFile, JSON.stringify(payload, null, 2));
9238
+ fs8.mkdirSync(path15.dirname(cacheFile), { recursive: true });
9239
+ fs8.writeFileSync(cacheFile, JSON.stringify(payload, null, 2));
9172
9240
  }
9173
9241
  async function fetchRegistryCatalog({
9174
9242
  fetchImpl = fetch,
@@ -10440,6 +10508,93 @@ var init_task_helpers = __esm({
10440
10508
  }
10441
10509
  });
10442
10510
 
10511
+ // ../../scripts/virtual-office/code-runner/swarm-admission.mjs
10512
+ function canLaunchSuccessorAgent(agent, platform = process.platform) {
10513
+ const name = typeof agent === "string" ? agent.trim() : "";
10514
+ if (!Object.prototype.hasOwnProperty.call(SUCCESSOR_LAUNCH_SHAPES, name)) return false;
10515
+ if (platform === "win32" && !SUCCESSOR_LAUNCH_SHAPES[name]) return false;
10516
+ return true;
10517
+ }
10518
+ function isSubscriptionExhausted(usage) {
10519
+ if (!usage || typeof usage !== "object") return false;
10520
+ const readings = [usage.seven_day_used_pct, usage.five_hour_used_pct, usage.monthly_used_pct];
10521
+ return readings.some((v) => typeof v === "number" && Number.isFinite(v) && v >= SUBSCRIPTION_EXHAUSTED_PCT);
10522
+ }
10523
+ function clampSubagents(requested) {
10524
+ if (!Number.isFinite(requested) || requested < 1) return 0;
10525
+ return Math.min(Math.floor(requested), MAX_BOUND_SUBAGENTS);
10526
+ }
10527
+ function usageFor(accountUsage, agent) {
10528
+ if (!Array.isArray(accountUsage)) return null;
10529
+ return accountUsage.find((row) => row && row.agent === agent) ?? null;
10530
+ }
10531
+ function exhaustedAgents(availableAgents, accountUsage) {
10532
+ if (!Array.isArray(availableAgents)) return [];
10533
+ return availableAgents.filter((row) => row && row.installed === true && row.authenticated === true && row.auth_tier === AUTH_TIER_SUBSCRIPTION && isSubscriptionExhausted(usageFor(accountUsage, row.agent))).map((row) => row.agent);
10534
+ }
10535
+ function resolveRunnerSwarmBinding({
10536
+ swarmId,
10537
+ agent,
10538
+ availableAgents,
10539
+ accountUsage = [],
10540
+ requestedSubagents = MAX_BOUND_SUBAGENTS,
10541
+ nowIso,
10542
+ platform = process.platform
10543
+ } = {}) {
10544
+ const id = typeof swarmId === "string" ? swarmId.trim() : "";
10545
+ const boundAgent = typeof agent === "string" ? agent.trim() : "";
10546
+ if (id.length === 0 || boundAgent.length === 0) return null;
10547
+ if (!canLaunchSuccessorAgent(boundAgent, platform)) return null;
10548
+ const budget = clampSubagents(requestedSubagents);
10549
+ if (budget === 0) return null;
10550
+ const rows = Array.isArray(availableAgents) ? availableAgents : [];
10551
+ const row = rows.find((r) => r && r.agent === boundAgent) ?? null;
10552
+ if (!row || row.installed !== true || row.authenticated !== true) return null;
10553
+ const tier = AUTH_TIER_TO_SWARM_TIER[row.auth_tier];
10554
+ if (!tier) return null;
10555
+ const exhausted = exhaustedAgents(rows, accountUsage);
10556
+ const boundExhausted = tier === "tier1_subscription" && isSubscriptionExhausted(usageFor(accountUsage, boundAgent));
10557
+ const effectiveBudget = boundExhausted ? Math.min(budget, EXHAUSTED_SUBAGENT_BUDGET) : budget;
10558
+ const basis = `code-task dispatch admitted on '${boundAgent}' at auth tier '${row.auth_tier}' (runner-local capability probe)`;
10559
+ return {
10560
+ schema_version: 1,
10561
+ swarm_id: id,
10562
+ tier,
10563
+ agent: boundAgent,
10564
+ reason: boundExhausted ? `${basis}; that subscription window is >=${SUBSCRIPTION_EXHAUSTED_PCT}% spent, so the fan-out is bound at a REDUCED ceiling of ${effectiveBudget} instead of being left unbound and uncapped` : basis,
10565
+ exhausted_agents: exhausted,
10566
+ subagent_budget: effectiveBudget,
10567
+ // Never a platform-billed fan-out in this lane — see the module header.
10568
+ spend_cap_usd: null,
10569
+ resolved_at: typeof nowIso === "string" && nowIso ? nowIso : (/* @__PURE__ */ new Date()).toISOString()
10570
+ };
10571
+ }
10572
+ function mintSwarmTierBindingEnv(input) {
10573
+ const binding = resolveRunnerSwarmBinding(input);
10574
+ if (!binding) return {};
10575
+ return { [SWARM_TIER_BINDING_ENV]: JSON.stringify(binding) };
10576
+ }
10577
+ var SWARM_TIER_BINDING_ENV, MAX_BOUND_SUBAGENTS, SUBSCRIPTION_EXHAUSTED_PCT, EXHAUSTED_SUBAGENT_BUDGET, SUCCESSOR_LAUNCH_SHAPES, AUTH_TIER_TO_SWARM_TIER;
10578
+ var init_swarm_admission = __esm({
10579
+ "../../scripts/virtual-office/code-runner/swarm-admission.mjs"() {
10580
+ "use strict";
10581
+ init_agent_auth_tier();
10582
+ SWARM_TIER_BINDING_ENV = "VO_SWARM_TIER_BINDING";
10583
+ MAX_BOUND_SUBAGENTS = 20;
10584
+ SUBSCRIPTION_EXHAUSTED_PCT = 95;
10585
+ EXHAUSTED_SUBAGENT_BUDGET = 1;
10586
+ SUCCESSOR_LAUNCH_SHAPES = Object.freeze({
10587
+ claude: true,
10588
+ codex: false
10589
+ });
10590
+ AUTH_TIER_TO_SWARM_TIER = Object.freeze({
10591
+ [AUTH_TIER_SUBSCRIPTION]: "tier1_subscription",
10592
+ [AUTH_TIER_LOCAL]: "tier1_local",
10593
+ [AUTH_TIER_API_KEY]: "tier2_user_key"
10594
+ });
10595
+ }
10596
+ });
10597
+
10443
10598
  // ../../scripts/virtual-office/code-runner/agent-process-env.mjs
10444
10599
  function safeIdentityPart(value, fallback) {
10445
10600
  const normalized = String(value || "").trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -10452,8 +10607,14 @@ function safeBaseEnv(env2 = {}) {
10452
10607
  }
10453
10608
  return result;
10454
10609
  }
10455
- function buildAgentProcessEnv(env2, { agent = "agent", runnerId = "vo-runner", taskId = "task", githubReadToken = null } = {}) {
10610
+ function buildAgentProcessEnv(env2, { agent = "agent", runnerId = "vo-runner", taskId = "task", githubReadToken = null, swarmAdmission = null } = {}) {
10456
10611
  const base = safeBaseEnv(env2);
10612
+ if (swarmAdmission) {
10613
+ for (const key of Object.keys(base)) {
10614
+ if (key.toUpperCase() === SWARM_TIER_BINDING_ENV) delete base[key];
10615
+ }
10616
+ Object.assign(base, mintSwarmTierBindingEnv({ ...swarmAdmission, agent, swarmId: taskId }));
10617
+ }
10457
10618
  if (typeof githubReadToken === "string" && githubReadToken) {
10458
10619
  base.GH_TOKEN = githubReadToken;
10459
10620
  base.GITHUB_TOKEN = githubReadToken;
@@ -10471,6 +10632,7 @@ var SAFE_ENV_NAMES;
10471
10632
  var init_agent_process_env = __esm({
10472
10633
  "../../scripts/virtual-office/code-runner/agent-process-env.mjs"() {
10473
10634
  "use strict";
10635
+ init_swarm_admission();
10474
10636
  SAFE_ENV_NAMES = /* @__PURE__ */ new Set([
10475
10637
  "AGENT_ID",
10476
10638
  "APPDATA",
@@ -10511,7 +10673,31 @@ var init_agent_process_env = __esm({
10511
10673
  // it. #9242 added VO_RUNNER_PREFER_KEY without this line, which left the
10512
10674
  // escape hatch inert — an operator who set it still got the subscription.
10513
10675
  "VO_RUNNER_PREFER_KEY",
10514
- "VO_RUNNER_CLAUDE_PREFER_KEY"
10676
+ "VO_RUNNER_CLAUDE_PREFER_KEY",
10677
+ // The swarm tier binding (SWARM_TIER_BINDING_ENV in
10678
+ // packages/vo-mcp/src/swarm/tier-binding.ts). A fan-out resolves its billing
10679
+ // tier ONCE at admission and exports the binding so every subagent inherits
10680
+ // the same answer instead of re-resolving its own. This line is what lets it
10681
+ // cross the process boundary at all: the daemon builds each child env with
10682
+ // buildAgentProcessEnv(process.env) at
10683
+ // scripts/virtual-office/code-runner-daemon.mjs:117 (sibling dir, not this
10684
+ // one), so a name absent from this set is stripped and the binding binds
10685
+ // NOTHING —
10686
+ // exactly how #9242's VO_RUNNER_PREFER_KEY shipped inert until #9247.
10687
+ //
10688
+ // NOT a credential and NOT an authorization input: it names a tier, it never
10689
+ // grants one, and it carries no key material (see the module's header rule).
10690
+ "VO_SWARM_TIER_BINDING",
10691
+ // Where the swarm SPAWN LEDGER lives (SWARM_LEDGER_DIR_ENV in
10692
+ // packages/vo-mcp/src/swarm/spawn-ledger.ts). The ledger is the durable,
10693
+ // host-shared counter that bounds the TOTAL spawns under one swarm_id; the
10694
+ // binding above only bounds the depth of one chain. If a parent's override
10695
+ // were stripped here, the child would ledger into a DIFFERENT directory,
10696
+ // claim slot 0 again, and the shared ceiling would silently degrade back to a
10697
+ // per-process quota — which is precisely the defect the ledger closes.
10698
+ //
10699
+ // A path, not a credential. Absent means the default ~/.vo/swarm-ledger.
10700
+ "VO_SWARM_LEDGER_DIR"
10515
10701
  ]);
10516
10702
  }
10517
10703
  });
@@ -11002,7 +11188,7 @@ var init_inference_task_runner = __esm({
11002
11188
  });
11003
11189
 
11004
11190
  // ../../scripts/virtual-office/code-runner/isolation-audit.mjs
11005
- import fs8 from "node:fs";
11191
+ import fs9 from "node:fs";
11006
11192
  import fsp11 from "node:fs/promises";
11007
11193
  import path16 from "node:path";
11008
11194
  async function defaultRun(command, args, cwd, options = {}) {
@@ -11097,7 +11283,7 @@ async function restoreExactCanonicalPaths(baseline, evidence, run) {
11097
11283
  for (const relative of evidence.untracked) {
11098
11284
  const target = path16.resolve(baseline.root, relative);
11099
11285
  const prefix = `${path16.resolve(baseline.root)}${path16.sep}`;
11100
- if (!target.startsWith(prefix) || !fs8.existsSync(target)) continue;
11286
+ if (!target.startsWith(prefix) || !fs9.existsSync(target)) continue;
11101
11287
  await fsp11.rm(target, { force: true });
11102
11288
  }
11103
11289
  }
@@ -11627,7 +11813,7 @@ var init_publication_scope = __esm({
11627
11813
  });
11628
11814
 
11629
11815
  // ../../scripts/virtual-office/code-runner/recovery-ledger.mjs
11630
- import fs9 from "node:fs";
11816
+ import fs10 from "node:fs";
11631
11817
  import fsp13 from "node:fs/promises";
11632
11818
  import path18 from "node:path";
11633
11819
  function recoveryTaskId(prompt) {
@@ -11665,7 +11851,7 @@ async function readLedger(file, readFile5) {
11665
11851
  async function findPreservedRecovery(task, {
11666
11852
  clonesRoot: clonesRoot2 = process.env.VO_CODE_RUNNER_CLONES_ROOT || "",
11667
11853
  readFile: readFile5 = fsp13.readFile,
11668
- exists = fs9.existsSync
11854
+ exists = fs10.existsSync
11669
11855
  } = {}) {
11670
11856
  const resumedFrom = /^[0-9a-f-]{36}$/iu.test(String(task.resumed_from || "")) ? String(task.resumed_from).toLowerCase() : null;
11671
11857
  const originalTaskId = recoveryTaskId(task.prompt) ?? resumedFrom;
@@ -12389,7 +12575,7 @@ import { fileURLToPath as fileURLToPath6 } from "node:url";
12389
12575
  function log(msg) {
12390
12576
  console.log(`[code-runner ${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}`);
12391
12577
  }
12392
- async function processOneTask(client, task, cfg, runnerInstanceId) {
12578
+ async function processOneTask(client, task, cfg, runnerInstanceId, swarmAdmission = null) {
12393
12579
  const id = task.code_task_id;
12394
12580
  let worktreeName = "";
12395
12581
  let preserveReason = null;
@@ -12439,7 +12625,8 @@ async function processOneTask(client, task, cfg, runnerInstanceId) {
12439
12625
  model,
12440
12626
  effort: effectiveEffort,
12441
12627
  maxBudgetUsd: sel.agent === "claude" ? effectiveMaxBudgetUsd : void 0,
12442
- env: buildAgentProcessEnv(process.env, { agent: sel.agent, runnerId: cfg.runnerId, taskId: id, githubReadToken: agentGithubReadToken }),
12628
+ env: buildAgentProcessEnv(process.env, { agent: sel.agent, runnerId: cfg.runnerId, taskId: id, githubReadToken: agentGithubReadToken, swarmAdmission }),
12629
+ // swarmAdmission mints VO_SWARM_TIER_BINDING: ONE tier decision for this task's whole agent tree
12443
12630
  sandbox,
12444
12631
  onProgress: (text, checkpoint) => {
12445
12632
  const usage = checkpoint?.tokenUsage ? { token_usage: checkpoint.tokenUsage } : {};
@@ -12725,7 +12912,7 @@ async function main({ env: env2 = process.env, once: once2 = false } = {}) {
12725
12912
  }
12726
12913
  log(`claimed task ${task.code_task_id} (${task.repo})`);
12727
12914
  active += 1;
12728
- const runTask = task.kind === "inference" ? processInferenceTask(client, task, cfg, { safeProgress, runnerStagePatch, log }) : processOneTask(client, task, cfg, runnerInstanceId);
12915
+ const runTask = task.kind === "inference" ? processInferenceTask(client, task, cfg, { safeProgress, runnerStagePatch, log }) : processOneTask(client, task, cfg, runnerInstanceId, { availableAgents: claimAgents.availableAgents, accountUsage: accountUsage.get() });
12729
12916
  const done = runTask.catch(async (error) => {
12730
12917
  log(`task ${task.code_task_id} unhandled runner error: ${error.message}`);
12731
12918
  if (task.kind === "inference") await deliverTerminalRun({