@cortexkit/anthropic-auth-core 2.2.1 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -241,7 +241,7 @@ async function select(terminal, items, options) {
241
241
  import { createHash, randomBytes, randomUUID as randomUUID4 } from "node:crypto";
242
242
  import { constants as fsConstants } from "node:fs";
243
243
  import { chmod, mkdir as mkdir3, open as open3, readFile as readFile3, realpath, rename as rename4, stat as stat2, unlink as unlink2 } from "node:fs/promises";
244
- import { basename, dirname as dirname4, extname, isAbsolute, join as join2, resolve as resolve2 } from "node:path";
244
+ import { basename, dirname as dirname4, extname, isAbsolute, join as join3, resolve as resolve2 } from "node:path";
245
245
  import { ClaustrumCredentialError, ClaustrumClient as ClaustrumWireClient, writeEnrollmentTokenFile } from "@cortexkit/claustrum-client";
246
246
 
247
247
  // ../../node_modules/@cortexkit/common-auth/dist/fs/atomic-write.js
@@ -252,7 +252,8 @@ import { dirname as dirname2 } from "node:path";
252
252
  // ../../node_modules/@cortexkit/common-auth/dist/fs/private-files.js
253
253
  import { randomUUID } from "node:crypto";
254
254
  import { lstat, readFile, rename, unlink } from "node:fs/promises";
255
- import { dirname, resolve } from "node:path";
255
+ import { tmpdir } from "node:os";
256
+ import { dirname, join, resolve } from "node:path";
256
257
  var windowsPrivateFiles = process.platform === "win32";
257
258
  var migrationNotices = new Set;
258
259
  function ioCode(detail) {
@@ -265,8 +266,32 @@ function ioCode(detail) {
265
266
  return detail?.code ?? "ERR_PRIVATE_FILE";
266
267
  }
267
268
  var backend;
269
+ var PRIVATE_FILES_UNAVAILABLE_REASON = "native-addon-unavailable";
270
+ function privateFilesUnavailable(cause) {
271
+ return Object.assign(new Error("Windows private-files native addon is unavailable", { cause }), {
272
+ code: "ERR_PRIVATE_FILES_UNAVAILABLE",
273
+ reason: PRIVATE_FILES_UNAVAILABLE_REASON
274
+ });
275
+ }
276
+ function isUnavailable(api, error) {
277
+ return error instanceof api.PrivateFilesUnavailableError || error?.code === "ERR_PRIVATE_FILES_UNAVAILABLE";
278
+ }
279
+ async function assertNativeAddonLoads(api) {
280
+ try {
281
+ await api.verifyPrivatePath(join(tmpdir(), `.common-auth-private-files-probe-${randomUUID()}`), "file");
282
+ } catch (error) {
283
+ if (isUnavailable(api, error))
284
+ throw privateFilesUnavailable(error);
285
+ }
286
+ }
268
287
  function loadBackend() {
269
- backend ??= import("@cortexkit/private-files");
288
+ backend ??= import("@cortexkit/private-files").then(async (api) => {
289
+ if (windowsPrivateFiles)
290
+ await assertNativeAddonLoads(api);
291
+ return api;
292
+ }, (cause) => {
293
+ throw windowsPrivateFiles ? privateFilesUnavailable(cause) : cause;
294
+ });
270
295
  return backend;
271
296
  }
272
297
 
@@ -284,7 +309,7 @@ class PrivateFileError extends Error {
284
309
  orphanPath;
285
310
  constructor(path, stage, cause) {
286
311
  const detail = cause;
287
- super(`Private file refused at ${stage}: ${path} (${detail?.reason ?? detail?.code ?? "io-error"}). Use a safe parent directory. Repair only a named secret file in safe ancestry whose owner the published policy trusts, without changing its owner or any existing directory. Previously exposed credentials may need rotation. Windows requires the private-files native prebuild and an ACL-persisting local filesystem such as NTFS.`, { cause });
312
+ super(detail?.code === "ERR_PRIVATE_FILES_UNAVAILABLE" ? `Private file refused at ${stage}: ${path} (${PRIVATE_FILES_UNAVAILABLE_REASON}). The Windows native addon of @cortexkit/private-files could not be loaded, so owner-only access cannot be enforced and nothing was read or written. Reinstall the plugin so the private-files Windows prebuild for this architecture is present; Windows has no safe fallback to permission bits.` : `Private file refused at ${stage}: ${path} (${detail?.reason ?? detail?.code ?? "io-error"}). Keep this file in a folder that only you, the system or administrators can change, such as a folder in your home directory. If other users could read the file before, sign in again to replace the credentials it held. On Windows the file must also be on a local drive that keeps Windows file permissions, such as NTFS.`, { cause });
288
313
  this.path = path;
289
314
  this.stage = stage;
290
315
  this.name = "PrivateFileError";
@@ -617,7 +642,7 @@ var WRITER_LOCK_CONSTANTS = Object.freeze({
617
642
  // ../../node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.js
618
643
  import { randomUUID as randomUUID3 } from "node:crypto";
619
644
  import { mkdir as mkdir2, open as open2, readFile as readFile2, rename as rename3, rm as rm2, stat } from "node:fs/promises";
620
- import { dirname as dirname3, join } from "node:path";
645
+ import { dirname as dirname3, join as join2 } from "node:path";
621
646
 
622
647
  // ../../node_modules/@cortexkit/common-auth/dist/fs/with-lock.js
623
648
  function lockPathFor(target, name) {
@@ -644,6 +669,7 @@ class LockOwnershipError extends Error {
644
669
  async function withLock(target, options, fn) {
645
670
  const started = performance.now();
646
671
  for (;; ) {
672
+ options.signal?.throwIfAborted();
647
673
  const lock = await acquireRefreshFileLock({
648
674
  path: target,
649
675
  name: options.name,
@@ -654,6 +680,7 @@ async function withLock(target, options, fn) {
654
680
  });
655
681
  if (lock) {
656
682
  try {
683
+ options.signal?.throwIfAborted();
657
684
  return await fn(lock);
658
685
  } finally {
659
686
  await lock.release();
@@ -691,7 +718,7 @@ function acquireRefreshFileLock(options) {
691
718
  }
692
719
  async function acquireRefreshFileLockWithClock(options) {
693
720
  const lockPath = lockPathFor(options.path, options.name);
694
- const legacyOwnerPath = join(lockPath, "owner.json");
721
+ const legacyOwnerPath = join2(lockPath, "owner.json");
695
722
  const ownerId = randomUUID3();
696
723
  const now = options.now ?? Date.now;
697
724
  let renewTimer = null;
@@ -732,7 +759,7 @@ async function acquireRefreshFileLockWithClock(options) {
732
759
  let terminalIOError;
733
760
  let renewalInFlight = null;
734
761
  const evictPath = `${lockPath}.evicting`;
735
- const evictOwnerPath = join(evictPath, "owner.json");
762
+ const evictOwnerPath = join2(evictPath, "owner.json");
736
763
  const evictOwnerId = randomUUID3();
737
764
  const EVICT_TTL = 5000;
738
765
  const MAX_STEAL_ATTEMPTS = 8;
@@ -1296,7 +1323,9 @@ var ENROLLMENT_SCHEMA = 1;
1296
1323
  var ENROLLMENT_FILE_MAX_BYTES = 16 * 1024;
1297
1324
  var ENROLLMENT_LOCK_TTL_MS = 30000;
1298
1325
  var TOKEN_RE = /^[0-9a-f]{64}$/;
1326
+ var UNSUPPORTED_ENROLLMENT_CODE = "unknown_method";
1299
1327
  var TERMINAL_ENROLLMENT_CODES = new Set([
1328
+ UNSUPPORTED_ENROLLMENT_CODE,
1300
1329
  "invalid_params",
1301
1330
  "pending_exists",
1302
1331
  "not_found",
@@ -1326,7 +1355,7 @@ function getClaustrumEnrollmentPaths(tokenPath) {
1326
1355
  const extension = extname(tokenPath) || ".json";
1327
1356
  const stem = basename(tokenPath, extname(tokenPath));
1328
1357
  return {
1329
- statePath: join2(dirname4(tokenPath), `${stem}-state${extension}`),
1358
+ statePath: join3(dirname4(tokenPath), `${stem}-state${extension}`),
1330
1359
  tokenPath
1331
1360
  };
1332
1361
  }
@@ -1334,7 +1363,7 @@ function hostEnrollmentPaths(input) {
1334
1363
  const override = input.override?.trim();
1335
1364
  if (override && !isAbsolute(override) && !input.cwd)
1336
1365
  throw new ClaustrumConsumerError("invalid-state", "A relative Claustrum enrollment override needs a base directory");
1337
- const tokenPath = override ? isAbsolute(override) ? override : resolve2(input.cwd, override) : join2(input.stateDir, `${input.host}-enrollment.json`);
1366
+ const tokenPath = override ? isAbsolute(override) ? override : resolve2(input.cwd, override) : join3(input.stateDir, `${input.host}-enrollment.json`);
1338
1367
  return getClaustrumEnrollmentPaths(tokenPath);
1339
1368
  }
1340
1369
  function isRecord(value) {
@@ -1570,7 +1599,7 @@ async function writeStateAtomic(path, state, ancestorOptions = {}) {
1570
1599
  }
1571
1600
  if (windowsPrivateFiles)
1572
1601
  return writePrivateAtomic(path, bytes);
1573
- const temporary = join2(parent, `.${basename(path)}.${process.pid}.${randomUUID4()}.tmp`);
1602
+ const temporary = join3(parent, `.${basename(path)}.${process.pid}.${randomUUID4()}.tmp`);
1574
1603
  let descriptor;
1575
1604
  let created = false;
1576
1605
  try {
@@ -1799,6 +1828,18 @@ class ClaustrumEnrollmentManager {
1799
1828
  retryCode: refusal.code
1800
1829
  };
1801
1830
  }
1831
+ if (refusal.code === UNSUPPORTED_ENROLLMENT_CODE) {
1832
+ await lock.assertOwned();
1833
+ await unlink2(this.#paths.statePath).catch((cause) => {
1834
+ if (cause.code !== "ENOENT")
1835
+ throw cause;
1836
+ });
1837
+ return {
1838
+ state: "unavailable",
1839
+ proposedName: state.proposedName,
1840
+ code: refusal.code
1841
+ };
1842
+ }
1802
1843
  return this.#block(state, refusal.code);
1803
1844
  }
1804
1845
  }
@@ -2187,8 +2228,8 @@ function setupEnrollment(error) {
2187
2228
  // ../../node_modules/@cortexkit/common-auth/dist/setup/detect.js
2188
2229
  import { accessSync, constants, existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2189
2230
  import { mkdtemp, rm as rm3 } from "node:fs/promises";
2190
- import { tmpdir } from "node:os";
2191
- import { join as join3 } from "node:path";
2231
+ import { tmpdir as tmpdir2 } from "node:os";
2232
+ import { join as join4 } from "node:path";
2192
2233
  import { parse } from "jsonc-parser";
2193
2234
 
2194
2235
  // ../../node_modules/@cortexkit/common-auth/dist/setup/paths.js
@@ -2357,7 +2398,7 @@ async function detectHosts(plugin, io = {}) {
2357
2398
  return null;
2358
2399
  let root;
2359
2400
  try {
2360
- root = await mkdtemp(join3(tmpdir(), "common-auth-setup-version-"));
2401
+ root = await mkdtemp(join4(tmpdir2(), "common-auth-setup-version-"));
2361
2402
  const probeEnv = {
2362
2403
  ...env,
2363
2404
  HOME: root,
@@ -2425,6 +2466,8 @@ import { writeEnrollmentTokenFile as writeEnrollmentTokenFile2 } from "@cortexki
2425
2466
  var WINDOWS_CIM_TIMEOUT_MS = 45000;
2426
2467
  var HOSTS = new Set(["opencode", "litecode", "opencode2", "pi"]);
2427
2468
  var RUNTIMES = new Set(["node", "bun"]);
2469
+ var WINDOWS_FENCE_FILTER = [...HOSTS, ...RUNTIMES].map((name) => `Name LIKE '${name}%'`).join(" OR ");
2470
+ var WINDOWS_FENCE_QUERY = `$ErrorActionPreference = 'Stop'; $rows = @(Get-CimInstance Win32_Process -Filter "${WINDOWS_FENCE_FILTER}" | Select-Object Name,ProcessId,CommandLine); ConvertTo-Json -Compress -Depth 3 -InputObject @{ complete = $true; processes = $rows }`;
2428
2471
  var PI_SCRIPT_PATTERN = /(?:^|[/\\])pi-coding-agent[/\\]dist[/\\](?:(?:bundle|bun)[/\\])?cli\.m?js$/i;
2429
2472
  function commandArguments(command) {
2430
2473
  return [...command.matchAll(/"([^"]*)"|(\S+)/g)].map((match) => match[1] ?? match[2] ?? "");
@@ -2530,6 +2573,7 @@ Please quit all OpenCode, LiteCode, and Pi processes before running setup.`);
2530
2573
  }
2531
2574
  async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2532
2575
  const windows = (options.platform ?? process.platform) === "win32";
2576
+ const selfPid = options.selfPid ?? process.pid;
2533
2577
  let inspection = {
2534
2578
  step: windows ? "tasklist" : "ps",
2535
2579
  exitCode: null,
@@ -2566,6 +2610,29 @@ async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2566
2610
  }
2567
2611
  };
2568
2612
  try {
2613
+ if (windows && options.hostImagesOnly) {
2614
+ const details = await inspect("CIM", "powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", WINDOWS_FENCE_QUERY], WINDOWS_CIM_TIMEOUT_MS);
2615
+ if (details.exitCode !== 0)
2616
+ throw new ProcessInspectionError(inspection);
2617
+ const value = JSON.parse(details.stdout);
2618
+ if (!value || typeof value !== "object" || !("complete" in value) || value.complete !== true || !("processes" in value))
2619
+ throw new ProcessInspectionError(inspection);
2620
+ const listed = value.processes;
2621
+ const rows = listed === null ? [] : Array.isArray(listed) ? listed : [listed];
2622
+ const processes2 = [];
2623
+ for (const row of rows) {
2624
+ if (!row || typeof row !== "object" || !("Name" in row) || typeof row.Name !== "string" || !("ProcessId" in row) || !Number.isSafeInteger(row.ProcessId) || row.ProcessId < 0 || !("CommandLine" in row))
2625
+ throw new ProcessInspectionError(inspection);
2626
+ const pid = row.ProcessId;
2627
+ if (!/^(?:node|bun)\.exe$/i.test(row.Name))
2628
+ processes2.push({ pid, command: row.Name });
2629
+ else if (typeof row.CommandLine === "string")
2630
+ processes2.push({ pid, command: row.CommandLine });
2631
+ else if (pid !== selfPid)
2632
+ throw new ProcessInspectionError(inspection);
2633
+ }
2634
+ return processes2;
2635
+ }
2569
2636
  const result = await inspect(windows ? "tasklist" : "ps", windows ? "tasklist.exe" : "ps", windows ? ["/fo", "csv", "/nh"] : ["-eo", "pid,command"]);
2570
2637
  if (result.exitCode !== 0)
2571
2638
  throw new ProcessInspectionError(inspection);
@@ -2598,7 +2665,7 @@ async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2598
2665
  }
2599
2666
  if (!processes.length)
2600
2667
  throw new ProcessInspectionError(inspection);
2601
- const runtimes = processes.filter((entry) => entry.pid !== process.pid && /^(?:node|bun)\.exe$/i.test(entry.command));
2668
+ const runtimes = processes.filter((entry) => entry.pid !== selfPid && /^(?:node|bun)\.exe$/i.test(entry.command));
2602
2669
  if (windows && runtimes.length && options.inspectRuntimes !== false) {
2603
2670
  const details = await inspect("CIM", "powershell.exe", [
2604
2671
  "-NoProfile",
@@ -2631,10 +2698,15 @@ async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2631
2698
  }
2632
2699
  }
2633
2700
  function createProcessFence(runner = defaultCommandRunner, options = {}) {
2634
- const isHost = (entry) => entry.pid !== process.pid && hostName(entry.command) !== null;
2701
+ const selfPid = options.selfPid ?? process.pid;
2702
+ const isHost = (entry) => entry.pid !== selfPid && hostName(entry.command) !== null;
2635
2703
  return {
2636
2704
  async listRunningHosts(env) {
2637
- return (await listSetupProcesses(runner, { ...options, env })).filter(isHost);
2705
+ return (await listSetupProcesses(runner, {
2706
+ ...options,
2707
+ env,
2708
+ hostImagesOnly: true
2709
+ })).filter(isHost);
2638
2710
  },
2639
2711
  async previewRunningHosts(env) {
2640
2712
  const processes = await listSetupProcesses(runner, {
@@ -2645,7 +2717,7 @@ function createProcessFence(runner = defaultCommandRunner, options = {}) {
2645
2717
  const windows = (options.platform ?? process.platform) === "win32";
2646
2718
  return {
2647
2719
  hosts: processes.filter(isHost),
2648
- uncheckedRuntimes: windows ? processes.filter((entry) => entry.pid !== process.pid && /^(?:node|bun)\.exe$/i.test(entry.command)).length : 0
2720
+ uncheckedRuntimes: windows ? processes.filter((entry) => entry.pid !== selfPid && /^(?:node|bun)\.exe$/i.test(entry.command)).length : 0
2649
2721
  };
2650
2722
  }
2651
2723
  };
@@ -2658,8 +2730,27 @@ async function assertHostsStopped(fence, env) {
2658
2730
 
2659
2731
  // ../../node_modules/@cortexkit/common-auth/dist/setup/enroll.js
2660
2732
  var ENROLLMENT_INCOMPLETE_MESSAGE = "Claustrum enrollment did not complete. Inspect and approve with ck, then rerun setup.";
2733
+ var UNSUPPORTED_VAULT_MESSAGE = "This Claustrum vault does not support connecting plugins yet, so setup cannot connect to it. Run setup without --claustrum to use local accounts.";
2734
+ var ENROLLMENT_WAIT_MS = 300000;
2735
+ var APPROVAL_POLL_MS = 1000;
2736
+ var PROPOSE_BACKOFF_MS = [1000, 2000, 4000, 8000, 16000, 30000];
2737
+ function safeCode(code) {
2738
+ return code && /^[a-z][a-z0-9_]{0,63}$/.test(code) ? code : "unknown";
2739
+ }
2661
2740
 
2662
2741
  class HostNotEnrolledError extends Error {
2742
+ reason;
2743
+ lastErrorCode;
2744
+ constructor(message, details) {
2745
+ super(message);
2746
+ this.name = "HostNotEnrolledError";
2747
+ this.reason = details.reason;
2748
+ if (details.lastErrorCode !== undefined)
2749
+ this.lastErrorCode = safeCode(details.lastErrorCode);
2750
+ }
2751
+ }
2752
+ function approveCommand(requestId, name) {
2753
+ return `ck auth enroll approve --request-id ${requestId} --name ${name}`;
2663
2754
  }
2664
2755
  async function connectSetupHost(plugin, host, io, terminal, fence) {
2665
2756
  const { name, paths: input } = plugin.vault.hosts[host];
@@ -2669,54 +2760,89 @@ async function connectSetupHost(plugin, host, io, terminal, fence) {
2669
2760
  connectionFile: plugin.vault.connectionFile,
2670
2761
  handshakeTimeoutMs: 2000
2671
2762
  }).catch(() => {
2672
- throw new HostNotEnrolledError("Claustrum connection failed; start ck and rerun setup.");
2763
+ throw new HostNotEnrolledError("Claustrum connection failed; start ck and rerun setup.", { reason: "connection-failed" });
2673
2764
  });
2765
+ const now = io.now ?? (() => performance.now());
2766
+ const wait = io.wait ?? delay;
2674
2767
  try {
2675
2768
  const manager = new ClaustrumEnrollmentManager({
2676
2769
  proposedName: name,
2677
2770
  paths,
2678
- client: {
2679
- enrollPropose: async (input2) => {
2680
- await fence();
2681
- return client.enrollPropose(input2);
2682
- },
2683
- enrollPoll: async (input2) => {
2684
- await fence();
2685
- return client.enrollPoll(input2);
2686
- }
2687
- },
2771
+ client,
2688
2772
  writeTokenFile: async (path, file) => {
2689
2773
  await fence();
2690
2774
  await writeEnrollmentTokenFile2(path, file);
2691
2775
  }
2692
2776
  });
2777
+ printLine(terminal, `Asking the vault to connect ${name}…`);
2778
+ const deadline = now() + ENROLLMENT_WAIT_MS;
2693
2779
  let printedRequest;
2694
- for (let tick = 0;tick < 300; tick++) {
2780
+ let lastCode;
2781
+ let reportedCode;
2782
+ let failedProposals = 0;
2783
+ for (;; ) {
2695
2784
  await fence();
2696
2785
  const status = await manager.reconcile();
2697
2786
  if (status.state === "approved") {
2698
2787
  printLine(terminal, `Connected ${host} to Claustrum.`);
2699
2788
  return;
2700
2789
  }
2790
+ if (status.state === "unavailable" && status.code === UNSUPPORTED_ENROLLMENT_CODE)
2791
+ throw new HostNotEnrolledError(UNSUPPORTED_VAULT_MESSAGE, {
2792
+ reason: "unsupported-vault",
2793
+ lastErrorCode: status.code
2794
+ });
2701
2795
  if (status.state !== "pending" && status.state !== "busy")
2702
- throw new HostNotEnrolledError("Claustrum enrollment refused; inspect its status with ck before rerunning setup.");
2703
- if (status.state === "pending" && status.requestId && status.requestId !== printedRequest) {
2704
- if (!/^[a-zA-Z0-9_-]+$/.test(status.requestId))
2705
- throw new HostNotEnrolledError("Invalid enrollment request id.");
2706
- printedRequest = status.requestId;
2707
- printLine(terminal, "Waiting for approval. In another terminal, run:");
2708
- printLine(terminal, ` ck auth enroll approve --request-id ${status.requestId} --name ${name}`);
2709
- printLine(terminal, `Enrollment files: ${paths.statePath}, ${paths.tokenPath}`);
2710
- }
2711
- await (io.wait ?? delay)(1000);
2712
- }
2713
- throw new HostNotEnrolledError("Claustrum approval is still pending; approve with ck and rerun setup.");
2796
+ throw new HostNotEnrolledError("Claustrum enrollment refused; inspect its status with ck before rerunning setup.", {
2797
+ reason: "refused",
2798
+ ..."code" in status && { lastErrorCode: status.code }
2799
+ });
2800
+ let pause = APPROVAL_POLL_MS;
2801
+ if (status.state === "busy")
2802
+ lastCode = "busy";
2803
+ else if (status.retryCode)
2804
+ lastCode = status.retryCode;
2805
+ if (status.state === "pending" && status.requestId) {
2806
+ failedProposals = 0;
2807
+ if (status.requestId !== printedRequest) {
2808
+ if (!/^[a-zA-Z0-9_-]+$/.test(status.requestId))
2809
+ throw new HostNotEnrolledError("Invalid enrollment request id.", {
2810
+ reason: "invalid-request"
2811
+ });
2812
+ printedRequest = status.requestId;
2813
+ printLine(terminal, "Waiting for approval. In another terminal, run:");
2814
+ printLine(terminal, ` ${approveCommand(status.requestId, name)}`);
2815
+ printLine(terminal, `Enrollment files: ${paths.statePath}, ${paths.tokenPath}`);
2816
+ }
2817
+ } else if (status.state === "pending" && status.retryCode) {
2818
+ pause = PROPOSE_BACKOFF_MS[Math.min(failedProposals, PROPOSE_BACKOFF_MS.length - 1)] ?? APPROVAL_POLL_MS;
2819
+ failedProposals++;
2820
+ const code2 = safeCode(status.retryCode);
2821
+ if (code2 !== reportedCode) {
2822
+ reportedCode = code2;
2823
+ printLine(terminal, `The vault has not created the request yet (${code2}); retrying.`);
2824
+ }
2825
+ }
2826
+ const remaining = deadline - now();
2827
+ if (remaining <= 0)
2828
+ break;
2829
+ await wait(Math.min(pause, remaining));
2830
+ }
2831
+ if (printedRequest)
2832
+ throw new HostNotEnrolledError(`Claustrum approval is still pending. In another terminal, run: ${approveCommand(printedRequest, name)} and then rerun setup.`, {
2833
+ reason: "approval-pending",
2834
+ ...lastCode !== undefined && { lastErrorCode: lastCode }
2835
+ });
2836
+ const code = safeCode(lastCode);
2837
+ throw new HostNotEnrolledError(`The vault never created the enrollment request (last error: ${code}). Check that ck is running, then rerun setup.`, { reason: "request-not-created", lastErrorCode: code });
2714
2838
  } catch (error) {
2715
- if (error instanceof ProcessFenceViolationError || error instanceof ProcessInspectionError)
2839
+ if (error instanceof ProcessFenceViolationError || error instanceof ProcessInspectionError || error instanceof HostNotEnrolledError)
2716
2840
  throw error;
2717
- if (error instanceof HostNotEnrolledError)
2718
- throw new HostNotEnrolledError(ENROLLMENT_INCOMPLETE_MESSAGE);
2719
- throw new Error(ENROLLMENT_INCOMPLETE_MESSAGE);
2841
+ const code = error?.code;
2842
+ throw new HostNotEnrolledError(ENROLLMENT_INCOMPLETE_MESSAGE, {
2843
+ reason: "incomplete",
2844
+ ...typeof code === "string" && { lastErrorCode: code }
2845
+ });
2720
2846
  } finally {
2721
2847
  client.close();
2722
2848
  }
@@ -2754,7 +2880,7 @@ import { applyEdits, createScanner, findNodeAtLocation, modify, parse as parse2,
2754
2880
  // ../../node_modules/@cortexkit/common-auth/dist/setup/config-write.js
2755
2881
  import { randomUUID as randomUUID5 } from "node:crypto";
2756
2882
  import { mkdir as mkdir4, open as open4, rename as rename5, stat as stat4, unlink as unlink3 } from "node:fs/promises";
2757
- import { basename as basename2, dirname as dirname5, join as join4 } from "node:path";
2883
+ import { basename as basename2, dirname as dirname5, join as join5 } from "node:path";
2758
2884
  import { setTimeout as delay2 } from "node:timers/promises";
2759
2885
  async function writeHostConfigAtomic(file, content, options = {}) {
2760
2886
  const windows = (options.platform ?? process.platform) === "win32";
@@ -2769,7 +2895,7 @@ async function writeHostConfigAtomic(file, content, options = {}) {
2769
2895
  throw error;
2770
2896
  }
2771
2897
  }
2772
- const stage = join4(parent, `.${basename2(file)}.${(options.stageName ?? randomUUID5)()}.tmp`);
2898
+ const stage = join5(parent, `.${basename2(file)}.${(options.stageName ?? randomUUID5)()}.tmp`);
2773
2899
  let created = false;
2774
2900
  try {
2775
2901
  const handle = await open4(stage, "wx", mode ?? 438);
@@ -3137,13 +3263,13 @@ ${write.content}`);
3137
3263
  import { createHash as createHash2, randomUUID as randomUUID6 } from "node:crypto";
3138
3264
  import { mkdir as mkdir5, readFile as readFile5, rename as rename6, rm as rm4, stat as stat5, writeFile } from "node:fs/promises";
3139
3265
  import { homedir as homedir2 } from "node:os";
3140
- import { dirname as dirname6, join as join6 } from "node:path";
3266
+ import { dirname as dirname6, join as join7 } from "node:path";
3141
3267
 
3142
3268
  // src/claustrum.ts
3143
3269
  import { readdirSync, statSync as statSync2 } from "node:fs";
3144
3270
  import * as fs from "node:fs/promises";
3145
- import { tmpdir as tmpdir2, userInfo } from "node:os";
3146
- import { join as join5 } from "node:path";
3271
+ import { tmpdir as tmpdir3, userInfo } from "node:os";
3272
+ import { join as join6 } from "node:path";
3147
3273
  function errorCode(error) {
3148
3274
  return error && typeof error === "object" && "code" in error && typeof error.code === "string" ? error.code : "unknown";
3149
3275
  }
@@ -3171,7 +3297,7 @@ function listSubcTempConnectionFiles(dir) {
3171
3297
  if (!name.startsWith(CLAUSTRUM_TEMP_PREFIX) || !name.endsWith(CLAUSTRUM_TEMP_SUFFIX)) {
3172
3298
  continue;
3173
3299
  }
3174
- const candidate = join5(dir, name);
3300
+ const candidate = join6(dir, name);
3175
3301
  if (safeIsFile(candidate))
3176
3302
  matches.push(candidate);
3177
3303
  }
@@ -3181,13 +3307,13 @@ function listSubcTempConnectionFiles(dir) {
3181
3307
  function findExistingClaustrumConnectionPath(env = process.env) {
3182
3308
  const runtime = env.XDG_RUNTIME_DIR?.trim();
3183
3309
  if (runtime) {
3184
- const candidate = join5(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3310
+ const candidate = join6(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3185
3311
  if (safeIsFile(candidate))
3186
3312
  return candidate;
3187
3313
  }
3188
3314
  const home = env.HOME?.trim();
3189
3315
  if (home) {
3190
- const candidate = join5(home, ".local", "share", "cortexkit", "run", PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3316
+ const candidate = join6(home, ".local", "share", "cortexkit", "run", PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3191
3317
  if (safeIsFile(candidate))
3192
3318
  return candidate;
3193
3319
  }
@@ -3195,7 +3321,7 @@ function findExistingClaustrumConnectionPath(env = process.env) {
3195
3321
  const linuxRun = `/run/user/${uid}/${PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME}`;
3196
3322
  if (safeIsFile(linuxRun))
3197
3323
  return linuxRun;
3198
- const tempMatches = listSubcTempConnectionFiles(tmpdir2());
3324
+ const tempMatches = listSubcTempConnectionFiles(tmpdir3());
3199
3325
  if (tempMatches.length === 1)
3200
3326
  return tempMatches[0];
3201
3327
  return;
@@ -3206,11 +3332,11 @@ function getDefaultClaustrumConnectionPath(env = process.env) {
3206
3332
  return existing;
3207
3333
  const runtime = env.XDG_RUNTIME_DIR?.trim();
3208
3334
  if (runtime && (process.platform !== "darwin" || safeIsFile(runtime))) {
3209
- return join5(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3335
+ return join6(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3210
3336
  }
3211
3337
  if (process.platform === "darwin") {
3212
3338
  const home = env.HOME?.trim() || userInfo().homedir;
3213
- return join5(home, ".local", "share", "cortexkit", "run", PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3339
+ return join6(home, ".local", "share", "cortexkit", "run", PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3214
3340
  }
3215
3341
  const uid = process.getuid?.() ?? userInfo().uid;
3216
3342
  return `/run/user/${uid}/${PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME}`;
@@ -3312,6 +3438,345 @@ function assertNotCustodyTombstone(refreshToken, provider) {
3312
3438
  }
3313
3439
  }
3314
3440
 
3441
+ // src/model-capabilities.ts
3442
+ var PER_TURN_CONTROL_BETA = "per-turn-control-2026-07-01";
3443
+ var TURN_END_NOTE_BETA = "mid-conversation-system-clear-at-2026-08-21";
3444
+ var CLAUDE_CODE_BETA = "claude-code-20250219";
3445
+ var PROMPT_CACHING_SCOPE_BETA = "prompt-caching-scope-2026-01-05";
3446
+ var CLAUDE_CODE_FULL_AGENT_BETAS = [
3447
+ CLAUDE_CODE_BETA,
3448
+ "oauth-2025-04-20",
3449
+ "interleaved-thinking-2025-05-14",
3450
+ "thinking-token-count-2026-05-13",
3451
+ "context-management-2025-06-27",
3452
+ PROMPT_CACHING_SCOPE_BETA,
3453
+ "mid-conversation-tool-changes-2026-07-01",
3454
+ "advanced-tool-use-2025-11-20",
3455
+ TURN_END_NOTE_BETA,
3456
+ "effort-2025-11-24",
3457
+ "thinking-binding-controls-2026-08-01",
3458
+ "thinking-display-updates-2026-08-18",
3459
+ "extended-cache-ttl-2025-04-11",
3460
+ "cache-diagnosis-2026-04-07"
3461
+ ];
3462
+ var CLAUDE_CODE_TITLE_BETAS = [
3463
+ "oauth-2025-04-20",
3464
+ "interleaved-thinking-2025-05-14",
3465
+ "redact-thinking-2026-02-12",
3466
+ "thinking-token-count-2026-05-13",
3467
+ "context-management-2025-06-27",
3468
+ PROMPT_CACHING_SCOPE_BETA,
3469
+ "mid-conversation-tool-changes-2026-07-01",
3470
+ TURN_END_NOTE_BETA,
3471
+ "effort-2025-11-24",
3472
+ "cache-diagnosis-2026-04-07"
3473
+ ];
3474
+ var CLAUDE_CODE_QUOTA_BETAS = [
3475
+ "oauth-2025-04-20",
3476
+ "interleaved-thinking-2025-05-14",
3477
+ "redact-thinking-2026-02-12",
3478
+ "thinking-token-count-2026-05-13",
3479
+ "context-management-2025-06-27",
3480
+ PROMPT_CACHING_SCOPE_BETA
3481
+ ];
3482
+ var CLAUDE_CODE_DEFAULT_BETAS = {
3483
+ main: CLAUDE_CODE_FULL_AGENT_BETAS,
3484
+ title: CLAUDE_CODE_TITLE_BETAS,
3485
+ quota: CLAUDE_CODE_QUOTA_BETAS
3486
+ };
3487
+ function claudeCodeBetaLists(options) {
3488
+ const adjust = (list) => {
3489
+ const selected = [...list];
3490
+ if (options.claudeCodeBetaAfterCachingScope) {
3491
+ const codeIndex = selected.indexOf(CLAUDE_CODE_BETA);
3492
+ if (codeIndex >= 0) {
3493
+ selected.splice(codeIndex, 1);
3494
+ selected.splice(selected.indexOf(PROMPT_CACHING_SCOPE_BETA) + 1, 0, CLAUDE_CODE_BETA);
3495
+ }
3496
+ }
3497
+ if (options.perTurnControl) {
3498
+ let index = selected.indexOf(PROMPT_CACHING_SCOPE_BETA);
3499
+ if (index >= 0 && selected[index + 1] === CLAUDE_CODE_BETA)
3500
+ index += 1;
3501
+ if (index >= 0)
3502
+ selected.splice(index + 1, 0, PER_TURN_CONTROL_BETA);
3503
+ else
3504
+ selected.push(PER_TURN_CONTROL_BETA);
3505
+ }
3506
+ return selected;
3507
+ };
3508
+ return {
3509
+ main: adjust(CLAUDE_CODE_FULL_AGENT_BETAS),
3510
+ title: adjust(CLAUDE_CODE_TITLE_BETAS),
3511
+ quota: adjust(CLAUDE_CODE_QUOTA_BETAS)
3512
+ };
3513
+ }
3514
+ var ALL_ADAPTIVE_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
3515
+ var FABLE_MYTHOS_5_CATALOGUE = {
3516
+ releaseDate: "2026-06-09",
3517
+ contextWindow: 1e6,
3518
+ maxOutputTokens: 128000,
3519
+ pricing: {
3520
+ input: 10,
3521
+ output: 50,
3522
+ cacheRead: 1,
3523
+ cacheWrite5m: 12.5,
3524
+ cacheWrite1h: 20
3525
+ }
3526
+ };
3527
+ var FABLE_MYTHOS_5_1_CATALOGUE = {
3528
+ releaseDate: "2026-09-01",
3529
+ contextWindow: 1e6,
3530
+ maxOutputTokens: 128000,
3531
+ pricing: {
3532
+ input: 10,
3533
+ output: 50,
3534
+ cacheRead: 0.25,
3535
+ cacheWrite5m: 12.5,
3536
+ cacheWrite1h: 20
3537
+ }
3538
+ };
3539
+ var CLAUDE_MODEL_CAPABILITIES = [
3540
+ {
3541
+ id: "claude-fable-5",
3542
+ name: "Claude Fable 5",
3543
+ family: "fable",
3544
+ idSuffixes: "any",
3545
+ catalogue: FABLE_MYTHOS_5_CATALOGUE,
3546
+ thinkingModes: ["adaptive"],
3547
+ rejectsForcedToolChoice: false,
3548
+ efforts: { default: "high" },
3549
+ effortMarkers: "none",
3550
+ turnEndNote: false,
3551
+ thinkingBindingControls: false,
3552
+ claudeCodeBetas: CLAUDE_CODE_DEFAULT_BETAS,
3553
+ serverSideFallback: true,
3554
+ refusalRecoveryFamily: "fable-5",
3555
+ scopedQuota: "fable",
3556
+ fastMode: false
3557
+ },
3558
+ {
3559
+ id: "claude-mythos-5",
3560
+ name: "Claude Mythos 5",
3561
+ family: "mythos",
3562
+ idSuffixes: "any",
3563
+ limited: true,
3564
+ catalogue: FABLE_MYTHOS_5_CATALOGUE,
3565
+ thinkingModes: ["adaptive"],
3566
+ rejectsForcedToolChoice: false,
3567
+ efforts: { default: "high" },
3568
+ effortMarkers: "none",
3569
+ turnEndNote: false,
3570
+ thinkingBindingControls: false,
3571
+ claudeCodeBetas: CLAUDE_CODE_DEFAULT_BETAS,
3572
+ serverSideFallback: false,
3573
+ scopedQuota: "mythos",
3574
+ fastMode: false
3575
+ },
3576
+ {
3577
+ id: "claude-fable-5-1",
3578
+ name: "Claude Fable 5.1",
3579
+ family: "fable",
3580
+ idSuffixes: "any",
3581
+ catalogue: FABLE_MYTHOS_5_1_CATALOGUE,
3582
+ thinkingModes: ["adaptive"],
3583
+ rejectsForcedToolChoice: true,
3584
+ efforts: { variants: ALL_ADAPTIVE_EFFORTS, default: "high" },
3585
+ effortMarkers: "always",
3586
+ turnEndNote: true,
3587
+ thinkingBindingControls: true,
3588
+ claudeCodeBetas: claudeCodeBetaLists({ perTurnControl: true }),
3589
+ serverSideFallback: true,
3590
+ refusalRecoveryFamily: "fable-5-1",
3591
+ scopedQuota: "fable",
3592
+ fastMode: false
3593
+ },
3594
+ {
3595
+ id: "claude-mythos-5-1",
3596
+ name: "Claude Mythos 5.1",
3597
+ family: "mythos",
3598
+ idSuffixes: "any",
3599
+ limited: true,
3600
+ catalogue: FABLE_MYTHOS_5_1_CATALOGUE,
3601
+ thinkingModes: ["adaptive"],
3602
+ rejectsForcedToolChoice: true,
3603
+ efforts: { default: "high" },
3604
+ effortMarkers: "none",
3605
+ turnEndNote: false,
3606
+ thinkingBindingControls: false,
3607
+ claudeCodeBetas: CLAUDE_CODE_DEFAULT_BETAS,
3608
+ serverSideFallback: false,
3609
+ scopedQuota: "mythos",
3610
+ fastMode: false
3611
+ },
3612
+ {
3613
+ id: "claude-opus-5",
3614
+ name: "Claude Opus 5",
3615
+ family: "opus",
3616
+ idSuffixes: "any",
3617
+ thinkingModes: ["adaptive", "disabled"],
3618
+ rejectsForcedToolChoice: false,
3619
+ efforts: { variants: ALL_ADAPTIVE_EFFORTS, default: "high" },
3620
+ effortMarkers: "none",
3621
+ turnEndNote: false,
3622
+ thinkingBindingControls: false,
3623
+ claudeCodeBetas: CLAUDE_CODE_DEFAULT_BETAS,
3624
+ serverSideFallback: true,
3625
+ refusalRecoveryFamily: "opus-5",
3626
+ fastMode: true
3627
+ },
3628
+ {
3629
+ id: "claude-opus-5-5",
3630
+ name: "Claude Opus 5.5",
3631
+ family: "opus",
3632
+ idSuffixes: "any",
3633
+ catalogue: {
3634
+ releaseDate: "2026-09-18",
3635
+ contextWindow: 1e6,
3636
+ maxOutputTokens: 128000,
3637
+ pricing: {
3638
+ input: 4,
3639
+ output: 20,
3640
+ cacheRead: 0.2,
3641
+ cacheWrite5m: 5,
3642
+ cacheWrite1h: 8
3643
+ }
3644
+ },
3645
+ thinkingModes: ["adaptive"],
3646
+ rejectsForcedToolChoice: true,
3647
+ efforts: { variants: ALL_ADAPTIVE_EFFORTS, default: "medium" },
3648
+ effortMarkers: "with-adaptive-thinking",
3649
+ turnEndNote: true,
3650
+ thinkingBindingControls: true,
3651
+ claudeCodeBetas: claudeCodeBetaLists({ perTurnControl: true }),
3652
+ serverSideFallback: true,
3653
+ refusalRecoveryFamily: "opus-5-5",
3654
+ fastMode: true
3655
+ },
3656
+ {
3657
+ id: "claude-sonnet-5",
3658
+ name: "Claude Sonnet 5",
3659
+ family: "sonnet",
3660
+ idSuffixes: "any",
3661
+ thinkingModes: ["adaptive", "disabled"],
3662
+ rejectsForcedToolChoice: false,
3663
+ efforts: { default: "high" },
3664
+ effortMarkers: "none",
3665
+ turnEndNote: false,
3666
+ thinkingBindingControls: false,
3667
+ claudeCodeBetas: CLAUDE_CODE_DEFAULT_BETAS,
3668
+ serverSideFallback: false,
3669
+ fastMode: false
3670
+ },
3671
+ {
3672
+ id: "claude-sonnet-5-5",
3673
+ name: "Claude Sonnet 5.5",
3674
+ family: "sonnet",
3675
+ idSuffixes: "any",
3676
+ catalogue: {
3677
+ releaseDate: "2026-09-28",
3678
+ contextWindow: 1e6,
3679
+ maxOutputTokens: 128000,
3680
+ pricing: {
3681
+ input: 2,
3682
+ output: 10,
3683
+ cacheRead: 0.2,
3684
+ cacheWrite5m: 2.5,
3685
+ cacheWrite1h: 4
3686
+ }
3687
+ },
3688
+ thinkingModes: ["adaptive", "between_tools"],
3689
+ rejectsForcedToolChoice: true,
3690
+ efforts: { variants: ALL_ADAPTIVE_EFFORTS, default: "high" },
3691
+ effortMarkers: "with-adaptive-thinking",
3692
+ turnEndNote: true,
3693
+ thinkingBindingControls: true,
3694
+ claudeCodeBetas: claudeCodeBetaLists({ perTurnControl: true }),
3695
+ serverSideFallback: false,
3696
+ fastMode: false
3697
+ },
3698
+ {
3699
+ id: "claude-haiku-5-5",
3700
+ name: "Claude Haiku 5.5",
3701
+ family: "haiku",
3702
+ idSuffixes: "dated",
3703
+ catalogue: {
3704
+ releaseDate: "2026-10-07",
3705
+ contextWindow: 1e6,
3706
+ maxOutputTokens: 128000,
3707
+ pricing: {
3708
+ input: 0.1,
3709
+ output: 0.5,
3710
+ cacheRead: 0.01,
3711
+ cacheWrite5m: 0.125,
3712
+ cacheWrite1h: 0.2
3713
+ },
3714
+ longContext: {
3715
+ inputTokensAbove: 1e5,
3716
+ pricing: {
3717
+ input: 0.5,
3718
+ output: 2.5,
3719
+ cacheRead: 0.05,
3720
+ cacheWrite5m: 0.625,
3721
+ cacheWrite1h: 1
3722
+ }
3723
+ }
3724
+ },
3725
+ thinkingModes: ["adaptive", "disabled"],
3726
+ rejectsForcedToolChoice: false,
3727
+ efforts: { variants: ALL_ADAPTIVE_EFFORTS, default: "medium" },
3728
+ effortMarkers: "none",
3729
+ turnEndNote: true,
3730
+ thinkingBindingControls: true,
3731
+ claudeCodeBetas: claudeCodeBetaLists({
3732
+ perTurnControl: true,
3733
+ claudeCodeBetaAfterCachingScope: true
3734
+ }),
3735
+ serverSideFallback: false,
3736
+ fastMode: false
3737
+ }
3738
+ ];
3739
+ function normalizeAnthropicModelId(model) {
3740
+ return model.endsWith("[1m]") ? model.slice(0, -4) : model;
3741
+ }
3742
+ function matchesRow(row, normalized) {
3743
+ if (normalized === row.id)
3744
+ return true;
3745
+ if (!normalized.startsWith(`${row.id}-`))
3746
+ return false;
3747
+ if (row.idSuffixes === "any")
3748
+ return true;
3749
+ return /^\d{8}$/.test(normalized.slice(row.id.length + 1));
3750
+ }
3751
+ function resolveClaudeModelCapabilities(model) {
3752
+ if (typeof model !== "string")
3753
+ return;
3754
+ const normalized = normalizeAnthropicModelId(model);
3755
+ let resolved;
3756
+ for (const row of CLAUDE_MODEL_CAPABILITIES) {
3757
+ if (!matchesRow(row, normalized))
3758
+ continue;
3759
+ if (!resolved || row.id.length > resolved.id.length)
3760
+ resolved = row;
3761
+ }
3762
+ return resolved;
3763
+ }
3764
+ function getClaudeModelCapabilities(id) {
3765
+ const row = CLAUDE_MODEL_CAPABILITIES.find((entry) => entry.id === id);
3766
+ if (!row)
3767
+ throw new Error(`No model capability row for ${id}`);
3768
+ return row;
3769
+ }
3770
+ function getClaudeModelCatalogue(id) {
3771
+ const catalogue = getClaudeModelCapabilities(id).catalogue;
3772
+ if (!catalogue)
3773
+ throw new Error(`No catalogue facts for ${id}`);
3774
+ return catalogue;
3775
+ }
3776
+ function pinsEffortOnEveryRequest(model) {
3777
+ return resolveClaudeModelCapabilities(model)?.effortMarkers === "always";
3778
+ }
3779
+
3315
3780
  // src/constants.ts
3316
3781
  var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
3317
3782
  var AUTHORIZE_URLS = {
@@ -3342,7 +3807,7 @@ function mergeAnthropicBetas(existing, betas) {
3342
3807
  return [...new Set([...incoming, ...betas])].join(",");
3343
3808
  }
3344
3809
  function isFastModeSupportedModel(model) {
3345
- return typeof model === "string" && (model.startsWith("claude-opus-4-8") || model.startsWith("claude-opus-5"));
3810
+ return typeof model === "string" && (model.startsWith("claude-opus-4-8") || model.startsWith("claude-opus-5") || resolveClaudeModelCapabilities(model)?.fastMode === true);
3346
3811
  }
3347
3812
  var OPENCODE_IDENTITY_PREFIX = "You are OpenCode";
3348
3813
  var CLAUDE_CODE_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude.";
@@ -3659,16 +4124,16 @@ function getConfigDir() {
3659
4124
  if (process.env.OPENCODE_CONFIG_DIR?.trim()) {
3660
4125
  return process.env.OPENCODE_CONFIG_DIR.trim();
3661
4126
  }
3662
- return join6(process.env.XDG_CONFIG_HOME || join6(homedir2(), ".config"), "opencode");
4127
+ return join7(process.env.XDG_CONFIG_HOME || join7(homedir2(), ".config"), "opencode");
3663
4128
  }
3664
4129
  function getAccountStoragePath() {
3665
- return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim() || join6(getConfigDir(), ACCOUNT_FILE_NAME);
4130
+ return process.env.OPENCODE_ANTHROPIC_AUTH_FILE?.trim() || join7(getConfigDir(), ACCOUNT_FILE_NAME);
3666
4131
  }
3667
4132
  function getAccountStatePath(configPath = getAccountStoragePath()) {
3668
4133
  const explicit = process.env.OPENCODE_ANTHROPIC_AUTH_STATE_FILE?.trim();
3669
4134
  if (explicit)
3670
4135
  return explicit;
3671
- return configPath.endsWith(ACCOUNT_FILE_NAME) ? join6(dirname6(configPath), ACCOUNT_STATE_FILE_NAME) : `${configPath}.state.json`;
4136
+ return configPath.endsWith(ACCOUNT_FILE_NAME) ? join7(dirname6(configPath), ACCOUNT_STATE_FILE_NAME) : `${configPath}.state.json`;
3672
4137
  }
3673
4138
  function createEmptyStorage() {
3674
4139
  return {
@@ -3789,7 +4254,7 @@ function getClaustrumMode(storage) {
3789
4254
  async function acquireRefreshFileLock2(options) {
3790
4255
  const accountPath = options.path ?? getAccountStoragePath();
3791
4256
  const lockPath = `${accountPath}.${options.name}.lock`;
3792
- const legacyOwnerPath = join6(lockPath, "owner.json");
4257
+ const legacyOwnerPath = join7(lockPath, "owner.json");
3793
4258
  const ownerId = randomUUID6();
3794
4259
  const now = Date.now;
3795
4260
  let renewTimer = null;
@@ -3843,7 +4308,7 @@ async function acquireRefreshFileLock2(options) {
3843
4308
  let acquired = await tryAcquire();
3844
4309
  if (!acquired) {
3845
4310
  const evictPath = `${lockPath}.evicting`;
3846
- const evictOwnerPath = join6(evictPath, "owner.json");
4311
+ const evictOwnerPath = join7(evictPath, "owner.json");
3847
4312
  const evictOwnerId = randomUUID6();
3848
4313
  const EVICT_TTL = 5000;
3849
4314
  const MAX_STEAL_ATTEMPTS = 8;
@@ -4789,374 +5254,32 @@ function extractBillingPromptId(body) {
4789
5254
  }
4790
5255
  function stripBillingLineageFields(value) {
4791
5256
  return value.replace(BILLING_LINEAGE_FIELD_PATTERN, "");
4792
- }
4793
- function stripBillingLineageFromBody(body) {
4794
- if (!body || typeof body !== "object")
4795
- return 0;
4796
- const system = body.system;
4797
- if (!Array.isArray(system))
4798
- return 0;
4799
- let stripped = 0;
4800
- for (const block of system) {
4801
- if (!block || typeof block !== "object")
4802
- continue;
4803
- const text = block.text;
4804
- if (typeof text !== "string" || !text.startsWith("x-anthropic-billing-header:")) {
4805
- continue;
4806
- }
4807
- const clean = stripBillingLineageFields(text);
4808
- if (clean === text)
4809
- continue;
4810
- block.text = clean;
4811
- stripped += 1;
4812
- }
4813
- return stripped;
4814
- }
4815
-
4816
- // src/claude-code.ts
4817
- import { randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
4818
-
4819
- // src/models.ts
4820
- var CLAUDE_FABLE_5_MODEL_ID = "claude-fable-5";
4821
- var CLAUDE_MYTHOS_5_MODEL_ID = "claude-mythos-5";
4822
- var CLAUDE_FABLE_5_1_MODEL_ID = "claude-fable-5-1";
4823
- var CLAUDE_MYTHOS_5_1_MODEL_ID = "claude-mythos-5-1";
4824
- var CLAUDE_HAIKU_4_5_MODEL_ID = "claude-haiku-4-5";
4825
- function normalizeAnthropicModelId(model) {
4826
- return model.endsWith("[1m]") ? model.slice(0, -4) : model;
4827
- }
4828
- var CLAUDE_HAIKU_4_5_PRICING = {
4829
- input: 1,
4830
- output: 5
4831
- };
4832
- var CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS = [
4833
- CLAUDE_FABLE_5_1_MODEL_ID,
4834
- CLAUDE_MYTHOS_5_1_MODEL_ID
4835
- ];
4836
- var CLAUDE_FABLE_MYTHOS_5_MODEL_IDS = [
4837
- CLAUDE_FABLE_5_MODEL_ID,
4838
- CLAUDE_MYTHOS_5_MODEL_ID,
4839
- ...CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS
4840
- ];
4841
- var CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING = {
4842
- type: "adaptive",
4843
- display: "summarized"
4844
- };
4845
- var CLAUDE_FABLE_MYTHOS_5_PRICING = {
4846
- input: 10,
4847
- output: 50,
4848
- cacheRead: 1,
4849
- cacheWrite5m: 12.5,
4850
- cacheWrite1h: 20
4851
- };
4852
- var CLAUDE_FABLE_MYTHOS_5_1_PRICING = {
4853
- input: 10,
4854
- output: 50,
4855
- cacheRead: 0.25,
4856
- cacheWrite5m: 12.5,
4857
- cacheWrite1h: 20
4858
- };
4859
- var CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW = 1e6;
4860
- var CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS = 128000;
4861
- var CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE = "2026-06-09";
4862
- var CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE = "2026-09-01";
4863
- var CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS = {
4864
- [CLAUDE_FABLE_5_MODEL_ID]: {
4865
- id: CLAUDE_FABLE_5_MODEL_ID,
4866
- name: "Claude Fable 5"
4867
- },
4868
- [CLAUDE_MYTHOS_5_MODEL_ID]: {
4869
- id: CLAUDE_MYTHOS_5_MODEL_ID,
4870
- name: "Claude Mythos 5",
4871
- limited: true
4872
- },
4873
- [CLAUDE_FABLE_5_1_MODEL_ID]: {
4874
- id: CLAUDE_FABLE_5_1_MODEL_ID,
4875
- name: "Claude Fable 5.1"
4876
- },
4877
- [CLAUDE_MYTHOS_5_1_MODEL_ID]: {
4878
- id: CLAUDE_MYTHOS_5_1_MODEL_ID,
4879
- name: "Claude Mythos 5.1",
4880
- limited: true
4881
- }
4882
- };
4883
- var CLAUDE_FABLE_MYTHOS_5_1_MODEL_SPECS = {
4884
- [CLAUDE_FABLE_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_FABLE_5_1_MODEL_ID],
4885
- [CLAUDE_MYTHOS_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_MYTHOS_5_1_MODEL_ID]
4886
- };
4887
- function isClaudeFableOrMythos5Model(model) {
4888
- if (typeof model !== "string")
4889
- return false;
4890
- const normalized = normalizeAnthropicModelId(model);
4891
- return CLAUDE_FABLE_MYTHOS_5_MODEL_IDS.some((id) => normalized === id || normalized.startsWith(`${id}-`));
4892
- }
4893
- function isClaudeFableOrMythos51Model(model) {
4894
- if (typeof model !== "string")
4895
- return false;
4896
- const normalized = normalizeAnthropicModelId(model);
4897
- return CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS.some((id) => normalized === id || normalized.startsWith(`${id}-`));
4898
- }
4899
- function isClaudeFable51Model(model) {
4900
- if (typeof model !== "string")
4901
- return false;
4902
- const normalized = normalizeAnthropicModelId(model);
4903
- return normalized === CLAUDE_FABLE_5_1_MODEL_ID || normalized.startsWith(`${CLAUDE_FABLE_5_1_MODEL_ID}-`);
4904
- }
4905
- function getClaudeFableMythos5ReleaseDate(model) {
4906
- return isClaudeFableOrMythos51Model(model) ? CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE : CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE;
4907
- }
4908
- var CLAUDE_SONNET_5_MODEL_ID = "claude-sonnet-5";
4909
- var CLAUDE_SONNET_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4910
- function isClaudeSonnet5Model(model) {
4911
- if (typeof model !== "string")
4912
- return false;
4913
- const normalized = normalizeAnthropicModelId(model);
4914
- return !isClaudeSonnet55Model(normalized) && (normalized === CLAUDE_SONNET_5_MODEL_ID || normalized.startsWith(`${CLAUDE_SONNET_5_MODEL_ID}-`));
4915
- }
4916
- var CLAUDE_SONNET_5_5_MODEL_ID = "claude-sonnet-5-5";
4917
- var CLAUDE_SONNET_5_5_RELEASE_DATE = "2026-09-28";
4918
- var CLAUDE_SONNET_5_5_CONTEXT_WINDOW = 1e6;
4919
- var CLAUDE_SONNET_5_5_MAX_OUTPUT_TOKENS = 128000;
4920
- var CLAUDE_SONNET_5_5_PRICING = {
4921
- input: 2,
4922
- output: 10,
4923
- cacheRead: 0.2,
4924
- cacheWrite5m: 2.5,
4925
- cacheWrite1h: 4
4926
- };
4927
- var CLAUDE_SONNET_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4928
- function isClaudeSonnet55Model(model) {
4929
- if (typeof model !== "string")
4930
- return false;
4931
- const normalized = normalizeAnthropicModelId(model);
4932
- return normalized === CLAUDE_SONNET_5_5_MODEL_ID || normalized.startsWith(`${CLAUDE_SONNET_5_5_MODEL_ID}-`);
4933
- }
4934
- var CLAUDE_HAIKU_5_5_MODEL_ID = "claude-haiku-5-5";
4935
- var CLAUDE_HAIKU_5_5_RELEASE_DATE = "2026-10-07";
4936
- var CLAUDE_HAIKU_5_5_CONTEXT_WINDOW = 1e6;
4937
- var CLAUDE_HAIKU_5_5_MAX_OUTPUT_TOKENS = 128000;
4938
- var CLAUDE_HAIKU_5_5_LONG_CONTEXT_THRESHOLD = 1e5;
4939
- var CLAUDE_HAIKU_5_5_PRICING = {
4940
- input: 0.1,
4941
- output: 0.5,
4942
- cacheRead: 0.01,
4943
- cacheWrite5m: 0.125,
4944
- cacheWrite1h: 0.2
4945
- };
4946
- var CLAUDE_HAIKU_5_5_LONG_CONTEXT_PRICING = {
4947
- input: 0.5,
4948
- output: 2.5,
4949
- cacheRead: 0.05,
4950
- cacheWrite5m: 0.625,
4951
- cacheWrite1h: 1
4952
- };
4953
- var CLAUDE_HAIKU_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4954
- function isClaudeHaiku55Model(model) {
4955
- if (typeof model !== "string")
4956
- return false;
4957
- const normalized = normalizeAnthropicModelId(model);
4958
- return normalized === CLAUDE_HAIKU_5_5_MODEL_ID || /^claude-haiku-5-5-\d{8}$/.test(normalized);
4959
- }
4960
- var CLAUDE_OPUS_5_MODEL_ID = "claude-opus-5";
4961
- var CLAUDE_OPUS_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4962
- function isClaudeOpus5Model(model) {
4963
- if (typeof model !== "string")
4964
- return false;
4965
- const normalized = normalizeAnthropicModelId(model);
4966
- return !isClaudeOpus55Model(normalized) && (normalized === CLAUDE_OPUS_5_MODEL_ID || normalized.startsWith(`${CLAUDE_OPUS_5_MODEL_ID}-`));
4967
- }
4968
- var CLAUDE_OPUS_5_5_MODEL_ID = "claude-opus-5-5";
4969
- var CLAUDE_OPUS_5_5_RELEASE_DATE = "2026-09-18";
4970
- var CLAUDE_OPUS_5_5_CONTEXT_WINDOW = 1e6;
4971
- var CLAUDE_OPUS_5_5_MAX_OUTPUT_TOKENS = 128000;
4972
- var CLAUDE_OPUS_5_5_PRICING = {
4973
- input: 4,
4974
- output: 20,
4975
- cacheRead: 0.2,
4976
- cacheWrite5m: 5,
4977
- cacheWrite1h: 8
4978
- };
4979
- var CLAUDE_OPUS_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4980
- function isClaudeOpus55Model(model) {
4981
- if (typeof model !== "string")
4982
- return false;
4983
- const normalized = normalizeAnthropicModelId(model);
4984
- return normalized === CLAUDE_OPUS_5_5_MODEL_ID || normalized.startsWith(`${CLAUDE_OPUS_5_5_MODEL_ID}-`);
4985
- }
4986
- function isClaudeOpus5FamilyModel(model) {
4987
- return isClaudeOpus5Model(model) || isClaudeOpus55Model(model);
4988
- }
4989
- function isOpenAIReasoningSignature(value) {
4990
- if (typeof value !== "string")
4991
- return false;
4992
- if (value.startsWith("gAAAA"))
4993
- return true;
4994
- if (!value.startsWith("{"))
4995
- return false;
4996
- try {
4997
- const parsed = JSON.parse(value);
4998
- return parsed.type === "reasoning" && typeof parsed.id === "string" && parsed.id.startsWith("rs_") && typeof parsed.encrypted_content === "string" && parsed.encrypted_content.startsWith("gAAAA");
4999
- } catch {
5000
- return false;
5001
- }
5002
- }
5003
-
5004
- // src/mid-conversation-output-config.ts
5005
- var PER_TURN_CONTROL_BETA = "per-turn-control-2026-07-01";
5006
- function isRecord3(value) {
5007
- return typeof value === "object" && value !== null && !Array.isArray(value);
5008
- }
5009
- function normalizeAdaptiveEffort(value) {
5010
- if (value === "minimal")
5011
- return "low";
5012
- if (value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "max") {
5013
- return value;
5014
- }
5015
- return;
5016
- }
5017
- function usesPerTurnControl(model) {
5018
- return isClaudeOpus55Model(model) || isClaudeSonnet55Model(model);
5019
- }
5020
- function sendsPerTurnControlBeta(model) {
5021
- return usesPerTurnControl(model) || isClaudeFable51Model(model) || isClaudeHaiku55Model(model);
5022
- }
5023
- function supportsPerMessageEffort(body) {
5024
- if (isClaudeFable51Model(body.model))
5025
- return true;
5026
- return usesPerTurnControl(body.model) && isRecord3(body.thinking) && body.thinking.type === "adaptive";
5027
- }
5028
- function defaultAdaptiveEffort(model) {
5029
- return isClaudeOpus55Model(model) || isClaudeHaiku55Model(model) ? "medium" : "high";
5030
- }
5031
- function compactTransitions(transitions) {
5032
- const compacted = [];
5033
- for (const transition of transitions) {
5034
- if (!Number.isSafeInteger(transition.afterAssistantMessages) || transition.afterAssistantMessages < 0 || !normalizeAdaptiveEffort(transition.effort)) {
5035
- continue;
5036
- }
5037
- const normalized = {
5038
- afterAssistantMessages: transition.afterAssistantMessages,
5039
- effort: transition.effort
5040
- };
5041
- const previous = compacted.at(-1);
5042
- if (previous && previous.afterAssistantMessages === normalized.afterAssistantMessages) {
5043
- previous.effort = normalized.effort;
5044
- continue;
5045
- }
5046
- if (previous?.effort === normalized.effort)
5047
- continue;
5048
- compacted.push(normalized);
5049
- }
5050
- return compacted;
5051
- }
5052
- function applyMidConversationOutputConfig(body, transitions) {
5053
- if (!supportsPerMessageEffort(body) || !Array.isArray(body.messages)) {
5054
- return { applied: false, inserted: 0 };
5055
- }
5056
- const compacted = compactTransitions(transitions);
5057
- const pinsEveryRequest = isClaudeFable51Model(body.model);
5058
- if (!pinsEveryRequest && compacted.length < 2) {
5059
- return { applied: false, inserted: 0 };
5060
- }
5061
- const currentOutputConfig = isRecord3(body.output_config) ? body.output_config : {};
5062
- const baseline = compacted[0]?.effort ?? normalizeAdaptiveEffort(currentOutputConfig.effort) ?? defaultAdaptiveEffort(body.model);
5063
- const pinnedOutputConfig = { ...currentOutputConfig, effort: baseline };
5064
- if (pinsEveryRequest)
5065
- body.output_config = pinnedOutputConfig;
5066
- if (compacted.length < 2)
5067
- return { applied: true, inserted: 0 };
5068
- const messages = body.messages;
5069
- const transitionsByBoundary = new Map;
5070
- for (const transition of compacted.slice(1)) {
5071
- transitionsByBoundary.set(transition.afterAssistantMessages, transition.effort);
5072
- }
5073
- let assistantMessages = 0;
5074
- let activeEffort = baseline;
5075
- let inserted = 0;
5076
- const rewritten = [];
5077
- for (const message of messages) {
5078
- if (isRecord3(message) && message.role === "user" && transitionsByBoundary.has(assistantMessages)) {
5079
- const effort = transitionsByBoundary.get(assistantMessages);
5080
- if (effort && effort !== activeEffort) {
5081
- rewritten.push({
5082
- role: "system",
5083
- content: [],
5084
- output_config: { effort }
5085
- });
5086
- activeEffort = effort;
5087
- inserted++;
5088
- }
5089
- }
5090
- rewritten.push(message);
5091
- if (isRecord3(message) && message.role === "assistant")
5092
- assistantMessages++;
5093
- }
5094
- if (!pinsEveryRequest && inserted === 0) {
5095
- return { applied: false, inserted: 0 };
5096
- }
5097
- body.output_config = pinnedOutputConfig;
5098
- body.messages = rewritten;
5099
- return { applied: true, inserted };
5100
- }
5101
-
5102
- // src/turn-end-note.ts
5103
- var TURN_END_NOTE_BETA = "mid-conversation-system-clear-at-2026-08-21";
5104
- var TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
5105
- var TURN_END_NOTE_CONTENT = "Your reply above has already reached the user. The tool call after it was housekeeping and changed nothing they need to know. Do not repeat, summarize or rewrite that reply. If no new work remains, end the turn without restating anything.";
5106
- var DEFAULT_TOOLS = ["board", "ctx_reduce"];
5107
- function isRecord4(value) {
5108
- return value !== null && typeof value === "object" && !Array.isArray(value);
5109
- }
5110
- function supportsTurnEndNote(model) {
5111
- return isClaudeFable51Model(model) || isClaudeHaiku55Model(model) || isClaudeOpus55Model(model) || isClaudeSonnet55Model(model);
5112
- }
5113
- function applyTurnEndNotes(body, options = {}) {
5114
- if (!supportsTurnEndNote(body.model) || !Array.isArray(body.messages))
5257
+ }
5258
+ function stripBillingLineageFromBody(body) {
5259
+ if (!body || typeof body !== "object")
5115
5260
  return 0;
5116
- const allowed = new Set((options.tools ?? DEFAULT_TOOLS).map((name) => options.mapToolName?.(name) ?? name));
5117
- if (!allowed.size)
5261
+ const system = body.system;
5262
+ if (!Array.isArray(system))
5118
5263
  return 0;
5119
- const messages = body.messages;
5120
- const rewritten = [];
5121
- let inserted = 0;
5122
- for (let index = 0;index < messages.length; index++) {
5123
- const results = messages[index];
5124
- rewritten.push(results);
5125
- let preceding = index - 1;
5126
- while (preceding >= 0) {
5127
- const control = messages[preceding];
5128
- if (!isRecord4(control) || control.role !== "system" || !Array.isArray(control.content) || control.content.length !== 0 || !isRecord4(control.output_config))
5129
- break;
5130
- preceding--;
5131
- }
5132
- const assistant = messages[preceding];
5133
- if (!isRecord4(assistant) || assistant.role !== "assistant" || !Array.isArray(assistant.content) || !isRecord4(results) || results.role !== "user" || !Array.isArray(results.content))
5134
- continue;
5135
- const visible = options.visibleText ? options.visibleText(assistant) : assistant.content.filter((block) => isRecord4(block) && block.type === "text" && typeof block.text === "string" && block.text.trim().length > 0).map((block) => block.text).join("");
5136
- if (visible.length < TURN_END_NOTE_MIN_VISIBLE_CHARACTERS)
5137
- continue;
5138
- const calls = assistant.content.filter((block) => isRecord4(block) && block.type === "tool_use");
5139
- if (!calls.length || !calls.every((call) => allowed.has(call.name)))
5264
+ let stripped = 0;
5265
+ for (const block of system) {
5266
+ if (!block || typeof block !== "object")
5140
5267
  continue;
5141
- const resultIds = new Set(results.content.filter((block) => isRecord4(block) && block.type === "tool_result").map((block) => block.tool_use_id));
5142
- if (!calls.every((call) => typeof call.id === "string" && resultIds.has(call.id)))
5268
+ const text = block.text;
5269
+ if (typeof text !== "string" || !text.startsWith("x-anthropic-billing-header:")) {
5143
5270
  continue;
5144
- const next = messages[index + 1];
5145
- if (isRecord4(next) && next.role === "user")
5271
+ }
5272
+ const clean = stripBillingLineageFields(text);
5273
+ if (clean === text)
5146
5274
  continue;
5147
- rewritten.push({
5148
- role: "system",
5149
- clear_at: "next_user_message",
5150
- content: TURN_END_NOTE_CONTENT
5151
- });
5152
- inserted++;
5275
+ block.text = clean;
5276
+ stripped += 1;
5153
5277
  }
5154
- if (inserted)
5155
- body.messages = rewritten;
5156
- return inserted;
5278
+ return stripped;
5157
5279
  }
5158
5280
 
5159
5281
  // src/claude-code.ts
5282
+ import { randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
5160
5283
  var IDENTITY_CACHE_LIMIT = 1000;
5161
5284
  var identityCache = new Map;
5162
5285
  function setBounded(map, key, value, limit = IDENTITY_CACHE_LIMIT) {
@@ -5369,7 +5492,7 @@ async function resolveClaudeCodeAccountIdentity(accessToken, model, accountIdent
5369
5492
  throw new ClaudeUnsupportedAccessError;
5370
5493
  return resolveClaudeCodeIdentity(accessToken, model, accountIdentity);
5371
5494
  }
5372
- function isRecord5(value) {
5495
+ function isRecord3(value) {
5373
5496
  return value != null && typeof value === "object" && !Array.isArray(value);
5374
5497
  }
5375
5498
  function buildClaudeCodeMetadataUserId(identity) {
@@ -5384,55 +5507,17 @@ function buildClaudeCodeMetadataUserId(identity) {
5384
5507
  function applyClaudeCodeMetadata(body, identity) {
5385
5508
  const userId = buildClaudeCodeMetadataUserId(identity);
5386
5509
  if (!userId) {
5387
- if (isRecord5(body.metadata))
5510
+ if (isRecord3(body.metadata))
5388
5511
  delete body.metadata.user_id;
5389
5512
  return false;
5390
5513
  }
5391
- if (!isRecord5(body.metadata))
5514
+ if (!isRecord3(body.metadata))
5392
5515
  body.metadata = {};
5393
5516
  const metadata = body.metadata;
5394
- if (isRecord5(metadata))
5517
+ if (isRecord3(metadata))
5395
5518
  metadata.user_id = userId;
5396
5519
  return true;
5397
5520
  }
5398
- var CLAUDE_CODE_FULL_AGENT_BETAS = [
5399
- "claude-code-20250219",
5400
- "oauth-2025-04-20",
5401
- "interleaved-thinking-2025-05-14",
5402
- "thinking-token-count-2026-05-13",
5403
- "context-management-2025-06-27",
5404
- "prompt-caching-scope-2026-01-05",
5405
- "mid-conversation-tool-changes-2026-07-01",
5406
- "advanced-tool-use-2025-11-20",
5407
- TURN_END_NOTE_BETA,
5408
- "effort-2025-11-24",
5409
- "thinking-binding-controls-2026-08-01",
5410
- "thinking-display-updates-2026-08-18",
5411
- "extended-cache-ttl-2025-04-11",
5412
- "cache-diagnosis-2026-04-07"
5413
- ];
5414
- var CLAUDE_CODE_TITLE_BETAS = [
5415
- "oauth-2025-04-20",
5416
- "interleaved-thinking-2025-05-14",
5417
- "redact-thinking-2026-02-12",
5418
- "thinking-token-count-2026-05-13",
5419
- "context-management-2025-06-27",
5420
- "prompt-caching-scope-2026-01-05",
5421
- "mid-conversation-tool-changes-2026-07-01",
5422
- "mid-conversation-system-clear-at-2026-08-21",
5423
- "effort-2025-11-24",
5424
- "cache-diagnosis-2026-04-07"
5425
- ];
5426
- var CLAUDE_CODE_QUOTA_BETAS = [
5427
- "oauth-2025-04-20",
5428
- "interleaved-thinking-2025-05-14",
5429
- "redact-thinking-2026-02-12",
5430
- "thinking-token-count-2026-05-13",
5431
- "context-management-2025-06-27",
5432
- "prompt-caching-scope-2026-01-05"
5433
- ];
5434
- var CLAUDE_CODE_BETA = "claude-code-20250219";
5435
- var PROMPT_CACHING_SCOPE_BETA = "prompt-caching-scope-2026-01-05";
5436
5521
  function hasStructuredOutput(body) {
5437
5522
  const outputConfig = body.output_config;
5438
5523
  const format = outputConfig?.format;
@@ -5442,25 +5527,10 @@ function isQuotaProbe(body) {
5442
5527
  return body.max_tokens === 1 && !body.stream && !body.thinking && (!Array.isArray(body.tools) || body.tools.length === 0) && !hasStructuredOutput(body);
5443
5528
  }
5444
5529
  function selectClaudeCodeBetas(body, extraBetas = [], requestClass = "main") {
5445
- const selected = requestClass === "main" ? [...CLAUDE_CODE_FULL_AGENT_BETAS] : body && isQuotaProbe(body) ? [...CLAUDE_CODE_QUOTA_BETAS] : [...CLAUDE_CODE_TITLE_BETAS];
5446
- if (Array.isArray(body?.messages) && body.messages.some((message) => isRecord5(message) && message.clear_at === "next_user_message") && !selected.includes(TURN_END_NOTE_BETA))
5530
+ const lists = body && resolveClaudeModelCapabilities(body.model)?.claudeCodeBetas || CLAUDE_CODE_DEFAULT_BETAS;
5531
+ const selected = requestClass === "main" ? [...lists.main] : body && isQuotaProbe(body) ? [...lists.quota] : [...lists.title];
5532
+ if (Array.isArray(body?.messages) && body.messages.some((message) => isRecord3(message) && message.clear_at === "next_user_message") && !selected.includes(TURN_END_NOTE_BETA))
5447
5533
  selected.push(TURN_END_NOTE_BETA);
5448
- if (body && isClaudeHaiku55Model(body.model)) {
5449
- const codeIndex = selected.indexOf(CLAUDE_CODE_BETA);
5450
- if (codeIndex >= 0) {
5451
- selected.splice(codeIndex, 1);
5452
- selected.splice(selected.indexOf(PROMPT_CACHING_SCOPE_BETA) + 1, 0, CLAUDE_CODE_BETA);
5453
- }
5454
- }
5455
- if (body && sendsPerTurnControlBeta(body.model)) {
5456
- let index = selected.indexOf(PROMPT_CACHING_SCOPE_BETA);
5457
- if (index >= 0 && selected[index + 1] === CLAUDE_CODE_BETA)
5458
- index += 1;
5459
- if (index >= 0)
5460
- selected.splice(index + 1, 0, PER_TURN_CONTROL_BETA);
5461
- else
5462
- selected.push(PER_TURN_CONTROL_BETA);
5463
- }
5464
5534
  if (body && hasStructuredOutput(body)) {
5465
5535
  const index = selected.indexOf("cache-diagnosis-2026-04-07");
5466
5536
  selected.splice(index < 0 ? selected.length : index, 0, "structured-outputs-2025-12-15");
@@ -5574,8 +5644,8 @@ import {
5574
5644
  unlink as unlink4,
5575
5645
  writeFile as writeFile2
5576
5646
  } from "node:fs/promises";
5577
- import { tmpdir as tmpdir4 } from "node:os";
5578
- import { join as join8, resolve as resolve3 } from "node:path";
5647
+ import { tmpdir as tmpdir5 } from "node:os";
5648
+ import { join as join9, resolve as resolve3 } from "node:path";
5579
5649
 
5580
5650
  // src/json.ts
5581
5651
  function parseJsonRedacted(text) {
@@ -5846,7 +5916,7 @@ var DUMP_USAGE_TITLE = "## Claude Dump Usage";
5846
5916
  var DUMP_USAGE = "Usage: `/claude-dump`, `/claude-dump on`, or `/claude-dump off`.";
5847
5917
  var DUMP_DIR_ENV = "OPENCODE_ANTHROPIC_AUTH_DUMP_DIR";
5848
5918
  var DUMP_MAX_BYTES_ENV = "OPENCODE_ANTHROPIC_AUTH_DUMP_MAX_BYTES";
5849
- var DEFAULT_DUMP_DIR = join8(tmpdir4(), "opencode-anthropic-auth-dumps");
5919
+ var DEFAULT_DUMP_DIR = join9(tmpdir5(), "opencode-anthropic-auth-dumps");
5850
5920
  var DEFAULT_DUMP_MAX_BYTES = 512 * 1024 * 1024;
5851
5921
  var DUMP_SWEEP_INTERVAL_MS = 5 * 60 * 1000;
5852
5922
  var DUMP_SWEEP_NEWNESS_FLOOR_MS = 60 * 1000;
@@ -5949,7 +6019,7 @@ async function sweepDumpDirectory(options) {
5949
6019
  const partial = isDumpPartialFileName(entry.name);
5950
6020
  if (!partial && !isDumpArtifactFileName(entry.name))
5951
6021
  return;
5952
- const path2 = join8(dumpDir, entry.name);
6022
+ const path2 = join9(dumpDir, entry.name);
5953
6023
  try {
5954
6024
  const stats = await lstat2(path2);
5955
6025
  if (!stats.isFile() || stats.isSymbolicLink())
@@ -6154,7 +6224,7 @@ async function loadLatestDumpBody(input) {
6154
6224
  const candidates = names.map((name) => ({ name, tag: dumpBodyTagForAffinity(name, affinity) })).filter((candidate) => candidate.tag !== undefined).sort((a, b) => b.name.localeCompare(a.name));
6155
6225
  for (const candidate of candidates) {
6156
6226
  try {
6157
- const path2 = join8(dumpDir, candidate.name);
6227
+ const path2 = join9(dumpDir, candidate.name);
6158
6228
  const metadataPath = path2.replace(/\.body\.json$/, ".meta.json");
6159
6229
  if (!(await lstat2(path2)).isFile())
6160
6230
  continue;
@@ -6281,7 +6351,7 @@ async function dumpRequest(input) {
6281
6351
  const tagSegment = dumpTagSegment(input.tag);
6282
6352
  const id = `${new Date().toISOString().replace(/[:.]/g, "-")}-${String(nextDumpId).padStart(6, "0")}-${dumpFileSessionSegment(affinity, 80 - tagSegment.length)}${tagSegment}-${dumpRequestSegment(input)}`;
6283
6353
  const dumpDir = getDumpDirectory();
6284
- const prefix = join8(dumpDir, id);
6354
+ const prefix = join9(dumpDir, id);
6285
6355
  const files = {
6286
6356
  body: `${prefix}.body.json`,
6287
6357
  metadata: `${prefix}.meta.json`,
@@ -8491,8 +8561,8 @@ import {
8491
8561
  rm as rm5,
8492
8562
  writeFile as writeFile3
8493
8563
  } from "node:fs/promises";
8494
- import { tmpdir as tmpdir5 } from "node:os";
8495
- import { join as join9 } from "node:path";
8564
+ import { tmpdir as tmpdir6 } from "node:os";
8565
+ import { join as join10 } from "node:path";
8496
8566
  var CACHE_KEEP_REGISTRY_LEASE_MS = 3 * 60000;
8497
8567
  function normalizeSession(value) {
8498
8568
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -8527,7 +8597,7 @@ function isExpiredRecord(record, now, leaseMs) {
8527
8597
  return record.updatedAt <= now && now - record.updatedAt > leaseMs;
8528
8598
  }
8529
8599
  function getDefaultCacheKeepRegistryDirectory(scope) {
8530
- return join9(tmpdir5(), "opencode-anthropic-auth", "cachekeep-sessions", scope);
8600
+ return join10(tmpdir6(), "opencode-anthropic-auth", "cachekeep-sessions", scope);
8531
8601
  }
8532
8602
 
8533
8603
  class CacheKeepSessionRegistry {
@@ -8538,7 +8608,7 @@ class CacheKeepSessionRegistry {
8538
8608
  constructor(options) {
8539
8609
  this.options = options;
8540
8610
  const instanceId = options.instanceId ?? `${process.pid}-${randomUUID8()}`;
8541
- this.filePath = join9(options.directory, `${instanceId}.json`);
8611
+ this.filePath = join10(options.directory, `${instanceId}.json`);
8542
8612
  }
8543
8613
  publish(sessions) {
8544
8614
  const snapshot = sessions.map((session) => ({ ...session }));
@@ -8578,7 +8648,7 @@ class CacheKeepSessionRegistry {
8578
8648
  }
8579
8649
  const records = await Promise.all(names.map(async (name) => {
8580
8650
  try {
8581
- const raw = await readFile7(join9(this.options.directory, name), "utf8");
8651
+ const raw = await readFile7(join10(this.options.directory, name), "utf8");
8582
8652
  return normalizeRecord(JSON.parse(raw));
8583
8653
  } catch {
8584
8654
  return;
@@ -8620,7 +8690,7 @@ class CacheKeepSessionRegistry {
8620
8690
  return;
8621
8691
  }
8622
8692
  await Promise.all(names.map(async (name) => {
8623
- const recordPath = join9(this.options.directory, name);
8693
+ const recordPath = join10(this.options.directory, name);
8624
8694
  if (recordPath === this.filePath)
8625
8695
  return;
8626
8696
  let initialRecord;
@@ -8701,7 +8771,7 @@ import {
8701
8771
  dirname as dirname8,
8702
8772
  extname as extname2,
8703
8773
  isAbsolute as isAbsolute2,
8704
- join as join10,
8774
+ join as join11,
8705
8775
  resolve as resolve4
8706
8776
  } from "node:path";
8707
8777
  import {
@@ -8855,16 +8925,16 @@ function getClaustrumEnrollmentPaths2(tokenPath) {
8855
8925
  const extension = extname2(tokenPath) || ".json";
8856
8926
  const stem = basename3(tokenPath, extname2(tokenPath));
8857
8927
  return {
8858
- statePath: join10(dirname8(tokenPath), `${stem}-state${extension}`),
8928
+ statePath: join11(dirname8(tokenPath), `${stem}-state${extension}`),
8859
8929
  tokenPath
8860
8930
  };
8861
8931
  }
8862
8932
  function getHostClaustrumEnrollmentPaths(host, env = process.env, cwd = process.cwd()) {
8863
8933
  const configured = env[`${host.toUpperCase()}_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE`]?.trim();
8864
- const tokenPath = configured ? isAbsolute2(configured) ? configured : resolve4(cwd, configured) : join10(env.XDG_STATE_HOME || join10(homedir3(), ".local", "state"), "cortexkit", "anthropic-auth", `${host}-enrollment.json`);
8934
+ const tokenPath = configured ? isAbsolute2(configured) ? configured : resolve4(cwd, configured) : join11(env.XDG_STATE_HOME || join11(homedir3(), ".local", "state"), "cortexkit", "anthropic-auth", `${host}-enrollment.json`);
8865
8935
  return getClaustrumEnrollmentPaths2(tokenPath);
8866
8936
  }
8867
- function isRecord6(value) {
8937
+ function isRecord4(value) {
8868
8938
  return typeof value === "object" && value !== null && !Array.isArray(value);
8869
8939
  }
8870
8940
  function validTimestamp2(value) {
@@ -8874,7 +8944,7 @@ function validGeneration2(value) {
8874
8944
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
8875
8945
  }
8876
8946
  function decodeEnrollmentState2(value) {
8877
- if (!isRecord6(value) || value.version !== ENROLLMENT_SCHEMA2 || typeof value.proposedName !== "string" || value.proposedName.length === 0) {
8947
+ if (!isRecord4(value) || value.version !== ENROLLMENT_SCHEMA2 || typeof value.proposedName !== "string" || value.proposedName.length === 0) {
8878
8948
  throw new Error("invalid Claustrum enrollment state");
8879
8949
  }
8880
8950
  if (value.phase === "pending") {
@@ -8925,7 +8995,7 @@ function decodeEnrollmentState2(value) {
8925
8995
  throw new Error("invalid Claustrum enrollment state");
8926
8996
  }
8927
8997
  function decodeTokenFile2(value) {
8928
- if (!isRecord6(value) || !TOKEN_RE2.test(String(value.token ?? "")) || !validGeneration2(value.token_generation)) {
8998
+ if (!isRecord4(value) || !TOKEN_RE2.test(String(value.token ?? "")) || !validGeneration2(value.token_generation)) {
8929
8999
  throw new Error("invalid Claustrum enrollment token file");
8930
9000
  }
8931
9001
  return {
@@ -9006,7 +9076,7 @@ async function writeStateAtomic2(path2, state, beforeRename) {
9006
9076
  if (Buffer.byteLength(bytes) > ENROLLMENT_FILE_MAX_BYTES2) {
9007
9077
  throw new Error("Claustrum enrollment state is too large");
9008
9078
  }
9009
- const temporary = join10(parent, `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9079
+ const temporary = join11(parent, `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9010
9080
  let descriptor;
9011
9081
  try {
9012
9082
  const nativeCreated = await createWindowsOwnerOnly(temporary, bytes);
@@ -9025,7 +9095,7 @@ async function writeStateAtomic2(path2, state, beforeRename) {
9025
9095
  }
9026
9096
  }
9027
9097
  async function writeTokenAtomic(path2, value, writeTokenFile, beforeRename) {
9028
- const staged = join10(dirname8(path2), `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9098
+ const staged = join11(dirname8(path2), `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9029
9099
  try {
9030
9100
  await writeTokenFile(staged, value);
9031
9101
  await beforeRename();
@@ -9487,7 +9557,9 @@ function formatEnrollmentStatus(status, scopedServing = false) {
9487
9557
  case "busy":
9488
9558
  return ["- Enrollment: setup is busy"];
9489
9559
  case "unavailable":
9490
- return ["- Enrollment: temporarily unavailable"];
9560
+ return [
9561
+ "- Enrollment: this Claustrum vault does not support connecting plugins"
9562
+ ];
9491
9563
  case "pending":
9492
9564
  return status.requestId && /^[A-Za-z0-9_-]{1,128}$/.test(status.requestId) ? [`- Enrollment: pending approval (${status.requestId})`, setup] : [
9493
9565
  status.requestId ? "- Enrollment: pending approval" : "- Enrollment: request not sent",
@@ -10069,6 +10141,102 @@ function executeLoggingCommand(input) {
10069
10141
  ].join(`
10070
10142
  `);
10071
10143
  }
10144
+ // src/mid-conversation-output-config.ts
10145
+ function isRecord5(value) {
10146
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10147
+ }
10148
+ function normalizeAdaptiveEffort(value) {
10149
+ if (value === "minimal")
10150
+ return "low";
10151
+ if (value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "max") {
10152
+ return value;
10153
+ }
10154
+ return;
10155
+ }
10156
+ function usesPerTurnControl(model) {
10157
+ return resolveClaudeModelCapabilities(model)?.effortMarkers === "with-adaptive-thinking";
10158
+ }
10159
+ function sendsPerTurnControlBeta(model) {
10160
+ return resolveClaudeModelCapabilities(model)?.claudeCodeBetas.main.includes(PER_TURN_CONTROL_BETA) ?? false;
10161
+ }
10162
+ function supportsPerMessageEffort(body) {
10163
+ if (pinsEffortOnEveryRequest(body.model))
10164
+ return true;
10165
+ return usesPerTurnControl(body.model) && isRecord5(body.thinking) && body.thinking.type === "adaptive";
10166
+ }
10167
+ function defaultAdaptiveEffort(model) {
10168
+ return resolveClaudeModelCapabilities(model)?.efforts.default ?? "high";
10169
+ }
10170
+ function compactTransitions(transitions) {
10171
+ const compacted = [];
10172
+ for (const transition of transitions) {
10173
+ if (!Number.isSafeInteger(transition.afterAssistantMessages) || transition.afterAssistantMessages < 0 || !normalizeAdaptiveEffort(transition.effort)) {
10174
+ continue;
10175
+ }
10176
+ const normalized = {
10177
+ afterAssistantMessages: transition.afterAssistantMessages,
10178
+ effort: transition.effort
10179
+ };
10180
+ const previous = compacted.at(-1);
10181
+ if (previous && previous.afterAssistantMessages === normalized.afterAssistantMessages) {
10182
+ previous.effort = normalized.effort;
10183
+ continue;
10184
+ }
10185
+ if (previous?.effort === normalized.effort)
10186
+ continue;
10187
+ compacted.push(normalized);
10188
+ }
10189
+ return compacted;
10190
+ }
10191
+ function applyMidConversationOutputConfig(body, transitions) {
10192
+ if (!supportsPerMessageEffort(body) || !Array.isArray(body.messages)) {
10193
+ return { applied: false, inserted: 0 };
10194
+ }
10195
+ const compacted = compactTransitions(transitions);
10196
+ const pinsEveryRequest = pinsEffortOnEveryRequest(body.model);
10197
+ if (!pinsEveryRequest && compacted.length < 2) {
10198
+ return { applied: false, inserted: 0 };
10199
+ }
10200
+ const currentOutputConfig = isRecord5(body.output_config) ? body.output_config : {};
10201
+ const baseline = compacted[0]?.effort ?? normalizeAdaptiveEffort(currentOutputConfig.effort) ?? defaultAdaptiveEffort(body.model);
10202
+ const pinnedOutputConfig = { ...currentOutputConfig, effort: baseline };
10203
+ if (pinsEveryRequest)
10204
+ body.output_config = pinnedOutputConfig;
10205
+ if (compacted.length < 2)
10206
+ return { applied: true, inserted: 0 };
10207
+ const messages = body.messages;
10208
+ const transitionsByBoundary = new Map;
10209
+ for (const transition of compacted.slice(1)) {
10210
+ transitionsByBoundary.set(transition.afterAssistantMessages, transition.effort);
10211
+ }
10212
+ let assistantMessages = 0;
10213
+ let activeEffort = baseline;
10214
+ let inserted = 0;
10215
+ const rewritten = [];
10216
+ for (const message of messages) {
10217
+ if (isRecord5(message) && message.role === "user" && transitionsByBoundary.has(assistantMessages)) {
10218
+ const effort = transitionsByBoundary.get(assistantMessages);
10219
+ if (effort && effort !== activeEffort) {
10220
+ rewritten.push({
10221
+ role: "system",
10222
+ content: [],
10223
+ output_config: { effort }
10224
+ });
10225
+ activeEffort = effort;
10226
+ inserted++;
10227
+ }
10228
+ }
10229
+ rewritten.push(message);
10230
+ if (isRecord5(message) && message.role === "assistant")
10231
+ assistantMessages++;
10232
+ }
10233
+ if (!pinsEveryRequest && inserted === 0) {
10234
+ return { applied: false, inserted: 0 };
10235
+ }
10236
+ body.output_config = pinnedOutputConfig;
10237
+ body.messages = rewritten;
10238
+ return { applied: true, inserted };
10239
+ }
10072
10240
  // src/model-remap.ts
10073
10241
  function getEnv(name) {
10074
10242
  const value = process.env[name]?.trim();
@@ -10116,6 +10284,130 @@ function remapRequestBodyModel(parsed) {
10116
10284
  parsed.model = remapped;
10117
10285
  return true;
10118
10286
  }
10287
+ // src/models.ts
10288
+ var CLAUDE_FABLE_5_MODEL_ID = "claude-fable-5";
10289
+ var CLAUDE_MYTHOS_5_MODEL_ID = "claude-mythos-5";
10290
+ var CLAUDE_FABLE_5_1_MODEL_ID = "claude-fable-5-1";
10291
+ var CLAUDE_MYTHOS_5_1_MODEL_ID = "claude-mythos-5-1";
10292
+ var CLAUDE_HAIKU_4_5_MODEL_ID = "claude-haiku-4-5";
10293
+ var CLAUDE_HAIKU_4_5_PRICING = {
10294
+ input: 1,
10295
+ output: 5
10296
+ };
10297
+ var CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS = [
10298
+ CLAUDE_FABLE_5_1_MODEL_ID,
10299
+ CLAUDE_MYTHOS_5_1_MODEL_ID
10300
+ ];
10301
+ var CLAUDE_FABLE_MYTHOS_5_MODEL_IDS = [
10302
+ CLAUDE_FABLE_5_MODEL_ID,
10303
+ CLAUDE_MYTHOS_5_MODEL_ID,
10304
+ ...CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS
10305
+ ];
10306
+ var CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING = {
10307
+ type: "adaptive",
10308
+ display: "summarized"
10309
+ };
10310
+ var FABLE_5_CATALOGUE = getClaudeModelCatalogue(CLAUDE_FABLE_5_MODEL_ID);
10311
+ var FABLE_5_1_CATALOGUE = getClaudeModelCatalogue(CLAUDE_FABLE_5_1_MODEL_ID);
10312
+ var CLAUDE_FABLE_MYTHOS_5_PRICING = FABLE_5_CATALOGUE.pricing;
10313
+ var CLAUDE_FABLE_MYTHOS_5_1_PRICING = FABLE_5_1_CATALOGUE.pricing;
10314
+ var CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW = FABLE_5_CATALOGUE.contextWindow;
10315
+ var CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS = FABLE_5_CATALOGUE.maxOutputTokens;
10316
+ var CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE = FABLE_5_CATALOGUE.releaseDate;
10317
+ var CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE = FABLE_5_1_CATALOGUE.releaseDate;
10318
+ function isFableOrMythosRow(row) {
10319
+ return row?.family === "fable" || row?.family === "mythos";
10320
+ }
10321
+ var CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS = Object.fromEntries(CLAUDE_FABLE_MYTHOS_5_MODEL_IDS.map((id) => {
10322
+ const row = getClaudeModelCapabilities(id);
10323
+ return [
10324
+ id,
10325
+ { id, name: row.name, ...row.limited && { limited: true } }
10326
+ ];
10327
+ }));
10328
+ var CLAUDE_FABLE_MYTHOS_5_1_MODEL_SPECS = {
10329
+ [CLAUDE_FABLE_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_FABLE_5_1_MODEL_ID],
10330
+ [CLAUDE_MYTHOS_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_MYTHOS_5_1_MODEL_ID]
10331
+ };
10332
+ function resolvedModelId(model) {
10333
+ return resolveClaudeModelCapabilities(model)?.id;
10334
+ }
10335
+ function isClaudeFableOrMythos5Model(model) {
10336
+ return isFableOrMythosRow(resolveClaudeModelCapabilities(model));
10337
+ }
10338
+ function isClaudeFableOrMythos51Model(model) {
10339
+ const id = resolvedModelId(model);
10340
+ return CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS.includes(id);
10341
+ }
10342
+ function isClaudeFable51Model(model) {
10343
+ return resolvedModelId(model) === CLAUDE_FABLE_5_1_MODEL_ID;
10344
+ }
10345
+ function getClaudeFableMythos5ReleaseDate(model) {
10346
+ return isClaudeFableOrMythos51Model(model) ? CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE : CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE;
10347
+ }
10348
+ var CLAUDE_SONNET_5_MODEL_ID = "claude-sonnet-5";
10349
+ var CLAUDE_SONNET_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
10350
+ function isClaudeSonnet5Model(model) {
10351
+ return resolvedModelId(model) === CLAUDE_SONNET_5_MODEL_ID;
10352
+ }
10353
+ var CLAUDE_SONNET_5_5_MODEL_ID = "claude-sonnet-5-5";
10354
+ var SONNET_5_5_CATALOGUE = getClaudeModelCatalogue(CLAUDE_SONNET_5_5_MODEL_ID);
10355
+ var CLAUDE_SONNET_5_5_RELEASE_DATE = SONNET_5_5_CATALOGUE.releaseDate;
10356
+ var CLAUDE_SONNET_5_5_CONTEXT_WINDOW = SONNET_5_5_CATALOGUE.contextWindow;
10357
+ var CLAUDE_SONNET_5_5_MAX_OUTPUT_TOKENS = SONNET_5_5_CATALOGUE.maxOutputTokens;
10358
+ var CLAUDE_SONNET_5_5_PRICING = SONNET_5_5_CATALOGUE.pricing;
10359
+ var CLAUDE_SONNET_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
10360
+ function isClaudeSonnet55Model(model) {
10361
+ return resolvedModelId(model) === CLAUDE_SONNET_5_5_MODEL_ID;
10362
+ }
10363
+ var CLAUDE_HAIKU_5_5_MODEL_ID = "claude-haiku-5-5";
10364
+ var HAIKU_5_5_CATALOGUE = getClaudeModelCatalogue(CLAUDE_HAIKU_5_5_MODEL_ID);
10365
+ var HAIKU_5_5_LONG_CONTEXT = HAIKU_5_5_CATALOGUE.longContext;
10366
+ if (!HAIKU_5_5_LONG_CONTEXT) {
10367
+ throw new Error("Haiku 5.5 capability row lacks long-context pricing");
10368
+ }
10369
+ var CLAUDE_HAIKU_5_5_RELEASE_DATE = HAIKU_5_5_CATALOGUE.releaseDate;
10370
+ var CLAUDE_HAIKU_5_5_CONTEXT_WINDOW = HAIKU_5_5_CATALOGUE.contextWindow;
10371
+ var CLAUDE_HAIKU_5_5_MAX_OUTPUT_TOKENS = HAIKU_5_5_CATALOGUE.maxOutputTokens;
10372
+ var CLAUDE_HAIKU_5_5_LONG_CONTEXT_THRESHOLD = HAIKU_5_5_LONG_CONTEXT.inputTokensAbove;
10373
+ var CLAUDE_HAIKU_5_5_PRICING = HAIKU_5_5_CATALOGUE.pricing;
10374
+ var CLAUDE_HAIKU_5_5_LONG_CONTEXT_PRICING = HAIKU_5_5_LONG_CONTEXT.pricing;
10375
+ var CLAUDE_HAIKU_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
10376
+ function isClaudeHaiku55Model(model) {
10377
+ return resolvedModelId(model) === CLAUDE_HAIKU_5_5_MODEL_ID;
10378
+ }
10379
+ var CLAUDE_OPUS_5_MODEL_ID = "claude-opus-5";
10380
+ var CLAUDE_OPUS_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
10381
+ function isClaudeOpus5Model(model) {
10382
+ return resolvedModelId(model) === CLAUDE_OPUS_5_MODEL_ID;
10383
+ }
10384
+ var CLAUDE_OPUS_5_5_MODEL_ID = "claude-opus-5-5";
10385
+ var OPUS_5_5_CATALOGUE = getClaudeModelCatalogue(CLAUDE_OPUS_5_5_MODEL_ID);
10386
+ var CLAUDE_OPUS_5_5_RELEASE_DATE = OPUS_5_5_CATALOGUE.releaseDate;
10387
+ var CLAUDE_OPUS_5_5_CONTEXT_WINDOW = OPUS_5_5_CATALOGUE.contextWindow;
10388
+ var CLAUDE_OPUS_5_5_MAX_OUTPUT_TOKENS = OPUS_5_5_CATALOGUE.maxOutputTokens;
10389
+ var CLAUDE_OPUS_5_5_PRICING = OPUS_5_5_CATALOGUE.pricing;
10390
+ var CLAUDE_OPUS_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
10391
+ function isClaudeOpus55Model(model) {
10392
+ return resolvedModelId(model) === CLAUDE_OPUS_5_5_MODEL_ID;
10393
+ }
10394
+ function isClaudeOpus5FamilyModel(model) {
10395
+ return isClaudeOpus5Model(model) || isClaudeOpus55Model(model);
10396
+ }
10397
+ function isOpenAIReasoningSignature(value) {
10398
+ if (typeof value !== "string")
10399
+ return false;
10400
+ if (value.startsWith("gAAAA"))
10401
+ return true;
10402
+ if (!value.startsWith("{"))
10403
+ return false;
10404
+ try {
10405
+ const parsed = JSON.parse(value);
10406
+ return parsed.type === "reasoning" && typeof parsed.id === "string" && parsed.id.startsWith("rs_") && typeof parsed.encrypted_content === "string" && parsed.encrypted_content.startsWith("gAAAA");
10407
+ } catch {
10408
+ return false;
10409
+ }
10410
+ }
10119
10411
  // src/native-account-runtime.ts
10120
10412
  import { randomUUID as randomUUID15 } from "node:crypto";
10121
10413
 
@@ -10356,7 +10648,7 @@ function canonicalJson(value) {
10356
10648
  const encode = (item) => {
10357
10649
  if (Array.isArray(item))
10358
10650
  return `[${item.map(encode).join(",")}]`;
10359
- if (isRecord7(item))
10651
+ if (isRecord6(item))
10360
10652
  return `{${Object.keys(item).sort().map((key) => `${JSON.stringify(key)}:${encode(item[key])}`).join(",")}}`;
10361
10653
  return JSON.stringify(item);
10362
10654
  };
@@ -10366,12 +10658,12 @@ function canonicalDigest(value) {
10366
10658
  return createHash6("sha256").update(canonicalJson(value)).digest("hex");
10367
10659
  }
10368
10660
  function parseReservation(raw) {
10369
- if (!isRecord7(raw) || Object.keys(raw).length !== 1 || typeof raw.reservation !== "string" || !raw.reservation)
10661
+ if (!isRecord6(raw) || Object.keys(raw).length !== 1 || typeof raw.reservation !== "string" || !raw.reservation)
10370
10662
  return;
10371
10663
  return { reservation: raw.reservation };
10372
10664
  }
10373
10665
  function parseStagedStamp(raw) {
10374
- if (!isRecord7(raw) || typeof raw.reservation !== "string" || !raw.reservation || typeof raw.disabledReason !== "string")
10666
+ if (!isRecord6(raw) || typeof raw.reservation !== "string" || !raw.reservation || typeof raw.disabledReason !== "string")
10375
10667
  return;
10376
10668
  if (Object.keys(raw).some((key) => !["reservation", "label", "disabledReason", "providerState"].includes(key)))
10377
10669
  return;
@@ -10382,7 +10674,7 @@ function parseStagedStamp(raw) {
10382
10674
  return raw;
10383
10675
  }
10384
10676
  var PROVIDER_STATE_KEY = "commonAuthProviderState";
10385
- function isRecord7(value) {
10677
+ function isRecord6(value) {
10386
10678
  return value != null && typeof value === "object" && !Array.isArray(value);
10387
10679
  }
10388
10680
  var UNSAFE_IDS = new Set(["__proto__", "constructor", "prototype"]);
@@ -10446,7 +10738,7 @@ function providerStateDigest(codec, value) {
10446
10738
  function boundProviderStateDigest(account, credential, credentialEpoch, identity) {
10447
10739
  if (!credential || credentialEpoch === undefined)
10448
10740
  return;
10449
- if (!isRecord7(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
10741
+ if (!isRecord6(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
10450
10742
  return;
10451
10743
  const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
10452
10744
  if (!stamp || stamp.providerState === undefined || stamp.digest !== credentialDigest(credential) || stamp.credentialEpoch !== credentialEpoch || stamp.binding?.identity !== identity)
@@ -10457,7 +10749,7 @@ function isCredentialEpoch(value) {
10457
10749
  return Number.isSafeInteger(value) && value >= 1;
10458
10750
  }
10459
10751
  function parseStamp(raw) {
10460
- if (!isRecord7(raw))
10752
+ if (!isRecord6(raw))
10461
10753
  return;
10462
10754
  const epoch = raw.credentialEpoch;
10463
10755
  if (!isCredentialEpoch(epoch))
@@ -10482,7 +10774,7 @@ function parseStamp(raw) {
10482
10774
  if (!("binding" in raw))
10483
10775
  return "dispatch" in raw || "replace" in raw || "providerState" in raw || "staged" in raw ? undefined : { credentialEpoch: epoch, digest: raw.digest };
10484
10776
  const binding = raw.binding;
10485
- if (!isRecord7(binding))
10777
+ if (!isRecord6(binding))
10486
10778
  return;
10487
10779
  if ("identity" in binding && (typeof binding.identity !== "string" || !binding.identity))
10488
10780
  return;
@@ -10513,7 +10805,7 @@ function bindingAgrees(binding, credential, identity) {
10513
10805
  function stampStatusOf(credential, credentialEpoch, identity, account) {
10514
10806
  if (!credential)
10515
10807
  return "none";
10516
- if (!isRecord7(account) || !Object.hasOwn(account, CREDENTIAL_STAMP_KEY))
10808
+ if (!isRecord6(account) || !Object.hasOwn(account, CREDENTIAL_STAMP_KEY))
10517
10809
  return "missing";
10518
10810
  const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
10519
10811
  if (!stamp)
@@ -10536,7 +10828,7 @@ function classifyConfig(read) {
10536
10828
  if ("parseError" in read)
10537
10829
  return { status: "error", reason: "config file is not valid JSON" };
10538
10830
  const value = read.value;
10539
- if (!isRecord7(value))
10831
+ if (!isRecord6(value))
10540
10832
  return { status: "error", reason: "config root is not an object" };
10541
10833
  if ("accounts" in value && !Array.isArray(value.accounts))
10542
10834
  return { status: "error", reason: "config accounts is not an array" };
@@ -10544,7 +10836,7 @@ function classifyConfig(read) {
10544
10836
  return Array.isArray(value.accounts) ? { status: "pending-migration", config: value } : { status: "ready", exists: true, config: value };
10545
10837
  }
10546
10838
  const pool = value[POOL_KEY];
10547
- if (!isRecord7(pool))
10839
+ if (!isRecord6(pool))
10548
10840
  return { status: "error", reason: `${POOL_KEY} is not an object` };
10549
10841
  const version = pool.schemaVersion;
10550
10842
  if (typeof version !== "number" || !Number.isInteger(version) || version < 1)
@@ -10554,7 +10846,7 @@ function classifyConfig(read) {
10554
10846
  status: "error",
10555
10847
  reason: `${POOL_KEY}.schemaVersion ${version} is newer than ${POOL_SCHEMA_VERSION}`
10556
10848
  };
10557
- if (POOL_ROWS_KEY in pool && !isRecord7(pool[POOL_ROWS_KEY]))
10849
+ if (POOL_ROWS_KEY in pool && !isRecord6(pool[POOL_ROWS_KEY]))
10558
10850
  return {
10559
10851
  status: "error",
10560
10852
  reason: `${POOL_KEY}.${POOL_ROWS_KEY} is not an object`
@@ -10566,9 +10858,9 @@ function classifyState(read) {
10566
10858
  return { status: "ready", exists: false, state: {} };
10567
10859
  if ("parseError" in read)
10568
10860
  return { status: "error", reason: "state file is not valid JSON" };
10569
- if (!isRecord7(read.value))
10861
+ if (!isRecord6(read.value))
10570
10862
  return { status: "error", reason: "state root is not an object" };
10571
- if ("accounts" in read.value && !isRecord7(read.value.accounts))
10863
+ if ("accounts" in read.value && !isRecord6(read.value.accounts))
10572
10864
  return { status: "error", reason: "state accounts is not an object" };
10573
10865
  return { status: "ready", exists: true, state: read.value };
10574
10866
  }
@@ -10577,16 +10869,16 @@ function rosterOf(config) {
10577
10869
  }
10578
10870
  function entriesOf(config) {
10579
10871
  const pool = config[POOL_KEY];
10580
- if (!isRecord7(pool))
10872
+ if (!isRecord6(pool))
10581
10873
  return {};
10582
10874
  const rows = pool[POOL_ROWS_KEY];
10583
- return isRecord7(rows) ? rows : {};
10875
+ return isRecord6(rows) ? rows : {};
10584
10876
  }
10585
10877
  function stateAccountsOf(state) {
10586
- return isRecord7(state.accounts) ? state.accounts : {};
10878
+ return isRecord6(state.accounts) ? state.accounts : {};
10587
10879
  }
10588
10880
  function rosterRowProblem(raw) {
10589
- if (!isRecord7(raw))
10881
+ if (!isRecord6(raw))
10590
10882
  return "not an object";
10591
10883
  const problem = idProblem(raw.id);
10592
10884
  if (problem)
@@ -10598,7 +10890,7 @@ function rosterRowProblem(raw) {
10598
10890
  return "unknown type";
10599
10891
  }
10600
10892
  function parseEntry(raw, codec) {
10601
- if (!isRecord7(raw))
10893
+ if (!isRecord6(raw))
10602
10894
  return;
10603
10895
  const epoch = raw.credentialEpoch;
10604
10896
  if (!isCredentialEpoch(epoch))
@@ -10620,7 +10912,7 @@ function parseEntry(raw, codec) {
10620
10912
  };
10621
10913
  }
10622
10914
  function credentialFor(raw, stateEntry) {
10623
- if (!isRecord7(stateEntry))
10915
+ if (!isRecord6(stateEntry))
10624
10916
  return;
10625
10917
  if (raw.type === "api") {
10626
10918
  const apiKey = typeof stateEntry.apiKey === "string" ? stateEntry.apiKey.trim() : "";
@@ -10647,23 +10939,23 @@ function credentialFor(raw, stateEntry) {
10647
10939
  };
10648
10940
  }
10649
10941
  function rosterRowIn(config, id) {
10650
- return rosterOf(config).find((raw) => isRecord7(raw) && raw.id === id);
10942
+ return rosterOf(config).find((raw) => isRecord6(raw) && raw.id === id);
10651
10943
  }
10652
10944
  function ensurePool(config) {
10653
- if (!isRecord7(config[POOL_KEY]))
10945
+ if (!isRecord6(config[POOL_KEY]))
10654
10946
  config[POOL_KEY] = {};
10655
10947
  return config[POOL_KEY];
10656
10948
  }
10657
10949
  function ensureEntries(config) {
10658
10950
  const pool = ensurePool(config);
10659
- if (!isRecord7(pool[POOL_ROWS_KEY]))
10951
+ if (!isRecord6(pool[POOL_ROWS_KEY]))
10660
10952
  pool[POOL_ROWS_KEY] = {};
10661
10953
  return pool[POOL_ROWS_KEY];
10662
10954
  }
10663
10955
  function entryIn(config, id) {
10664
10956
  const entries = entriesOf(config);
10665
10957
  const entry = Object.hasOwn(entries, id) ? entries[id] : undefined;
10666
- return isRecord7(entry) ? entry : undefined;
10958
+ return isRecord6(entry) ? entry : undefined;
10667
10959
  }
10668
10960
  function setEntryIn(config, id, entry) {
10669
10961
  Object.defineProperty(ensureEntries(config), id, {
@@ -10675,10 +10967,10 @@ function setEntryIn(config, id, entry) {
10675
10967
  }
10676
10968
  function retiredEpochIn(config, id) {
10677
10969
  const pool = config[POOL_KEY];
10678
- if (!isRecord7(pool))
10970
+ if (!isRecord6(pool))
10679
10971
  return;
10680
10972
  const retired = pool[POOL_RETIRED_EPOCHS_KEY];
10681
- if (!isRecord7(retired) || !Object.hasOwn(retired, id))
10973
+ if (!isRecord6(retired) || !Object.hasOwn(retired, id))
10682
10974
  return;
10683
10975
  const epoch = retired[id];
10684
10976
  return isCredentialEpoch(epoch) ? epoch : undefined;
@@ -10695,7 +10987,7 @@ function retireEpochsIn(config, dropped) {
10695
10987
  if (ids.length === 0)
10696
10988
  return;
10697
10989
  const pool = ensurePool(config);
10698
- const previous = isRecord7(pool[POOL_RETIRED_EPOCHS_KEY]) ? pool[POOL_RETIRED_EPOCHS_KEY] : {};
10990
+ const previous = isRecord6(pool[POOL_RETIRED_EPOCHS_KEY]) ? pool[POOL_RETIRED_EPOCHS_KEY] : {};
10699
10991
  const next = {};
10700
10992
  const define = (id, epoch) => Object.defineProperty(next, id, {
10701
10993
  value: epoch,
@@ -10717,17 +11009,17 @@ function buildRawRows(config, state, codec, providerCodec) {
10717
11009
  const rows = [];
10718
11010
  for (const raw of rosterOf(config)) {
10719
11011
  const problem = rosterRowProblem(raw);
10720
- const id = isRecord7(raw) && typeof raw.id === "string" ? raw.id : undefined;
11012
+ const id = isRecord6(raw) && typeof raw.id === "string" ? raw.id : undefined;
10721
11013
  const rawEntry = id === undefined ? undefined : entries[id];
10722
- const reserved = isRecord7(rawEntry) && Object.hasOwn(rawEntry, "staged");
11014
+ const reserved = isRecord6(rawEntry) && Object.hasOwn(rawEntry, "staged");
10723
11015
  const staged = reserved ? parseReservation(rawEntry.staged) : undefined;
10724
- if (problem || !isRecord7(raw) || id === undefined || seen.has(id)) {
11016
+ if (problem || !isRecord6(raw) || id === undefined || seen.has(id)) {
10725
11017
  if (id !== undefined && !seen.has(id))
10726
11018
  seen.add(id);
10727
11019
  if (id !== undefined)
10728
11020
  rows.push({
10729
11021
  id,
10730
- type: isRecord7(raw) && raw.type === "api" ? "api" : "oauth",
11022
+ type: isRecord6(raw) && raw.type === "api" ? "api" : "oauth",
10731
11023
  enabled: false,
10732
11024
  needsFirstReading: true,
10733
11025
  hasEntry: Object.hasOwn(entries, id),
@@ -10774,7 +11066,7 @@ function buildRawRows(config, state, codec, providerCodec) {
10774
11066
  return rows;
10775
11067
  }
10776
11068
  function providerStateFields(account, credential, credentialEpoch, identity, codec) {
10777
- if (!isRecord7(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
11069
+ if (!isRecord6(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
10778
11070
  return {};
10779
11071
  const digest = boundProviderStateDigest(account, credential, credentialEpoch, identity);
10780
11072
  if (digest === undefined)
@@ -10834,7 +11126,7 @@ function storedCredential(credential, lastRefreshedAt) {
10834
11126
  };
10835
11127
  }
10836
11128
  function credentialProblem(credential, options = {}) {
10837
- if (!isRecord7(credential))
11129
+ if (!isRecord6(credential))
10838
11130
  return "credential must be an object";
10839
11131
  if (credential.type === "oauth") {
10840
11132
  if (typeof credential.refresh !== "string" || !credential.refresh.trim())
@@ -10858,10 +11150,10 @@ function credentialProblem(credential, options = {}) {
10858
11150
  var TRANSITION_STAMP_KEY = "transition";
10859
11151
  var TRANSITION_MARK_KEY = "transitionMark";
10860
11152
  function stampedTransition(rawStamp) {
10861
- if (!isRecord7(rawStamp))
11153
+ if (!isRecord6(rawStamp))
10862
11154
  return;
10863
11155
  const raw = rawStamp[TRANSITION_STAMP_KEY];
10864
- if (!isRecord7(raw))
11156
+ if (!isRecord6(raw))
10865
11157
  return;
10866
11158
  if (typeof raw.mark !== "string" || raw.mark.length === 0)
10867
11159
  return;
@@ -10904,13 +11196,13 @@ function isReplaceStamp(stamp) {
10904
11196
  return stamp.replace === true || stamp.dispatch === undefined;
10905
11197
  }
10906
11198
  function tornStamps(config, state, codec, options = {}) {
10907
- const accounts = isRecord7(state.accounts) ? state.accounts : {};
11199
+ const accounts = isRecord6(state.accounts) ? state.accounts : {};
10908
11200
  const torn = new Map;
10909
11201
  for (const row of buildRawRows(config, state, codec)) {
10910
11202
  if (row.invalid || row.staged || !row.credential)
10911
11203
  continue;
10912
11204
  const account = Object.hasOwn(accounts, row.id) ? accounts[row.id] : undefined;
10913
- if (!isRecord7(account))
11205
+ if (!isRecord6(account))
10914
11206
  continue;
10915
11207
  const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
10916
11208
  if (!stamp?.binding)
@@ -11115,7 +11407,7 @@ class Transaction {
11115
11407
  return entry && Object.hasOwn(entry, "staged") ? entry.staged : undefined;
11116
11408
  }
11117
11409
  const stamp = this.stateAccount(id)?.[CREDENTIAL_STAMP_KEY];
11118
- return isRecord7(stamp) && Object.hasOwn(stamp, "staged") ? stamp.staged : undefined;
11410
+ return isRecord6(stamp) && Object.hasOwn(stamp, "staged") ? stamp.staged : undefined;
11119
11411
  }
11120
11412
  assertNotStaged(id) {
11121
11413
  assertNotReserved(this.info.operation, id, this.reservation(id));
@@ -11131,7 +11423,7 @@ class Transaction {
11131
11423
  }
11132
11424
  dropRosterRows(id) {
11133
11425
  const roster = this.roster();
11134
- const kept = roster.filter((raw) => !(isRecord7(raw) && raw.id === id));
11426
+ const kept = roster.filter((raw) => !(isRecord6(raw) && raw.id === id));
11135
11427
  this.config.accounts = kept;
11136
11428
  return roster.length - kept.length;
11137
11429
  }
@@ -11153,16 +11445,16 @@ class Transaction {
11153
11445
  await this.commitConfig({ counted: false });
11154
11446
  }
11155
11447
  stateAccount(id) {
11156
- const accounts = isRecord7(this.state.accounts) ? this.state.accounts : {};
11448
+ const accounts = isRecord6(this.state.accounts) ? this.state.accounts : {};
11157
11449
  const entry = Object.hasOwn(accounts, id) ? accounts[id] : undefined;
11158
- return isRecord7(entry) ? entry : undefined;
11450
+ return isRecord6(entry) ? entry : undefined;
11159
11451
  }
11160
11452
  dropStateAccount(id) {
11161
- if (isRecord7(this.state.accounts) && Object.hasOwn(this.state.accounts, id))
11453
+ if (isRecord6(this.state.accounts) && Object.hasOwn(this.state.accounts, id))
11162
11454
  delete this.state.accounts[id];
11163
11455
  }
11164
11456
  setStateAccount(id, fields) {
11165
- if (!isRecord7(this.state.accounts))
11457
+ if (!isRecord6(this.state.accounts))
11166
11458
  this.state.accounts = {};
11167
11459
  Object.defineProperty(this.state.accounts, id, {
11168
11460
  value: fields,
@@ -11175,11 +11467,11 @@ class Transaction {
11175
11467
  const roster = this.roster();
11176
11468
  const rosterIds = new Set;
11177
11469
  for (const raw of roster)
11178
- if (isRecord7(raw) && typeof raw.id === "string")
11470
+ if (isRecord6(raw) && typeof raw.id === "string")
11179
11471
  rosterIds.add(raw.id);
11180
11472
  const dropped = new Set;
11181
11473
  for (const raw of rosterOf(this.snapshot.config))
11182
- if (isRecord7(raw) && typeof raw.id === "string" && !rosterIds.has(raw.id))
11474
+ if (isRecord6(raw) && typeof raw.id === "string" && !rosterIds.has(raw.id))
11183
11475
  dropped.add(raw.id);
11184
11476
  for (const id of Object.keys(this.entries()))
11185
11477
  if (!rosterIds.has(id))
@@ -11221,7 +11513,7 @@ class Transaction {
11221
11513
  const next = {
11222
11514
  ...this.state,
11223
11515
  version: LEGACY_STORE_VERSION,
11224
- accounts: isRecord7(this.state.accounts) ? this.state.accounts : {}
11516
+ accounts: isRecord6(this.state.accounts) ? this.state.accounts : {}
11225
11517
  };
11226
11518
  await this.write(this.ctx.statePath, next, "state", true, options.durable ?? false);
11227
11519
  this.state = next;
@@ -11416,11 +11708,11 @@ async function readRow(rt, operation, id) {
11416
11708
  const row = result.rows.find((candidate) => candidate.id === id);
11417
11709
  const entry = entryIn(result.config, id);
11418
11710
  const accounts = result.state.accounts;
11419
- const account = isRecord7(accounts) && Object.hasOwn(accounts, id) ? accounts[id] : undefined;
11420
- const stamp = isRecord7(account) ? account[CREDENTIAL_STAMP_KEY] : undefined;
11711
+ const account = isRecord6(accounts) && Object.hasOwn(accounts, id) ? accounts[id] : undefined;
11712
+ const stamp = isRecord6(account) ? account[CREDENTIAL_STAMP_KEY] : undefined;
11421
11713
  if (row && !["enable", "disable"].includes(operation) && entry && Object.hasOwn(entry, "staged"))
11422
11714
  assertNotReserved(operation, id, entry.staged);
11423
- if (!row && isRecord7(stamp) && Object.hasOwn(stamp, "staged"))
11715
+ if (!row && isRecord6(stamp) && Object.hasOwn(stamp, "staged"))
11424
11716
  assertNotReserved(operation, id, stamp.staged);
11425
11717
  if (!row)
11426
11718
  throw unknownRow(operation, id);
@@ -11552,7 +11844,7 @@ async function updateProviderStateRow(rt, id, fence, mutator, options = {}) {
11552
11844
  throw refusal(operation, id, "invalid-input", "the store was opened without a provider-state codec");
11553
11845
  if (typeof mutator !== "function")
11554
11846
  throw refusal(operation, id, "invalid-input", "a mutator is required");
11555
- const captured = isRecord7(fence) ? fence.credentialEpoch : undefined;
11847
+ const captured = isRecord6(fence) ? fence.credentialEpoch : undefined;
11556
11848
  if (!isCredentialEpoch(captured))
11557
11849
  throw refusal(operation, id, "invalid-input", "the credential epoch the provider state was read at is required");
11558
11850
  const { row: seen } = await readRow(rt, operation, id);
@@ -11596,7 +11888,7 @@ async function planProviderStateIn(tx, codec, operation, row, mutator, declinabl
11596
11888
  const account = tx.stateAccount(id);
11597
11889
  const rawStamp = account?.[CREDENTIAL_STAMP_KEY];
11598
11890
  const stamp = parseStamp(rawStamp);
11599
- if (!isRecord7(rawStamp) || !stamp?.binding || stamp.digest !== credentialDigest(credential) || stamp.credentialEpoch !== epoch || stamp.binding.identity !== row.identity)
11891
+ if (!isRecord6(rawStamp) || !stamp?.binding || stamp.digest !== credentialDigest(credential) || stamp.credentialEpoch !== epoch || stamp.binding.identity !== row.identity)
11600
11892
  throw refusal(operation, id, "unbound-credential", `row ${id}'s credential carries no stamp of this store to bind a provider state to (stamp ${row.stamp}); rotate or replace it first`);
11601
11893
  const current = row.providerState === undefined ? undefined : structuredClone(row.providerState);
11602
11894
  const returned = await runInsideHook(operation, () => mutator(current, row));
@@ -11672,7 +11964,7 @@ function onRowEndpoint(tx, id, credential) {
11672
11964
  if (credential.type !== "api")
11673
11965
  return credential;
11674
11966
  const raw = tx.rosterRow(id);
11675
- if (!isRecord7(raw)) {
11967
+ if (!isRecord6(raw)) {
11676
11968
  if (credential.baseURL === undefined)
11677
11969
  throw refusal(tx.info.operation, id, "invalid-input", "api credential needs a valid baseURL");
11678
11970
  return { ...credential, baseURL: credential.baseURL };
@@ -11691,7 +11983,7 @@ function onRowEndpoint(tx, id, credential) {
11691
11983
  function bindingInTx(tx, id, stored, learnt) {
11692
11984
  const raw = tx.rosterRow(id);
11693
11985
  const projected = tx.row(id);
11694
- const identity = learnt ?? (projected ? projected.identity : isRecord7(raw) && typeof raw.accountId === "string" && raw.accountId ? raw.accountId : undefined);
11986
+ const identity = learnt ?? (projected ? projected.identity : isRecord6(raw) && typeof raw.accountId === "string" && raw.accountId ? raw.accountId : undefined);
11695
11987
  return {
11696
11988
  ...identity !== undefined ? { identity } : {},
11697
11989
  ...stored.type === "api" ? {
@@ -11775,7 +12067,7 @@ function requireUsableRow(operation, id, row, credential) {
11775
12067
  return row;
11776
12068
  }
11777
12069
  function validateAttribution(operation, id, fence) {
11778
- if (fence !== undefined && !isCredentialEpoch(isRecord7(fence) ? fence.credentialEpoch : undefined))
12070
+ if (fence !== undefined && !isCredentialEpoch(isRecord6(fence) ? fence.credentialEpoch : undefined))
11779
12071
  throw refusal(operation, id, "invalid-input", "the attribution must name a credential epoch that is a positive safe integer");
11780
12072
  }
11781
12073
  function assertRowAttribution(operation, id, row, fence) {
@@ -11930,7 +12222,7 @@ async function addRow(rt, input, options = {}) {
11930
12222
  const mode = options.onExisting ?? "rotate";
11931
12223
  if (input.stage !== undefined && mode === "rotate")
11932
12224
  throw refusal("add", id, "invalid-input", "a staged add needs onExisting: 'refuse' or 'stage-duplicate'");
11933
- if (!["rotate", "refuse", "stage-duplicate"].includes(mode) || input.stage !== undefined && (label !== undefined && typeof label !== "string" || identity !== undefined && (typeof identity !== "string" || !identity)) || input.disabled !== undefined && (!isRecord7(input.disabled) || typeof input.disabled.reason !== "string") || input.stage !== undefined && (!isRecord7(input.stage) || typeof input.stage.reservation !== "string" || !input.stage.reservation || !input.disabled) || mode === "stage-duplicate" && (!input.disabled || !input.stage))
12225
+ if (!["rotate", "refuse", "stage-duplicate"].includes(mode) || input.stage !== undefined && (label !== undefined && typeof label !== "string" || identity !== undefined && (typeof identity !== "string" || !identity)) || input.disabled !== undefined && (!isRecord6(input.disabled) || typeof input.disabled.reason !== "string") || input.stage !== undefined && (!isRecord6(input.stage) || typeof input.stage.reservation !== "string" || !input.stage.reservation || !input.disabled) || mode === "stage-duplicate" && (!input.disabled || !input.stage))
11934
12226
  throw refusal("add", id, "invalid-input", "staging requires a reservation and a disabled reason");
11935
12227
  const incoming = input.providerState === undefined ? undefined : acceptProviderState(ctx.providerState, "add", id, input.providerState);
11936
12228
  await locks.acquire(rowLockSpec(rt, { id, identity }));
@@ -11940,12 +12232,12 @@ async function addRow(rt, input, options = {}) {
11940
12232
  await locks.acquire(extra);
11941
12233
  return withTransaction(ctx, locks, progress, { operation: "add", rowId: id }, async (tx) => {
11942
12234
  await protectIn(tx, id, options.protect);
11943
- const stateAccounts = isRecord7(tx.state.accounts) ? tx.state.accounts : {};
12235
+ const stateAccounts = isRecord6(tx.state.accounts) ? tx.state.accounts : {};
11944
12236
  const stagedOrphan = Object.entries(stateAccounts).find(([orphanId, account]) => {
11945
- if (orphanId === id || tx.rosterRow(orphanId) || !isRecord7(account))
12237
+ if (orphanId === id || tx.rosterRow(orphanId) || !isRecord6(account))
11946
12238
  return false;
11947
12239
  const stamp = account[CREDENTIAL_STAMP_KEY];
11948
- if (!isRecord7(stamp) || !Object.hasOwn(stamp, "staged"))
12240
+ if (!isRecord6(stamp) || !Object.hasOwn(stamp, "staged"))
11949
12241
  return false;
11950
12242
  return credential.type === "oauth" ? account.refresh === credential.refresh : typeof account.apiKey === "string" && account.apiKey.trim() === credential.apiKey.trim();
11951
12243
  });
@@ -11963,9 +12255,9 @@ async function addRow(rt, input, options = {}) {
11963
12255
  }
11964
12256
  if (mode === "refuse") {
11965
12257
  const holder = tx.rows().find((row) => row.fingerprint === fingerprintOf(credential) || row.id === id && row.credential);
11966
- const accounts = isRecord7(tx.state.accounts) ? tx.state.accounts : {};
12258
+ const accounts = isRecord6(tx.state.accounts) ? tx.state.accounts : {};
11967
12259
  const stateHolder = Object.entries(accounts).find(([, account]) => {
11968
- if (!isRecord7(account))
12260
+ if (!isRecord6(account))
11969
12261
  return false;
11970
12262
  if (credential.type === "oauth")
11971
12263
  return account.refresh === credential.refresh;
@@ -12298,7 +12590,7 @@ async function removeRow(rt, id, options = {}) {
12298
12590
  throw refusal("remove", id, "invalid-input", "id must be non-empty");
12299
12591
  const fence = options.attribution;
12300
12592
  validateAttribution("remove", id, fence);
12301
- if (options.staged !== undefined && (!isRecord7(options.staged) || typeof options.staged.reservation !== "string" || !options.staged.reservation))
12593
+ if (options.staged !== undefined && (!isRecord6(options.staged) || typeof options.staged.reservation !== "string" || !options.staged.reservation))
12302
12594
  throw refusal("remove", id, "invalid-input", "a staged removal needs a reservation");
12303
12595
  const result = await readPool(ctx);
12304
12596
  if (result.status !== "ready")
@@ -12313,7 +12605,7 @@ async function removeRow(rt, id, options = {}) {
12313
12605
  return withTransaction(ctx, locks, progress, { operation: "remove", rowId: id }, async (tx) => {
12314
12606
  const reservation = tx.reservation(id);
12315
12607
  if (reservation !== undefined) {
12316
- if (!isRecord7(reservation) || !options.staged || reservation.reservation !== options.staged.reservation)
12608
+ if (!isRecord6(reservation) || !options.staged || reservation.reservation !== options.staged.reservation)
12317
12609
  throw refusal("remove", id, "row-staged", `row ${id} is reserved for roster publication`);
12318
12610
  } else if (options.staged)
12319
12611
  throw refusal("remove", id, "attribution", `row ${id} is no longer reserved`);
@@ -12401,10 +12693,10 @@ function assertOrphanAttribution(rt, tx, id, fence) {
12401
12693
  }
12402
12694
  function hasStateAccount(state, id) {
12403
12695
  const accounts = state.accounts;
12404
- return isRecord7(accounts) && Object.hasOwn(accounts, id);
12696
+ return isRecord6(accounts) && Object.hasOwn(accounts, id);
12405
12697
  }
12406
12698
  function rosterIdOf(raw) {
12407
- return isRecord7(raw) && typeof raw.id === "string" ? raw.id : undefined;
12699
+ return isRecord6(raw) && typeof raw.id === "string" ? raw.id : undefined;
12408
12700
  }
12409
12701
  function orderProblem(roster, ids) {
12410
12702
  if (!Array.isArray(ids))
@@ -12479,7 +12771,7 @@ async function recordRowIdentity(rt, id, identity, attribution, options = {}) {
12479
12771
  return runOperation(rt.ctx, "recordIdentity", id, options.onFailure, async (locks, progress) => {
12480
12772
  if (typeof identity !== "string" || identity.length === 0)
12481
12773
  throw refusal("recordIdentity", id, "invalid-input", "identity must be non-empty");
12482
- const captured = isRecord7(attribution) ? attribution.credentialEpoch : undefined;
12774
+ const captured = isRecord6(attribution) ? attribution.credentialEpoch : undefined;
12483
12775
  if (!isCredentialEpoch(captured))
12484
12776
  throw refusal("recordIdentity", id, "invalid-input", "the credential epoch the identity lookup was issued for is required");
12485
12777
  const { row: seen } = await readRow(rt, "recordIdentity", id);
@@ -12508,14 +12800,14 @@ async function recordRowIdentity(rt, id, identity, attribution, options = {}) {
12508
12800
  // ../../node_modules/@cortexkit/common-auth/dist/store/publication.js
12509
12801
  function receiptsIn(config) {
12510
12802
  const pool = config[POOL_KEY];
12511
- return isRecord7(pool) && isRecord7(pool.publications) ? pool.publications : {};
12803
+ return isRecord6(pool) && isRecord6(pool.publications) ? pool.publications : {};
12512
12804
  }
12513
12805
  function receiptIn(config, operationId) {
12514
12806
  const receipts = receiptsIn(config);
12515
12807
  if (!Object.hasOwn(receipts, operationId))
12516
12808
  return;
12517
12809
  const raw = receipts[operationId];
12518
- if (!isRecord7(raw) || raw.operationId !== operationId || typeof raw.planDigest !== "string" || !/^[a-f0-9]{64}$/.test(raw.planDigest) || !["committed", "cleaned"].includes(String(raw.phase)) || !Array.isArray(raw.removed) || !Array.isArray(raw.finalized) || raw.removed.some((ref) => !isRecord7(ref) || typeof ref.id !== "string" || !isCredentialEpoch(ref.credentialEpoch)) || raw.finalized.some((ref) => !isRecord7(ref) || typeof ref.id !== "string" || !isCredentialEpoch(ref.credentialEpoch) || typeof ref.reservation !== "string" || !ref.reservation || typeof ref.enabled !== "boolean"))
12810
+ if (!isRecord6(raw) || raw.operationId !== operationId || typeof raw.planDigest !== "string" || !/^[a-f0-9]{64}$/.test(raw.planDigest) || !["committed", "cleaned"].includes(String(raw.phase)) || !Array.isArray(raw.removed) || !Array.isArray(raw.finalized) || raw.removed.some((ref) => !isRecord6(ref) || typeof ref.id !== "string" || !isCredentialEpoch(ref.credentialEpoch)) || raw.finalized.some((ref) => !isRecord6(ref) || typeof ref.id !== "string" || !isCredentialEpoch(ref.credentialEpoch) || typeof ref.reservation !== "string" || !ref.reservation || typeof ref.enabled !== "boolean"))
12519
12811
  throw refusal("publishRoster", operationId, "invalid-input", "the stored publication receipt is malformed");
12520
12812
  return structuredClone(raw);
12521
12813
  }
@@ -12529,11 +12821,11 @@ function validatePlan(rt, plan) {
12529
12821
  const fail = () => {
12530
12822
  throw refusal("publishRoster", plan?.operationId ?? "", "invalid-input", "the publication plan is invalid");
12531
12823
  };
12532
- if (!isRecord7(plan) || typeof plan.operationId !== "string" || !plan.operationId || !Array.isArray(plan.remove) || !Array.isArray(plan.finalize) || !Array.isArray(plan.order))
12824
+ if (!isRecord6(plan) || typeof plan.operationId !== "string" || !plan.operationId || !Array.isArray(plan.remove) || !Array.isArray(plan.finalize) || !Array.isArray(plan.order))
12533
12825
  fail();
12534
12826
  const ids = new Set;
12535
12827
  for (const ref of [...plan.remove, ...plan.finalize]) {
12536
- if (!isRecord7(ref) || typeof ref.id !== "string" || idProblem(ref.id) || ids.has(ref.id) || !ref.attribution)
12828
+ if (!isRecord6(ref) || typeof ref.id !== "string" || idProblem(ref.id) || ids.has(ref.id) || !ref.attribution)
12537
12829
  fail();
12538
12830
  ids.add(ref.id);
12539
12831
  validateAttribution("publishRoster", ref.id, ref.attribution);
@@ -12565,7 +12857,7 @@ function saveReceipt(tx, receipt) {
12565
12857
  function publicationSurvivors(tx, plan, rows) {
12566
12858
  const rosterIds = new Set;
12567
12859
  for (const raw of rosterOf(tx.config)) {
12568
- if (!isRecord7(raw) || typeof raw.id !== "string")
12860
+ if (!isRecord6(raw) || typeof raw.id !== "string")
12569
12861
  continue;
12570
12862
  if (rosterIds.has(raw.id))
12571
12863
  throw refusal("publishRoster", plan.operationId, "invalid-input", "publication needs a roster of unique named rows");
@@ -12604,14 +12896,14 @@ async function cleanup(tx, receipt) {
12604
12896
  async function publishRoster(rt, plan, options = {}) {
12605
12897
  assertNotInsideHook("publishRoster");
12606
12898
  return runOperation(rt.ctx, "publishRoster", plan?.operationId ?? "", options.onFailure, async (locks, progress) => {
12607
- if (!isRecord7(plan) || typeof plan.operationId !== "string" || !plan.operationId)
12899
+ if (!isRecord6(plan) || typeof plan.operationId !== "string" || !plan.operationId)
12608
12900
  throw refusal("publishRoster", plan?.operationId ?? "", "invalid-input", "the publication needs an operation id");
12609
12901
  plan = structuredClone(plan);
12610
12902
  const planDigest = canonicalDigest(plan);
12611
12903
  const named = [
12612
12904
  ...Array.isArray(plan.remove) ? plan.remove : [],
12613
12905
  ...Array.isArray(plan.finalize) ? plan.finalize : []
12614
- ].filter((ref) => isRecord7(ref) && typeof ref.id === "string");
12906
+ ].filter((ref) => isRecord6(ref) && typeof ref.id === "string");
12615
12907
  for (let attempt = 0;; attempt++) {
12616
12908
  const seen = await readPool(rt.ctx);
12617
12909
  if (seen.status !== "ready")
@@ -12715,7 +13007,7 @@ async function publishRoster(rt, plan, options = {}) {
12715
13007
  entry.disabledReason = ref.disabledReason;
12716
13008
  tx.setEntry(ref.id, entry);
12717
13009
  }
12718
- const preserved = tx.roster().filter((raw) => !isRecord7(raw) || typeof raw.id !== "string" || rows.find((row) => row.id === raw.id)?.invalid === "roster");
13010
+ const preserved = tx.roster().filter((raw) => !isRecord6(raw) || typeof raw.id !== "string" || rows.find((row) => row.id === raw.id)?.invalid === "roster");
12719
13011
  tx.config.accounts = [
12720
13012
  ...plan.order.map((id) => tx.rosterRow(id)),
12721
13013
  ...preserved
@@ -13089,7 +13381,7 @@ async function updatePoolSettings(rt, mutator, options = {}) {
13089
13381
  const draft = structuredClone(current);
13090
13382
  const returned = await runInsideHook("updateSettings", () => mutator(draft));
13091
13383
  const next = returned === undefined ? draft : returned;
13092
- if (!isRecord7(next))
13384
+ if (!isRecord6(next))
13093
13385
  throw settingsRefusal("the settings mutator must produce an object");
13094
13386
  const owned = POOL_OWNED_KEYS.filter((key) => Object.hasOwn(next, key));
13095
13387
  if (owned.length > 0)
@@ -13226,7 +13518,7 @@ function entryTime(entry) {
13226
13518
  function limitKey(scope, label) {
13227
13519
  return JSON.stringify([scope, label]);
13228
13520
  }
13229
- function isRecord8(value) {
13521
+ function isRecord7(value) {
13230
13522
  return typeof value === "object" && value !== null && !Array.isArray(value);
13231
13523
  }
13232
13524
  function isFiniteNumber(value) {
@@ -13245,7 +13537,7 @@ function isString(value) {
13245
13537
  return typeof value === "string";
13246
13538
  }
13247
13539
  function isQuotaEntry(value) {
13248
- if (!isRecord8(value) || !isName(value.scope) || !isName(value.label)) {
13540
+ if (!isRecord7(value) || !isName(value.scope) || !isName(value.label)) {
13249
13541
  return false;
13250
13542
  }
13251
13543
  switch (value.kind) {
@@ -13260,20 +13552,26 @@ function isQuotaEntry(value) {
13260
13552
  }
13261
13553
  }
13262
13554
  function isCreditBudgetEntry(value) {
13263
- if (!isRecord8(value) || !isFiniteNumber(value.checkedAt))
13555
+ if (!isRecord7(value) || !isFiniteNumber(value.checkedAt))
13264
13556
  return false;
13265
13557
  if (value.kind === "cleared")
13266
13558
  return true;
13267
13559
  return value.kind === "reading" && typeof value.reached === "boolean" && optional(value, "remainingPercent", isFiniteNumber) && optional(value, "usedPercent", isFiniteNumber) && optional(value, "resetsAt", isString) && optional(value, "limit", isFiniteNumber) && optional(value, "used", isFiniteNumber) && optional(value, "remaining", isFiniteNumber) && optional(value, "unit", isString);
13268
13560
  }
13269
13561
  function isQuotaCounter(value) {
13270
- return isRecord8(value) && isFiniteNumber(value.value) && Number.isInteger(value.value) && value.value >= 0 && isFiniteNumber(value.checkedAt);
13562
+ return isRecord7(value) && isFiniteNumber(value.value) && Number.isInteger(value.value) && value.value >= 0 && isFiniteNumber(value.checkedAt);
13271
13563
  }
13272
13564
  function isQuotaCounters(value) {
13273
- return isRecord8(value) && Object.values(value).every(isQuotaCounter);
13565
+ return isRecord7(value) && Object.values(value).every(isQuotaCounter);
13566
+ }
13567
+ function isBoolean(value) {
13568
+ return typeof value === "boolean";
13569
+ }
13570
+ function isQuotaCredits(value) {
13571
+ return isRecord7(value) && typeof value.hasCredits === "boolean" && typeof value.unlimited === "boolean" && optional(value, "balance", isFiniteNumber) && optional(value, "overageLimitReached", isBoolean) && isFiniteNumber(value.checkedAt);
13274
13572
  }
13275
13573
  function readQuotaCounters(value) {
13276
- if (!isRecord8(value))
13574
+ if (!isRecord7(value))
13277
13575
  return;
13278
13576
  const entries = Object.entries(value).filter(([, entry]) => isQuotaCounter(entry));
13279
13577
  return entries.length === 0 ? undefined : Object.fromEntries(entries);
@@ -13281,16 +13579,21 @@ function readQuotaCounters(value) {
13281
13579
  function decodeQuotaMap(value) {
13282
13580
  if (isQuotaMap(value))
13283
13581
  return value;
13284
- if (!isRecord8(value))
13582
+ if (!isRecord7(value))
13285
13583
  return;
13286
- const { counters: rawCounters, ...rest } = value;
13584
+ const { counters: rawCounters, credits: rawCredits, ...rest } = value;
13287
13585
  if (!isQuotaMap(rest))
13288
13586
  return;
13289
13587
  const counters = readQuotaCounters(rawCounters);
13290
- return { ...rest, ...counters === undefined ? {} : { counters } };
13588
+ const credits = isQuotaCredits(rawCredits) ? rawCredits : undefined;
13589
+ return {
13590
+ ...rest,
13591
+ ...counters === undefined ? {} : { counters },
13592
+ ...credits === undefined ? {} : { credits }
13593
+ };
13291
13594
  }
13292
13595
  function isQuotaMap(value) {
13293
- if (!isRecord8(value) || !Array.isArray(value.limits))
13596
+ if (!isRecord7(value) || !Array.isArray(value.limits))
13294
13597
  return false;
13295
13598
  const seen = new Set;
13296
13599
  for (const entry of value.limits) {
@@ -13301,7 +13604,7 @@ function isQuotaMap(value) {
13301
13604
  return false;
13302
13605
  seen.add(key);
13303
13606
  }
13304
- return optional(value, "budget", isCreditBudgetEntry) && optional(value, "counters", isQuotaCounters);
13607
+ return optional(value, "budget", isCreditBudgetEntry) && optional(value, "counters", isQuotaCounters) && optional(value, "credits", isQuotaCredits);
13305
13608
  }
13306
13609
 
13307
13610
  // ../../node_modules/@cortexkit/common-auth/dist/quota/merge.js
@@ -13311,7 +13614,7 @@ class QuotaCodecError extends TypeError {
13311
13614
  this.name = "QuotaCodecError";
13312
13615
  }
13313
13616
  }
13314
- function isRecord9(value) {
13617
+ function isRecord8(value) {
13315
13618
  return typeof value === "object" && value !== null && !Array.isArray(value);
13316
13619
  }
13317
13620
  function isFiniteNumber2(value) {
@@ -13330,20 +13633,20 @@ function optionalString(record, key) {
13330
13633
  return record[key] === undefined || typeof record[key] === "string";
13331
13634
  }
13332
13635
  function isObservedReading(value) {
13333
- return isRecord9(value) && isScope(value.scope) && isLabel(value.label) && isFiniteNumber2(value.usedPercent) && optionalString(value, "resetsAt") && (value.windowMinutes === undefined || isFiniteNumber2(value.windowMinutes) && value.windowMinutes > 0);
13636
+ return isRecord8(value) && isScope(value.scope) && isLabel(value.label) && isFiniteNumber2(value.usedPercent) && optionalString(value, "resetsAt") && (value.windowMinutes === undefined || isFiniteNumber2(value.windowMinutes) && value.windowMinutes > 0);
13334
13637
  }
13335
13638
  function isObservedPair(value) {
13336
- return isRecord9(value) && isScope(value.scope) && isLabel(value.label);
13639
+ return isRecord8(value) && isScope(value.scope) && isLabel(value.label);
13337
13640
  }
13338
13641
  function isObservedBudget(value) {
13339
- if (!isRecord9(value))
13642
+ if (!isRecord8(value))
13340
13643
  return false;
13341
13644
  if (value.kind === "cleared")
13342
13645
  return true;
13343
13646
  return value.kind === "reading" && typeof value.reached === "boolean" && optionalFinite(value, "remainingPercent") && optionalFinite(value, "usedPercent") && optionalString(value, "resetsAt") && optionalFinite(value, "limit") && optionalFinite(value, "used") && optionalFinite(value, "remaining") && optionalString(value, "unit");
13344
13647
  }
13345
13648
  function isQuotaObservation(value) {
13346
- if (!isRecord9(value) || !isFiniteNumber2(value.checkedAt))
13649
+ if (!isRecord8(value) || !isFiniteNumber2(value.checkedAt))
13347
13650
  return false;
13348
13651
  const readings = value.readings ?? [];
13349
13652
  const coverage = value.coverage ?? [];
@@ -13360,7 +13663,7 @@ function isQuotaObservation(value) {
13360
13663
  }
13361
13664
  if (!coverage.every(isObservedPair))
13362
13665
  return false;
13363
- return (value.budget === undefined || isObservedBudget(value.budget)) && (value.counters === undefined || isQuotaCounters(value.counters));
13666
+ return (value.budget === undefined || isObservedBudget(value.budget)) && (value.counters === undefined || isQuotaCounters(value.counters)) && (value.credits === undefined || isQuotaCredits(value.credits));
13364
13667
  }
13365
13668
  function compareEntries(left, right) {
13366
13669
  if (left.scope !== right.scope)
@@ -13386,6 +13689,14 @@ function mergeCounters(stored, observed) {
13386
13689
  }
13387
13690
  return counters.size === 0 ? undefined : Object.fromEntries(counters);
13388
13691
  }
13692
+ function mergeCredits(stored, observed) {
13693
+ if (observed === undefined)
13694
+ return stored;
13695
+ if (stored !== undefined && observed.checkedAt < stored.checkedAt) {
13696
+ return stored;
13697
+ }
13698
+ return { ...observed };
13699
+ }
13389
13700
  function mergeQuotaObservation(stored, observation) {
13390
13701
  const decoded = stored === undefined ? undefined : decodeQuotaMap(stored);
13391
13702
  if (stored !== undefined && decoded === undefined) {
@@ -13429,14 +13740,16 @@ function mergeQuotaObservation(stored, observation) {
13429
13740
  const existing = entries.get(key);
13430
13741
  entries.set(key, existing === undefined || existing.kind === "absent" ? { scope, label: pair.label, kind: "absent", checkedAt: at } : { scope, label: pair.label, kind: "retired", retiredAt: at });
13431
13742
  }
13432
- const { limits: _limits, budget: _budget, counters: _counters, ...unknownKeys } = base;
13743
+ const { limits: _limits, budget: _budget, counters: _counters, credits: _credits, ...unknownKeys } = base;
13433
13744
  const budget = mergeBudget(base.budget, observation.budget, at);
13434
13745
  const counters = mergeCounters(base.counters, observation.counters);
13746
+ const credits = mergeCredits(base.credits, observation.credits);
13435
13747
  return {
13436
13748
  ...unknownKeys,
13437
13749
  limits: [...entries.values()].sort(compareEntries),
13438
13750
  ...budget === undefined ? {} : { budget },
13439
- ...counters === undefined ? {} : { counters }
13751
+ ...counters === undefined ? {} : { counters },
13752
+ ...credits === undefined ? {} : { credits }
13440
13753
  };
13441
13754
  }
13442
13755
 
@@ -13512,6 +13825,13 @@ function quotaWindowParts(quota, options) {
13512
13825
  const parts = windows.map(({ part }) => part);
13513
13826
  return age === undefined ? { windows: parts } : { windows: parts, age };
13514
13827
  }
13828
+ function withShortNames(windows) {
13829
+ const abbreviations = scopeAbbreviations(windows.filter(({ part, scope }) => part.kind === "window" && scope !== ALL_SCOPE).map(({ scope }) => scope));
13830
+ for (const window of windows) {
13831
+ window.part.short = window.part.kind === "budget" ? "cr" : window.scope === ALL_SCOPE ? window.part.name : abbreviations.get(window.scope) ?? window.scope;
13832
+ }
13833
+ return windows;
13834
+ }
13515
13835
  function scopedWindowParts(quota, options) {
13516
13836
  if (!quota)
13517
13837
  return { windows: [] };
@@ -13525,6 +13845,7 @@ function scopedWindowParts(quota, options) {
13525
13845
  part: {
13526
13846
  kind: "window",
13527
13847
  name: quotaWindowName(limit),
13848
+ short: "",
13528
13849
  figure: percentLeft(limit.remainingPercent ?? 0),
13529
13850
  remainingPercent,
13530
13851
  checkedAt: limit.checkedAt,
@@ -13542,6 +13863,7 @@ function scopedWindowParts(quota, options) {
13542
13863
  part: {
13543
13864
  kind: "budget",
13544
13865
  name: "credits",
13866
+ short: "",
13545
13867
  figure,
13546
13868
  ...remainingPercent === undefined ? {} : { remainingPercent: clampPercent2(remainingPercent) },
13547
13869
  checkedAt: budget.checkedAt,
@@ -13549,6 +13871,7 @@ function scopedWindowParts(quota, options) {
13549
13871
  }
13550
13872
  });
13551
13873
  }
13874
+ withShortNames(windows);
13552
13875
  if (windows.length > 0) {
13553
13876
  const age = now - Math.min(...windows.map(({ part }) => part.checkedAt));
13554
13877
  if (age > (options.staleAfterMs ?? QUOTA_STALE_AFTER_MS)) {
@@ -13629,15 +13952,14 @@ function narrowTextParts(quota, options) {
13629
13952
  return grouped;
13630
13953
  const general = windows.filter(({ part, scope }) => part.kind === "window" && scope === ALL_SCOPE);
13631
13954
  const scoped = windows.filter(({ part, scope }) => part.kind === "window" && scope !== ALL_SCOPE);
13632
- const abbreviations = scopeAbbreviations(scoped.map(({ scope }) => scope));
13633
13955
  const budget = windows.find(({ part }) => part.kind === "budget");
13634
13956
  const budgetLeft = budget?.spent ? 0 : budget?.part.remainingPercent;
13635
13957
  const extras = [
13636
- ...scoped.map(({ scope, part }) => ({
13637
- label: abbreviations.get(scope) ?? scope,
13958
+ ...scoped.map(({ part }) => ({
13959
+ label: part.short,
13638
13960
  remaining: part.remainingPercent ?? 0
13639
13961
  })),
13640
- ...budgetLeft === undefined ? [] : [{ label: "cr", remaining: budgetLeft }]
13962
+ ...budgetLeft === undefined || budget === undefined ? [] : [{ label: budget.part.short, remaining: budgetLeft }]
13641
13963
  ];
13642
13964
  const tightest = extras.reduce((best, item) => best === undefined || item.remaining < best.remaining ? item : best, undefined);
13643
13965
  const pieces = general.map(({ part }) => `${part.name} ${wholePercent(part.remainingPercent ?? 0)}%`);
@@ -13894,7 +14216,7 @@ var nativeQuotaCodec = {
13894
14216
  import { randomUUID as randomUUID12 } from "node:crypto";
13895
14217
  import { constants as constants2 } from "node:fs";
13896
14218
  import { lstat as lstat5, mkdir as mkdir9, open as open6, rename as rename11, rm as rm6 } from "node:fs/promises";
13897
- import { basename as basename4, dirname as dirname9, isAbsolute as isAbsolute3, join as join11 } from "node:path";
14219
+ import { basename as basename4, dirname as dirname9, isAbsolute as isAbsolute3, join as join12 } from "node:path";
13898
14220
  import { types as utilTypes5 } from "node:util";
13899
14221
 
13900
14222
  // src/pool-binding.ts
@@ -15354,7 +15676,7 @@ async function writeNativeRuntimeOutcome(path2, storageId, change, hooks, firstI
15354
15676
  assertTransitions(current, next, firstIdentity);
15355
15677
  const bytes = `${JSON.stringify(next, null, 2)}
15356
15678
  `;
15357
- const stage = join11(dirname9(path2), `${basename4(path2)}.native-runtime.${randomUUID12()}.partial`);
15679
+ const stage = join12(dirname9(path2), `${basename4(path2)}.native-runtime.${randomUUID12()}.partial`);
15358
15680
  let ownsStage = false;
15359
15681
  try {
15360
15682
  const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
@@ -17774,8 +18096,12 @@ class ClaustrumScopedCustody {
17774
18096
  }
17775
18097
  }
17776
18098
 
18099
+ // ../../node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
18100
+ import { resolve as resolve8 } from "node:path";
18101
+
17777
18102
  // ../../node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
17778
18103
  import { createHash as createHash12 } from "node:crypto";
18104
+ import { resolve as resolve7 } from "node:path";
17779
18105
 
17780
18106
  // ../../node_modules/@cortexkit/common-auth/dist/claustrum/interlock.js
17781
18107
  function matches(entry2, credentialId, accountIdentity) {
@@ -17950,15 +18276,15 @@ function vaultRoutingRows(roster) {
17950
18276
  ...row.quota !== undefined && { quota: row.quota }
17951
18277
  }));
17952
18278
  }
17953
- function isRecord10(value) {
18279
+ function isRecord9(value) {
17954
18280
  return typeof value === "object" && value !== null && !Array.isArray(value);
17955
18281
  }
17956
18282
  function optionalString2(value) {
17957
18283
  return value === undefined || typeof value === "string";
17958
18284
  }
17959
18285
  function decodeRow(value) {
17960
- const quota2 = isRecord10(value) ? decodeQuotaMap(value.quota) : undefined;
17961
- if (!isRecord10(value) || typeof value.routeId !== "string" || typeof value.credentialId !== "string" || value.credentialType !== "oauth" && value.credentialType !== "api_key" || typeof value.state !== "string" || typeof value.label !== "string" || typeof value.enabled !== "boolean" || typeof value.addedAt !== "number" || !optionalString2(value.accountIdentity) || !optionalString2(value.email) || !optionalString2(value.orgName) || value.aliases !== undefined && (!Array.isArray(value.aliases) || !value.aliases.every((alias) => typeof alias === "string")) || value.quota !== undefined && quota2 === undefined || value.stale !== undefined && value.stale !== true || value.unclaimed !== undefined && value.unclaimed !== true)
18286
+ const quota2 = isRecord9(value) ? decodeQuotaMap(value.quota) : undefined;
18287
+ if (!isRecord9(value) || typeof value.routeId !== "string" || typeof value.credentialId !== "string" || value.credentialType !== "oauth" && value.credentialType !== "api_key" || typeof value.state !== "string" || typeof value.label !== "string" || typeof value.enabled !== "boolean" || typeof value.addedAt !== "number" || !optionalString2(value.accountIdentity) || !optionalString2(value.email) || !optionalString2(value.orgName) || value.aliases !== undefined && (!Array.isArray(value.aliases) || !value.aliases.every((alias) => typeof alias === "string")) || value.quota !== undefined && quota2 === undefined || value.stale !== undefined && value.stale !== true || value.unclaimed !== undefined && value.unclaimed !== true)
17962
18288
  return;
17963
18289
  return {
17964
18290
  ...value,
@@ -17976,14 +18302,14 @@ function decodeRejected(value) {
17976
18302
  return;
17977
18303
  const records = [];
17978
18304
  for (const entry2 of value) {
17979
- if (!isRecord10(entry2) || !optionalString2(entry2.credentialId) || typeof entry2.reason !== "string" || !SKIPPED_REASONS.has(entry2.reason))
18305
+ if (!isRecord9(entry2) || !optionalString2(entry2.credentialId) || typeof entry2.reason !== "string" || !SKIPPED_REASONS.has(entry2.reason))
17980
18306
  return;
17981
18307
  records.push(entry2);
17982
18308
  }
17983
18309
  return records;
17984
18310
  }
17985
18311
  function decodeRoster(value) {
17986
- if (!isRecord10(value) || value.version !== 1 || !optionalString2(value.view) || !Array.isArray(value.rows) || !Array.isArray(value.declined) || value.complete !== undefined && typeof value.complete !== "boolean" || value.rejected !== undefined && !decodeRejected(value.rejected))
18312
+ if (!isRecord9(value) || value.version !== 1 || !optionalString2(value.view) || !Array.isArray(value.rows) || !Array.isArray(value.declined) || value.complete !== undefined && typeof value.complete !== "boolean" || value.rejected !== undefined && !decodeRejected(value.rejected))
17987
18313
  throw new ClaustrumConsumerError("invalid-state", "Claustrum roster file is not valid");
17988
18314
  const rows = [];
17989
18315
  for (const entry2 of value.rows) {
@@ -17994,7 +18320,7 @@ function decodeRoster(value) {
17994
18320
  }
17995
18321
  const declined = [];
17996
18322
  for (const entry2 of value.declined) {
17997
- if (!isRecord10(entry2) || typeof entry2.credentialId !== "string" || !optionalString2(entry2.accountIdentity))
18323
+ if (!isRecord9(entry2) || typeof entry2.credentialId !== "string" || !optionalString2(entry2.accountIdentity))
17998
18324
  throw new ClaustrumConsumerError("invalid-state", "Claustrum roster file is not valid");
17999
18325
  declined.push(entry2);
18000
18326
  }
@@ -18028,11 +18354,12 @@ async function readVaultRoster(path2) {
18028
18354
  var WRITE_LOCK = {
18029
18355
  name: "claustrum-roster-write",
18030
18356
  ttlMs: 1e4,
18031
- timeoutMs: 5000
18357
+ timeoutMs: 5000,
18358
+ renew: true
18032
18359
  };
18033
18360
  var DISCOVERY_LEASE = { name: "claustrum-roster", ttlMs: 30000 };
18034
18361
  async function mutateVaultRoster(path2, change, options = {}) {
18035
- return withLock(path2, WRITE_LOCK, async (lock) => {
18362
+ return withLock(path2, { ...WRITE_LOCK, signal: options.signal }, async (lock) => {
18036
18363
  const current = await readVaultRoster(path2);
18037
18364
  const { next, result } = await change(current, {
18038
18365
  assertOwned: () => lock.assertOwned()
@@ -18042,6 +18369,7 @@ async function mutateVaultRoster(path2, change, options = {}) {
18042
18369
  await writeJsonAtomic(path2, next, {
18043
18370
  beforeRename: async () => {
18044
18371
  await options.beforePublish?.();
18372
+ options.signal?.throwIfAborted();
18045
18373
  await lock.assertOwned();
18046
18374
  }
18047
18375
  });
@@ -18091,43 +18419,52 @@ function receiptFence(row, receipt) {
18091
18419
  return "bind";
18092
18420
  return "refuse";
18093
18421
  }
18094
- function recordVaultQuota(path2, input) {
18095
- return mutateVaultRoster(path2, (current) => {
18096
- const row = current?.rows.find((entry2) => entry2.routeId === input.routeId);
18097
- const fence = !current || !row ? "refuse" : receiptFence(row, input);
18098
- if (!current || !row || fence === "refuse")
18099
- return { result: false };
18100
- const quota2 = mergeQuotaObservation(row.quota, input.observation);
18101
- const bound = fence === "bind" ? { accountIdentity: input.accountIdentity, unclaimed: true } : {};
18102
- return {
18103
- next: {
18104
- ...current,
18105
- rows: current.rows.map((entry2) => entry2 === row ? { ...entry2, ...bound, quota: quota2 } : entry2)
18106
- },
18107
- result: true
18108
- };
18422
+ async function recordVaultQuota(path2, input) {
18423
+ const { routeId, observation, ...receipt } = input;
18424
+ return enqueueFencedVaultQuota(path2, {
18425
+ routeId,
18426
+ observation,
18427
+ accountIdentity: receipt.accountIdentity,
18428
+ receipt
18109
18429
  });
18110
18430
  }
18431
+ async function enqueueFencedVaultQuota(path2, publication2) {
18432
+ if (!isQuotaObservation(publication2.observation))
18433
+ return false;
18434
+ const current = pendingVaultQuota(path2, await readVaultRoster(path2));
18435
+ if (!applyVaultQuota(current, publication2).kept)
18436
+ return false;
18437
+ return enqueueVaultQuota(path2, publication2);
18438
+ }
18111
18439
  function recordVaultAccountQuota(path2, input) {
18112
- return mutateVaultRoster(path2, (current) => {
18113
- const row = current?.rows.find((entry2) => entry2.routeId === input.routeId);
18114
- if (!current || !row || row.accountIdentity === undefined || row.accountIdentity !== input.accountIdentity)
18115
- return { result: false };
18116
- const quota2 = mergeQuotaObservation(row.quota, input.observation);
18117
- return {
18118
- next: {
18119
- ...current,
18120
- rows: current.rows.map((entry2) => entry2 === row ? { ...entry2, quota: quota2 } : entry2)
18121
- },
18122
- result: true
18123
- };
18124
- });
18440
+ return enqueueFencedVaultQuota(path2, input);
18441
+ }
18442
+ function applyVaultQuota(current, input) {
18443
+ const row = current?.rows.find((entry2) => entry2.routeId === input.routeId);
18444
+ const fence = !row ? "refuse" : input.receipt ? receiptFence(row, input.receipt) : row.accountIdentity !== undefined && row.accountIdentity === input.accountIdentity ? "hold" : "refuse";
18445
+ if (!current || !row || fence === "refuse")
18446
+ return { roster: current, kept: false };
18447
+ const quota2 = mergeQuotaObservation(row.quota, input.observation);
18448
+ const bound = fence === "bind" ? { accountIdentity: input.accountIdentity, unclaimed: true } : {};
18449
+ return {
18450
+ roster: {
18451
+ ...current,
18452
+ rows: current.rows.map((entry2) => entry2 === row ? { ...entry2, ...bound, quota: quota2 } : entry2)
18453
+ },
18454
+ kept: true
18455
+ };
18456
+ }
18457
+ var pendingDiscoveries = new Map;
18458
+ function forgetPendingVaultDiscovery(path2) {
18459
+ pendingDiscoveries.delete(resolve7(path2));
18125
18460
  }
18126
18461
  async function refreshVaultRoster(options) {
18127
18462
  options.signal?.throwIfAborted();
18128
18463
  const active = async () => await options.isActive?.() ?? true;
18129
- if (!await active())
18464
+ if (!await active()) {
18465
+ forgetPendingVaultDiscovery(options.path);
18130
18466
  return;
18467
+ }
18131
18468
  const lease = await acquireRefreshFileLock({
18132
18469
  ...DISCOVERY_LEASE,
18133
18470
  path: options.path,
@@ -18140,8 +18477,18 @@ async function refreshVaultRoster(options) {
18140
18477
  throw new ClaustrumConsumerError("roster-busy", "Claustrum account discovery is already in progress");
18141
18478
  return persisted;
18142
18479
  }
18480
+ const key = resolve7(options.path);
18481
+ let discovered;
18143
18482
  try {
18144
- const inventory = await options.custody.discover(options.signal);
18483
+ const previous = await readVaultRoster(options.path);
18484
+ const pending = pendingDiscoveries.get(key);
18485
+ discovered = pending && (pending.previousView === previous?.view || pending.inventory.view === previous?.view) ? pending : {
18486
+ inventory: await options.custody.discover(options.signal),
18487
+ previousView: previous?.view
18488
+ };
18489
+ pendingDiscoveries.delete(key);
18490
+ const { inventory } = discovered;
18491
+ options.onInventory?.(inventory);
18145
18492
  options.signal?.throwIfAborted();
18146
18493
  return await mutateVaultRoster(options.path, async (current) => {
18147
18494
  if (!await active())
@@ -18152,12 +18499,238 @@ async function refreshVaultRoster(options) {
18152
18499
  const next = projectVaultRoster(current, inventory, projection);
18153
18500
  const changed = JSON.stringify(current) !== JSON.stringify(next);
18154
18501
  return { ...changed && { next }, result: next };
18502
+ }, {
18503
+ beforePublish: async () => {
18504
+ options.signal?.throwIfAborted();
18505
+ await lease.assertOwned();
18506
+ }
18155
18507
  });
18508
+ } catch (error) {
18509
+ if (error instanceof LockContentionError && discovered && !options.signal?.aborted && await active())
18510
+ pendingDiscoveries.set(key, discovered);
18511
+ throw error;
18156
18512
  } finally {
18157
18513
  await lease.release();
18158
18514
  }
18159
18515
  }
18160
18516
 
18517
+ // ../../node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
18518
+ var writers = new Map;
18519
+ var logger2 = createLogger("claustrum");
18520
+ var COALESCE_MS = 100;
18521
+ function writerFor(path2) {
18522
+ const key = resolve8(path2);
18523
+ let writer = writers.get(key);
18524
+ if (!writer) {
18525
+ writer = {
18526
+ path: key,
18527
+ pending: new Map,
18528
+ listeners: new Set,
18529
+ wake: new Set,
18530
+ abort: new AbortController,
18531
+ failures: 0,
18532
+ draining: false,
18533
+ order: 0
18534
+ };
18535
+ writers.set(key, writer);
18536
+ }
18537
+ return writer;
18538
+ }
18539
+ function retainVaultQuotaWriter(path2, listener) {
18540
+ const writer = writerFor(path2);
18541
+ writer.listeners.add(listener);
18542
+ let released;
18543
+ return () => released ??= (() => {
18544
+ writer.listeners.delete(listener);
18545
+ return writer.listeners.size ? Promise.resolve() : drainVaultQuota(path2);
18546
+ })();
18547
+ }
18548
+ function fields(publication2) {
18549
+ const result = new Map;
18550
+ const { observation } = publication2;
18551
+ const witness = JSON.stringify([
18552
+ publication2.routeId,
18553
+ publication2.receipt?.credentialId,
18554
+ publication2.receipt?.accountIdentitySource,
18555
+ publication2.receipt?.expectedAccountIdentity
18556
+ ]);
18557
+ const add = (key, at, part) => result.set(`${witness}:${key}`, {
18558
+ at,
18559
+ order: 0,
18560
+ publication: { ...publication2, observation: part }
18561
+ });
18562
+ const keyFor = (scope, label) => JSON.stringify([scope ?? "all", label]);
18563
+ const read = new Set;
18564
+ for (const reading2 of observation.readings ?? []) {
18565
+ const key = keyFor(reading2.scope, reading2.label);
18566
+ read.add(key);
18567
+ add(key, observation.checkedAt, {
18568
+ checkedAt: observation.checkedAt,
18569
+ readings: [{ ...reading2 }]
18570
+ });
18571
+ }
18572
+ for (const pair of observation.coverage ?? []) {
18573
+ const key = keyFor(pair.scope, pair.label);
18574
+ if (!read.has(key))
18575
+ add(key, observation.checkedAt, {
18576
+ checkedAt: observation.checkedAt,
18577
+ coverage: [{ ...pair }]
18578
+ });
18579
+ }
18580
+ if (observation.budget)
18581
+ add("budget", observation.checkedAt, {
18582
+ checkedAt: observation.checkedAt,
18583
+ budget: { ...observation.budget }
18584
+ });
18585
+ for (const [name, counter2] of Object.entries(observation.counters ?? {})) {
18586
+ add(`counter:${name}`, counter2.checkedAt, {
18587
+ checkedAt: observation.checkedAt,
18588
+ counters: { [name]: { ...counter2 } }
18589
+ });
18590
+ }
18591
+ if (observation.credits)
18592
+ add("credits", observation.credits.checkedAt, {
18593
+ checkedAt: observation.checkedAt,
18594
+ credits: { ...observation.credits }
18595
+ });
18596
+ if (!result.size)
18597
+ add("empty", observation.checkedAt, { checkedAt: observation.checkedAt });
18598
+ return result;
18599
+ }
18600
+ function enqueueVaultQuota(path2, publication2) {
18601
+ if (!isQuotaObservation(publication2.observation))
18602
+ return Promise.resolve(false);
18603
+ const writer = writerFor(path2);
18604
+ const account = JSON.stringify([
18605
+ publication2.accountIdentity ?? null,
18606
+ publication2.accountIdentity === undefined ? publication2.routeId : null
18607
+ ]);
18608
+ const pending = writer.pending.get(account) ?? new Map;
18609
+ for (const [key, field] of fields(publication2)) {
18610
+ const previous = pending.get(key);
18611
+ if (!previous || field.at >= previous.at) {
18612
+ field.order = ++writer.order;
18613
+ if (field.publication.observation.coverage)
18614
+ field.priorReading = previous?.publication.observation.readings ? previous.publication : previous?.priorReading;
18615
+ pending.set(key, field);
18616
+ }
18617
+ }
18618
+ if (pending.size)
18619
+ writer.pending.set(account, pending);
18620
+ for (const listener of writer.listeners)
18621
+ listener(publication2);
18622
+ schedule(writer, COALESCE_MS);
18623
+ return Promise.resolve(true);
18624
+ }
18625
+ function orderedFields(pending) {
18626
+ return [...pending.values()].flatMap((account) => [...account.values()]).sort((a, b) => a.order - b.order);
18627
+ }
18628
+ function pendingVaultQuota(path2, roster) {
18629
+ const writer = writers.get(resolve8(path2));
18630
+ if (writer) {
18631
+ for (const field of orderedFields(writer.pending)) {
18632
+ if (field.priorReading)
18633
+ roster = applyVaultQuota(roster, field.priorReading).roster;
18634
+ roster = applyVaultQuota(roster, field.publication).roster;
18635
+ }
18636
+ }
18637
+ return roster;
18638
+ }
18639
+ function schedule(writer, delay3) {
18640
+ if (writer.running || writer.timer || !writer.pending.size || writer.abort.signal.aborted)
18641
+ return;
18642
+ writer.timer = setTimeout(() => {
18643
+ writer.timer = undefined;
18644
+ flush2(writer);
18645
+ }, delay3);
18646
+ if (!writer.draining)
18647
+ writer.timer.unref?.();
18648
+ }
18649
+ function flush2(writer) {
18650
+ if (writer.running || writer.abort.signal.aborted)
18651
+ return;
18652
+ const batch = new Map([...writer.pending].map(([account, pending]) => [
18653
+ account,
18654
+ new Map(pending)
18655
+ ]));
18656
+ writer.running = (async () => {
18657
+ try {
18658
+ await mutateVaultRoster(writer.path, (current) => {
18659
+ let next = current;
18660
+ for (const field of orderedFields(batch)) {
18661
+ if (field.priorReading)
18662
+ next = applyVaultQuota(next, field.priorReading).roster;
18663
+ next = applyVaultQuota(next, field.publication).roster;
18664
+ }
18665
+ return { ...next !== current && { next }, result: undefined };
18666
+ }, { signal: writer.abort.signal });
18667
+ for (const [account, fields2] of batch) {
18668
+ const pending = writer.pending.get(account);
18669
+ for (const [key, field] of fields2) {
18670
+ if (pending?.get(key) === field)
18671
+ pending.delete(key);
18672
+ }
18673
+ if (!pending?.size)
18674
+ writer.pending.delete(account);
18675
+ }
18676
+ writer.failures = 0;
18677
+ } catch (error) {
18678
+ if (!writer.abort.signal.aborted && writer.failures++ === 0) {
18679
+ logger2.warn("vault quota publication delayed; retrying", {
18680
+ error: error instanceof Error ? error.message : String(error)
18681
+ });
18682
+ }
18683
+ } finally {
18684
+ writer.running = undefined;
18685
+ for (const wake of writer.wake)
18686
+ wake();
18687
+ const backoff = writer.failures ? Math.min(5000, 100 * 2 ** Math.min(writer.failures, 6)) * (0.5 + Math.random()) : COALESCE_MS;
18688
+ schedule(writer, backoff);
18689
+ }
18690
+ })();
18691
+ }
18692
+ async function drainVaultQuota(path2, timeoutMs = 1000) {
18693
+ const key = resolve8(path2);
18694
+ const writer = writers.get(key);
18695
+ if (!writer)
18696
+ return;
18697
+ writer.draining = true;
18698
+ clearTimeout(writer.timer);
18699
+ writer.timer = undefined;
18700
+ let deadline;
18701
+ let wake;
18702
+ const drained = new Promise((done) => {
18703
+ wake = () => {
18704
+ if (!writer.pending.size || writer.abort.signal.aborted)
18705
+ done();
18706
+ };
18707
+ writer.wake.add(wake);
18708
+ wake();
18709
+ });
18710
+ try {
18711
+ if (writer.pending.size)
18712
+ flush2(writer);
18713
+ await Promise.race([
18714
+ drained,
18715
+ new Promise((done) => {
18716
+ deadline = setTimeout(done, Math.max(0, timeoutMs));
18717
+ })
18718
+ ]);
18719
+ } finally {
18720
+ clearTimeout(deadline);
18721
+ if (wake)
18722
+ writer.wake.delete(wake);
18723
+ writer.draining = false;
18724
+ if (!writer.listeners.size) {
18725
+ writer.abort.abort();
18726
+ clearTimeout(writer.timer);
18727
+ writer.pending.clear();
18728
+ if (writers.get(key) === writer)
18729
+ writers.delete(key);
18730
+ }
18731
+ }
18732
+ }
18733
+
18161
18734
  // ../../node_modules/@cortexkit/common-auth/dist/claustrum/consumer.js
18162
18735
  class ClaustrumConsumer {
18163
18736
  #options;
@@ -18175,9 +18748,13 @@ class ClaustrumConsumer {
18175
18748
  #releaseInsulaWatch;
18176
18749
  #insulaSkips = new Map;
18177
18750
  #discoveredAt;
18751
+ #releaseQuotaWriter;
18178
18752
  constructor(options) {
18179
18753
  this.#options = options;
18180
18754
  this.#logger = options.logger ?? createLogger("claustrum");
18755
+ this.#releaseQuotaWriter = retainVaultQuotaWriter(options.rosterPath, (publication2) => {
18756
+ this.#roster = applyVaultQuota(this.#roster, publication2).roster;
18757
+ });
18181
18758
  }
18182
18759
  #assertOpen(signal) {
18183
18760
  this.#shutdown.signal.throwIfAborted();
@@ -18191,7 +18768,7 @@ class ClaustrumConsumer {
18191
18768
  this.#shutdown.signal,
18192
18769
  ...signal ? [signal] : []
18193
18770
  ]);
18194
- return new Promise((resolve7, reject) => {
18771
+ return new Promise((resolve9, reject) => {
18195
18772
  const cleanup2 = () => {
18196
18773
  combined.signal.removeEventListener("abort", abort);
18197
18774
  combined.dispose();
@@ -18206,7 +18783,7 @@ class ClaustrumConsumer {
18206
18783
  if (combined.signal.aborted)
18207
18784
  reject(combined.signal.reason);
18208
18785
  else
18209
- resolve7(value);
18786
+ resolve9(value);
18210
18787
  }, (error) => {
18211
18788
  cleanup2();
18212
18789
  reject(error);
@@ -18292,11 +18869,9 @@ class ClaustrumConsumer {
18292
18869
  let discovered;
18293
18870
  const roster = await refreshVaultRoster({
18294
18871
  path: this.#options.rosterPath,
18295
- custody: {
18296
- discover: async (signal) => {
18297
- discovered = await custody.discover(signal);
18298
- return discovered;
18299
- }
18872
+ custody,
18873
+ onInventory: (inventory) => {
18874
+ discovered = inventory;
18300
18875
  },
18301
18876
  isActive: () => this.#active(),
18302
18877
  signal: this.#shutdown.signal,
@@ -18309,7 +18884,7 @@ class ClaustrumConsumer {
18309
18884
  });
18310
18885
  this.#assertOpen();
18311
18886
  const changed = roster?.view !== this.#roster?.view;
18312
- this.#roster = roster;
18887
+ this.#roster = pendingVaultQuota(this.#options.rosterPath, roster);
18313
18888
  custody.retain(roster?.rows ?? []);
18314
18889
  if (discovered && roster?.view !== undefined)
18315
18890
  this.#grantReach = discovered.grantReach ? { view: roster.view, reach: discovered.grantReach } : undefined;
@@ -18406,7 +18981,7 @@ class ClaustrumConsumer {
18406
18981
  return;
18407
18982
  try {
18408
18983
  await readClaustrumEnrollmentToken(this.#options.tokenPath);
18409
- const roster = await readVaultRoster(this.#options.rosterPath);
18984
+ const roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18410
18985
  const row = roster?.rows.find((entry2) => entry2.routeId === routeId);
18411
18986
  return this.#normalizeInsulaQuota(row?.accountIdentity);
18412
18987
  } catch {
@@ -18419,7 +18994,7 @@ class ClaustrumConsumer {
18419
18994
  return { miss: "unreachable" };
18420
18995
  try {
18421
18996
  await readClaustrumEnrollmentToken(this.#options.tokenPath);
18422
- const roster = await readVaultRoster(this.#options.rosterPath);
18997
+ const roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18423
18998
  const account = roster?.rows.find((row) => row.routeId === routeId)?.accountIdentity;
18424
18999
  if (!account || !this.#insula)
18425
19000
  return { miss: "unreachable" };
@@ -18463,7 +19038,7 @@ class ClaustrumConsumer {
18463
19038
  this.#insula = undefined;
18464
19039
  throw new ClaustrumConsumerError("not-active", "Claustrum scoped custody is not active");
18465
19040
  }
18466
- const current = await readVaultRoster(this.#options.rosterPath);
19041
+ const current = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18467
19042
  this.#assertOpen(signal);
18468
19043
  const observed = roster.rows.find((row) => row.routeId === routeId);
18469
19044
  const configured = current?.rows.find((row) => row.routeId === routeId);
@@ -18531,17 +19106,17 @@ class ClaustrumConsumer {
18531
19106
  async decline(routeId) {
18532
19107
  this.#assertOpen();
18533
19108
  await declineVaultRoute(this.#options.rosterPath, routeId);
18534
- this.#roster = await readVaultRoster(this.#options.rosterPath);
19109
+ this.#roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18535
19110
  this.#custody?.retain(this.#roster?.rows ?? []);
18536
19111
  }
18537
19112
  async accept(routeId) {
18538
19113
  this.#assertOpen();
18539
19114
  await acceptVaultRoute(this.#options.rosterPath, routeId);
18540
- this.#roster = await readVaultRoster(this.#options.rosterPath);
19115
+ this.#roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18541
19116
  }
18542
19117
  async recordQuota(routeId, observation, attempt) {
18543
19118
  this.#assertOpen();
18544
- const kept = await recordVaultQuota(this.#options.rosterPath, {
19119
+ return recordVaultQuota(this.#options.rosterPath, {
18545
19120
  routeId,
18546
19121
  observation,
18547
19122
  credentialId: attempt.credentialId,
@@ -18553,20 +19128,14 @@ class ClaustrumConsumer {
18553
19128
  expectedAccountIdentity: attempt.expectedAccountIdentity
18554
19129
  }
18555
19130
  });
18556
- if (kept)
18557
- this.#roster = await readVaultRoster(this.#options.rosterPath);
18558
- return kept;
18559
19131
  }
18560
19132
  async recordAccountQuota(routeId, accountIdentity, observation) {
18561
19133
  this.#assertOpen();
18562
- const kept = await recordVaultAccountQuota(this.#options.rosterPath, {
19134
+ return recordVaultAccountQuota(this.#options.rosterPath, {
18563
19135
  routeId,
18564
19136
  accountIdentity,
18565
19137
  observation
18566
19138
  });
18567
- if (kept)
18568
- this.#roster = await readVaultRoster(this.#options.rosterPath);
18569
- return kept;
18570
19139
  }
18571
19140
  close() {
18572
19141
  if (this.#shutdown.signal.aborted)
@@ -18581,6 +19150,12 @@ class ClaustrumConsumer {
18581
19150
  this.#insula = undefined;
18582
19151
  this.#roster = undefined;
18583
19152
  this.#grantReach = undefined;
19153
+ this.#releaseQuotaWriter();
19154
+ forgetPendingVaultDiscovery(this.#options.rosterPath);
19155
+ }
19156
+ async dispose() {
19157
+ this.close();
19158
+ await this.#releaseQuotaWriter();
18584
19159
  }
18585
19160
  }
18586
19161
 
@@ -18621,16 +19196,16 @@ function nativeCode(value) {
18621
19196
  class NativeCustodyError extends Error {
18622
19197
  code;
18623
19198
  constructor(code) {
18624
- const safeCode = nativeCode(code);
18625
- super(`Native custody refused: ${safeCode}`);
19199
+ const safeCode2 = nativeCode(code);
19200
+ super(`Native custody refused: ${safeCode2}`);
18626
19201
  this.name = "NativeCustodyError";
18627
- this.code = safeCode;
19202
+ this.code = safeCode2;
18628
19203
  }
18629
19204
  }
18630
19205
  function createNativeCustody(options) {
18631
19206
  const env = { ...options.env ?? process.env };
18632
19207
  const connect = options.connect;
18633
- const logger2 = options.logger;
19208
+ const logger3 = options.logger;
18634
19209
  let closed = false;
18635
19210
  let revoked = false;
18636
19211
  let client;
@@ -18677,8 +19252,8 @@ function createNativeCustody(options) {
18677
19252
  let stopped = false;
18678
19253
  let inner;
18679
19254
  let finish = () => {};
18680
- const ended = new Promise((resolve7) => {
18681
- finish = resolve7;
19255
+ const ended = new Promise((resolve9) => {
19256
+ finish = resolve9;
18682
19257
  });
18683
19258
  const failed = (error) => stopped || closed || error instanceof NativeCustodyError ? { kind: "stopped" } : classifyVaultFailure(error) === "unreachable" ? { kind: "transport_lost", error: new ClaustrumUnreachableError } : { kind: "ended" };
18684
19259
  Promise.resolve().then(connection).then((owned) => {
@@ -18727,8 +19302,8 @@ function createNativeCustody(options) {
18727
19302
  ...options.setTimeout && { setTimeoutImpl: options.setTimeout },
18728
19303
  ...options.clearTimeout && { clearTimeoutImpl: options.clearTimeout },
18729
19304
  logger: {
18730
- warn: () => logger2?.warn("Native custody inventory record skipped"),
18731
- debug: () => logger2?.debug("Native custody failure reported")
19305
+ warn: () => logger3?.warn("Native custody inventory record skipped"),
19306
+ debug: () => logger3?.debug("Native custody failure reported")
18732
19307
  }
18733
19308
  });
18734
19309
  async function run(operation, signal) {
@@ -18852,13 +19427,13 @@ function createNativeCustody(options) {
18852
19427
  }
18853
19428
 
18854
19429
  // src/native-vault-invalidation.ts
18855
- import { resolve as resolve7 } from "node:path";
19430
+ import { resolve as resolve9 } from "node:path";
18856
19431
  var holders = new Set;
18857
19432
  function watchNativeVaultAuthority(holder) {
18858
19433
  const held = {
18859
19434
  ...holder,
18860
- roster: resolve7(holder.roster),
18861
- tokenPath: resolve7(holder.tokenPath)
19435
+ roster: resolve9(holder.roster),
19436
+ tokenPath: resolve9(holder.tokenPath)
18862
19437
  };
18863
19438
  holders.add(held);
18864
19439
  return () => {
@@ -18867,12 +19442,12 @@ function watchNativeVaultAuthority(holder) {
18867
19442
  }
18868
19443
  function retainNativeVaultRoster(path2, roster) {
18869
19444
  for (const holder of holders)
18870
- if (holder.roster === resolve7(path2))
19445
+ if (holder.roster === resolve9(path2))
18871
19446
  holder.retain(roster);
18872
19447
  }
18873
19448
  function closeNativeVaultAuthority(tokenPath) {
18874
19449
  for (const holder of holders)
18875
- if (holder.tokenPath === resolve7(tokenPath))
19450
+ if (holder.tokenPath === resolve9(tokenPath))
18876
19451
  holder.close();
18877
19452
  }
18878
19453
 
@@ -18906,9 +19481,18 @@ var reasons = new Set([
18906
19481
  "ETIMEDOUT",
18907
19482
  "ERR_PRIVATE_FILES_SECURITY"
18908
19483
  ]);
19484
+ var addonUnavailable = new Set([
19485
+ "ERR_PRIVATE_FILES_UNAVAILABLE",
19486
+ "native-addon-unavailable"
19487
+ ]);
19488
+ var privateFilesUnavailableReasons = new Set([
19489
+ "unsupported-filesystem",
19490
+ "native-addon-unavailable"
19491
+ ]);
18909
19492
  async function logRefusal(host, paths, readStatus) {
18910
19493
  let stage = "enrollment";
18911
19494
  let reason = "unreadable";
19495
+ let unavailable = false;
18912
19496
  try {
18913
19497
  await readStatus(paths, `anthropic-auth-${host}`);
18914
19498
  } catch (error) {
@@ -18917,17 +19501,31 @@ async function logRefusal(host, paths, readStatus) {
18917
19501
  const detail = current;
18918
19502
  if (detail.stage && stages.has(detail.stage))
18919
19503
  stage = detail.stage;
18920
- for (const value of [detail.kind, detail.code, detail.reason])
19504
+ for (const value of [detail.kind, detail.code, detail.reason]) {
18921
19505
  if (value && reasons.has(value))
18922
19506
  reason = value;
19507
+ if (value && addonUnavailable.has(value))
19508
+ unavailable = true;
19509
+ }
18923
19510
  current = detail.cause;
18924
19511
  }
18925
19512
  }
19513
+ if (unavailable)
19514
+ reason = "native-addon-unavailable";
18926
19515
  logger.warn("enrollment", "Native enrollment authority refused", {
18927
19516
  host,
18928
19517
  stage,
18929
19518
  reason
18930
19519
  });
19520
+ return reason;
19521
+ }
19522
+ var PRIVATE_FILES_UNAVAILABLE_MESSAGE = "Private file support didn't load on this machine (@cortexkit/private-files). Reinstall the plugin; if this persists, report it with your OS and Node version.";
19523
+
19524
+ class NativePrivateFilesUnavailableError extends NativeCustodyError {
19525
+ constructor() {
19526
+ super("invalid-token");
19527
+ this.message = PRIVATE_FILES_UNAVAILABLE_MESSAGE;
19528
+ }
18931
19529
  }
18932
19530
  async function readNativeEnrollmentMode(host, env = process.env, dependencies = { enrollmentAuthority, readClaustrumEnrollmentStatus }) {
18933
19531
  const paths = getHostClaustrumEnrollmentPaths(host, env);
@@ -18935,7 +19533,9 @@ async function readNativeEnrollmentMode(host, env = process.env, dependencies =
18935
19533
  if (authority !== "vault")
18936
19534
  closeNativeVaultAuthority(getHostClaustrumEnrollmentPaths(host, env).tokenPath);
18937
19535
  if (authority === "unreadable") {
18938
- await logRefusal(host, paths, dependencies.readClaustrumEnrollmentStatus);
19536
+ const reason = await logRefusal(host, paths, dependencies.readClaustrumEnrollmentStatus);
19537
+ if (privateFilesUnavailableReasons.has(reason))
19538
+ throw new NativePrivateFilesUnavailableError;
18939
19539
  throw new NativeCustodyError("invalid-token");
18940
19540
  }
18941
19541
  return authority === "vault" ? "claustrum" : "local";
@@ -19118,12 +19718,12 @@ async function joinNativePoolWrite(paths, signals, check, onLockEvent) {
19118
19718
  function pause(ms, signals) {
19119
19719
  if (signals.some((signal) => signal.aborted))
19120
19720
  return Promise.resolve();
19121
- return new Promise((resolve8) => {
19721
+ return new Promise((resolve10) => {
19122
19722
  const wake = () => {
19123
19723
  clearTimeout(timer);
19124
19724
  for (const signal of signals)
19125
19725
  signal.removeEventListener("abort", wake);
19126
- resolve8();
19726
+ resolve10();
19127
19727
  };
19128
19728
  const timer = setTimeout(wake, ms);
19129
19729
  for (const signal of signals)
@@ -19379,7 +19979,7 @@ function createNativeRefreshCoordinator(options) {
19379
19979
  name: spec.name,
19380
19980
  timeoutMs: POOL_LOCK_DEFAULTS.timeoutMs
19381
19981
  });
19382
- await new Promise((resolve8) => setTimeout(resolve8, Math.min(POOL_LOCK_DEFAULTS.retryMs, remaining)));
19982
+ await new Promise((resolve10) => setTimeout(resolve10, Math.min(POOL_LOCK_DEFAULTS.retryMs, remaining)));
19383
19983
  }
19384
19984
  }
19385
19985
  async function run(job, request) {
@@ -19949,7 +20549,7 @@ class NativeMigrationSourceError extends Error {
19949
20549
  }
19950
20550
  }
19951
20551
  var MAX_SOURCE_BYTES = 4 * 1024 * 1024;
19952
- function isRecord11(value) {
20552
+ function isRecord10(value) {
19953
20553
  return value !== null && typeof value === "object" && !Array.isArray(value);
19954
20554
  }
19955
20555
  function freezeJson(root) {
@@ -20029,7 +20629,7 @@ async function readNativeMigrationSource(role, path2, hooks = {}) {
20029
20629
  } catch {
20030
20630
  throw new NativeMigrationSourceError(role, "invalid-source");
20031
20631
  }
20032
- if (!isRecord11(data))
20632
+ if (!isRecord10(data))
20033
20633
  throw new NativeMigrationSourceError(role, "invalid-source");
20034
20634
  return sourceSnapshot({
20035
20635
  role,
@@ -20081,7 +20681,7 @@ class NativeAuthorityError extends Error {
20081
20681
  code;
20082
20682
  constructor(code) {
20083
20683
  super({
20084
- "migration-required": "Anthropic account migration is required. Stop OpenCode, LiteCode and Pi, then run npx @cortexkit/opencode-anthropic-auth@2.0.0 setup",
20684
+ "migration-required": "Anthropic account migration is required. Stop OpenCode, LiteCode and Pi, then run npx @cortexkit/opencode-anthropic-auth setup",
20085
20685
  "migration-incomplete": "Anthropic account migration is incomplete; resume setup",
20086
20686
  "invalid-journal": "Anthropic account migration journal is invalid",
20087
20687
  "journal-conflict": "Anthropic account migration journal changed"
@@ -20090,7 +20690,7 @@ class NativeAuthorityError extends Error {
20090
20690
  this.name = "NativeAuthorityError";
20091
20691
  }
20092
20692
  }
20093
- function isRecord12(value) {
20693
+ function isRecord11(value) {
20094
20694
  return value !== null && typeof value === "object" && !Array.isArray(value);
20095
20695
  }
20096
20696
  function captureJournalJson(value) {
@@ -20126,19 +20726,19 @@ function isCapturedPath(value) {
20126
20726
  return typeof value === "string" && isAbsolute4(value) && !/\p{Cc}/u.test(value) && !value.endsWith(sep) && normalize(value) === value && (sep !== "\\" || parse3(value).root !== sep) && !value.split(sep).some((part) => part === "." || part === "..");
20127
20727
  }
20128
20728
  function isSources(value) {
20129
- return isRecord12(value) && hasKeys(value, ["config", "state", "hostAuth", "routing"]) && isFileDigest(value.config) && isFileDigest(value.state) && isHostEntry(value.hostAuth) && isFileDigest(value.routing);
20729
+ return isRecord11(value) && hasKeys(value, ["config", "state", "hostAuth", "routing"]) && isFileDigest(value.config) && isFileDigest(value.state) && isHostEntry(value.hostAuth) && isFileDigest(value.routing);
20130
20730
  }
20131
20731
  function isRoutingPaths(value) {
20132
- return isRecord12(value) && hasKeys(value, ["source", "destination"]) && isCapturedPath(value.source) && isCapturedPath(value.destination);
20732
+ return isRecord11(value) && hasKeys(value, ["source", "destination"]) && isCapturedPath(value.source) && isCapturedPath(value.destination);
20133
20733
  }
20134
20734
  function isText(value) {
20135
20735
  return typeof value === "string" && value.length > 0;
20136
20736
  }
20137
20737
  function decodeRoster2(value) {
20138
- if (!isRecord12(value) || !hasKeys(value, ["version", "view", "complete", "rows", "declined"]) || value.version !== 1 || !isText(value.view) || value.complete !== true || !Array.isArray(value.rows) || !Array.isArray(value.declined))
20738
+ if (!isRecord11(value) || !hasKeys(value, ["version", "view", "complete", "rows", "declined"]) || value.version !== 1 || !isText(value.view) || value.complete !== true || !Array.isArray(value.rows) || !Array.isArray(value.declined))
20139
20739
  throw new NativeAuthorityError("invalid-journal");
20140
20740
  const rows = value.rows.map((row) => {
20141
- if (!isRecord12(row) || !hasKeys(row, [
20741
+ if (!isRecord11(row) || !hasKeys(row, [
20142
20742
  "routeId",
20143
20743
  "credentialId",
20144
20744
  "credentialType",
@@ -20161,7 +20761,7 @@ function decodeRoster2(value) {
20161
20761
  };
20162
20762
  });
20163
20763
  const declined = value.declined.map((entry2) => {
20164
- if (!isRecord12(entry2) || !isText(entry2.credentialId) || !(hasKeys(entry2, ["credentialId"]) || hasKeys(entry2, ["credentialId", "accountIdentity"]) && isText(entry2.accountIdentity)))
20764
+ if (!isRecord11(entry2) || !isText(entry2.credentialId) || !(hasKeys(entry2, ["credentialId"]) || hasKeys(entry2, ["credentialId", "accountIdentity"]) && isText(entry2.accountIdentity)))
20165
20765
  throw new NativeAuthorityError("invalid-journal");
20166
20766
  return isText(entry2.accountIdentity) ? {
20167
20767
  credentialId: entry2.credentialId,
@@ -20173,7 +20773,7 @@ function decodeRoster2(value) {
20173
20773
  return { version: 1, view: value.view, complete: true, rows, declined };
20174
20774
  }
20175
20775
  function decodeDigestPair(value, keys4, valid) {
20176
- if (!isRecord12(value) || !hasKeys(value, [...keys4]) || !keys4.every((key) => valid(value[key])))
20776
+ if (!isRecord11(value) || !hasKeys(value, [...keys4]) || !keys4.every((key) => valid(value[key])))
20177
20777
  throw new NativeAuthorityError("invalid-journal");
20178
20778
  return Object.fromEntries(keys4.map((key) => [key, value[key]]));
20179
20779
  }
@@ -20181,7 +20781,7 @@ var ACTIVATION_PHASES = ["prepared", "published", "committed"];
20181
20781
  function decodeActivation(value, phase) {
20182
20782
  if (value === null)
20183
20783
  return null;
20184
- if (!isRecord12(value))
20784
+ if (!isRecord11(value))
20185
20785
  throw new NativeAuthorityError("invalid-journal");
20186
20786
  if (value.kind === "requested" && hasKeys(value, ["kind"]))
20187
20787
  return { kind: "requested" };
@@ -20195,7 +20795,7 @@ function decodeActivation(value, phase) {
20195
20795
  "settings",
20196
20796
  "runtime",
20197
20797
  "hostAuth"
20198
- ]) || !ACTIVATION_PHASES.some((item) => item === value.phase) || !isRecord12(value.primary) || !hasKeys(value.primary, ["routeId", "credentialId", "accountIdentity"]) || !isText(value.primary.routeId) || !isText(value.primary.credentialId) || !isText(value.primary.accountIdentity) || !Array.isArray(value.removeIds) || !value.removeIds.every(isText))
20798
+ ]) || !ACTIVATION_PHASES.some((item) => item === value.phase) || !isRecord11(value.primary) || !hasKeys(value.primary, ["routeId", "credentialId", "accountIdentity"]) || !isText(value.primary.routeId) || !isText(value.primary.credentialId) || !isText(value.primary.accountIdentity) || !Array.isArray(value.removeIds) || !value.removeIds.every(isText))
20199
20799
  throw new NativeAuthorityError("invalid-journal");
20200
20800
  const primary = {
20201
20801
  routeId: value.primary.routeId,
@@ -20222,7 +20822,7 @@ function decodeActivation(value, phase) {
20222
20822
  }
20223
20823
  function decodeJournal(input, storageId) {
20224
20824
  const value = captureJournalJson(input);
20225
- if (!isRecord12(value) || value.storageId !== storageId)
20825
+ if (!isRecord11(value) || value.storageId !== storageId)
20226
20826
  throw new NativeAuthorityError("invalid-journal");
20227
20827
  if (value.version === 5 && value.kind === "empty-init") {
20228
20828
  if (!hasKeys(value, ["version", "kind", "storageId", "host", "phase"]) || value.host !== "opencode" || value.phase !== "committed")
@@ -20398,7 +20998,7 @@ async function beginNativeMigration(paths, input, hooks = {}) {
20398
20998
  }
20399
20999
  async function recordNativeMigrationExpectations(paths, expectations, hooks = {}) {
20400
21000
  const captured = captureJournalJson(expectations);
20401
- if (!isRecord12(captured) || !hasKeys(captured, [
21001
+ if (!isRecord11(captured) || !hasKeys(captured, [
20402
21002
  "expectedHostAuth",
20403
21003
  "expectedRouting",
20404
21004
  "preparedProof"
@@ -20473,7 +21073,7 @@ function journalLock(hooks) {
20473
21073
  }
20474
21074
  async function recordNativeCustodyActivation(paths, plan, hooks = {}) {
20475
21075
  const captured = captureJournalJson(plan);
20476
- if (!isRecord12(captured) || captured.phase !== "prepared")
21076
+ if (!isRecord11(captured) || captured.phase !== "prepared")
20477
21077
  throw new NativeAuthorityError("journal-conflict");
20478
21078
  const decoded = decodeActivation(captured, "retired");
20479
21079
  if (decoded?.kind !== "activation")
@@ -20819,7 +21419,7 @@ function createNativeUsagePublisher(channel) {
20819
21419
  return {
20820
21420
  observe,
20821
21421
  publish(write) {
20822
- observe(new Promise((resolve8) => setTimeout(resolve8, 0)).then(write));
21422
+ observe(new Promise((resolve10) => setTimeout(resolve10, 0)).then(write));
20823
21423
  },
20824
21424
  async drain() {
20825
21425
  while (pending.size)
@@ -20895,7 +21495,7 @@ class NativeQuotaObservations extends Map {
20895
21495
  }
20896
21496
 
20897
21497
  // src/native-runtime-registry.ts
20898
- import { resolve as resolve8 } from "node:path";
21498
+ import { resolve as resolve10 } from "node:path";
20899
21499
  var identities = new WeakMap;
20900
21500
  var nextIdentity = 0;
20901
21501
  function nativeRuntimeOptionIdentity(value) {
@@ -20924,14 +21524,14 @@ function nativeRuntimeStorageKey(options) {
20924
21524
  "runtime",
20925
21525
  "journal",
20926
21526
  "roster"
20927
- ].map((field) => resolve8(paths[field])),
20928
- resolve8(enrollment.tokenPath),
20929
- resolve8(enrollment.statePath),
20930
- resolve8(connection)
21527
+ ].map((field) => resolve10(paths[field])),
21528
+ resolve10(enrollment.tokenPath),
21529
+ resolve10(enrollment.statePath),
21530
+ resolve10(connection)
20931
21531
  ]);
20932
21532
  }
20933
21533
  function nativeRuntimeConnectionFile(host, env) {
20934
- return resolve8(resolveClaustrumConnectionPath(host === "pi" ? env.PI_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE : undefined, host === "pi" ? {
21534
+ return resolve10(resolveClaustrumConnectionPath(host === "pi" ? env.PI_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE : undefined, host === "pi" ? {
20935
21535
  ...env,
20936
21536
  OPENCODE_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE: undefined
20937
21537
  } : env));
@@ -20970,9 +21570,9 @@ class NativeRuntimeRegistry {
20970
21570
 
20971
21571
  // src/native-vault-paths.ts
20972
21572
  import { createHash as createHash15 } from "node:crypto";
20973
- import { basename as basename5, dirname as dirname11, join as join12 } from "node:path";
21573
+ import { basename as basename5, dirname as dirname11, join as join13 } from "node:path";
20974
21574
  function sibling(path2, expected, name, suffix) {
20975
- return basename5(path2) === expected ? join12(dirname11(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
21575
+ return basename5(path2) === expected ? join13(dirname11(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
20976
21576
  }
20977
21577
  function nativeVaultPaths(local) {
20978
21578
  const config = sibling(local.legacyConfig, "anthropic-auth.json", "anthropic-auth-vault-settings.json", "vault-settings");
@@ -21185,10 +21785,10 @@ function seedCode(value) {
21185
21785
  class NativeRosterSeedError extends Error {
21186
21786
  code;
21187
21787
  constructor(code) {
21188
- const safeCode = seedCode(code);
21189
- super(`Native roster seed refused: ${safeCode}`);
21788
+ const safeCode2 = seedCode(code);
21789
+ super(`Native roster seed refused: ${safeCode2}`);
21190
21790
  this.name = "NativeRosterSeedError";
21191
- this.code = safeCode;
21791
+ this.code = safeCode2;
21192
21792
  }
21193
21793
  }
21194
21794
  function guarded(body) {
@@ -21533,8 +22133,8 @@ function mergeHeaderQuotaSnapshot(existing, incoming) {
21533
22133
  // src/quota-manager.ts
21534
22134
  var nativeSetTimeout = globalThis.setTimeout;
21535
22135
  function pauseOnRealTimer(ms) {
21536
- return new Promise((resolve9) => {
21537
- const id2 = nativeSetTimeout(resolve9, ms);
22136
+ return new Promise((resolve11) => {
22137
+ const id2 = nativeSetTimeout(resolve11, ms);
21538
22138
  if (typeof id2 === "object" && "unref" in id2)
21539
22139
  id2.unref();
21540
22140
  });
@@ -22301,7 +22901,8 @@ async function publishNativeVaultRosterSeed(paths, input, options = {}) {
22301
22901
  }
22302
22902
  async function publishNativeVaultRuntimeSeed(paths, state, options = {}) {
22303
22903
  const imported = decodeNativeRuntime(captureNativePlainData(state), paths.storageId);
22304
- await mutateVaultRoster(paths.roster, async (roster, lease) => {
22904
+ const assertPinned = async () => {
22905
+ const roster = await readVaultRoster(paths.roster);
22305
22906
  for (const [id2, entry2] of Object.entries(imported.accounts)) {
22306
22907
  if (entry2.binding.kind !== "custody")
22307
22908
  continue;
@@ -22310,13 +22911,13 @@ async function publishNativeVaultRuntimeSeed(paths, state, options = {}) {
22310
22911
  if (!row?.accountIdentity || row.accountIdentity !== binding2.accountIdentity || row.credentialId !== binding2.credentialId && !row.aliases?.includes(binding2.credentialId))
22311
22912
  throw new NativeRuntimeError("publication-refused");
22312
22913
  }
22313
- await updateNativeRuntime(paths.runtime, paths.storageId, () => imported, {
22314
- beforeRename: async () => {
22315
- await options.assertOwned?.();
22316
- await lease.assertOwned();
22317
- }
22318
- });
22319
- return { result: undefined };
22914
+ };
22915
+ await assertPinned();
22916
+ await updateNativeRuntime(paths.runtime, paths.storageId, () => imported, {
22917
+ beforeRename: async () => {
22918
+ await options.assertOwned?.();
22919
+ await assertPinned();
22920
+ }
22320
22921
  });
22321
22922
  }
22322
22923
  var NATIVE_VAULT_CONNECT_TIMEOUT_MS = 2000;
@@ -22363,11 +22964,6 @@ function createNativeVaultRuntime(options) {
22363
22964
  onLockEvent: options.onLockEvent
22364
22965
  });
22365
22966
  const observeLock = nativeLockObserver(options.onLockEvent);
22366
- const observeRosterLock = () => observeLock?.({
22367
- type: "acquiring",
22368
- name: "claustrum-roster-write",
22369
- path: paths.roster
22370
- });
22371
22967
  let rosterWatch;
22372
22968
  let rosterWatching = false;
22373
22969
  let rosterView;
@@ -22584,46 +23180,49 @@ function createNativeVaultRuntime(options) {
22584
23180
  await requireActive(signal);
22585
23181
  if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22586
23182
  return;
22587
- observeRosterLock();
22588
- await mutateVaultRoster(paths.roster, async (roster, lease) => {
22589
- if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22590
- return { result: undefined };
22591
- const primary = roster?.rows.find((row) => (row.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID || row.aliases?.includes(NATIVE_PRIMARY_CREDENTIAL_ID)) && row.credentialType === "oauth" && !row.stale && !row.unclaimed && typeof row.accountIdentity === "string" && row.accountIdentity.length > 0);
22592
- const read = await store.readSettings();
22593
- if (read.status !== "ready")
22594
- throw new NativeCustodyError("invalid-state");
22595
- const previous = nativeVaultPrimaryPin(read.settings);
22596
- if (!absentOnly && (!primary && !previous || primary && previous?.routeId === primary.routeId && previous.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID && previous.accountIdentity === primary.accountIdentity))
22597
- return { result: undefined };
22598
- const writer = createNativePoolStore({
22599
- paths,
22600
- quota: nativeQuotaCodec,
22601
- onLockEvent: options.onLockEvent,
22602
- onStep: async (point) => {
22603
- if (point === "before-config-write" || point === "before-state-write") {
22604
- await requireActive(signal);
22605
- await lease.assertOwned();
22606
- }
22607
- }
22608
- });
22609
- await writer.updateSettings(async (settings) => {
22610
- if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22611
- return settings;
22612
- if (primary) {
22613
- settings.mainAccountId = primary.routeId;
22614
- settings.claustrum = {
22615
- primaryAccount: {
22616
- credentialId: NATIVE_PRIMARY_CREDENTIAL_ID,
22617
- accountId: primary.accountIdentity
22618
- }
22619
- };
22620
- } else {
22621
- delete settings.mainAccountId;
22622
- delete settings.claustrum;
23183
+ const roster = await readVaultRoster(paths.roster);
23184
+ if (absentOnly && !await nativeVaultFileAbsent(paths.config))
23185
+ return;
23186
+ const primaryFor = (roster2) => roster2?.rows.find((row) => (row.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID || row.aliases?.includes(NATIVE_PRIMARY_CREDENTIAL_ID)) && row.credentialType === "oauth" && !row.stale && !row.unclaimed && typeof row.accountIdentity === "string" && row.accountIdentity.length > 0);
23187
+ const primary = primaryFor(roster);
23188
+ const read = await store.readSettings();
23189
+ if (read.status !== "ready")
23190
+ throw new NativeCustodyError("invalid-state");
23191
+ const previous = nativeVaultPrimaryPin(read.settings);
23192
+ if (!absentOnly && (!primary && !previous || primary && previous?.routeId === primary.routeId && previous.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID && previous.accountIdentity === primary.accountIdentity))
23193
+ return;
23194
+ const assertPrimary = async () => {
23195
+ await requireActive(signal);
23196
+ const pinned = primaryFor(await readVaultRoster(paths.roster));
23197
+ if (pinned?.routeId !== primary?.routeId || pinned?.accountIdentity !== primary?.accountIdentity)
23198
+ throw new NativeRuntimeError("publication-refused");
23199
+ };
23200
+ const writer = createNativePoolStore({
23201
+ paths,
23202
+ quota: nativeQuotaCodec,
23203
+ onLockEvent: options.onLockEvent,
23204
+ onStep: async (point) => {
23205
+ if (point === "before-config-write" || point === "before-state-write") {
23206
+ await assertPrimary();
22623
23207
  }
23208
+ }
23209
+ });
23210
+ await writer.updateSettings(async (settings) => {
23211
+ if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22624
23212
  return settings;
22625
- });
22626
- return { result: undefined };
23213
+ if (primary) {
23214
+ settings.mainAccountId = primary.routeId;
23215
+ settings.claustrum = {
23216
+ primaryAccount: {
23217
+ credentialId: NATIVE_PRIMARY_CREDENTIAL_ID,
23218
+ accountId: primary.accountIdentity
23219
+ }
23220
+ };
23221
+ } else {
23222
+ delete settings.mainAccountId;
23223
+ delete settings.claustrum;
23224
+ }
23225
+ return settings;
22627
23226
  });
22628
23227
  }
22629
23228
  async function rowFor(roster, routeId) {
@@ -23003,56 +23602,52 @@ function createNativeVaultRuntime(options) {
23003
23602
  ]);
23004
23603
  if ((versions.get(key) ?? 0) > receipt.recordVersion)
23005
23604
  return false;
23006
- observeRosterLock();
23007
- return mutateVaultRoster(paths.roster, async (roster, lease) => {
23008
- const row = await rowFor(roster, route.logicalId);
23009
- if (!row?.accountIdentity || row.routeId !== route.routeId || row.accountIdentity !== receipt.assertedAccountIdentity || row.credentialId !== receipt.credentialId && !row.aliases?.includes(receipt.credentialId))
23010
- return { result: false };
23011
- const accountIdentity = row.accountIdentity;
23012
- let kept = false;
23013
- try {
23014
- const outcome = await updateNativeRuntimeOptional(paths.runtime, paths.storageId, (current) => {
23015
- const old = current.accounts[route.routeId];
23016
- const binding2 = old?.binding;
23017
- if (binding2?.kind === "custody" && binding2.credentialId === receipt.credentialId && binding2.accountIdentity === receipt.assertedAccountIdentity && binding2.recordVersion > receipt.recordVersion)
23018
- throw new NativeRuntimeError("runtime-conflict");
23019
- const same = binding2?.kind === "custody" && binding2.accountIdentity === receipt.assertedAccountIdentity;
23020
- current.accounts[route.routeId] = change({
23021
- ...same ? old : {},
23022
- binding: {
23023
- kind: "custody",
23024
- storageId: paths.storageId,
23025
- routeId: route.routeId,
23026
- credentialId: receipt.credentialId,
23027
- accountIdentity,
23028
- recordVersion: receipt.recordVersion
23029
- }
23030
- });
23031
- kept = true;
23032
- return current;
23033
- }, {
23034
- onLockEvent: options.onLockEvent,
23035
- beforeRename: async () => {
23036
- await requireActive();
23037
- const pinned = await rowFor(roster, route.logicalId);
23038
- if (!pinned || pinned.routeId !== route.routeId || pinned.accountIdentity !== receipt.assertedAccountIdentity)
23039
- throw new NativeRuntimeError("publication-refused");
23040
- const superseded = (versions.get(key) ?? 0) > receipt.recordVersion;
23041
- if (superseded && onSuperseded === "refuse")
23042
- throw new NativeRuntimeError("runtime-conflict");
23043
- await lease.assertOwned();
23044
- return superseded ? "skip" : "publish";
23605
+ const row = await rowFor(await readVaultRoster(paths.roster), route.logicalId);
23606
+ if (!row?.accountIdentity || row.routeId !== route.routeId || row.accountIdentity !== receipt.assertedAccountIdentity || row.credentialId !== receipt.credentialId && !row.aliases?.includes(receipt.credentialId))
23607
+ return false;
23608
+ const accountIdentity = row.accountIdentity;
23609
+ let kept = false;
23610
+ try {
23611
+ const outcome = await updateNativeRuntimeOptional(paths.runtime, paths.storageId, (current) => {
23612
+ const old = current.accounts[route.routeId];
23613
+ const binding2 = old?.binding;
23614
+ if (binding2?.kind === "custody" && binding2.credentialId === receipt.credentialId && binding2.accountIdentity === receipt.assertedAccountIdentity && binding2.recordVersion > receipt.recordVersion)
23615
+ throw new NativeRuntimeError("runtime-conflict");
23616
+ const same = binding2?.kind === "custody" && binding2.accountIdentity === receipt.assertedAccountIdentity && (binding2.credentialId === row.credentialId || row.aliases?.includes(binding2.credentialId));
23617
+ current.accounts[route.routeId] = change({
23618
+ ...same ? old : {},
23619
+ binding: {
23620
+ kind: "custody",
23621
+ storageId: paths.storageId,
23622
+ routeId: route.routeId,
23623
+ credentialId: receipt.credentialId,
23624
+ accountIdentity,
23625
+ recordVersion: receipt.recordVersion
23045
23626
  }
23046
23627
  });
23047
- if (outcome.status === "skipped")
23048
- return { result: false };
23049
- } catch (error) {
23050
- if (error instanceof NativeRuntimeError && error.code === "runtime-conflict")
23051
- return { result: false };
23052
- throw error;
23053
- }
23054
- return { result: kept };
23055
- });
23628
+ kept = true;
23629
+ return current;
23630
+ }, {
23631
+ onLockEvent: options.onLockEvent,
23632
+ beforeRename: async () => {
23633
+ await requireActive();
23634
+ const pinned = await rowFor(await readVaultRoster(paths.roster), route.logicalId);
23635
+ if (!pinned || pinned.routeId !== route.routeId || pinned.accountIdentity !== receipt.assertedAccountIdentity || pinned.credentialId !== receipt.credentialId && !pinned.aliases?.includes(receipt.credentialId))
23636
+ throw new NativeRuntimeError("publication-refused");
23637
+ const superseded = (versions.get(key) ?? 0) > receipt.recordVersion;
23638
+ if (superseded && onSuperseded === "refuse")
23639
+ throw new NativeRuntimeError("runtime-conflict");
23640
+ return superseded ? "skip" : "publish";
23641
+ }
23642
+ });
23643
+ if (outcome.status === "skipped")
23644
+ return false;
23645
+ } catch (error) {
23646
+ if (error instanceof NativeRuntimeError && error.code === "runtime-conflict")
23647
+ return false;
23648
+ throw error;
23649
+ }
23650
+ return kept;
23056
23651
  }
23057
23652
  async function fetchReading(routeId, fetchImpl, signal, read, onFailure, dispatch) {
23058
23653
  const combined = signalFor(signal);
@@ -23136,7 +23731,7 @@ function recencyOnly(patch) {
23136
23731
  return keys4.length === 1 && keys4[0] === "lastUsed" && typeof patch.lastUsed === "number";
23137
23732
  }
23138
23733
  function waitFor(pending, signal) {
23139
- return new Promise((resolve9, reject) => {
23734
+ return new Promise((resolve11, reject) => {
23140
23735
  const abort = () => {
23141
23736
  cleanup2();
23142
23737
  reject(signal.reason);
@@ -23145,7 +23740,7 @@ function waitFor(pending, signal) {
23145
23740
  signal.addEventListener("abort", abort, { once: true });
23146
23741
  pending.then((value) => {
23147
23742
  cleanup2();
23148
- signal.aborted ? reject(signal.reason) : resolve9(value);
23743
+ signal.aborted ? reject(signal.reason) : resolve11(value);
23149
23744
  }, (error) => {
23150
23745
  cleanup2();
23151
23746
  reject(error);
@@ -23219,12 +23814,12 @@ function leaseNativeVaultRuntime(use, close) {
23219
23814
  // src/pool-paths.ts
23220
23815
  import { createHash as createHash17 } from "node:crypto";
23221
23816
  import { realpath as realpath3 } from "node:fs/promises";
23222
- import { basename as basename7, dirname as dirname13, join as join14, resolve as resolve9 } from "node:path";
23817
+ import { basename as basename7, dirname as dirname13, join as join15, resolve as resolve11 } from "node:path";
23223
23818
 
23224
23819
  // src/sticky-routing.ts
23225
23820
  import { createHash as createHash16, randomUUID as randomUUID14 } from "node:crypto";
23226
23821
  import { mkdir as mkdir10, readFile as readFile9, rename as rename12, rm as rm7, stat as stat7, writeFile as writeFile4 } from "node:fs/promises";
23227
- import { basename as basename6, dirname as dirname12, join as join13 } from "node:path";
23822
+ import { basename as basename6, dirname as dirname12, join as join14 } from "node:path";
23228
23823
  var STICKY_ROUTING_MAIN_ACCOUNT_ID = "main";
23229
23824
  var STICKY_ROUTING_SHORT_RESET_GRACE_MS = 15 * 60000;
23230
23825
  var STICKY_ROUTING_ASSIGNMENT_TTL_MS = 7 * 24 * 60 * 60000;
@@ -23274,14 +23869,14 @@ function createStickyNoRouteResponse(input) {
23274
23869
  }
23275
23870
  });
23276
23871
  }
23277
- function isRecord13(value) {
23872
+ function isRecord12(value) {
23278
23873
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
23279
23874
  }
23280
23875
  function finiteNumber(value) {
23281
23876
  return typeof value === "number" && Number.isFinite(value) ? value : undefined;
23282
23877
  }
23283
23878
  function normalizeAssignment(value) {
23284
- if (!isRecord13(value))
23879
+ if (!isRecord12(value))
23285
23880
  return;
23286
23881
  if (typeof value.accountId !== "string" || !["fable", "opus", "general"].includes(String(value.family))) {
23287
23882
  return;
@@ -23310,7 +23905,7 @@ function normalizeAssignment(value) {
23310
23905
  };
23311
23906
  }
23312
23907
  function normalizeState(value) {
23313
- if (!isRecord13(value) || value.version !== 1 || !isRecord13(value.assignments)) {
23908
+ if (!isRecord12(value) || value.version !== 1 || !isRecord12(value.assignments)) {
23314
23909
  return;
23315
23910
  }
23316
23911
  const assignments = {};
@@ -23328,7 +23923,7 @@ function normalizeState(value) {
23328
23923
  }
23329
23924
  function migrateStickyRoutingState(source2, rowIdMap) {
23330
23925
  try {
23331
- if (!isRecord13(source2) || !isRecord13(source2.assignments))
23926
+ if (!isRecord12(source2) || !isRecord12(source2.assignments))
23332
23927
  throw new Error;
23333
23928
  const entries = Object.entries(source2.assignments);
23334
23929
  const state = normalizeState({
@@ -23346,10 +23941,10 @@ function migrateStickyRoutingState(source2, rowIdMap) {
23346
23941
  const assignments = Object.create(null);
23347
23942
  for (const [index, [key, original]] of entries.entries()) {
23348
23943
  const assignment = state.assignments[String(index)];
23349
- if (!isRecord13(original) || !assignment)
23944
+ if (!isRecord12(original) || !assignment)
23350
23945
  throw new Error;
23351
- const fields = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
23352
- if (Object.keys(original).length !== fields.length || fields.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
23946
+ const fields2 = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
23947
+ if (Object.keys(original).length !== fields2.length || fields2.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
23353
23948
  throw new Error;
23354
23949
  }
23355
23950
  const accountId = rowIdMap.get(assignment.accountId);
@@ -23474,7 +24069,7 @@ function decideStickyQuotaFailure(input) {
23474
24069
  function getStickyRoutingStatePath(accountStoragePath) {
23475
24070
  const name = basename6(accountStoragePath);
23476
24071
  const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
23477
- return join13(dirname12(accountStoragePath), `${stem}-routing-state.json`);
24072
+ return join14(dirname12(accountStoragePath), `${stem}-routing-state.json`);
23478
24073
  }
23479
24074
  function stickyRetryAfterWithJitter(sessionId, retryAfterSeconds) {
23480
24075
  const hash2 = createHash16("sha256").update(sessionId).digest().readUInt32BE(0);
@@ -23575,7 +24170,7 @@ class StickySessionRouter {
23575
24170
  if (!wait || performance.now() >= deadline) {
23576
24171
  throw new Error("Timed out acquiring sticky routing state lock");
23577
24172
  }
23578
- await new Promise((resolve9) => setTimeout(resolve9, STICKY_ROUTING_LOCK_POLL_MS));
24173
+ await new Promise((resolve11) => setTimeout(resolve11, STICKY_ROUTING_LOCK_POLL_MS));
23579
24174
  }
23580
24175
  }
23581
24176
  recoverLocalPins() {
@@ -23690,7 +24285,7 @@ class StickySessionRouter {
23690
24285
  const source2 = await readNativeVaultLegacyJson(seed.legacyConfig);
23691
24286
  const routes = nativeVaultLegacyRoutes(source2, roster);
23692
24287
  const legacy = await readNativeVaultLegacyJson(getStickyRoutingStatePath(seed.legacyConfig));
23693
- if (isRecord13(legacy) && legacy.version === 1 && isRecord13(legacy.assignments)) {
24288
+ if (isRecord12(legacy) && legacy.version === 1 && isRecord12(legacy.assignments)) {
23694
24289
  for (const [key, raw] of Object.entries(legacy.assignments)) {
23695
24290
  if (!/^[0-9a-f]{64}$/.test(key) || Object.hasOwn(state.assignments, key))
23696
24291
  continue;
@@ -23941,7 +24536,7 @@ function resolveLocalRoutingDestination(host, paths, env) {
23941
24536
  return (host === "opencode" ? env.OPENCODE_ANTHROPIC_AUTH_ROUTING_STATE_FILE : env.PI_ANTHROPIC_AUTH_ROUTING_STATE_FILE) || getStickyRoutingStatePath(paths.config);
23942
24537
  }
23943
24538
  async function canonicalPath(path2) {
23944
- const absolute = resolve9(path2);
24539
+ const absolute = resolve11(path2);
23945
24540
  try {
23946
24541
  return await realpath3(absolute);
23947
24542
  } catch (error) {
@@ -23952,10 +24547,10 @@ async function canonicalPath(path2) {
23952
24547
  const parent = dirname13(absolute);
23953
24548
  if (parent === absolute)
23954
24549
  return absolute;
23955
- return join14(await canonicalPath(parent), basename7(absolute));
24550
+ return join15(await canonicalPath(parent), basename7(absolute));
23956
24551
  }
23957
24552
  function sibling2(path2, legacyName, name, suffix) {
23958
- return basename7(path2) === legacyName ? join14(dirname13(path2), name) : `${path2}.${suffix}.json`;
24553
+ return basename7(path2) === legacyName ? join15(dirname13(path2), name) : `${path2}.${suffix}.json`;
23959
24554
  }
23960
24555
  async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), legacyState = getAccountStatePath(legacyConfig)) {
23961
24556
  const [sourceConfig, sourceState] = await Promise.all([
@@ -24532,7 +25127,7 @@ class PersistentRelaySession {
24532
25127
  return;
24533
25128
  if (this.connecting)
24534
25129
  return await this.connecting;
24535
- this.connecting = new Promise((resolve10, reject) => {
25130
+ this.connecting = new Promise((resolve12, reject) => {
24536
25131
  const url = toWebSocketUrl(this.config.url, this.config.token);
24537
25132
  const parsed = new URL(url);
24538
25133
  parsed.searchParams.set("affinity", this.affinity);
@@ -24554,7 +25149,7 @@ class PersistentRelaySession {
24554
25149
  if (message.type === "ready") {
24555
25150
  this.timers.clearTimeout(timeout);
24556
25151
  this.serverState = message.state;
24557
- resolve10();
25152
+ resolve12();
24558
25153
  return;
24559
25154
  }
24560
25155
  this.handleMessage(message);
@@ -24606,15 +25201,15 @@ class PersistentRelaySession {
24606
25201
  const sentAt = perfNowMs();
24607
25202
  let resolveDone;
24608
25203
  let rejectDone;
24609
- const done = new Promise((resolve10, reject) => {
24610
- resolveDone = resolve10;
25204
+ const done = new Promise((resolve12, reject) => {
25205
+ resolveDone = resolve12;
24611
25206
  rejectDone = reject;
24612
25207
  });
24613
- const response = new Promise((resolve10, reject) => {
25208
+ const response = new Promise((resolve12, reject) => {
24614
25209
  const pending = {
24615
25210
  payload,
24616
25211
  bodyText,
24617
- resolve: resolve10,
25212
+ resolve: resolve12,
24618
25213
  reject,
24619
25214
  streamDone: false,
24620
25215
  accepted: false,
@@ -25938,7 +26533,7 @@ function createNativeAccountRuntime(options) {
25938
26533
  const { mode, paths: paths2, store: store2 } = await selectedStorage();
25939
26534
  for (let attempt = 0;attempt < 4; attempt++) {
25940
26535
  if (attempt)
25941
- await new Promise((resolve10) => setTimeout(resolve10, 10));
26536
+ await new Promise((resolve12) => setTimeout(resolve12, 10));
25942
26537
  const settings = await store2.readSettings();
25943
26538
  if (settings.status !== "ready")
25944
26539
  throw new NativeRuntimeError("publication-refused");
@@ -26648,7 +27243,7 @@ function relayGeneration(input) {
26648
27243
  // src/native-host-auth-write.ts
26649
27244
  import { randomUUID as randomUUID16 } from "node:crypto";
26650
27245
  import { lstat as lstat7, open as open9, rename as rename13, unlink as unlink6 } from "node:fs/promises";
26651
- import { dirname as dirname14, isAbsolute as isAbsolute5, join as join15 } from "node:path";
27246
+ import { dirname as dirname14, isAbsolute as isAbsolute5, join as join16 } from "node:path";
26652
27247
  class NativeHostAuthWriteError extends Error {
26653
27248
  code;
26654
27249
  effect;
@@ -26709,7 +27304,7 @@ async function writeNativeHostAuth(input, hooks = {}) {
26709
27304
  const removingFile = host === "pi" && Object.keys(next).length === 0;
26710
27305
  const outcome = Object.freeze(host === "pi" ? { status: "removed", file: removingFile ? "unlinked" : "replaced" } : { status: snapshot.data === undefined ? "created" : "replaced" });
26711
27306
  if (!removingFile) {
26712
- stage = join15(dirname14(authPath), `.native-host-auth-write.${randomUUID16()}.tmp`);
27307
+ stage = join16(dirname14(authPath), `.native-host-auth-write.${randomUUID16()}.tmp`);
26713
27308
  const bytes = `${JSON.stringify(next, null, 2)}
26714
27309
  `;
26715
27310
  const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
@@ -27584,7 +28179,7 @@ class NativeCustodyActivationError extends Error {
27584
28179
  function refuse4(code) {
27585
28180
  throw new NativeCustodyActivationError(code);
27586
28181
  }
27587
- function isRecord14(value) {
28182
+ function isRecord13(value) {
27588
28183
  return value !== null && typeof value === "object" && !Array.isArray(value);
27589
28184
  }
27590
28185
  function sameJson(left, right) {
@@ -27669,7 +28264,7 @@ var ACCOUNT_RUNTIME_FIELDS = [
27669
28264
  "quotaErrorGeneration"
27670
28265
  ];
27671
28266
  function vaultSettings(settings, primary) {
27672
- const custody = isRecord14(settings.claustrum) ? settings.claustrum : {};
28267
+ const custody = isRecord13(settings.claustrum) ? settings.claustrum : {};
27673
28268
  return {
27674
28269
  ...settings,
27675
28270
  claustrum: {
@@ -27779,7 +28374,7 @@ async function preparePlan(options, journal, store) {
27779
28374
  const main = pool.settings.mainAccountId;
27780
28375
  if (typeof main !== "string" || !main)
27781
28376
  refuse4("invalid-state");
27782
- const custody = isRecord14(pool.settings.claustrum) ? pool.settings.claustrum : {};
28377
+ const custody = isRecord13(pool.settings.claustrum) ? pool.settings.claustrum : {};
27783
28378
  const host = await readHostEntry(options.host, journal.hostAuthPath);
27784
28379
  const hostAuth = {
27785
28380
  source: host.digest,
@@ -27810,7 +28405,7 @@ async function preparePlan(options, journal, store) {
27810
28405
  let roster;
27811
28406
  let targetSettings;
27812
28407
  if (custody.mode === "claustrum") {
27813
- const pin = isRecord14(custody.primaryAccount) ? custody.primaryAccount : {};
28408
+ const pin = isRecord13(custody.primaryAccount) ? custody.primaryAccount : {};
27814
28409
  if (oauth.length > 0 || pin.credentialId !== primary.credentialId || pin.accountId !== primary.accountIdentity)
27815
28410
  refuse4("primary-mismatch");
27816
28411
  if (!existing)
@@ -27861,7 +28456,7 @@ async function preparePlan(options, journal, store) {
27861
28456
  } catch (error) {
27862
28457
  if (error instanceof NativeCustodyActivationError)
27863
28458
  throw error;
27864
- return refuse4(isRecord14(error) && error.code === "unenrolled-local-row" ? "unenrolled-local-row" : "roster-conflict");
28459
+ return refuse4(isRecord13(error) && error.code === "unenrolled-local-row" ? "unenrolled-local-row" : "roster-conflict");
27865
28460
  }
27866
28461
  roster = existing ?? rosterProjection(seed);
27867
28462
  targetSettings = vaultSettings(pool.settings, primary);
@@ -28013,7 +28608,7 @@ async function runNativeCustodyActivation(options, hooks = {}) {
28013
28608
  if (settings.status !== "ready")
28014
28609
  refuse4("invalid-state");
28015
28610
  const custody = settings.settings.claustrum;
28016
- if (isRecord14(custody) && custody.mode === "claustrum")
28611
+ if (isRecord13(custody) && custody.mode === "claustrum")
28017
28612
  return { status: "already-vault", journal };
28018
28613
  }
28019
28614
  if (journal.activation?.kind === "activation" && journal.activation.phase === "committed")
@@ -28234,8 +28829,8 @@ async function runNativeCustodyActivation(options, hooks = {}) {
28234
28829
  }
28235
28830
  async function commitMode(paths, routingPath, plan, context) {
28236
28831
  let openGate = () => {};
28237
- const gate = new Promise((resolve10) => {
28238
- openGate = resolve10;
28832
+ const gate = new Promise((resolve12) => {
28833
+ openGate = resolve12;
28239
28834
  });
28240
28835
  let leases;
28241
28836
  let scope;
@@ -28864,7 +29459,7 @@ function readPlain(value, allowed) {
28864
29459
  const prototype = Object.getPrototypeOf(value);
28865
29460
  if (prototype !== Object.prototype && prototype !== null)
28866
29461
  return "malformed";
28867
- const fields = new Map;
29462
+ const fields2 = new Map;
28868
29463
  let unknownKey = false;
28869
29464
  for (const key of Reflect.ownKeys(value)) {
28870
29465
  if (typeof key !== "string")
@@ -28875,9 +29470,9 @@ function readPlain(value, allowed) {
28875
29470
  if (!allowed.includes(key))
28876
29471
  unknownKey = true;
28877
29472
  else
28878
- fields.set(key, descriptor.value);
29473
+ fields2.set(key, descriptor.value);
28879
29474
  }
28880
- return unknownKey ? "unknown-key" : fields;
29475
+ return unknownKey ? "unknown-key" : fields2;
28881
29476
  }
28882
29477
  function readArray(value) {
28883
29478
  if (value === null || typeof value !== "object")
@@ -28931,13 +29526,13 @@ function readKillswitchEntries(value) {
28931
29526
  return;
28932
29527
  const entries = [];
28933
29528
  for (const item of items2) {
28934
- const fields = readPlain(item, ENTRY_KEYS);
28935
- if (!(fields instanceof Map))
29529
+ const fields2 = readPlain(item, ENTRY_KEYS);
29530
+ if (!(fields2 instanceof Map))
28936
29531
  return;
28937
- const account = fields.get("account");
28938
- const fh = fields.get("fh");
28939
- const sd = fields.get("sd");
28940
- const scoped = fields.get("scoped");
29532
+ const account = fields2.get("account");
29533
+ const fh = fields2.get("fh");
29534
+ const sd = fields2.get("sd");
29535
+ const scoped = fields2.get("scoped");
28941
29536
  if (!isKillswitchAccount(account))
28942
29537
  return;
28943
29538
  if (!isDigitInteger(fh) || !isDigitInteger(sd))
@@ -29021,14 +29616,14 @@ var CONTEXT_KEYS = [
29021
29616
  "signal"
29022
29617
  ];
29023
29618
  function readContext(value) {
29024
- const fields = readPlain(value, CONTEXT_KEYS);
29025
- if (!(fields instanceof Map))
29619
+ const fields2 = readPlain(value, CONTEXT_KEYS);
29620
+ if (!(fields2 instanceof Map))
29026
29621
  return;
29027
- const interactive = fields.get("interactive");
29028
- const custodyMode = fields.get("custodyMode");
29029
- const confirmed = fields.get("confirmed");
29030
- const sessionId = fields.get("sessionId");
29031
- const rawSignal = fields.get("signal");
29622
+ const interactive = fields2.get("interactive");
29623
+ const custodyMode = fields2.get("custodyMode");
29624
+ const confirmed = fields2.get("confirmed");
29625
+ const sessionId = fields2.get("sessionId");
29626
+ const rawSignal = fields2.get("signal");
29032
29627
  if (typeof interactive !== "boolean")
29033
29628
  return;
29034
29629
  if (custodyMode !== "local" && custodyMode !== "claustrum")
@@ -29128,9 +29723,9 @@ var DISCONNECT_RESULTS = new Set([
29128
29723
  "conflict"
29129
29724
  ]);
29130
29725
  function readOutcome(action, outcome) {
29131
- const fields = readPlain(outcome, ["ok", "text"]);
29132
- const ok = fields instanceof Map ? fields.get("ok") : undefined;
29133
- const text5 = fields instanceof Map ? fields.get("text") : undefined;
29726
+ const fields2 = readPlain(outcome, ["ok", "text"]);
29727
+ const ok = fields2 instanceof Map ? fields2.get("ok") : undefined;
29728
+ const text5 = fields2 instanceof Map ? fields2.get("text") : undefined;
29134
29729
  if (typeof ok !== "boolean" || typeof text5 !== "string")
29135
29730
  return Object.freeze({ status: "failed", action, code: "invalid-outcome" });
29136
29731
  return Object.freeze({ status: "executed", action, ok, text: text5 });
@@ -29173,12 +29768,12 @@ function disconnectFailureCode(error) {
29173
29768
  return "execution-failed";
29174
29769
  }
29175
29770
  function createNativeMenuExecutor(options) {
29176
- const fields = readPlain(options, ["host", "dispatch", "disconnectVault"]);
29177
- if (!(fields instanceof Map))
29771
+ const fields2 = readPlain(options, ["host", "dispatch", "disconnectVault"]);
29772
+ if (!(fields2 instanceof Map))
29178
29773
  throw new TypeError("Native menu executor options are invalid");
29179
- const host = fields.get("host");
29180
- const dispatch = fields.get("dispatch");
29181
- const disconnectVault = fields.get("disconnectVault");
29774
+ const host = fields2.get("host");
29775
+ const dispatch = fields2.get("dispatch");
29776
+ const disconnectVault = fields2.get("disconnectVault");
29182
29777
  if (!HOSTS2.has(host))
29183
29778
  throw invalidOption2("host");
29184
29779
  if (typeof dispatch !== "function" || utilTypes7.isProxy(dispatch))
@@ -29634,8 +30229,8 @@ function showSignInLink(text5, scrub) {
29634
30229
  const links = new Set((text5.match(/https:\/\/\S+/g) ?? []).filter(isSignInLink));
29635
30230
  const [link2] = links;
29636
30231
  if (links.size !== 1 || link2 === undefined)
29637
- return scrub(text5);
29638
- return text5.split(link2).map(scrub).join(link2);
30232
+ return { text: scrub(text5) };
30233
+ return { text: text5.split(link2).map(scrub).join(link2), link: link2 };
29639
30234
  }
29640
30235
  var DISCONNECT_OUTCOMES = {
29641
30236
  disconnected: {
@@ -29834,12 +30429,16 @@ function createNativeUi(options) {
29834
30429
  safe = safe.split(value).join("[REDACTED]");
29835
30430
  return redact2(safe);
29836
30431
  };
29837
- const finish = async (result2, signInLink = false) => ({
29838
- command: "claude",
29839
- ...result2,
29840
- text: signInLink ? showSignInLink(result2.text, scrub) : scrub(result2.text),
29841
- menu: await model(invocation, scrub, readable)
29842
- });
30432
+ const finish = async (result2, signInLink = false) => {
30433
+ const shown = signInLink ? showSignInLink(result2.text, scrub) : { text: scrub(result2.text) };
30434
+ return {
30435
+ command: "claude",
30436
+ ...result2,
30437
+ text: shown.text,
30438
+ ...shown.link !== undefined ? { authorizationUrl: shown.link } : {},
30439
+ menu: await model(invocation, scrub, readable)
30440
+ };
30441
+ };
29843
30442
  if (request?.command !== "claude" || !action || request.itemId !== undefined || request.sessionId !== undefined && request.sessionId !== invocation.sessionId) {
29844
30443
  return finish({
29845
30444
  ok: false,
@@ -29933,11 +30532,11 @@ async function refreshForRequest(runtime2, ready) {
29933
30532
  break;
29934
30533
  if (combined.aborted)
29935
30534
  break;
29936
- await new Promise((resolve10) => {
30535
+ await new Promise((resolve12) => {
29937
30536
  const finish = () => {
29938
30537
  clearTimeout(pause2);
29939
30538
  combined.removeEventListener("abort", finish);
29940
- resolve10();
30539
+ resolve12();
29941
30540
  };
29942
30541
  const pause2 = setTimeout(finish, 25);
29943
30542
  combined.addEventListener("abort", finish, { once: true });
@@ -29953,16 +30552,16 @@ async function refreshForRequest(runtime2, ready) {
29953
30552
  function waitForRequest(pending, signal) {
29954
30553
  if (!signal)
29955
30554
  return pending;
29956
- return new Promise((resolve10, reject) => {
30555
+ return new Promise((resolve12, reject) => {
29957
30556
  const abort = () => reject(signal.reason);
29958
30557
  signal.addEventListener("abort", abort, { once: true });
29959
- pending.then(resolve10, reject).finally(() => signal.removeEventListener("abort", abort));
30558
+ pending.then(resolve12, reject).finally(() => signal.removeEventListener("abort", abort));
29960
30559
  if (signal.aborted)
29961
30560
  abort();
29962
30561
  });
29963
30562
  }
29964
30563
  // src/native-vault-connection.ts
29965
- import { dirname as dirname17, join as join16, resolve as resolve11 } from "node:path";
30564
+ import { dirname as dirname17, join as join17, resolve as resolve13 } from "node:path";
29966
30565
  // ../../node_modules/@cortexkit/common-auth/dist/opencode2/integration.js
29967
30566
  var PLACEHOLDER_PREFIX = "common-auth-placeholder";
29968
30567
  var PLACEHOLDER_LIFETIME_MS = 365 * 24 * 60 * 60 * 1000;
@@ -29973,7 +30572,7 @@ function placeholderSecret(integrationID) {
29973
30572
  import { createHash as createHash20 } from "node:crypto";
29974
30573
  import { constants as constants4 } from "node:fs";
29975
30574
  import { lstat as lstat9, mkdir as mkdir13, open as open10, unlink as unlink8 } from "node:fs/promises";
29976
- import { dirname as dirname16, resolve as resolve10 } from "node:path";
30575
+ import { dirname as dirname16, resolve as resolve12 } from "node:path";
29977
30576
  import { setTimeout as sleep } from "node:timers/promises";
29978
30577
 
29979
30578
  // ../../node_modules/@cortexkit/common-auth/dist/pi-slot/lock.js
@@ -30066,7 +30665,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
30066
30665
  if (!released && lastUpdate + RENEWAL_STALE < Date.now())
30067
30666
  compromise();
30068
30667
  }
30069
- function schedule(delay3 = UPDATE) {
30668
+ function schedule2(delay3 = UPDATE) {
30070
30669
  if (released)
30071
30670
  return;
30072
30671
  timer = setTimeout(() => {
@@ -30080,7 +30679,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
30080
30679
  if (errorCode2(error) === "ENOENT" || lastUpdate + RENEWAL_STALE < Date.now())
30081
30680
  compromise();
30082
30681
  else
30083
- schedule(1000);
30682
+ schedule2(1000);
30084
30683
  }
30085
30684
  async function update() {
30086
30685
  assertFresh();
@@ -30113,14 +30712,14 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
30113
30712
  mtime = next.getTime();
30114
30713
  lastUpdate = Date.now();
30115
30714
  active.set(path2, { ...identity2, mtime, renewedAt: lastUpdate });
30116
- schedule();
30715
+ schedule2();
30117
30716
  }
30118
30717
  onRenew?.(async () => {
30119
30718
  if (timer)
30120
30719
  clearTimeout(timer);
30121
30720
  await update();
30122
30721
  });
30123
- schedule();
30722
+ schedule2();
30124
30723
  return {
30125
30724
  assertFresh,
30126
30725
  async release() {
@@ -30361,8 +30960,8 @@ function createPiSlot(options, onStep, hooks) {
30361
30960
  if (!provider || !options.authPath || !options.stashPath || !placeholderKey || placeholderKey.startsWith("!") || placeholderKey.includes("$") || !Number.isFinite(timeout) || timeout < 0) {
30362
30961
  throw new PiSlotError("invalid-options");
30363
30962
  }
30364
- const authPath = resolve10(options.authPath);
30365
- const stashPath = resolve10(options.stashPath);
30963
+ const authPath = resolve12(options.authPath);
30964
+ const stashPath = resolve12(options.stashPath);
30366
30965
  if (authPath === stashPath || stashPath === `${authPath}.lock`) {
30367
30966
  throw new PiSlotError("invalid-options");
30368
30967
  }
@@ -30500,8 +31099,8 @@ function createPiSlot(options, onStep, hooks) {
30500
31099
  // src/native-vault-connection.ts
30501
31100
  function nativePiAuthSlotPaths(options) {
30502
31101
  return {
30503
- authPath: resolve11(options.authPath),
30504
- stashPath: join16(dirname17(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
31102
+ authPath: resolve13(options.authPath),
31103
+ stashPath: join17(dirname17(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
30505
31104
  provider: "anthropic",
30506
31105
  placeholderKey: placeholderSecret("anthropic")
30507
31106
  };
@@ -30522,8 +31121,8 @@ async function disconnectNativeVaultForHost(options) {
30522
31121
  import { createHash as createHash21 } from "node:crypto";
30523
31122
  import { realpathSync as realpathSync2 } from "node:fs";
30524
31123
  import { mkdir as mkdir14, readdir as readdir3, rm as rm8, stat as stat9, writeFile as writeFile5 } from "node:fs/promises";
30525
- import { tmpdir as tmpdir6 } from "node:os";
30526
- import { join as join17, resolve as resolve12 } from "node:path";
31124
+ import { tmpdir as tmpdir7 } from "node:os";
31125
+ import { join as join18, resolve as resolve14 } from "node:path";
30527
31126
  var CLAUDE_PRIME_COMMAND_NAME = "claude-prime";
30528
31127
  var PRIME_TICK_MS = 60000;
30529
31128
  var PRIME_DUE_OFFSET_MS = 60000;
@@ -30711,10 +31310,10 @@ function buildPrimeRequestBody() {
30711
31310
  return JSON.parse(JSON.stringify(PRIME_REQUEST_BODY));
30712
31311
  }
30713
31312
  function defaultMarkerDir() {
30714
- return join17(tmpdir6(), "opencode-anthropic-auth", "prime");
31313
+ return join18(tmpdir7(), "opencode-anthropic-auth", "prime");
30715
31314
  }
30716
31315
  function primeStorageFingerprint(storagePath) {
30717
- const absolutePath = resolve12(storagePath);
31316
+ const absolutePath = resolve14(storagePath);
30718
31317
  let canonicalPath2;
30719
31318
  try {
30720
31319
  canonicalPath2 = realpathSync2(absolutePath);
@@ -30726,19 +31325,19 @@ function primeStorageFingerprint(storagePath) {
30726
31325
  return createHash21("sha256").update(canonicalPath2).digest("hex").slice(0, 12);
30727
31326
  }
30728
31327
  function primeMarkerNamespaceDir(markerDir, storagePath) {
30729
- return join17(markerDir, primeStorageFingerprint(storagePath));
31328
+ return join18(markerDir, primeStorageFingerprint(storagePath));
30730
31329
  }
30731
31330
  function primeAccountMarkerDir(markerDir, storagePath, accountFingerprint) {
30732
31331
  if (!/^[a-f0-9]{12,}$/i.test(accountFingerprint)) {
30733
31332
  throw new Error("Prime account fingerprint must be a hexadecimal digest");
30734
31333
  }
30735
- return join17(primeMarkerNamespaceDir(markerDir, storagePath), accountFingerprint.toLowerCase().slice(0, 12));
31334
+ return join18(primeMarkerNamespaceDir(markerDir, storagePath), accountFingerprint.toLowerCase().slice(0, 12));
30736
31335
  }
30737
31336
  function primeMarkerPath(markerDir, accountId2, resetsAtEpochMs) {
30738
- return join17(markerDir, `${encodeURIComponent(accountId2)}-${resetsAtEpochMs}`);
31337
+ return join18(markerDir, `${encodeURIComponent(accountId2)}-${resetsAtEpochMs}`);
30739
31338
  }
30740
31339
  function primeBootstrapMarkerPath(markerDir, accountId2) {
30741
- return join17(markerDir, `${encodeURIComponent(accountId2)}-bootstrap`);
31340
+ return join18(markerDir, `${encodeURIComponent(accountId2)}-bootstrap`);
30742
31341
  }
30743
31342
  function primeAccountLabel(id2, fallback) {
30744
31343
  if (id2 === "main")
@@ -31162,7 +31761,7 @@ class PrimeManager {
31162
31761
  let swept = 0;
31163
31762
  for (const entry2 of entries) {
31164
31763
  try {
31165
- const path2 = join17(dir, entry2);
31764
+ const path2 = join18(dir, entry2);
31166
31765
  const s = await stat9(path2);
31167
31766
  if (s.isDirectory()) {
31168
31767
  swept += await this.sweepMarkerDirectory(path2, now);
@@ -31196,12 +31795,12 @@ import {
31196
31795
  stat as stat10,
31197
31796
  writeFile as writeFile6
31198
31797
  } from "node:fs/promises";
31199
- import { tmpdir as tmpdir7 } from "node:os";
31200
- import { join as join18 } from "node:path";
31798
+ import { tmpdir as tmpdir8 } from "node:os";
31799
+ import { join as join19 } from "node:path";
31201
31800
  var QUOTA_HEADER_FEED_SCHEMA_VERSION = 3;
31202
31801
  var QUOTA_HEADER_FEED_LEASE_MS = 180000;
31203
31802
  function getDefaultQuotaHeaderFeedDirectory() {
31204
- return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ?? join18(tmpdir7(), "opencode-anthropic-auth", "quota-header-feed");
31803
+ return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ?? join19(tmpdir8(), "opencode-anthropic-auth", "quota-header-feed");
31205
31804
  }
31206
31805
  function configuredAnthropicOAuthAccountCount(input) {
31207
31806
  const fallbackCount = input.storage?.accounts.filter(isOAuthAccount).length ?? 0;
@@ -31360,7 +31959,7 @@ class QuotaHeaderFeedRegistry {
31360
31959
  constructor(options = {}) {
31361
31960
  this.options = options;
31362
31961
  const instanceId = options.instanceId ?? `${process.pid}-${randomUUID17()}`;
31363
- this.filePath = join18(options.directory ?? getDefaultQuotaHeaderFeedDirectory(), `${instanceId}.json`);
31962
+ this.filePath = join19(options.directory ?? getDefaultQuotaHeaderFeedDirectory(), `${instanceId}.json`);
31364
31963
  }
31365
31964
  publish(entry2) {
31366
31965
  const { accountKey, quota: quota2 } = entry2;
@@ -31421,7 +32020,7 @@ class QuotaHeaderFeedRegistry {
31421
32020
  return;
31422
32021
  }
31423
32022
  await Promise.all(names2.filter((name) => /^\d+-[0-9a-f-]+\.json$/i.test(name)).map(async (name) => {
31424
- const path2 = join18(directory, name);
32023
+ const path2 = join19(directory, name);
31425
32024
  if (path2 === this.filePath)
31426
32025
  return;
31427
32026
  try {
@@ -31450,7 +32049,7 @@ class QuotaHeaderFeedRegistry {
31450
32049
  const newest = new Map;
31451
32050
  await Promise.all(names2.map(async (name) => {
31452
32051
  try {
31453
- const record9 = JSON.parse(await readFile10(join18(directory, name), "utf8"));
32052
+ const record9 = JSON.parse(await readFile10(join19(directory, name), "utf8"));
31454
32053
  if (record9.version !== QUOTA_HEADER_FEED_SCHEMA_VERSION || !record9.entries || typeof record9.entries !== "object")
31455
32054
  return;
31456
32055
  for (const [accountKey, candidate] of Object.entries(record9.entries)) {
@@ -31631,7 +32230,7 @@ function buildClaudeQuotaSummary(input) {
31631
32230
  }
31632
32231
  // src/request-gzip.ts
31633
32232
  import { mkdir as mkdir16, readFile as readFile11, rename as rename15, rm as rm10, writeFile as writeFile7 } from "node:fs/promises";
31634
- import { basename as basename8, dirname as dirname18, join as join19 } from "node:path";
32233
+ import { basename as basename8, dirname as dirname18, join as join20 } from "node:path";
31635
32234
  import { promisify } from "node:util";
31636
32235
  import { gzip } from "node:zlib";
31637
32236
  var gzipAsync = promisify(gzip);
@@ -31777,7 +32376,7 @@ function getRequestGzipLatch(path2) {
31777
32376
  function getRequestGzipLatchPath(accountStoragePath) {
31778
32377
  const name = basename8(accountStoragePath);
31779
32378
  const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
31780
- return join19(dirname18(accountStoragePath), `${stem}-request-gzip.json`);
32379
+ return join20(dirname18(accountStoragePath), `${stem}-request-gzip.json`);
31781
32380
  }
31782
32381
  async function decideRequestGzip(options) {
31783
32382
  if (!CLAUDE_CODE_GZIPS_REQUEST_BODIES)
@@ -31922,7 +32521,7 @@ var REPORTED_BLOCK_TYPES = new Set([
31922
32521
  "document"
31923
32522
  ]);
31924
32523
  var EMPTY_TEXT_BLOCK_KEYS = new Set(["type", "text", "cache_control"]);
31925
- function isRecord15(value) {
32524
+ function isRecord14(value) {
31926
32525
  return typeof value === "object" && value !== null && !Array.isArray(value);
31927
32526
  }
31928
32527
  function isProvablyEmptyContent(content) {
@@ -31930,14 +32529,14 @@ function isProvablyEmptyContent(content) {
31930
32529
  return content.trim() === "";
31931
32530
  if (!Array.isArray(content))
31932
32531
  return false;
31933
- return content.every((block) => isRecord15(block) && block.type === "text" && typeof block.text === "string" && block.text.trim() === "" && Object.keys(block).every((key) => EMPTY_TEXT_BLOCK_KEYS.has(key)));
32532
+ return content.every((block) => isRecord14(block) && block.type === "text" && typeof block.text === "string" && block.text.trim() === "" && Object.keys(block).every((key) => EMPTY_TEXT_BLOCK_KEYS.has(key)));
31934
32533
  }
31935
32534
  function describeContent(content) {
31936
32535
  if (Array.isArray(content)) {
31937
32536
  return {
31938
32537
  contentShape: "array",
31939
32538
  contentBlockCount: content.length,
31940
- contentBlockTypes: content.map((block) => isRecord15(block) && typeof block.type === "string" && REPORTED_BLOCK_TYPES.has(block.type) ? block.type : "other")
32539
+ contentBlockTypes: content.map((block) => isRecord14(block) && typeof block.type === "string" && REPORTED_BLOCK_TYPES.has(block.type) ? block.type : "other")
31941
32540
  };
31942
32541
  }
31943
32542
  if (typeof content === "string")
@@ -31950,7 +32549,7 @@ function assertNoMeaningfulTrailingAssistant(messages) {
31950
32549
  let end = messages.length;
31951
32550
  while (end > 0) {
31952
32551
  const last = messages[end - 1];
31953
- if (!isRecord15(last) || last.role !== "assistant")
32552
+ if (!isRecord14(last) || last.role !== "assistant")
31954
32553
  break;
31955
32554
  if (!isProvablyEmptyContent(last.content)) {
31956
32555
  throw new TrailingAssistantHistoryError({
@@ -32093,11 +32692,11 @@ function executeLaneStartCommand(input) {
32093
32692
  }
32094
32693
  // src/thinking-binding.ts
32095
32694
  var THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
32096
- function isRecord16(value) {
32695
+ function isRecord15(value) {
32097
32696
  return typeof value === "object" && value !== null && !Array.isArray(value);
32098
32697
  }
32099
32698
  function isReplayableThinkingBlock(block) {
32100
- if (!isRecord16(block))
32699
+ if (!isRecord15(block))
32101
32700
  return false;
32102
32701
  if (block.type === "thinking") {
32103
32702
  return typeof block.signature === "string" && block.signature.length > 0;
@@ -32115,7 +32714,7 @@ function hasReplayableThinkingBlocks(body) {
32115
32714
  if (!Array.isArray(body.messages))
32116
32715
  return false;
32117
32716
  return body.messages.some((message) => {
32118
- if (!isRecord16(message) || message.role !== "assistant")
32717
+ if (!isRecord15(message) || message.role !== "assistant")
32119
32718
  return false;
32120
32719
  return Array.isArray(message.content) && message.content.some(isReplayableThinkingBlock);
32121
32720
  });
@@ -32123,11 +32722,11 @@ function hasReplayableThinkingBlocks(body) {
32123
32722
  function applyThinkingBindingControls(body, behavior = "account-default") {
32124
32723
  if (behavior === "account-default")
32125
32724
  return false;
32126
- if (!isClaudeFable51Model(body.model) && !isClaudeOpus55Model(body.model) && !isClaudeSonnet55Model(body.model) && !isClaudeHaiku55Model(body.model))
32725
+ if (!resolveClaudeModelCapabilities(body.model)?.thinkingBindingControls)
32127
32726
  return false;
32128
32727
  if (!hasReplayableThinkingBlocks(body))
32129
32728
  return false;
32130
- if (!isRecord16(body.thinking) || body.thinking.type !== "adaptive")
32729
+ if (!isRecord15(body.thinking) || body.thinking.type !== "adaptive")
32131
32730
  return false;
32132
32731
  body.thinking.block_binding = {
32133
32732
  prefix_mismatch_behavior: behavior
@@ -32135,13 +32734,68 @@ function applyThinkingBindingControls(body, behavior = "account-default") {
32135
32734
  return true;
32136
32735
  }
32137
32736
  function hasThinkingBindingControls(body) {
32138
- if (!isRecord16(body.thinking))
32737
+ if (!isRecord15(body.thinking))
32139
32738
  return false;
32140
- if (!isRecord16(body.thinking.block_binding))
32739
+ if (!isRecord15(body.thinking.block_binding))
32141
32740
  return false;
32142
32741
  const behavior = body.thinking.block_binding.prefix_mismatch_behavior;
32143
32742
  return behavior === "error" || behavior === "drop_block";
32144
32743
  }
32744
+ // src/turn-end-note.ts
32745
+ var TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
32746
+ var TURN_END_NOTE_CONTENT = "Your reply above has already reached the user. The tool call after it was housekeeping and changed nothing they need to know. Do not repeat, summarize or rewrite that reply. If no new work remains, end the turn without restating anything.";
32747
+ var DEFAULT_TOOLS = ["board", "ctx_reduce"];
32748
+ function isRecord16(value) {
32749
+ return value !== null && typeof value === "object" && !Array.isArray(value);
32750
+ }
32751
+ function supportsTurnEndNote(model) {
32752
+ return resolveClaudeModelCapabilities(model)?.turnEndNote === true;
32753
+ }
32754
+ function applyTurnEndNotes(body, options = {}) {
32755
+ if (!supportsTurnEndNote(body.model) || !Array.isArray(body.messages))
32756
+ return 0;
32757
+ const allowed = new Set((options.tools ?? DEFAULT_TOOLS).map((name) => options.mapToolName?.(name) ?? name));
32758
+ if (!allowed.size)
32759
+ return 0;
32760
+ const messages = body.messages;
32761
+ const rewritten = [];
32762
+ let inserted = 0;
32763
+ for (let index = 0;index < messages.length; index++) {
32764
+ const results = messages[index];
32765
+ rewritten.push(results);
32766
+ let preceding = index - 1;
32767
+ while (preceding >= 0) {
32768
+ const control = messages[preceding];
32769
+ if (!isRecord16(control) || control.role !== "system" || !Array.isArray(control.content) || control.content.length !== 0 || !isRecord16(control.output_config))
32770
+ break;
32771
+ preceding--;
32772
+ }
32773
+ const assistant = messages[preceding];
32774
+ if (!isRecord16(assistant) || assistant.role !== "assistant" || !Array.isArray(assistant.content) || !isRecord16(results) || results.role !== "user" || !Array.isArray(results.content))
32775
+ continue;
32776
+ const visible = options.visibleText ? options.visibleText(assistant) : assistant.content.filter((block) => isRecord16(block) && block.type === "text" && typeof block.text === "string" && block.text.trim().length > 0).map((block) => block.text).join("");
32777
+ if (visible.length < TURN_END_NOTE_MIN_VISIBLE_CHARACTERS)
32778
+ continue;
32779
+ const calls = assistant.content.filter((block) => isRecord16(block) && block.type === "tool_use");
32780
+ if (!calls.length || !calls.every((call) => allowed.has(call.name)))
32781
+ continue;
32782
+ const resultIds = new Set(results.content.filter((block) => isRecord16(block) && block.type === "tool_result").map((block) => block.tool_use_id));
32783
+ if (!calls.every((call) => typeof call.id === "string" && resultIds.has(call.id)))
32784
+ continue;
32785
+ const next = messages[index + 1];
32786
+ if (isRecord16(next) && next.role === "user")
32787
+ continue;
32788
+ rewritten.push({
32789
+ role: "system",
32790
+ clear_at: "next_user_message",
32791
+ content: TURN_END_NOTE_CONTENT
32792
+ });
32793
+ inserted++;
32794
+ }
32795
+ if (inserted)
32796
+ body.messages = rewritten;
32797
+ return inserted;
32798
+ }
32145
32799
  export {
32146
32800
  writeNativeHostAuth,
32147
32801
  writeDumpFile,
@@ -32183,6 +32837,7 @@ export {
32183
32837
  resolveNativePoolPaths,
32184
32838
  resolveLocalRoutingDestination,
32185
32839
  resolveClaustrumConnectionPath,
32840
+ resolveClaudeModelCapabilities,
32186
32841
  resolveClaudeCodeIdentity,
32187
32842
  resolveClaudeCodeAccountIdentity,
32188
32843
  resetFastModeState,
@@ -32227,6 +32882,7 @@ export {
32227
32882
  primeEligibilityReasonLabel,
32228
32883
  primeAccountMarkerDir,
32229
32884
  prepareNativeMigration,
32885
+ pinsEffortOnEveryRequest,
32230
32886
  parseSseFrame,
32231
32887
  parseRoutingCommandAction,
32232
32888
  parseRetryAfterHeader,
@@ -32352,6 +33008,8 @@ export {
32352
33008
  getDefaultCacheKeepRegistryDirectory,
32353
33009
  getClaustrumMode,
32354
33010
  getClaustrumEnrollmentPaths2 as getClaustrumEnrollmentPaths,
33011
+ getClaudeModelCatalogue,
33012
+ getClaudeModelCapabilities,
32355
33013
  getClaudeFableMythos5ReleaseDate,
32356
33014
  getClaudeCodeIdentityForVerifiedAccount,
32357
33015
  getClaudeCodeIdentity,
@@ -32496,6 +33154,7 @@ export {
32496
33154
  PrimeManager,
32497
33155
  PROFILE_TTL_MS,
32498
33156
  PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME,
33157
+ PRIVATE_FILES_UNAVAILABLE_MESSAGE,
32499
33158
  PRIME_TICK_MS,
32500
33159
  PRIME_REQUEST_BODY,
32501
33160
  PRIME_POST_FIRE_REFRESH_MS,
@@ -32511,6 +33170,7 @@ export {
32511
33170
  NativeTransientAccountError,
32512
33171
  NativeRuntimeError,
32513
33172
  NativeQuotaObservations,
33173
+ NativePrivateFilesUnavailableError,
32514
33174
  PiSlotError as NativePiAuthSlotError,
32515
33175
  NativeMigrationError,
32516
33176
  NativeHostAuthError,
@@ -32563,6 +33223,7 @@ export {
32563
33223
  CLAUDE_OPUS_5_5_ADAPTIVE_THINKING,
32564
33224
  CLAUDE_MYTHOS_5_MODEL_ID,
32565
33225
  CLAUDE_MYTHOS_5_1_MODEL_ID,
33226
+ CLAUDE_MODEL_CAPABILITIES,
32566
33227
  CLAUDE_LOGGING_COMMAND_NAME,
32567
33228
  CLAUDE_HAIKU_5_5_RELEASE_DATE,
32568
33229
  CLAUDE_HAIKU_5_5_PRICING,
@@ -32597,6 +33258,7 @@ export {
32597
33258
  CLAUDE_CODE_GZIPS_REQUEST_BODIES,
32598
33259
  CLAUDE_CODE_FULL_AGENT_BETAS,
32599
33260
  CLAUDE_CODE_ENTRYPOINT,
33261
+ CLAUDE_CODE_DEFAULT_BETAS,
32600
33262
  CLAUDE_CACHE_KEEP_COMMAND_NAME,
32601
33263
  CLAUDE_ACCOUNT_COMMAND_NAME,
32602
33264
  CCH_SALT,