@cortexkit/anthropic-auth-core 2.2.2 → 2.2.4

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) {
@@ -693,7 +718,7 @@ function acquireRefreshFileLock(options) {
693
718
  }
694
719
  async function acquireRefreshFileLockWithClock(options) {
695
720
  const lockPath = lockPathFor(options.path, options.name);
696
- const legacyOwnerPath = join(lockPath, "owner.json");
721
+ const legacyOwnerPath = join2(lockPath, "owner.json");
697
722
  const ownerId = randomUUID3();
698
723
  const now = options.now ?? Date.now;
699
724
  let renewTimer = null;
@@ -734,7 +759,7 @@ async function acquireRefreshFileLockWithClock(options) {
734
759
  let terminalIOError;
735
760
  let renewalInFlight = null;
736
761
  const evictPath = `${lockPath}.evicting`;
737
- const evictOwnerPath = join(evictPath, "owner.json");
762
+ const evictOwnerPath = join2(evictPath, "owner.json");
738
763
  const evictOwnerId = randomUUID3();
739
764
  const EVICT_TTL = 5000;
740
765
  const MAX_STEAL_ATTEMPTS = 8;
@@ -1298,7 +1323,9 @@ var ENROLLMENT_SCHEMA = 1;
1298
1323
  var ENROLLMENT_FILE_MAX_BYTES = 16 * 1024;
1299
1324
  var ENROLLMENT_LOCK_TTL_MS = 30000;
1300
1325
  var TOKEN_RE = /^[0-9a-f]{64}$/;
1326
+ var UNSUPPORTED_ENROLLMENT_CODE = "unknown_method";
1301
1327
  var TERMINAL_ENROLLMENT_CODES = new Set([
1328
+ UNSUPPORTED_ENROLLMENT_CODE,
1302
1329
  "invalid_params",
1303
1330
  "pending_exists",
1304
1331
  "not_found",
@@ -1328,7 +1355,7 @@ function getClaustrumEnrollmentPaths(tokenPath) {
1328
1355
  const extension = extname(tokenPath) || ".json";
1329
1356
  const stem = basename(tokenPath, extname(tokenPath));
1330
1357
  return {
1331
- statePath: join2(dirname4(tokenPath), `${stem}-state${extension}`),
1358
+ statePath: join3(dirname4(tokenPath), `${stem}-state${extension}`),
1332
1359
  tokenPath
1333
1360
  };
1334
1361
  }
@@ -1336,7 +1363,7 @@ function hostEnrollmentPaths(input) {
1336
1363
  const override = input.override?.trim();
1337
1364
  if (override && !isAbsolute(override) && !input.cwd)
1338
1365
  throw new ClaustrumConsumerError("invalid-state", "A relative Claustrum enrollment override needs a base directory");
1339
- 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`);
1340
1367
  return getClaustrumEnrollmentPaths(tokenPath);
1341
1368
  }
1342
1369
  function isRecord(value) {
@@ -1572,7 +1599,7 @@ async function writeStateAtomic(path, state, ancestorOptions = {}) {
1572
1599
  }
1573
1600
  if (windowsPrivateFiles)
1574
1601
  return writePrivateAtomic(path, bytes);
1575
- const temporary = join2(parent, `.${basename(path)}.${process.pid}.${randomUUID4()}.tmp`);
1602
+ const temporary = join3(parent, `.${basename(path)}.${process.pid}.${randomUUID4()}.tmp`);
1576
1603
  let descriptor;
1577
1604
  let created = false;
1578
1605
  try {
@@ -1801,6 +1828,18 @@ class ClaustrumEnrollmentManager {
1801
1828
  retryCode: refusal.code
1802
1829
  };
1803
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
+ }
1804
1843
  return this.#block(state, refusal.code);
1805
1844
  }
1806
1845
  }
@@ -2189,8 +2228,8 @@ function setupEnrollment(error) {
2189
2228
  // ../../node_modules/@cortexkit/common-auth/dist/setup/detect.js
2190
2229
  import { accessSync, constants, existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2191
2230
  import { mkdtemp, rm as rm3 } from "node:fs/promises";
2192
- import { tmpdir } from "node:os";
2193
- import { join as join3 } from "node:path";
2231
+ import { tmpdir as tmpdir2 } from "node:os";
2232
+ import { join as join4 } from "node:path";
2194
2233
  import { parse } from "jsonc-parser";
2195
2234
 
2196
2235
  // ../../node_modules/@cortexkit/common-auth/dist/setup/paths.js
@@ -2359,7 +2398,7 @@ async function detectHosts(plugin, io = {}) {
2359
2398
  return null;
2360
2399
  let root;
2361
2400
  try {
2362
- root = await mkdtemp(join3(tmpdir(), "common-auth-setup-version-"));
2401
+ root = await mkdtemp(join4(tmpdir2(), "common-auth-setup-version-"));
2363
2402
  const probeEnv = {
2364
2403
  ...env,
2365
2404
  HOME: root,
@@ -2427,6 +2466,8 @@ import { writeEnrollmentTokenFile as writeEnrollmentTokenFile2 } from "@cortexki
2427
2466
  var WINDOWS_CIM_TIMEOUT_MS = 45000;
2428
2467
  var HOSTS = new Set(["opencode", "litecode", "opencode2", "pi"]);
2429
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 }`;
2430
2471
  var PI_SCRIPT_PATTERN = /(?:^|[/\\])pi-coding-agent[/\\]dist[/\\](?:(?:bundle|bun)[/\\])?cli\.m?js$/i;
2431
2472
  function commandArguments(command) {
2432
2473
  return [...command.matchAll(/"([^"]*)"|(\S+)/g)].map((match) => match[1] ?? match[2] ?? "");
@@ -2569,6 +2610,29 @@ async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2569
2610
  }
2570
2611
  };
2571
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
+ }
2572
2636
  const result = await inspect(windows ? "tasklist" : "ps", windows ? "tasklist.exe" : "ps", windows ? ["/fo", "csv", "/nh"] : ["-eo", "pid,command"]);
2573
2637
  if (result.exitCode !== 0)
2574
2638
  throw new ProcessInspectionError(inspection);
@@ -2638,7 +2702,11 @@ function createProcessFence(runner = defaultCommandRunner, options = {}) {
2638
2702
  const isHost = (entry) => entry.pid !== selfPid && hostName(entry.command) !== null;
2639
2703
  return {
2640
2704
  async listRunningHosts(env) {
2641
- return (await listSetupProcesses(runner, { ...options, env })).filter(isHost);
2705
+ return (await listSetupProcesses(runner, {
2706
+ ...options,
2707
+ env,
2708
+ hostImagesOnly: true
2709
+ })).filter(isHost);
2642
2710
  },
2643
2711
  async previewRunningHosts(env) {
2644
2712
  const processes = await listSetupProcesses(runner, {
@@ -2662,8 +2730,27 @@ async function assertHostsStopped(fence, env) {
2662
2730
 
2663
2731
  // ../../node_modules/@cortexkit/common-auth/dist/setup/enroll.js
2664
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
+ }
2665
2740
 
2666
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}`;
2667
2754
  }
2668
2755
  async function connectSetupHost(plugin, host, io, terminal, fence) {
2669
2756
  const { name, paths: input } = plugin.vault.hosts[host];
@@ -2673,54 +2760,89 @@ async function connectSetupHost(plugin, host, io, terminal, fence) {
2673
2760
  connectionFile: plugin.vault.connectionFile,
2674
2761
  handshakeTimeoutMs: 2000
2675
2762
  }).catch(() => {
2676
- 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" });
2677
2764
  });
2765
+ const now = io.now ?? (() => performance.now());
2766
+ const wait = io.wait ?? delay;
2678
2767
  try {
2679
2768
  const manager = new ClaustrumEnrollmentManager({
2680
2769
  proposedName: name,
2681
2770
  paths,
2682
- client: {
2683
- enrollPropose: async (input2) => {
2684
- await fence();
2685
- return client.enrollPropose(input2);
2686
- },
2687
- enrollPoll: async (input2) => {
2688
- await fence();
2689
- return client.enrollPoll(input2);
2690
- }
2691
- },
2771
+ client,
2692
2772
  writeTokenFile: async (path, file) => {
2693
2773
  await fence();
2694
2774
  await writeEnrollmentTokenFile2(path, file);
2695
2775
  }
2696
2776
  });
2777
+ printLine(terminal, `Asking the vault to connect ${name}…`);
2778
+ const deadline = now() + ENROLLMENT_WAIT_MS;
2697
2779
  let printedRequest;
2698
- for (let tick = 0;tick < 300; tick++) {
2780
+ let lastCode;
2781
+ let reportedCode;
2782
+ let failedProposals = 0;
2783
+ for (;; ) {
2699
2784
  await fence();
2700
2785
  const status = await manager.reconcile();
2701
2786
  if (status.state === "approved") {
2702
2787
  printLine(terminal, `Connected ${host} to Claustrum.`);
2703
2788
  return;
2704
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
+ });
2705
2795
  if (status.state !== "pending" && status.state !== "busy")
2706
- throw new HostNotEnrolledError("Claustrum enrollment refused; inspect its status with ck before rerunning setup.");
2707
- if (status.state === "pending" && status.requestId && status.requestId !== printedRequest) {
2708
- if (!/^[a-zA-Z0-9_-]+$/.test(status.requestId))
2709
- throw new HostNotEnrolledError("Invalid enrollment request id.");
2710
- printedRequest = status.requestId;
2711
- printLine(terminal, "Waiting for approval. In another terminal, run:");
2712
- printLine(terminal, ` ck auth enroll approve --request-id ${status.requestId} --name ${name}`);
2713
- printLine(terminal, `Enrollment files: ${paths.statePath}, ${paths.tokenPath}`);
2714
- }
2715
- await (io.wait ?? delay)(1000);
2716
- }
2717
- 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 });
2718
2838
  } catch (error) {
2719
- if (error instanceof ProcessFenceViolationError || error instanceof ProcessInspectionError)
2839
+ if (error instanceof ProcessFenceViolationError || error instanceof ProcessInspectionError || error instanceof HostNotEnrolledError)
2720
2840
  throw error;
2721
- if (error instanceof HostNotEnrolledError)
2722
- throw new HostNotEnrolledError(ENROLLMENT_INCOMPLETE_MESSAGE);
2723
- 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
+ });
2724
2846
  } finally {
2725
2847
  client.close();
2726
2848
  }
@@ -2758,7 +2880,7 @@ import { applyEdits, createScanner, findNodeAtLocation, modify, parse as parse2,
2758
2880
  // ../../node_modules/@cortexkit/common-auth/dist/setup/config-write.js
2759
2881
  import { randomUUID as randomUUID5 } from "node:crypto";
2760
2882
  import { mkdir as mkdir4, open as open4, rename as rename5, stat as stat4, unlink as unlink3 } from "node:fs/promises";
2761
- 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";
2762
2884
  import { setTimeout as delay2 } from "node:timers/promises";
2763
2885
  async function writeHostConfigAtomic(file, content, options = {}) {
2764
2886
  const windows = (options.platform ?? process.platform) === "win32";
@@ -2773,7 +2895,7 @@ async function writeHostConfigAtomic(file, content, options = {}) {
2773
2895
  throw error;
2774
2896
  }
2775
2897
  }
2776
- const stage = join4(parent, `.${basename2(file)}.${(options.stageName ?? randomUUID5)()}.tmp`);
2898
+ const stage = join5(parent, `.${basename2(file)}.${(options.stageName ?? randomUUID5)()}.tmp`);
2777
2899
  let created = false;
2778
2900
  try {
2779
2901
  const handle = await open4(stage, "wx", mode ?? 438);
@@ -3141,13 +3263,13 @@ ${write.content}`);
3141
3263
  import { createHash as createHash2, randomUUID as randomUUID6 } from "node:crypto";
3142
3264
  import { mkdir as mkdir5, readFile as readFile5, rename as rename6, rm as rm4, stat as stat5, writeFile } from "node:fs/promises";
3143
3265
  import { homedir as homedir2 } from "node:os";
3144
- import { dirname as dirname6, join as join6 } from "node:path";
3266
+ import { dirname as dirname6, join as join7 } from "node:path";
3145
3267
 
3146
3268
  // src/claustrum.ts
3147
3269
  import { readdirSync, statSync as statSync2 } from "node:fs";
3148
3270
  import * as fs from "node:fs/promises";
3149
- import { tmpdir as tmpdir2, userInfo } from "node:os";
3150
- import { join as join5 } from "node:path";
3271
+ import { tmpdir as tmpdir3, userInfo } from "node:os";
3272
+ import { join as join6 } from "node:path";
3151
3273
  function errorCode(error) {
3152
3274
  return error && typeof error === "object" && "code" in error && typeof error.code === "string" ? error.code : "unknown";
3153
3275
  }
@@ -3175,7 +3297,7 @@ function listSubcTempConnectionFiles(dir) {
3175
3297
  if (!name.startsWith(CLAUSTRUM_TEMP_PREFIX) || !name.endsWith(CLAUSTRUM_TEMP_SUFFIX)) {
3176
3298
  continue;
3177
3299
  }
3178
- const candidate = join5(dir, name);
3300
+ const candidate = join6(dir, name);
3179
3301
  if (safeIsFile(candidate))
3180
3302
  matches.push(candidate);
3181
3303
  }
@@ -3185,13 +3307,13 @@ function listSubcTempConnectionFiles(dir) {
3185
3307
  function findExistingClaustrumConnectionPath(env = process.env) {
3186
3308
  const runtime = env.XDG_RUNTIME_DIR?.trim();
3187
3309
  if (runtime) {
3188
- const candidate = join5(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3310
+ const candidate = join6(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3189
3311
  if (safeIsFile(candidate))
3190
3312
  return candidate;
3191
3313
  }
3192
3314
  const home = env.HOME?.trim();
3193
3315
  if (home) {
3194
- 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);
3195
3317
  if (safeIsFile(candidate))
3196
3318
  return candidate;
3197
3319
  }
@@ -3199,7 +3321,7 @@ function findExistingClaustrumConnectionPath(env = process.env) {
3199
3321
  const linuxRun = `/run/user/${uid}/${PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME}`;
3200
3322
  if (safeIsFile(linuxRun))
3201
3323
  return linuxRun;
3202
- const tempMatches = listSubcTempConnectionFiles(tmpdir2());
3324
+ const tempMatches = listSubcTempConnectionFiles(tmpdir3());
3203
3325
  if (tempMatches.length === 1)
3204
3326
  return tempMatches[0];
3205
3327
  return;
@@ -3210,11 +3332,11 @@ function getDefaultClaustrumConnectionPath(env = process.env) {
3210
3332
  return existing;
3211
3333
  const runtime = env.XDG_RUNTIME_DIR?.trim();
3212
3334
  if (runtime && (process.platform !== "darwin" || safeIsFile(runtime))) {
3213
- return join5(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3335
+ return join6(runtime, PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME);
3214
3336
  }
3215
3337
  if (process.platform === "darwin") {
3216
3338
  const home = env.HOME?.trim() || userInfo().homedir;
3217
- 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);
3218
3340
  }
3219
3341
  const uid = process.getuid?.() ?? userInfo().uid;
3220
3342
  return `/run/user/${uid}/${PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME}`;
@@ -3316,6 +3438,345 @@ function assertNotCustodyTombstone(refreshToken, provider) {
3316
3438
  }
3317
3439
  }
3318
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
+
3319
3780
  // src/constants.ts
3320
3781
  var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
3321
3782
  var AUTHORIZE_URLS = {
@@ -3346,7 +3807,7 @@ function mergeAnthropicBetas(existing, betas) {
3346
3807
  return [...new Set([...incoming, ...betas])].join(",");
3347
3808
  }
3348
3809
  function isFastModeSupportedModel(model) {
3349
- 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);
3350
3811
  }
3351
3812
  var OPENCODE_IDENTITY_PREFIX = "You are OpenCode";
3352
3813
  var CLAUDE_CODE_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude.";
@@ -3663,16 +4124,16 @@ function getConfigDir() {
3663
4124
  if (process.env.OPENCODE_CONFIG_DIR?.trim()) {
3664
4125
  return process.env.OPENCODE_CONFIG_DIR.trim();
3665
4126
  }
3666
- return join6(process.env.XDG_CONFIG_HOME || join6(homedir2(), ".config"), "opencode");
4127
+ return join7(process.env.XDG_CONFIG_HOME || join7(homedir2(), ".config"), "opencode");
3667
4128
  }
3668
4129
  function getAccountStoragePath() {
3669
- 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);
3670
4131
  }
3671
4132
  function getAccountStatePath(configPath = getAccountStoragePath()) {
3672
4133
  const explicit = process.env.OPENCODE_ANTHROPIC_AUTH_STATE_FILE?.trim();
3673
4134
  if (explicit)
3674
4135
  return explicit;
3675
- 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`;
3676
4137
  }
3677
4138
  function createEmptyStorage() {
3678
4139
  return {
@@ -3793,7 +4254,7 @@ function getClaustrumMode(storage) {
3793
4254
  async function acquireRefreshFileLock2(options) {
3794
4255
  const accountPath = options.path ?? getAccountStoragePath();
3795
4256
  const lockPath = `${accountPath}.${options.name}.lock`;
3796
- const legacyOwnerPath = join6(lockPath, "owner.json");
4257
+ const legacyOwnerPath = join7(lockPath, "owner.json");
3797
4258
  const ownerId = randomUUID6();
3798
4259
  const now = Date.now;
3799
4260
  let renewTimer = null;
@@ -3847,7 +4308,7 @@ async function acquireRefreshFileLock2(options) {
3847
4308
  let acquired = await tryAcquire();
3848
4309
  if (!acquired) {
3849
4310
  const evictPath = `${lockPath}.evicting`;
3850
- const evictOwnerPath = join6(evictPath, "owner.json");
4311
+ const evictOwnerPath = join7(evictPath, "owner.json");
3851
4312
  const evictOwnerId = randomUUID6();
3852
4313
  const EVICT_TTL = 5000;
3853
4314
  const MAX_STEAL_ATTEMPTS = 8;
@@ -4751,416 +5212,74 @@ function computeCcVersionSuffix(firstUserText, version = CLAUDE_CODE_VERSION) {
4751
5212
  }
4752
5213
  function countUserPrompts(messages) {
4753
5214
  if (!Array.isArray(messages))
4754
- return 0;
4755
- let count = 0;
4756
- for (const message of messages) {
4757
- if (!message || typeof message !== "object")
4758
- continue;
4759
- const { role, content } = message;
4760
- if (role !== "user")
4761
- continue;
4762
- if (Array.isArray(content) && content.length > 0 && content.every((block) => !!block && typeof block === "object" && block.type === "tool_result"))
4763
- continue;
4764
- count += 1;
4765
- }
4766
- return count;
4767
- }
4768
- function buildBillingHeaderValue(messages, version = CLAUDE_CODE_VERSION, entrypoint, pinnedFirstUserText, lineage) {
4769
- const suffix = computeCcVersionSuffix(pinnedFirstUserText ?? extractFirstUserMessageText(messages), version);
4770
- let value = "x-anthropic-billing-header: " + `cc_version=${version}.${suffix}; ` + `cc_entrypoint=${entrypoint}; ` + "cch=00000;";
4771
- if (lineage?.previousRequestId && isValidAnthropicRequestId(lineage.previousRequestId)) {
4772
- value += ` cc_prev_req=${lineage.previousRequestId};`;
4773
- }
4774
- if (lineage?.promptId && isValidBillingPromptId(lineage.promptId)) {
4775
- value += ` cc_prompt_id=${lineage.promptId};`;
4776
- const index = lineage.promptIndex;
4777
- if (index !== undefined && Number.isSafeInteger(index) && index > 0) {
4778
- value += " cc_turn_origin=human;" + ` cc_prompt_index=${index};` + ` cc_turn_index=${index};`;
4779
- }
4780
- }
4781
- return value;
4782
- }
4783
- function extractBillingPromptId(body) {
4784
- const system = body?.system;
4785
- if (!Array.isArray(system))
4786
- return;
4787
- const first = system[0];
4788
- const text = first?.text;
4789
- if (typeof text !== "string" || !text.startsWith("x-anthropic-billing-header:"))
4790
- return;
4791
- const id = / cc_prompt_id=([^;\r\n]*);/.exec(text)?.[1];
4792
- return id && isValidBillingPromptId(id) ? id : undefined;
4793
- }
4794
- function stripBillingLineageFields(value) {
4795
- return value.replace(BILLING_LINEAGE_FIELD_PATTERN, "");
4796
- }
4797
- function stripBillingLineageFromBody(body) {
4798
- if (!body || typeof body !== "object")
4799
- return 0;
4800
- const system = body.system;
4801
- if (!Array.isArray(system))
4802
- return 0;
4803
- let stripped = 0;
4804
- for (const block of system) {
4805
- if (!block || typeof block !== "object")
4806
- continue;
4807
- const text = block.text;
4808
- if (typeof text !== "string" || !text.startsWith("x-anthropic-billing-header:")) {
4809
- continue;
4810
- }
4811
- const clean = stripBillingLineageFields(text);
4812
- if (clean === text)
4813
- continue;
4814
- block.text = clean;
4815
- stripped += 1;
4816
- }
4817
- return stripped;
4818
- }
4819
-
4820
- // src/claude-code.ts
4821
- import { randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
4822
-
4823
- // src/models.ts
4824
- var CLAUDE_FABLE_5_MODEL_ID = "claude-fable-5";
4825
- var CLAUDE_MYTHOS_5_MODEL_ID = "claude-mythos-5";
4826
- var CLAUDE_FABLE_5_1_MODEL_ID = "claude-fable-5-1";
4827
- var CLAUDE_MYTHOS_5_1_MODEL_ID = "claude-mythos-5-1";
4828
- var CLAUDE_HAIKU_4_5_MODEL_ID = "claude-haiku-4-5";
4829
- function normalizeAnthropicModelId(model) {
4830
- return model.endsWith("[1m]") ? model.slice(0, -4) : model;
4831
- }
4832
- var CLAUDE_HAIKU_4_5_PRICING = {
4833
- input: 1,
4834
- output: 5
4835
- };
4836
- var CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS = [
4837
- CLAUDE_FABLE_5_1_MODEL_ID,
4838
- CLAUDE_MYTHOS_5_1_MODEL_ID
4839
- ];
4840
- var CLAUDE_FABLE_MYTHOS_5_MODEL_IDS = [
4841
- CLAUDE_FABLE_5_MODEL_ID,
4842
- CLAUDE_MYTHOS_5_MODEL_ID,
4843
- ...CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS
4844
- ];
4845
- var CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING = {
4846
- type: "adaptive",
4847
- display: "summarized"
4848
- };
4849
- var CLAUDE_FABLE_MYTHOS_5_PRICING = {
4850
- input: 10,
4851
- output: 50,
4852
- cacheRead: 1,
4853
- cacheWrite5m: 12.5,
4854
- cacheWrite1h: 20
4855
- };
4856
- var CLAUDE_FABLE_MYTHOS_5_1_PRICING = {
4857
- input: 10,
4858
- output: 50,
4859
- cacheRead: 0.25,
4860
- cacheWrite5m: 12.5,
4861
- cacheWrite1h: 20
4862
- };
4863
- var CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW = 1e6;
4864
- var CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS = 128000;
4865
- var CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE = "2026-06-09";
4866
- var CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE = "2026-09-01";
4867
- var CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS = {
4868
- [CLAUDE_FABLE_5_MODEL_ID]: {
4869
- id: CLAUDE_FABLE_5_MODEL_ID,
4870
- name: "Claude Fable 5"
4871
- },
4872
- [CLAUDE_MYTHOS_5_MODEL_ID]: {
4873
- id: CLAUDE_MYTHOS_5_MODEL_ID,
4874
- name: "Claude Mythos 5",
4875
- limited: true
4876
- },
4877
- [CLAUDE_FABLE_5_1_MODEL_ID]: {
4878
- id: CLAUDE_FABLE_5_1_MODEL_ID,
4879
- name: "Claude Fable 5.1"
4880
- },
4881
- [CLAUDE_MYTHOS_5_1_MODEL_ID]: {
4882
- id: CLAUDE_MYTHOS_5_1_MODEL_ID,
4883
- name: "Claude Mythos 5.1",
4884
- limited: true
4885
- }
4886
- };
4887
- var CLAUDE_FABLE_MYTHOS_5_1_MODEL_SPECS = {
4888
- [CLAUDE_FABLE_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_FABLE_5_1_MODEL_ID],
4889
- [CLAUDE_MYTHOS_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_MYTHOS_5_1_MODEL_ID]
4890
- };
4891
- function isClaudeFableOrMythos5Model(model) {
4892
- if (typeof model !== "string")
4893
- return false;
4894
- const normalized = normalizeAnthropicModelId(model);
4895
- return CLAUDE_FABLE_MYTHOS_5_MODEL_IDS.some((id) => normalized === id || normalized.startsWith(`${id}-`));
4896
- }
4897
- function isClaudeFableOrMythos51Model(model) {
4898
- if (typeof model !== "string")
4899
- return false;
4900
- const normalized = normalizeAnthropicModelId(model);
4901
- return CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS.some((id) => normalized === id || normalized.startsWith(`${id}-`));
4902
- }
4903
- function isClaudeFable51Model(model) {
4904
- if (typeof model !== "string")
4905
- return false;
4906
- const normalized = normalizeAnthropicModelId(model);
4907
- return normalized === CLAUDE_FABLE_5_1_MODEL_ID || normalized.startsWith(`${CLAUDE_FABLE_5_1_MODEL_ID}-`);
4908
- }
4909
- function getClaudeFableMythos5ReleaseDate(model) {
4910
- return isClaudeFableOrMythos51Model(model) ? CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE : CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE;
4911
- }
4912
- var CLAUDE_SONNET_5_MODEL_ID = "claude-sonnet-5";
4913
- var CLAUDE_SONNET_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4914
- function isClaudeSonnet5Model(model) {
4915
- if (typeof model !== "string")
4916
- return false;
4917
- const normalized = normalizeAnthropicModelId(model);
4918
- return !isClaudeSonnet55Model(normalized) && (normalized === CLAUDE_SONNET_5_MODEL_ID || normalized.startsWith(`${CLAUDE_SONNET_5_MODEL_ID}-`));
4919
- }
4920
- var CLAUDE_SONNET_5_5_MODEL_ID = "claude-sonnet-5-5";
4921
- var CLAUDE_SONNET_5_5_RELEASE_DATE = "2026-09-28";
4922
- var CLAUDE_SONNET_5_5_CONTEXT_WINDOW = 1e6;
4923
- var CLAUDE_SONNET_5_5_MAX_OUTPUT_TOKENS = 128000;
4924
- var CLAUDE_SONNET_5_5_PRICING = {
4925
- input: 2,
4926
- output: 10,
4927
- cacheRead: 0.2,
4928
- cacheWrite5m: 2.5,
4929
- cacheWrite1h: 4
4930
- };
4931
- var CLAUDE_SONNET_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4932
- function isClaudeSonnet55Model(model) {
4933
- if (typeof model !== "string")
4934
- return false;
4935
- const normalized = normalizeAnthropicModelId(model);
4936
- return normalized === CLAUDE_SONNET_5_5_MODEL_ID || normalized.startsWith(`${CLAUDE_SONNET_5_5_MODEL_ID}-`);
4937
- }
4938
- var CLAUDE_HAIKU_5_5_MODEL_ID = "claude-haiku-5-5";
4939
- var CLAUDE_HAIKU_5_5_RELEASE_DATE = "2026-10-07";
4940
- var CLAUDE_HAIKU_5_5_CONTEXT_WINDOW = 1e6;
4941
- var CLAUDE_HAIKU_5_5_MAX_OUTPUT_TOKENS = 128000;
4942
- var CLAUDE_HAIKU_5_5_LONG_CONTEXT_THRESHOLD = 1e5;
4943
- var CLAUDE_HAIKU_5_5_PRICING = {
4944
- input: 0.1,
4945
- output: 0.5,
4946
- cacheRead: 0.01,
4947
- cacheWrite5m: 0.125,
4948
- cacheWrite1h: 0.2
4949
- };
4950
- var CLAUDE_HAIKU_5_5_LONG_CONTEXT_PRICING = {
4951
- input: 0.5,
4952
- output: 2.5,
4953
- cacheRead: 0.05,
4954
- cacheWrite5m: 0.625,
4955
- cacheWrite1h: 1
4956
- };
4957
- var CLAUDE_HAIKU_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4958
- function isClaudeHaiku55Model(model) {
4959
- if (typeof model !== "string")
4960
- return false;
4961
- const normalized = normalizeAnthropicModelId(model);
4962
- return normalized === CLAUDE_HAIKU_5_5_MODEL_ID || /^claude-haiku-5-5-\d{8}$/.test(normalized);
4963
- }
4964
- var CLAUDE_OPUS_5_MODEL_ID = "claude-opus-5";
4965
- var CLAUDE_OPUS_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4966
- function isClaudeOpus5Model(model) {
4967
- if (typeof model !== "string")
4968
- return false;
4969
- const normalized = normalizeAnthropicModelId(model);
4970
- return !isClaudeOpus55Model(normalized) && (normalized === CLAUDE_OPUS_5_MODEL_ID || normalized.startsWith(`${CLAUDE_OPUS_5_MODEL_ID}-`));
4971
- }
4972
- var CLAUDE_OPUS_5_5_MODEL_ID = "claude-opus-5-5";
4973
- var CLAUDE_OPUS_5_5_RELEASE_DATE = "2026-09-18";
4974
- var CLAUDE_OPUS_5_5_CONTEXT_WINDOW = 1e6;
4975
- var CLAUDE_OPUS_5_5_MAX_OUTPUT_TOKENS = 128000;
4976
- var CLAUDE_OPUS_5_5_PRICING = {
4977
- input: 4,
4978
- output: 20,
4979
- cacheRead: 0.2,
4980
- cacheWrite5m: 5,
4981
- cacheWrite1h: 8
4982
- };
4983
- var CLAUDE_OPUS_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
4984
- function isClaudeOpus55Model(model) {
4985
- if (typeof model !== "string")
4986
- return false;
4987
- const normalized = normalizeAnthropicModelId(model);
4988
- return normalized === CLAUDE_OPUS_5_5_MODEL_ID || normalized.startsWith(`${CLAUDE_OPUS_5_5_MODEL_ID}-`);
4989
- }
4990
- function isClaudeOpus5FamilyModel(model) {
4991
- return isClaudeOpus5Model(model) || isClaudeOpus55Model(model);
4992
- }
4993
- function isOpenAIReasoningSignature(value) {
4994
- if (typeof value !== "string")
4995
- return false;
4996
- if (value.startsWith("gAAAA"))
4997
- return true;
4998
- if (!value.startsWith("{"))
4999
- return false;
5000
- try {
5001
- const parsed = JSON.parse(value);
5002
- return parsed.type === "reasoning" && typeof parsed.id === "string" && parsed.id.startsWith("rs_") && typeof parsed.encrypted_content === "string" && parsed.encrypted_content.startsWith("gAAAA");
5003
- } catch {
5004
- return false;
5005
- }
5006
- }
5007
-
5008
- // src/mid-conversation-output-config.ts
5009
- var PER_TURN_CONTROL_BETA = "per-turn-control-2026-07-01";
5010
- function isRecord3(value) {
5011
- return typeof value === "object" && value !== null && !Array.isArray(value);
5012
- }
5013
- function normalizeAdaptiveEffort(value) {
5014
- if (value === "minimal")
5015
- return "low";
5016
- if (value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "max") {
5017
- return value;
5018
- }
5019
- return;
5020
- }
5021
- function usesPerTurnControl(model) {
5022
- return isClaudeOpus55Model(model) || isClaudeSonnet55Model(model);
5023
- }
5024
- function sendsPerTurnControlBeta(model) {
5025
- return usesPerTurnControl(model) || isClaudeFable51Model(model) || isClaudeHaiku55Model(model);
5026
- }
5027
- function supportsPerMessageEffort(body) {
5028
- if (isClaudeFable51Model(body.model))
5029
- return true;
5030
- return usesPerTurnControl(body.model) && isRecord3(body.thinking) && body.thinking.type === "adaptive";
5031
- }
5032
- function defaultAdaptiveEffort(model) {
5033
- return isClaudeOpus55Model(model) || isClaudeHaiku55Model(model) ? "medium" : "high";
5034
- }
5035
- function compactTransitions(transitions) {
5036
- const compacted = [];
5037
- for (const transition of transitions) {
5038
- if (!Number.isSafeInteger(transition.afterAssistantMessages) || transition.afterAssistantMessages < 0 || !normalizeAdaptiveEffort(transition.effort)) {
5215
+ return 0;
5216
+ let count = 0;
5217
+ for (const message of messages) {
5218
+ if (!message || typeof message !== "object")
5039
5219
  continue;
5040
- }
5041
- const normalized = {
5042
- afterAssistantMessages: transition.afterAssistantMessages,
5043
- effort: transition.effort
5044
- };
5045
- const previous = compacted.at(-1);
5046
- if (previous && previous.afterAssistantMessages === normalized.afterAssistantMessages) {
5047
- previous.effort = normalized.effort;
5220
+ const { role, content } = message;
5221
+ if (role !== "user")
5048
5222
  continue;
5049
- }
5050
- if (previous?.effort === normalized.effort)
5223
+ if (Array.isArray(content) && content.length > 0 && content.every((block) => !!block && typeof block === "object" && block.type === "tool_result"))
5051
5224
  continue;
5052
- compacted.push(normalized);
5225
+ count += 1;
5053
5226
  }
5054
- return compacted;
5227
+ return count;
5055
5228
  }
5056
- function applyMidConversationOutputConfig(body, transitions) {
5057
- if (!supportsPerMessageEffort(body) || !Array.isArray(body.messages)) {
5058
- return { applied: false, inserted: 0 };
5059
- }
5060
- const compacted = compactTransitions(transitions);
5061
- const pinsEveryRequest = isClaudeFable51Model(body.model);
5062
- if (!pinsEveryRequest && compacted.length < 2) {
5063
- return { applied: false, inserted: 0 };
5064
- }
5065
- const currentOutputConfig = isRecord3(body.output_config) ? body.output_config : {};
5066
- const baseline = compacted[0]?.effort ?? normalizeAdaptiveEffort(currentOutputConfig.effort) ?? defaultAdaptiveEffort(body.model);
5067
- const pinnedOutputConfig = { ...currentOutputConfig, effort: baseline };
5068
- if (pinsEveryRequest)
5069
- body.output_config = pinnedOutputConfig;
5070
- if (compacted.length < 2)
5071
- return { applied: true, inserted: 0 };
5072
- const messages = body.messages;
5073
- const transitionsByBoundary = new Map;
5074
- for (const transition of compacted.slice(1)) {
5075
- transitionsByBoundary.set(transition.afterAssistantMessages, transition.effort);
5229
+ function buildBillingHeaderValue(messages, version = CLAUDE_CODE_VERSION, entrypoint, pinnedFirstUserText, lineage) {
5230
+ const suffix = computeCcVersionSuffix(pinnedFirstUserText ?? extractFirstUserMessageText(messages), version);
5231
+ let value = "x-anthropic-billing-header: " + `cc_version=${version}.${suffix}; ` + `cc_entrypoint=${entrypoint}; ` + "cch=00000;";
5232
+ if (lineage?.previousRequestId && isValidAnthropicRequestId(lineage.previousRequestId)) {
5233
+ value += ` cc_prev_req=${lineage.previousRequestId};`;
5076
5234
  }
5077
- let assistantMessages = 0;
5078
- let activeEffort = baseline;
5079
- let inserted = 0;
5080
- const rewritten = [];
5081
- for (const message of messages) {
5082
- if (isRecord3(message) && message.role === "user" && transitionsByBoundary.has(assistantMessages)) {
5083
- const effort = transitionsByBoundary.get(assistantMessages);
5084
- if (effort && effort !== activeEffort) {
5085
- rewritten.push({
5086
- role: "system",
5087
- content: [],
5088
- output_config: { effort }
5089
- });
5090
- activeEffort = effort;
5091
- inserted++;
5092
- }
5235
+ if (lineage?.promptId && isValidBillingPromptId(lineage.promptId)) {
5236
+ value += ` cc_prompt_id=${lineage.promptId};`;
5237
+ const index = lineage.promptIndex;
5238
+ if (index !== undefined && Number.isSafeInteger(index) && index > 0) {
5239
+ value += " cc_turn_origin=human;" + ` cc_prompt_index=${index};` + ` cc_turn_index=${index};`;
5093
5240
  }
5094
- rewritten.push(message);
5095
- if (isRecord3(message) && message.role === "assistant")
5096
- assistantMessages++;
5097
- }
5098
- if (!pinsEveryRequest && inserted === 0) {
5099
- return { applied: false, inserted: 0 };
5100
5241
  }
5101
- body.output_config = pinnedOutputConfig;
5102
- body.messages = rewritten;
5103
- return { applied: true, inserted };
5242
+ return value;
5104
5243
  }
5105
-
5106
- // src/turn-end-note.ts
5107
- var TURN_END_NOTE_BETA = "mid-conversation-system-clear-at-2026-08-21";
5108
- var TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
5109
- 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.";
5110
- var DEFAULT_TOOLS = ["board", "ctx_reduce"];
5111
- function isRecord4(value) {
5112
- return value !== null && typeof value === "object" && !Array.isArray(value);
5244
+ function extractBillingPromptId(body) {
5245
+ const system = body?.system;
5246
+ if (!Array.isArray(system))
5247
+ return;
5248
+ const first = system[0];
5249
+ const text = first?.text;
5250
+ if (typeof text !== "string" || !text.startsWith("x-anthropic-billing-header:"))
5251
+ return;
5252
+ const id = / cc_prompt_id=([^;\r\n]*);/.exec(text)?.[1];
5253
+ return id && isValidBillingPromptId(id) ? id : undefined;
5113
5254
  }
5114
- function supportsTurnEndNote(model) {
5115
- return isClaudeFable51Model(model) || isClaudeHaiku55Model(model) || isClaudeOpus55Model(model) || isClaudeSonnet55Model(model);
5255
+ function stripBillingLineageFields(value) {
5256
+ return value.replace(BILLING_LINEAGE_FIELD_PATTERN, "");
5116
5257
  }
5117
- function applyTurnEndNotes(body, options = {}) {
5118
- if (!supportsTurnEndNote(body.model) || !Array.isArray(body.messages))
5258
+ function stripBillingLineageFromBody(body) {
5259
+ if (!body || typeof body !== "object")
5119
5260
  return 0;
5120
- const allowed = new Set((options.tools ?? DEFAULT_TOOLS).map((name) => options.mapToolName?.(name) ?? name));
5121
- if (!allowed.size)
5261
+ const system = body.system;
5262
+ if (!Array.isArray(system))
5122
5263
  return 0;
5123
- const messages = body.messages;
5124
- const rewritten = [];
5125
- let inserted = 0;
5126
- for (let index = 0;index < messages.length; index++) {
5127
- const results = messages[index];
5128
- rewritten.push(results);
5129
- let preceding = index - 1;
5130
- while (preceding >= 0) {
5131
- const control = messages[preceding];
5132
- if (!isRecord4(control) || control.role !== "system" || !Array.isArray(control.content) || control.content.length !== 0 || !isRecord4(control.output_config))
5133
- break;
5134
- preceding--;
5135
- }
5136
- const assistant = messages[preceding];
5137
- if (!isRecord4(assistant) || assistant.role !== "assistant" || !Array.isArray(assistant.content) || !isRecord4(results) || results.role !== "user" || !Array.isArray(results.content))
5138
- continue;
5139
- 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("");
5140
- if (visible.length < TURN_END_NOTE_MIN_VISIBLE_CHARACTERS)
5141
- continue;
5142
- const calls = assistant.content.filter((block) => isRecord4(block) && block.type === "tool_use");
5143
- 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")
5144
5267
  continue;
5145
- const resultIds = new Set(results.content.filter((block) => isRecord4(block) && block.type === "tool_result").map((block) => block.tool_use_id));
5146
- 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:")) {
5147
5270
  continue;
5148
- const next = messages[index + 1];
5149
- if (isRecord4(next) && next.role === "user")
5271
+ }
5272
+ const clean = stripBillingLineageFields(text);
5273
+ if (clean === text)
5150
5274
  continue;
5151
- rewritten.push({
5152
- role: "system",
5153
- clear_at: "next_user_message",
5154
- content: TURN_END_NOTE_CONTENT
5155
- });
5156
- inserted++;
5275
+ block.text = clean;
5276
+ stripped += 1;
5157
5277
  }
5158
- if (inserted)
5159
- body.messages = rewritten;
5160
- return inserted;
5278
+ return stripped;
5161
5279
  }
5162
5280
 
5163
5281
  // src/claude-code.ts
5282
+ import { randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
5164
5283
  var IDENTITY_CACHE_LIMIT = 1000;
5165
5284
  var identityCache = new Map;
5166
5285
  function setBounded(map, key, value, limit = IDENTITY_CACHE_LIMIT) {
@@ -5373,7 +5492,7 @@ async function resolveClaudeCodeAccountIdentity(accessToken, model, accountIdent
5373
5492
  throw new ClaudeUnsupportedAccessError;
5374
5493
  return resolveClaudeCodeIdentity(accessToken, model, accountIdentity);
5375
5494
  }
5376
- function isRecord5(value) {
5495
+ function isRecord3(value) {
5377
5496
  return value != null && typeof value === "object" && !Array.isArray(value);
5378
5497
  }
5379
5498
  function buildClaudeCodeMetadataUserId(identity) {
@@ -5388,55 +5507,17 @@ function buildClaudeCodeMetadataUserId(identity) {
5388
5507
  function applyClaudeCodeMetadata(body, identity) {
5389
5508
  const userId = buildClaudeCodeMetadataUserId(identity);
5390
5509
  if (!userId) {
5391
- if (isRecord5(body.metadata))
5510
+ if (isRecord3(body.metadata))
5392
5511
  delete body.metadata.user_id;
5393
5512
  return false;
5394
5513
  }
5395
- if (!isRecord5(body.metadata))
5514
+ if (!isRecord3(body.metadata))
5396
5515
  body.metadata = {};
5397
5516
  const metadata = body.metadata;
5398
- if (isRecord5(metadata))
5517
+ if (isRecord3(metadata))
5399
5518
  metadata.user_id = userId;
5400
5519
  return true;
5401
5520
  }
5402
- var CLAUDE_CODE_FULL_AGENT_BETAS = [
5403
- "claude-code-20250219",
5404
- "oauth-2025-04-20",
5405
- "interleaved-thinking-2025-05-14",
5406
- "thinking-token-count-2026-05-13",
5407
- "context-management-2025-06-27",
5408
- "prompt-caching-scope-2026-01-05",
5409
- "mid-conversation-tool-changes-2026-07-01",
5410
- "advanced-tool-use-2025-11-20",
5411
- TURN_END_NOTE_BETA,
5412
- "effort-2025-11-24",
5413
- "thinking-binding-controls-2026-08-01",
5414
- "thinking-display-updates-2026-08-18",
5415
- "extended-cache-ttl-2025-04-11",
5416
- "cache-diagnosis-2026-04-07"
5417
- ];
5418
- var CLAUDE_CODE_TITLE_BETAS = [
5419
- "oauth-2025-04-20",
5420
- "interleaved-thinking-2025-05-14",
5421
- "redact-thinking-2026-02-12",
5422
- "thinking-token-count-2026-05-13",
5423
- "context-management-2025-06-27",
5424
- "prompt-caching-scope-2026-01-05",
5425
- "mid-conversation-tool-changes-2026-07-01",
5426
- "mid-conversation-system-clear-at-2026-08-21",
5427
- "effort-2025-11-24",
5428
- "cache-diagnosis-2026-04-07"
5429
- ];
5430
- var CLAUDE_CODE_QUOTA_BETAS = [
5431
- "oauth-2025-04-20",
5432
- "interleaved-thinking-2025-05-14",
5433
- "redact-thinking-2026-02-12",
5434
- "thinking-token-count-2026-05-13",
5435
- "context-management-2025-06-27",
5436
- "prompt-caching-scope-2026-01-05"
5437
- ];
5438
- var CLAUDE_CODE_BETA = "claude-code-20250219";
5439
- var PROMPT_CACHING_SCOPE_BETA = "prompt-caching-scope-2026-01-05";
5440
5521
  function hasStructuredOutput(body) {
5441
5522
  const outputConfig = body.output_config;
5442
5523
  const format = outputConfig?.format;
@@ -5446,25 +5527,10 @@ function isQuotaProbe(body) {
5446
5527
  return body.max_tokens === 1 && !body.stream && !body.thinking && (!Array.isArray(body.tools) || body.tools.length === 0) && !hasStructuredOutput(body);
5447
5528
  }
5448
5529
  function selectClaudeCodeBetas(body, extraBetas = [], requestClass = "main") {
5449
- const selected = requestClass === "main" ? [...CLAUDE_CODE_FULL_AGENT_BETAS] : body && isQuotaProbe(body) ? [...CLAUDE_CODE_QUOTA_BETAS] : [...CLAUDE_CODE_TITLE_BETAS];
5450
- 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))
5451
5533
  selected.push(TURN_END_NOTE_BETA);
5452
- if (body && isClaudeHaiku55Model(body.model)) {
5453
- const codeIndex = selected.indexOf(CLAUDE_CODE_BETA);
5454
- if (codeIndex >= 0) {
5455
- selected.splice(codeIndex, 1);
5456
- selected.splice(selected.indexOf(PROMPT_CACHING_SCOPE_BETA) + 1, 0, CLAUDE_CODE_BETA);
5457
- }
5458
- }
5459
- if (body && sendsPerTurnControlBeta(body.model)) {
5460
- let index = selected.indexOf(PROMPT_CACHING_SCOPE_BETA);
5461
- if (index >= 0 && selected[index + 1] === CLAUDE_CODE_BETA)
5462
- index += 1;
5463
- if (index >= 0)
5464
- selected.splice(index + 1, 0, PER_TURN_CONTROL_BETA);
5465
- else
5466
- selected.push(PER_TURN_CONTROL_BETA);
5467
- }
5468
5534
  if (body && hasStructuredOutput(body)) {
5469
5535
  const index = selected.indexOf("cache-diagnosis-2026-04-07");
5470
5536
  selected.splice(index < 0 ? selected.length : index, 0, "structured-outputs-2025-12-15");
@@ -5578,8 +5644,8 @@ import {
5578
5644
  unlink as unlink4,
5579
5645
  writeFile as writeFile2
5580
5646
  } from "node:fs/promises";
5581
- import { tmpdir as tmpdir4 } from "node:os";
5582
- 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";
5583
5649
 
5584
5650
  // src/json.ts
5585
5651
  function parseJsonRedacted(text) {
@@ -5850,7 +5916,7 @@ var DUMP_USAGE_TITLE = "## Claude Dump Usage";
5850
5916
  var DUMP_USAGE = "Usage: `/claude-dump`, `/claude-dump on`, or `/claude-dump off`.";
5851
5917
  var DUMP_DIR_ENV = "OPENCODE_ANTHROPIC_AUTH_DUMP_DIR";
5852
5918
  var DUMP_MAX_BYTES_ENV = "OPENCODE_ANTHROPIC_AUTH_DUMP_MAX_BYTES";
5853
- var DEFAULT_DUMP_DIR = join8(tmpdir4(), "opencode-anthropic-auth-dumps");
5919
+ var DEFAULT_DUMP_DIR = join9(tmpdir5(), "opencode-anthropic-auth-dumps");
5854
5920
  var DEFAULT_DUMP_MAX_BYTES = 512 * 1024 * 1024;
5855
5921
  var DUMP_SWEEP_INTERVAL_MS = 5 * 60 * 1000;
5856
5922
  var DUMP_SWEEP_NEWNESS_FLOOR_MS = 60 * 1000;
@@ -5953,7 +6019,7 @@ async function sweepDumpDirectory(options) {
5953
6019
  const partial = isDumpPartialFileName(entry.name);
5954
6020
  if (!partial && !isDumpArtifactFileName(entry.name))
5955
6021
  return;
5956
- const path2 = join8(dumpDir, entry.name);
6022
+ const path2 = join9(dumpDir, entry.name);
5957
6023
  try {
5958
6024
  const stats = await lstat2(path2);
5959
6025
  if (!stats.isFile() || stats.isSymbolicLink())
@@ -6158,7 +6224,7 @@ async function loadLatestDumpBody(input) {
6158
6224
  const candidates = names.map((name) => ({ name, tag: dumpBodyTagForAffinity(name, affinity) })).filter((candidate) => candidate.tag !== undefined).sort((a, b) => b.name.localeCompare(a.name));
6159
6225
  for (const candidate of candidates) {
6160
6226
  try {
6161
- const path2 = join8(dumpDir, candidate.name);
6227
+ const path2 = join9(dumpDir, candidate.name);
6162
6228
  const metadataPath = path2.replace(/\.body\.json$/, ".meta.json");
6163
6229
  if (!(await lstat2(path2)).isFile())
6164
6230
  continue;
@@ -6285,7 +6351,7 @@ async function dumpRequest(input) {
6285
6351
  const tagSegment = dumpTagSegment(input.tag);
6286
6352
  const id = `${new Date().toISOString().replace(/[:.]/g, "-")}-${String(nextDumpId).padStart(6, "0")}-${dumpFileSessionSegment(affinity, 80 - tagSegment.length)}${tagSegment}-${dumpRequestSegment(input)}`;
6287
6353
  const dumpDir = getDumpDirectory();
6288
- const prefix = join8(dumpDir, id);
6354
+ const prefix = join9(dumpDir, id);
6289
6355
  const files = {
6290
6356
  body: `${prefix}.body.json`,
6291
6357
  metadata: `${prefix}.meta.json`,
@@ -8495,8 +8561,8 @@ import {
8495
8561
  rm as rm5,
8496
8562
  writeFile as writeFile3
8497
8563
  } from "node:fs/promises";
8498
- import { tmpdir as tmpdir5 } from "node:os";
8499
- import { join as join9 } from "node:path";
8564
+ import { tmpdir as tmpdir6 } from "node:os";
8565
+ import { join as join10 } from "node:path";
8500
8566
  var CACHE_KEEP_REGISTRY_LEASE_MS = 3 * 60000;
8501
8567
  function normalizeSession(value) {
8502
8568
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -8531,7 +8597,7 @@ function isExpiredRecord(record, now, leaseMs) {
8531
8597
  return record.updatedAt <= now && now - record.updatedAt > leaseMs;
8532
8598
  }
8533
8599
  function getDefaultCacheKeepRegistryDirectory(scope) {
8534
- return join9(tmpdir5(), "opencode-anthropic-auth", "cachekeep-sessions", scope);
8600
+ return join10(tmpdir6(), "opencode-anthropic-auth", "cachekeep-sessions", scope);
8535
8601
  }
8536
8602
 
8537
8603
  class CacheKeepSessionRegistry {
@@ -8542,7 +8608,7 @@ class CacheKeepSessionRegistry {
8542
8608
  constructor(options) {
8543
8609
  this.options = options;
8544
8610
  const instanceId = options.instanceId ?? `${process.pid}-${randomUUID8()}`;
8545
- this.filePath = join9(options.directory, `${instanceId}.json`);
8611
+ this.filePath = join10(options.directory, `${instanceId}.json`);
8546
8612
  }
8547
8613
  publish(sessions) {
8548
8614
  const snapshot = sessions.map((session) => ({ ...session }));
@@ -8582,7 +8648,7 @@ class CacheKeepSessionRegistry {
8582
8648
  }
8583
8649
  const records = await Promise.all(names.map(async (name) => {
8584
8650
  try {
8585
- const raw = await readFile7(join9(this.options.directory, name), "utf8");
8651
+ const raw = await readFile7(join10(this.options.directory, name), "utf8");
8586
8652
  return normalizeRecord(JSON.parse(raw));
8587
8653
  } catch {
8588
8654
  return;
@@ -8624,7 +8690,7 @@ class CacheKeepSessionRegistry {
8624
8690
  return;
8625
8691
  }
8626
8692
  await Promise.all(names.map(async (name) => {
8627
- const recordPath = join9(this.options.directory, name);
8693
+ const recordPath = join10(this.options.directory, name);
8628
8694
  if (recordPath === this.filePath)
8629
8695
  return;
8630
8696
  let initialRecord;
@@ -8705,7 +8771,7 @@ import {
8705
8771
  dirname as dirname8,
8706
8772
  extname as extname2,
8707
8773
  isAbsolute as isAbsolute2,
8708
- join as join10,
8774
+ join as join11,
8709
8775
  resolve as resolve4
8710
8776
  } from "node:path";
8711
8777
  import {
@@ -8859,16 +8925,16 @@ function getClaustrumEnrollmentPaths2(tokenPath) {
8859
8925
  const extension = extname2(tokenPath) || ".json";
8860
8926
  const stem = basename3(tokenPath, extname2(tokenPath));
8861
8927
  return {
8862
- statePath: join10(dirname8(tokenPath), `${stem}-state${extension}`),
8928
+ statePath: join11(dirname8(tokenPath), `${stem}-state${extension}`),
8863
8929
  tokenPath
8864
8930
  };
8865
8931
  }
8866
8932
  function getHostClaustrumEnrollmentPaths(host, env = process.env, cwd = process.cwd()) {
8867
8933
  const configured = env[`${host.toUpperCase()}_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE`]?.trim();
8868
- 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`);
8869
8935
  return getClaustrumEnrollmentPaths2(tokenPath);
8870
8936
  }
8871
- function isRecord6(value) {
8937
+ function isRecord4(value) {
8872
8938
  return typeof value === "object" && value !== null && !Array.isArray(value);
8873
8939
  }
8874
8940
  function validTimestamp2(value) {
@@ -8878,7 +8944,7 @@ function validGeneration2(value) {
8878
8944
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
8879
8945
  }
8880
8946
  function decodeEnrollmentState2(value) {
8881
- 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) {
8882
8948
  throw new Error("invalid Claustrum enrollment state");
8883
8949
  }
8884
8950
  if (value.phase === "pending") {
@@ -8929,7 +8995,7 @@ function decodeEnrollmentState2(value) {
8929
8995
  throw new Error("invalid Claustrum enrollment state");
8930
8996
  }
8931
8997
  function decodeTokenFile2(value) {
8932
- 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)) {
8933
8999
  throw new Error("invalid Claustrum enrollment token file");
8934
9000
  }
8935
9001
  return {
@@ -9010,7 +9076,7 @@ async function writeStateAtomic2(path2, state, beforeRename) {
9010
9076
  if (Buffer.byteLength(bytes) > ENROLLMENT_FILE_MAX_BYTES2) {
9011
9077
  throw new Error("Claustrum enrollment state is too large");
9012
9078
  }
9013
- const temporary = join10(parent, `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9079
+ const temporary = join11(parent, `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9014
9080
  let descriptor;
9015
9081
  try {
9016
9082
  const nativeCreated = await createWindowsOwnerOnly(temporary, bytes);
@@ -9029,7 +9095,7 @@ async function writeStateAtomic2(path2, state, beforeRename) {
9029
9095
  }
9030
9096
  }
9031
9097
  async function writeTokenAtomic(path2, value, writeTokenFile, beforeRename) {
9032
- const staged = join10(dirname8(path2), `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9098
+ const staged = join11(dirname8(path2), `.${basename3(path2)}.${process.pid}.${randomUUID9()}.tmp`);
9033
9099
  try {
9034
9100
  await writeTokenFile(staged, value);
9035
9101
  await beforeRename();
@@ -9491,7 +9557,9 @@ function formatEnrollmentStatus(status, scopedServing = false) {
9491
9557
  case "busy":
9492
9558
  return ["- Enrollment: setup is busy"];
9493
9559
  case "unavailable":
9494
- return ["- Enrollment: temporarily unavailable"];
9560
+ return [
9561
+ '- Enrollment: this Claustrum vault is too old to connect plugins. Run `ck upgrade` to move to Claustrum v0.2.0 or newer (read "Upgrading from v0.1.3" in its release notes first).'
9562
+ ];
9495
9563
  case "pending":
9496
9564
  return status.requestId && /^[A-Za-z0-9_-]{1,128}$/.test(status.requestId) ? [`- Enrollment: pending approval (${status.requestId})`, setup] : [
9497
9565
  status.requestId ? "- Enrollment: pending approval" : "- Enrollment: request not sent",
@@ -10038,40 +10106,136 @@ function buildLoggingStatusSummary(input) {
10038
10106
  ].join(`
10039
10107
  `);
10040
10108
  }
10041
- function executeLoggingCommand(input) {
10042
- const action = parseLoggingCommandAction(input.argumentsText);
10043
- const level = input.level ?? "info";
10044
- if (action.type === "status")
10045
- return buildLoggingStatusSummary({
10046
- level,
10047
- settingsPath: input.settingsPath
10048
- });
10049
- if (action.type === "level") {
10050
- return [
10051
- "## Claude Log Level Updated",
10052
- "",
10053
- `Level set to \`${action.level}\`.`,
10054
- "",
10055
- ...buildLoggingStatusSummary({
10056
- level: action.level,
10057
- settingsPath: input.settingsPath
10058
- }).split(`
10059
- `).slice(2)
10060
- ].join(`
10061
- `);
10109
+ function executeLoggingCommand(input) {
10110
+ const action = parseLoggingCommandAction(input.argumentsText);
10111
+ const level = input.level ?? "info";
10112
+ if (action.type === "status")
10113
+ return buildLoggingStatusSummary({
10114
+ level,
10115
+ settingsPath: input.settingsPath
10116
+ });
10117
+ if (action.type === "level") {
10118
+ return [
10119
+ "## Claude Log Level Updated",
10120
+ "",
10121
+ `Level set to \`${action.level}\`.`,
10122
+ "",
10123
+ ...buildLoggingStatusSummary({
10124
+ level: action.level,
10125
+ settingsPath: input.settingsPath
10126
+ }).split(`
10127
+ `).slice(2)
10128
+ ].join(`
10129
+ `);
10130
+ }
10131
+ return [
10132
+ "## Claude Log Level Usage",
10133
+ "",
10134
+ LOGGING_USAGE,
10135
+ "",
10136
+ ...buildLoggingStatusSummary({
10137
+ level,
10138
+ settingsPath: input.settingsPath
10139
+ }).split(`
10140
+ `).slice(2)
10141
+ ].join(`
10142
+ `);
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 };
10062
10194
  }
10063
- return [
10064
- "## Claude Log Level Usage",
10065
- "",
10066
- LOGGING_USAGE,
10067
- "",
10068
- ...buildLoggingStatusSummary({
10069
- level,
10070
- settingsPath: input.settingsPath
10071
- }).split(`
10072
- `).slice(2)
10073
- ].join(`
10074
- `);
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 };
10075
10239
  }
10076
10240
  // src/model-remap.ts
10077
10241
  function getEnv(name) {
@@ -10120,6 +10284,130 @@ function remapRequestBodyModel(parsed) {
10120
10284
  parsed.model = remapped;
10121
10285
  return true;
10122
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
+ }
10123
10411
  // src/native-account-runtime.ts
10124
10412
  import { randomUUID as randomUUID15 } from "node:crypto";
10125
10413
 
@@ -10360,7 +10648,7 @@ function canonicalJson(value) {
10360
10648
  const encode = (item) => {
10361
10649
  if (Array.isArray(item))
10362
10650
  return `[${item.map(encode).join(",")}]`;
10363
- if (isRecord7(item))
10651
+ if (isRecord6(item))
10364
10652
  return `{${Object.keys(item).sort().map((key) => `${JSON.stringify(key)}:${encode(item[key])}`).join(",")}}`;
10365
10653
  return JSON.stringify(item);
10366
10654
  };
@@ -10370,12 +10658,12 @@ function canonicalDigest(value) {
10370
10658
  return createHash6("sha256").update(canonicalJson(value)).digest("hex");
10371
10659
  }
10372
10660
  function parseReservation(raw) {
10373
- 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)
10374
10662
  return;
10375
10663
  return { reservation: raw.reservation };
10376
10664
  }
10377
10665
  function parseStagedStamp(raw) {
10378
- 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")
10379
10667
  return;
10380
10668
  if (Object.keys(raw).some((key) => !["reservation", "label", "disabledReason", "providerState"].includes(key)))
10381
10669
  return;
@@ -10386,7 +10674,7 @@ function parseStagedStamp(raw) {
10386
10674
  return raw;
10387
10675
  }
10388
10676
  var PROVIDER_STATE_KEY = "commonAuthProviderState";
10389
- function isRecord7(value) {
10677
+ function isRecord6(value) {
10390
10678
  return value != null && typeof value === "object" && !Array.isArray(value);
10391
10679
  }
10392
10680
  var UNSAFE_IDS = new Set(["__proto__", "constructor", "prototype"]);
@@ -10450,7 +10738,7 @@ function providerStateDigest(codec, value) {
10450
10738
  function boundProviderStateDigest(account, credential, credentialEpoch, identity) {
10451
10739
  if (!credential || credentialEpoch === undefined)
10452
10740
  return;
10453
- if (!isRecord7(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
10741
+ if (!isRecord6(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
10454
10742
  return;
10455
10743
  const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
10456
10744
  if (!stamp || stamp.providerState === undefined || stamp.digest !== credentialDigest(credential) || stamp.credentialEpoch !== credentialEpoch || stamp.binding?.identity !== identity)
@@ -10461,7 +10749,7 @@ function isCredentialEpoch(value) {
10461
10749
  return Number.isSafeInteger(value) && value >= 1;
10462
10750
  }
10463
10751
  function parseStamp(raw) {
10464
- if (!isRecord7(raw))
10752
+ if (!isRecord6(raw))
10465
10753
  return;
10466
10754
  const epoch = raw.credentialEpoch;
10467
10755
  if (!isCredentialEpoch(epoch))
@@ -10486,7 +10774,7 @@ function parseStamp(raw) {
10486
10774
  if (!("binding" in raw))
10487
10775
  return "dispatch" in raw || "replace" in raw || "providerState" in raw || "staged" in raw ? undefined : { credentialEpoch: epoch, digest: raw.digest };
10488
10776
  const binding = raw.binding;
10489
- if (!isRecord7(binding))
10777
+ if (!isRecord6(binding))
10490
10778
  return;
10491
10779
  if ("identity" in binding && (typeof binding.identity !== "string" || !binding.identity))
10492
10780
  return;
@@ -10517,7 +10805,7 @@ function bindingAgrees(binding, credential, identity) {
10517
10805
  function stampStatusOf(credential, credentialEpoch, identity, account) {
10518
10806
  if (!credential)
10519
10807
  return "none";
10520
- if (!isRecord7(account) || !Object.hasOwn(account, CREDENTIAL_STAMP_KEY))
10808
+ if (!isRecord6(account) || !Object.hasOwn(account, CREDENTIAL_STAMP_KEY))
10521
10809
  return "missing";
10522
10810
  const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
10523
10811
  if (!stamp)
@@ -10540,7 +10828,7 @@ function classifyConfig(read) {
10540
10828
  if ("parseError" in read)
10541
10829
  return { status: "error", reason: "config file is not valid JSON" };
10542
10830
  const value = read.value;
10543
- if (!isRecord7(value))
10831
+ if (!isRecord6(value))
10544
10832
  return { status: "error", reason: "config root is not an object" };
10545
10833
  if ("accounts" in value && !Array.isArray(value.accounts))
10546
10834
  return { status: "error", reason: "config accounts is not an array" };
@@ -10548,7 +10836,7 @@ function classifyConfig(read) {
10548
10836
  return Array.isArray(value.accounts) ? { status: "pending-migration", config: value } : { status: "ready", exists: true, config: value };
10549
10837
  }
10550
10838
  const pool = value[POOL_KEY];
10551
- if (!isRecord7(pool))
10839
+ if (!isRecord6(pool))
10552
10840
  return { status: "error", reason: `${POOL_KEY} is not an object` };
10553
10841
  const version = pool.schemaVersion;
10554
10842
  if (typeof version !== "number" || !Number.isInteger(version) || version < 1)
@@ -10558,7 +10846,7 @@ function classifyConfig(read) {
10558
10846
  status: "error",
10559
10847
  reason: `${POOL_KEY}.schemaVersion ${version} is newer than ${POOL_SCHEMA_VERSION}`
10560
10848
  };
10561
- if (POOL_ROWS_KEY in pool && !isRecord7(pool[POOL_ROWS_KEY]))
10849
+ if (POOL_ROWS_KEY in pool && !isRecord6(pool[POOL_ROWS_KEY]))
10562
10850
  return {
10563
10851
  status: "error",
10564
10852
  reason: `${POOL_KEY}.${POOL_ROWS_KEY} is not an object`
@@ -10570,9 +10858,9 @@ function classifyState(read) {
10570
10858
  return { status: "ready", exists: false, state: {} };
10571
10859
  if ("parseError" in read)
10572
10860
  return { status: "error", reason: "state file is not valid JSON" };
10573
- if (!isRecord7(read.value))
10861
+ if (!isRecord6(read.value))
10574
10862
  return { status: "error", reason: "state root is not an object" };
10575
- if ("accounts" in read.value && !isRecord7(read.value.accounts))
10863
+ if ("accounts" in read.value && !isRecord6(read.value.accounts))
10576
10864
  return { status: "error", reason: "state accounts is not an object" };
10577
10865
  return { status: "ready", exists: true, state: read.value };
10578
10866
  }
@@ -10581,16 +10869,16 @@ function rosterOf(config) {
10581
10869
  }
10582
10870
  function entriesOf(config) {
10583
10871
  const pool = config[POOL_KEY];
10584
- if (!isRecord7(pool))
10872
+ if (!isRecord6(pool))
10585
10873
  return {};
10586
10874
  const rows = pool[POOL_ROWS_KEY];
10587
- return isRecord7(rows) ? rows : {};
10875
+ return isRecord6(rows) ? rows : {};
10588
10876
  }
10589
10877
  function stateAccountsOf(state) {
10590
- return isRecord7(state.accounts) ? state.accounts : {};
10878
+ return isRecord6(state.accounts) ? state.accounts : {};
10591
10879
  }
10592
10880
  function rosterRowProblem(raw) {
10593
- if (!isRecord7(raw))
10881
+ if (!isRecord6(raw))
10594
10882
  return "not an object";
10595
10883
  const problem = idProblem(raw.id);
10596
10884
  if (problem)
@@ -10602,7 +10890,7 @@ function rosterRowProblem(raw) {
10602
10890
  return "unknown type";
10603
10891
  }
10604
10892
  function parseEntry(raw, codec) {
10605
- if (!isRecord7(raw))
10893
+ if (!isRecord6(raw))
10606
10894
  return;
10607
10895
  const epoch = raw.credentialEpoch;
10608
10896
  if (!isCredentialEpoch(epoch))
@@ -10624,7 +10912,7 @@ function parseEntry(raw, codec) {
10624
10912
  };
10625
10913
  }
10626
10914
  function credentialFor(raw, stateEntry) {
10627
- if (!isRecord7(stateEntry))
10915
+ if (!isRecord6(stateEntry))
10628
10916
  return;
10629
10917
  if (raw.type === "api") {
10630
10918
  const apiKey = typeof stateEntry.apiKey === "string" ? stateEntry.apiKey.trim() : "";
@@ -10651,23 +10939,23 @@ function credentialFor(raw, stateEntry) {
10651
10939
  };
10652
10940
  }
10653
10941
  function rosterRowIn(config, id) {
10654
- return rosterOf(config).find((raw) => isRecord7(raw) && raw.id === id);
10942
+ return rosterOf(config).find((raw) => isRecord6(raw) && raw.id === id);
10655
10943
  }
10656
10944
  function ensurePool(config) {
10657
- if (!isRecord7(config[POOL_KEY]))
10945
+ if (!isRecord6(config[POOL_KEY]))
10658
10946
  config[POOL_KEY] = {};
10659
10947
  return config[POOL_KEY];
10660
10948
  }
10661
10949
  function ensureEntries(config) {
10662
10950
  const pool = ensurePool(config);
10663
- if (!isRecord7(pool[POOL_ROWS_KEY]))
10951
+ if (!isRecord6(pool[POOL_ROWS_KEY]))
10664
10952
  pool[POOL_ROWS_KEY] = {};
10665
10953
  return pool[POOL_ROWS_KEY];
10666
10954
  }
10667
10955
  function entryIn(config, id) {
10668
10956
  const entries = entriesOf(config);
10669
10957
  const entry = Object.hasOwn(entries, id) ? entries[id] : undefined;
10670
- return isRecord7(entry) ? entry : undefined;
10958
+ return isRecord6(entry) ? entry : undefined;
10671
10959
  }
10672
10960
  function setEntryIn(config, id, entry) {
10673
10961
  Object.defineProperty(ensureEntries(config), id, {
@@ -10679,10 +10967,10 @@ function setEntryIn(config, id, entry) {
10679
10967
  }
10680
10968
  function retiredEpochIn(config, id) {
10681
10969
  const pool = config[POOL_KEY];
10682
- if (!isRecord7(pool))
10970
+ if (!isRecord6(pool))
10683
10971
  return;
10684
10972
  const retired = pool[POOL_RETIRED_EPOCHS_KEY];
10685
- if (!isRecord7(retired) || !Object.hasOwn(retired, id))
10973
+ if (!isRecord6(retired) || !Object.hasOwn(retired, id))
10686
10974
  return;
10687
10975
  const epoch = retired[id];
10688
10976
  return isCredentialEpoch(epoch) ? epoch : undefined;
@@ -10699,7 +10987,7 @@ function retireEpochsIn(config, dropped) {
10699
10987
  if (ids.length === 0)
10700
10988
  return;
10701
10989
  const pool = ensurePool(config);
10702
- 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] : {};
10703
10991
  const next = {};
10704
10992
  const define = (id, epoch) => Object.defineProperty(next, id, {
10705
10993
  value: epoch,
@@ -10721,17 +11009,17 @@ function buildRawRows(config, state, codec, providerCodec) {
10721
11009
  const rows = [];
10722
11010
  for (const raw of rosterOf(config)) {
10723
11011
  const problem = rosterRowProblem(raw);
10724
- const id = isRecord7(raw) && typeof raw.id === "string" ? raw.id : undefined;
11012
+ const id = isRecord6(raw) && typeof raw.id === "string" ? raw.id : undefined;
10725
11013
  const rawEntry = id === undefined ? undefined : entries[id];
10726
- const reserved = isRecord7(rawEntry) && Object.hasOwn(rawEntry, "staged");
11014
+ const reserved = isRecord6(rawEntry) && Object.hasOwn(rawEntry, "staged");
10727
11015
  const staged = reserved ? parseReservation(rawEntry.staged) : undefined;
10728
- if (problem || !isRecord7(raw) || id === undefined || seen.has(id)) {
11016
+ if (problem || !isRecord6(raw) || id === undefined || seen.has(id)) {
10729
11017
  if (id !== undefined && !seen.has(id))
10730
11018
  seen.add(id);
10731
11019
  if (id !== undefined)
10732
11020
  rows.push({
10733
11021
  id,
10734
- type: isRecord7(raw) && raw.type === "api" ? "api" : "oauth",
11022
+ type: isRecord6(raw) && raw.type === "api" ? "api" : "oauth",
10735
11023
  enabled: false,
10736
11024
  needsFirstReading: true,
10737
11025
  hasEntry: Object.hasOwn(entries, id),
@@ -10778,7 +11066,7 @@ function buildRawRows(config, state, codec, providerCodec) {
10778
11066
  return rows;
10779
11067
  }
10780
11068
  function providerStateFields(account, credential, credentialEpoch, identity, codec) {
10781
- if (!isRecord7(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
11069
+ if (!isRecord6(account) || !Object.hasOwn(account, PROVIDER_STATE_KEY))
10782
11070
  return {};
10783
11071
  const digest = boundProviderStateDigest(account, credential, credentialEpoch, identity);
10784
11072
  if (digest === undefined)
@@ -10838,7 +11126,7 @@ function storedCredential(credential, lastRefreshedAt) {
10838
11126
  };
10839
11127
  }
10840
11128
  function credentialProblem(credential, options = {}) {
10841
- if (!isRecord7(credential))
11129
+ if (!isRecord6(credential))
10842
11130
  return "credential must be an object";
10843
11131
  if (credential.type === "oauth") {
10844
11132
  if (typeof credential.refresh !== "string" || !credential.refresh.trim())
@@ -10862,10 +11150,10 @@ function credentialProblem(credential, options = {}) {
10862
11150
  var TRANSITION_STAMP_KEY = "transition";
10863
11151
  var TRANSITION_MARK_KEY = "transitionMark";
10864
11152
  function stampedTransition(rawStamp) {
10865
- if (!isRecord7(rawStamp))
11153
+ if (!isRecord6(rawStamp))
10866
11154
  return;
10867
11155
  const raw = rawStamp[TRANSITION_STAMP_KEY];
10868
- if (!isRecord7(raw))
11156
+ if (!isRecord6(raw))
10869
11157
  return;
10870
11158
  if (typeof raw.mark !== "string" || raw.mark.length === 0)
10871
11159
  return;
@@ -10908,13 +11196,13 @@ function isReplaceStamp(stamp) {
10908
11196
  return stamp.replace === true || stamp.dispatch === undefined;
10909
11197
  }
10910
11198
  function tornStamps(config, state, codec, options = {}) {
10911
- const accounts = isRecord7(state.accounts) ? state.accounts : {};
11199
+ const accounts = isRecord6(state.accounts) ? state.accounts : {};
10912
11200
  const torn = new Map;
10913
11201
  for (const row of buildRawRows(config, state, codec)) {
10914
11202
  if (row.invalid || row.staged || !row.credential)
10915
11203
  continue;
10916
11204
  const account = Object.hasOwn(accounts, row.id) ? accounts[row.id] : undefined;
10917
- if (!isRecord7(account))
11205
+ if (!isRecord6(account))
10918
11206
  continue;
10919
11207
  const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
10920
11208
  if (!stamp?.binding)
@@ -11119,7 +11407,7 @@ class Transaction {
11119
11407
  return entry && Object.hasOwn(entry, "staged") ? entry.staged : undefined;
11120
11408
  }
11121
11409
  const stamp = this.stateAccount(id)?.[CREDENTIAL_STAMP_KEY];
11122
- return isRecord7(stamp) && Object.hasOwn(stamp, "staged") ? stamp.staged : undefined;
11410
+ return isRecord6(stamp) && Object.hasOwn(stamp, "staged") ? stamp.staged : undefined;
11123
11411
  }
11124
11412
  assertNotStaged(id) {
11125
11413
  assertNotReserved(this.info.operation, id, this.reservation(id));
@@ -11135,7 +11423,7 @@ class Transaction {
11135
11423
  }
11136
11424
  dropRosterRows(id) {
11137
11425
  const roster = this.roster();
11138
- const kept = roster.filter((raw) => !(isRecord7(raw) && raw.id === id));
11426
+ const kept = roster.filter((raw) => !(isRecord6(raw) && raw.id === id));
11139
11427
  this.config.accounts = kept;
11140
11428
  return roster.length - kept.length;
11141
11429
  }
@@ -11157,16 +11445,16 @@ class Transaction {
11157
11445
  await this.commitConfig({ counted: false });
11158
11446
  }
11159
11447
  stateAccount(id) {
11160
- const accounts = isRecord7(this.state.accounts) ? this.state.accounts : {};
11448
+ const accounts = isRecord6(this.state.accounts) ? this.state.accounts : {};
11161
11449
  const entry = Object.hasOwn(accounts, id) ? accounts[id] : undefined;
11162
- return isRecord7(entry) ? entry : undefined;
11450
+ return isRecord6(entry) ? entry : undefined;
11163
11451
  }
11164
11452
  dropStateAccount(id) {
11165
- if (isRecord7(this.state.accounts) && Object.hasOwn(this.state.accounts, id))
11453
+ if (isRecord6(this.state.accounts) && Object.hasOwn(this.state.accounts, id))
11166
11454
  delete this.state.accounts[id];
11167
11455
  }
11168
11456
  setStateAccount(id, fields) {
11169
- if (!isRecord7(this.state.accounts))
11457
+ if (!isRecord6(this.state.accounts))
11170
11458
  this.state.accounts = {};
11171
11459
  Object.defineProperty(this.state.accounts, id, {
11172
11460
  value: fields,
@@ -11179,11 +11467,11 @@ class Transaction {
11179
11467
  const roster = this.roster();
11180
11468
  const rosterIds = new Set;
11181
11469
  for (const raw of roster)
11182
- if (isRecord7(raw) && typeof raw.id === "string")
11470
+ if (isRecord6(raw) && typeof raw.id === "string")
11183
11471
  rosterIds.add(raw.id);
11184
11472
  const dropped = new Set;
11185
11473
  for (const raw of rosterOf(this.snapshot.config))
11186
- if (isRecord7(raw) && typeof raw.id === "string" && !rosterIds.has(raw.id))
11474
+ if (isRecord6(raw) && typeof raw.id === "string" && !rosterIds.has(raw.id))
11187
11475
  dropped.add(raw.id);
11188
11476
  for (const id of Object.keys(this.entries()))
11189
11477
  if (!rosterIds.has(id))
@@ -11225,7 +11513,7 @@ class Transaction {
11225
11513
  const next = {
11226
11514
  ...this.state,
11227
11515
  version: LEGACY_STORE_VERSION,
11228
- accounts: isRecord7(this.state.accounts) ? this.state.accounts : {}
11516
+ accounts: isRecord6(this.state.accounts) ? this.state.accounts : {}
11229
11517
  };
11230
11518
  await this.write(this.ctx.statePath, next, "state", true, options.durable ?? false);
11231
11519
  this.state = next;
@@ -11420,11 +11708,11 @@ async function readRow(rt, operation, id) {
11420
11708
  const row = result.rows.find((candidate) => candidate.id === id);
11421
11709
  const entry = entryIn(result.config, id);
11422
11710
  const accounts = result.state.accounts;
11423
- const account = isRecord7(accounts) && Object.hasOwn(accounts, id) ? accounts[id] : undefined;
11424
- 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;
11425
11713
  if (row && !["enable", "disable"].includes(operation) && entry && Object.hasOwn(entry, "staged"))
11426
11714
  assertNotReserved(operation, id, entry.staged);
11427
- if (!row && isRecord7(stamp) && Object.hasOwn(stamp, "staged"))
11715
+ if (!row && isRecord6(stamp) && Object.hasOwn(stamp, "staged"))
11428
11716
  assertNotReserved(operation, id, stamp.staged);
11429
11717
  if (!row)
11430
11718
  throw unknownRow(operation, id);
@@ -11556,7 +11844,7 @@ async function updateProviderStateRow(rt, id, fence, mutator, options = {}) {
11556
11844
  throw refusal(operation, id, "invalid-input", "the store was opened without a provider-state codec");
11557
11845
  if (typeof mutator !== "function")
11558
11846
  throw refusal(operation, id, "invalid-input", "a mutator is required");
11559
- const captured = isRecord7(fence) ? fence.credentialEpoch : undefined;
11847
+ const captured = isRecord6(fence) ? fence.credentialEpoch : undefined;
11560
11848
  if (!isCredentialEpoch(captured))
11561
11849
  throw refusal(operation, id, "invalid-input", "the credential epoch the provider state was read at is required");
11562
11850
  const { row: seen } = await readRow(rt, operation, id);
@@ -11600,7 +11888,7 @@ async function planProviderStateIn(tx, codec, operation, row, mutator, declinabl
11600
11888
  const account = tx.stateAccount(id);
11601
11889
  const rawStamp = account?.[CREDENTIAL_STAMP_KEY];
11602
11890
  const stamp = parseStamp(rawStamp);
11603
- 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)
11604
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`);
11605
11893
  const current = row.providerState === undefined ? undefined : structuredClone(row.providerState);
11606
11894
  const returned = await runInsideHook(operation, () => mutator(current, row));
@@ -11676,7 +11964,7 @@ function onRowEndpoint(tx, id, credential) {
11676
11964
  if (credential.type !== "api")
11677
11965
  return credential;
11678
11966
  const raw = tx.rosterRow(id);
11679
- if (!isRecord7(raw)) {
11967
+ if (!isRecord6(raw)) {
11680
11968
  if (credential.baseURL === undefined)
11681
11969
  throw refusal(tx.info.operation, id, "invalid-input", "api credential needs a valid baseURL");
11682
11970
  return { ...credential, baseURL: credential.baseURL };
@@ -11695,7 +11983,7 @@ function onRowEndpoint(tx, id, credential) {
11695
11983
  function bindingInTx(tx, id, stored, learnt) {
11696
11984
  const raw = tx.rosterRow(id);
11697
11985
  const projected = tx.row(id);
11698
- 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);
11699
11987
  return {
11700
11988
  ...identity !== undefined ? { identity } : {},
11701
11989
  ...stored.type === "api" ? {
@@ -11779,7 +12067,7 @@ function requireUsableRow(operation, id, row, credential) {
11779
12067
  return row;
11780
12068
  }
11781
12069
  function validateAttribution(operation, id, fence) {
11782
- if (fence !== undefined && !isCredentialEpoch(isRecord7(fence) ? fence.credentialEpoch : undefined))
12070
+ if (fence !== undefined && !isCredentialEpoch(isRecord6(fence) ? fence.credentialEpoch : undefined))
11783
12071
  throw refusal(operation, id, "invalid-input", "the attribution must name a credential epoch that is a positive safe integer");
11784
12072
  }
11785
12073
  function assertRowAttribution(operation, id, row, fence) {
@@ -11934,7 +12222,7 @@ async function addRow(rt, input, options = {}) {
11934
12222
  const mode = options.onExisting ?? "rotate";
11935
12223
  if (input.stage !== undefined && mode === "rotate")
11936
12224
  throw refusal("add", id, "invalid-input", "a staged add needs onExisting: 'refuse' or 'stage-duplicate'");
11937
- 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))
11938
12226
  throw refusal("add", id, "invalid-input", "staging requires a reservation and a disabled reason");
11939
12227
  const incoming = input.providerState === undefined ? undefined : acceptProviderState(ctx.providerState, "add", id, input.providerState);
11940
12228
  await locks.acquire(rowLockSpec(rt, { id, identity }));
@@ -11944,12 +12232,12 @@ async function addRow(rt, input, options = {}) {
11944
12232
  await locks.acquire(extra);
11945
12233
  return withTransaction(ctx, locks, progress, { operation: "add", rowId: id }, async (tx) => {
11946
12234
  await protectIn(tx, id, options.protect);
11947
- const stateAccounts = isRecord7(tx.state.accounts) ? tx.state.accounts : {};
12235
+ const stateAccounts = isRecord6(tx.state.accounts) ? tx.state.accounts : {};
11948
12236
  const stagedOrphan = Object.entries(stateAccounts).find(([orphanId, account]) => {
11949
- if (orphanId === id || tx.rosterRow(orphanId) || !isRecord7(account))
12237
+ if (orphanId === id || tx.rosterRow(orphanId) || !isRecord6(account))
11950
12238
  return false;
11951
12239
  const stamp = account[CREDENTIAL_STAMP_KEY];
11952
- if (!isRecord7(stamp) || !Object.hasOwn(stamp, "staged"))
12240
+ if (!isRecord6(stamp) || !Object.hasOwn(stamp, "staged"))
11953
12241
  return false;
11954
12242
  return credential.type === "oauth" ? account.refresh === credential.refresh : typeof account.apiKey === "string" && account.apiKey.trim() === credential.apiKey.trim();
11955
12243
  });
@@ -11967,9 +12255,9 @@ async function addRow(rt, input, options = {}) {
11967
12255
  }
11968
12256
  if (mode === "refuse") {
11969
12257
  const holder = tx.rows().find((row) => row.fingerprint === fingerprintOf(credential) || row.id === id && row.credential);
11970
- const accounts = isRecord7(tx.state.accounts) ? tx.state.accounts : {};
12258
+ const accounts = isRecord6(tx.state.accounts) ? tx.state.accounts : {};
11971
12259
  const stateHolder = Object.entries(accounts).find(([, account]) => {
11972
- if (!isRecord7(account))
12260
+ if (!isRecord6(account))
11973
12261
  return false;
11974
12262
  if (credential.type === "oauth")
11975
12263
  return account.refresh === credential.refresh;
@@ -12302,7 +12590,7 @@ async function removeRow(rt, id, options = {}) {
12302
12590
  throw refusal("remove", id, "invalid-input", "id must be non-empty");
12303
12591
  const fence = options.attribution;
12304
12592
  validateAttribution("remove", id, fence);
12305
- 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))
12306
12594
  throw refusal("remove", id, "invalid-input", "a staged removal needs a reservation");
12307
12595
  const result = await readPool(ctx);
12308
12596
  if (result.status !== "ready")
@@ -12317,7 +12605,7 @@ async function removeRow(rt, id, options = {}) {
12317
12605
  return withTransaction(ctx, locks, progress, { operation: "remove", rowId: id }, async (tx) => {
12318
12606
  const reservation = tx.reservation(id);
12319
12607
  if (reservation !== undefined) {
12320
- if (!isRecord7(reservation) || !options.staged || reservation.reservation !== options.staged.reservation)
12608
+ if (!isRecord6(reservation) || !options.staged || reservation.reservation !== options.staged.reservation)
12321
12609
  throw refusal("remove", id, "row-staged", `row ${id} is reserved for roster publication`);
12322
12610
  } else if (options.staged)
12323
12611
  throw refusal("remove", id, "attribution", `row ${id} is no longer reserved`);
@@ -12405,10 +12693,10 @@ function assertOrphanAttribution(rt, tx, id, fence) {
12405
12693
  }
12406
12694
  function hasStateAccount(state, id) {
12407
12695
  const accounts = state.accounts;
12408
- return isRecord7(accounts) && Object.hasOwn(accounts, id);
12696
+ return isRecord6(accounts) && Object.hasOwn(accounts, id);
12409
12697
  }
12410
12698
  function rosterIdOf(raw) {
12411
- return isRecord7(raw) && typeof raw.id === "string" ? raw.id : undefined;
12699
+ return isRecord6(raw) && typeof raw.id === "string" ? raw.id : undefined;
12412
12700
  }
12413
12701
  function orderProblem(roster, ids) {
12414
12702
  if (!Array.isArray(ids))
@@ -12483,7 +12771,7 @@ async function recordRowIdentity(rt, id, identity, attribution, options = {}) {
12483
12771
  return runOperation(rt.ctx, "recordIdentity", id, options.onFailure, async (locks, progress) => {
12484
12772
  if (typeof identity !== "string" || identity.length === 0)
12485
12773
  throw refusal("recordIdentity", id, "invalid-input", "identity must be non-empty");
12486
- const captured = isRecord7(attribution) ? attribution.credentialEpoch : undefined;
12774
+ const captured = isRecord6(attribution) ? attribution.credentialEpoch : undefined;
12487
12775
  if (!isCredentialEpoch(captured))
12488
12776
  throw refusal("recordIdentity", id, "invalid-input", "the credential epoch the identity lookup was issued for is required");
12489
12777
  const { row: seen } = await readRow(rt, "recordIdentity", id);
@@ -12512,14 +12800,14 @@ async function recordRowIdentity(rt, id, identity, attribution, options = {}) {
12512
12800
  // ../../node_modules/@cortexkit/common-auth/dist/store/publication.js
12513
12801
  function receiptsIn(config) {
12514
12802
  const pool = config[POOL_KEY];
12515
- return isRecord7(pool) && isRecord7(pool.publications) ? pool.publications : {};
12803
+ return isRecord6(pool) && isRecord6(pool.publications) ? pool.publications : {};
12516
12804
  }
12517
12805
  function receiptIn(config, operationId) {
12518
12806
  const receipts = receiptsIn(config);
12519
12807
  if (!Object.hasOwn(receipts, operationId))
12520
12808
  return;
12521
12809
  const raw = receipts[operationId];
12522
- 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"))
12523
12811
  throw refusal("publishRoster", operationId, "invalid-input", "the stored publication receipt is malformed");
12524
12812
  return structuredClone(raw);
12525
12813
  }
@@ -12533,11 +12821,11 @@ function validatePlan(rt, plan) {
12533
12821
  const fail = () => {
12534
12822
  throw refusal("publishRoster", plan?.operationId ?? "", "invalid-input", "the publication plan is invalid");
12535
12823
  };
12536
- 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))
12537
12825
  fail();
12538
12826
  const ids = new Set;
12539
12827
  for (const ref of [...plan.remove, ...plan.finalize]) {
12540
- 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)
12541
12829
  fail();
12542
12830
  ids.add(ref.id);
12543
12831
  validateAttribution("publishRoster", ref.id, ref.attribution);
@@ -12569,7 +12857,7 @@ function saveReceipt(tx, receipt) {
12569
12857
  function publicationSurvivors(tx, plan, rows) {
12570
12858
  const rosterIds = new Set;
12571
12859
  for (const raw of rosterOf(tx.config)) {
12572
- if (!isRecord7(raw) || typeof raw.id !== "string")
12860
+ if (!isRecord6(raw) || typeof raw.id !== "string")
12573
12861
  continue;
12574
12862
  if (rosterIds.has(raw.id))
12575
12863
  throw refusal("publishRoster", plan.operationId, "invalid-input", "publication needs a roster of unique named rows");
@@ -12608,14 +12896,14 @@ async function cleanup(tx, receipt) {
12608
12896
  async function publishRoster(rt, plan, options = {}) {
12609
12897
  assertNotInsideHook("publishRoster");
12610
12898
  return runOperation(rt.ctx, "publishRoster", plan?.operationId ?? "", options.onFailure, async (locks, progress) => {
12611
- if (!isRecord7(plan) || typeof plan.operationId !== "string" || !plan.operationId)
12899
+ if (!isRecord6(plan) || typeof plan.operationId !== "string" || !plan.operationId)
12612
12900
  throw refusal("publishRoster", plan?.operationId ?? "", "invalid-input", "the publication needs an operation id");
12613
12901
  plan = structuredClone(plan);
12614
12902
  const planDigest = canonicalDigest(plan);
12615
12903
  const named = [
12616
12904
  ...Array.isArray(plan.remove) ? plan.remove : [],
12617
12905
  ...Array.isArray(plan.finalize) ? plan.finalize : []
12618
- ].filter((ref) => isRecord7(ref) && typeof ref.id === "string");
12906
+ ].filter((ref) => isRecord6(ref) && typeof ref.id === "string");
12619
12907
  for (let attempt = 0;; attempt++) {
12620
12908
  const seen = await readPool(rt.ctx);
12621
12909
  if (seen.status !== "ready")
@@ -12719,7 +13007,7 @@ async function publishRoster(rt, plan, options = {}) {
12719
13007
  entry.disabledReason = ref.disabledReason;
12720
13008
  tx.setEntry(ref.id, entry);
12721
13009
  }
12722
- 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");
12723
13011
  tx.config.accounts = [
12724
13012
  ...plan.order.map((id) => tx.rosterRow(id)),
12725
13013
  ...preserved
@@ -13093,7 +13381,7 @@ async function updatePoolSettings(rt, mutator, options = {}) {
13093
13381
  const draft = structuredClone(current);
13094
13382
  const returned = await runInsideHook("updateSettings", () => mutator(draft));
13095
13383
  const next = returned === undefined ? draft : returned;
13096
- if (!isRecord7(next))
13384
+ if (!isRecord6(next))
13097
13385
  throw settingsRefusal("the settings mutator must produce an object");
13098
13386
  const owned = POOL_OWNED_KEYS.filter((key) => Object.hasOwn(next, key));
13099
13387
  if (owned.length > 0)
@@ -13230,7 +13518,7 @@ function entryTime(entry) {
13230
13518
  function limitKey(scope, label) {
13231
13519
  return JSON.stringify([scope, label]);
13232
13520
  }
13233
- function isRecord8(value) {
13521
+ function isRecord7(value) {
13234
13522
  return typeof value === "object" && value !== null && !Array.isArray(value);
13235
13523
  }
13236
13524
  function isFiniteNumber(value) {
@@ -13249,7 +13537,7 @@ function isString(value) {
13249
13537
  return typeof value === "string";
13250
13538
  }
13251
13539
  function isQuotaEntry(value) {
13252
- if (!isRecord8(value) || !isName(value.scope) || !isName(value.label)) {
13540
+ if (!isRecord7(value) || !isName(value.scope) || !isName(value.label)) {
13253
13541
  return false;
13254
13542
  }
13255
13543
  switch (value.kind) {
@@ -13264,26 +13552,26 @@ function isQuotaEntry(value) {
13264
13552
  }
13265
13553
  }
13266
13554
  function isCreditBudgetEntry(value) {
13267
- if (!isRecord8(value) || !isFiniteNumber(value.checkedAt))
13555
+ if (!isRecord7(value) || !isFiniteNumber(value.checkedAt))
13268
13556
  return false;
13269
13557
  if (value.kind === "cleared")
13270
13558
  return true;
13271
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);
13272
13560
  }
13273
13561
  function isQuotaCounter(value) {
13274
- 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);
13275
13563
  }
13276
13564
  function isQuotaCounters(value) {
13277
- return isRecord8(value) && Object.values(value).every(isQuotaCounter);
13565
+ return isRecord7(value) && Object.values(value).every(isQuotaCounter);
13278
13566
  }
13279
13567
  function isBoolean(value) {
13280
13568
  return typeof value === "boolean";
13281
13569
  }
13282
13570
  function isQuotaCredits(value) {
13283
- return isRecord8(value) && typeof value.hasCredits === "boolean" && typeof value.unlimited === "boolean" && optional(value, "balance", isFiniteNumber) && optional(value, "overageLimitReached", isBoolean) && isFiniteNumber(value.checkedAt);
13571
+ return isRecord7(value) && typeof value.hasCredits === "boolean" && typeof value.unlimited === "boolean" && optional(value, "balance", isFiniteNumber) && optional(value, "overageLimitReached", isBoolean) && isFiniteNumber(value.checkedAt);
13284
13572
  }
13285
13573
  function readQuotaCounters(value) {
13286
- if (!isRecord8(value))
13574
+ if (!isRecord7(value))
13287
13575
  return;
13288
13576
  const entries = Object.entries(value).filter(([, entry]) => isQuotaCounter(entry));
13289
13577
  return entries.length === 0 ? undefined : Object.fromEntries(entries);
@@ -13291,7 +13579,7 @@ function readQuotaCounters(value) {
13291
13579
  function decodeQuotaMap(value) {
13292
13580
  if (isQuotaMap(value))
13293
13581
  return value;
13294
- if (!isRecord8(value))
13582
+ if (!isRecord7(value))
13295
13583
  return;
13296
13584
  const { counters: rawCounters, credits: rawCredits, ...rest } = value;
13297
13585
  if (!isQuotaMap(rest))
@@ -13305,7 +13593,7 @@ function decodeQuotaMap(value) {
13305
13593
  };
13306
13594
  }
13307
13595
  function isQuotaMap(value) {
13308
- if (!isRecord8(value) || !Array.isArray(value.limits))
13596
+ if (!isRecord7(value) || !Array.isArray(value.limits))
13309
13597
  return false;
13310
13598
  const seen = new Set;
13311
13599
  for (const entry of value.limits) {
@@ -13326,7 +13614,7 @@ class QuotaCodecError extends TypeError {
13326
13614
  this.name = "QuotaCodecError";
13327
13615
  }
13328
13616
  }
13329
- function isRecord9(value) {
13617
+ function isRecord8(value) {
13330
13618
  return typeof value === "object" && value !== null && !Array.isArray(value);
13331
13619
  }
13332
13620
  function isFiniteNumber2(value) {
@@ -13345,20 +13633,20 @@ function optionalString(record, key) {
13345
13633
  return record[key] === undefined || typeof record[key] === "string";
13346
13634
  }
13347
13635
  function isObservedReading(value) {
13348
- 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);
13349
13637
  }
13350
13638
  function isObservedPair(value) {
13351
- return isRecord9(value) && isScope(value.scope) && isLabel(value.label);
13639
+ return isRecord8(value) && isScope(value.scope) && isLabel(value.label);
13352
13640
  }
13353
13641
  function isObservedBudget(value) {
13354
- if (!isRecord9(value))
13642
+ if (!isRecord8(value))
13355
13643
  return false;
13356
13644
  if (value.kind === "cleared")
13357
13645
  return true;
13358
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");
13359
13647
  }
13360
13648
  function isQuotaObservation(value) {
13361
- if (!isRecord9(value) || !isFiniteNumber2(value.checkedAt))
13649
+ if (!isRecord8(value) || !isFiniteNumber2(value.checkedAt))
13362
13650
  return false;
13363
13651
  const readings = value.readings ?? [];
13364
13652
  const coverage = value.coverage ?? [];
@@ -13928,7 +14216,7 @@ var nativeQuotaCodec = {
13928
14216
  import { randomUUID as randomUUID12 } from "node:crypto";
13929
14217
  import { constants as constants2 } from "node:fs";
13930
14218
  import { lstat as lstat5, mkdir as mkdir9, open as open6, rename as rename11, rm as rm6 } from "node:fs/promises";
13931
- 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";
13932
14220
  import { types as utilTypes5 } from "node:util";
13933
14221
 
13934
14222
  // src/pool-binding.ts
@@ -15388,7 +15676,7 @@ async function writeNativeRuntimeOutcome(path2, storageId, change, hooks, firstI
15388
15676
  assertTransitions(current, next, firstIdentity);
15389
15677
  const bytes = `${JSON.stringify(next, null, 2)}
15390
15678
  `;
15391
- const stage = join11(dirname9(path2), `${basename4(path2)}.native-runtime.${randomUUID12()}.partial`);
15679
+ const stage = join12(dirname9(path2), `${basename4(path2)}.native-runtime.${randomUUID12()}.partial`);
15392
15680
  let ownsStage = false;
15393
15681
  try {
15394
15682
  const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
@@ -17988,15 +18276,15 @@ function vaultRoutingRows(roster) {
17988
18276
  ...row.quota !== undefined && { quota: row.quota }
17989
18277
  }));
17990
18278
  }
17991
- function isRecord10(value) {
18279
+ function isRecord9(value) {
17992
18280
  return typeof value === "object" && value !== null && !Array.isArray(value);
17993
18281
  }
17994
18282
  function optionalString2(value) {
17995
18283
  return value === undefined || typeof value === "string";
17996
18284
  }
17997
18285
  function decodeRow(value) {
17998
- const quota2 = isRecord10(value) ? decodeQuotaMap(value.quota) : undefined;
17999
- 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)
18000
18288
  return;
18001
18289
  return {
18002
18290
  ...value,
@@ -18014,14 +18302,14 @@ function decodeRejected(value) {
18014
18302
  return;
18015
18303
  const records = [];
18016
18304
  for (const entry2 of value) {
18017
- 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))
18018
18306
  return;
18019
18307
  records.push(entry2);
18020
18308
  }
18021
18309
  return records;
18022
18310
  }
18023
18311
  function decodeRoster(value) {
18024
- 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))
18025
18313
  throw new ClaustrumConsumerError("invalid-state", "Claustrum roster file is not valid");
18026
18314
  const rows = [];
18027
18315
  for (const entry2 of value.rows) {
@@ -18032,7 +18320,7 @@ function decodeRoster(value) {
18032
18320
  }
18033
18321
  const declined = [];
18034
18322
  for (const entry2 of value.declined) {
18035
- if (!isRecord10(entry2) || typeof entry2.credentialId !== "string" || !optionalString2(entry2.accountIdentity))
18323
+ if (!isRecord9(entry2) || typeof entry2.credentialId !== "string" || !optionalString2(entry2.accountIdentity))
18036
18324
  throw new ClaustrumConsumerError("invalid-state", "Claustrum roster file is not valid");
18037
18325
  declined.push(entry2);
18038
18326
  }
@@ -18908,10 +19196,10 @@ function nativeCode(value) {
18908
19196
  class NativeCustodyError extends Error {
18909
19197
  code;
18910
19198
  constructor(code) {
18911
- const safeCode = nativeCode(code);
18912
- super(`Native custody refused: ${safeCode}`);
19199
+ const safeCode2 = nativeCode(code);
19200
+ super(`Native custody refused: ${safeCode2}`);
18913
19201
  this.name = "NativeCustodyError";
18914
- this.code = safeCode;
19202
+ this.code = safeCode2;
18915
19203
  }
18916
19204
  }
18917
19205
  function createNativeCustody(options) {
@@ -19193,9 +19481,18 @@ var reasons = new Set([
19193
19481
  "ETIMEDOUT",
19194
19482
  "ERR_PRIVATE_FILES_SECURITY"
19195
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
+ ]);
19196
19492
  async function logRefusal(host, paths, readStatus) {
19197
19493
  let stage = "enrollment";
19198
19494
  let reason = "unreadable";
19495
+ let unavailable = false;
19199
19496
  try {
19200
19497
  await readStatus(paths, `anthropic-auth-${host}`);
19201
19498
  } catch (error) {
@@ -19204,17 +19501,31 @@ async function logRefusal(host, paths, readStatus) {
19204
19501
  const detail = current;
19205
19502
  if (detail.stage && stages.has(detail.stage))
19206
19503
  stage = detail.stage;
19207
- for (const value of [detail.kind, detail.code, detail.reason])
19504
+ for (const value of [detail.kind, detail.code, detail.reason]) {
19208
19505
  if (value && reasons.has(value))
19209
19506
  reason = value;
19507
+ if (value && addonUnavailable.has(value))
19508
+ unavailable = true;
19509
+ }
19210
19510
  current = detail.cause;
19211
19511
  }
19212
19512
  }
19513
+ if (unavailable)
19514
+ reason = "native-addon-unavailable";
19213
19515
  logger.warn("enrollment", "Native enrollment authority refused", {
19214
19516
  host,
19215
19517
  stage,
19216
19518
  reason
19217
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
+ }
19218
19529
  }
19219
19530
  async function readNativeEnrollmentMode(host, env = process.env, dependencies = { enrollmentAuthority, readClaustrumEnrollmentStatus }) {
19220
19531
  const paths = getHostClaustrumEnrollmentPaths(host, env);
@@ -19222,7 +19533,9 @@ async function readNativeEnrollmentMode(host, env = process.env, dependencies =
19222
19533
  if (authority !== "vault")
19223
19534
  closeNativeVaultAuthority(getHostClaustrumEnrollmentPaths(host, env).tokenPath);
19224
19535
  if (authority === "unreadable") {
19225
- await logRefusal(host, paths, dependencies.readClaustrumEnrollmentStatus);
19536
+ const reason = await logRefusal(host, paths, dependencies.readClaustrumEnrollmentStatus);
19537
+ if (privateFilesUnavailableReasons.has(reason))
19538
+ throw new NativePrivateFilesUnavailableError;
19226
19539
  throw new NativeCustodyError("invalid-token");
19227
19540
  }
19228
19541
  return authority === "vault" ? "claustrum" : "local";
@@ -20236,7 +20549,7 @@ class NativeMigrationSourceError extends Error {
20236
20549
  }
20237
20550
  }
20238
20551
  var MAX_SOURCE_BYTES = 4 * 1024 * 1024;
20239
- function isRecord11(value) {
20552
+ function isRecord10(value) {
20240
20553
  return value !== null && typeof value === "object" && !Array.isArray(value);
20241
20554
  }
20242
20555
  function freezeJson(root) {
@@ -20316,7 +20629,7 @@ async function readNativeMigrationSource(role, path2, hooks = {}) {
20316
20629
  } catch {
20317
20630
  throw new NativeMigrationSourceError(role, "invalid-source");
20318
20631
  }
20319
- if (!isRecord11(data))
20632
+ if (!isRecord10(data))
20320
20633
  throw new NativeMigrationSourceError(role, "invalid-source");
20321
20634
  return sourceSnapshot({
20322
20635
  role,
@@ -20368,7 +20681,7 @@ class NativeAuthorityError extends Error {
20368
20681
  code;
20369
20682
  constructor(code) {
20370
20683
  super({
20371
- "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",
20372
20685
  "migration-incomplete": "Anthropic account migration is incomplete; resume setup",
20373
20686
  "invalid-journal": "Anthropic account migration journal is invalid",
20374
20687
  "journal-conflict": "Anthropic account migration journal changed"
@@ -20377,7 +20690,7 @@ class NativeAuthorityError extends Error {
20377
20690
  this.name = "NativeAuthorityError";
20378
20691
  }
20379
20692
  }
20380
- function isRecord12(value) {
20693
+ function isRecord11(value) {
20381
20694
  return value !== null && typeof value === "object" && !Array.isArray(value);
20382
20695
  }
20383
20696
  function captureJournalJson(value) {
@@ -20413,19 +20726,19 @@ function isCapturedPath(value) {
20413
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 === "..");
20414
20727
  }
20415
20728
  function isSources(value) {
20416
- 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);
20417
20730
  }
20418
20731
  function isRoutingPaths(value) {
20419
- 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);
20420
20733
  }
20421
20734
  function isText(value) {
20422
20735
  return typeof value === "string" && value.length > 0;
20423
20736
  }
20424
20737
  function decodeRoster2(value) {
20425
- 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))
20426
20739
  throw new NativeAuthorityError("invalid-journal");
20427
20740
  const rows = value.rows.map((row) => {
20428
- if (!isRecord12(row) || !hasKeys(row, [
20741
+ if (!isRecord11(row) || !hasKeys(row, [
20429
20742
  "routeId",
20430
20743
  "credentialId",
20431
20744
  "credentialType",
@@ -20448,7 +20761,7 @@ function decodeRoster2(value) {
20448
20761
  };
20449
20762
  });
20450
20763
  const declined = value.declined.map((entry2) => {
20451
- 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)))
20452
20765
  throw new NativeAuthorityError("invalid-journal");
20453
20766
  return isText(entry2.accountIdentity) ? {
20454
20767
  credentialId: entry2.credentialId,
@@ -20460,7 +20773,7 @@ function decodeRoster2(value) {
20460
20773
  return { version: 1, view: value.view, complete: true, rows, declined };
20461
20774
  }
20462
20775
  function decodeDigestPair(value, keys4, valid) {
20463
- 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])))
20464
20777
  throw new NativeAuthorityError("invalid-journal");
20465
20778
  return Object.fromEntries(keys4.map((key) => [key, value[key]]));
20466
20779
  }
@@ -20468,7 +20781,7 @@ var ACTIVATION_PHASES = ["prepared", "published", "committed"];
20468
20781
  function decodeActivation(value, phase) {
20469
20782
  if (value === null)
20470
20783
  return null;
20471
- if (!isRecord12(value))
20784
+ if (!isRecord11(value))
20472
20785
  throw new NativeAuthorityError("invalid-journal");
20473
20786
  if (value.kind === "requested" && hasKeys(value, ["kind"]))
20474
20787
  return { kind: "requested" };
@@ -20482,7 +20795,7 @@ function decodeActivation(value, phase) {
20482
20795
  "settings",
20483
20796
  "runtime",
20484
20797
  "hostAuth"
20485
- ]) || !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))
20486
20799
  throw new NativeAuthorityError("invalid-journal");
20487
20800
  const primary = {
20488
20801
  routeId: value.primary.routeId,
@@ -20509,7 +20822,7 @@ function decodeActivation(value, phase) {
20509
20822
  }
20510
20823
  function decodeJournal(input, storageId) {
20511
20824
  const value = captureJournalJson(input);
20512
- if (!isRecord12(value) || value.storageId !== storageId)
20825
+ if (!isRecord11(value) || value.storageId !== storageId)
20513
20826
  throw new NativeAuthorityError("invalid-journal");
20514
20827
  if (value.version === 5 && value.kind === "empty-init") {
20515
20828
  if (!hasKeys(value, ["version", "kind", "storageId", "host", "phase"]) || value.host !== "opencode" || value.phase !== "committed")
@@ -20595,6 +20908,9 @@ function nativeMigrationAuthorityPhase(journal) {
20595
20908
  return;
20596
20909
  return journal.phase;
20597
20910
  }
20911
+ function nativeJournalMayAdoptLaterHostLogin(journal, host) {
20912
+ return host === "opencode" && journal !== undefined && journal.kind !== "empty-init" && journal.host === "opencode" && journal.phase === "retired" && journal.activation === null;
20913
+ }
20598
20914
  async function requireNativePoolAuthority(paths) {
20599
20915
  const journal = await readNativeMigrationJournal(paths);
20600
20916
  if (!journal)
@@ -20634,7 +20950,7 @@ async function writeJournal(paths, journal, assertOwned, hooks) {
20634
20950
  });
20635
20951
  await hooks.onWriteStep?.("after-write", snapshot);
20636
20952
  }
20637
- async function beginNativeMigration(paths, input, hooks = {}) {
20953
+ async function beginNativeMigration(paths, input, hooks = {}, replaces) {
20638
20954
  try {
20639
20955
  requireNativeMigrationDataObject(input);
20640
20956
  } catch {
@@ -20667,6 +20983,12 @@ async function beginNativeMigration(paths, input, hooks = {}) {
20667
20983
  renew: true
20668
20984
  }, async (lock) => {
20669
20985
  const current = await readNativeMigrationJournal(paths);
20986
+ if (replaces) {
20987
+ if (initial.version !== 5 || !nativeJournalMayAdoptLaterHostLogin(replaces, initial.host) || !current || nativeMigrationCanonicalJson(current) !== nativeMigrationCanonicalJson(replaces))
20988
+ throw new NativeAuthorityError("journal-conflict");
20989
+ await writeJournal(paths, initial, () => lock.assertOwned(), hooks);
20990
+ return initial;
20991
+ }
20670
20992
  if (current?.kind === "empty-init") {
20671
20993
  if (current.host !== initial.host)
20672
20994
  throw new NativeAuthorityError("journal-conflict");
@@ -20685,7 +21007,7 @@ async function beginNativeMigration(paths, input, hooks = {}) {
20685
21007
  }
20686
21008
  async function recordNativeMigrationExpectations(paths, expectations, hooks = {}) {
20687
21009
  const captured = captureJournalJson(expectations);
20688
- if (!isRecord12(captured) || !hasKeys(captured, [
21010
+ if (!isRecord11(captured) || !hasKeys(captured, [
20689
21011
  "expectedHostAuth",
20690
21012
  "expectedRouting",
20691
21013
  "preparedProof"
@@ -20760,7 +21082,7 @@ function journalLock(hooks) {
20760
21082
  }
20761
21083
  async function recordNativeCustodyActivation(paths, plan, hooks = {}) {
20762
21084
  const captured = captureJournalJson(plan);
20763
- if (!isRecord12(captured) || captured.phase !== "prepared")
21085
+ if (!isRecord11(captured) || captured.phase !== "prepared")
20764
21086
  throw new NativeAuthorityError("journal-conflict");
20765
21087
  const decoded = decodeActivation(captured, "retired");
20766
21088
  if (decoded?.kind !== "activation")
@@ -21257,9 +21579,9 @@ class NativeRuntimeRegistry {
21257
21579
 
21258
21580
  // src/native-vault-paths.ts
21259
21581
  import { createHash as createHash15 } from "node:crypto";
21260
- import { basename as basename5, dirname as dirname11, join as join12 } from "node:path";
21582
+ import { basename as basename5, dirname as dirname11, join as join13 } from "node:path";
21261
21583
  function sibling(path2, expected, name, suffix) {
21262
- return basename5(path2) === expected ? join12(dirname11(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
21584
+ return basename5(path2) === expected ? join13(dirname11(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
21263
21585
  }
21264
21586
  function nativeVaultPaths(local) {
21265
21587
  const config = sibling(local.legacyConfig, "anthropic-auth.json", "anthropic-auth-vault-settings.json", "vault-settings");
@@ -21472,10 +21794,10 @@ function seedCode(value) {
21472
21794
  class NativeRosterSeedError extends Error {
21473
21795
  code;
21474
21796
  constructor(code) {
21475
- const safeCode = seedCode(code);
21476
- super(`Native roster seed refused: ${safeCode}`);
21797
+ const safeCode2 = seedCode(code);
21798
+ super(`Native roster seed refused: ${safeCode2}`);
21477
21799
  this.name = "NativeRosterSeedError";
21478
- this.code = safeCode;
21800
+ this.code = safeCode2;
21479
21801
  }
21480
21802
  }
21481
21803
  function guarded(body) {
@@ -23501,12 +23823,12 @@ function leaseNativeVaultRuntime(use, close) {
23501
23823
  // src/pool-paths.ts
23502
23824
  import { createHash as createHash17 } from "node:crypto";
23503
23825
  import { realpath as realpath3 } from "node:fs/promises";
23504
- import { basename as basename7, dirname as dirname13, join as join14, resolve as resolve11 } from "node:path";
23826
+ import { basename as basename7, dirname as dirname13, join as join15, resolve as resolve11 } from "node:path";
23505
23827
 
23506
23828
  // src/sticky-routing.ts
23507
23829
  import { createHash as createHash16, randomUUID as randomUUID14 } from "node:crypto";
23508
23830
  import { mkdir as mkdir10, readFile as readFile9, rename as rename12, rm as rm7, stat as stat7, writeFile as writeFile4 } from "node:fs/promises";
23509
- import { basename as basename6, dirname as dirname12, join as join13 } from "node:path";
23831
+ import { basename as basename6, dirname as dirname12, join as join14 } from "node:path";
23510
23832
  var STICKY_ROUTING_MAIN_ACCOUNT_ID = "main";
23511
23833
  var STICKY_ROUTING_SHORT_RESET_GRACE_MS = 15 * 60000;
23512
23834
  var STICKY_ROUTING_ASSIGNMENT_TTL_MS = 7 * 24 * 60 * 60000;
@@ -23556,14 +23878,14 @@ function createStickyNoRouteResponse(input) {
23556
23878
  }
23557
23879
  });
23558
23880
  }
23559
- function isRecord13(value) {
23881
+ function isRecord12(value) {
23560
23882
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
23561
23883
  }
23562
23884
  function finiteNumber(value) {
23563
23885
  return typeof value === "number" && Number.isFinite(value) ? value : undefined;
23564
23886
  }
23565
23887
  function normalizeAssignment(value) {
23566
- if (!isRecord13(value))
23888
+ if (!isRecord12(value))
23567
23889
  return;
23568
23890
  if (typeof value.accountId !== "string" || !["fable", "opus", "general"].includes(String(value.family))) {
23569
23891
  return;
@@ -23592,7 +23914,7 @@ function normalizeAssignment(value) {
23592
23914
  };
23593
23915
  }
23594
23916
  function normalizeState(value) {
23595
- if (!isRecord13(value) || value.version !== 1 || !isRecord13(value.assignments)) {
23917
+ if (!isRecord12(value) || value.version !== 1 || !isRecord12(value.assignments)) {
23596
23918
  return;
23597
23919
  }
23598
23920
  const assignments = {};
@@ -23610,7 +23932,7 @@ function normalizeState(value) {
23610
23932
  }
23611
23933
  function migrateStickyRoutingState(source2, rowIdMap) {
23612
23934
  try {
23613
- if (!isRecord13(source2) || !isRecord13(source2.assignments))
23935
+ if (!isRecord12(source2) || !isRecord12(source2.assignments))
23614
23936
  throw new Error;
23615
23937
  const entries = Object.entries(source2.assignments);
23616
23938
  const state = normalizeState({
@@ -23628,7 +23950,7 @@ function migrateStickyRoutingState(source2, rowIdMap) {
23628
23950
  const assignments = Object.create(null);
23629
23951
  for (const [index, [key, original]] of entries.entries()) {
23630
23952
  const assignment = state.assignments[String(index)];
23631
- if (!isRecord13(original) || !assignment)
23953
+ if (!isRecord12(original) || !assignment)
23632
23954
  throw new Error;
23633
23955
  const fields2 = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
23634
23956
  if (Object.keys(original).length !== fields2.length || fields2.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
@@ -23756,7 +24078,7 @@ function decideStickyQuotaFailure(input) {
23756
24078
  function getStickyRoutingStatePath(accountStoragePath) {
23757
24079
  const name = basename6(accountStoragePath);
23758
24080
  const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
23759
- return join13(dirname12(accountStoragePath), `${stem}-routing-state.json`);
24081
+ return join14(dirname12(accountStoragePath), `${stem}-routing-state.json`);
23760
24082
  }
23761
24083
  function stickyRetryAfterWithJitter(sessionId, retryAfterSeconds) {
23762
24084
  const hash2 = createHash16("sha256").update(sessionId).digest().readUInt32BE(0);
@@ -23972,7 +24294,7 @@ class StickySessionRouter {
23972
24294
  const source2 = await readNativeVaultLegacyJson(seed.legacyConfig);
23973
24295
  const routes = nativeVaultLegacyRoutes(source2, roster);
23974
24296
  const legacy = await readNativeVaultLegacyJson(getStickyRoutingStatePath(seed.legacyConfig));
23975
- if (isRecord13(legacy) && legacy.version === 1 && isRecord13(legacy.assignments)) {
24297
+ if (isRecord12(legacy) && legacy.version === 1 && isRecord12(legacy.assignments)) {
23976
24298
  for (const [key, raw] of Object.entries(legacy.assignments)) {
23977
24299
  if (!/^[0-9a-f]{64}$/.test(key) || Object.hasOwn(state.assignments, key))
23978
24300
  continue;
@@ -24234,10 +24556,10 @@ async function canonicalPath(path2) {
24234
24556
  const parent = dirname13(absolute);
24235
24557
  if (parent === absolute)
24236
24558
  return absolute;
24237
- return join14(await canonicalPath(parent), basename7(absolute));
24559
+ return join15(await canonicalPath(parent), basename7(absolute));
24238
24560
  }
24239
24561
  function sibling2(path2, legacyName, name, suffix) {
24240
- return basename7(path2) === legacyName ? join14(dirname13(path2), name) : `${path2}.${suffix}.json`;
24562
+ return basename7(path2) === legacyName ? join15(dirname13(path2), name) : `${path2}.${suffix}.json`;
24241
24563
  }
24242
24564
  async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), legacyState = getAccountStatePath(legacyConfig)) {
24243
24565
  const [sourceConfig, sourceState] = await Promise.all([
@@ -26930,7 +27252,7 @@ function relayGeneration(input) {
26930
27252
  // src/native-host-auth-write.ts
26931
27253
  import { randomUUID as randomUUID16 } from "node:crypto";
26932
27254
  import { lstat as lstat7, open as open9, rename as rename13, unlink as unlink6 } from "node:fs/promises";
26933
- import { dirname as dirname14, isAbsolute as isAbsolute5, join as join15 } from "node:path";
27255
+ import { dirname as dirname14, isAbsolute as isAbsolute5, join as join16 } from "node:path";
26934
27256
  class NativeHostAuthWriteError extends Error {
26935
27257
  code;
26936
27258
  effect;
@@ -26991,7 +27313,7 @@ async function writeNativeHostAuth(input, hooks = {}) {
26991
27313
  const removingFile = host === "pi" && Object.keys(next).length === 0;
26992
27314
  const outcome = Object.freeze(host === "pi" ? { status: "removed", file: removingFile ? "unlinked" : "replaced" } : { status: snapshot.data === undefined ? "created" : "replaced" });
26993
27315
  if (!removingFile) {
26994
- stage = join15(dirname14(authPath), `.native-host-auth-write.${randomUUID16()}.tmp`);
27316
+ stage = join16(dirname14(authPath), `.native-host-auth-write.${randomUUID16()}.tmp`);
26995
27317
  const bytes = `${JSON.stringify(next, null, 2)}
26996
27318
  `;
26997
27319
  const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
@@ -27198,7 +27520,7 @@ async function capture2(input, checkPool = false) {
27198
27520
  refuse3();
27199
27521
  const current = await readNativeMigrationJournal(input.paths);
27200
27522
  const emptyInit = current?.kind === "empty-init";
27201
- const journal = current?.kind === "empty-init" ? undefined : current;
27523
+ let journal = current?.kind === "empty-init" ? undefined : current;
27202
27524
  if (emptyInit) {
27203
27525
  if (current.host !== input.host || input.routingDestinationPath !== resolveLocalRoutingDestination(input.host, input.paths, input.env))
27204
27526
  refuse3();
@@ -27228,6 +27550,11 @@ async function capture2(input, checkPool = false) {
27228
27550
  refuse3();
27229
27551
  if (journal && (journal.host !== input.host || journal.hostAuthPath !== hostAuthPath || journal.routingPaths.source !== routingSourcePath || journal.routingPaths.destination !== routingDestinationPath))
27230
27552
  refuse3();
27553
+ let replaces;
27554
+ if (nativeJournalMayAdoptLaterHostLogin(journal, input.host) && entry2.kind === "oauth" && !await nativePoolHoldsAccountData({ paths: input.paths })) {
27555
+ replaces = journal;
27556
+ journal = undefined;
27557
+ }
27231
27558
  if (journal?.phase === "committed" || journal?.phase === "retired") {
27232
27559
  const missing2 = (role, path2) => ({
27233
27560
  role,
@@ -27262,7 +27589,7 @@ async function capture2(input, checkPool = false) {
27262
27589
  const config = await readNativeMigrationSource("config", input.legacyConfigPath ?? input.paths.legacyConfig);
27263
27590
  const state = await readNativeMigrationSource("state", input.legacyStatePath ?? input.paths.legacyState);
27264
27591
  const routing = await readNativeMigrationSource("routing", input.routingSourcePath);
27265
- const routingDestination = emptyInit || journal?.kind === "legacy-import" ? await readNativeMigrationSource("routing", input.routingDestinationPath) : undefined;
27592
+ const routingDestination = emptyInit || replaces || journal?.kind === "legacy-import" ? await readNativeMigrationSource("routing", input.routingDestinationPath) : undefined;
27266
27593
  if (routingDestination)
27267
27594
  owned(routingDestination);
27268
27595
  for (const source2 of [config, state, routing])
@@ -27321,6 +27648,7 @@ async function capture2(input, checkPool = false) {
27321
27648
  routing,
27322
27649
  auth,
27323
27650
  journal: current,
27651
+ ...replaces ? { replaces } : {},
27324
27652
  routingDestination,
27325
27653
  projection,
27326
27654
  seedInput,
@@ -27525,11 +27853,11 @@ async function runNativeMigration(input, hooks = {}) {
27525
27853
  const captured = await capture2(operation, true);
27526
27854
  if (operation.preflight) {
27527
27855
  const previous = preflights.get(operation.preflight);
27528
- if (!previous || operation.preflight.storageId !== paths.storageId || operation.preflight.host !== operation.host || previous.config.digest !== captured.config.digest || previous.state.digest !== captured.state.digest || previous.routing.digest !== captured.routing.digest || previous.routingDestination?.digest !== captured.routingDestination?.digest || inspectNativeHostAuthEntry(operation.host, previous.auth.data).digest !== inspectNativeHostAuthEntry(operation.host, captured.auth.data).digest || previous.hostAuthPath !== captured.hostAuthPath || previous.routingSourcePath !== captured.routingSourcePath || previous.routingDestinationPath !== captured.routingDestinationPath)
27856
+ if (!previous || operation.preflight.storageId !== paths.storageId || operation.preflight.host !== operation.host || previous.config.digest !== captured.config.digest || previous.state.digest !== captured.state.digest || previous.routing.digest !== captured.routing.digest || previous.routingDestination?.digest !== captured.routingDestination?.digest || inspectNativeHostAuthEntry(operation.host, previous.auth.data).digest !== inspectNativeHostAuthEntry(operation.host, captured.auth.data).digest || previous.hostAuthPath !== captured.hostAuthPath || previous.routingSourcePath !== captured.routingSourcePath || previous.routingDestinationPath !== captured.routingDestinationPath || previous.replaces === undefined !== (captured.replaces === undefined))
27529
27857
  refuse3();
27530
27858
  }
27531
- const emptyInit = captured.journal?.kind === "empty-init";
27532
- let journal = captured.journal?.kind === "empty-init" ? undefined : captured.journal;
27859
+ const emptyInit = captured.journal?.kind === "empty-init" || captured.replaces !== undefined;
27860
+ let journal = captured.journal?.kind === "empty-init" || captured.replaces ? undefined : captured.journal;
27533
27861
  const store = createNativePoolStore({
27534
27862
  paths,
27535
27863
  quota: nativeQuotaCodec,
@@ -27597,7 +27925,7 @@ async function runNativeMigration(input, hooks = {}) {
27597
27925
  destination: captured.routingDestinationPath
27598
27926
  },
27599
27927
  ...operation.requestVaultActivation ? { activation: "requested" } : {}
27600
- }, journalHooks);
27928
+ }, journalHooks, captured.replaces);
27601
27929
  }
27602
27930
  let bytes;
27603
27931
  let seed;
@@ -27866,7 +28194,7 @@ class NativeCustodyActivationError extends Error {
27866
28194
  function refuse4(code) {
27867
28195
  throw new NativeCustodyActivationError(code);
27868
28196
  }
27869
- function isRecord14(value) {
28197
+ function isRecord13(value) {
27870
28198
  return value !== null && typeof value === "object" && !Array.isArray(value);
27871
28199
  }
27872
28200
  function sameJson(left, right) {
@@ -27951,7 +28279,7 @@ var ACCOUNT_RUNTIME_FIELDS = [
27951
28279
  "quotaErrorGeneration"
27952
28280
  ];
27953
28281
  function vaultSettings(settings, primary) {
27954
- const custody = isRecord14(settings.claustrum) ? settings.claustrum : {};
28282
+ const custody = isRecord13(settings.claustrum) ? settings.claustrum : {};
27955
28283
  return {
27956
28284
  ...settings,
27957
28285
  claustrum: {
@@ -28061,7 +28389,7 @@ async function preparePlan(options, journal, store) {
28061
28389
  const main = pool.settings.mainAccountId;
28062
28390
  if (typeof main !== "string" || !main)
28063
28391
  refuse4("invalid-state");
28064
- const custody = isRecord14(pool.settings.claustrum) ? pool.settings.claustrum : {};
28392
+ const custody = isRecord13(pool.settings.claustrum) ? pool.settings.claustrum : {};
28065
28393
  const host = await readHostEntry(options.host, journal.hostAuthPath);
28066
28394
  const hostAuth = {
28067
28395
  source: host.digest,
@@ -28092,7 +28420,7 @@ async function preparePlan(options, journal, store) {
28092
28420
  let roster;
28093
28421
  let targetSettings;
28094
28422
  if (custody.mode === "claustrum") {
28095
- const pin = isRecord14(custody.primaryAccount) ? custody.primaryAccount : {};
28423
+ const pin = isRecord13(custody.primaryAccount) ? custody.primaryAccount : {};
28096
28424
  if (oauth.length > 0 || pin.credentialId !== primary.credentialId || pin.accountId !== primary.accountIdentity)
28097
28425
  refuse4("primary-mismatch");
28098
28426
  if (!existing)
@@ -28143,7 +28471,7 @@ async function preparePlan(options, journal, store) {
28143
28471
  } catch (error) {
28144
28472
  if (error instanceof NativeCustodyActivationError)
28145
28473
  throw error;
28146
- return refuse4(isRecord14(error) && error.code === "unenrolled-local-row" ? "unenrolled-local-row" : "roster-conflict");
28474
+ return refuse4(isRecord13(error) && error.code === "unenrolled-local-row" ? "unenrolled-local-row" : "roster-conflict");
28147
28475
  }
28148
28476
  roster = existing ?? rosterProjection(seed);
28149
28477
  targetSettings = vaultSettings(pool.settings, primary);
@@ -28295,7 +28623,7 @@ async function runNativeCustodyActivation(options, hooks = {}) {
28295
28623
  if (settings.status !== "ready")
28296
28624
  refuse4("invalid-state");
28297
28625
  const custody = settings.settings.claustrum;
28298
- if (isRecord14(custody) && custody.mode === "claustrum")
28626
+ if (isRecord13(custody) && custody.mode === "claustrum")
28299
28627
  return { status: "already-vault", journal };
28300
28628
  }
28301
28629
  if (journal.activation?.kind === "activation" && journal.activation.phase === "committed")
@@ -29916,8 +30244,8 @@ function showSignInLink(text5, scrub) {
29916
30244
  const links = new Set((text5.match(/https:\/\/\S+/g) ?? []).filter(isSignInLink));
29917
30245
  const [link2] = links;
29918
30246
  if (links.size !== 1 || link2 === undefined)
29919
- return scrub(text5);
29920
- return text5.split(link2).map(scrub).join(link2);
30247
+ return { text: scrub(text5) };
30248
+ return { text: text5.split(link2).map(scrub).join(link2), link: link2 };
29921
30249
  }
29922
30250
  var DISCONNECT_OUTCOMES = {
29923
30251
  disconnected: {
@@ -30116,12 +30444,16 @@ function createNativeUi(options) {
30116
30444
  safe = safe.split(value).join("[REDACTED]");
30117
30445
  return redact2(safe);
30118
30446
  };
30119
- const finish = async (result2, signInLink = false) => ({
30120
- command: "claude",
30121
- ...result2,
30122
- text: signInLink ? showSignInLink(result2.text, scrub) : scrub(result2.text),
30123
- menu: await model(invocation, scrub, readable)
30124
- });
30447
+ const finish = async (result2, signInLink = false) => {
30448
+ const shown = signInLink ? showSignInLink(result2.text, scrub) : { text: scrub(result2.text) };
30449
+ return {
30450
+ command: "claude",
30451
+ ...result2,
30452
+ text: shown.text,
30453
+ ...shown.link !== undefined ? { authorizationUrl: shown.link } : {},
30454
+ menu: await model(invocation, scrub, readable)
30455
+ };
30456
+ };
30125
30457
  if (request?.command !== "claude" || !action || request.itemId !== undefined || request.sessionId !== undefined && request.sessionId !== invocation.sessionId) {
30126
30458
  return finish({
30127
30459
  ok: false,
@@ -30244,7 +30576,7 @@ function waitForRequest(pending, signal) {
30244
30576
  });
30245
30577
  }
30246
30578
  // src/native-vault-connection.ts
30247
- import { dirname as dirname17, join as join16, resolve as resolve13 } from "node:path";
30579
+ import { dirname as dirname17, join as join17, resolve as resolve13 } from "node:path";
30248
30580
  // ../../node_modules/@cortexkit/common-auth/dist/opencode2/integration.js
30249
30581
  var PLACEHOLDER_PREFIX = "common-auth-placeholder";
30250
30582
  var PLACEHOLDER_LIFETIME_MS = 365 * 24 * 60 * 60 * 1000;
@@ -30783,7 +31115,7 @@ function createPiSlot(options, onStep, hooks) {
30783
31115
  function nativePiAuthSlotPaths(options) {
30784
31116
  return {
30785
31117
  authPath: resolve13(options.authPath),
30786
- stashPath: join16(dirname17(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
31118
+ stashPath: join17(dirname17(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
30787
31119
  provider: "anthropic",
30788
31120
  placeholderKey: placeholderSecret("anthropic")
30789
31121
  };
@@ -30804,8 +31136,8 @@ async function disconnectNativeVaultForHost(options) {
30804
31136
  import { createHash as createHash21 } from "node:crypto";
30805
31137
  import { realpathSync as realpathSync2 } from "node:fs";
30806
31138
  import { mkdir as mkdir14, readdir as readdir3, rm as rm8, stat as stat9, writeFile as writeFile5 } from "node:fs/promises";
30807
- import { tmpdir as tmpdir6 } from "node:os";
30808
- import { join as join17, resolve as resolve14 } from "node:path";
31139
+ import { tmpdir as tmpdir7 } from "node:os";
31140
+ import { join as join18, resolve as resolve14 } from "node:path";
30809
31141
  var CLAUDE_PRIME_COMMAND_NAME = "claude-prime";
30810
31142
  var PRIME_TICK_MS = 60000;
30811
31143
  var PRIME_DUE_OFFSET_MS = 60000;
@@ -30993,7 +31325,7 @@ function buildPrimeRequestBody() {
30993
31325
  return JSON.parse(JSON.stringify(PRIME_REQUEST_BODY));
30994
31326
  }
30995
31327
  function defaultMarkerDir() {
30996
- return join17(tmpdir6(), "opencode-anthropic-auth", "prime");
31328
+ return join18(tmpdir7(), "opencode-anthropic-auth", "prime");
30997
31329
  }
30998
31330
  function primeStorageFingerprint(storagePath) {
30999
31331
  const absolutePath = resolve14(storagePath);
@@ -31008,19 +31340,19 @@ function primeStorageFingerprint(storagePath) {
31008
31340
  return createHash21("sha256").update(canonicalPath2).digest("hex").slice(0, 12);
31009
31341
  }
31010
31342
  function primeMarkerNamespaceDir(markerDir, storagePath) {
31011
- return join17(markerDir, primeStorageFingerprint(storagePath));
31343
+ return join18(markerDir, primeStorageFingerprint(storagePath));
31012
31344
  }
31013
31345
  function primeAccountMarkerDir(markerDir, storagePath, accountFingerprint) {
31014
31346
  if (!/^[a-f0-9]{12,}$/i.test(accountFingerprint)) {
31015
31347
  throw new Error("Prime account fingerprint must be a hexadecimal digest");
31016
31348
  }
31017
- return join17(primeMarkerNamespaceDir(markerDir, storagePath), accountFingerprint.toLowerCase().slice(0, 12));
31349
+ return join18(primeMarkerNamespaceDir(markerDir, storagePath), accountFingerprint.toLowerCase().slice(0, 12));
31018
31350
  }
31019
31351
  function primeMarkerPath(markerDir, accountId2, resetsAtEpochMs) {
31020
- return join17(markerDir, `${encodeURIComponent(accountId2)}-${resetsAtEpochMs}`);
31352
+ return join18(markerDir, `${encodeURIComponent(accountId2)}-${resetsAtEpochMs}`);
31021
31353
  }
31022
31354
  function primeBootstrapMarkerPath(markerDir, accountId2) {
31023
- return join17(markerDir, `${encodeURIComponent(accountId2)}-bootstrap`);
31355
+ return join18(markerDir, `${encodeURIComponent(accountId2)}-bootstrap`);
31024
31356
  }
31025
31357
  function primeAccountLabel(id2, fallback) {
31026
31358
  if (id2 === "main")
@@ -31444,7 +31776,7 @@ class PrimeManager {
31444
31776
  let swept = 0;
31445
31777
  for (const entry2 of entries) {
31446
31778
  try {
31447
- const path2 = join17(dir, entry2);
31779
+ const path2 = join18(dir, entry2);
31448
31780
  const s = await stat9(path2);
31449
31781
  if (s.isDirectory()) {
31450
31782
  swept += await this.sweepMarkerDirectory(path2, now);
@@ -31478,12 +31810,12 @@ import {
31478
31810
  stat as stat10,
31479
31811
  writeFile as writeFile6
31480
31812
  } from "node:fs/promises";
31481
- import { tmpdir as tmpdir7 } from "node:os";
31482
- import { join as join18 } from "node:path";
31813
+ import { tmpdir as tmpdir8 } from "node:os";
31814
+ import { join as join19 } from "node:path";
31483
31815
  var QUOTA_HEADER_FEED_SCHEMA_VERSION = 3;
31484
31816
  var QUOTA_HEADER_FEED_LEASE_MS = 180000;
31485
31817
  function getDefaultQuotaHeaderFeedDirectory() {
31486
- return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ?? join18(tmpdir7(), "opencode-anthropic-auth", "quota-header-feed");
31818
+ return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ?? join19(tmpdir8(), "opencode-anthropic-auth", "quota-header-feed");
31487
31819
  }
31488
31820
  function configuredAnthropicOAuthAccountCount(input) {
31489
31821
  const fallbackCount = input.storage?.accounts.filter(isOAuthAccount).length ?? 0;
@@ -31642,7 +31974,7 @@ class QuotaHeaderFeedRegistry {
31642
31974
  constructor(options = {}) {
31643
31975
  this.options = options;
31644
31976
  const instanceId = options.instanceId ?? `${process.pid}-${randomUUID17()}`;
31645
- this.filePath = join18(options.directory ?? getDefaultQuotaHeaderFeedDirectory(), `${instanceId}.json`);
31977
+ this.filePath = join19(options.directory ?? getDefaultQuotaHeaderFeedDirectory(), `${instanceId}.json`);
31646
31978
  }
31647
31979
  publish(entry2) {
31648
31980
  const { accountKey, quota: quota2 } = entry2;
@@ -31703,7 +32035,7 @@ class QuotaHeaderFeedRegistry {
31703
32035
  return;
31704
32036
  }
31705
32037
  await Promise.all(names2.filter((name) => /^\d+-[0-9a-f-]+\.json$/i.test(name)).map(async (name) => {
31706
- const path2 = join18(directory, name);
32038
+ const path2 = join19(directory, name);
31707
32039
  if (path2 === this.filePath)
31708
32040
  return;
31709
32041
  try {
@@ -31732,7 +32064,7 @@ class QuotaHeaderFeedRegistry {
31732
32064
  const newest = new Map;
31733
32065
  await Promise.all(names2.map(async (name) => {
31734
32066
  try {
31735
- const record9 = JSON.parse(await readFile10(join18(directory, name), "utf8"));
32067
+ const record9 = JSON.parse(await readFile10(join19(directory, name), "utf8"));
31736
32068
  if (record9.version !== QUOTA_HEADER_FEED_SCHEMA_VERSION || !record9.entries || typeof record9.entries !== "object")
31737
32069
  return;
31738
32070
  for (const [accountKey, candidate] of Object.entries(record9.entries)) {
@@ -31913,7 +32245,7 @@ function buildClaudeQuotaSummary(input) {
31913
32245
  }
31914
32246
  // src/request-gzip.ts
31915
32247
  import { mkdir as mkdir16, readFile as readFile11, rename as rename15, rm as rm10, writeFile as writeFile7 } from "node:fs/promises";
31916
- import { basename as basename8, dirname as dirname18, join as join19 } from "node:path";
32248
+ import { basename as basename8, dirname as dirname18, join as join20 } from "node:path";
31917
32249
  import { promisify } from "node:util";
31918
32250
  import { gzip } from "node:zlib";
31919
32251
  var gzipAsync = promisify(gzip);
@@ -32059,7 +32391,7 @@ function getRequestGzipLatch(path2) {
32059
32391
  function getRequestGzipLatchPath(accountStoragePath) {
32060
32392
  const name = basename8(accountStoragePath);
32061
32393
  const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
32062
- return join19(dirname18(accountStoragePath), `${stem}-request-gzip.json`);
32394
+ return join20(dirname18(accountStoragePath), `${stem}-request-gzip.json`);
32063
32395
  }
32064
32396
  async function decideRequestGzip(options) {
32065
32397
  if (!CLAUDE_CODE_GZIPS_REQUEST_BODIES)
@@ -32204,7 +32536,7 @@ var REPORTED_BLOCK_TYPES = new Set([
32204
32536
  "document"
32205
32537
  ]);
32206
32538
  var EMPTY_TEXT_BLOCK_KEYS = new Set(["type", "text", "cache_control"]);
32207
- function isRecord15(value) {
32539
+ function isRecord14(value) {
32208
32540
  return typeof value === "object" && value !== null && !Array.isArray(value);
32209
32541
  }
32210
32542
  function isProvablyEmptyContent(content) {
@@ -32212,14 +32544,14 @@ function isProvablyEmptyContent(content) {
32212
32544
  return content.trim() === "";
32213
32545
  if (!Array.isArray(content))
32214
32546
  return false;
32215
- 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)));
32547
+ 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)));
32216
32548
  }
32217
32549
  function describeContent(content) {
32218
32550
  if (Array.isArray(content)) {
32219
32551
  return {
32220
32552
  contentShape: "array",
32221
32553
  contentBlockCount: content.length,
32222
- contentBlockTypes: content.map((block) => isRecord15(block) && typeof block.type === "string" && REPORTED_BLOCK_TYPES.has(block.type) ? block.type : "other")
32554
+ contentBlockTypes: content.map((block) => isRecord14(block) && typeof block.type === "string" && REPORTED_BLOCK_TYPES.has(block.type) ? block.type : "other")
32223
32555
  };
32224
32556
  }
32225
32557
  if (typeof content === "string")
@@ -32232,7 +32564,7 @@ function assertNoMeaningfulTrailingAssistant(messages) {
32232
32564
  let end = messages.length;
32233
32565
  while (end > 0) {
32234
32566
  const last = messages[end - 1];
32235
- if (!isRecord15(last) || last.role !== "assistant")
32567
+ if (!isRecord14(last) || last.role !== "assistant")
32236
32568
  break;
32237
32569
  if (!isProvablyEmptyContent(last.content)) {
32238
32570
  throw new TrailingAssistantHistoryError({
@@ -32375,11 +32707,11 @@ function executeLaneStartCommand(input) {
32375
32707
  }
32376
32708
  // src/thinking-binding.ts
32377
32709
  var THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
32378
- function isRecord16(value) {
32710
+ function isRecord15(value) {
32379
32711
  return typeof value === "object" && value !== null && !Array.isArray(value);
32380
32712
  }
32381
32713
  function isReplayableThinkingBlock(block) {
32382
- if (!isRecord16(block))
32714
+ if (!isRecord15(block))
32383
32715
  return false;
32384
32716
  if (block.type === "thinking") {
32385
32717
  return typeof block.signature === "string" && block.signature.length > 0;
@@ -32397,7 +32729,7 @@ function hasReplayableThinkingBlocks(body) {
32397
32729
  if (!Array.isArray(body.messages))
32398
32730
  return false;
32399
32731
  return body.messages.some((message) => {
32400
- if (!isRecord16(message) || message.role !== "assistant")
32732
+ if (!isRecord15(message) || message.role !== "assistant")
32401
32733
  return false;
32402
32734
  return Array.isArray(message.content) && message.content.some(isReplayableThinkingBlock);
32403
32735
  });
@@ -32405,11 +32737,11 @@ function hasReplayableThinkingBlocks(body) {
32405
32737
  function applyThinkingBindingControls(body, behavior = "account-default") {
32406
32738
  if (behavior === "account-default")
32407
32739
  return false;
32408
- if (!isClaudeFable51Model(body.model) && !isClaudeOpus55Model(body.model) && !isClaudeSonnet55Model(body.model) && !isClaudeHaiku55Model(body.model))
32740
+ if (!resolveClaudeModelCapabilities(body.model)?.thinkingBindingControls)
32409
32741
  return false;
32410
32742
  if (!hasReplayableThinkingBlocks(body))
32411
32743
  return false;
32412
- if (!isRecord16(body.thinking) || body.thinking.type !== "adaptive")
32744
+ if (!isRecord15(body.thinking) || body.thinking.type !== "adaptive")
32413
32745
  return false;
32414
32746
  body.thinking.block_binding = {
32415
32747
  prefix_mismatch_behavior: behavior
@@ -32417,13 +32749,68 @@ function applyThinkingBindingControls(body, behavior = "account-default") {
32417
32749
  return true;
32418
32750
  }
32419
32751
  function hasThinkingBindingControls(body) {
32420
- if (!isRecord16(body.thinking))
32752
+ if (!isRecord15(body.thinking))
32421
32753
  return false;
32422
- if (!isRecord16(body.thinking.block_binding))
32754
+ if (!isRecord15(body.thinking.block_binding))
32423
32755
  return false;
32424
32756
  const behavior = body.thinking.block_binding.prefix_mismatch_behavior;
32425
32757
  return behavior === "error" || behavior === "drop_block";
32426
32758
  }
32759
+ // src/turn-end-note.ts
32760
+ var TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
32761
+ 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.";
32762
+ var DEFAULT_TOOLS = ["board", "ctx_reduce"];
32763
+ function isRecord16(value) {
32764
+ return value !== null && typeof value === "object" && !Array.isArray(value);
32765
+ }
32766
+ function supportsTurnEndNote(model) {
32767
+ return resolveClaudeModelCapabilities(model)?.turnEndNote === true;
32768
+ }
32769
+ function applyTurnEndNotes(body, options = {}) {
32770
+ if (!supportsTurnEndNote(body.model) || !Array.isArray(body.messages))
32771
+ return 0;
32772
+ const allowed = new Set((options.tools ?? DEFAULT_TOOLS).map((name) => options.mapToolName?.(name) ?? name));
32773
+ if (!allowed.size)
32774
+ return 0;
32775
+ const messages = body.messages;
32776
+ const rewritten = [];
32777
+ let inserted = 0;
32778
+ for (let index = 0;index < messages.length; index++) {
32779
+ const results = messages[index];
32780
+ rewritten.push(results);
32781
+ let preceding = index - 1;
32782
+ while (preceding >= 0) {
32783
+ const control = messages[preceding];
32784
+ if (!isRecord16(control) || control.role !== "system" || !Array.isArray(control.content) || control.content.length !== 0 || !isRecord16(control.output_config))
32785
+ break;
32786
+ preceding--;
32787
+ }
32788
+ const assistant = messages[preceding];
32789
+ if (!isRecord16(assistant) || assistant.role !== "assistant" || !Array.isArray(assistant.content) || !isRecord16(results) || results.role !== "user" || !Array.isArray(results.content))
32790
+ continue;
32791
+ 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("");
32792
+ if (visible.length < TURN_END_NOTE_MIN_VISIBLE_CHARACTERS)
32793
+ continue;
32794
+ const calls = assistant.content.filter((block) => isRecord16(block) && block.type === "tool_use");
32795
+ if (!calls.length || !calls.every((call) => allowed.has(call.name)))
32796
+ continue;
32797
+ const resultIds = new Set(results.content.filter((block) => isRecord16(block) && block.type === "tool_result").map((block) => block.tool_use_id));
32798
+ if (!calls.every((call) => typeof call.id === "string" && resultIds.has(call.id)))
32799
+ continue;
32800
+ const next = messages[index + 1];
32801
+ if (isRecord16(next) && next.role === "user")
32802
+ continue;
32803
+ rewritten.push({
32804
+ role: "system",
32805
+ clear_at: "next_user_message",
32806
+ content: TURN_END_NOTE_CONTENT
32807
+ });
32808
+ inserted++;
32809
+ }
32810
+ if (inserted)
32811
+ body.messages = rewritten;
32812
+ return inserted;
32813
+ }
32427
32814
  export {
32428
32815
  writeNativeHostAuth,
32429
32816
  writeDumpFile,
@@ -32465,6 +32852,7 @@ export {
32465
32852
  resolveNativePoolPaths,
32466
32853
  resolveLocalRoutingDestination,
32467
32854
  resolveClaustrumConnectionPath,
32855
+ resolveClaudeModelCapabilities,
32468
32856
  resolveClaudeCodeIdentity,
32469
32857
  resolveClaudeCodeAccountIdentity,
32470
32858
  resetFastModeState,
@@ -32509,6 +32897,7 @@ export {
32509
32897
  primeEligibilityReasonLabel,
32510
32898
  primeAccountMarkerDir,
32511
32899
  prepareNativeMigration,
32900
+ pinsEffortOnEveryRequest,
32512
32901
  parseSseFrame,
32513
32902
  parseRoutingCommandAction,
32514
32903
  parseRetryAfterHeader,
@@ -32542,6 +32931,7 @@ export {
32542
32931
  nativeMigrationAuthorityPhase,
32543
32932
  nativeLocalQuotaLineage,
32544
32933
  nativeLocalCredentialValidationMatches,
32934
+ nativeJournalMayAdoptLaterHostLogin,
32545
32935
  nativeCacheKeepAlways,
32546
32936
  nativeAccountPolicy,
32547
32937
  nativeAccountCanServe,
@@ -32634,6 +33024,8 @@ export {
32634
33024
  getDefaultCacheKeepRegistryDirectory,
32635
33025
  getClaustrumMode,
32636
33026
  getClaustrumEnrollmentPaths2 as getClaustrumEnrollmentPaths,
33027
+ getClaudeModelCatalogue,
33028
+ getClaudeModelCapabilities,
32637
33029
  getClaudeFableMythos5ReleaseDate,
32638
33030
  getClaudeCodeIdentityForVerifiedAccount,
32639
33031
  getClaudeCodeIdentity,
@@ -32778,6 +33170,7 @@ export {
32778
33170
  PrimeManager,
32779
33171
  PROFILE_TTL_MS,
32780
33172
  PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME,
33173
+ PRIVATE_FILES_UNAVAILABLE_MESSAGE,
32781
33174
  PRIME_TICK_MS,
32782
33175
  PRIME_REQUEST_BODY,
32783
33176
  PRIME_POST_FIRE_REFRESH_MS,
@@ -32793,6 +33186,7 @@ export {
32793
33186
  NativeTransientAccountError,
32794
33187
  NativeRuntimeError,
32795
33188
  NativeQuotaObservations,
33189
+ NativePrivateFilesUnavailableError,
32796
33190
  PiSlotError as NativePiAuthSlotError,
32797
33191
  NativeMigrationError,
32798
33192
  NativeHostAuthError,
@@ -32845,6 +33239,7 @@ export {
32845
33239
  CLAUDE_OPUS_5_5_ADAPTIVE_THINKING,
32846
33240
  CLAUDE_MYTHOS_5_MODEL_ID,
32847
33241
  CLAUDE_MYTHOS_5_1_MODEL_ID,
33242
+ CLAUDE_MODEL_CAPABILITIES,
32848
33243
  CLAUDE_LOGGING_COMMAND_NAME,
32849
33244
  CLAUDE_HAIKU_5_5_RELEASE_DATE,
32850
33245
  CLAUDE_HAIKU_5_5_PRICING,
@@ -32879,6 +33274,7 @@ export {
32879
33274
  CLAUDE_CODE_GZIPS_REQUEST_BODIES,
32880
33275
  CLAUDE_CODE_FULL_AGENT_BETAS,
32881
33276
  CLAUDE_CODE_ENTRYPOINT,
33277
+ CLAUDE_CODE_DEFAULT_BETAS,
32882
33278
  CLAUDE_CACHE_KEEP_COMMAND_NAME,
32883
33279
  CLAUDE_ACCOUNT_COMMAND_NAME,
32884
33280
  CCH_SALT,