usebeeline 0.0.134 → 0.1.0

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.
Files changed (2) hide show
  1. package/dist/usebeeline.mjs +1765 -1463
  2. package/package.json +1 -1
@@ -9071,7 +9071,7 @@ var init_access_policy = __esm({
9071
9071
  import { randomBytes as randomBytes5 } from "node:crypto";
9072
9072
  import { execFile } from "node:child_process";
9073
9073
  import { closeSync, openSync, readFileSync } from "node:fs";
9074
- import { mkdir, readFile as readFile2, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
9074
+ import { chmod, mkdir, readFile as readFile2, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
9075
9075
  import { homedir } from "node:os";
9076
9076
  import { dirname, resolve } from "node:path";
9077
9077
  import { spawn as spawn2 } from "node:child_process";
@@ -9138,6 +9138,10 @@ async function readRuntimeRecord(path) {
9138
9138
  runtimeIdentity(parsed.body);
9139
9139
  return parsed;
9140
9140
  }
9141
+ async function convergeRuntimeRecordFileModes(path) {
9142
+ await chmod(dirname(path), 448).catch(() => void 0);
9143
+ await chmod(path, 384).catch(() => void 0);
9144
+ }
9141
9145
  async function migrateRuntimeRecordAccessPolicy(path) {
9142
9146
  const runtime = await readRuntimeRecord(path);
9143
9147
  if (runtime.accessPolicy)
@@ -9983,7 +9987,7 @@ var init_systemd = __esm({
9983
9987
  // apps/body/dist/launchd.js
9984
9988
  import { execFile as execFile3 } from "node:child_process";
9985
9989
  import { realpathSync } from "node:fs";
9986
- import { chmod, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rename as rename2, rm, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
9990
+ import { chmod as chmod2, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rename as rename2, rm, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
9987
9991
  import { homedir as homedir4 } from "node:os";
9988
9992
  import { dirname as dirname4, resolve as resolve4 } from "node:path";
9989
9993
  import { setTimeout as sleep2 } from "node:timers/promises";
@@ -10150,7 +10154,7 @@ async function writeManagedFile(path, content, mode) {
10150
10154
  await mkdir3(dirname4(path), { recursive: true, mode: 448 });
10151
10155
  const pending = `${path}.${process.pid}.pending`;
10152
10156
  await writeFile3(pending, content, { mode });
10153
- await chmod(pending, mode);
10157
+ await chmod2(pending, mode);
10154
10158
  await rename2(pending, path);
10155
10159
  return true;
10156
10160
  }
@@ -10402,7 +10406,7 @@ __export(self_update_exports, {
10402
10406
  });
10403
10407
  import { createHash } from "node:crypto";
10404
10408
  import { constants as fsConstants2 } from "node:fs";
10405
- import { access, chmod as chmod2, lstat, mkdir as mkdir4, open, readFile as readFile5, rename as rename3, rm as rm2, symlink, writeFile as writeFile4 } from "node:fs/promises";
10409
+ import { access, chmod as chmod3, lstat, mkdir as mkdir4, open, readFile as readFile5, rename as rename3, rm as rm2, symlink, writeFile as writeFile4 } from "node:fs/promises";
10406
10410
  import { spawn as spawn4 } from "node:child_process";
10407
10411
  import { homedir as homedir5 } from "node:os";
10408
10412
  import { dirname as dirname5, join as join3, resolve as resolve5 } from "node:path";
@@ -10704,7 +10708,7 @@ function forwarderScript(tool) {
10704
10708
  async function replaceFile(path, contents, mode) {
10705
10709
  const temp = `${path}.new-${process.pid}`;
10706
10710
  await writeFile4(temp, contents, { mode });
10707
- await chmod2(temp, mode);
10711
+ await chmod3(temp, mode);
10708
10712
  await rename3(temp, path);
10709
10713
  }
10710
10714
  async function activateRelease(layout, releaseId) {
@@ -11244,7 +11248,7 @@ var init_cursor_models = __esm({
11244
11248
  // apps/body/dist/cursor-acp-bridge.js
11245
11249
  import { spawn as spawn6 } from "node:child_process";
11246
11250
  import { existsSync as existsSync3 } from "node:fs";
11247
- import { chmod as chmod3, lstat as lstat2, mkdir as mkdir6, rename as rename4, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
11251
+ import { chmod as chmod4, lstat as lstat2, mkdir as mkdir6, rename as rename4, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
11248
11252
  import { createRequire as createRequire3 } from "node:module";
11249
11253
  import { createInterface as createInterface3 } from "node:readline";
11250
11254
  import { basename, dirname as dirname7, resolve as resolvePath } from "node:path";
@@ -11316,7 +11320,7 @@ async function writeIsolatedCursorFile(path, content) {
11316
11320
  const temporary = resolvePath(parent, `.${basename(path)}.${process.pid}.${randomUUID2()}.tmp`);
11317
11321
  try {
11318
11322
  await writeFile5(temporary, content, { mode: 384, flag: "wx" });
11319
- await chmod3(temporary, 384);
11323
+ await chmod4(temporary, 384);
11320
11324
  await rename4(temporary, path);
11321
11325
  } finally {
11322
11326
  await unlink3(temporary).catch(() => void 0);
@@ -23288,6 +23292,8 @@ function isSquireApprovalUrl(value) {
23288
23292
  const host = url.hostname;
23289
23293
  if (!["trustysquire.ai", "trustysquire.test"].some((domain) => host === domain || host.endsWith(`.${domain}`)))
23290
23294
  return false;
23295
+ if (url.pathname === "/" || url.pathname === "/install")
23296
+ return true;
23291
23297
  return /^\/(?:vault\/(?:pay|fetch|mutate|mutate-card)|approval|passkey|vouch)\/[^/]+\/?$/.test(url.pathname);
23292
23298
  }
23293
23299
  function linkKindFor(key, url) {
@@ -23479,6 +23485,56 @@ function squireApprovalFromMcp(request, response) {
23479
23485
  const args = record(params?.arguments) ?? {};
23480
23486
  return { tool, ...squireApprovalCopy(tool, args), ...link2 };
23481
23487
  }
23488
+ function squireLoginWallIn(value, depth = 0) {
23489
+ if (depth > 6)
23490
+ return void 0;
23491
+ if (typeof value === "string") {
23492
+ const trimmed = value.trim();
23493
+ if (trimmed.length > 2e4 || !/^[{[]/.test(trimmed))
23494
+ return void 0;
23495
+ try {
23496
+ return squireLoginWallIn(JSON.parse(trimmed), depth + 1);
23497
+ } catch {
23498
+ return void 0;
23499
+ }
23500
+ }
23501
+ if (Array.isArray(value)) {
23502
+ for (const entry of value) {
23503
+ const found = squireLoginWallIn(entry, depth + 1);
23504
+ if (found)
23505
+ return found;
23506
+ }
23507
+ return void 0;
23508
+ }
23509
+ const item = record(value);
23510
+ if (!item)
23511
+ return void 0;
23512
+ const needsUser = record(item.needs_user);
23513
+ if (needsUser?.wall === "google_session") {
23514
+ const message = shortString(needsUser.message);
23515
+ if (message)
23516
+ return { wall: "google_session", message };
23517
+ }
23518
+ const oauth = record(item.oauth);
23519
+ if (oauth?.state === "awaiting_human") {
23520
+ const reason = shortString(oauth.reason);
23521
+ if (reason)
23522
+ return { wall: "awaiting_human", message: reason };
23523
+ }
23524
+ for (const entry of Object.values(item)) {
23525
+ const found = squireLoginWallIn(entry, depth + 1);
23526
+ if (found)
23527
+ return found;
23528
+ }
23529
+ return void 0;
23530
+ }
23531
+ function squireLoginWallFromMcp(request, response) {
23532
+ if (!request || request.method !== "tools/call" || request.id !== response.id)
23533
+ return void 0;
23534
+ if (!("result" in response))
23535
+ return void 0;
23536
+ return squireLoginWallIn(response.result);
23537
+ }
23482
23538
  async function postSquireApproval(approval, authFile, signInUrl, fetchImpl = fetch) {
23483
23539
  const auth = JSON.parse(await readFile(authFile, "utf8"));
23484
23540
  const context = JSON.parse(await readFile(auth.turnContextPath, "utf8"));
@@ -23495,6 +23551,22 @@ async function postSquireApproval(approval, authFile, signInUrl, fetchImpl = fet
23495
23551
  signal: AbortSignal.timeout(2e4)
23496
23552
  });
23497
23553
  }
23554
+ async function postSquireLoginWall(wall, authFile, fetchImpl = fetch) {
23555
+ const auth = JSON.parse(await readFile(authFile, "utf8"));
23556
+ const context = JSON.parse(await readFile(auth.turnContextPath, "utf8"));
23557
+ if (![context.roomId, context.requestId, context.generationId].every((value) => typeof value === "string" && value.length > 0))
23558
+ return;
23559
+ await fetchImpl(new URL("/v1/daemon/operations/postSquireLoginWall", auth.baseUrl), {
23560
+ method: "POST",
23561
+ headers: {
23562
+ authorization: `Bearer ${auth.daemonToken}`,
23563
+ "content-type": "application/json",
23564
+ "x-beeline-helper-version": auth.helperVersion ?? "v0.0.0"
23565
+ },
23566
+ body: JSON.stringify({ ...context, wall: wall.wall, message: wall.message }),
23567
+ signal: AbortSignal.timeout(2e4)
23568
+ });
23569
+ }
23498
23570
  function resourceCallFacts(message, target) {
23499
23571
  if (message.method !== "tools/call")
23500
23572
  return {};
@@ -23560,6 +23632,11 @@ function runResourceFacade(env = process.env) {
23560
23632
  if (request?.drivenUrl && activeSquireBrowserUrl === request.drivenUrl)
23561
23633
  activeSquireBrowserUrl = void 0;
23562
23634
  }
23635
+ const loginWall = squireLoginWallFromMcp(request?.message, message);
23636
+ if (loginWall) {
23637
+ await postSquireLoginWall(loginWall, authFile).catch(() => {
23638
+ });
23639
+ }
23563
23640
  };
23564
23641
  const authorizedResponseIds = /* @__PURE__ */ new Set();
23565
23642
  let child;
@@ -23725,7 +23802,7 @@ function configureNetworkFamilyDefaults(network = net) {
23725
23802
  configureNetworkFamilyDefaults();
23726
23803
 
23727
23804
  // apps/body/dist/cli.js
23728
- import { dirname as dirname26, resolve as resolve39 } from "node:path";
23805
+ import { dirname as dirname27, resolve as resolve39 } from "node:path";
23729
23806
  import { stdin as stdin4, stdout as stdout5 } from "node:process";
23730
23807
 
23731
23808
  // node_modules/@clack/core/dist/index.mjs
@@ -25808,7 +25885,13 @@ async function installSquire(options) {
25808
25885
  if (resolution.reResolved) {
25809
25886
  log2(`trusty-squire stale copy ${resolution.resolvedVersion ?? "unknown"} re-resolved against current release ${resolution.currentRelease}`);
25810
25887
  }
25811
- const install = await streamRun("npx", [...resolution.npxArgs, "connect", "--target=codex", "--json"], squireConnectProcessEnv(profileDir));
25888
+ const install = await streamRun("npx", [
25889
+ ...resolution.npxArgs,
25890
+ "connect",
25891
+ "--target=codex",
25892
+ "--json",
25893
+ ...options.forceReloginProvider ? [`--force-relogin=${options.forceReloginProvider}`] : []
25894
+ ], squireConnectProcessEnv(profileDir));
25812
25895
  const report = install.report;
25813
25896
  const version = resolution.resolvedVersion;
25814
25897
  if (!report) {
@@ -26543,549 +26626,1143 @@ function isAllowedAgentModelConfigCategory(category, id) {
26543
26626
  // apps/body/dist/model-config.js
26544
26627
  import { lstatSync, readFileSync as readFileSync3 } from "node:fs";
26545
26628
  import { basename as basename3, resolve as resolve9 } from "node:path";
26546
- var GROK_SESSION_MODEL_AXIS_ID = "beeline:grok-session-model";
26547
- var GROK_LAUNCH_EFFORT_AXIS_ID = "beeline:grok-launch-reasoning-effort";
26548
- function isGrokAgentCommand(agent) {
26549
- if (agent.kind === "grok")
26550
- return true;
26551
- if (agent.kind && agent.kind !== "custom")
26629
+
26630
+ // packages/api-contract/dist/daemon-operations.js
26631
+ function isAgentCommand(value) {
26632
+ if (!value || typeof value !== "object")
26552
26633
  return false;
26553
- return /^grok(?:\.[a-z0-9]+)?$/i.test(basename3(agent.command));
26554
- }
26555
- function agentArgsWithModelSelection(agent, selection) {
26556
- const original = [...agent.args];
26557
- if (!selection || !selection.model && !selection.effort || !isGrokAgentCommand(agent) || !original.includes("agent") || !original.includes("stdio")) {
26558
- return original;
26559
- }
26560
- const stripped = [];
26561
- for (let index = 0; index < original.length; index += 1) {
26562
- const arg = original[index];
26563
- if (arg === "-m" || arg === "--model" || arg === "--reasoning-effort") {
26564
- index += 1;
26565
- continue;
26566
- }
26567
- if (arg.startsWith("--model=") || arg.startsWith("--reasoning-effort=") || /^-m=/.test(arg)) {
26568
- continue;
26569
- }
26570
- stripped.push(arg);
26571
- }
26572
- const stdioIndex = stripped.lastIndexOf("stdio");
26573
- const configured = [
26574
- ...selection.model ? ["--model", selection.model] : [],
26575
- ...selection.effort ? ["--reasoning-effort", selection.effort] : []
26576
- ];
26577
- stripped.splice(stdioIndex, 0, ...configured);
26578
- return stripped;
26579
- }
26580
- function advertisedChoiceId(choice) {
26581
- if (typeof choice.id === "string" && choice.id.length > 0)
26582
- return choice.id;
26583
- if (typeof choice.value === "string" && choice.value.length > 0)
26584
- return choice.value;
26585
- return void 0;
26634
+ const c2 = value;
26635
+ if (![
26636
+ "id",
26637
+ "roomId",
26638
+ "agentId",
26639
+ "sourceMessageId",
26640
+ "turnRequestId",
26641
+ "rootCommandId",
26642
+ "rootSourceMessageId",
26643
+ "reason"
26644
+ ].every((key) => typeof c2[key] === "string" && c2[key].length > 0))
26645
+ return false;
26646
+ if (!["input", "resume", "stop", "restart"].includes(String(c2.action)) || !Number.isInteger(c2.agentDepth) || Number(c2.agentDepth) < 0 || Number(c2.agentDepth) > 3)
26647
+ return false;
26648
+ const source = c2.source;
26649
+ return Boolean(source && typeof source.id === "string" && typeof source.authorId === "string" && typeof source.body === "string" && typeof source.createdAt === "number" && Array.isArray(source.attachments));
26586
26650
  }
26587
- function sortModelChoicesNewestFirst(choices) {
26588
- return choices.map((choice, index) => ({ choice, index })).sort((left, right) => {
26589
- const leftParts = left.choice.id.match(/\d+/g)?.map(Number) ?? [];
26590
- const rightParts = right.choice.id.match(/\d+/g)?.map(Number) ?? [];
26591
- for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {
26592
- const delta = (rightParts[index] ?? -1) - (leftParts[index] ?? -1);
26593
- if (delta !== 0)
26594
- return delta;
26595
- }
26596
- return left.index - right.index;
26597
- }).map(({ choice }) => choice);
26651
+
26652
+ // packages/api-contract/dist/artifacts.js
26653
+ var ARTIFACT_EXTENSIONS_BY_MIME = {
26654
+ "text/html": [".html", ".htm"],
26655
+ "image/svg+xml": [".svg"],
26656
+ "application/pdf": [".pdf"],
26657
+ "text/markdown": [".md"],
26658
+ "image/png": [".png"],
26659
+ "image/jpeg": [".jpg", ".jpeg"],
26660
+ "image/gif": [".gif"],
26661
+ "image/webp": [".webp"],
26662
+ "text/plain": [".txt", ".log"],
26663
+ "application/json": [".json"],
26664
+ "text/csv": [".csv"],
26665
+ "application/zip": [".zip"],
26666
+ "application/octet-stream": []
26667
+ };
26668
+ var ARTIFACT_MIME_BY_EXTENSION = Object.fromEntries(Object.entries(ARTIFACT_EXTENSIONS_BY_MIME).flatMap(([mime, extensions]) => extensions.map((extension2) => [extension2, mime])));
26669
+ var ARTIFACT_MAXIMUM_BYTES = 25 * 1024 * 1024;
26670
+
26671
+ // packages/api-contract/dist/daemon.js
26672
+ init_agent_access();
26673
+
26674
+ // packages/api-contract/dist/system-events.js
26675
+ var SERVER_EVENT_KINDS = [
26676
+ "joined",
26677
+ "schedule-ran",
26678
+ "corner-opened",
26679
+ "check-passed",
26680
+ "check-failed",
26681
+ "merged",
26682
+ "grant-decided",
26683
+ "connector-offer-decided",
26684
+ "turn-cancelled",
26685
+ "choice-answered",
26686
+ "choice-skipped",
26687
+ "poll-closed",
26688
+ "workflow-handoff"
26689
+ ];
26690
+
26691
+ // packages/api-contract/dist/turn-silence.js
26692
+ var HICCUP_BACKOFF_MS = [0, 5e3, 2e4];
26693
+ var TURN_SILENCE_KINDS = [
26694
+ "hiccup",
26695
+ "wrong-model",
26696
+ "allowance-spent",
26697
+ "not-signed-in",
26698
+ "workspace-failure",
26699
+ "helper-out-of-date",
26700
+ "update-interrupted",
26701
+ "offline"
26702
+ ];
26703
+ var TURN_RECEIPT_REASON_KINDS = [
26704
+ "hiccup",
26705
+ "wrong-model",
26706
+ "allowance-spent",
26707
+ "not-signed-in",
26708
+ "workspace-failure",
26709
+ "helper-out-of-date",
26710
+ "update-interrupted",
26711
+ "offline",
26712
+ "model-selection-unavailable"
26713
+ ];
26714
+ function isTurnReceiptReasonKind(value) {
26715
+ return typeof value === "string" && TURN_RECEIPT_REASON_KINDS.includes(value);
26598
26716
  }
26599
- function parseAdvertisedConfigOptions(raw, preferredModelId, includeLaunchEffort = false) {
26600
- const configOptions = raw?.configOptions;
26601
- const result = [];
26602
- for (const entry of Array.isArray(configOptions) ? configOptions : []) {
26603
- if (!entry || typeof entry !== "object")
26604
- continue;
26605
- const record6 = entry;
26606
- const id = record6.id;
26607
- const category = record6.category;
26608
- if (typeof id !== "string" || typeof category !== "string")
26609
- continue;
26610
- const rawChoices = Array.isArray(record6.options) ? record6.options : [];
26611
- const choices = [];
26612
- for (const rawChoice of rawChoices) {
26613
- if (!rawChoice || typeof rawChoice !== "object")
26614
- continue;
26615
- const choice = rawChoice;
26616
- const choiceId = advertisedChoiceId(choice);
26617
- if (!choiceId)
26618
- continue;
26619
- choices.push({
26620
- id: choiceId,
26621
- ...typeof choice.name === "string" ? { name: choice.name } : {}
26622
- });
26623
- }
26624
- result.push({
26625
- id,
26626
- category,
26627
- ...typeof record6.currentValue === "string" ? { currentValue: record6.currentValue } : {},
26628
- options: category === "model" ? sortModelChoicesNewestFirst(choices) : choices
26629
- });
26630
- }
26631
- const models = raw?.models;
26632
- if (!models || typeof models !== "object")
26633
- return result;
26634
- const modelState = models;
26635
- const availableModels = Array.isArray(modelState.availableModels) ? modelState.availableModels : [];
26636
- const modelChoices = [];
26637
- for (const entry of availableModels) {
26638
- if (!entry || typeof entry !== "object")
26639
- continue;
26640
- const model = entry;
26641
- if (typeof model.modelId !== "string" || !model.modelId)
26642
- continue;
26643
- modelChoices.push({
26644
- id: model.modelId,
26645
- ...typeof model.name === "string" ? { name: model.name } : {}
26646
- });
26647
- }
26648
- const currentModelId = typeof modelState.currentModelId === "string" ? modelState.currentModelId : void 0;
26649
- if (modelChoices.length > 0 && !result.some((axis) => axis.category === "model")) {
26650
- result.push({
26651
- id: GROK_SESSION_MODEL_AXIS_ID,
26652
- category: "model",
26653
- ...currentModelId ? { currentValue: currentModelId } : {},
26654
- options: sortModelChoicesNewestFirst(modelChoices)
26655
- });
26656
- }
26657
- const effortModelId = preferredModelId ?? currentModelId;
26658
- const currentModel = availableModels.find((entry) => entry && typeof entry === "object" && entry.modelId === effortModelId);
26659
- const meta = currentModel?._meta;
26660
- const modelMeta = meta && typeof meta === "object" ? meta : void 0;
26661
- const efforts = Array.isArray(modelMeta?.reasoningEfforts) ? modelMeta.reasoningEfforts : [];
26662
- const effortChoices = [];
26663
- for (const entry of efforts) {
26664
- if (!entry || typeof entry !== "object")
26665
- continue;
26666
- const effort = entry;
26667
- const id = advertisedChoiceId(effort);
26668
- if (!id)
26669
- continue;
26670
- effortChoices.push({
26671
- id,
26672
- ...typeof effort.label === "string" ? { name: effort.label } : typeof effort.name === "string" ? { name: effort.name } : {}
26673
- });
26674
- }
26675
- const hasEffortAxis = result.some((axis) => ["thought_level", "effort", "reasoning_effort"].includes(axis.category));
26676
- if (includeLaunchEffort && effortChoices.length > 0 && !hasEffortAxis) {
26677
- const currentEffort = typeof modelMeta?.reasoningEffort === "string" ? modelMeta.reasoningEffort : efforts.find((entry) => entry && typeof entry === "object" && entry.default)?.value;
26678
- result.push({
26679
- id: GROK_LAUNCH_EFFORT_AXIS_ID,
26680
- category: "reasoning_effort",
26681
- ...typeof currentEffort === "string" ? { currentValue: currentEffort } : {},
26682
- options: effortChoices
26683
- });
26684
- }
26685
- return result;
26717
+ function receiptKindToSilenceKind(kind) {
26718
+ if (kind === "model-selection-unavailable" || kind === "wrong-model")
26719
+ return "wrong-model";
26720
+ if (kind && TURN_SILENCE_KINDS.includes(kind))
26721
+ return kind;
26722
+ return "hiccup";
26686
26723
  }
26687
- function filterAllowedModelConfigOptions(options) {
26688
- return options.filter((option) => isAllowedAgentModelConfigCategory(option.category, option.id));
26724
+ var ALLOWANCE_UNTIL = /(?:try again at|until|resets?(?: at)?|available(?: again)?(?: at)?)\s+([A-Z][a-z]{2,9}\s+\d{1,2}(?:st|nd|rd|th)?,?\s+\d{4}(?:\s+\d{1,2}:\d{2}(?:\s*[AP]M)?)?)/i;
26725
+ var REPO_FROM_URL = /github\.com[:/]([^/\s]+\/[^/\s.]+?)(?:\.git)?(?:[/\s]|$)/i;
26726
+ var REPO_FROM_SLUG = /\b([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\b/;
26727
+ function firstMatch(value, pattern) {
26728
+ const match = value.match(pattern);
26729
+ const captured = match?.[1]?.trim();
26730
+ return captured || void 0;
26689
26731
  }
26690
- var PROVIDER_CREDENTIAL_ENV_HINTS = {
26691
- openai: ["OPENAI_API_KEY", "OPENAI_COMPAT_API_KEY"],
26692
- openrouter: ["OPENROUTER_API_KEY"],
26693
- anthropic: ["ANTHROPIC_API_KEY"],
26694
- google: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
26695
- groq: ["GROQ_API_KEY"],
26696
- mistral: ["MISTRAL_API_KEY"],
26697
- deepseek: ["DEEPSEEK_API_KEY"],
26698
- xai: ["XAI_API_KEY"],
26699
- cohere: ["COHERE_API_KEY"],
26700
- together: ["TOGETHER_API_KEY"],
26701
- fireworks: ["FIREWORKS_API_KEY"]
26702
- };
26703
- function credentialedProviders(env) {
26704
- const held = /* @__PURE__ */ new Set();
26705
- for (const [provider, names] of Object.entries(PROVIDER_CREDENTIAL_ENV_HINTS)) {
26706
- if (names.some((name) => Boolean(env[name]?.trim())))
26707
- held.add(provider);
26708
- }
26709
- for (const provider of credentialedPiCustomProviders(env))
26710
- held.add(provider);
26711
- return held;
26732
+ function isAuthShapedFault(text2) {
26733
+ return /authentication required/i.test(text2) || /not signed in/i.test(text2) || /isn't signed in/i.test(text2) || /invalid api[_ -]?key/i.test(text2) || /\b401\b/.test(text2);
26712
26734
  }
26713
- function credentialedPiCustomProviders(env) {
26714
- const agentDir = env.PI_CODING_AGENT_DIR?.trim() ? resolve9(env.PI_CODING_AGENT_DIR) : env.HOME?.trim() ? resolve9(env.HOME, ".pi/agent") : void 0;
26715
- const held = /* @__PURE__ */ new Set();
26716
- if (!agentDir)
26717
- return held;
26718
- const path = resolve9(agentDir, "models.json");
26719
- try {
26720
- const stats = lstatSync(path);
26721
- if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
26722
- return held;
26735
+ function classifyTurnSilence(reason, reasonKind) {
26736
+ if (isTurnReceiptReasonKind(reasonKind)) {
26737
+ const kind = receiptKindToSilenceKind(reasonKind);
26738
+ if (kind === "hiccup") {
26739
+ return { kind, fault: (reason ?? "").trim() || "the turn stalled" };
26723
26740
  }
26724
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
26725
- const providers = parsed.providers;
26726
- const remember = (name, config) => {
26727
- if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
26728
- return;
26729
- const apiKey = config.apiKey;
26730
- if (typeof apiKey === "string" && apiKey.trim())
26731
- held.add(name.trim());
26741
+ return {
26742
+ kind,
26743
+ ...kind === "allowance-spent" ? { allowanceUntil: firstMatch(reason ?? "", ALLOWANCE_UNTIL) } : {},
26744
+ ...kind === "workspace-failure" ? { repo: repoFromReason(reason ?? "") } : {}
26732
26745
  };
26733
- if (Array.isArray(providers)) {
26734
- for (const provider of providers) {
26735
- const record6 = provider;
26736
- remember(record6?.name ?? record6?.id, record6);
26737
- }
26738
- } else if (providers && typeof providers === "object") {
26739
- for (const [name, config] of Object.entries(providers)) {
26740
- remember(name, config);
26741
- }
26742
- }
26743
- } catch {
26744
26746
  }
26745
- return held;
26746
- }
26747
- function filterModelOptionsByCredentials(options, env) {
26748
- const held = credentialedProviders(env);
26749
- return options.map((option) => {
26750
- if (option.category !== "model")
26751
- return option;
26747
+ const text2 = (reason ?? "").trim();
26748
+ if (!text2)
26749
+ return { kind: "hiccup", fault: "the turn stalled" };
26750
+ if (/model selection unavailable/i.test(text2) || /isn't available/i.test(text2) || /not advertised/i.test(text2)) {
26751
+ return { kind: "wrong-model" };
26752
+ }
26753
+ if (/\b402\b/.test(text2) || /usage limit/i.test(text2) || /more credits/i.test(text2) || /quota/i.test(text2) || /allowance is spent/i.test(text2)) {
26752
26754
  return {
26753
- ...option,
26754
- options: option.options.filter((choice) => {
26755
- const slash = choice.id.indexOf("/");
26756
- if (slash < 0)
26757
- return true;
26758
- return held.has(choice.id.slice(0, slash));
26759
- })
26755
+ kind: "allowance-spent",
26756
+ allowanceUntil: firstMatch(text2, ALLOWANCE_UNTIL)
26760
26757
  };
26761
- });
26762
- }
26763
- var DisallowedModelConfigOptionError = class extends Error {
26764
- constructor(configId) {
26765
- super(`model config option "${configId}" is not in the allow-listed catalog`);
26766
- this.name = "DisallowedModelConfigOptionError";
26767
- }
26768
- };
26769
- function supportsFastMode(options) {
26770
- const axis = options.find((option) => option.id === "fast-mode" && option.category === "model_config");
26771
- return Boolean(axis?.options.some((choice) => choice.id === "on") && axis.options.some((choice) => choice.id === "off"));
26772
- }
26773
- var ModelSelectionUnavailableError = class extends Error {
26774
- label;
26775
- value;
26776
- reason;
26777
- guidance;
26778
- constructor(input) {
26779
- const recovery = input.guidance ? ` ${input.guidance}` : " Choose one of the values in the live harness catalog.";
26780
- super(`${input.label} "${input.value}" is unavailable.${recovery}`);
26781
- this.name = "ModelSelectionUnavailableError";
26782
- this.label = input.label;
26783
- this.value = input.value;
26784
- this.reason = input.reason;
26785
- this.guidance = input.guidance;
26786
26758
  }
26787
- };
26788
- function withEffectiveCurrentValues(options, selection) {
26789
- if (!selection || !selection.model && !selection.effort)
26790
- return options;
26791
- return options.map((option) => {
26792
- const target = modelSelectionTargets(selection).find((entry) => entry.categories.includes(option.category));
26793
- if (!target?.value || option.currentValue === target.value)
26794
- return option;
26795
- return { ...option, currentValue: target.value };
26796
- });
26797
- }
26798
- function modelSelectionTargets(selection) {
26799
- return [
26800
- { categories: ["model"], label: "model", value: selection.model },
26801
- {
26802
- categories: ["thought_level", "effort", "reasoning_effort"],
26803
- label: "effort",
26804
- value: selection.effort
26805
- }
26806
- ];
26807
- }
26808
- function assertModelConfigAxisAllowed(configId, advertisedOptions) {
26809
- const axis = advertisedOptions.find((option) => option.id === configId);
26810
- if (!axis || !isAllowedAgentModelConfigCategory(axis.category, axis.id)) {
26811
- throw new DisallowedModelConfigOptionError(configId);
26759
+ if (isAuthShapedFault(text2)) {
26760
+ return { kind: "not-signed-in" };
26812
26761
  }
26813
- }
26814
- async function applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, advertisedOptions, selection) {
26815
- let currentOptions = advertisedOptions;
26816
- for (const target of modelSelectionTargets(selection)) {
26817
- if (!target.value)
26818
- continue;
26819
- const axis = currentOptions.find((option) => target.categories.includes(option.category));
26820
- if (!axis)
26821
- continue;
26822
- assertModelConfigAxisAllowed(axis.id, currentOptions);
26823
- if (!axis.options.some((choice) => choice.id === target.value)) {
26824
- throw new ModelSelectionUnavailableError({
26825
- label: target.label,
26826
- value: target.value,
26827
- reason: "not-advertised"
26828
- });
26829
- }
26830
- try {
26831
- if (axis.id === GROK_SESSION_MODEL_AXIS_ID) {
26832
- if (!client.setModel)
26833
- throw new Error("ACP client does not support session/set_model");
26834
- await client.setModel(sessionId, target.value);
26835
- } else if (axis.id === GROK_LAUNCH_EFFORT_AXIS_ID) {
26836
- if (axis.currentValue !== target.value) {
26837
- throw new Error(`Grok started with reasoning effort "${axis.currentValue ?? "unknown"}", not "${target.value}"`);
26838
- }
26839
- } else {
26840
- const updated = await client.setConfigOption(sessionId, axis.id, target.value);
26841
- const refreshed = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(updated, selection.model));
26842
- if (refreshed.length > 0)
26843
- currentOptions = refreshed;
26844
- }
26845
- } catch (error) {
26846
- throw new ModelSelectionUnavailableError({
26847
- label: target.label,
26848
- value: target.value,
26849
- reason: "provider-refused",
26850
- guidance: error instanceof Error ? error.message : String(error)
26851
- });
26852
- }
26762
+ if (/command protocol/i.test(text2) || /refusing intake/i.test(text2) || /helper is out of date/i.test(text2)) {
26763
+ return { kind: "helper-out-of-date" };
26853
26764
  }
26854
- if (selection.fastMode && !supportsFastMode(currentOptions)) {
26855
- throw new Error("Fast mode is unavailable for the selected model and harness");
26765
+ if (/working copy/i.test(text2) || /could not (?:clone|fetch|checkout)/i.test(text2) || /repository not found/i.test(text2) || /could not resolve host/i.test(text2) || /failed to start corner/i.test(text2) || /unable to access/i.test(text2) || /\bgit clone\b/i.test(text2) || /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2) || /profile_busy/i.test(text2) || /broker unavailable/i.test(text2)) {
26766
+ return { kind: "workspace-failure", repo: repoFromReason(text2) };
26856
26767
  }
26857
- if (supportsFastMode(currentOptions)) {
26858
- await client.setConfigOption(sessionId, "fast-mode", selection.fastMode ? "on" : "off");
26768
+ if (/helper isn't running/i.test(text2) || /helper is offline/i.test(text2)) {
26769
+ return { kind: "offline" };
26859
26770
  }
26860
- return currentOptions;
26771
+ const fault = text2 || "the turn stalled";
26772
+ return { kind: "hiccup", fault };
26861
26773
  }
26862
- async function applyAgentModelSelection(client, sessionId, advertisedOptions, selection) {
26863
- await applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, advertisedOptions, selection);
26774
+ function repoFromReason(text2) {
26775
+ return firstMatch(text2, REPO_FROM_URL) ?? firstMatch(text2, REPO_FROM_SLUG) ?? "the repository";
26776
+ }
26777
+ function isStandingWorkspaceConfigurationFault(text2) {
26778
+ return /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2);
26779
+ }
26780
+ function hiccupBackoffMs(attempt) {
26781
+ const index = Math.max(1, attempt) - 1;
26782
+ return HICCUP_BACKOFF_MS[Math.min(index, HICCUP_BACKOFF_MS.length - 1)] ?? 0;
26864
26783
  }
26865
26784
 
26866
- // apps/body/dist/model-catalog.js
26867
- import { mkdtemp, rm as rm3 } from "node:fs/promises";
26868
- import { tmpdir } from "node:os";
26869
- import { resolve as resolve10 } from "node:path";
26870
-
26871
- // apps/body/dist/acp.js
26872
- init_adapter_install_lock();
26873
- import { spawn as spawn10 } from "node:child_process";
26874
- import { EventEmitter } from "node:events";
26875
-
26876
- // apps/body/dist/harness-capabilities.js
26877
- init_cursor_acp_bridge();
26878
- var PROFILES = [
26879
- {
26880
- match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
26881
- profile: {
26882
- enforcement: "sandboxed",
26883
- note: "codex-acp asks for every command/file change and enforces an offline read-only OS sandbox in read-only mode; under bubblewrap a Room runs it in agent-full-access and bwrap holds the filesystem rule"
26884
- }
26885
- },
26886
- {
26887
- match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i,
26888
- profile: {
26889
- enforcement: "permission-callback",
26890
- note: "claude-agent-acp asks for every tool call; it advertises no read-only mode, so the daemon callback is the only boundary"
26891
- }
26892
- },
26893
- {
26894
- match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
26895
- profile: {
26896
- enforcement: "none",
26897
- note: "pi-acp never sends session/request_permission for a tool call: pi executes reads, writes, edits, and shell commands before the daemon sees them, and exposes no sandbox or permission flag to pass at spawn"
26898
- }
26899
- },
26900
- {
26901
- match: /(^|[/\\])grok(\.[a-z]+)?$/i,
26902
- profile: {
26903
- enforcement: "permission-callback",
26904
- note: "grok sends standard session/request_permission requests for mutating tools in its default ask mode; it advertises no read-only ACP mode, so the daemon callback is the only boundary unless the OS sandbox wraps it"
26905
- }
26906
- },
26907
- {
26908
- match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
26909
- profile: {
26910
- enforcement: "permission-callback",
26911
- note: "buzz-agent sends session/request_permission for mutating tools"
26912
- }
26913
- },
26914
- {
26915
- match: CURSOR_HARNESS_COMMAND,
26916
- profile: {
26917
- enforcement: "none",
26918
- note: "cursor-acp-bridge drives cursor-agent with --force --approve-mcps in non-interactive stream-json mode, so cursor-agent never sends session/request_permission; Beeline already sandboxes the child"
26919
- }
26920
- }
26921
- ];
26922
- function harnessEnforcement(agentCommand) {
26923
- if (!agentCommand)
26924
- return { enforcement: "unknown", note: "no ACP command configured" };
26925
- for (const { match, profile } of PROFILES) {
26926
- if (match.test(agentCommand))
26927
- return profile;
26785
+ // packages/api-contract/dist/institutional-memory.js
26786
+ var INSTITUTIONAL_MEMORY_PROPOSAL_VERSION = 1;
26787
+ var INSTITUTIONAL_MEMORY_BODY_MAX_BYTES = 200;
26788
+ var INSTITUTIONAL_MEMORY_KEYWORDS_MIN = 1;
26789
+ var INSTITUTIONAL_MEMORY_KEYWORDS_MAX = 6;
26790
+ var INSTITUTIONAL_MEMORY_KEYWORD_PATTERN = /^[a-z0-9][a-z0-9_./-]{2,31}$/;
26791
+ var INSTITUTIONAL_MEMORY_STOPWORDS = /* @__PURE__ */ new Set([
26792
+ "the",
26793
+ "and",
26794
+ "you",
26795
+ "your",
26796
+ "for",
26797
+ "with",
26798
+ "that",
26799
+ "this",
26800
+ "are",
26801
+ "was",
26802
+ "were",
26803
+ "but",
26804
+ "not",
26805
+ "have",
26806
+ "has",
26807
+ "had",
26808
+ "can",
26809
+ "all",
26810
+ "any",
26811
+ "our",
26812
+ "out",
26813
+ "use",
26814
+ "get",
26815
+ "got",
26816
+ "how",
26817
+ "what",
26818
+ "when",
26819
+ "who",
26820
+ "why",
26821
+ "will",
26822
+ "just",
26823
+ "from",
26824
+ "they",
26825
+ "them",
26826
+ "then",
26827
+ "than",
26828
+ "there",
26829
+ "here",
26830
+ "about",
26831
+ "into",
26832
+ "also",
26833
+ "its",
26834
+ "it's",
26835
+ "please",
26836
+ "should",
26837
+ "would",
26838
+ "could",
26839
+ "some",
26840
+ "more",
26841
+ "most",
26842
+ "very",
26843
+ "only",
26844
+ "one",
26845
+ "now",
26846
+ "yes",
26847
+ "okay",
26848
+ "let",
26849
+ "make",
26850
+ "want",
26851
+ "need",
26852
+ "does",
26853
+ "did",
26854
+ "done",
26855
+ "like",
26856
+ "know",
26857
+ "think",
26858
+ "see",
26859
+ "look",
26860
+ "thing",
26861
+ "things",
26862
+ "way"
26863
+ ]);
26864
+ var INSTITUTIONAL_STANDING_PREFERENCE_KEY = "standing";
26865
+ var INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH = 160;
26866
+ var INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH = 500;
26867
+ var INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX = 16;
26868
+ var INSTITUTIONAL_MEMORY_JOB_ERROR_MAX_LENGTH = 1e3;
26869
+ var WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH = 60;
26870
+ var WORKSPACE_SKILL_MARKDOWN_MAX_BYTES = 32 * 1024;
26871
+ var WORKSPACE_SKILL_SLUG_MAX_LENGTH = 64;
26872
+ var INSTITUTIONAL_REVIEW_FINDING_MAX = 20;
26873
+ var INSTITUTIONAL_CURATOR_ACTION_MAX = 50;
26874
+ function record2(value, label) {
26875
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
26876
+ throw new Error(`${label} must be an object`);
26928
26877
  }
26929
- return {
26930
- enforcement: "unknown",
26931
- note: `'${agentCommand}' has not been verified to send session/request_permission for mutating tools`
26932
- };
26878
+ return value;
26933
26879
  }
26934
- function harnessHonorsSessionSystemPrompt(agentCommand) {
26935
- return Boolean(agentCommand && /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand));
26880
+ function exactKeys(value, allowed, label) {
26881
+ const unknown = Object.keys(value).find((key) => !allowed.includes(key));
26882
+ if (unknown)
26883
+ throw new Error(`${label} has unknown field ${unknown}`);
26936
26884
  }
26937
- var GROK_WARM_SESSION_IDLE_MS = 30 * 6e4;
26938
- function cornerAutonomyModeCandidates(agentCommand) {
26939
- if (agentCommand && /(^|[/\\])codex-acp(\.[a-z]+)?$/i.test(agentCommand)) {
26940
- return ["agent-full-access"];
26885
+ function omitted(value) {
26886
+ return value === void 0 || value === null;
26887
+ }
26888
+ function boundedText(value, label, maximum, bytes = false) {
26889
+ if (typeof value !== "string" || value.includes("\0"))
26890
+ throw new Error(`${label} is invalid`);
26891
+ const normalized = value.trim();
26892
+ const size = bytes ? new TextEncoder().encode(normalized).length : normalized.length;
26893
+ if (!normalized || size > maximum)
26894
+ throw new Error(`${label} is invalid`);
26895
+ return normalized;
26896
+ }
26897
+ var FILLER_OPENINGS = /^(?:the user|user|this user|the requester|requester|it is|it's|note that|please|remember that|keep in mind)\b/i;
26898
+ var HEDGES = /\b(?:maybe|perhaps|probably|possibly|might|seems?|i think|apparently|likely)\b/i;
26899
+ function conciseInstitutionalMemoryBody(value) {
26900
+ const body = boundedText(value, `institutional memory body (at most ${INSTITUTIONAL_MEMORY_BODY_MAX_BYTES} bytes)`, INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
26901
+ if (FILLER_OPENINGS.test(body)) {
26902
+ throw new Error("institutional memory body must state the fact itself, without a filler opening");
26941
26903
  }
26942
- if (agentCommand && /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand)) {
26943
- return ["bypassPermissions"];
26904
+ if (/[.!?;]\s+\S/.test(body) || /\n/.test(body)) {
26905
+ throw new Error("institutional memory body must be one sentence");
26944
26906
  }
26945
- if (agentCommand && /(^|[/\\])grok(\.[a-z]+)?$/i.test(agentCommand))
26946
- return [];
26947
- if (agentCommand && /(^|[/\\])pi-acp(\.[a-z]+)?$/i.test(agentCommand))
26948
- return [];
26949
- return ["agent", "edit", "code"];
26907
+ if (HEDGES.test(body)) {
26908
+ throw new Error("institutional memory body must not hedge; save only what is known");
26909
+ }
26910
+ return body;
26950
26911
  }
26951
- function roomModeCandidates(agentCommand, options = {}) {
26952
- if (options.osSandbox && agentCommand && /(^|[/\\])codex-acp(\.[a-z]+)?$/i.test(agentCommand)) {
26953
- return ["agent-full-access"];
26912
+ function institutionalMemoryKeywords(value) {
26913
+ if (!Array.isArray(value) || value.length < INSTITUTIONAL_MEMORY_KEYWORDS_MIN || value.length > INSTITUTIONAL_MEMORY_KEYWORDS_MAX) {
26914
+ throw new Error(`institutional memory needs ${INSTITUTIONAL_MEMORY_KEYWORDS_MIN} to ${INSTITUTIONAL_MEMORY_KEYWORDS_MAX} keywords`);
26954
26915
  }
26955
- return ["read-only", "readonly"];
26916
+ const keywords = value.map((keyword) => typeof keyword === "string" ? keyword.trim().toLocaleLowerCase("en-US") : "");
26917
+ if (keywords.some((keyword) => !INSTITUTIONAL_MEMORY_KEYWORD_PATTERN.test(keyword) || INSTITUTIONAL_MEMORY_STOPWORDS.has(keyword))) {
26918
+ throw new Error("institutional memory keywords are distinctive single lower-case words of 3 to 32 letters, digits, or _./-");
26919
+ }
26920
+ if (new Set(keywords).size !== keywords.length) {
26921
+ throw new Error("institutional memory keywords must be unique");
26922
+ }
26923
+ return keywords;
26956
26924
  }
26957
- function harnessDeclaresShellExecuteKind(agentCommand) {
26958
- return Boolean(agentCommand && (/(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand) || /(^|[/\\])grok(\.[a-z]+)?$/i.test(agentCommand)));
26925
+ function parseInstitutionalMemoryProposal(value) {
26926
+ const proposal = record2(value, "institutional memory proposal");
26927
+ exactKeys(proposal, [
26928
+ "proposalVersion",
26929
+ "candidateType",
26930
+ "memoryKind",
26931
+ "subjectIdentityId",
26932
+ "canonicalKey",
26933
+ "body",
26934
+ "keywords",
26935
+ "source",
26936
+ "audience",
26937
+ "confidence",
26938
+ "classification",
26939
+ "cas"
26940
+ ], "institutional memory proposal");
26941
+ if (proposal.proposalVersion !== INSTITUTIONAL_MEMORY_PROPOSAL_VERSION) {
26942
+ throw new Error("institutional memory proposal version is unsupported");
26943
+ }
26944
+ if (proposal.candidateType !== "correction_candidate" && proposal.candidateType !== "fact_candidate" && proposal.candidateType !== "preference_candidate") {
26945
+ throw new Error("institutional memory candidate type is invalid");
26946
+ }
26947
+ if (proposal.memoryKind !== "workspace_fact" && proposal.memoryKind !== "human_profile_fact") {
26948
+ throw new Error("institutional memory kind is invalid");
26949
+ }
26950
+ if (proposal.audience !== "workspace" && proposal.audience !== "human_profile") {
26951
+ throw new Error("institutional memory audience is invalid");
26952
+ }
26953
+ if (typeof proposal.confidence !== "number" || !Number.isFinite(proposal.confidence) || proposal.confidence < 0 || proposal.confidence > 1) {
26954
+ throw new Error("institutional memory confidence is invalid");
26955
+ }
26956
+ const source = record2(proposal.source, "institutional memory source");
26957
+ exactKeys(source, ["roomId", "messageIds"], "institutional memory source");
26958
+ const roomId = boundedText(source.roomId, "institutional memory source room", 200);
26959
+ if (!Array.isArray(source.messageIds) || source.messageIds.length === 0 || source.messageIds.length > INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX) {
26960
+ throw new Error("institutional memory source messages are invalid");
26961
+ }
26962
+ const messageIds = source.messageIds.map((messageId) => boundedText(messageId, "institutional memory source message", 200));
26963
+ if (new Set(messageIds).size !== messageIds.length) {
26964
+ throw new Error("institutional memory source messages must be unique");
26965
+ }
26966
+ const classification = record2(proposal.classification, "institutional memory classification");
26967
+ exactKeys(classification, ["stillTrueForAnotherRequester", "subjectIsRequester", "rationale"], "institutional memory classification");
26968
+ if (classification.stillTrueForAnotherRequester !== void 0 && typeof classification.stillTrueForAnotherRequester !== "boolean") {
26969
+ throw new Error("institutional memory classification test is invalid");
26970
+ }
26971
+ if (classification.subjectIsRequester !== void 0 && typeof classification.subjectIsRequester !== "boolean") {
26972
+ throw new Error("institutional memory subject classification is invalid");
26973
+ }
26974
+ const canonicalKey = boundedText(proposal.canonicalKey, "institutional memory canonical key", INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH);
26975
+ if (canonicalKey === INSTITUTIONAL_STANDING_PREFERENCE_KEY) {
26976
+ throw new Error("the standing preference key is reserved for owner-confirmed preferences");
26977
+ }
26978
+ const rationale = boundedText(classification.rationale, "institutional memory classification rationale", INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH);
26979
+ const cas = record2(proposal.cas, "institutional memory CAS");
26980
+ exactKeys(cas, ["baseVersion", "supersedesItemId"], "institutional memory CAS");
26981
+ if (cas.baseVersion !== null && (!Number.isSafeInteger(cas.baseVersion) || cas.baseVersion < 0)) {
26982
+ throw new Error("institutional memory base version is invalid");
26983
+ }
26984
+ const supersedesItemId = cas.supersedesItemId === void 0 ? void 0 : boundedText(cas.supersedesItemId, "institutional memory supersedes item", 200);
26985
+ const workspaceFact = proposal.memoryKind === "workspace_fact";
26986
+ if (classification.subjectIsRequester !== void 0 && classification.subjectIsRequester === workspaceFact) {
26987
+ throw new Error("institutional memory kind contradicts its subject");
26988
+ }
26989
+ if (proposal.audience === "workspace" !== workspaceFact) {
26990
+ throw new Error("institutional memory audience contradicts its kind");
26991
+ }
26992
+ const subjectIdentityId = proposal.subjectIdentityId === void 0 ? void 0 : boundedText(proposal.subjectIdentityId, "institutional memory profile subject", 200);
26993
+ if (workspaceFact === Boolean(subjectIdentityId)) {
26994
+ throw new Error(workspaceFact ? "workspace facts cannot name a profile subject" : "human profile facts require a subject");
26995
+ }
26996
+ return {
26997
+ proposalVersion: INSTITUTIONAL_MEMORY_PROPOSAL_VERSION,
26998
+ candidateType: proposal.candidateType,
26999
+ memoryKind: proposal.memoryKind,
27000
+ ...subjectIdentityId ? { subjectIdentityId } : {},
27001
+ canonicalKey,
27002
+ body: conciseInstitutionalMemoryBody(proposal.body),
27003
+ keywords: institutionalMemoryKeywords(proposal.keywords),
27004
+ source: { roomId, messageIds },
27005
+ audience: proposal.audience,
27006
+ confidence: proposal.confidence,
27007
+ classification: {
27008
+ ...classification.stillTrueForAnotherRequester === void 0 ? {} : {
27009
+ stillTrueForAnotherRequester: classification.stillTrueForAnotherRequester
27010
+ },
27011
+ ...classification.subjectIsRequester === void 0 ? {} : {
27012
+ subjectIsRequester: classification.subjectIsRequester
27013
+ },
27014
+ rationale
27015
+ },
27016
+ cas: {
27017
+ baseVersion: cas.baseVersion,
27018
+ ...supersedesItemId ? { supersedesItemId } : {}
27019
+ }
27020
+ };
26959
27021
  }
26960
- function roomShellCapability(agentCommand, options = {}) {
26961
- const { enforcement } = harnessEnforcement(agentCommand);
26962
- if (enforcement === "sandboxed" || enforcement === "none")
26963
- return "runs";
26964
- if (enforcement === "unknown")
26965
- return "unknown";
26966
- if (!harnessDeclaresShellExecuteKind(agentCommand))
26967
- return "unknown";
26968
- return options.osSandbox ? "runs" : "refused";
27022
+ function repositoryRelativePath(value) {
27023
+ if (typeof value !== "string" || value.length === 0 || value.length > 500)
27024
+ return void 0;
27025
+ if (value.startsWith("/") || value.includes("\\") || value.split("/").some((segment) => segment === ".." || segment === "")) {
27026
+ return void 0;
27027
+ }
27028
+ return value;
26969
27029
  }
26970
-
26971
- // apps/body/dist/harness-tool-scope.js
26972
- init_cursor_acp_bridge();
26973
- var CLAUDE_TOOL_SCOPE_SETTINGS = { disableClaudeAiConnectors: true };
26974
- var CLAUDE_PROFILE = {
26975
- // `settingSources: ['user']` admits the sanitized user MCP copy
26976
- // while rejecting repository/local/plugin MCP. `strictMcpConfig` cannot be
26977
- // used because it would reject the user copy too. Account-bound claude.ai
26978
- // cloud connectors remain off independently.
26979
- enforcement: "config-isolated",
26980
- note: "claude-agent-acp forwards _meta.claudeCode.options to the Claude Agent SDK; user-only settingSources loads MCP from the isolated CLAUDE_CONFIG_DIR without repository/local settings, while disableClaudeAiConnectors keeps account-bound connectors off",
26981
- sessionMeta: {
26982
- claudeCode: {
26983
- options: {
26984
- // Only the sanitized user config in the isolated CLAUDE_CONFIG_DIR;
26985
- // never a repository's .mcp.json, local settings, or plugins.
26986
- settingSources: ["user"],
26987
- // Account-bound claude.ai cloud connectors are not fetched at all.
26988
- settings: CLAUDE_TOOL_SCOPE_SETTINGS
27030
+ function optionalAnchorField(key, value) {
27031
+ return value === void 0 ? {} : { [key]: value };
27032
+ }
27033
+ function parseInstitutionalMergeReviewProposal(value) {
27034
+ const proposal = record2(value, "institutional merge review proposal");
27035
+ exactKeys(proposal, ["proposalVersion", "skill", "findings"], "institutional merge review proposal");
27036
+ if (proposal.proposalVersion !== 1) {
27037
+ throw new Error("institutional merge review proposal version is unsupported");
27038
+ }
27039
+ let skill = null;
27040
+ if (!omitted(proposal.skill)) {
27041
+ const rawSkill = record2(proposal.skill, "workspace skill proposal");
27042
+ exactKeys(rawSkill, ["slug", "description", "markdown", "baseVersion", "anchor"], "workspace skill proposal");
27043
+ const slug = boundedText(rawSkill.slug, "workspace skill slug", WORKSPACE_SKILL_SLUG_MAX_LENGTH);
27044
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) {
27045
+ throw new Error("workspace skill slug is invalid");
27046
+ }
27047
+ const anchor = record2(rawSkill.anchor, "workspace skill code anchor");
27048
+ exactKeys(anchor, ["repository", "targetCommit", "path"], "workspace skill code anchor");
27049
+ if (rawSkill.baseVersion !== null && (!Number.isSafeInteger(rawSkill.baseVersion) || rawSkill.baseVersion <= 0)) {
27050
+ throw new Error("workspace skill base version is invalid");
27051
+ }
27052
+ skill = {
27053
+ slug,
27054
+ description: boundedText(rawSkill.description, "workspace skill description", WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH),
27055
+ markdown: boundedText(rawSkill.markdown, "workspace skill markdown", WORKSPACE_SKILL_MARKDOWN_MAX_BYTES, true),
27056
+ baseVersion: rawSkill.baseVersion,
27057
+ anchor: {
27058
+ repository: boundedText(anchor.repository, "workspace skill repository", 300),
27059
+ targetCommit: boundedText(anchor.targetCommit, "workspace skill target commit", 160),
27060
+ ...optionalAnchorField("path", repositoryRelativePath(anchor.path))
26989
27061
  }
27062
+ };
27063
+ }
27064
+ if (!Array.isArray(proposal.findings) || proposal.findings.length > INSTITUTIONAL_REVIEW_FINDING_MAX) {
27065
+ throw new Error("institutional review findings are invalid");
27066
+ }
27067
+ const findings = proposal.findings.map((value2) => {
27068
+ const finding = record2(value2, "institutional review finding");
27069
+ exactKeys(finding, ["taxonomy", "summary", "severity", "confidence", "path"], "institutional review finding");
27070
+ if (finding.severity !== "info" && finding.severity !== "warning" && finding.severity !== "error") {
27071
+ throw new Error("institutional review finding severity is invalid");
26990
27072
  }
26991
- },
26992
- metaSystemPrompt: true
26993
- };
26994
- var PROFILES2 = [
26995
- { match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i, profile: CLAUDE_PROFILE },
26996
- {
26997
- match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
26998
- profile: {
26999
- enforcement: "config-isolated",
27000
- note: "codex-acp merges the session's MCP servers into $CODEX_HOME/config.toml's own [mcp_servers] instead of replacing them, so only an isolated CODEX_HOME scopes the session; the ChatGPT account's codex_apps connectors survive either way"
27073
+ const severity = finding.severity;
27074
+ if (typeof finding.confidence !== "number" || !Number.isFinite(finding.confidence) || finding.confidence < 0 || finding.confidence > 1) {
27075
+ throw new Error("institutional review finding confidence is invalid");
27001
27076
  }
27002
- },
27003
- {
27004
- match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
27005
- profile: {
27006
- enforcement: "config-isolated",
27007
- note: "pi-acp 0.0.33 still stores session/new mcpServers and never reads them; pi 0.85.1 itself has no MCP client, while optional pi-mcp-adapter reads $PI_CODING_AGENT_DIR/mcp.json and isolated homes exclude the settings.json that would load it"
27077
+ return {
27078
+ taxonomy: boundedText(finding.taxonomy, "institutional review finding taxonomy", 120),
27079
+ summary: boundedText(finding.summary, "institutional review finding summary", 1e3),
27080
+ severity,
27081
+ confidence: finding.confidence,
27082
+ ...omitted(finding.path) ? {} : { path: boundedText(finding.path, "institutional review finding path", 500) }
27083
+ };
27084
+ });
27085
+ return { proposalVersion: 1, skill, findings };
27086
+ }
27087
+ function parseInstitutionalCuratorProposal(value) {
27088
+ const proposal = record2(value, "institutional curator proposal");
27089
+ exactKeys(proposal, ["proposalVersion", "partition", "actions"], "institutional curator proposal");
27090
+ if (proposal.proposalVersion !== 1) {
27091
+ throw new Error("institutional curator proposal version is unsupported");
27092
+ }
27093
+ const partition = boundedText(proposal.partition, "institutional curator partition", 300);
27094
+ if (!Array.isArray(proposal.actions) || proposal.actions.length > INSTITUTIONAL_CURATOR_ACTION_MAX) {
27095
+ throw new Error("institutional curator actions are invalid");
27096
+ }
27097
+ const actions = proposal.actions.map((value2) => {
27098
+ const action = record2(value2, "institutional curator action");
27099
+ exactKeys(action, [
27100
+ "action",
27101
+ "targetType",
27102
+ "targetId",
27103
+ "baseVersion",
27104
+ "duplicateIds",
27105
+ "body",
27106
+ "description",
27107
+ "markdown",
27108
+ "rationale"
27109
+ ], "institutional curator action");
27110
+ if (action.action !== "retain" && action.action !== "stale" && action.action !== "archive" && action.action !== "consolidate") {
27111
+ throw new Error("institutional curator action kind is invalid");
27008
27112
  }
27009
- },
27010
- {
27011
- match: /(^|[/\\])grok(\.[a-z]+)?$/i,
27012
- profile: {
27013
- enforcement: "config-isolated",
27014
- note: "grok loads the operator's own ~/.grok MCP servers even when session/new passes an empty mcpServers list (measured live), so only an isolated GROK_HOME scopes the session; no account-bound connector surface was found"
27113
+ if (action.targetType !== "memory_item" && action.targetType !== "workspace_skill") {
27114
+ throw new Error("institutional curator target type is invalid");
27015
27115
  }
27016
- },
27017
- {
27018
- match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
27019
- profile: {
27020
- enforcement: "allowlisted",
27021
- note: "buzz-agent mounts only the MCP servers the daemon passes; it has no operator-global tool config"
27116
+ if (!Number.isSafeInteger(action.baseVersion) || action.baseVersion <= 0) {
27117
+ throw new Error("institutional curator base version is invalid");
27022
27118
  }
27023
- },
27024
- {
27025
- match: CURSOR_HARNESS_COMMAND,
27026
- profile: {
27027
- enforcement: "config-isolated",
27028
- note: "cursor-acp-bridge writes session/new mcpServers into the isolated CURSOR_HOME mcp.json and the isolated $HOME/.cursor/mcp.json cursor-agent loads; it never writes the operator ~/.cursor"
27119
+ if (!Array.isArray(action.duplicateIds) || action.duplicateIds.length > 20 || action.duplicateIds.some((id) => typeof id !== "string" || !id || id.length > 100)) {
27120
+ throw new Error("institutional curator duplicate ids are invalid");
27029
27121
  }
27030
- }
27031
- ];
27032
- function sessionToolScopeMeta(agentCommand) {
27033
- const meta = matchProfile(agentCommand)?.sessionMeta;
27034
- return meta ? JSON.parse(JSON.stringify(meta)) : void 0;
27035
- }
27036
- function harnessReadsMetaSystemPrompt(agentCommand) {
27037
- return matchProfile(agentCommand)?.metaSystemPrompt === true;
27122
+ if (action.action === "consolidate" && action.duplicateIds.length === 0) {
27123
+ throw new Error("institutional curator consolidation needs duplicates");
27124
+ }
27125
+ if (action.action !== "consolidate" && action.duplicateIds.length !== 0) {
27126
+ throw new Error("institutional curator lifecycle action cannot carry duplicates");
27127
+ }
27128
+ const body = omitted(action.body) ? void 0 : action.targetType === "memory_item" ? conciseInstitutionalMemoryBody(action.body) : boundedText(action.body, "institutional curator body", INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
27129
+ const description = omitted(action.description) ? void 0 : boundedText(action.description, "institutional curator skill description", WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH);
27130
+ const markdown = omitted(action.markdown) ? void 0 : boundedText(action.markdown, "institutional curator skill markdown", WORKSPACE_SKILL_MARKDOWN_MAX_BYTES, true);
27131
+ if (action.action === "consolidate" && (action.targetType === "memory_item" && (!body || description || markdown) || action.targetType === "workspace_skill" && (!description || !markdown || body))) {
27132
+ throw new Error("institutional curator consolidation content is invalid");
27133
+ }
27134
+ if (action.action !== "consolidate" && (body || description || markdown)) {
27135
+ throw new Error("institutional curator lifecycle action cannot replace content");
27136
+ }
27137
+ return {
27138
+ action: action.action,
27139
+ targetType: action.targetType,
27140
+ targetId: boundedText(action.targetId, "institutional curator target id", 100),
27141
+ baseVersion: action.baseVersion,
27142
+ duplicateIds: [...new Set(action.duplicateIds)],
27143
+ ...body ? { body } : {},
27144
+ ...description ? { description } : {},
27145
+ ...markdown ? { markdown } : {},
27146
+ rationale: boundedText(action.rationale, "institutional curator rationale", 500)
27147
+ };
27148
+ });
27149
+ return { proposalVersion: 1, partition, actions };
27038
27150
  }
27039
- function matchProfile(agentCommand) {
27040
- if (!agentCommand)
27041
- return void 0;
27042
- for (const { match, profile } of PROFILES2) {
27043
- if (match.test(agentCommand))
27044
- return profile;
27045
- }
27046
- return void 0;
27151
+
27152
+ // packages/api-contract/dist/workflow-contracts.js
27153
+ var WORKFLOW_TIMEOUT_SECONDS_MAX = 30 * 24 * 60 * 60;
27154
+
27155
+ // packages/api-contract/dist/agent-classes.js
27156
+ var WEIGHT_TIER_RULE_PATTERN_MAX_LENGTH = 32;
27157
+ var RULE_PATTERN_SHAPE = new RegExp(`^[a-z0-9*.-]{1,${WEIGHT_TIER_RULE_PATTERN_MAX_LENGTH}}$`);
27158
+
27159
+ // apps/body/dist/transient-provider-error.js
27160
+ var TRANSIENT_PATTERNS = [
27161
+ /\b429\b/,
27162
+ /\b529\b/,
27163
+ /overloaded/i,
27164
+ /rate.?limit/i,
27165
+ /\bETIMEDOUT\b/,
27166
+ /\bECONNRESET\b/,
27167
+ /\bECONNREFUSED\b/,
27168
+ /timed out/i,
27169
+ /\btimeout\b/i
27170
+ ];
27171
+ function isTransientProviderText(text2) {
27172
+ return TRANSIENT_PATTERNS.some((pattern) => pattern.test(text2));
27047
27173
  }
27048
27174
 
27049
- // apps/body/dist/acp.js
27050
- var STDERR_TAIL_MAX_CHARS2 = 2e3;
27051
- function braceDelta(line) {
27052
- let delta = 0;
27053
- for (const char of line) {
27054
- if (char === "{")
27055
- delta += 1;
27056
- else if (char === "}")
27057
- delta -= 1;
27058
- }
27059
- return delta;
27175
+ // apps/body/dist/model-config.js
27176
+ var GROK_SESSION_MODEL_AXIS_ID = "beeline:grok-session-model";
27177
+ var GROK_LAUNCH_EFFORT_AXIS_ID = "beeline:grok-launch-reasoning-effort";
27178
+ function isGrokAgentCommand(agent) {
27179
+ if (agent.kind === "grok")
27180
+ return true;
27181
+ if (agent.kind && agent.kind !== "custom")
27182
+ return false;
27183
+ return /^grok(?:\.[a-z0-9]+)?$/i.test(basename3(agent.command));
27060
27184
  }
27061
- function meaningfulHarnessStderr(tail) {
27062
- const lines = tail.split(/\r?\n/);
27063
- const kept = [];
27064
- for (let index = 0; index < lines.length; index += 1) {
27065
- const line = lines[index];
27066
- if (!/error handling notification/i.test(line)) {
27067
- kept.push(line);
27068
- continue;
27069
- }
27070
- const block2 = [line];
27071
- let depth = braceDelta(line);
27072
- if (depth === 0 && lines[index + 1]?.trimStart().startsWith("{")) {
27185
+ function agentArgsWithModelSelection(agent, selection) {
27186
+ const original = [...agent.args];
27187
+ if (!selection || !selection.model && !selection.effort || !isGrokAgentCommand(agent) || !original.includes("agent") || !original.includes("stdio")) {
27188
+ return original;
27189
+ }
27190
+ const stripped = [];
27191
+ for (let index = 0; index < original.length; index += 1) {
27192
+ const arg = original[index];
27193
+ if (arg === "-m" || arg === "--model" || arg === "--reasoning-effort") {
27073
27194
  index += 1;
27074
- block2.push(lines[index]);
27075
- depth = braceDelta(lines[index]);
27195
+ continue;
27076
27196
  }
27077
- while (depth > 0 && index + 1 < lines.length) {
27078
- index += 1;
27079
- block2.push(lines[index]);
27080
- depth += braceDelta(lines[index]);
27197
+ if (arg.startsWith("--model=") || arg.startsWith("--reasoning-effort=") || /^-m=/.test(arg)) {
27198
+ continue;
27081
27199
  }
27082
- if (!/notifications\/initialized/.test(block2.join("\n")))
27083
- kept.push(...block2);
27200
+ stripped.push(arg);
27084
27201
  }
27085
- return kept.join("\n").trim();
27086
- }
27087
- function flattenHarnessCause(tail) {
27088
- return meaningfulHarnessStderr(tail).replace(/\s+/g, " ").trim();
27202
+ const stdioIndex = stripped.lastIndexOf("stdio");
27203
+ const configured = [
27204
+ ...selection.model ? ["--model", selection.model] : [],
27205
+ ...selection.effort ? ["--reasoning-effort", selection.effort] : []
27206
+ ];
27207
+ stripped.splice(stdioIndex, 0, ...configured);
27208
+ return stripped;
27209
+ }
27210
+ function advertisedChoiceId(choice) {
27211
+ if (typeof choice.id === "string" && choice.id.length > 0)
27212
+ return choice.id;
27213
+ if (typeof choice.value === "string" && choice.value.length > 0)
27214
+ return choice.value;
27215
+ return void 0;
27216
+ }
27217
+ function modelFamilyKey(choice) {
27218
+ return (/^\s*[\p{L}]+/u.exec(choice.name ?? "")?.[0] ?? "").toLowerCase();
27219
+ }
27220
+ function modelVersionKey(choice) {
27221
+ const digits = choice.name?.match(/\d+/g) ?? choice.id.match(/\d+/g) ?? [];
27222
+ return digits.map(Number);
27223
+ }
27224
+ function sortModelChoicesNewestFirst(choices) {
27225
+ const indexed = choices.map((choice, index) => ({ choice, index }));
27226
+ const families = /* @__PURE__ */ new Map();
27227
+ for (const entry of indexed) {
27228
+ const key = modelFamilyKey(entry.choice);
27229
+ const bucket = families.get(key);
27230
+ if (bucket)
27231
+ bucket.push(entry);
27232
+ else
27233
+ families.set(key, [entry]);
27234
+ }
27235
+ const result = [];
27236
+ for (const bucket of families.values()) {
27237
+ bucket.sort((left, right) => {
27238
+ const leftParts = modelVersionKey(left.choice);
27239
+ const rightParts = modelVersionKey(right.choice);
27240
+ for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {
27241
+ const delta = (rightParts[index] ?? -1) - (leftParts[index] ?? -1);
27242
+ if (delta !== 0)
27243
+ return delta;
27244
+ }
27245
+ return left.index - right.index;
27246
+ });
27247
+ result.push(...bucket.map(({ choice }) => choice));
27248
+ }
27249
+ return result;
27250
+ }
27251
+ function resolveModelFamilyFallback(options, missingId) {
27252
+ const family = (/^\s*[\p{L}]+/u.exec(missingId)?.[0] ?? "").toLowerCase();
27253
+ if (!family)
27254
+ return void 0;
27255
+ return options.find((choice) => modelFamilyKey(choice) === family);
27256
+ }
27257
+ function parseAdvertisedConfigOptions(raw, preferredModelId, includeLaunchEffort = false) {
27258
+ const configOptions = raw?.configOptions;
27259
+ const result = [];
27260
+ for (const entry of Array.isArray(configOptions) ? configOptions : []) {
27261
+ if (!entry || typeof entry !== "object")
27262
+ continue;
27263
+ const record6 = entry;
27264
+ const id = record6.id;
27265
+ const category = record6.category;
27266
+ if (typeof id !== "string" || typeof category !== "string")
27267
+ continue;
27268
+ const rawChoices = Array.isArray(record6.options) ? record6.options : [];
27269
+ const choices = [];
27270
+ for (const rawChoice of rawChoices) {
27271
+ if (!rawChoice || typeof rawChoice !== "object")
27272
+ continue;
27273
+ const choice = rawChoice;
27274
+ const choiceId = advertisedChoiceId(choice);
27275
+ if (!choiceId)
27276
+ continue;
27277
+ choices.push({
27278
+ id: choiceId,
27279
+ ...typeof choice.name === "string" ? { name: choice.name } : {}
27280
+ });
27281
+ }
27282
+ result.push({
27283
+ id,
27284
+ category,
27285
+ ...typeof record6.currentValue === "string" ? { currentValue: record6.currentValue } : {},
27286
+ options: category === "model" ? sortModelChoicesNewestFirst(choices) : choices
27287
+ });
27288
+ }
27289
+ const models = raw?.models;
27290
+ if (!models || typeof models !== "object")
27291
+ return result;
27292
+ const modelState = models;
27293
+ const availableModels = Array.isArray(modelState.availableModels) ? modelState.availableModels : [];
27294
+ const modelChoices = [];
27295
+ for (const entry of availableModels) {
27296
+ if (!entry || typeof entry !== "object")
27297
+ continue;
27298
+ const model = entry;
27299
+ if (typeof model.modelId !== "string" || !model.modelId)
27300
+ continue;
27301
+ modelChoices.push({
27302
+ id: model.modelId,
27303
+ ...typeof model.name === "string" ? { name: model.name } : {}
27304
+ });
27305
+ }
27306
+ const currentModelId = typeof modelState.currentModelId === "string" ? modelState.currentModelId : void 0;
27307
+ if (modelChoices.length > 0 && !result.some((axis) => axis.category === "model")) {
27308
+ result.push({
27309
+ id: GROK_SESSION_MODEL_AXIS_ID,
27310
+ category: "model",
27311
+ ...currentModelId ? { currentValue: currentModelId } : {},
27312
+ options: sortModelChoicesNewestFirst(modelChoices)
27313
+ });
27314
+ }
27315
+ const effortModelId = preferredModelId ?? currentModelId;
27316
+ const currentModel = availableModels.find((entry) => entry && typeof entry === "object" && entry.modelId === effortModelId);
27317
+ const meta = currentModel?._meta;
27318
+ const modelMeta = meta && typeof meta === "object" ? meta : void 0;
27319
+ const efforts = Array.isArray(modelMeta?.reasoningEfforts) ? modelMeta.reasoningEfforts : [];
27320
+ const effortChoices = [];
27321
+ for (const entry of efforts) {
27322
+ if (!entry || typeof entry !== "object")
27323
+ continue;
27324
+ const effort = entry;
27325
+ const id = advertisedChoiceId(effort);
27326
+ if (!id)
27327
+ continue;
27328
+ effortChoices.push({
27329
+ id,
27330
+ ...typeof effort.label === "string" ? { name: effort.label } : typeof effort.name === "string" ? { name: effort.name } : {}
27331
+ });
27332
+ }
27333
+ const hasEffortAxis = result.some((axis) => ["thought_level", "effort", "reasoning_effort"].includes(axis.category));
27334
+ if (includeLaunchEffort && effortChoices.length > 0 && !hasEffortAxis) {
27335
+ const currentEffort = typeof modelMeta?.reasoningEffort === "string" ? modelMeta.reasoningEffort : efforts.find((entry) => entry && typeof entry === "object" && entry.default)?.value;
27336
+ result.push({
27337
+ id: GROK_LAUNCH_EFFORT_AXIS_ID,
27338
+ category: "reasoning_effort",
27339
+ ...typeof currentEffort === "string" ? { currentValue: currentEffort } : {},
27340
+ options: effortChoices
27341
+ });
27342
+ }
27343
+ return result;
27344
+ }
27345
+ function filterAllowedModelConfigOptions(options) {
27346
+ return options.filter((option) => isAllowedAgentModelConfigCategory(option.category, option.id));
27347
+ }
27348
+ var PROVIDER_CREDENTIAL_ENV_HINTS = {
27349
+ openai: ["OPENAI_API_KEY", "OPENAI_COMPAT_API_KEY"],
27350
+ openrouter: ["OPENROUTER_API_KEY"],
27351
+ anthropic: ["ANTHROPIC_API_KEY"],
27352
+ google: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
27353
+ groq: ["GROQ_API_KEY"],
27354
+ mistral: ["MISTRAL_API_KEY"],
27355
+ deepseek: ["DEEPSEEK_API_KEY"],
27356
+ xai: ["XAI_API_KEY"],
27357
+ cohere: ["COHERE_API_KEY"],
27358
+ together: ["TOGETHER_API_KEY"],
27359
+ fireworks: ["FIREWORKS_API_KEY"]
27360
+ };
27361
+ function credentialedProviders(env) {
27362
+ const held = /* @__PURE__ */ new Set();
27363
+ for (const [provider, names] of Object.entries(PROVIDER_CREDENTIAL_ENV_HINTS)) {
27364
+ if (names.some((name) => Boolean(env[name]?.trim())))
27365
+ held.add(provider);
27366
+ }
27367
+ for (const provider of credentialedPiCustomProviders(env))
27368
+ held.add(provider);
27369
+ return held;
27370
+ }
27371
+ function credentialedPiCustomProviders(env) {
27372
+ const agentDir = env.PI_CODING_AGENT_DIR?.trim() ? resolve9(env.PI_CODING_AGENT_DIR) : env.HOME?.trim() ? resolve9(env.HOME, ".pi/agent") : void 0;
27373
+ const held = /* @__PURE__ */ new Set();
27374
+ if (!agentDir)
27375
+ return held;
27376
+ const path = resolve9(agentDir, "models.json");
27377
+ try {
27378
+ const stats = lstatSync(path);
27379
+ if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
27380
+ return held;
27381
+ }
27382
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
27383
+ const providers = parsed.providers;
27384
+ const remember = (name, config) => {
27385
+ if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
27386
+ return;
27387
+ const apiKey = config.apiKey;
27388
+ if (typeof apiKey === "string" && apiKey.trim())
27389
+ held.add(name.trim());
27390
+ };
27391
+ if (Array.isArray(providers)) {
27392
+ for (const provider of providers) {
27393
+ const record6 = provider;
27394
+ remember(record6?.name ?? record6?.id, record6);
27395
+ }
27396
+ } else if (providers && typeof providers === "object") {
27397
+ for (const [name, config] of Object.entries(providers)) {
27398
+ remember(name, config);
27399
+ }
27400
+ }
27401
+ } catch {
27402
+ }
27403
+ return held;
27404
+ }
27405
+ function filterModelOptionsByCredentials(options, env) {
27406
+ const held = credentialedProviders(env);
27407
+ return options.map((option) => {
27408
+ if (option.category !== "model")
27409
+ return option;
27410
+ return {
27411
+ ...option,
27412
+ options: option.options.filter((choice) => {
27413
+ const slash = choice.id.indexOf("/");
27414
+ if (slash < 0)
27415
+ return true;
27416
+ return held.has(choice.id.slice(0, slash));
27417
+ })
27418
+ };
27419
+ });
27420
+ }
27421
+ var DisallowedModelConfigOptionError = class extends Error {
27422
+ constructor(configId) {
27423
+ super(`model config option "${configId}" is not in the allow-listed catalog`);
27424
+ this.name = "DisallowedModelConfigOptionError";
27425
+ }
27426
+ };
27427
+ function supportsFastMode(options) {
27428
+ const axis = options.find((option) => option.id === "fast-mode" && option.category === "model_config");
27429
+ return Boolean(axis?.options.some((choice) => choice.id === "on") && axis.options.some((choice) => choice.id === "off"));
27430
+ }
27431
+ var ModelSelectionUnavailableError = class extends Error {
27432
+ label;
27433
+ value;
27434
+ reason;
27435
+ guidance;
27436
+ constructor(input) {
27437
+ const recovery = input.guidance ? ` ${input.guidance}` : " Choose one of the values in the live harness catalog.";
27438
+ super(`${input.label} "${input.value}" is unavailable.${recovery}`);
27439
+ this.name = "ModelSelectionUnavailableError";
27440
+ this.label = input.label;
27441
+ this.value = input.value;
27442
+ this.reason = input.reason;
27443
+ this.guidance = input.guidance;
27444
+ }
27445
+ };
27446
+ function withEffectiveCurrentValues(options, selection) {
27447
+ if (!selection || !selection.model && !selection.effort)
27448
+ return options;
27449
+ return options.map((option) => {
27450
+ const target = modelSelectionTargets(selection).find((entry) => entry.categories.includes(option.category));
27451
+ if (!target?.value || option.currentValue === target.value)
27452
+ return option;
27453
+ return { ...option, currentValue: target.value };
27454
+ });
27455
+ }
27456
+ function modelSelectionTargets(selection) {
27457
+ return [
27458
+ { categories: ["model"], label: "model", value: selection.model },
27459
+ {
27460
+ categories: ["thought_level", "effort", "reasoning_effort"],
27461
+ label: "effort",
27462
+ value: selection.effort
27463
+ }
27464
+ ];
27465
+ }
27466
+ function assertModelConfigAxisAllowed(configId, advertisedOptions) {
27467
+ const axis = advertisedOptions.find((option) => option.id === configId);
27468
+ if (!axis || !isAllowedAgentModelConfigCategory(axis.category, axis.id)) {
27469
+ throw new DisallowedModelConfigOptionError(configId);
27470
+ }
27471
+ }
27472
+ async function applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, advertisedOptions, selection) {
27473
+ let currentOptions = advertisedOptions;
27474
+ const appliedSelection = {};
27475
+ let modelWasSubstituted = false;
27476
+ for (const target of modelSelectionTargets(selection)) {
27477
+ if (!target.value)
27478
+ continue;
27479
+ const axis = currentOptions.find((option) => target.categories.includes(option.category));
27480
+ if (!axis)
27481
+ continue;
27482
+ assertModelConfigAxisAllowed(axis.id, currentOptions);
27483
+ let value = target.value;
27484
+ if (!axis.options.some((choice) => choice.id === value)) {
27485
+ const fallback = target.label === "model" ? resolveModelFamilyFallback(axis.options, value) : void 0;
27486
+ if (fallback) {
27487
+ value = fallback.id;
27488
+ modelWasSubstituted = true;
27489
+ } else if (target.label === "effort" && modelWasSubstituted) {
27490
+ continue;
27491
+ } else {
27492
+ throw new ModelSelectionUnavailableError({
27493
+ label: target.label,
27494
+ value: target.value,
27495
+ reason: "not-advertised"
27496
+ });
27497
+ }
27498
+ }
27499
+ try {
27500
+ if (axis.id === GROK_SESSION_MODEL_AXIS_ID) {
27501
+ if (!client.setModel)
27502
+ throw new Error("ACP client does not support session/set_model");
27503
+ await client.setModel(sessionId, value);
27504
+ } else if (axis.id === GROK_LAUNCH_EFFORT_AXIS_ID) {
27505
+ if (axis.currentValue !== value) {
27506
+ throw new Error(`Grok started with reasoning effort "${axis.currentValue ?? "unknown"}", not "${value}"`);
27507
+ }
27508
+ } else {
27509
+ const updated = await client.setConfigOption(sessionId, axis.id, value);
27510
+ const refreshed = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(updated, target.label === "model" ? value : selection.model));
27511
+ if (refreshed.length > 0)
27512
+ currentOptions = refreshed;
27513
+ }
27514
+ } catch (error) {
27515
+ const message = error instanceof Error ? error.message : String(error);
27516
+ if (isTransientProviderText(message) || isAuthShapedFault(message)) {
27517
+ throw error instanceof Error ? error : new Error(message);
27518
+ }
27519
+ throw new ModelSelectionUnavailableError({
27520
+ label: target.label,
27521
+ value: target.value,
27522
+ reason: "provider-refused",
27523
+ guidance: message
27524
+ });
27525
+ }
27526
+ if (target.label === "model")
27527
+ appliedSelection.model = value;
27528
+ else
27529
+ appliedSelection.effort = value;
27530
+ }
27531
+ if (selection.fastMode && !supportsFastMode(currentOptions)) {
27532
+ throw new Error("Fast mode is unavailable for the selected model and harness");
27533
+ }
27534
+ if (supportsFastMode(currentOptions)) {
27535
+ await client.setConfigOption(sessionId, "fast-mode", selection.fastMode ? "on" : "off");
27536
+ }
27537
+ return { options: currentOptions, appliedSelection };
27538
+ }
27539
+ async function applyAgentModelSelection(client, sessionId, advertisedOptions, selection) {
27540
+ return applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, advertisedOptions, selection);
27541
+ }
27542
+
27543
+ // apps/body/dist/model-catalog.js
27544
+ import { mkdtemp, rm as rm3 } from "node:fs/promises";
27545
+ import { tmpdir } from "node:os";
27546
+ import { resolve as resolve10 } from "node:path";
27547
+
27548
+ // apps/body/dist/acp.js
27549
+ init_adapter_install_lock();
27550
+ import { spawn as spawn10 } from "node:child_process";
27551
+ import { EventEmitter } from "node:events";
27552
+
27553
+ // apps/body/dist/harness-capabilities.js
27554
+ init_cursor_acp_bridge();
27555
+ var PROFILES = [
27556
+ {
27557
+ match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
27558
+ profile: {
27559
+ enforcement: "sandboxed",
27560
+ note: "codex-acp asks for every command/file change and enforces an offline read-only OS sandbox in read-only mode; under bubblewrap a Room runs it in agent-full-access and bwrap holds the filesystem rule"
27561
+ }
27562
+ },
27563
+ {
27564
+ match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i,
27565
+ profile: {
27566
+ enforcement: "permission-callback",
27567
+ note: "claude-agent-acp asks for every tool call; it advertises no read-only mode, so the daemon callback is the only boundary"
27568
+ }
27569
+ },
27570
+ {
27571
+ match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
27572
+ profile: {
27573
+ enforcement: "none",
27574
+ note: "pi-acp never sends session/request_permission for a tool call: pi executes reads, writes, edits, and shell commands before the daemon sees them, and exposes no sandbox or permission flag to pass at spawn"
27575
+ }
27576
+ },
27577
+ {
27578
+ match: /(^|[/\\])grok(\.[a-z]+)?$/i,
27579
+ profile: {
27580
+ enforcement: "permission-callback",
27581
+ note: "grok sends standard session/request_permission requests for mutating tools in its default ask mode; it advertises no read-only ACP mode, so the daemon callback is the only boundary unless the OS sandbox wraps it"
27582
+ }
27583
+ },
27584
+ {
27585
+ match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
27586
+ profile: {
27587
+ enforcement: "permission-callback",
27588
+ note: "buzz-agent sends session/request_permission for mutating tools"
27589
+ }
27590
+ },
27591
+ {
27592
+ match: CURSOR_HARNESS_COMMAND,
27593
+ profile: {
27594
+ enforcement: "none",
27595
+ note: "cursor-acp-bridge drives cursor-agent with --force --approve-mcps in non-interactive stream-json mode, so cursor-agent never sends session/request_permission; Beeline already sandboxes the child"
27596
+ }
27597
+ }
27598
+ ];
27599
+ function harnessEnforcement(agentCommand) {
27600
+ if (!agentCommand)
27601
+ return { enforcement: "unknown", note: "no ACP command configured" };
27602
+ for (const { match, profile } of PROFILES) {
27603
+ if (match.test(agentCommand))
27604
+ return profile;
27605
+ }
27606
+ return {
27607
+ enforcement: "unknown",
27608
+ note: `'${agentCommand}' has not been verified to send session/request_permission for mutating tools`
27609
+ };
27610
+ }
27611
+ function harnessHonorsSessionSystemPrompt(agentCommand) {
27612
+ return Boolean(agentCommand && /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand));
27613
+ }
27614
+ var GROK_WARM_SESSION_IDLE_MS = 30 * 6e4;
27615
+ function cornerAutonomyModeCandidates(agentCommand) {
27616
+ if (agentCommand && /(^|[/\\])codex-acp(\.[a-z]+)?$/i.test(agentCommand)) {
27617
+ return ["agent-full-access"];
27618
+ }
27619
+ if (agentCommand && /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand)) {
27620
+ return ["bypassPermissions"];
27621
+ }
27622
+ if (agentCommand && /(^|[/\\])grok(\.[a-z]+)?$/i.test(agentCommand))
27623
+ return [];
27624
+ if (agentCommand && /(^|[/\\])pi-acp(\.[a-z]+)?$/i.test(agentCommand))
27625
+ return [];
27626
+ return ["agent", "edit", "code"];
27627
+ }
27628
+ function roomModeCandidates(agentCommand, options = {}) {
27629
+ if (options.osSandbox && agentCommand && /(^|[/\\])codex-acp(\.[a-z]+)?$/i.test(agentCommand)) {
27630
+ return ["agent-full-access"];
27631
+ }
27632
+ return ["read-only", "readonly"];
27633
+ }
27634
+ function harnessDeclaresShellExecuteKind(agentCommand) {
27635
+ return Boolean(agentCommand && (/(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i.test(agentCommand) || /(^|[/\\])grok(\.[a-z]+)?$/i.test(agentCommand)));
27636
+ }
27637
+ function roomShellCapability(agentCommand, options = {}) {
27638
+ const { enforcement } = harnessEnforcement(agentCommand);
27639
+ if (enforcement === "sandboxed" || enforcement === "none")
27640
+ return "runs";
27641
+ if (enforcement === "unknown")
27642
+ return "unknown";
27643
+ if (!harnessDeclaresShellExecuteKind(agentCommand))
27644
+ return "unknown";
27645
+ return options.osSandbox ? "runs" : "refused";
27646
+ }
27647
+
27648
+ // apps/body/dist/harness-tool-scope.js
27649
+ init_cursor_acp_bridge();
27650
+ var CLAUDE_TOOL_SCOPE_SETTINGS = { disableClaudeAiConnectors: true };
27651
+ var CLAUDE_PROFILE = {
27652
+ // `settingSources: ['user']` admits the sanitized user MCP copy
27653
+ // while rejecting repository/local/plugin MCP. `strictMcpConfig` cannot be
27654
+ // used because it would reject the user copy too. Account-bound claude.ai
27655
+ // cloud connectors remain off independently.
27656
+ enforcement: "config-isolated",
27657
+ note: "claude-agent-acp forwards _meta.claudeCode.options to the Claude Agent SDK; user-only settingSources loads MCP from the isolated CLAUDE_CONFIG_DIR without repository/local settings, while disableClaudeAiConnectors keeps account-bound connectors off",
27658
+ sessionMeta: {
27659
+ claudeCode: {
27660
+ options: {
27661
+ // Only the sanitized user config in the isolated CLAUDE_CONFIG_DIR;
27662
+ // never a repository's .mcp.json, local settings, or plugins.
27663
+ settingSources: ["user"],
27664
+ // Account-bound claude.ai cloud connectors are not fetched at all.
27665
+ settings: CLAUDE_TOOL_SCOPE_SETTINGS
27666
+ }
27667
+ }
27668
+ },
27669
+ metaSystemPrompt: true
27670
+ };
27671
+ var PROFILES2 = [
27672
+ { match: /(^|[/\\])claude-(agent|code)-acp(\.[a-z]+)?$/i, profile: CLAUDE_PROFILE },
27673
+ {
27674
+ match: /(^|[/\\])codex-acp(\.[a-z]+)?$/i,
27675
+ profile: {
27676
+ enforcement: "config-isolated",
27677
+ note: "codex-acp merges the session's MCP servers into $CODEX_HOME/config.toml's own [mcp_servers] instead of replacing them, so only an isolated CODEX_HOME scopes the session; the ChatGPT account's codex_apps connectors survive either way"
27678
+ }
27679
+ },
27680
+ {
27681
+ match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
27682
+ profile: {
27683
+ enforcement: "config-isolated",
27684
+ note: "pi-acp 0.0.33 still stores session/new mcpServers and never reads them; pi 0.85.1 itself has no MCP client, while optional pi-mcp-adapter reads $PI_CODING_AGENT_DIR/mcp.json and isolated homes exclude the settings.json that would load it"
27685
+ }
27686
+ },
27687
+ {
27688
+ match: /(^|[/\\])grok(\.[a-z]+)?$/i,
27689
+ profile: {
27690
+ enforcement: "config-isolated",
27691
+ note: "grok loads the operator's own ~/.grok MCP servers even when session/new passes an empty mcpServers list (measured live), so only an isolated GROK_HOME scopes the session; no account-bound connector surface was found"
27692
+ }
27693
+ },
27694
+ {
27695
+ match: /(^|[/\\])buzz-agent(\.[a-z]+)?$/i,
27696
+ profile: {
27697
+ enforcement: "allowlisted",
27698
+ note: "buzz-agent mounts only the MCP servers the daemon passes; it has no operator-global tool config"
27699
+ }
27700
+ },
27701
+ {
27702
+ match: CURSOR_HARNESS_COMMAND,
27703
+ profile: {
27704
+ enforcement: "config-isolated",
27705
+ note: "cursor-acp-bridge writes session/new mcpServers into the isolated CURSOR_HOME mcp.json and the isolated $HOME/.cursor/mcp.json cursor-agent loads; it never writes the operator ~/.cursor"
27706
+ }
27707
+ }
27708
+ ];
27709
+ function sessionToolScopeMeta(agentCommand) {
27710
+ const meta = matchProfile(agentCommand)?.sessionMeta;
27711
+ return meta ? JSON.parse(JSON.stringify(meta)) : void 0;
27712
+ }
27713
+ function harnessReadsMetaSystemPrompt(agentCommand) {
27714
+ return matchProfile(agentCommand)?.metaSystemPrompt === true;
27715
+ }
27716
+ function matchProfile(agentCommand) {
27717
+ if (!agentCommand)
27718
+ return void 0;
27719
+ for (const { match, profile } of PROFILES2) {
27720
+ if (match.test(agentCommand))
27721
+ return profile;
27722
+ }
27723
+ return void 0;
27724
+ }
27725
+
27726
+ // apps/body/dist/acp.js
27727
+ var STDERR_TAIL_MAX_CHARS2 = 2e3;
27728
+ function braceDelta(line) {
27729
+ let delta = 0;
27730
+ for (const char of line) {
27731
+ if (char === "{")
27732
+ delta += 1;
27733
+ else if (char === "}")
27734
+ delta -= 1;
27735
+ }
27736
+ return delta;
27737
+ }
27738
+ function meaningfulHarnessStderr(tail) {
27739
+ const lines = tail.split(/\r?\n/);
27740
+ const kept = [];
27741
+ for (let index = 0; index < lines.length; index += 1) {
27742
+ const line = lines[index];
27743
+ if (!/error handling notification/i.test(line)) {
27744
+ kept.push(line);
27745
+ continue;
27746
+ }
27747
+ const block2 = [line];
27748
+ let depth = braceDelta(line);
27749
+ if (depth === 0 && lines[index + 1]?.trimStart().startsWith("{")) {
27750
+ index += 1;
27751
+ block2.push(lines[index]);
27752
+ depth = braceDelta(lines[index]);
27753
+ }
27754
+ while (depth > 0 && index + 1 < lines.length) {
27755
+ index += 1;
27756
+ block2.push(lines[index]);
27757
+ depth += braceDelta(lines[index]);
27758
+ }
27759
+ if (!/notifications\/initialized/.test(block2.join("\n")))
27760
+ kept.push(...block2);
27761
+ }
27762
+ return kept.join("\n").trim();
27763
+ }
27764
+ function flattenHarnessCause(tail) {
27765
+ return meaningfulHarnessStderr(tail).replace(/\s+/g, " ").trim();
27089
27766
  }
27090
27767
  var AcpRequestTimeoutError = class extends Error {
27091
27768
  method;
@@ -27972,9 +28649,17 @@ function filterAgentModelCatalog(agent, raw, agentEnv) {
27972
28649
  const allowed = filterAllowedModelConfigOptions(raw).filter((axis) => axis.id !== "fast-mode" || agent.kind === "codex");
27973
28650
  return agent.kind === "goose" || agent.kind === "opencode" ? allowed : filterModelOptionsByCredentials(allowed, agentEnv);
27974
28651
  }
27975
- async function withAgentModelCatalog(agent, agentEnv, selection, inspect, limits = {}) {
27976
- const deadline = limits.timeoutMs === void 0 ? void 0 : Date.now() + limits.timeoutMs;
27977
- const remaining = () => deadline === void 0 ? void 0 : Math.max(1, deadline - Date.now());
28652
+ function withDeadline(work, ms, what) {
28653
+ let timer;
28654
+ const expired = new Promise((_, reject) => {
28655
+ timer = setTimeout(() => reject(new Error(`${what} timed out after ${ms}ms`)), ms);
28656
+ timer.unref?.();
28657
+ });
28658
+ return Promise.race([work, expired]).finally(() => clearTimeout(timer));
28659
+ }
28660
+ async function withAgentModelCatalog(agent, agentEnv, selection, inspect, limits = {}) {
28661
+ const deadline = limits.timeoutMs === void 0 ? void 0 : Date.now() + limits.timeoutMs;
28662
+ const remaining = () => deadline === void 0 ? void 0 : Math.max(1, deadline - Date.now());
27978
28663
  const scratchCwd = await mkdtemp(resolve10(tmpdir(), "beeline-pair-model-check-"));
27979
28664
  const probeEnv = modelCatalogProbeEnvironment(agent, agentEnv, scratchCwd);
27980
28665
  const client = new AcpClient({
@@ -27998,7 +28683,9 @@ async function withAgentModelCatalog(agent, agentEnv, selection, inspect, limits
27998
28683
  });
27999
28684
  const raw = parseAdvertisedConfigOptions(sessionRaw, selection?.model, isGrokAgentCommand(agent));
28000
28685
  const catalog = filterAgentModelCatalog(agent, raw, probeEnv);
28001
- return await inspect({ client, sessionId, raw, catalog });
28686
+ const inspected = inspect({ client, sessionId, raw, catalog });
28687
+ const inspectDeadline = remaining();
28688
+ return inspectDeadline === void 0 ? await inspected : await withDeadline(inspected, inspectDeadline, "model catalog probe");
28002
28689
  } finally {
28003
28690
  await client.stop().catch(() => void 0);
28004
28691
  await rm3(scratchCwd, { recursive: true, force: true }).catch(() => void 0);
@@ -28024,7 +28711,7 @@ async function filterModelChoicesByLiveValidation(client, sessionId, catalog, pr
28024
28711
  });
28025
28712
  available.push(choice);
28026
28713
  if (choice.id === preferred)
28027
- preferredCatalog = updated;
28714
+ preferredCatalog = updated.options;
28028
28715
  } catch {
28029
28716
  }
28030
28717
  }
@@ -28034,7 +28721,7 @@ async function filterModelChoicesByLiveValidation(client, sessionId, catalog, pr
28034
28721
  async function validateAgentModelSelection(agent, agentEnv, selection) {
28035
28722
  return withAgentModelCatalog(agent, agentEnv, selection, async ({ client, sessionId, raw, catalog }) => {
28036
28723
  const applied = await applyAgentModelSelectionWithUpdatedCatalog(client, sessionId, catalog, selection);
28037
- return { raw, catalog: applied };
28724
+ return { raw, catalog: applied.options };
28038
28725
  });
28039
28726
  }
28040
28727
 
@@ -28064,6 +28751,9 @@ function modelUnavailableState(selection, error) {
28064
28751
  }
28065
28752
 
28066
28753
  // apps/body/dist/runtime-model-validation.js
28754
+ function resolvePreflightModelSelection(local, server) {
28755
+ return server ?? local;
28756
+ }
28067
28757
  async function revalidateRuntimeModelSelection(agent, agentEnv, selection, validate = validateAgentModelSelection, refreshAdapter) {
28068
28758
  if (!selection.model && !selection.effort)
28069
28759
  return void 0;
@@ -28142,7 +28832,8 @@ async function syncAgentModelCatalog(input) {
28142
28832
  // `fetchAgentModelCatalog` already applied the category allow-list.
28143
28833
  options: effectiveCatalog,
28144
28834
  ...selection ? { selection } : {},
28145
- ...input.startupUnavailable ? { unavailable: input.startupUnavailable } : {}
28835
+ ...input.startupUnavailable ? { unavailable: input.startupUnavailable } : {},
28836
+ ...input.agent.kind ? { harness: input.agent.kind } : {}
28146
28837
  });
28147
28838
  await writeFile6(hashPath, `${hash}
28148
28839
  `, { mode: 384 });
@@ -28439,7 +29130,7 @@ function isHostMcpIdentity(candidate, hostNames = CODE_OWNED_HOST_MCP_NAMES) {
28439
29130
 
28440
29131
  // apps/body/dist/registry-mcp.js
28441
29132
  var REGISTRY_MCP_BROKER_FLAG = "--registry-mcp-broker";
28442
- function record2(value) {
29133
+ function record3(value) {
28443
29134
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
28444
29135
  }
28445
29136
  function safeUrl(value) {
@@ -28535,7 +29226,7 @@ async function jsonResponse(response) {
28535
29226
  if (bytes.byteLength > 256 * 1024)
28536
29227
  throw new Error("provider metadata is too large");
28537
29228
  const parsed = JSON.parse(new TextDecoder().decode(bytes));
28538
- const result = record2(parsed);
29229
+ const result = record3(parsed);
28539
29230
  if (!result)
28540
29231
  throw new Error("provider metadata is invalid");
28541
29232
  return result;
@@ -29109,878 +29800,363 @@ var ConnectorAssignmentLoop = class {
29109
29800
  * to a new generation, and a ceremony latched to the old one must never
29110
29801
  * swallow it. */
29111
29802
  registryCeremonies = /* @__PURE__ */ new Map();
29112
- readVaultFn;
29113
- revokeGrantsFn;
29114
- /** Armed only while this helper owns a live sign-in ceremony. */
29115
- connectWatch;
29116
- started = false;
29117
- stopped = false;
29118
- /** One install at a time per connector; concurrent wakes skip it. */
29119
- inFlight = /* @__PURE__ */ new Set();
29120
- mcp;
29121
- constructor(options) {
29122
- this.agentId = options.agentId;
29123
- this.api = options.api;
29124
- this.log = options.log ?? (() => {
29125
- });
29126
- this.install = options.install ?? installSquire;
29127
- this.installTailscale = options.installTailscale ?? installTailscale;
29128
- this.watchTailscaleSignIn = options.watchTailscaleSignIn ?? watchTailscaleSignIn;
29129
- this.registryHomeDir = options.registryHome ?? process.env.HOME ?? process.cwd();
29130
- this.installRegistry = options.installRegistry ?? installRegistryMcp;
29131
- this.readVaultFn = options.readVault ?? readVault;
29132
- this.revokeGrantsFn = options.revokeGrants ?? revokeGrants;
29133
- }
29134
- start() {
29135
- if (this.stopped || this.started)
29136
- return;
29137
- this.started = true;
29138
- void this.runOnce();
29139
- }
29140
- /** Event-driven drain, also called when the socket reconnects. */
29141
- wake() {
29142
- if (this.stopped)
29143
- return;
29144
- void this.runOnce();
29145
- }
29146
- stop() {
29147
- this.stopped = true;
29148
- this.connectWatch?.();
29149
- this.connectWatch = void 0;
29150
- this.tailscaleWatch?.();
29151
- this.tailscaleWatch = void 0;
29152
- }
29153
- /**
29154
- * Watch the sign-in this helper is holding open. The phone paints
29155
- * `installing` for the whole ceremony and only a drain that reaches
29156
- * Squire's already-connected short-circuit flips the row to `connected`;
29157
- * nothing on the wire announces that the human finished, so the connect
29158
- * process exiting is the signal. Drain on that, and the row settles on the
29159
- * process exit event without waiting for a server read timer.
29160
- */
29161
- watchConnectSignIn() {
29162
- if (this.stopped || this.connectWatch)
29163
- return;
29164
- const claim = squireConnectSession();
29165
- this.connectWatch = claim?.onExit?.(() => {
29166
- this.connectWatch = void 0;
29167
- if (!this.stopped)
29168
- void this.runOnce();
29169
- });
29170
- }
29171
- /** Drain the queue once; every failure is logged, never raised. */
29172
- async runOnce() {
29173
- let assignments;
29174
- try {
29175
- const result = await this.api.execute("getConnectorAssignments", { agentId: this.agentId });
29176
- assignments = result.assignments;
29177
- } catch (error) {
29178
- this.log(`connector assignments unavailable: ${describe(error)}`);
29179
- return;
29180
- }
29181
- for (const assignment of assignments) {
29182
- const key = `${assignment.kind}:${assignment.connectorId}`;
29183
- if (assignment.kind === "uninstall")
29184
- continue;
29185
- if (this.inFlight.has(key))
29186
- continue;
29187
- this.inFlight.add(key);
29188
- void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe(error)}`)).finally(() => this.inFlight.delete(key));
29189
- }
29190
- }
29191
- squire() {
29192
- this.mcp ??= defaultSquireMcpClient({ agentId: this.agentId, roomId: "connector" });
29193
- return this.mcp;
29194
- }
29195
- async handle(assignment) {
29196
- const pairingGeneration = assignment.kind === "install" || assignment.kind === "uninstall" ? assignment.pairingGeneration : void 0;
29197
- if (assignment.kind === "install") {
29198
- if (assignment.connectorType?.startsWith("google-")) {
29199
- await this.api.execute("postConnectorStatus", {
29200
- agentId: this.agentId,
29201
- connectorId: assignment.connectorId,
29202
- steps: [{
29203
- label: "Connect app",
29204
- status: "failed",
29205
- reason: "Reconnect through Connect an app"
29206
- }],
29207
- errorMessage: "Reconnect through Connect an app",
29208
- ...pairingGeneration !== void 0 ? { pairingGeneration } : {}
29209
- });
29210
- } else if (assignment.connectorType === "registry-mcp") {
29211
- await this.runRegistryMcpInstall(assignment);
29212
- } else if (assignment.connectorType === "tailscale") {
29213
- await this.runTailscaleInstall(assignment.connectorId, pairingGeneration);
29214
- } else {
29215
- await this.runInstall(assignment.connectorId, pairingGeneration);
29216
- }
29217
- } else if (assignment.kind === "sync" && assignment.connectorType === "tailscale") {
29218
- await this.runTailscaleInstall(assignment.connectorId);
29219
- } else if (assignment.kind === "sync") {
29220
- await this.runSync();
29221
- } else if (assignment.kind === "refresh-google-grant") {
29222
- this.log("retired Google grant assignment ignored; reconnect through Connect an app");
29223
- } else if (assignment.kind === "revoke-grants")
29224
- await this.runRevoke(assignment.connectorId, assignment.reference);
29225
- }
29226
- ceremonyKey(assignment) {
29227
- return `${assignment.connectorId}:${assignment.pairingGeneration ?? 1}`;
29228
- }
29229
- async runRegistryMcpInstall(assignment) {
29230
- const generation = assignment.pairingGeneration !== void 0 ? { pairingGeneration: assignment.pairingGeneration } : {};
29231
- const ceremonyKey = this.ceremonyKey(assignment);
29232
- const result = await this.installRegistry({
29233
- api: this.api,
29234
- agentId: this.agentId,
29235
- assignment,
29236
- home: this.registryHomeDir
29237
- });
29238
- const stopWatch = () => {
29239
- };
29240
- if (result.status === "connected") {
29241
- stopWatch();
29242
- this.registryCeremonies.delete(ceremonyKey);
29243
- await this.api.execute("installConnector", {
29244
- agentId: this.agentId,
29245
- connectorId: assignment.connectorId,
29246
- ...generation
29247
- });
29248
- return;
29249
- }
29250
- if (result.status === "installing") {
29251
- const ceremony = this.registryCeremonies.get(ceremonyKey);
29252
- if (!ceremony || ceremony.attemptId !== result.attemptId) {
29253
- this.registryCeremonies.set(ceremonyKey, {
29254
- attemptId: result.attemptId,
29255
- endsAt: result.attemptExpiresAt
29256
- });
29257
- } else if (ceremony.expired) {
29258
- return;
29259
- } else if (Date.now() >= ceremony.endsAt) {
29260
- stopWatch();
29261
- this.registryCeremonies.set(ceremonyKey, { ...ceremony, expired: true });
29262
- await this.api.execute("postConnectorStatus", {
29263
- agentId: this.agentId,
29264
- connectorId: assignment.connectorId,
29265
- steps: [
29266
- { label: "Connect provider account", status: "failed", reason: CEREMONY_EXPIRED }
29267
- ],
29268
- signIn: null,
29269
- errorMessage: CEREMONY_EXPIRED,
29270
- ...generation
29271
- });
29272
- return;
29273
- }
29274
- } else {
29275
- this.registryCeremonies.delete(ceremonyKey);
29276
- }
29277
- await this.api.execute("postConnectorStatus", {
29278
- agentId: this.agentId,
29279
- connectorId: assignment.connectorId,
29280
- steps: result.steps,
29281
- ...result.status === "installing" ? {
29282
- signIn: {
29283
- method: "oauth",
29284
- url: result.authorizationUrl,
29285
- attemptId: result.attemptId
29286
- }
29287
- } : { signIn: null, errorMessage: result.errorMessage },
29288
- ...generation
29289
- });
29290
- }
29291
- /** Install Tailscale and publish its browser login URL until the tailnet is connected. */
29292
- async runTailscaleInstall(connectorId, pairingGeneration) {
29293
- const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
29294
- const report = async (steps2) => {
29295
- try {
29296
- await this.api.execute("postConnectorStatus", {
29297
- agentId: this.agentId,
29298
- connectorId,
29299
- steps: steps2,
29300
- ...generation
29301
- });
29302
- } catch (error) {
29303
- this.log(`step report failed: ${describe(error)}`);
29304
- }
29305
- };
29306
- const existing = await this.connectorRow(connectorId);
29307
- const result = await this.installTailscale({
29308
- onProgress: report,
29309
- ...existing?.signIn ? { signIn: existing.signIn } : {}
29310
- });
29311
- if (result.status === "connected") {
29312
- this.tailscaleWatch?.();
29313
- this.tailscaleWatch = void 0;
29314
- await this.api.execute("installConnector", {
29315
- agentId: this.agentId,
29316
- connectorId,
29317
- ...result.signedInAs ? { signedInAs: result.signedInAs } : {},
29318
- ...generation
29319
- });
29320
- return;
29321
- }
29322
- await this.api.execute("postConnectorStatus", {
29323
- agentId: this.agentId,
29324
- connectorId,
29325
- steps: result.steps,
29326
- signIn: result.status === "installing" ? result.signIn : null,
29327
- ...result.status === "error" ? { errorMessage: result.errorMessage } : {},
29328
- ...generation
29329
- });
29330
- if (result.status === "installing" && !this.tailscaleWatch)
29331
- this.tailscaleWatch = this.watchTailscaleSignIn(() => {
29332
- this.tailscaleWatch = void 0;
29333
- if (!this.stopped)
29334
- this.wake();
29335
- });
29336
- }
29337
- /** Install Trusty Squire, reporting every step as it settles. */
29338
- async runInstall(connectorId, pairingGeneration) {
29339
- const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
29340
- const claim = squireConnectSession();
29341
- const spent = claim ? Date.now() - claim.claimedAt >= CONNECT_TIMEOUT_MS : false;
29342
- if (claim && !spent && isProcessAlive(claim.pid)) {
29343
- if (!await this.rearmedByHuman(connectorId)) {
29344
- this.log(`trusty-squire connect still waiting for sign-in (pid ${String(claim.pid)}); leaving it alone`);
29345
- this.watchConnectSignIn();
29346
- return;
29347
- }
29348
- this.log("trusty-squire re-pair requested; superseding the connect holding the browser");
29349
- } else if (spent && (await this.connectorRow(connectorId))?.signIn) {
29350
- releaseSquireConnectSession((message) => this.log(`[trusty-squire] ${message}`));
29351
- await this.api.execute("postConnectorStatus", {
29352
- agentId: this.agentId,
29353
- connectorId,
29354
- steps: [{ label: "waiting for sign-in", status: "failed", reason: CEREMONY_EXPIRED }],
29355
- signIn: null,
29356
- errorMessage: CEREMONY_EXPIRED,
29357
- ...generation
29358
- });
29359
- return;
29360
- }
29361
- const report = async (steps2) => {
29362
- try {
29363
- await this.api.execute("postConnectorStatus", {
29364
- agentId: this.agentId,
29365
- connectorId,
29366
- steps: steps2,
29367
- ...generation
29368
- });
29369
- } catch (error) {
29370
- this.log(`step report failed: ${describe(error)}`);
29371
- }
29372
- };
29373
- const result = await this.install({
29374
- workspaceId: this.agentId,
29375
- mcp: this.squire(),
29376
- onProgress: report,
29377
- log: (message) => this.log(`[trusty-squire] ${message}`)
29378
- });
29379
- if (result.status === "error") {
29380
- await this.api.execute("postConnectorStatus", {
29381
- agentId: this.agentId,
29382
- connectorId,
29383
- steps: result.steps,
29384
- signIn: null,
29385
- errorMessage: result.errorMessage,
29386
- ...generation
29387
- });
29388
- return;
29389
- }
29390
- if (result.status === "connected") {
29391
- await this.api.execute("installConnector", {
29392
- agentId: this.agentId,
29393
- connectorId,
29394
- ...result.squireVersion ? { squireVersion: result.squireVersion } : {},
29395
- ...generation
29396
- });
29397
- await this.reportVault(connectorId);
29398
- return;
29399
- }
29400
- await this.api.execute("postConnectorStatus", {
29401
- agentId: this.agentId,
29402
- connectorId,
29403
- steps: result.steps,
29404
- signIn: result.signIn ?? null,
29405
- ...result.squireVersion ? { squireVersion: result.squireVersion } : {},
29406
- ...generation
29407
- });
29408
- this.watchConnectSignIn();
29409
- }
29410
- /** This connector's own row, or undefined when the server cannot answer. */
29411
- async connectorRow(connectorId) {
29412
- try {
29413
- const status = await this.api.execute("getConnectorStatus", {
29414
- agentId: this.agentId,
29415
- connectorId
29416
- });
29417
- return status.connectorId === connectorId ? status : void 0;
29418
- } catch (error) {
29419
- this.log(`connector status unavailable: ${describe(error)}`);
29420
- return void 0;
29421
- }
29422
- }
29423
- /**
29424
- * True when a human asked for this connector again while a connect of ours
29425
- * still holds the browser. `pairConnector` re-arms the row to its default
29426
- * all-pending steps, so a row whose every step is still pending is a fresh
29427
- * request; the row carrying the ceremony this helper published has settled
29428
- * ones. An unreadable row is not evidence of a retry.
29429
- */
29430
- async rearmedByHuman(connectorId) {
29431
- const status = await this.connectorRow(connectorId);
29432
- if (!status)
29433
- return false;
29434
- return status.steps.length > 0 && status.steps.every((step3) => step3.status === "pending");
29435
- }
29436
- /** One vault report covers every live trusty-squire connector on this helper. */
29437
- async runSync() {
29438
- await this.reportVault();
29439
- }
29440
- async runRevoke(connectorId, reference) {
29441
- const outcome = await this.revokeGrantsFn(this.squire(), reference);
29442
- this.log(`revoked ${outcome.revoked} grant(s) on ${reference}` + (outcome.failed ? `, ${outcome.failed} failed` : ""));
29443
- if (outcome.failed)
29444
- return;
29445
- await this.api.execute("revokeConnectionGrants", {
29446
- agentId: this.agentId,
29447
- ref: reference
29448
- });
29449
- void connectorId;
29450
- }
29451
- async reportVault(_connectorId) {
29452
- const connections = await this.readVaultFn(this.squire());
29453
- await this.api.execute("postConnectorVault", { agentId: this.agentId, connections });
29454
- }
29455
- };
29456
- function describe(error) {
29457
- return error instanceof Error ? error.message : String(error);
29458
- }
29459
-
29460
- // apps/body/dist/institutional-memory-shadow-worker.js
29461
- import { mkdtemp as mkdtemp2, rm as rm5 } from "node:fs/promises";
29462
- import { tmpdir as tmpdir3 } from "node:os";
29463
- import { resolve as resolve12 } from "node:path";
29464
-
29465
- // packages/api-contract/dist/daemon-operations.js
29466
- function isAgentCommand(value) {
29467
- if (!value || typeof value !== "object")
29468
- return false;
29469
- const c2 = value;
29470
- if (![
29471
- "id",
29472
- "roomId",
29473
- "agentId",
29474
- "sourceMessageId",
29475
- "turnRequestId",
29476
- "rootCommandId",
29477
- "rootSourceMessageId",
29478
- "reason"
29479
- ].every((key) => typeof c2[key] === "string" && c2[key].length > 0))
29480
- return false;
29481
- if (!["input", "resume", "stop", "restart"].includes(String(c2.action)) || !Number.isInteger(c2.agentDepth) || Number(c2.agentDepth) < 0 || Number(c2.agentDepth) > 3)
29482
- return false;
29483
- const source = c2.source;
29484
- return Boolean(source && typeof source.id === "string" && typeof source.authorId === "string" && typeof source.body === "string" && typeof source.createdAt === "number" && Array.isArray(source.attachments));
29485
- }
29486
-
29487
- // packages/api-contract/dist/artifacts.js
29488
- var ARTIFACT_EXTENSIONS_BY_MIME = {
29489
- "text/html": [".html", ".htm"],
29490
- "image/svg+xml": [".svg"],
29491
- "application/pdf": [".pdf"],
29492
- "text/markdown": [".md"],
29493
- "image/png": [".png"],
29494
- "image/jpeg": [".jpg", ".jpeg"],
29495
- "image/gif": [".gif"],
29496
- "image/webp": [".webp"],
29497
- "text/plain": [".txt", ".log"],
29498
- "application/json": [".json"],
29499
- "text/csv": [".csv"],
29500
- "application/zip": [".zip"],
29501
- "application/octet-stream": []
29502
- };
29503
- var ARTIFACT_MIME_BY_EXTENSION = Object.fromEntries(Object.entries(ARTIFACT_EXTENSIONS_BY_MIME).flatMap(([mime, extensions]) => extensions.map((extension2) => [extension2, mime])));
29504
- var ARTIFACT_MAXIMUM_BYTES = 25 * 1024 * 1024;
29505
-
29506
- // packages/api-contract/dist/daemon.js
29507
- init_agent_access();
29508
-
29509
- // packages/api-contract/dist/system-events.js
29510
- var SERVER_EVENT_KINDS = [
29511
- "joined",
29512
- "schedule-ran",
29513
- "corner-opened",
29514
- "check-passed",
29515
- "check-failed",
29516
- "merged",
29517
- "grant-decided",
29518
- "connector-offer-decided",
29519
- "turn-cancelled",
29520
- "choice-answered",
29521
- "choice-skipped",
29522
- "poll-closed"
29523
- ];
29524
-
29525
- // packages/api-contract/dist/turn-silence.js
29526
- var HICCUP_BACKOFF_MS = [0, 5e3, 2e4];
29527
- var TURN_SILENCE_KINDS = [
29528
- "hiccup",
29529
- "wrong-model",
29530
- "allowance-spent",
29531
- "not-signed-in",
29532
- "workspace-failure",
29533
- "helper-out-of-date",
29534
- "update-interrupted",
29535
- "offline"
29536
- ];
29537
- var TURN_RECEIPT_REASON_KINDS = [
29538
- "hiccup",
29539
- "wrong-model",
29540
- "allowance-spent",
29541
- "not-signed-in",
29542
- "workspace-failure",
29543
- "helper-out-of-date",
29544
- "update-interrupted",
29545
- "offline",
29546
- "model-selection-unavailable"
29547
- ];
29548
- function isTurnReceiptReasonKind(value) {
29549
- return typeof value === "string" && TURN_RECEIPT_REASON_KINDS.includes(value);
29550
- }
29551
- function receiptKindToSilenceKind(kind) {
29552
- if (kind === "model-selection-unavailable" || kind === "wrong-model")
29553
- return "wrong-model";
29554
- if (kind && TURN_SILENCE_KINDS.includes(kind))
29555
- return kind;
29556
- return "hiccup";
29557
- }
29558
- var ALLOWANCE_UNTIL = /(?:try again at|until|resets?(?: at)?|available(?: again)?(?: at)?)\s+([A-Z][a-z]{2,9}\s+\d{1,2}(?:st|nd|rd|th)?,?\s+\d{4}(?:\s+\d{1,2}:\d{2}(?:\s*[AP]M)?)?)/i;
29559
- var REPO_FROM_URL = /github\.com[:/]([^/\s]+\/[^/\s.]+?)(?:\.git)?(?:[/\s]|$)/i;
29560
- var REPO_FROM_SLUG = /\b([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\b/;
29561
- function firstMatch(value, pattern) {
29562
- const match = value.match(pattern);
29563
- const captured = match?.[1]?.trim();
29564
- return captured || void 0;
29565
- }
29566
- function classifyTurnSilence(reason, reasonKind) {
29567
- if (isTurnReceiptReasonKind(reasonKind)) {
29568
- const kind = receiptKindToSilenceKind(reasonKind);
29569
- if (kind === "hiccup") {
29570
- return { kind, fault: (reason ?? "").trim() || "the turn stalled" };
29571
- }
29572
- return {
29573
- kind,
29574
- ...kind === "allowance-spent" ? { allowanceUntil: firstMatch(reason ?? "", ALLOWANCE_UNTIL) } : {},
29575
- ...kind === "workspace-failure" ? { repo: repoFromReason(reason ?? "") } : {}
29576
- };
29577
- }
29578
- const text2 = (reason ?? "").trim();
29579
- if (!text2)
29580
- return { kind: "hiccup", fault: "the turn stalled" };
29581
- if (/model selection unavailable/i.test(text2) || /isn't available/i.test(text2) || /not advertised/i.test(text2)) {
29582
- return { kind: "wrong-model" };
29583
- }
29584
- if (/\b402\b/.test(text2) || /usage limit/i.test(text2) || /more credits/i.test(text2) || /quota/i.test(text2) || /allowance is spent/i.test(text2)) {
29585
- return {
29586
- kind: "allowance-spent",
29587
- allowanceUntil: firstMatch(text2, ALLOWANCE_UNTIL)
29588
- };
29589
- }
29590
- if (/authentication required/i.test(text2) || /not signed in/i.test(text2) || /isn't signed in/i.test(text2) || /invalid api[_ -]?key/i.test(text2) || /\b401\b/.test(text2)) {
29591
- return { kind: "not-signed-in" };
29592
- }
29593
- if (/command protocol/i.test(text2) || /refusing intake/i.test(text2) || /helper is out of date/i.test(text2)) {
29594
- return { kind: "helper-out-of-date" };
29595
- }
29596
- if (/working copy/i.test(text2) || /could not (?:clone|fetch|checkout)/i.test(text2) || /repository not found/i.test(text2) || /could not resolve host/i.test(text2) || /failed to start corner/i.test(text2) || /unable to access/i.test(text2) || /\bgit clone\b/i.test(text2) || /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2) || /profile_busy/i.test(text2) || /broker unavailable/i.test(text2)) {
29597
- return { kind: "workspace-failure", repo: repoFromReason(text2) };
29598
- }
29599
- if (/helper isn't running/i.test(text2) || /helper is offline/i.test(text2)) {
29600
- return { kind: "offline" };
29601
- }
29602
- const fault = text2 || "the turn stalled";
29603
- return { kind: "hiccup", fault };
29604
- }
29605
- function repoFromReason(text2) {
29606
- return firstMatch(text2, REPO_FROM_URL) ?? firstMatch(text2, REPO_FROM_SLUG) ?? "the repository";
29607
- }
29608
- function isStandingWorkspaceConfigurationFault(text2) {
29609
- return /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2);
29610
- }
29611
- function hiccupBackoffMs(attempt) {
29612
- const index = Math.max(1, attempt) - 1;
29613
- return HICCUP_BACKOFF_MS[Math.min(index, HICCUP_BACKOFF_MS.length - 1)] ?? 0;
29614
- }
29615
-
29616
- // packages/api-contract/dist/institutional-memory.js
29617
- var INSTITUTIONAL_MEMORY_PROPOSAL_VERSION = 1;
29618
- var INSTITUTIONAL_MEMORY_BODY_MAX_BYTES = 200;
29619
- var INSTITUTIONAL_MEMORY_KEYWORDS_MIN = 1;
29620
- var INSTITUTIONAL_MEMORY_KEYWORDS_MAX = 6;
29621
- var INSTITUTIONAL_MEMORY_KEYWORD_PATTERN = /^[a-z0-9][a-z0-9_./-]{2,31}$/;
29622
- var INSTITUTIONAL_MEMORY_STOPWORDS = /* @__PURE__ */ new Set([
29623
- "the",
29624
- "and",
29625
- "you",
29626
- "your",
29627
- "for",
29628
- "with",
29629
- "that",
29630
- "this",
29631
- "are",
29632
- "was",
29633
- "were",
29634
- "but",
29635
- "not",
29636
- "have",
29637
- "has",
29638
- "had",
29639
- "can",
29640
- "all",
29641
- "any",
29642
- "our",
29643
- "out",
29644
- "use",
29645
- "get",
29646
- "got",
29647
- "how",
29648
- "what",
29649
- "when",
29650
- "who",
29651
- "why",
29652
- "will",
29653
- "just",
29654
- "from",
29655
- "they",
29656
- "them",
29657
- "then",
29658
- "than",
29659
- "there",
29660
- "here",
29661
- "about",
29662
- "into",
29663
- "also",
29664
- "its",
29665
- "it's",
29666
- "please",
29667
- "should",
29668
- "would",
29669
- "could",
29670
- "some",
29671
- "more",
29672
- "most",
29673
- "very",
29674
- "only",
29675
- "one",
29676
- "now",
29677
- "yes",
29678
- "okay",
29679
- "let",
29680
- "make",
29681
- "want",
29682
- "need",
29683
- "does",
29684
- "did",
29685
- "done",
29686
- "like",
29687
- "know",
29688
- "think",
29689
- "see",
29690
- "look",
29691
- "thing",
29692
- "things",
29693
- "way"
29694
- ]);
29695
- var INSTITUTIONAL_STANDING_PREFERENCE_KEY = "standing";
29696
- var INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH = 160;
29697
- var INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH = 500;
29698
- var INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX = 16;
29699
- var INSTITUTIONAL_MEMORY_JOB_ERROR_MAX_LENGTH = 1e3;
29700
- var WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH = 60;
29701
- var WORKSPACE_SKILL_MARKDOWN_MAX_BYTES = 32 * 1024;
29702
- var WORKSPACE_SKILL_SLUG_MAX_LENGTH = 64;
29703
- var INSTITUTIONAL_REVIEW_FINDING_MAX = 20;
29704
- var INSTITUTIONAL_CURATOR_ACTION_MAX = 50;
29705
- function record3(value, label) {
29706
- if (!value || typeof value !== "object" || Array.isArray(value)) {
29707
- throw new Error(`${label} must be an object`);
29708
- }
29709
- return value;
29710
- }
29711
- function exactKeys(value, allowed, label) {
29712
- const unknown = Object.keys(value).find((key) => !allowed.includes(key));
29713
- if (unknown)
29714
- throw new Error(`${label} has unknown field ${unknown}`);
29715
- }
29716
- function omitted(value) {
29717
- return value === void 0 || value === null;
29718
- }
29719
- function boundedText(value, label, maximum, bytes = false) {
29720
- if (typeof value !== "string" || value.includes("\0"))
29721
- throw new Error(`${label} is invalid`);
29722
- const normalized = value.trim();
29723
- const size = bytes ? new TextEncoder().encode(normalized).length : normalized.length;
29724
- if (!normalized || size > maximum)
29725
- throw new Error(`${label} is invalid`);
29726
- return normalized;
29727
- }
29728
- var FILLER_OPENINGS = /^(?:the user|user|this user|the requester|requester|it is|it's|note that|please|remember that|keep in mind)\b/i;
29729
- var HEDGES = /\b(?:maybe|perhaps|probably|possibly|might|seems?|i think|apparently|likely)\b/i;
29730
- function conciseInstitutionalMemoryBody(value) {
29731
- const body = boundedText(value, `institutional memory body (at most ${INSTITUTIONAL_MEMORY_BODY_MAX_BYTES} bytes)`, INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
29732
- if (FILLER_OPENINGS.test(body)) {
29733
- throw new Error("institutional memory body must state the fact itself, without a filler opening");
29734
- }
29735
- if (/[.!?;]\s+\S/.test(body) || /\n/.test(body)) {
29736
- throw new Error("institutional memory body must be one sentence");
29737
- }
29738
- if (HEDGES.test(body)) {
29739
- throw new Error("institutional memory body must not hedge; save only what is known");
29740
- }
29741
- return body;
29742
- }
29743
- function institutionalMemoryKeywords(value) {
29744
- if (!Array.isArray(value) || value.length < INSTITUTIONAL_MEMORY_KEYWORDS_MIN || value.length > INSTITUTIONAL_MEMORY_KEYWORDS_MAX) {
29745
- throw new Error(`institutional memory needs ${INSTITUTIONAL_MEMORY_KEYWORDS_MIN} to ${INSTITUTIONAL_MEMORY_KEYWORDS_MAX} keywords`);
29746
- }
29747
- const keywords = value.map((keyword) => typeof keyword === "string" ? keyword.trim().toLocaleLowerCase("en-US") : "");
29748
- if (keywords.some((keyword) => !INSTITUTIONAL_MEMORY_KEYWORD_PATTERN.test(keyword) || INSTITUTIONAL_MEMORY_STOPWORDS.has(keyword))) {
29749
- throw new Error("institutional memory keywords are distinctive single lower-case words of 3 to 32 letters, digits, or _./-");
29750
- }
29751
- if (new Set(keywords).size !== keywords.length) {
29752
- throw new Error("institutional memory keywords must be unique");
29753
- }
29754
- return keywords;
29755
- }
29756
- function parseInstitutionalMemoryProposal(value) {
29757
- const proposal = record3(value, "institutional memory proposal");
29758
- exactKeys(proposal, [
29759
- "proposalVersion",
29760
- "candidateType",
29761
- "memoryKind",
29762
- "subjectIdentityId",
29763
- "canonicalKey",
29764
- "body",
29765
- "keywords",
29766
- "source",
29767
- "audience",
29768
- "confidence",
29769
- "classification",
29770
- "cas"
29771
- ], "institutional memory proposal");
29772
- if (proposal.proposalVersion !== INSTITUTIONAL_MEMORY_PROPOSAL_VERSION) {
29773
- throw new Error("institutional memory proposal version is unsupported");
29774
- }
29775
- if (proposal.candidateType !== "correction_candidate" && proposal.candidateType !== "fact_candidate" && proposal.candidateType !== "preference_candidate") {
29776
- throw new Error("institutional memory candidate type is invalid");
29777
- }
29778
- if (proposal.memoryKind !== "workspace_fact" && proposal.memoryKind !== "human_profile_fact") {
29779
- throw new Error("institutional memory kind is invalid");
29780
- }
29781
- if (proposal.audience !== "workspace" && proposal.audience !== "human_profile") {
29782
- throw new Error("institutional memory audience is invalid");
29783
- }
29784
- if (typeof proposal.confidence !== "number" || !Number.isFinite(proposal.confidence) || proposal.confidence < 0 || proposal.confidence > 1) {
29785
- throw new Error("institutional memory confidence is invalid");
29786
- }
29787
- const source = record3(proposal.source, "institutional memory source");
29788
- exactKeys(source, ["roomId", "messageIds"], "institutional memory source");
29789
- const roomId = boundedText(source.roomId, "institutional memory source room", 200);
29790
- if (!Array.isArray(source.messageIds) || source.messageIds.length === 0 || source.messageIds.length > INSTITUTIONAL_MEMORY_SOURCE_MESSAGE_MAX) {
29791
- throw new Error("institutional memory source messages are invalid");
29792
- }
29793
- const messageIds = source.messageIds.map((messageId) => boundedText(messageId, "institutional memory source message", 200));
29794
- if (new Set(messageIds).size !== messageIds.length) {
29795
- throw new Error("institutional memory source messages must be unique");
29796
- }
29797
- const classification = record3(proposal.classification, "institutional memory classification");
29798
- exactKeys(classification, ["stillTrueForAnotherRequester", "subjectIsRequester", "rationale"], "institutional memory classification");
29799
- if (classification.stillTrueForAnotherRequester !== void 0 && typeof classification.stillTrueForAnotherRequester !== "boolean") {
29800
- throw new Error("institutional memory classification test is invalid");
29801
- }
29802
- if (classification.subjectIsRequester !== void 0 && typeof classification.subjectIsRequester !== "boolean") {
29803
- throw new Error("institutional memory subject classification is invalid");
29804
- }
29805
- const canonicalKey = boundedText(proposal.canonicalKey, "institutional memory canonical key", INSTITUTIONAL_MEMORY_CANONICAL_KEY_MAX_LENGTH);
29806
- if (canonicalKey === INSTITUTIONAL_STANDING_PREFERENCE_KEY) {
29807
- throw new Error("the standing preference key is reserved for owner-confirmed preferences");
29803
+ readVaultFn;
29804
+ revokeGrantsFn;
29805
+ /** Armed only while this helper owns a live sign-in ceremony. */
29806
+ connectWatch;
29807
+ started = false;
29808
+ stopped = false;
29809
+ /** One install at a time per connector; concurrent wakes skip it. */
29810
+ inFlight = /* @__PURE__ */ new Set();
29811
+ mcp;
29812
+ constructor(options) {
29813
+ this.agentId = options.agentId;
29814
+ this.api = options.api;
29815
+ this.log = options.log ?? (() => {
29816
+ });
29817
+ this.install = options.install ?? installSquire;
29818
+ this.installTailscale = options.installTailscale ?? installTailscale;
29819
+ this.watchTailscaleSignIn = options.watchTailscaleSignIn ?? watchTailscaleSignIn;
29820
+ this.registryHomeDir = options.registryHome ?? process.env.HOME ?? process.cwd();
29821
+ this.installRegistry = options.installRegistry ?? installRegistryMcp;
29822
+ this.readVaultFn = options.readVault ?? readVault;
29823
+ this.revokeGrantsFn = options.revokeGrants ?? revokeGrants;
29808
29824
  }
29809
- const rationale = boundedText(classification.rationale, "institutional memory classification rationale", INSTITUTIONAL_MEMORY_RATIONALE_MAX_LENGTH);
29810
- const cas = record3(proposal.cas, "institutional memory CAS");
29811
- exactKeys(cas, ["baseVersion", "supersedesItemId"], "institutional memory CAS");
29812
- if (cas.baseVersion !== null && (!Number.isSafeInteger(cas.baseVersion) || cas.baseVersion < 0)) {
29813
- throw new Error("institutional memory base version is invalid");
29825
+ start() {
29826
+ if (this.stopped || this.started)
29827
+ return;
29828
+ this.started = true;
29829
+ void this.runOnce();
29814
29830
  }
29815
- const supersedesItemId = cas.supersedesItemId === void 0 ? void 0 : boundedText(cas.supersedesItemId, "institutional memory supersedes item", 200);
29816
- const workspaceFact = proposal.memoryKind === "workspace_fact";
29817
- if (classification.subjectIsRequester !== void 0 && classification.subjectIsRequester === workspaceFact) {
29818
- throw new Error("institutional memory kind contradicts its subject");
29831
+ /** Event-driven drain, also called when the socket reconnects. */
29832
+ wake() {
29833
+ if (this.stopped)
29834
+ return;
29835
+ void this.runOnce();
29819
29836
  }
29820
- if (proposal.audience === "workspace" !== workspaceFact) {
29821
- throw new Error("institutional memory audience contradicts its kind");
29837
+ stop() {
29838
+ this.stopped = true;
29839
+ this.connectWatch?.();
29840
+ this.connectWatch = void 0;
29841
+ this.tailscaleWatch?.();
29842
+ this.tailscaleWatch = void 0;
29822
29843
  }
29823
- const subjectIdentityId = proposal.subjectIdentityId === void 0 ? void 0 : boundedText(proposal.subjectIdentityId, "institutional memory profile subject", 200);
29824
- if (workspaceFact === Boolean(subjectIdentityId)) {
29825
- throw new Error(workspaceFact ? "workspace facts cannot name a profile subject" : "human profile facts require a subject");
29844
+ /**
29845
+ * Watch the sign-in this helper is holding open. The phone paints
29846
+ * `installing` for the whole ceremony and only a drain that reaches
29847
+ * Squire's already-connected short-circuit flips the row to `connected`;
29848
+ * nothing on the wire announces that the human finished, so the connect
29849
+ * process exiting is the signal. Drain on that, and the row settles on the
29850
+ * process exit event without waiting for a server read timer.
29851
+ */
29852
+ watchConnectSignIn() {
29853
+ if (this.stopped || this.connectWatch)
29854
+ return;
29855
+ const claim = squireConnectSession();
29856
+ this.connectWatch = claim?.onExit?.(() => {
29857
+ this.connectWatch = void 0;
29858
+ if (!this.stopped)
29859
+ void this.runOnce();
29860
+ });
29826
29861
  }
29827
- return {
29828
- proposalVersion: INSTITUTIONAL_MEMORY_PROPOSAL_VERSION,
29829
- candidateType: proposal.candidateType,
29830
- memoryKind: proposal.memoryKind,
29831
- ...subjectIdentityId ? { subjectIdentityId } : {},
29832
- canonicalKey,
29833
- body: conciseInstitutionalMemoryBody(proposal.body),
29834
- keywords: institutionalMemoryKeywords(proposal.keywords),
29835
- source: { roomId, messageIds },
29836
- audience: proposal.audience,
29837
- confidence: proposal.confidence,
29838
- classification: {
29839
- ...classification.stillTrueForAnotherRequester === void 0 ? {} : {
29840
- stillTrueForAnotherRequester: classification.stillTrueForAnotherRequester
29841
- },
29842
- ...classification.subjectIsRequester === void 0 ? {} : {
29843
- subjectIsRequester: classification.subjectIsRequester
29844
- },
29845
- rationale
29846
- },
29847
- cas: {
29848
- baseVersion: cas.baseVersion,
29849
- ...supersedesItemId ? { supersedesItemId } : {}
29862
+ /** Drain the queue once; every failure is logged, never raised. */
29863
+ async runOnce() {
29864
+ let assignments;
29865
+ try {
29866
+ const result = await this.api.execute("getConnectorAssignments", { agentId: this.agentId });
29867
+ assignments = result.assignments;
29868
+ } catch (error) {
29869
+ this.log(`connector assignments unavailable: ${describe(error)}`);
29870
+ return;
29871
+ }
29872
+ for (const assignment of assignments) {
29873
+ const key = `${assignment.kind}:${assignment.connectorId}`;
29874
+ if (assignment.kind === "uninstall")
29875
+ continue;
29876
+ if (this.inFlight.has(key))
29877
+ continue;
29878
+ this.inFlight.add(key);
29879
+ void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe(error)}`)).finally(() => this.inFlight.delete(key));
29850
29880
  }
29851
- };
29852
- }
29853
- function repositoryRelativePath(value) {
29854
- if (typeof value !== "string" || value.length === 0 || value.length > 500)
29855
- return void 0;
29856
- if (value.startsWith("/") || value.includes("\\") || value.split("/").some((segment) => segment === ".." || segment === "")) {
29857
- return void 0;
29858
29881
  }
29859
- return value;
29860
- }
29861
- function optionalAnchorField(key, value) {
29862
- return value === void 0 ? {} : { [key]: value };
29863
- }
29864
- function parseInstitutionalMergeReviewProposal(value) {
29865
- const proposal = record3(value, "institutional merge review proposal");
29866
- exactKeys(proposal, ["proposalVersion", "skill", "findings"], "institutional merge review proposal");
29867
- if (proposal.proposalVersion !== 1) {
29868
- throw new Error("institutional merge review proposal version is unsupported");
29882
+ squire() {
29883
+ this.mcp ??= defaultSquireMcpClient({ agentId: this.agentId, roomId: "connector" });
29884
+ return this.mcp;
29869
29885
  }
29870
- let skill = null;
29871
- if (!omitted(proposal.skill)) {
29872
- const rawSkill = record3(proposal.skill, "workspace skill proposal");
29873
- exactKeys(rawSkill, ["slug", "description", "markdown", "baseVersion", "anchor"], "workspace skill proposal");
29874
- const slug = boundedText(rawSkill.slug, "workspace skill slug", WORKSPACE_SKILL_SLUG_MAX_LENGTH);
29875
- if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) {
29876
- throw new Error("workspace skill slug is invalid");
29877
- }
29878
- const anchor = record3(rawSkill.anchor, "workspace skill code anchor");
29879
- exactKeys(anchor, ["repository", "targetCommit", "path"], "workspace skill code anchor");
29880
- if (rawSkill.baseVersion !== null && (!Number.isSafeInteger(rawSkill.baseVersion) || rawSkill.baseVersion <= 0)) {
29881
- throw new Error("workspace skill base version is invalid");
29882
- }
29883
- skill = {
29884
- slug,
29885
- description: boundedText(rawSkill.description, "workspace skill description", WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH),
29886
- markdown: boundedText(rawSkill.markdown, "workspace skill markdown", WORKSPACE_SKILL_MARKDOWN_MAX_BYTES, true),
29887
- baseVersion: rawSkill.baseVersion,
29888
- anchor: {
29889
- repository: boundedText(anchor.repository, "workspace skill repository", 300),
29890
- targetCommit: boundedText(anchor.targetCommit, "workspace skill target commit", 160),
29891
- ...optionalAnchorField("path", repositoryRelativePath(anchor.path))
29886
+ async handle(assignment) {
29887
+ const pairingGeneration = assignment.kind === "install" || assignment.kind === "uninstall" ? assignment.pairingGeneration : void 0;
29888
+ if (assignment.kind === "install") {
29889
+ if (assignment.connectorType?.startsWith("google-")) {
29890
+ await this.api.execute("postConnectorStatus", {
29891
+ agentId: this.agentId,
29892
+ connectorId: assignment.connectorId,
29893
+ steps: [{
29894
+ label: "Connect app",
29895
+ status: "failed",
29896
+ reason: "Reconnect through Connect an app"
29897
+ }],
29898
+ errorMessage: "Reconnect through Connect an app",
29899
+ ...pairingGeneration !== void 0 ? { pairingGeneration } : {}
29900
+ });
29901
+ } else if (assignment.connectorType === "registry-mcp") {
29902
+ await this.runRegistryMcpInstall(assignment);
29903
+ } else if (assignment.connectorType === "tailscale") {
29904
+ await this.runTailscaleInstall(assignment.connectorId, pairingGeneration);
29905
+ } else {
29906
+ await this.runInstall(assignment.connectorId, pairingGeneration, assignment.forceReloginProvider);
29892
29907
  }
29893
- };
29908
+ } else if (assignment.kind === "sync" && assignment.connectorType === "tailscale") {
29909
+ await this.runTailscaleInstall(assignment.connectorId);
29910
+ } else if (assignment.kind === "sync") {
29911
+ await this.runSync();
29912
+ } else if (assignment.kind === "refresh-google-grant") {
29913
+ this.log("retired Google grant assignment ignored; reconnect through Connect an app");
29914
+ } else if (assignment.kind === "revoke-grants")
29915
+ await this.runRevoke(assignment.connectorId, assignment.reference);
29894
29916
  }
29895
- if (!Array.isArray(proposal.findings) || proposal.findings.length > INSTITUTIONAL_REVIEW_FINDING_MAX) {
29896
- throw new Error("institutional review findings are invalid");
29917
+ ceremonyKey(assignment) {
29918
+ return `${assignment.connectorId}:${assignment.pairingGeneration ?? 1}`;
29897
29919
  }
29898
- const findings = proposal.findings.map((value2) => {
29899
- const finding = record3(value2, "institutional review finding");
29900
- exactKeys(finding, ["taxonomy", "summary", "severity", "confidence", "path"], "institutional review finding");
29901
- if (finding.severity !== "info" && finding.severity !== "warning" && finding.severity !== "error") {
29902
- throw new Error("institutional review finding severity is invalid");
29903
- }
29904
- const severity = finding.severity;
29905
- if (typeof finding.confidence !== "number" || !Number.isFinite(finding.confidence) || finding.confidence < 0 || finding.confidence > 1) {
29906
- throw new Error("institutional review finding confidence is invalid");
29907
- }
29908
- return {
29909
- taxonomy: boundedText(finding.taxonomy, "institutional review finding taxonomy", 120),
29910
- summary: boundedText(finding.summary, "institutional review finding summary", 1e3),
29911
- severity,
29912
- confidence: finding.confidence,
29913
- ...omitted(finding.path) ? {} : { path: boundedText(finding.path, "institutional review finding path", 500) }
29920
+ async runRegistryMcpInstall(assignment) {
29921
+ const generation = assignment.pairingGeneration !== void 0 ? { pairingGeneration: assignment.pairingGeneration } : {};
29922
+ const ceremonyKey = this.ceremonyKey(assignment);
29923
+ const result = await this.installRegistry({
29924
+ api: this.api,
29925
+ agentId: this.agentId,
29926
+ assignment,
29927
+ home: this.registryHomeDir
29928
+ });
29929
+ const stopWatch = () => {
29914
29930
  };
29915
- });
29916
- return { proposalVersion: 1, skill, findings };
29917
- }
29918
- function parseInstitutionalCuratorProposal(value) {
29919
- const proposal = record3(value, "institutional curator proposal");
29920
- exactKeys(proposal, ["proposalVersion", "partition", "actions"], "institutional curator proposal");
29921
- if (proposal.proposalVersion !== 1) {
29922
- throw new Error("institutional curator proposal version is unsupported");
29923
- }
29924
- const partition = boundedText(proposal.partition, "institutional curator partition", 300);
29925
- if (!Array.isArray(proposal.actions) || proposal.actions.length > INSTITUTIONAL_CURATOR_ACTION_MAX) {
29926
- throw new Error("institutional curator actions are invalid");
29927
- }
29928
- const actions = proposal.actions.map((value2) => {
29929
- const action = record3(value2, "institutional curator action");
29930
- exactKeys(action, [
29931
- "action",
29932
- "targetType",
29933
- "targetId",
29934
- "baseVersion",
29935
- "duplicateIds",
29936
- "body",
29937
- "description",
29938
- "markdown",
29939
- "rationale"
29940
- ], "institutional curator action");
29941
- if (action.action !== "retain" && action.action !== "stale" && action.action !== "archive" && action.action !== "consolidate") {
29942
- throw new Error("institutional curator action kind is invalid");
29943
- }
29944
- if (action.targetType !== "memory_item" && action.targetType !== "workspace_skill") {
29945
- throw new Error("institutional curator target type is invalid");
29931
+ if (result.status === "connected") {
29932
+ stopWatch();
29933
+ this.registryCeremonies.delete(ceremonyKey);
29934
+ await this.api.execute("installConnector", {
29935
+ agentId: this.agentId,
29936
+ connectorId: assignment.connectorId,
29937
+ ...generation
29938
+ });
29939
+ return;
29946
29940
  }
29947
- if (!Number.isSafeInteger(action.baseVersion) || action.baseVersion <= 0) {
29948
- throw new Error("institutional curator base version is invalid");
29941
+ if (result.status === "installing") {
29942
+ const ceremony = this.registryCeremonies.get(ceremonyKey);
29943
+ if (!ceremony || ceremony.attemptId !== result.attemptId) {
29944
+ this.registryCeremonies.set(ceremonyKey, {
29945
+ attemptId: result.attemptId,
29946
+ endsAt: result.attemptExpiresAt
29947
+ });
29948
+ } else if (ceremony.expired) {
29949
+ return;
29950
+ } else if (Date.now() >= ceremony.endsAt) {
29951
+ stopWatch();
29952
+ this.registryCeremonies.set(ceremonyKey, { ...ceremony, expired: true });
29953
+ await this.api.execute("postConnectorStatus", {
29954
+ agentId: this.agentId,
29955
+ connectorId: assignment.connectorId,
29956
+ steps: [
29957
+ { label: "Connect provider account", status: "failed", reason: CEREMONY_EXPIRED }
29958
+ ],
29959
+ signIn: null,
29960
+ errorMessage: CEREMONY_EXPIRED,
29961
+ ...generation
29962
+ });
29963
+ return;
29964
+ }
29965
+ } else {
29966
+ this.registryCeremonies.delete(ceremonyKey);
29949
29967
  }
29950
- if (!Array.isArray(action.duplicateIds) || action.duplicateIds.length > 20 || action.duplicateIds.some((id) => typeof id !== "string" || !id || id.length > 100)) {
29951
- throw new Error("institutional curator duplicate ids are invalid");
29968
+ await this.api.execute("postConnectorStatus", {
29969
+ agentId: this.agentId,
29970
+ connectorId: assignment.connectorId,
29971
+ steps: result.steps,
29972
+ ...result.status === "installing" ? {
29973
+ signIn: {
29974
+ method: "oauth",
29975
+ url: result.authorizationUrl,
29976
+ attemptId: result.attemptId
29977
+ }
29978
+ } : { signIn: null, errorMessage: result.errorMessage },
29979
+ ...generation
29980
+ });
29981
+ }
29982
+ /** Install Tailscale and publish its browser login URL until the tailnet is connected. */
29983
+ async runTailscaleInstall(connectorId, pairingGeneration) {
29984
+ const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
29985
+ const report = async (steps2) => {
29986
+ try {
29987
+ await this.api.execute("postConnectorStatus", {
29988
+ agentId: this.agentId,
29989
+ connectorId,
29990
+ steps: steps2,
29991
+ ...generation
29992
+ });
29993
+ } catch (error) {
29994
+ this.log(`step report failed: ${describe(error)}`);
29995
+ }
29996
+ };
29997
+ const existing = await this.connectorRow(connectorId);
29998
+ const result = await this.installTailscale({
29999
+ onProgress: report,
30000
+ ...existing?.signIn ? { signIn: existing.signIn } : {}
30001
+ });
30002
+ if (result.status === "connected") {
30003
+ this.tailscaleWatch?.();
30004
+ this.tailscaleWatch = void 0;
30005
+ await this.api.execute("installConnector", {
30006
+ agentId: this.agentId,
30007
+ connectorId,
30008
+ ...result.signedInAs ? { signedInAs: result.signedInAs } : {},
30009
+ ...generation
30010
+ });
30011
+ return;
29952
30012
  }
29953
- if (action.action === "consolidate" && action.duplicateIds.length === 0) {
29954
- throw new Error("institutional curator consolidation needs duplicates");
30013
+ await this.api.execute("postConnectorStatus", {
30014
+ agentId: this.agentId,
30015
+ connectorId,
30016
+ steps: result.steps,
30017
+ signIn: result.status === "installing" ? result.signIn : null,
30018
+ ...result.status === "error" ? { errorMessage: result.errorMessage } : {},
30019
+ ...generation
30020
+ });
30021
+ if (result.status === "installing" && !this.tailscaleWatch)
30022
+ this.tailscaleWatch = this.watchTailscaleSignIn(() => {
30023
+ this.tailscaleWatch = void 0;
30024
+ if (!this.stopped)
30025
+ this.wake();
30026
+ });
30027
+ }
30028
+ /** Install Trusty Squire, reporting every step as it settles.
30029
+ * `forceReloginProvider` is set only for a login-wall reconnect. */
30030
+ async runInstall(connectorId, pairingGeneration, forceReloginProvider) {
30031
+ const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
30032
+ const claim = squireConnectSession();
30033
+ const spent = claim ? Date.now() - claim.claimedAt >= CONNECT_TIMEOUT_MS : false;
30034
+ if (claim && !spent && isProcessAlive(claim.pid)) {
30035
+ if (!await this.rearmedByHuman(connectorId)) {
30036
+ this.log(`trusty-squire connect still waiting for sign-in (pid ${String(claim.pid)}); leaving it alone`);
30037
+ this.watchConnectSignIn();
30038
+ return;
30039
+ }
30040
+ this.log("trusty-squire re-pair requested; superseding the connect holding the browser");
30041
+ } else if (spent && (await this.connectorRow(connectorId))?.signIn) {
30042
+ releaseSquireConnectSession((message) => this.log(`[trusty-squire] ${message}`));
30043
+ await this.api.execute("postConnectorStatus", {
30044
+ agentId: this.agentId,
30045
+ connectorId,
30046
+ steps: [{ label: "waiting for sign-in", status: "failed", reason: CEREMONY_EXPIRED }],
30047
+ signIn: null,
30048
+ errorMessage: CEREMONY_EXPIRED,
30049
+ ...generation
30050
+ });
30051
+ return;
29955
30052
  }
29956
- if (action.action !== "consolidate" && action.duplicateIds.length !== 0) {
29957
- throw new Error("institutional curator lifecycle action cannot carry duplicates");
30053
+ const report = async (steps2) => {
30054
+ try {
30055
+ await this.api.execute("postConnectorStatus", {
30056
+ agentId: this.agentId,
30057
+ connectorId,
30058
+ steps: steps2,
30059
+ ...generation
30060
+ });
30061
+ } catch (error) {
30062
+ this.log(`step report failed: ${describe(error)}`);
30063
+ }
30064
+ };
30065
+ const result = await this.install({
30066
+ workspaceId: this.agentId,
30067
+ mcp: this.squire(),
30068
+ onProgress: report,
30069
+ log: (message) => this.log(`[trusty-squire] ${message}`),
30070
+ ...forceReloginProvider ? { forceReloginProvider } : {}
30071
+ });
30072
+ if (result.status === "error") {
30073
+ await this.api.execute("postConnectorStatus", {
30074
+ agentId: this.agentId,
30075
+ connectorId,
30076
+ steps: result.steps,
30077
+ signIn: null,
30078
+ errorMessage: result.errorMessage,
30079
+ ...generation
30080
+ });
30081
+ return;
29958
30082
  }
29959
- const body = omitted(action.body) ? void 0 : action.targetType === "memory_item" ? conciseInstitutionalMemoryBody(action.body) : boundedText(action.body, "institutional curator body", INSTITUTIONAL_MEMORY_BODY_MAX_BYTES, true);
29960
- const description = omitted(action.description) ? void 0 : boundedText(action.description, "institutional curator skill description", WORKSPACE_SKILL_DESCRIPTION_MAX_LENGTH);
29961
- const markdown = omitted(action.markdown) ? void 0 : boundedText(action.markdown, "institutional curator skill markdown", WORKSPACE_SKILL_MARKDOWN_MAX_BYTES, true);
29962
- if (action.action === "consolidate" && (action.targetType === "memory_item" && (!body || description || markdown) || action.targetType === "workspace_skill" && (!description || !markdown || body))) {
29963
- throw new Error("institutional curator consolidation content is invalid");
30083
+ if (result.status === "connected") {
30084
+ await this.api.execute("installConnector", {
30085
+ agentId: this.agentId,
30086
+ connectorId,
30087
+ ...result.squireVersion ? { squireVersion: result.squireVersion } : {},
30088
+ ...generation
30089
+ });
30090
+ await this.reportVault(connectorId);
30091
+ return;
29964
30092
  }
29965
- if (action.action !== "consolidate" && (body || description || markdown)) {
29966
- throw new Error("institutional curator lifecycle action cannot replace content");
30093
+ await this.api.execute("postConnectorStatus", {
30094
+ agentId: this.agentId,
30095
+ connectorId,
30096
+ steps: result.steps,
30097
+ signIn: result.signIn ?? null,
30098
+ ...result.squireVersion ? { squireVersion: result.squireVersion } : {},
30099
+ ...generation
30100
+ });
30101
+ this.watchConnectSignIn();
30102
+ }
30103
+ /** This connector's own row, or undefined when the server cannot answer. */
30104
+ async connectorRow(connectorId) {
30105
+ try {
30106
+ const status = await this.api.execute("getConnectorStatus", {
30107
+ agentId: this.agentId,
30108
+ connectorId
30109
+ });
30110
+ return status.connectorId === connectorId ? status : void 0;
30111
+ } catch (error) {
30112
+ this.log(`connector status unavailable: ${describe(error)}`);
30113
+ return void 0;
29967
30114
  }
29968
- return {
29969
- action: action.action,
29970
- targetType: action.targetType,
29971
- targetId: boundedText(action.targetId, "institutional curator target id", 100),
29972
- baseVersion: action.baseVersion,
29973
- duplicateIds: [...new Set(action.duplicateIds)],
29974
- ...body ? { body } : {},
29975
- ...description ? { description } : {},
29976
- ...markdown ? { markdown } : {},
29977
- rationale: boundedText(action.rationale, "institutional curator rationale", 500)
29978
- };
29979
- });
29980
- return { proposalVersion: 1, partition, actions };
30115
+ }
30116
+ /**
30117
+ * True when a human asked for this connector again while a connect of ours
30118
+ * still holds the browser. `pairConnector` re-arms the row to its default
30119
+ * all-pending steps, so a row whose every step is still pending is a fresh
30120
+ * request; the row carrying the ceremony this helper published has settled
30121
+ * ones. An unreadable row is not evidence of a retry.
30122
+ */
30123
+ async rearmedByHuman(connectorId) {
30124
+ const status = await this.connectorRow(connectorId);
30125
+ if (!status)
30126
+ return false;
30127
+ return status.steps.length > 0 && status.steps.every((step3) => step3.status === "pending");
30128
+ }
30129
+ /** One vault report covers every live trusty-squire connector on this helper. */
30130
+ async runSync() {
30131
+ await this.reportVault();
30132
+ }
30133
+ async runRevoke(connectorId, reference) {
30134
+ const outcome = await this.revokeGrantsFn(this.squire(), reference);
30135
+ this.log(`revoked ${outcome.revoked} grant(s) on ${reference}` + (outcome.failed ? `, ${outcome.failed} failed` : ""));
30136
+ if (outcome.failed)
30137
+ return;
30138
+ await this.api.execute("revokeConnectionGrants", {
30139
+ agentId: this.agentId,
30140
+ ref: reference
30141
+ });
30142
+ void connectorId;
30143
+ }
30144
+ async reportVault(_connectorId) {
30145
+ const connections = await this.readVaultFn(this.squire());
30146
+ await this.api.execute("postConnectorVault", { agentId: this.agentId, connections });
30147
+ }
30148
+ };
30149
+ function describe(error) {
30150
+ return error instanceof Error ? error.message : String(error);
29981
30151
  }
29982
30152
 
30153
+ // apps/body/dist/institutional-memory-shadow-worker.js
30154
+ import { mkdtemp as mkdtemp2, rm as rm5 } from "node:fs/promises";
30155
+ import { tmpdir as tmpdir3 } from "node:os";
30156
+ import { resolve as resolve12 } from "node:path";
30157
+
29983
30158
  // apps/body/dist/institutional-context.js
30159
+ import { performance as performance2 } from "node:perf_hooks";
29984
30160
  var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 200;
29985
30161
  var INSTITUTIONAL_MEMORY_LIVE_FLAG = "BEELINE_INSTITUTIONAL_MEMORY_ENABLED";
29986
30162
  function institutionalMemoryFlagEnabled(env, flag) {
@@ -29993,21 +30169,34 @@ var EMPTY_INSTITUTIONAL_CONTEXT = {
29993
30169
  totalBytes: 0,
29994
30170
  omitted: {}
29995
30171
  };
29996
- async function institutionalContextForTurn(api, roomId, log2 = console.warn, timeoutMs = INSTITUTIONAL_CONTEXT_TIMEOUT_MS, enabled = institutionalMemoryFlagEnabled(process.env, INSTITUTIONAL_MEMORY_LIVE_FLAG)) {
29997
- if (!enabled)
29998
- return EMPTY_INSTITUTIONAL_CONTEXT;
30172
+ var INSTITUTIONAL_CONTEXT_MISSED_TEXT = "institutional memory did not load this turn; use search_memory before concluding anything is not stored.";
30173
+ function startInstitutionalContextFetch(api, roomId, enabled = institutionalMemoryFlagEnabled(process.env, INSTITUTIONAL_MEMORY_LIVE_FLAG), now2 = () => performance2.now()) {
30174
+ const startedAt = now2();
30175
+ const promise = enabled ? api.execute("getInstitutionalContext", { roomId }) : Promise.resolve(EMPTY_INSTITUTIONAL_CONTEXT);
30176
+ promise.catch(() => {
30177
+ });
30178
+ return { promise, startedAt };
30179
+ }
30180
+ async function awaitInstitutionalContext(fetch2, log2 = console.warn, budgetMs = INSTITUTIONAL_CONTEXT_TIMEOUT_MS, now2 = () => performance2.now()) {
30181
+ const remainingMs = budgetMs - (now2() - fetch2.startedAt);
29999
30182
  let timer;
30000
30183
  try {
30001
- return await Promise.race([
30002
- api.execute("getInstitutionalContext", { roomId }),
30184
+ const snapshot = await Promise.race([
30185
+ fetch2.promise,
30003
30186
  new Promise((_, reject) => {
30004
- timer = setTimeout(() => reject(new Error("institutional context timed out")), timeoutMs);
30187
+ timer = setTimeout(() => reject(new Error("institutional context timed out")), Math.max(0, remainingMs));
30005
30188
  timer.unref?.();
30006
30189
  })
30007
30190
  ]);
30191
+ const served = snapshot.text !== "" || snapshot.standingPreference !== void 0;
30192
+ return { ...snapshot, outcome: served ? "served" : "empty" };
30008
30193
  } catch (error) {
30009
30194
  log2(`institutional context unavailable: ${error instanceof Error ? error.message : String(error)}`);
30010
- return EMPTY_INSTITUTIONAL_CONTEXT;
30195
+ return {
30196
+ ...EMPTY_INSTITUTIONAL_CONTEXT,
30197
+ text: INSTITUTIONAL_CONTEXT_MISSED_TEXT,
30198
+ outcome: "timed-out"
30199
+ };
30011
30200
  } finally {
30012
30201
  if (timer)
30013
30202
  clearTimeout(timer);
@@ -30927,7 +31116,7 @@ import { execFile as execFile12 } from "node:child_process";
30927
31116
  import { createHash as createHash10 } from "node:crypto";
30928
31117
  import { existsSync as existsSync8, mkdirSync as mkdirSync3 } from "node:fs";
30929
31118
  import { cp, mkdir as mkdir20, readdir as readdir8, realpath as realpath2, rm as rm9 } from "node:fs/promises";
30930
- import { dirname as dirname18, relative as relative3, resolve as resolve29, sep as sep2 } from "node:path";
31119
+ import { dirname as dirname19, relative as relative3, resolve as resolve29, sep as sep2 } from "node:path";
30931
31120
  import { promisify as promisify8 } from "node:util";
30932
31121
 
30933
31122
  // apps/body/dist/grant-runner.js
@@ -30935,7 +31124,7 @@ import { execFile as execFile8 } from "node:child_process";
30935
31124
  import { createHash as createHash6, randomBytes as randomBytes7 } from "node:crypto";
30936
31125
  import { readFile as readFile12 } from "node:fs/promises";
30937
31126
  import { createServer as createServer3 } from "node:http";
30938
- import { dirname as dirname11, resolve as resolve16 } from "node:path";
31127
+ import { dirname as dirname12, resolve as resolve16 } from "node:path";
30939
31128
 
30940
31129
  // packages/api-contract/dist/agent-grants.js
30941
31130
  var AGENT_GRANT_KINDS = [
@@ -31182,9 +31371,9 @@ function surfaceAllows(surface, capability) {
31182
31371
  init_agent_command();
31183
31372
  init_cursor_acp_bridge();
31184
31373
  import { execFile as execFile7, spawnSync } from "node:child_process";
31185
- import { lstatSync as lstatSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
31374
+ import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
31186
31375
  import { homedir as homedir11 } from "node:os";
31187
- import { isAbsolute as isAbsolute2, relative, resolve as resolve14 } from "node:path";
31376
+ import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute2, relative, resolve as resolve14 } from "node:path";
31188
31377
  var DEFAULT_SANDBOX_POLICY = "bwrap";
31189
31378
  function isSandboxPolicy(value) {
31190
31379
  return value === "bwrap" || value === "off";
@@ -31270,6 +31459,18 @@ function credentialMaskPaths(extraPaths, home = homedir11(), stat8 = (path) => {
31270
31459
  }
31271
31460
  return masks.sort((a2, b) => a2.path.localeCompare(b.path));
31272
31461
  }
31462
+ function siblingAgentMaskPaths(ownRuntimeDir, listAgentDirs = (agentsRoot) => {
31463
+ try {
31464
+ return readdirSync2(agentsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
31465
+ } catch {
31466
+ return [];
31467
+ }
31468
+ }) {
31469
+ const own = resolve14(ownRuntimeDir);
31470
+ const agentsRoot = dirname10(own);
31471
+ const ownName = basename4(own).toLowerCase();
31472
+ return listAgentDirs(agentsRoot).filter((name) => name.toLowerCase() !== ownName).map((name) => ({ path: resolve14(agentsRoot, name), kind: "dir" })).sort((a2, b) => a2.path.localeCompare(b.path));
31473
+ }
31273
31474
  function isUnderTmp(path) {
31274
31475
  const rel = relative("/tmp", path);
31275
31476
  return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
@@ -31584,9 +31785,9 @@ async function ensureBwrapSandbox(options = {}) {
31584
31785
  }
31585
31786
 
31586
31787
  // apps/body/dist/provider-key-store.js
31587
- import { chmod as chmod4, mkdir as mkdir8, readFile as readFile11, writeFile as writeFile8 } from "node:fs/promises";
31788
+ import { chmod as chmod5, mkdir as mkdir8, readFile as readFile11, writeFile as writeFile8 } from "node:fs/promises";
31588
31789
  import { homedir as homedir12 } from "node:os";
31589
- import { dirname as dirname10, resolve as resolve15 } from "node:path";
31790
+ import { dirname as dirname11, resolve as resolve15 } from "node:path";
31590
31791
  var PROVIDER_KEY_ENV_VARS = {
31591
31792
  openrouter: "OPENROUTER_API_KEY",
31592
31793
  openai: "OPENAI_API_KEY",
@@ -31620,10 +31821,10 @@ async function readSavedProviderKey(provider, env = process.env) {
31620
31821
  async function saveProviderKey(provider, key, env = process.env) {
31621
31822
  const path = providerKeyStorePath(env);
31622
31823
  const store = { ...await readProviderKeyStore(env), [provider]: key };
31623
- await mkdir8(dirname10(path), { recursive: true, mode: 448 });
31824
+ await mkdir8(dirname11(path), { recursive: true, mode: 448 });
31624
31825
  await writeFile8(path, `${JSON.stringify(store, null, 2)}
31625
31826
  `, { mode: 384 });
31626
- await chmod4(path, 384);
31827
+ await chmod5(path, 384);
31627
31828
  }
31628
31829
  function providerKeyFromEnvironment(provider, env = process.env) {
31629
31830
  const primary = env[PROVIDER_KEY_ENV_VARS[provider]]?.trim();
@@ -31658,7 +31859,7 @@ function operatorSecretResolver(env = process.env) {
31658
31859
  if (saved)
31659
31860
  return saved;
31660
31861
  }
31661
- const raw = await readFile12(resolve16(dirname11(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
31862
+ const raw = await readFile12(resolve16(dirname12(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
31662
31863
  if (!raw)
31663
31864
  return void 0;
31664
31865
  try {
@@ -32230,7 +32431,7 @@ async function readHarnessTurnUsage(input) {
32230
32431
  import { randomUUID as randomUUID7 } from "node:crypto";
32231
32432
  import { mkdir as mkdir9, writeFile as writeFile9 } from "node:fs/promises";
32232
32433
  import { tmpdir as tmpdir5 } from "node:os";
32233
- import { dirname as dirname12, join as join8 } from "node:path";
32434
+ import { dirname as dirname13, join as join8 } from "node:path";
32234
32435
  var CommandExecutionContext = class {
32235
32436
  generationId = randomUUID7();
32236
32437
  path;
@@ -32240,7 +32441,7 @@ var CommandExecutionContext = class {
32240
32441
  }
32241
32442
  async enter(command) {
32242
32443
  this.current = command;
32243
- await mkdir9(dirname12(this.path), { recursive: true });
32444
+ await mkdir9(dirname13(this.path), { recursive: true });
32244
32445
  await writeFile9(this.path, JSON.stringify({
32245
32446
  roomId: command.roomId,
32246
32447
  requestId: command.turnRequestId,
@@ -32337,6 +32538,9 @@ async function runServerCommandIntake(options) {
32337
32538
  continue;
32338
32539
  pending.delete(command.id);
32339
32540
  claimed.add(command.id);
32541
+ const startingTurn = command.action !== "restart" && command.action !== "stop";
32542
+ if (startingTurn)
32543
+ options.onClaiming?.(command);
32340
32544
  try {
32341
32545
  await api.execute("claimAgentCommand", {
32342
32546
  roomId,
@@ -32345,6 +32549,8 @@ async function runServerCommandIntake(options) {
32345
32549
  });
32346
32550
  } catch (error) {
32347
32551
  claimed.delete(command.id);
32552
+ if (startingTurn)
32553
+ options.onClaimFailed?.(command);
32348
32554
  options.onError?.(error);
32349
32555
  continue;
32350
32556
  }
@@ -32408,7 +32614,7 @@ import { execFile as execFile11 } from "node:child_process";
32408
32614
  import { createHash as createHash9 } from "node:crypto";
32409
32615
  import { mkdir as mkdir18, readFile as readFile19, writeFile as writeFile14 } from "node:fs/promises";
32410
32616
  import { homedir as homedir14, hostname } from "node:os";
32411
- import { dirname as dirname16, join as join13, resolve as resolve28 } from "node:path";
32617
+ import { dirname as dirname17, join as join13, resolve as resolve28 } from "node:path";
32412
32618
  import { promisify as promisify7 } from "node:util";
32413
32619
 
32414
32620
  // apps/body/dist/agent-home.js
@@ -33211,9 +33417,9 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
33211
33417
 
33212
33418
  // apps/body/dist/agent-home.js
33213
33419
  import { createHash as createHash7, randomUUID as randomUUID8 } from "node:crypto";
33214
- import { chmod as chmod5, copyFile, lstat as lstat3, mkdir as mkdir11, readFile as readFile16, readlink, readdir as readdir5, realpath, rename as rename5, rm as rm6, symlink as symlink2, unlink as unlink5, writeFile as writeFile11 } from "node:fs/promises";
33420
+ import { chmod as chmod6, copyFile, lstat as lstat3, mkdir as mkdir11, readFile as readFile16, readlink, readdir as readdir5, realpath, rename as rename5, rm as rm6, symlink as symlink2, unlink as unlink5, writeFile as writeFile11 } from "node:fs/promises";
33215
33421
  import { homedir as homedir13 } from "node:os";
33216
- import { basename as basename4, dirname as dirname13, join as join10, relative as relative2, resolve as resolve21, sep } from "node:path";
33422
+ import { basename as basename5, dirname as dirname14, join as join10, relative as relative2, resolve as resolve21, sep } from "node:path";
33217
33423
 
33218
33424
  // apps/body/dist/draw-avatar-skill.js
33219
33425
  var DRAW_AVATAR_SKILL_NAME = "draw-avatar";
@@ -34534,7 +34740,7 @@ async function repairRoomAgentCredentialLinks(input) {
34534
34740
  if (!existsSync7(source))
34535
34741
  continue;
34536
34742
  const target = resolve21(root, credential.dir, credential.target);
34537
- await mkdir11(dirname13(target), { recursive: true, mode: 448 });
34743
+ await mkdir11(dirname14(target), { recursive: true, mode: 448 });
34538
34744
  const stats = await lstat3(target).catch((error) => {
34539
34745
  if (isMissingPathError(error))
34540
34746
  return void 0;
@@ -34542,7 +34748,7 @@ async function repairRoomAgentCredentialLinks(input) {
34542
34748
  });
34543
34749
  if (stats?.isSymbolicLink()) {
34544
34750
  const linked = await readlink(target);
34545
- if (resolve21(dirname13(target), linked) === source)
34751
+ if (resolve21(dirname14(target), linked) === source)
34546
34752
  continue;
34547
34753
  }
34548
34754
  if (stats) {
@@ -34999,8 +35205,8 @@ function readJsonObject(path) {
34999
35205
  }
35000
35206
  }
35001
35207
  async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
35002
- const parent = dirname13(target);
35003
- await assertRealContainedDirectory(parent, dirname13(parent));
35208
+ const parent = dirname14(target);
35209
+ await assertRealContainedDirectory(parent, dirname14(parent));
35004
35210
  const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
35005
35211
  if (await materializedSkillManifest(target) === plan.manifest)
35006
35212
  return;
@@ -35221,7 +35427,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
35221
35427
  const stats = await lstat3(resolvedSource);
35222
35428
  if (stats.isSymbolicLink())
35223
35429
  throw new Error(`shared skill contains a symlink: ${source}`);
35224
- if (BLOCKED_SHARED_FILENAMES.test(basename4(source))) {
35430
+ if (BLOCKED_SHARED_FILENAMES.test(basename5(source))) {
35225
35431
  throw new Error(`shared skill contains credential or configuration material: ${source}`);
35226
35432
  }
35227
35433
  if (stats.isDirectory()) {
@@ -35246,20 +35452,20 @@ async function copySafeSkillTree(source, target, sourceRoot) {
35246
35452
  file: async (rel, realPath) => {
35247
35453
  const destination = resolve21(target, rel);
35248
35454
  await copyFile(realPath, destination);
35249
- await chmod5(destination, 384);
35455
+ await chmod6(destination, 384);
35250
35456
  }
35251
35457
  });
35252
35458
  }
35253
35459
  async function writeIsolatedHarnessFile(path, content) {
35254
- const parent = dirname13(path);
35460
+ const parent = dirname14(path);
35255
35461
  const parentStats = await lstat3(parent);
35256
35462
  if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
35257
35463
  throw new Error(`isolated harness parent is not a real directory: ${parent}`);
35258
35464
  }
35259
- const temporary = resolve21(parent, `.${basename4(path)}.${process.pid}.${randomUUID8()}.tmp`);
35465
+ const temporary = resolve21(parent, `.${basename5(path)}.${process.pid}.${randomUUID8()}.tmp`);
35260
35466
  try {
35261
35467
  await writeFile11(temporary, content, { mode: 384, flag: "wx" });
35262
- await chmod5(temporary, 384);
35468
+ await chmod6(temporary, 384);
35263
35469
  await rename5(temporary, path);
35264
35470
  } finally {
35265
35471
  await unlink5(temporary).catch(() => void 0);
@@ -35324,7 +35530,7 @@ function agentCommandCatalogPublisher(input) {
35324
35530
 
35325
35531
  // apps/body/dist/attachment-delivery.js
35326
35532
  import { mkdir as mkdir12, writeFile as writeFile12 } from "node:fs/promises";
35327
- import { basename as basename5, extname, join as join11 } from "node:path";
35533
+ import { basename as basename6, extname, join as join11 } from "node:path";
35328
35534
  var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
35329
35535
  var EXPIRED_REASON = "expired: these attachment bytes are past their retention window";
35330
35536
  var FETCH_TIMEOUT_MS = 3e4;
@@ -35354,7 +35560,7 @@ async function fetchBoundedBytes(url, fetchImpl = fetch) {
35354
35560
  }
35355
35561
  var MAX_INLINE_IMAGE_BYTES = 5 * 1024 * 1024;
35356
35562
  function safeFileName(attachment, index, taken) {
35357
- const raw = basename5(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
35563
+ const raw = basename6(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
35358
35564
  let name = raw || `attachment-${index + 1}`;
35359
35565
  if (taken.has(name)) {
35360
35566
  const ext = extname(name);
@@ -35807,7 +36013,7 @@ function distillTurnFailureReason(error) {
35807
36013
  const clean4 = redactToolDetail(stripped).trim();
35808
36014
  const text2 = !clean4 ? "turn failed" : clean4.length > TURN_FAILURE_REASON_MAX ? `${clean4.slice(0, TURN_FAILURE_REASON_MAX - 1)}\u2026` : clean4;
35809
36015
  const classified = classifyTurnSilence(redactToolDetail(informative.join(" ")).replace(/\s+/g, " ") || text2);
35810
- const kind = classified.kind === "wrong-model" ? "model-selection-unavailable" : classified.kind;
36016
+ const kind = classified.kind === "wrong-model" ? "model-selection-unavailable" : classified.kind === "not-signed-in" ? "hiccup" : classified.kind;
35811
36017
  return { text: text2, kind };
35812
36018
  }
35813
36019
 
@@ -36379,14 +36585,14 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
36379
36585
  // apps/body/dist/codegraph.js
36380
36586
  import { execFile as execFile10 } from "node:child_process";
36381
36587
  import { access as access2, appendFile, mkdir as mkdir14, readFile as readFile17 } from "node:fs/promises";
36382
- import { dirname as dirname14, isAbsolute as isAbsolute3, resolve as resolve24 } from "node:path";
36588
+ import { dirname as dirname15, isAbsolute as isAbsolute3, resolve as resolve24 } from "node:path";
36383
36589
  import { promisify as promisify6 } from "node:util";
36384
36590
  var execFileAsync6 = promisify6(execFile10);
36385
36591
  var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
36386
36592
  var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
36387
36593
  var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
36388
36594
  function codegraphIndexDirectory(cwd) {
36389
- return resolve24(cwd, dirname14(CODEGRAPH_INDEX_PATH));
36595
+ return resolve24(cwd, dirname15(CODEGRAPH_INDEX_PATH));
36390
36596
  }
36391
36597
  function codegraphMcpServer(config, cwd, options) {
36392
36598
  if (!config.codegraphCommand)
@@ -36427,7 +36633,7 @@ async function excludeIndexFromGitStatus(cwd) {
36427
36633
  if (!gitPath)
36428
36634
  return;
36429
36635
  const path = isAbsolute3(gitPath) ? gitPath : resolve24(cwd, gitPath);
36430
- await mkdir14(dirname14(path), { recursive: true });
36636
+ await mkdir14(dirname15(path), { recursive: true });
36431
36637
  const existing = await readFile17(path, "utf8").catch(() => "");
36432
36638
  if (existing.split("\n").includes(".codegraph/"))
36433
36639
  return;
@@ -36607,6 +36813,7 @@ var CORNER_REVIEWER_UNSTABLE_HEAD_INSTRUCTION = "There is no stable green PR hea
36607
36813
  var CORNER_DELIVERY_NUDGE = "Before ending this turn, inspect the repository state and finish delivering the work unless a human hold stands: commit and push the intended changes and open the pull request if one does not exist. Decide yourself whether any remaining dirty work belongs to the objective; do not discard it merely to make the worktree clean. The pull request body must carry ## Reproduced and ## Demonstrated; if they are missing, add them before ending the turn.";
36608
36814
  var CORNER_YOLO_MERGE_NUDGE = 'Yolo is on. Call pr_checks_status now and merge this pull request with gh pr merge --squash --match-head-commit <sha> only when it returns checks="passed" and mergeAllowed=true. If checks="unknown", reply in this corner with the tool reason and stop instead of retrying. Otherwise stop without merging.';
36609
36815
  var RESEARCH_CORNER_HOLD = "This is a research corner with writable repository access. Investigate and edit files as needed. Do not commit, push, or open a pull request until a human explicitly directs that step. Never merge. Leave the corner open; only a human closes it.";
36816
+ var UPGRADE_INTENT_RULE = "Call this only while answering a human message, in this same corner, that clearly conveys intent to change the code \u2014 a bug report, a requested change, or a problem described for you to fix, not a specific required phrase. Never call it from an earlier message, or your own initiative.";
36610
36817
  var handle = (value) => value.replace(/^@/, "");
36611
36818
  function cornerMergeInstruction(yoloMode, reviewerHandle) {
36612
36819
  if (!reviewerHandle)
@@ -36859,7 +37066,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
36859
37066
  surfaces: ["no-code-corner"],
36860
37067
  render: ({ agentMayUpgradeCorner }) => [
36861
37068
  "This is a no-code corner with no repository checkout and no GitHub workflow. Work in this corner's writable workspace: create files with write_scratch_file or your own tools, then send them with post_artifact.",
36862
- agentMayUpgradeCorner ? "Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks. The one exception is beeline-agent upgrade_corner_to_code: call it only when the human message you are currently answering explicitly asks for code edits in this same corner. That one-way upgrade restarts this same corner with a feature branch and writable checkout, keeps its discussion, and re-delivers that same request in the code session, so end this turn immediately once it succeeds and do not edit this workspace. Never call it from an implied request, an earlier message, or your own initiative." : "Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks."
37069
+ agentMayUpgradeCorner ? `Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks. The one exception is beeline-agent upgrade_corner_to_code. ${UPGRADE_INTENT_RULE} That one-way upgrade restarts this same corner with a feature branch and writable checkout, keeps its discussion, and re-delivers that same request in the code session, so end this turn immediately once it succeeds and do not edit this workspace.` : "Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks."
36863
37070
  ].join("\n")
36864
37071
  },
36865
37072
  {
@@ -37144,7 +37351,7 @@ async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
37144
37351
  // apps/body/dist/turn-trace.js
37145
37352
  import { appendFile as appendFile2, mkdir as mkdir15, readdir as readdir6, rm as rm7 } from "node:fs/promises";
37146
37353
  import { resolve as resolve25 } from "node:path";
37147
- import { performance as performance2 } from "node:perf_hooks";
37354
+ import { performance as performance3 } from "node:perf_hooks";
37148
37355
  var TURN_PHASES = [
37149
37356
  /** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
37150
37357
  "queue-wait",
@@ -37183,7 +37390,7 @@ var TurnTrace = class {
37183
37390
  toolCallIds = /* @__PURE__ */ new Set();
37184
37391
  constructor(options) {
37185
37392
  this.options = options;
37186
- this.now = options.now ?? (() => performance2.now());
37393
+ this.now = options.now ?? (() => performance3.now());
37187
37394
  this.begunAt = this.now();
37188
37395
  this.attempts.push(this.newAttempt(1));
37189
37396
  }
@@ -37238,6 +37445,10 @@ var TurnTrace = class {
37238
37445
  noteActivation(kind) {
37239
37446
  this.current.activation = kind;
37240
37447
  }
37448
+ /** How this turn's institutional-memory snapshot fetch resolved (see the field's own doc). */
37449
+ noteInstitutionalMemory(outcome) {
37450
+ this.current.institutionalMemory = outcome;
37451
+ }
37241
37452
  /** What each section of the assembled prompt cost, so growth shows in the trace. */
37242
37453
  notePromptSections(report) {
37243
37454
  this.promptSections = Object.fromEntries(report.map((entry) => [entry.id, entry.bytes]));
@@ -37335,6 +37546,7 @@ var TurnTrace = class {
37335
37546
  ...attempt.capacityWait ? { capacityWait: true } : {},
37336
37547
  ...attempt.provider ? { provider: attempt.provider } : {},
37337
37548
  ...attempt.retryReason ? { retryReason: attempt.retryReason } : {},
37549
+ ...attempt.institutionalMemory ? { institutionalMemory: attempt.institutionalMemory } : {},
37338
37550
  phases: Object.fromEntries(TURN_PHASES.filter((phase) => attempt.phases.has(phase)).map((phase) => [
37339
37551
  phase,
37340
37552
  round(attempt.phases.get(phase))
@@ -37379,6 +37591,8 @@ function formatTurnAttempt(attempt) {
37379
37591
  parts.push("capacity-wait");
37380
37592
  if (attempt.provider)
37381
37593
  parts.push(`provider ${attempt.provider}`);
37594
+ if (attempt.institutionalMemory)
37595
+ parts.push(`memory ${attempt.institutionalMemory}`);
37382
37596
  for (const phase of TURN_PHASES) {
37383
37597
  const value = attempt.phases[phase];
37384
37598
  if (value === void 0)
@@ -37440,7 +37654,7 @@ var TurnTraceFile = class {
37440
37654
  };
37441
37655
 
37442
37656
  // apps/body/dist/corner-github-auth.js
37443
- import { chmod as chmod6, mkdir as mkdir16, writeFile as writeFile13 } from "node:fs/promises";
37657
+ import { chmod as chmod7, mkdir as mkdir16, writeFile as writeFile13 } from "node:fs/promises";
37444
37658
  import { delimiter as delimiter2, resolve as resolve26 } from "node:path";
37445
37659
  async function installCornerGitHubWrappers(input) {
37446
37660
  const bin = resolve26(input.root, "beeline-github-bin");
@@ -37592,14 +37806,14 @@ if (result.error) throw result.error;
37592
37806
  process.exit(result.status ?? 1);
37593
37807
  `;
37594
37808
  await writeFile13(path, source, { mode: 448 });
37595
- await chmod6(path, 448);
37809
+ await chmod7(path, 448);
37596
37810
  }
37597
37811
 
37598
37812
  // apps/body/dist/warm-node-modules.js
37599
37813
  import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
37600
37814
  import { constants as fsConstants3 } from "node:fs";
37601
- import { chmod as chmod7, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir17, readdir as readdir7, readFile as readFile18, readlink as readlink2, rename as rename6, rm as rm8, stat as stat6, symlink as symlink3, utimes } from "node:fs/promises";
37602
- import { dirname as dirname15, join as join12, resolve as resolve27 } from "node:path";
37815
+ import { chmod as chmod8, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir17, readdir as readdir7, readFile as readFile18, readlink as readlink2, rename as rename6, rm as rm8, stat as stat6, symlink as symlink3, utimes } from "node:fs/promises";
37816
+ import { dirname as dirname16, join as join12, resolve as resolve27 } from "node:path";
37603
37817
  var STORE_FORMAT = "v1";
37604
37818
  var STAGING_PREFIX = ".beeline-warm-";
37605
37819
  var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
@@ -37684,7 +37898,7 @@ async function seedWarmNodeModules(input) {
37684
37898
  }
37685
37899
  for (const tree of plan.trees) {
37686
37900
  const target = resolve27(input.worktreePath, tree);
37687
- await mkdir17(dirname15(target), { recursive: true });
37901
+ await mkdir17(dirname16(target), { recursive: true });
37688
37902
  await rename6(resolve27(staging, tree), target);
37689
37903
  placed.push(target);
37690
37904
  }
@@ -37834,7 +38048,7 @@ async function cloneTree(source, target, file, topLevel = true) {
37834
38048
  var harvestFile = async (source, target) => {
37835
38049
  await copyFile2(source, target, fsConstants3.COPYFILE_FICLONE);
37836
38050
  const info = await stat6(source);
37837
- await chmod7(target, info.mode & 4095 & ~146);
38051
+ await chmod8(target, info.mode & 4095 & ~146);
37838
38052
  };
37839
38053
  var seedFile = async (source, target, topLevel) => {
37840
38054
  if (!topLevel) {
@@ -37842,7 +38056,7 @@ var seedFile = async (source, target, topLevel) => {
37842
38056
  return;
37843
38057
  }
37844
38058
  await copyFile2(source, target);
37845
- await chmod7(target, 420);
38059
+ await chmod8(target, 420);
37846
38060
  };
37847
38061
  async function pruneWarmStore(storeRoot, keep) {
37848
38062
  const names = (await readdir7(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
@@ -38403,7 +38617,7 @@ var MonolithCornerTurnLoop = class {
38403
38617
  }) ? { relay: await this.squireRelay.listen() } : {}
38404
38618
  };
38405
38619
  const resourceAuthFile = `${this.commandContext.path}.resource-auth.json`;
38406
- await mkdir18(dirname16(resourceAuthFile), { recursive: true, mode: 448 });
38620
+ await mkdir18(dirname17(resourceAuthFile), { recursive: true, mode: 448 });
38407
38621
  await writeFile14(resourceAuthFile, JSON.stringify({
38408
38622
  ...this.options.api.connection(),
38409
38623
  turnContextPath: this.commandContext.path
@@ -38498,7 +38712,10 @@ var MonolithCornerTurnLoop = class {
38498
38712
  cargoTargetDir,
38499
38713
  ...registryMcpHostBindPaths(configuration.registryMcpRoutes)
38500
38714
  ],
38501
- maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
38715
+ maskPaths: [
38716
+ ...credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome),
38717
+ ...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
38718
+ ]
38502
38719
  },
38503
38720
  command,
38504
38721
  args: agentArgs
@@ -38617,13 +38834,35 @@ var MonolithCornerTurnLoop = class {
38617
38834
  this.sessionId = opened.sessionId;
38618
38835
  this.sessionFingerprint = fingerprint;
38619
38836
  this.sessionCodegraphReady = codegraphReady;
38837
+ let appliedModel;
38620
38838
  if (selection) {
38621
38839
  const options = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(opened.raw, selection.model));
38622
- await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
38840
+ const applied = await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
38841
+ appliedModel = applied.appliedSelection.model;
38842
+ if (selection.model && appliedModel && appliedModel !== selection.model) {
38843
+ this.recordModelFallback(applied.appliedSelection, applied.options);
38844
+ }
38623
38845
  }
38624
- this.sessionModel = selection?.model ?? null;
38846
+ this.sessionModel = appliedModel ?? selection?.model ?? null;
38625
38847
  return opened.sessionId;
38626
38848
  }
38849
+ /**
38850
+ * A vanished model id was just substituted for a same-family replacement
38851
+ * (`resolveModelFamilyFallback`) so THIS turn could proceed instead of
38852
+ * failing it. Persist the correction so the phone stops offering the dead
38853
+ * id and the durable `model_unavailable` flag stays clear, and let the
38854
+ * server (`daemon-service.ts`'s `modelCatalog`) name the change in the
38855
+ * agent's DM — fire-and-forget: a slow or failed report must never hold up
38856
+ * or fail a turn that already succeeded with the fallback model applied.
38857
+ */
38858
+ recordModelFallback(appliedSelection, options) {
38859
+ this.options.api.execute("postAgentModelCatalog", {
38860
+ agentId: this.agent.publicKey,
38861
+ workspaceId: this.options.workspaceId,
38862
+ options,
38863
+ selection: appliedSelection
38864
+ }).catch((error) => console.error(`[thin-core] failed to persist automatic model fallback for corner ${this.options.cornerId}:`, error));
38865
+ }
38627
38866
  /**
38628
38867
  * Resolve the review target at prompt time, not session activation time.
38629
38868
  *
@@ -38769,6 +39008,7 @@ var MonolithCornerTurnLoop = class {
38769
39008
  } : void 0;
38770
39009
  this.currentTurn = { requestId, ...requester ? { requester } : {} };
38771
39010
  const trace = this.beginTurnTrace(requestId);
39011
+ const institutionalContextFetch = startInstitutionalContextFetch(api, cornerId);
38772
39012
  let deliberateNoReply = false;
38773
39013
  let laneUpgraded = false;
38774
39014
  try {
@@ -38797,8 +39037,9 @@ var MonolithCornerTurnLoop = class {
38797
39037
  this.roster(),
38798
39038
  api.execute("getCornerRestoreState", { cornerId }),
38799
39039
  this.activeReviewerInstruction(),
38800
- institutionalContextForTurn(api, cornerId, (message) => console.warn(`[thin-core] corner ${cornerId}: ${message}`))
39040
+ awaitInstitutionalContext(institutionalContextFetch, (message) => console.warn(`[thin-core] corner ${cornerId}: ${message}`))
38801
39041
  ]));
39042
+ trace.noteInstitutionalMemory(institutionalContext.outcome);
38802
39043
  const briefAttachments = (restored.brief?.attachments ?? []).map((file) => ({
38803
39044
  url: new URL(`/v1/media/${file.objectId}`, api.baseUrl).toString(),
38804
39045
  name: file.title,
@@ -39240,6 +39481,17 @@ var MonolithCornerTurnLoop = class {
39240
39481
  this.options.onIntakeError?.(error);
39241
39482
  console.error("[thin-core] corner command failed", error);
39242
39483
  },
39484
+ // See monolith-room-turn.ts (C112): mark busy the instant a claim
39485
+ // attempt starts, before its own network round trip and before
39486
+ // context.enter()'s own file I/O, so a reconcile busy-check landing
39487
+ // anywhere in that window can never see this corner as idle when a
39488
+ // turn was already claimed (or about to be).
39489
+ onClaiming: () => {
39490
+ this.busy = true;
39491
+ },
39492
+ onClaimFailed: () => {
39493
+ this.busy = false;
39494
+ },
39243
39495
  onEnter: (command) => this.squireRelay.activate(command, this.commandContext.generationId),
39244
39496
  onLeave: (command) => this.squireRelay.deactivate(command.turnRequestId),
39245
39497
  stop: (requestId) => this.stopTurn(requestId),
@@ -39280,7 +39532,7 @@ var MonolithCornerTurnLoop = class {
39280
39532
  // apps/body/dist/monolith-room-turn.js
39281
39533
  import { mkdir as mkdir19, writeFile as writeFile15 } from "node:fs/promises";
39282
39534
  import { homedir as homedir15, hostname as hostname2 } from "node:os";
39283
- import { dirname as dirname17, join as join15 } from "node:path";
39535
+ import { dirname as dirname18, join as join15 } from "node:path";
39284
39536
 
39285
39537
  // packages/api-contract/dist/scheduled-prompts.js
39286
39538
  var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
@@ -39478,7 +39730,10 @@ var MonolithRoomTurnLoop = class {
39478
39730
  ...this.options.config.bwrapPath ? { bwrapPath: this.options.config.bwrapPath } : {},
39479
39731
  ...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {},
39480
39732
  ...this.sessionStateDirs.length ? { harnessStateDirs: this.sessionStateDirs } : {},
39481
- maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir15())
39733
+ maskPaths: [
39734
+ ...credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir15()),
39735
+ ...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
39736
+ ]
39482
39737
  };
39483
39738
  }
39484
39739
  /**
@@ -39728,7 +39983,7 @@ var MonolithRoomTurnLoop = class {
39728
39983
  }) ? { relay: await this.squireRelay.listen() } : {}
39729
39984
  };
39730
39985
  const resourceAuthFile = `${this.commandContext.path}.resource-auth.json`;
39731
- await mkdir19(dirname17(resourceAuthFile), { recursive: true, mode: 448 });
39986
+ await mkdir19(dirname18(resourceAuthFile), { recursive: true, mode: 448 });
39732
39987
  await writeFile15(resourceAuthFile, JSON.stringify({
39733
39988
  ...this.options.api.connection(),
39734
39989
  turnContextPath: this.commandContext.path
@@ -39803,7 +40058,10 @@ var MonolithRoomTurnLoop = class {
39803
40058
  ...codegraphReady ? [codegraphIndexDirectory(this.options.cwd)] : [],
39804
40059
  ...registryMcpHostBindPaths(configuration.registryMcpRoutes)
39805
40060
  ],
39806
- maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
40061
+ maskPaths: [
40062
+ ...credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome),
40063
+ ...siblingAgentMaskPaths(runtimeDirectory(this.options.runtime.supervisorRoot, this.options.runtime.agent.publicKey))
40064
+ ]
39807
40065
  },
39808
40066
  command,
39809
40067
  args: agentArgs
@@ -39909,10 +40167,30 @@ var MonolithRoomTurnLoop = class {
39909
40167
  this.sessionCodegraphReady = codegraphReady;
39910
40168
  if (selection) {
39911
40169
  const options = filterAllowedModelConfigOptions(parseAdvertisedConfigOptions(opened.raw, selection.model));
39912
- await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
40170
+ const applied = await applyAgentModelSelection(this.client, opened.sessionId, options, selection);
40171
+ if (selection.model && applied.appliedSelection.model && applied.appliedSelection.model !== selection.model) {
40172
+ this.recordModelFallback(applied.appliedSelection, applied.options);
40173
+ }
39913
40174
  }
39914
40175
  return opened.sessionId;
39915
40176
  }
40177
+ /**
40178
+ * A vanished model id was just substituted for a same-family replacement
40179
+ * (`resolveModelFamilyFallback`) so THIS turn could proceed instead of
40180
+ * failing it. Persist the correction so the phone stops offering the dead
40181
+ * id and the durable `model_unavailable` flag stays clear, and let the
40182
+ * server (`daemon-service.ts`'s `modelCatalog`) name the change in the
40183
+ * agent's DM — fire-and-forget: a slow or failed report must never hold up
40184
+ * or fail a turn that already succeeded with the fallback model applied.
40185
+ */
40186
+ recordModelFallback(appliedSelection, options) {
40187
+ this.options.api.execute("postAgentModelCatalog", {
40188
+ agentId: this.agent.publicKey,
40189
+ workspaceId: this.options.workspaceId,
40190
+ options,
40191
+ selection: appliedSelection
40192
+ }).catch((error) => console.error(`[thin-core] failed to persist automatic model fallback for Room ${this.options.roomId}:`, error));
40193
+ }
39916
40194
  /**
39917
40195
  * The scheduler seam, and the only place that can see the boundary between
39918
40196
  * waiting for a slot and spawning a harness: `queue-wait` closes the instant
@@ -40031,6 +40309,7 @@ var MonolithRoomTurnLoop = class {
40031
40309
  this.busy = true;
40032
40310
  this.turnMetrics = {};
40033
40311
  const trace = this.beginTurnTrace(item.id);
40312
+ const institutionalContextFetch = startInstitutionalContextFetch(api, this.options.roomId);
40034
40313
  let liveStream;
40035
40314
  let liveCornerOpened = false;
40036
40315
  try {
@@ -40070,8 +40349,9 @@ var MonolithRoomTurnLoop = class {
40070
40349
  this.roster(),
40071
40350
  this.deliver(item),
40072
40351
  api.execute("listRoomCorners", { roomId: this.options.roomId }),
40073
- institutionalContextForTurn(api, this.options.roomId, (message) => console.warn(`[thin-core] Room ${this.options.roomId}: ${message}`))
40352
+ awaitInstitutionalContext(institutionalContextFetch, (message) => console.warn(`[thin-core] Room ${this.options.roomId}: ${message}`))
40074
40353
  ]));
40354
+ trace.noteInstitutionalMemory(institutionalContext.outcome);
40075
40355
  const names = new Map(roster.members.map((member) => [member.identityId, member.name]));
40076
40356
  const transcriptRows = conversation.items.filter((message) => message.type === "message" && message.id !== item.id && !active.steers.some((steerItem) => steerItem.id === message.id)).slice(-80).map((message) => ({
40077
40357
  id: message.id,
@@ -40327,6 +40607,18 @@ var MonolithRoomTurnLoop = class {
40327
40607
  this.options.onIntakeError?.(error);
40328
40608
  console.error("[thin-core] Room command failed", error);
40329
40609
  },
40610
+ // Marks this loop busy the instant it attempts to claim a real
40611
+ // turn, before the claim's own network round trip and before
40612
+ // context.enter()'s own file I/O - closing the window where
40613
+ // RoomRuntimeCoordinator.reconcile's repository-revision restart
40614
+ // could see a claiming-but-not-yet-`busy` Room as idle and stop it,
40615
+ // cancelling a turn that had already begun (or was about to) (C112).
40616
+ onClaiming: () => {
40617
+ this.busy = true;
40618
+ },
40619
+ onClaimFailed: () => {
40620
+ this.busy = false;
40621
+ },
40330
40622
  onEnter: (command) => this.squireRelay.activate(command, this.commandContext.generationId),
40331
40623
  onLeave: (command) => this.squireRelay.deactivate(command.turnRequestId, this.pausedOnGrantRequestId),
40332
40624
  stop: (requestId) => this.stopTurn(requestId),
@@ -40913,8 +41205,8 @@ async function materializeCornerWorktree(input) {
40913
41205
  const remote = roomCheckoutRemote(input.remote);
40914
41206
  const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
40915
41207
  const path = resolve29(input.supervisorRoot, "beeline", "corners", input.cornerId);
40916
- await mkdir20(dirname18(gitCommonDir), { recursive: true, mode: 448 });
40917
- await mkdir20(dirname18(path), { recursive: true, mode: 448 });
41208
+ await mkdir20(dirname19(gitCommonDir), { recursive: true, mode: 448 });
41209
+ await mkdir20(dirname19(path), { recursive: true, mode: 448 });
40918
41210
  const authEnv = githubGitEnv(input.token);
40919
41211
  if (!existsSync8(resolve29(gitCommonDir, "HEAD"))) {
40920
41212
  await execFileAsync8("git", ["clone", "--bare", remote, gitCommonDir], {
@@ -41035,7 +41327,7 @@ async function mapWithConcurrency(values, limit, visit) {
41035
41327
  async function discoverCornerWorktree(supervisorRoot, cornerId) {
41036
41328
  const cornersRoot = resolve29(supervisorRoot, "beeline", "corners");
41037
41329
  const path = resolve29(cornersRoot, cornerId);
41038
- if (dirname18(path) !== cornersRoot || !existsSync8(resolve29(path, ".git")))
41330
+ if (dirname19(path) !== cornersRoot || !existsSync8(resolve29(path, ".git")))
41039
41331
  return void 0;
41040
41332
  const [canonicalRoot, canonicalPath] = await Promise.all([
41041
41333
  realpath2(cornersRoot),
@@ -41605,7 +41897,7 @@ var RoomRuntimeCoordinator = class {
41605
41897
  return this.runtime.rooms.find((room) => room.channelId === roomId);
41606
41898
  }
41607
41899
  roomRoot(roomId) {
41608
- return this.roomRecord(roomId)?.root ?? resolve29(dirname18(this.configPath), "rooms", roomId);
41900
+ return this.roomRecord(roomId)?.root ?? resolve29(dirname19(this.configPath), "rooms", roomId);
41609
41901
  }
41610
41902
  roomAgentHomeRoot(workspaceRoot, required = false) {
41611
41903
  const flag = process.env.BUZZY_BODY_ROOM_HOME;
@@ -41628,9 +41920,9 @@ var RoomRuntimeCoordinator = class {
41628
41920
  ...this.baseConfig,
41629
41921
  workspaceRoot,
41630
41922
  agentPrivateRoot: resolve29(workspaceRoot, "agent-private"),
41631
- agentMemoryRoot: resolve29(dirname18(this.configPath), "memory"),
41632
- openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname18(this.configPath)),
41633
- turnTraceDir: turnTraceDirectory(dirname18(this.configPath)),
41923
+ agentMemoryRoot: resolve29(dirname19(this.configPath), "memory"),
41924
+ openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname19(this.configPath)),
41925
+ turnTraceDir: turnTraceDirectory(dirname19(this.configPath)),
41634
41926
  ...agentHomeRoot ? { agentHomeRoot } : {}
41635
41927
  };
41636
41928
  }
@@ -41726,7 +42018,7 @@ var RoomRuntimeCoordinator = class {
41726
42018
  const targetBranch = repository.targetBranch || "main";
41727
42019
  const checkoutId = createHash10("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
41728
42020
  const path = resolve29(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
41729
- await mkdir20(dirname18(path), { recursive: true, mode: 448 });
42021
+ await mkdir20(dirname19(path), { recursive: true, mode: 448 });
41730
42022
  const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
41731
42023
  const env = token ? githubGitEnv(token.token) : process.env;
41732
42024
  if (!existsSync8(resolve29(path, ".git"))) {
@@ -42638,7 +42930,7 @@ init_systemd();
42638
42930
  import { spawn as spawn11 } from "node:child_process";
42639
42931
  import { createHash as createHash11 } from "node:crypto";
42640
42932
  import { mkdir as mkdir23, rm as rm11, stat as stat7, writeFile as writeFile17 } from "node:fs/promises";
42641
- import { dirname as dirname20, resolve as resolve33 } from "node:path";
42933
+ import { dirname as dirname21, resolve as resolve33 } from "node:path";
42642
42934
 
42643
42935
  // apps/body/dist/update-functional-probe.js
42644
42936
  import { mkdir as mkdir21, rm as rm10 } from "node:fs/promises";
@@ -42825,7 +43117,10 @@ async function runUpdateFunctionalProbe(input) {
42825
43117
  cwd,
42826
43118
  harnessStateDirs: stateDirs,
42827
43119
  harnessHomeStateDirs: homeStateDirs,
42828
- maskPaths: credentialMaskPaths(input.config.sandboxMaskPaths, operatorHome),
43120
+ maskPaths: [
43121
+ ...credentialMaskPaths(input.config.sandboxMaskPaths, operatorHome),
43122
+ ...siblingAgentMaskPaths(input.runtimeDir)
43123
+ ],
42829
43124
  ...tmpDir ? { tmpDir } : {}
42830
43125
  },
42831
43126
  command,
@@ -42972,7 +43267,7 @@ async function runUpdateFunctionalProbe(input) {
42972
43267
 
42973
43268
  // apps/body/dist/update-rollback-alert.js
42974
43269
  import { mkdir as mkdir22, readFile as readFile21, rename as rename7, unlink as unlink6, writeFile as writeFile16 } from "node:fs/promises";
42975
- import { dirname as dirname19, resolve as resolve32 } from "node:path";
43270
+ import { dirname as dirname20, resolve as resolve32 } from "node:path";
42976
43271
  var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
42977
43272
  var lastLogged = /* @__PURE__ */ new Map();
42978
43273
  function updateRollbackAlertPath(runtimeDir) {
@@ -42981,7 +43276,7 @@ function updateRollbackAlertPath(runtimeDir) {
42981
43276
  async function writeAlert(runtimeDir, alert) {
42982
43277
  const path = updateRollbackAlertPath(runtimeDir);
42983
43278
  const staged = `${path}.${process.pid}.tmp`;
42984
- await mkdir22(dirname19(path), { recursive: true });
43279
+ await mkdir22(dirname20(path), { recursive: true });
42985
43280
  await writeFile16(staged, `${JSON.stringify(alert, null, 2)}
42986
43281
  `, { mode: 384 });
42987
43282
  await rename7(staged, path);
@@ -43054,7 +43349,7 @@ async function withInstallLock(layout, work, options = {}) {
43054
43349
  const now2 = options.now ?? Date.now;
43055
43350
  const lock = resolve33(layout.releasesRoot, ".state", "install.lock");
43056
43351
  const deadline = now2() + (options.waitMs ?? 1e4);
43057
- await mkdir23(dirname20(lock), { recursive: true });
43352
+ await mkdir23(dirname21(lock), { recursive: true });
43058
43353
  for (; ; ) {
43059
43354
  try {
43060
43355
  await mkdir23(lock);
@@ -43680,7 +43975,7 @@ init_launchd();
43680
43975
  init_systemd();
43681
43976
  init_runtime();
43682
43977
  import { mkdir as mkdir24, rename as rename8 } from "node:fs/promises";
43683
- import { dirname as dirname21, resolve as resolve34 } from "node:path";
43978
+ import { dirname as dirname22, resolve as resolve34 } from "node:path";
43684
43979
  async function retireRemovedAgent(runtime, options = {}) {
43685
43980
  const deletedRoot = resolve34(runtime.supervisorRoot, "beeline", "deleted-runtimes");
43686
43981
  const target = resolve34(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
@@ -43703,13 +43998,13 @@ async function relocateAgentRuntime(runtime, target, options = {}) {
43703
43998
  ...options.run ? { run: options.run } : {}
43704
43999
  });
43705
44000
  }
43706
- await mkdir24(dirname21(destination), { recursive: true, mode: 448 });
44001
+ await mkdir24(dirname22(destination), { recursive: true, mode: 448 });
43707
44002
  await rename8(source, destination);
43708
44003
  return destination;
43709
44004
  }
43710
44005
 
43711
44006
  // apps/body/dist/start-command.js
43712
- import { basename as basename6, dirname as dirname22 } from "node:path";
44007
+ import { basename as basename7, dirname as dirname23 } from "node:path";
43713
44008
  var import_picocolors2 = __toESM(require_picocolors(), 1);
43714
44009
  init_agent_command();
43715
44010
  init_runtime();
@@ -43924,7 +44219,7 @@ async function startStoredRuntime(configPath, opts = {}, dependencyOverrides = {
43924
44219
  return { status: "started", pid };
43925
44220
  }
43926
44221
  function agentStartId(configPath) {
43927
- return basename6(dirname22(configPath));
44222
+ return basename7(dirname23(configPath));
43928
44223
  }
43929
44224
  async function startRuntime(configPath, spinnerHandle) {
43930
44225
  const report = (text2) => spinnerHandle ? spinnerHandle.message(text2) : console.log(text2);
@@ -44005,7 +44300,7 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
44005
44300
  for (const path of unique) {
44006
44301
  const id = agentStartId(path);
44007
44302
  const spinnerHandle = interactiveUi ? spinner() : void 0;
44008
- spinnerHandle?.start(`Starting ${dirname22(path)}\u2026`);
44303
+ spinnerHandle?.start(`Starting ${dirname23(path)}\u2026`);
44009
44304
  try {
44010
44305
  const outcome = await deps.startOne(path, spinnerHandle);
44011
44306
  const report = { id, path, ...outcome };
@@ -44039,9 +44334,9 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
44039
44334
  // apps/body/dist/connect-command.js
44040
44335
  import { spawn as spawn12 } from "node:child_process";
44041
44336
  import { createHash as createHash12, randomUUID as randomUUID10 } from "node:crypto";
44042
- import { chmod as chmod8, mkdir as mkdir25, readFile as readFile22, unlink as unlink7, writeFile as writeFile18 } from "node:fs/promises";
44337
+ import { chmod as chmod9, mkdir as mkdir25, readFile as readFile22, unlink as unlink7, writeFile as writeFile18 } from "node:fs/promises";
44043
44338
  import { homedir as homedir17, hostname as hostname3 } from "node:os";
44044
- import { dirname as dirname23, resolve as resolve35 } from "node:path";
44339
+ import { dirname as dirname24, resolve as resolve35 } from "node:path";
44045
44340
  import { stdin as stdin3, stdout as stdout4 } from "node:process";
44046
44341
  init_access_policy();
44047
44342
  init_agent_command();
@@ -44530,7 +44825,7 @@ async function loadConnectModelCatalog(input, dependencies = {}) {
44530
44825
  ...effort ? { effort } : {}
44531
44826
  };
44532
44827
  }
44533
- var CONNECT_PROBE_TIMEOUT_MS = 12e3;
44828
+ var CONNECT_PROBE_TIMEOUT_MS = 25e3;
44534
44829
  function connectProbeFoundModels(catalog) {
44535
44830
  return catalog.note === void 0 && catalog.options.length > 0;
44536
44831
  }
@@ -44588,13 +44883,17 @@ async function collectConnectWizard(prompts = clackPrompts, loadModels = loadCon
44588
44883
  return (picked ?? "").trim();
44589
44884
  };
44590
44885
  const probe = async (candidate) => {
44886
+ const spinner2 = spinner({ output: clackPromptOutput() });
44887
+ spinner2.start(brass(`Checking ${connectHarnessLabel(candidate)}\u2026`));
44591
44888
  try {
44592
44889
  const catalog2 = await loadModels({
44593
44890
  harness: candidate,
44594
44891
  timeoutMs: CONNECT_PROBE_TIMEOUT_MS
44595
44892
  });
44893
+ spinner2.stop();
44596
44894
  return connectProbeFoundModels(catalog2) ? catalog2 : void 0;
44597
44895
  } catch {
44896
+ spinner2.stop();
44598
44897
  return void 0;
44599
44898
  }
44600
44899
  };
@@ -44805,21 +45104,21 @@ function providerEnvironment(selection) {
44805
45104
  };
44806
45105
  }
44807
45106
  async function writePrivateJson(path, value) {
44808
- await mkdir25(dirname23(path), { recursive: true, mode: 448 });
45107
+ await mkdir25(dirname24(path), { recursive: true, mode: 448 });
44809
45108
  await writeFile18(path, `${JSON.stringify(value, null, 2)}
44810
45109
  `, { mode: 384 });
44811
- await chmod8(path, 384);
45110
+ await chmod9(path, 384);
44812
45111
  }
44813
45112
  async function writeProviderEnv(selection, agentPubkey) {
44814
45113
  const values = providerEnvironment(selection);
44815
45114
  if (Object.keys(values).length === 0)
44816
45115
  return void 0;
44817
45116
  const path = resolve35(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
44818
- await mkdir25(dirname23(path), { recursive: true, mode: 448 });
45117
+ await mkdir25(dirname24(path), { recursive: true, mode: 448 });
44819
45118
  const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
44820
45119
  await writeFile18(path, `${contents}
44821
45120
  `, { mode: 384 });
44822
- await chmod8(path, 384);
45121
+ await chmod9(path, 384);
44823
45122
  return path;
44824
45123
  }
44825
45124
  async function runInstalledFinish(binary, grantPath) {
@@ -44980,7 +45279,7 @@ async function runConnectFinishCommand(path) {
44980
45279
  if (model) {
44981
45280
  const decision2 = await resolveOpenRouterRouting({
44982
45281
  model,
44983
- cacheDir: openRouterRoutingCacheDir(dirname23(connected.configPath)),
45282
+ cacheDir: openRouterRoutingCacheDir(dirname24(connected.configPath)),
44984
45283
  ...apiKey ? { apiKey } : {},
44985
45284
  probeTimeoutMs: 1e4
44986
45285
  });
@@ -44999,7 +45298,7 @@ init_self_update();
44999
45298
 
45000
45299
  // apps/body/dist/daemon-failure.js
45001
45300
  import { mkdir as mkdir26, readFile as readFile23, rename as rename9, rm as rm12, writeFile as writeFile19 } from "node:fs/promises";
45002
- import { dirname as dirname24, resolve as resolve36 } from "node:path";
45301
+ import { dirname as dirname25, resolve as resolve36 } from "node:path";
45003
45302
  var DAEMON_FAILURE_LIMIT = 3;
45004
45303
  var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
45005
45304
  function daemonFailurePath(runtimeDir) {
@@ -45019,7 +45318,7 @@ async function readFailureRecord(runtimeDir) {
45019
45318
  async function writeFailureRecord(runtimeDir, record6) {
45020
45319
  const path = daemonFailurePath(runtimeDir);
45021
45320
  const staged = `${path}.${process.pid}.tmp`;
45022
- await mkdir26(dirname24(path), { recursive: true, mode: 448 });
45321
+ await mkdir26(dirname25(path), { recursive: true, mode: 448 });
45023
45322
  await writeFile19(staged, `${JSON.stringify(record6, null, 2)}
45024
45323
  `, { mode: 384 });
45025
45324
  await rename9(staged, path);
@@ -45046,7 +45345,7 @@ init_systemd();
45046
45345
 
45047
45346
  // apps/body/dist/current-release-probe.js
45048
45347
  import { spawn as spawn13 } from "node:child_process";
45049
- import { dirname as dirname25, join as join16 } from "node:path";
45348
+ import { dirname as dirname26, join as join16 } from "node:path";
45050
45349
  init_runtime();
45051
45350
  init_self_update();
45052
45351
  var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
@@ -45153,7 +45452,7 @@ async function runUpdateProbeCommand(args, options = {}) {
45153
45452
  const runtime = await readRuntimeRecord(configPath);
45154
45453
  const agent = runtimeAgentCommand(runtime);
45155
45454
  const config = loadBodyConfig({
45156
- workspaceRoot: join16(dirname25(configPath), "workspace"),
45455
+ workspaceRoot: join16(dirname26(configPath), "workspace"),
45157
45456
  llmEnvFile: runtime.llmEnvFile,
45158
45457
  env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
45159
45458
  agent
@@ -45171,7 +45470,7 @@ async function runUpdateProbeCommand(args, options = {}) {
45171
45470
  }
45172
45471
  const layout = beelineInstallLayout(env);
45173
45472
  const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
45174
- const runtimeDir = dirname25(configPath);
45473
+ const runtimeDir = dirname26(configPath);
45175
45474
  const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
45176
45475
  config,
45177
45476
  runtimeDir,
@@ -45342,7 +45641,8 @@ var DaemonExitError = class extends Error {
45342
45641
  };
45343
45642
  async function runStoredDaemon(pathOrPointer) {
45344
45643
  const configPath = await resolveRuntimeConfigPath(pathOrPointer);
45345
- daemonFailureRuntimeDir = dirname26(configPath);
45644
+ daemonFailureRuntimeDir = dirname27(configPath);
45645
+ await convergeRuntimeRecordFileModes(configPath);
45346
45646
  const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
45347
45647
  let runtime = accessMigration.runtime;
45348
45648
  if (!runtime.transport) {
@@ -45376,7 +45676,7 @@ async function runStoredDaemon(pathOrPointer) {
45376
45676
  BUZZ_DEV_MCP_BIN: runtime.mcpBinary
45377
45677
  };
45378
45678
  const config = loadBodyConfig({
45379
- workspaceRoot: resolve39(dirname26(configPath), "workspace"),
45679
+ workspaceRoot: resolve39(dirname27(configPath), "workspace"),
45380
45680
  llmEnvFile: runtime.llmEnvFile,
45381
45681
  env,
45382
45682
  agent
@@ -45392,8 +45692,10 @@ async function runStoredDaemon(pathOrPointer) {
45392
45692
  }
45393
45693
  if (runtime.sharedSkills)
45394
45694
  config.sharedSkills = [...runtime.sharedSkills];
45395
- if (runtime.modelSelection) {
45396
- await applyRuntimeModelPreflight(config, agent, runtime.modelSelection, void 0, refreshRuntimeAdapter);
45695
+ const serverModelSelection = await daemonApi.execute("getAgentConfiguration", { agentId: runtime.agent.publicKey }).then((result) => result.model || result.effort ? { ...result.model ? { model: result.model } : {}, ...result.effort ? { effort: result.effort } : {} } : void 0).catch(() => void 0);
45696
+ const preflightModelSelection = resolvePreflightModelSelection(runtime.modelSelection, serverModelSelection);
45697
+ if (preflightModelSelection) {
45698
+ await applyRuntimeModelPreflight(config, agent, preflightModelSelection, void 0, refreshRuntimeAdapter);
45397
45699
  if (!config.modelUnavailable) {
45398
45700
  console.log("[body] persisted model/effort selection passed live startup validation");
45399
45701
  } else {
@@ -45403,7 +45705,7 @@ async function runStoredDaemon(pathOrPointer) {
45403
45705
  config.runtimeConfigPath = configPath;
45404
45706
  const sandbox = await ensureBwrapSandbox({
45405
45707
  ...runtime.sandbox ? { policy: runtime.sandbox } : {},
45406
- stateDir: dirname26(configPath),
45708
+ stateDir: dirname27(configPath),
45407
45709
  beforeInstall: () => extendSystemdStartTimeout(BUBBLEWRAP_INSTALL_BUDGET_MS)
45408
45710
  });
45409
45711
  if (sandbox.path)
@@ -45415,7 +45717,7 @@ async function runStoredDaemon(pathOrPointer) {
45415
45717
  }
45416
45718
  const controller = new AbortController();
45417
45719
  const disposeStopSignals = installDaemonStopSignals(controller);
45418
- const runtimeDir = dirname26(configPath);
45720
+ const runtimeDir = dirname27(configPath);
45419
45721
  const layout = beelineInstallLayout(process.env);
45420
45722
  const notifier = new SystemdNotifier();
45421
45723
  let rollbackAlertDrain;
@@ -45862,7 +46164,7 @@ async function main() {
45862
46164
  }
45863
46165
  if (!configPath && agentPubkey) {
45864
46166
  const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
45865
- configPath = configs.find((candidate) => dirname26(candidate).endsWith(agentPubkey));
46167
+ configPath = configs.find((candidate) => dirname27(candidate).endsWith(agentPubkey));
45866
46168
  }
45867
46169
  if (!configPath && agentPubkey) {
45868
46170
  throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing service restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
@@ -45890,7 +46192,7 @@ async function main() {
45890
46192
  if (!agentPubkey)
45891
46193
  throw new Error("stop requires --agent <pubkey>");
45892
46194
  const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
45893
- const configPath = configs.find((candidate) => dirname26(candidate).endsWith(agentPubkey));
46195
+ const configPath = configs.find((candidate) => dirname27(candidate).endsWith(agentPubkey));
45894
46196
  if (!configPath)
45895
46197
  throw new Error(`no stored runtime found for agent ${agentPubkey}`);
45896
46198
  const runtime = await readRuntimeRecord(configPath);