@cortexkit/anthropic-auth-core 2.2.2 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/claude-code.d.ts +2 -1
- package/dist/constants.d.ts +5 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1038 -658
- package/dist/internal-types/claustrum/enrollment.d.ts +5 -0
- package/dist/internal-types/fs/private-files.d.ts +2 -0
- package/dist/internal-types/setup/enroll.d.ts +34 -0
- package/dist/internal-types/setup/index.d.ts +1 -0
- package/dist/internal-types/setup/process-fence.d.ts +7 -0
- package/dist/internal-types/setup/types.d.ts +5 -0
- package/dist/mid-conversation-output-config.d.ts +19 -15
- package/dist/model-capabilities.d.ts +136 -0
- package/dist/models.d.ts +28 -59
- package/dist/native-enrollment-authority.d.ts +19 -0
- package/dist/native-ui.d.ts +10 -1
- package/dist/turn-end-note.d.ts +4 -3
- package/package.json +2 -2
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
|
|
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 {
|
|
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"}).
|
|
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 =
|
|
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 =
|
|
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:
|
|
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) :
|
|
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 =
|
|
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
|
|
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(
|
|
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, {
|
|
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
|
-
|
|
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
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
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
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
3150
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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() ||
|
|
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) ?
|
|
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 =
|
|
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 =
|
|
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;
|
|
@@ -4819,348 +5280,6 @@ function stripBillingLineageFromBody(body) {
|
|
|
4819
5280
|
|
|
4820
5281
|
// src/claude-code.ts
|
|
4821
5282
|
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)) {
|
|
5039
|
-
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;
|
|
5048
|
-
continue;
|
|
5049
|
-
}
|
|
5050
|
-
if (previous?.effort === normalized.effort)
|
|
5051
|
-
continue;
|
|
5052
|
-
compacted.push(normalized);
|
|
5053
|
-
}
|
|
5054
|
-
return compacted;
|
|
5055
|
-
}
|
|
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);
|
|
5076
|
-
}
|
|
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
|
-
}
|
|
5093
|
-
}
|
|
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
|
-
}
|
|
5101
|
-
body.output_config = pinnedOutputConfig;
|
|
5102
|
-
body.messages = rewritten;
|
|
5103
|
-
return { applied: true, inserted };
|
|
5104
|
-
}
|
|
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);
|
|
5113
|
-
}
|
|
5114
|
-
function supportsTurnEndNote(model) {
|
|
5115
|
-
return isClaudeFable51Model(model) || isClaudeHaiku55Model(model) || isClaudeOpus55Model(model) || isClaudeSonnet55Model(model);
|
|
5116
|
-
}
|
|
5117
|
-
function applyTurnEndNotes(body, options = {}) {
|
|
5118
|
-
if (!supportsTurnEndNote(body.model) || !Array.isArray(body.messages))
|
|
5119
|
-
return 0;
|
|
5120
|
-
const allowed = new Set((options.tools ?? DEFAULT_TOOLS).map((name) => options.mapToolName?.(name) ?? name));
|
|
5121
|
-
if (!allowed.size)
|
|
5122
|
-
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)))
|
|
5144
|
-
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)))
|
|
5147
|
-
continue;
|
|
5148
|
-
const next = messages[index + 1];
|
|
5149
|
-
if (isRecord4(next) && next.role === "user")
|
|
5150
|
-
continue;
|
|
5151
|
-
rewritten.push({
|
|
5152
|
-
role: "system",
|
|
5153
|
-
clear_at: "next_user_message",
|
|
5154
|
-
content: TURN_END_NOTE_CONTENT
|
|
5155
|
-
});
|
|
5156
|
-
inserted++;
|
|
5157
|
-
}
|
|
5158
|
-
if (inserted)
|
|
5159
|
-
body.messages = rewritten;
|
|
5160
|
-
return inserted;
|
|
5161
|
-
}
|
|
5162
|
-
|
|
5163
|
-
// src/claude-code.ts
|
|
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
|
|
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 (
|
|
5510
|
+
if (isRecord3(body.metadata))
|
|
5392
5511
|
delete body.metadata.user_id;
|
|
5393
5512
|
return false;
|
|
5394
5513
|
}
|
|
5395
|
-
if (!
|
|
5514
|
+
if (!isRecord3(body.metadata))
|
|
5396
5515
|
body.metadata = {};
|
|
5397
5516
|
const metadata = body.metadata;
|
|
5398
|
-
if (
|
|
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
|
|
5450
|
-
|
|
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
|
|
5582
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
8499
|
-
import { join as
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
|
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:
|
|
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) :
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
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 [
|
|
9560
|
+
return [
|
|
9561
|
+
"- Enrollment: this Claustrum vault does not support connecting plugins"
|
|
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",
|
|
@@ -10073,6 +10141,102 @@ function executeLoggingCommand(input) {
|
|
|
10073
10141
|
].join(`
|
|
10074
10142
|
`);
|
|
10075
10143
|
}
|
|
10144
|
+
// src/mid-conversation-output-config.ts
|
|
10145
|
+
function isRecord5(value) {
|
|
10146
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10147
|
+
}
|
|
10148
|
+
function normalizeAdaptiveEffort(value) {
|
|
10149
|
+
if (value === "minimal")
|
|
10150
|
+
return "low";
|
|
10151
|
+
if (value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "max") {
|
|
10152
|
+
return value;
|
|
10153
|
+
}
|
|
10154
|
+
return;
|
|
10155
|
+
}
|
|
10156
|
+
function usesPerTurnControl(model) {
|
|
10157
|
+
return resolveClaudeModelCapabilities(model)?.effortMarkers === "with-adaptive-thinking";
|
|
10158
|
+
}
|
|
10159
|
+
function sendsPerTurnControlBeta(model) {
|
|
10160
|
+
return resolveClaudeModelCapabilities(model)?.claudeCodeBetas.main.includes(PER_TURN_CONTROL_BETA) ?? false;
|
|
10161
|
+
}
|
|
10162
|
+
function supportsPerMessageEffort(body) {
|
|
10163
|
+
if (pinsEffortOnEveryRequest(body.model))
|
|
10164
|
+
return true;
|
|
10165
|
+
return usesPerTurnControl(body.model) && isRecord5(body.thinking) && body.thinking.type === "adaptive";
|
|
10166
|
+
}
|
|
10167
|
+
function defaultAdaptiveEffort(model) {
|
|
10168
|
+
return resolveClaudeModelCapabilities(model)?.efforts.default ?? "high";
|
|
10169
|
+
}
|
|
10170
|
+
function compactTransitions(transitions) {
|
|
10171
|
+
const compacted = [];
|
|
10172
|
+
for (const transition of transitions) {
|
|
10173
|
+
if (!Number.isSafeInteger(transition.afterAssistantMessages) || transition.afterAssistantMessages < 0 || !normalizeAdaptiveEffort(transition.effort)) {
|
|
10174
|
+
continue;
|
|
10175
|
+
}
|
|
10176
|
+
const normalized = {
|
|
10177
|
+
afterAssistantMessages: transition.afterAssistantMessages,
|
|
10178
|
+
effort: transition.effort
|
|
10179
|
+
};
|
|
10180
|
+
const previous = compacted.at(-1);
|
|
10181
|
+
if (previous && previous.afterAssistantMessages === normalized.afterAssistantMessages) {
|
|
10182
|
+
previous.effort = normalized.effort;
|
|
10183
|
+
continue;
|
|
10184
|
+
}
|
|
10185
|
+
if (previous?.effort === normalized.effort)
|
|
10186
|
+
continue;
|
|
10187
|
+
compacted.push(normalized);
|
|
10188
|
+
}
|
|
10189
|
+
return compacted;
|
|
10190
|
+
}
|
|
10191
|
+
function applyMidConversationOutputConfig(body, transitions) {
|
|
10192
|
+
if (!supportsPerMessageEffort(body) || !Array.isArray(body.messages)) {
|
|
10193
|
+
return { applied: false, inserted: 0 };
|
|
10194
|
+
}
|
|
10195
|
+
const compacted = compactTransitions(transitions);
|
|
10196
|
+
const pinsEveryRequest = pinsEffortOnEveryRequest(body.model);
|
|
10197
|
+
if (!pinsEveryRequest && compacted.length < 2) {
|
|
10198
|
+
return { applied: false, inserted: 0 };
|
|
10199
|
+
}
|
|
10200
|
+
const currentOutputConfig = isRecord5(body.output_config) ? body.output_config : {};
|
|
10201
|
+
const baseline = compacted[0]?.effort ?? normalizeAdaptiveEffort(currentOutputConfig.effort) ?? defaultAdaptiveEffort(body.model);
|
|
10202
|
+
const pinnedOutputConfig = { ...currentOutputConfig, effort: baseline };
|
|
10203
|
+
if (pinsEveryRequest)
|
|
10204
|
+
body.output_config = pinnedOutputConfig;
|
|
10205
|
+
if (compacted.length < 2)
|
|
10206
|
+
return { applied: true, inserted: 0 };
|
|
10207
|
+
const messages = body.messages;
|
|
10208
|
+
const transitionsByBoundary = new Map;
|
|
10209
|
+
for (const transition of compacted.slice(1)) {
|
|
10210
|
+
transitionsByBoundary.set(transition.afterAssistantMessages, transition.effort);
|
|
10211
|
+
}
|
|
10212
|
+
let assistantMessages = 0;
|
|
10213
|
+
let activeEffort = baseline;
|
|
10214
|
+
let inserted = 0;
|
|
10215
|
+
const rewritten = [];
|
|
10216
|
+
for (const message of messages) {
|
|
10217
|
+
if (isRecord5(message) && message.role === "user" && transitionsByBoundary.has(assistantMessages)) {
|
|
10218
|
+
const effort = transitionsByBoundary.get(assistantMessages);
|
|
10219
|
+
if (effort && effort !== activeEffort) {
|
|
10220
|
+
rewritten.push({
|
|
10221
|
+
role: "system",
|
|
10222
|
+
content: [],
|
|
10223
|
+
output_config: { effort }
|
|
10224
|
+
});
|
|
10225
|
+
activeEffort = effort;
|
|
10226
|
+
inserted++;
|
|
10227
|
+
}
|
|
10228
|
+
}
|
|
10229
|
+
rewritten.push(message);
|
|
10230
|
+
if (isRecord5(message) && message.role === "assistant")
|
|
10231
|
+
assistantMessages++;
|
|
10232
|
+
}
|
|
10233
|
+
if (!pinsEveryRequest && inserted === 0) {
|
|
10234
|
+
return { applied: false, inserted: 0 };
|
|
10235
|
+
}
|
|
10236
|
+
body.output_config = pinnedOutputConfig;
|
|
10237
|
+
body.messages = rewritten;
|
|
10238
|
+
return { applied: true, inserted };
|
|
10239
|
+
}
|
|
10076
10240
|
// src/model-remap.ts
|
|
10077
10241
|
function getEnv(name) {
|
|
10078
10242
|
const value = process.env[name]?.trim();
|
|
@@ -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 (
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 && !
|
|
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 (!
|
|
10861
|
+
if (!isRecord6(read.value))
|
|
10574
10862
|
return { status: "error", reason: "state root is not an object" };
|
|
10575
|
-
if ("accounts" in read.value && !
|
|
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 (!
|
|
10872
|
+
if (!isRecord6(pool))
|
|
10585
10873
|
return {};
|
|
10586
10874
|
const rows = pool[POOL_ROWS_KEY];
|
|
10587
|
-
return
|
|
10875
|
+
return isRecord6(rows) ? rows : {};
|
|
10588
10876
|
}
|
|
10589
10877
|
function stateAccountsOf(state) {
|
|
10590
|
-
return
|
|
10878
|
+
return isRecord6(state.accounts) ? state.accounts : {};
|
|
10591
10879
|
}
|
|
10592
10880
|
function rosterRowProblem(raw) {
|
|
10593
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
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) =>
|
|
10942
|
+
return rosterOf(config).find((raw) => isRecord6(raw) && raw.id === id);
|
|
10655
10943
|
}
|
|
10656
10944
|
function ensurePool(config) {
|
|
10657
|
-
if (!
|
|
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 (!
|
|
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
|
|
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 (!
|
|
10970
|
+
if (!isRecord6(pool))
|
|
10683
10971
|
return;
|
|
10684
10972
|
const retired = pool[POOL_RETIRED_EPOCHS_KEY];
|
|
10685
|
-
if (!
|
|
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 =
|
|
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 =
|
|
11012
|
+
const id = isRecord6(raw) && typeof raw.id === "string" ? raw.id : undefined;
|
|
10725
11013
|
const rawEntry = id === undefined ? undefined : entries[id];
|
|
10726
|
-
const reserved =
|
|
11014
|
+
const reserved = isRecord6(rawEntry) && Object.hasOwn(rawEntry, "staged");
|
|
10727
11015
|
const staged = reserved ? parseReservation(rawEntry.staged) : undefined;
|
|
10728
|
-
if (problem || !
|
|
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:
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
11153
|
+
if (!isRecord6(rawStamp))
|
|
10866
11154
|
return;
|
|
10867
11155
|
const raw = rawStamp[TRANSITION_STAMP_KEY];
|
|
10868
|
-
if (!
|
|
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 =
|
|
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 (!
|
|
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
|
|
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) => !(
|
|
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 =
|
|
11448
|
+
const accounts = isRecord6(this.state.accounts) ? this.state.accounts : {};
|
|
11161
11449
|
const entry = Object.hasOwn(accounts, id) ? accounts[id] : undefined;
|
|
11162
|
-
return
|
|
11450
|
+
return isRecord6(entry) ? entry : undefined;
|
|
11163
11451
|
}
|
|
11164
11452
|
dropStateAccount(id) {
|
|
11165
|
-
if (
|
|
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 (!
|
|
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 (
|
|
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 (
|
|
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:
|
|
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 =
|
|
11424
|
-
const stamp =
|
|
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 &&
|
|
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 =
|
|
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 (!
|
|
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 (!
|
|
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 :
|
|
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(
|
|
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 && (!
|
|
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 =
|
|
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) || !
|
|
12237
|
+
if (orphanId === id || tx.rosterRow(orphanId) || !isRecord6(account))
|
|
11950
12238
|
return false;
|
|
11951
12239
|
const stamp = account[CREDENTIAL_STAMP_KEY];
|
|
11952
|
-
if (!
|
|
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 =
|
|
12258
|
+
const accounts = isRecord6(tx.state.accounts) ? tx.state.accounts : {};
|
|
11971
12259
|
const stateHolder = Object.entries(accounts).find(([, account]) => {
|
|
11972
|
-
if (!
|
|
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 && (!
|
|
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 (!
|
|
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
|
|
12696
|
+
return isRecord6(accounts) && Object.hasOwn(accounts, id);
|
|
12409
12697
|
}
|
|
12410
12698
|
function rosterIdOf(raw) {
|
|
12411
|
-
return
|
|
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 =
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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) =>
|
|
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) => !
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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
|
|
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
|
|
13639
|
+
return isRecord8(value) && isScope(value.scope) && isLabel(value.label);
|
|
13352
13640
|
}
|
|
13353
13641
|
function isObservedBudget(value) {
|
|
13354
|
-
if (!
|
|
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 (!
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
17999
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
18912
|
-
super(`Native custody refused: ${
|
|
19199
|
+
const safeCode2 = nativeCode(code);
|
|
19200
|
+
super(`Native custody refused: ${safeCode2}`);
|
|
18913
19201
|
this.name = "NativeCustodyError";
|
|
18914
|
-
this.code =
|
|
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
|
|
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 (!
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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) || !
|
|
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 (!
|
|
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")
|
|
@@ -20685,7 +20998,7 @@ async function beginNativeMigration(paths, input, hooks = {}) {
|
|
|
20685
20998
|
}
|
|
20686
20999
|
async function recordNativeMigrationExpectations(paths, expectations, hooks = {}) {
|
|
20687
21000
|
const captured = captureJournalJson(expectations);
|
|
20688
|
-
if (!
|
|
21001
|
+
if (!isRecord11(captured) || !hasKeys(captured, [
|
|
20689
21002
|
"expectedHostAuth",
|
|
20690
21003
|
"expectedRouting",
|
|
20691
21004
|
"preparedProof"
|
|
@@ -20760,7 +21073,7 @@ function journalLock(hooks) {
|
|
|
20760
21073
|
}
|
|
20761
21074
|
async function recordNativeCustodyActivation(paths, plan, hooks = {}) {
|
|
20762
21075
|
const captured = captureJournalJson(plan);
|
|
20763
|
-
if (!
|
|
21076
|
+
if (!isRecord11(captured) || captured.phase !== "prepared")
|
|
20764
21077
|
throw new NativeAuthorityError("journal-conflict");
|
|
20765
21078
|
const decoded = decodeActivation(captured, "retired");
|
|
20766
21079
|
if (decoded?.kind !== "activation")
|
|
@@ -21257,9 +21570,9 @@ class NativeRuntimeRegistry {
|
|
|
21257
21570
|
|
|
21258
21571
|
// src/native-vault-paths.ts
|
|
21259
21572
|
import { createHash as createHash15 } from "node:crypto";
|
|
21260
|
-
import { basename as basename5, dirname as dirname11, join as
|
|
21573
|
+
import { basename as basename5, dirname as dirname11, join as join13 } from "node:path";
|
|
21261
21574
|
function sibling(path2, expected, name, suffix) {
|
|
21262
|
-
return basename5(path2) === expected ?
|
|
21575
|
+
return basename5(path2) === expected ? join13(dirname11(path2), name) : path2.replace(/(?:\.json)?$/, `.${suffix}.json`);
|
|
21263
21576
|
}
|
|
21264
21577
|
function nativeVaultPaths(local) {
|
|
21265
21578
|
const config = sibling(local.legacyConfig, "anthropic-auth.json", "anthropic-auth-vault-settings.json", "vault-settings");
|
|
@@ -21472,10 +21785,10 @@ function seedCode(value) {
|
|
|
21472
21785
|
class NativeRosterSeedError extends Error {
|
|
21473
21786
|
code;
|
|
21474
21787
|
constructor(code) {
|
|
21475
|
-
const
|
|
21476
|
-
super(`Native roster seed refused: ${
|
|
21788
|
+
const safeCode2 = seedCode(code);
|
|
21789
|
+
super(`Native roster seed refused: ${safeCode2}`);
|
|
21477
21790
|
this.name = "NativeRosterSeedError";
|
|
21478
|
-
this.code =
|
|
21791
|
+
this.code = safeCode2;
|
|
21479
21792
|
}
|
|
21480
21793
|
}
|
|
21481
21794
|
function guarded(body) {
|
|
@@ -23501,12 +23814,12 @@ function leaseNativeVaultRuntime(use, close) {
|
|
|
23501
23814
|
// src/pool-paths.ts
|
|
23502
23815
|
import { createHash as createHash17 } from "node:crypto";
|
|
23503
23816
|
import { realpath as realpath3 } from "node:fs/promises";
|
|
23504
|
-
import { basename as basename7, dirname as dirname13, join as
|
|
23817
|
+
import { basename as basename7, dirname as dirname13, join as join15, resolve as resolve11 } from "node:path";
|
|
23505
23818
|
|
|
23506
23819
|
// src/sticky-routing.ts
|
|
23507
23820
|
import { createHash as createHash16, randomUUID as randomUUID14 } from "node:crypto";
|
|
23508
23821
|
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
|
|
23822
|
+
import { basename as basename6, dirname as dirname12, join as join14 } from "node:path";
|
|
23510
23823
|
var STICKY_ROUTING_MAIN_ACCOUNT_ID = "main";
|
|
23511
23824
|
var STICKY_ROUTING_SHORT_RESET_GRACE_MS = 15 * 60000;
|
|
23512
23825
|
var STICKY_ROUTING_ASSIGNMENT_TTL_MS = 7 * 24 * 60 * 60000;
|
|
@@ -23556,14 +23869,14 @@ function createStickyNoRouteResponse(input) {
|
|
|
23556
23869
|
}
|
|
23557
23870
|
});
|
|
23558
23871
|
}
|
|
23559
|
-
function
|
|
23872
|
+
function isRecord12(value) {
|
|
23560
23873
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
23561
23874
|
}
|
|
23562
23875
|
function finiteNumber(value) {
|
|
23563
23876
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
23564
23877
|
}
|
|
23565
23878
|
function normalizeAssignment(value) {
|
|
23566
|
-
if (!
|
|
23879
|
+
if (!isRecord12(value))
|
|
23567
23880
|
return;
|
|
23568
23881
|
if (typeof value.accountId !== "string" || !["fable", "opus", "general"].includes(String(value.family))) {
|
|
23569
23882
|
return;
|
|
@@ -23592,7 +23905,7 @@ function normalizeAssignment(value) {
|
|
|
23592
23905
|
};
|
|
23593
23906
|
}
|
|
23594
23907
|
function normalizeState(value) {
|
|
23595
|
-
if (!
|
|
23908
|
+
if (!isRecord12(value) || value.version !== 1 || !isRecord12(value.assignments)) {
|
|
23596
23909
|
return;
|
|
23597
23910
|
}
|
|
23598
23911
|
const assignments = {};
|
|
@@ -23610,7 +23923,7 @@ function normalizeState(value) {
|
|
|
23610
23923
|
}
|
|
23611
23924
|
function migrateStickyRoutingState(source2, rowIdMap) {
|
|
23612
23925
|
try {
|
|
23613
|
-
if (!
|
|
23926
|
+
if (!isRecord12(source2) || !isRecord12(source2.assignments))
|
|
23614
23927
|
throw new Error;
|
|
23615
23928
|
const entries = Object.entries(source2.assignments);
|
|
23616
23929
|
const state = normalizeState({
|
|
@@ -23628,7 +23941,7 @@ function migrateStickyRoutingState(source2, rowIdMap) {
|
|
|
23628
23941
|
const assignments = Object.create(null);
|
|
23629
23942
|
for (const [index, [key, original]] of entries.entries()) {
|
|
23630
23943
|
const assignment = state.assignments[String(index)];
|
|
23631
|
-
if (!
|
|
23944
|
+
if (!isRecord12(original) || !assignment)
|
|
23632
23945
|
throw new Error;
|
|
23633
23946
|
const fields2 = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
|
|
23634
23947
|
if (Object.keys(original).length !== fields2.length || fields2.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
|
|
@@ -23756,7 +24069,7 @@ function decideStickyQuotaFailure(input) {
|
|
|
23756
24069
|
function getStickyRoutingStatePath(accountStoragePath) {
|
|
23757
24070
|
const name = basename6(accountStoragePath);
|
|
23758
24071
|
const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
|
|
23759
|
-
return
|
|
24072
|
+
return join14(dirname12(accountStoragePath), `${stem}-routing-state.json`);
|
|
23760
24073
|
}
|
|
23761
24074
|
function stickyRetryAfterWithJitter(sessionId, retryAfterSeconds) {
|
|
23762
24075
|
const hash2 = createHash16("sha256").update(sessionId).digest().readUInt32BE(0);
|
|
@@ -23972,7 +24285,7 @@ class StickySessionRouter {
|
|
|
23972
24285
|
const source2 = await readNativeVaultLegacyJson(seed.legacyConfig);
|
|
23973
24286
|
const routes = nativeVaultLegacyRoutes(source2, roster);
|
|
23974
24287
|
const legacy = await readNativeVaultLegacyJson(getStickyRoutingStatePath(seed.legacyConfig));
|
|
23975
|
-
if (
|
|
24288
|
+
if (isRecord12(legacy) && legacy.version === 1 && isRecord12(legacy.assignments)) {
|
|
23976
24289
|
for (const [key, raw] of Object.entries(legacy.assignments)) {
|
|
23977
24290
|
if (!/^[0-9a-f]{64}$/.test(key) || Object.hasOwn(state.assignments, key))
|
|
23978
24291
|
continue;
|
|
@@ -24234,10 +24547,10 @@ async function canonicalPath(path2) {
|
|
|
24234
24547
|
const parent = dirname13(absolute);
|
|
24235
24548
|
if (parent === absolute)
|
|
24236
24549
|
return absolute;
|
|
24237
|
-
return
|
|
24550
|
+
return join15(await canonicalPath(parent), basename7(absolute));
|
|
24238
24551
|
}
|
|
24239
24552
|
function sibling2(path2, legacyName, name, suffix) {
|
|
24240
|
-
return basename7(path2) === legacyName ?
|
|
24553
|
+
return basename7(path2) === legacyName ? join15(dirname13(path2), name) : `${path2}.${suffix}.json`;
|
|
24241
24554
|
}
|
|
24242
24555
|
async function resolveNativePoolPaths(legacyConfig = getAccountStoragePath(), legacyState = getAccountStatePath(legacyConfig)) {
|
|
24243
24556
|
const [sourceConfig, sourceState] = await Promise.all([
|
|
@@ -26930,7 +27243,7 @@ function relayGeneration(input) {
|
|
|
26930
27243
|
// src/native-host-auth-write.ts
|
|
26931
27244
|
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
26932
27245
|
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
|
|
27246
|
+
import { dirname as dirname14, isAbsolute as isAbsolute5, join as join16 } from "node:path";
|
|
26934
27247
|
class NativeHostAuthWriteError extends Error {
|
|
26935
27248
|
code;
|
|
26936
27249
|
effect;
|
|
@@ -26991,7 +27304,7 @@ async function writeNativeHostAuth(input, hooks = {}) {
|
|
|
26991
27304
|
const removingFile = host === "pi" && Object.keys(next).length === 0;
|
|
26992
27305
|
const outcome = Object.freeze(host === "pi" ? { status: "removed", file: removingFile ? "unlinked" : "replaced" } : { status: snapshot.data === undefined ? "created" : "replaced" });
|
|
26993
27306
|
if (!removingFile) {
|
|
26994
|
-
stage =
|
|
27307
|
+
stage = join16(dirname14(authPath), `.native-host-auth-write.${randomUUID16()}.tmp`);
|
|
26995
27308
|
const bytes = `${JSON.stringify(next, null, 2)}
|
|
26996
27309
|
`;
|
|
26997
27310
|
const nativeCreated = await createWindowsOwnerOnly(stage, bytes);
|
|
@@ -27866,7 +28179,7 @@ class NativeCustodyActivationError extends Error {
|
|
|
27866
28179
|
function refuse4(code) {
|
|
27867
28180
|
throw new NativeCustodyActivationError(code);
|
|
27868
28181
|
}
|
|
27869
|
-
function
|
|
28182
|
+
function isRecord13(value) {
|
|
27870
28183
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
27871
28184
|
}
|
|
27872
28185
|
function sameJson(left, right) {
|
|
@@ -27951,7 +28264,7 @@ var ACCOUNT_RUNTIME_FIELDS = [
|
|
|
27951
28264
|
"quotaErrorGeneration"
|
|
27952
28265
|
];
|
|
27953
28266
|
function vaultSettings(settings, primary) {
|
|
27954
|
-
const custody =
|
|
28267
|
+
const custody = isRecord13(settings.claustrum) ? settings.claustrum : {};
|
|
27955
28268
|
return {
|
|
27956
28269
|
...settings,
|
|
27957
28270
|
claustrum: {
|
|
@@ -28061,7 +28374,7 @@ async function preparePlan(options, journal, store) {
|
|
|
28061
28374
|
const main = pool.settings.mainAccountId;
|
|
28062
28375
|
if (typeof main !== "string" || !main)
|
|
28063
28376
|
refuse4("invalid-state");
|
|
28064
|
-
const custody =
|
|
28377
|
+
const custody = isRecord13(pool.settings.claustrum) ? pool.settings.claustrum : {};
|
|
28065
28378
|
const host = await readHostEntry(options.host, journal.hostAuthPath);
|
|
28066
28379
|
const hostAuth = {
|
|
28067
28380
|
source: host.digest,
|
|
@@ -28092,7 +28405,7 @@ async function preparePlan(options, journal, store) {
|
|
|
28092
28405
|
let roster;
|
|
28093
28406
|
let targetSettings;
|
|
28094
28407
|
if (custody.mode === "claustrum") {
|
|
28095
|
-
const pin =
|
|
28408
|
+
const pin = isRecord13(custody.primaryAccount) ? custody.primaryAccount : {};
|
|
28096
28409
|
if (oauth.length > 0 || pin.credentialId !== primary.credentialId || pin.accountId !== primary.accountIdentity)
|
|
28097
28410
|
refuse4("primary-mismatch");
|
|
28098
28411
|
if (!existing)
|
|
@@ -28143,7 +28456,7 @@ async function preparePlan(options, journal, store) {
|
|
|
28143
28456
|
} catch (error) {
|
|
28144
28457
|
if (error instanceof NativeCustodyActivationError)
|
|
28145
28458
|
throw error;
|
|
28146
|
-
return refuse4(
|
|
28459
|
+
return refuse4(isRecord13(error) && error.code === "unenrolled-local-row" ? "unenrolled-local-row" : "roster-conflict");
|
|
28147
28460
|
}
|
|
28148
28461
|
roster = existing ?? rosterProjection(seed);
|
|
28149
28462
|
targetSettings = vaultSettings(pool.settings, primary);
|
|
@@ -28295,7 +28608,7 @@ async function runNativeCustodyActivation(options, hooks = {}) {
|
|
|
28295
28608
|
if (settings.status !== "ready")
|
|
28296
28609
|
refuse4("invalid-state");
|
|
28297
28610
|
const custody = settings.settings.claustrum;
|
|
28298
|
-
if (
|
|
28611
|
+
if (isRecord13(custody) && custody.mode === "claustrum")
|
|
28299
28612
|
return { status: "already-vault", journal };
|
|
28300
28613
|
}
|
|
28301
28614
|
if (journal.activation?.kind === "activation" && journal.activation.phase === "committed")
|
|
@@ -29916,8 +30229,8 @@ function showSignInLink(text5, scrub) {
|
|
|
29916
30229
|
const links = new Set((text5.match(/https:\/\/\S+/g) ?? []).filter(isSignInLink));
|
|
29917
30230
|
const [link2] = links;
|
|
29918
30231
|
if (links.size !== 1 || link2 === undefined)
|
|
29919
|
-
return scrub(text5);
|
|
29920
|
-
return text5.split(link2).map(scrub).join(link2);
|
|
30232
|
+
return { text: scrub(text5) };
|
|
30233
|
+
return { text: text5.split(link2).map(scrub).join(link2), link: link2 };
|
|
29921
30234
|
}
|
|
29922
30235
|
var DISCONNECT_OUTCOMES = {
|
|
29923
30236
|
disconnected: {
|
|
@@ -30116,12 +30429,16 @@ function createNativeUi(options) {
|
|
|
30116
30429
|
safe = safe.split(value).join("[REDACTED]");
|
|
30117
30430
|
return redact2(safe);
|
|
30118
30431
|
};
|
|
30119
|
-
const finish = async (result2, signInLink = false) =>
|
|
30120
|
-
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30432
|
+
const finish = async (result2, signInLink = false) => {
|
|
30433
|
+
const shown = signInLink ? showSignInLink(result2.text, scrub) : { text: scrub(result2.text) };
|
|
30434
|
+
return {
|
|
30435
|
+
command: "claude",
|
|
30436
|
+
...result2,
|
|
30437
|
+
text: shown.text,
|
|
30438
|
+
...shown.link !== undefined ? { authorizationUrl: shown.link } : {},
|
|
30439
|
+
menu: await model(invocation, scrub, readable)
|
|
30440
|
+
};
|
|
30441
|
+
};
|
|
30125
30442
|
if (request?.command !== "claude" || !action || request.itemId !== undefined || request.sessionId !== undefined && request.sessionId !== invocation.sessionId) {
|
|
30126
30443
|
return finish({
|
|
30127
30444
|
ok: false,
|
|
@@ -30244,7 +30561,7 @@ function waitForRequest(pending, signal) {
|
|
|
30244
30561
|
});
|
|
30245
30562
|
}
|
|
30246
30563
|
// src/native-vault-connection.ts
|
|
30247
|
-
import { dirname as dirname17, join as
|
|
30564
|
+
import { dirname as dirname17, join as join17, resolve as resolve13 } from "node:path";
|
|
30248
30565
|
// ../../node_modules/@cortexkit/common-auth/dist/opencode2/integration.js
|
|
30249
30566
|
var PLACEHOLDER_PREFIX = "common-auth-placeholder";
|
|
30250
30567
|
var PLACEHOLDER_LIFETIME_MS = 365 * 24 * 60 * 60 * 1000;
|
|
@@ -30783,7 +31100,7 @@ function createPiSlot(options, onStep, hooks) {
|
|
|
30783
31100
|
function nativePiAuthSlotPaths(options) {
|
|
30784
31101
|
return {
|
|
30785
31102
|
authPath: resolve13(options.authPath),
|
|
30786
|
-
stashPath:
|
|
31103
|
+
stashPath: join17(dirname17(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
|
|
30787
31104
|
provider: "anthropic",
|
|
30788
31105
|
placeholderKey: placeholderSecret("anthropic")
|
|
30789
31106
|
};
|
|
@@ -30804,8 +31121,8 @@ async function disconnectNativeVaultForHost(options) {
|
|
|
30804
31121
|
import { createHash as createHash21 } from "node:crypto";
|
|
30805
31122
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
30806
31123
|
import { mkdir as mkdir14, readdir as readdir3, rm as rm8, stat as stat9, writeFile as writeFile5 } from "node:fs/promises";
|
|
30807
|
-
import { tmpdir as
|
|
30808
|
-
import { join as
|
|
31124
|
+
import { tmpdir as tmpdir7 } from "node:os";
|
|
31125
|
+
import { join as join18, resolve as resolve14 } from "node:path";
|
|
30809
31126
|
var CLAUDE_PRIME_COMMAND_NAME = "claude-prime";
|
|
30810
31127
|
var PRIME_TICK_MS = 60000;
|
|
30811
31128
|
var PRIME_DUE_OFFSET_MS = 60000;
|
|
@@ -30993,7 +31310,7 @@ function buildPrimeRequestBody() {
|
|
|
30993
31310
|
return JSON.parse(JSON.stringify(PRIME_REQUEST_BODY));
|
|
30994
31311
|
}
|
|
30995
31312
|
function defaultMarkerDir() {
|
|
30996
|
-
return
|
|
31313
|
+
return join18(tmpdir7(), "opencode-anthropic-auth", "prime");
|
|
30997
31314
|
}
|
|
30998
31315
|
function primeStorageFingerprint(storagePath) {
|
|
30999
31316
|
const absolutePath = resolve14(storagePath);
|
|
@@ -31008,19 +31325,19 @@ function primeStorageFingerprint(storagePath) {
|
|
|
31008
31325
|
return createHash21("sha256").update(canonicalPath2).digest("hex").slice(0, 12);
|
|
31009
31326
|
}
|
|
31010
31327
|
function primeMarkerNamespaceDir(markerDir, storagePath) {
|
|
31011
|
-
return
|
|
31328
|
+
return join18(markerDir, primeStorageFingerprint(storagePath));
|
|
31012
31329
|
}
|
|
31013
31330
|
function primeAccountMarkerDir(markerDir, storagePath, accountFingerprint) {
|
|
31014
31331
|
if (!/^[a-f0-9]{12,}$/i.test(accountFingerprint)) {
|
|
31015
31332
|
throw new Error("Prime account fingerprint must be a hexadecimal digest");
|
|
31016
31333
|
}
|
|
31017
|
-
return
|
|
31334
|
+
return join18(primeMarkerNamespaceDir(markerDir, storagePath), accountFingerprint.toLowerCase().slice(0, 12));
|
|
31018
31335
|
}
|
|
31019
31336
|
function primeMarkerPath(markerDir, accountId2, resetsAtEpochMs) {
|
|
31020
|
-
return
|
|
31337
|
+
return join18(markerDir, `${encodeURIComponent(accountId2)}-${resetsAtEpochMs}`);
|
|
31021
31338
|
}
|
|
31022
31339
|
function primeBootstrapMarkerPath(markerDir, accountId2) {
|
|
31023
|
-
return
|
|
31340
|
+
return join18(markerDir, `${encodeURIComponent(accountId2)}-bootstrap`);
|
|
31024
31341
|
}
|
|
31025
31342
|
function primeAccountLabel(id2, fallback) {
|
|
31026
31343
|
if (id2 === "main")
|
|
@@ -31444,7 +31761,7 @@ class PrimeManager {
|
|
|
31444
31761
|
let swept = 0;
|
|
31445
31762
|
for (const entry2 of entries) {
|
|
31446
31763
|
try {
|
|
31447
|
-
const path2 =
|
|
31764
|
+
const path2 = join18(dir, entry2);
|
|
31448
31765
|
const s = await stat9(path2);
|
|
31449
31766
|
if (s.isDirectory()) {
|
|
31450
31767
|
swept += await this.sweepMarkerDirectory(path2, now);
|
|
@@ -31478,12 +31795,12 @@ import {
|
|
|
31478
31795
|
stat as stat10,
|
|
31479
31796
|
writeFile as writeFile6
|
|
31480
31797
|
} from "node:fs/promises";
|
|
31481
|
-
import { tmpdir as
|
|
31482
|
-
import { join as
|
|
31798
|
+
import { tmpdir as tmpdir8 } from "node:os";
|
|
31799
|
+
import { join as join19 } from "node:path";
|
|
31483
31800
|
var QUOTA_HEADER_FEED_SCHEMA_VERSION = 3;
|
|
31484
31801
|
var QUOTA_HEADER_FEED_LEASE_MS = 180000;
|
|
31485
31802
|
function getDefaultQuotaHeaderFeedDirectory() {
|
|
31486
|
-
return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ??
|
|
31803
|
+
return process.env.OPENCODE_ANTHROPIC_AUTH_QUOTA_FEED_DIR ?? join19(tmpdir8(), "opencode-anthropic-auth", "quota-header-feed");
|
|
31487
31804
|
}
|
|
31488
31805
|
function configuredAnthropicOAuthAccountCount(input) {
|
|
31489
31806
|
const fallbackCount = input.storage?.accounts.filter(isOAuthAccount).length ?? 0;
|
|
@@ -31642,7 +31959,7 @@ class QuotaHeaderFeedRegistry {
|
|
|
31642
31959
|
constructor(options = {}) {
|
|
31643
31960
|
this.options = options;
|
|
31644
31961
|
const instanceId = options.instanceId ?? `${process.pid}-${randomUUID17()}`;
|
|
31645
|
-
this.filePath =
|
|
31962
|
+
this.filePath = join19(options.directory ?? getDefaultQuotaHeaderFeedDirectory(), `${instanceId}.json`);
|
|
31646
31963
|
}
|
|
31647
31964
|
publish(entry2) {
|
|
31648
31965
|
const { accountKey, quota: quota2 } = entry2;
|
|
@@ -31703,7 +32020,7 @@ class QuotaHeaderFeedRegistry {
|
|
|
31703
32020
|
return;
|
|
31704
32021
|
}
|
|
31705
32022
|
await Promise.all(names2.filter((name) => /^\d+-[0-9a-f-]+\.json$/i.test(name)).map(async (name) => {
|
|
31706
|
-
const path2 =
|
|
32023
|
+
const path2 = join19(directory, name);
|
|
31707
32024
|
if (path2 === this.filePath)
|
|
31708
32025
|
return;
|
|
31709
32026
|
try {
|
|
@@ -31732,7 +32049,7 @@ class QuotaHeaderFeedRegistry {
|
|
|
31732
32049
|
const newest = new Map;
|
|
31733
32050
|
await Promise.all(names2.map(async (name) => {
|
|
31734
32051
|
try {
|
|
31735
|
-
const record9 = JSON.parse(await readFile10(
|
|
32052
|
+
const record9 = JSON.parse(await readFile10(join19(directory, name), "utf8"));
|
|
31736
32053
|
if (record9.version !== QUOTA_HEADER_FEED_SCHEMA_VERSION || !record9.entries || typeof record9.entries !== "object")
|
|
31737
32054
|
return;
|
|
31738
32055
|
for (const [accountKey, candidate] of Object.entries(record9.entries)) {
|
|
@@ -31913,7 +32230,7 @@ function buildClaudeQuotaSummary(input) {
|
|
|
31913
32230
|
}
|
|
31914
32231
|
// src/request-gzip.ts
|
|
31915
32232
|
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
|
|
32233
|
+
import { basename as basename8, dirname as dirname18, join as join20 } from "node:path";
|
|
31917
32234
|
import { promisify } from "node:util";
|
|
31918
32235
|
import { gzip } from "node:zlib";
|
|
31919
32236
|
var gzipAsync = promisify(gzip);
|
|
@@ -32059,7 +32376,7 @@ function getRequestGzipLatch(path2) {
|
|
|
32059
32376
|
function getRequestGzipLatchPath(accountStoragePath) {
|
|
32060
32377
|
const name = basename8(accountStoragePath);
|
|
32061
32378
|
const stem = name.endsWith(".json") ? name.slice(0, -5) : name;
|
|
32062
|
-
return
|
|
32379
|
+
return join20(dirname18(accountStoragePath), `${stem}-request-gzip.json`);
|
|
32063
32380
|
}
|
|
32064
32381
|
async function decideRequestGzip(options) {
|
|
32065
32382
|
if (!CLAUDE_CODE_GZIPS_REQUEST_BODIES)
|
|
@@ -32204,7 +32521,7 @@ var REPORTED_BLOCK_TYPES = new Set([
|
|
|
32204
32521
|
"document"
|
|
32205
32522
|
]);
|
|
32206
32523
|
var EMPTY_TEXT_BLOCK_KEYS = new Set(["type", "text", "cache_control"]);
|
|
32207
|
-
function
|
|
32524
|
+
function isRecord14(value) {
|
|
32208
32525
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32209
32526
|
}
|
|
32210
32527
|
function isProvablyEmptyContent(content) {
|
|
@@ -32212,14 +32529,14 @@ function isProvablyEmptyContent(content) {
|
|
|
32212
32529
|
return content.trim() === "";
|
|
32213
32530
|
if (!Array.isArray(content))
|
|
32214
32531
|
return false;
|
|
32215
|
-
return content.every((block) =>
|
|
32532
|
+
return content.every((block) => isRecord14(block) && block.type === "text" && typeof block.text === "string" && block.text.trim() === "" && Object.keys(block).every((key) => EMPTY_TEXT_BLOCK_KEYS.has(key)));
|
|
32216
32533
|
}
|
|
32217
32534
|
function describeContent(content) {
|
|
32218
32535
|
if (Array.isArray(content)) {
|
|
32219
32536
|
return {
|
|
32220
32537
|
contentShape: "array",
|
|
32221
32538
|
contentBlockCount: content.length,
|
|
32222
|
-
contentBlockTypes: content.map((block) =>
|
|
32539
|
+
contentBlockTypes: content.map((block) => isRecord14(block) && typeof block.type === "string" && REPORTED_BLOCK_TYPES.has(block.type) ? block.type : "other")
|
|
32223
32540
|
};
|
|
32224
32541
|
}
|
|
32225
32542
|
if (typeof content === "string")
|
|
@@ -32232,7 +32549,7 @@ function assertNoMeaningfulTrailingAssistant(messages) {
|
|
|
32232
32549
|
let end = messages.length;
|
|
32233
32550
|
while (end > 0) {
|
|
32234
32551
|
const last = messages[end - 1];
|
|
32235
|
-
if (!
|
|
32552
|
+
if (!isRecord14(last) || last.role !== "assistant")
|
|
32236
32553
|
break;
|
|
32237
32554
|
if (!isProvablyEmptyContent(last.content)) {
|
|
32238
32555
|
throw new TrailingAssistantHistoryError({
|
|
@@ -32375,11 +32692,11 @@ function executeLaneStartCommand(input) {
|
|
|
32375
32692
|
}
|
|
32376
32693
|
// src/thinking-binding.ts
|
|
32377
32694
|
var THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
|
|
32378
|
-
function
|
|
32695
|
+
function isRecord15(value) {
|
|
32379
32696
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32380
32697
|
}
|
|
32381
32698
|
function isReplayableThinkingBlock(block) {
|
|
32382
|
-
if (!
|
|
32699
|
+
if (!isRecord15(block))
|
|
32383
32700
|
return false;
|
|
32384
32701
|
if (block.type === "thinking") {
|
|
32385
32702
|
return typeof block.signature === "string" && block.signature.length > 0;
|
|
@@ -32397,7 +32714,7 @@ function hasReplayableThinkingBlocks(body) {
|
|
|
32397
32714
|
if (!Array.isArray(body.messages))
|
|
32398
32715
|
return false;
|
|
32399
32716
|
return body.messages.some((message) => {
|
|
32400
|
-
if (!
|
|
32717
|
+
if (!isRecord15(message) || message.role !== "assistant")
|
|
32401
32718
|
return false;
|
|
32402
32719
|
return Array.isArray(message.content) && message.content.some(isReplayableThinkingBlock);
|
|
32403
32720
|
});
|
|
@@ -32405,11 +32722,11 @@ function hasReplayableThinkingBlocks(body) {
|
|
|
32405
32722
|
function applyThinkingBindingControls(body, behavior = "account-default") {
|
|
32406
32723
|
if (behavior === "account-default")
|
|
32407
32724
|
return false;
|
|
32408
|
-
if (!
|
|
32725
|
+
if (!resolveClaudeModelCapabilities(body.model)?.thinkingBindingControls)
|
|
32409
32726
|
return false;
|
|
32410
32727
|
if (!hasReplayableThinkingBlocks(body))
|
|
32411
32728
|
return false;
|
|
32412
|
-
if (!
|
|
32729
|
+
if (!isRecord15(body.thinking) || body.thinking.type !== "adaptive")
|
|
32413
32730
|
return false;
|
|
32414
32731
|
body.thinking.block_binding = {
|
|
32415
32732
|
prefix_mismatch_behavior: behavior
|
|
@@ -32417,13 +32734,68 @@ function applyThinkingBindingControls(body, behavior = "account-default") {
|
|
|
32417
32734
|
return true;
|
|
32418
32735
|
}
|
|
32419
32736
|
function hasThinkingBindingControls(body) {
|
|
32420
|
-
if (!
|
|
32737
|
+
if (!isRecord15(body.thinking))
|
|
32421
32738
|
return false;
|
|
32422
|
-
if (!
|
|
32739
|
+
if (!isRecord15(body.thinking.block_binding))
|
|
32423
32740
|
return false;
|
|
32424
32741
|
const behavior = body.thinking.block_binding.prefix_mismatch_behavior;
|
|
32425
32742
|
return behavior === "error" || behavior === "drop_block";
|
|
32426
32743
|
}
|
|
32744
|
+
// src/turn-end-note.ts
|
|
32745
|
+
var TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
|
|
32746
|
+
var TURN_END_NOTE_CONTENT = "Your reply above has already reached the user. The tool call after it was housekeeping and changed nothing they need to know. Do not repeat, summarize or rewrite that reply. If no new work remains, end the turn without restating anything.";
|
|
32747
|
+
var DEFAULT_TOOLS = ["board", "ctx_reduce"];
|
|
32748
|
+
function isRecord16(value) {
|
|
32749
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
32750
|
+
}
|
|
32751
|
+
function supportsTurnEndNote(model) {
|
|
32752
|
+
return resolveClaudeModelCapabilities(model)?.turnEndNote === true;
|
|
32753
|
+
}
|
|
32754
|
+
function applyTurnEndNotes(body, options = {}) {
|
|
32755
|
+
if (!supportsTurnEndNote(body.model) || !Array.isArray(body.messages))
|
|
32756
|
+
return 0;
|
|
32757
|
+
const allowed = new Set((options.tools ?? DEFAULT_TOOLS).map((name) => options.mapToolName?.(name) ?? name));
|
|
32758
|
+
if (!allowed.size)
|
|
32759
|
+
return 0;
|
|
32760
|
+
const messages = body.messages;
|
|
32761
|
+
const rewritten = [];
|
|
32762
|
+
let inserted = 0;
|
|
32763
|
+
for (let index = 0;index < messages.length; index++) {
|
|
32764
|
+
const results = messages[index];
|
|
32765
|
+
rewritten.push(results);
|
|
32766
|
+
let preceding = index - 1;
|
|
32767
|
+
while (preceding >= 0) {
|
|
32768
|
+
const control = messages[preceding];
|
|
32769
|
+
if (!isRecord16(control) || control.role !== "system" || !Array.isArray(control.content) || control.content.length !== 0 || !isRecord16(control.output_config))
|
|
32770
|
+
break;
|
|
32771
|
+
preceding--;
|
|
32772
|
+
}
|
|
32773
|
+
const assistant = messages[preceding];
|
|
32774
|
+
if (!isRecord16(assistant) || assistant.role !== "assistant" || !Array.isArray(assistant.content) || !isRecord16(results) || results.role !== "user" || !Array.isArray(results.content))
|
|
32775
|
+
continue;
|
|
32776
|
+
const visible = options.visibleText ? options.visibleText(assistant) : assistant.content.filter((block) => isRecord16(block) && block.type === "text" && typeof block.text === "string" && block.text.trim().length > 0).map((block) => block.text).join("");
|
|
32777
|
+
if (visible.length < TURN_END_NOTE_MIN_VISIBLE_CHARACTERS)
|
|
32778
|
+
continue;
|
|
32779
|
+
const calls = assistant.content.filter((block) => isRecord16(block) && block.type === "tool_use");
|
|
32780
|
+
if (!calls.length || !calls.every((call) => allowed.has(call.name)))
|
|
32781
|
+
continue;
|
|
32782
|
+
const resultIds = new Set(results.content.filter((block) => isRecord16(block) && block.type === "tool_result").map((block) => block.tool_use_id));
|
|
32783
|
+
if (!calls.every((call) => typeof call.id === "string" && resultIds.has(call.id)))
|
|
32784
|
+
continue;
|
|
32785
|
+
const next = messages[index + 1];
|
|
32786
|
+
if (isRecord16(next) && next.role === "user")
|
|
32787
|
+
continue;
|
|
32788
|
+
rewritten.push({
|
|
32789
|
+
role: "system",
|
|
32790
|
+
clear_at: "next_user_message",
|
|
32791
|
+
content: TURN_END_NOTE_CONTENT
|
|
32792
|
+
});
|
|
32793
|
+
inserted++;
|
|
32794
|
+
}
|
|
32795
|
+
if (inserted)
|
|
32796
|
+
body.messages = rewritten;
|
|
32797
|
+
return inserted;
|
|
32798
|
+
}
|
|
32427
32799
|
export {
|
|
32428
32800
|
writeNativeHostAuth,
|
|
32429
32801
|
writeDumpFile,
|
|
@@ -32465,6 +32837,7 @@ export {
|
|
|
32465
32837
|
resolveNativePoolPaths,
|
|
32466
32838
|
resolveLocalRoutingDestination,
|
|
32467
32839
|
resolveClaustrumConnectionPath,
|
|
32840
|
+
resolveClaudeModelCapabilities,
|
|
32468
32841
|
resolveClaudeCodeIdentity,
|
|
32469
32842
|
resolveClaudeCodeAccountIdentity,
|
|
32470
32843
|
resetFastModeState,
|
|
@@ -32509,6 +32882,7 @@ export {
|
|
|
32509
32882
|
primeEligibilityReasonLabel,
|
|
32510
32883
|
primeAccountMarkerDir,
|
|
32511
32884
|
prepareNativeMigration,
|
|
32885
|
+
pinsEffortOnEveryRequest,
|
|
32512
32886
|
parseSseFrame,
|
|
32513
32887
|
parseRoutingCommandAction,
|
|
32514
32888
|
parseRetryAfterHeader,
|
|
@@ -32634,6 +33008,8 @@ export {
|
|
|
32634
33008
|
getDefaultCacheKeepRegistryDirectory,
|
|
32635
33009
|
getClaustrumMode,
|
|
32636
33010
|
getClaustrumEnrollmentPaths2 as getClaustrumEnrollmentPaths,
|
|
33011
|
+
getClaudeModelCatalogue,
|
|
33012
|
+
getClaudeModelCapabilities,
|
|
32637
33013
|
getClaudeFableMythos5ReleaseDate,
|
|
32638
33014
|
getClaudeCodeIdentityForVerifiedAccount,
|
|
32639
33015
|
getClaudeCodeIdentity,
|
|
@@ -32778,6 +33154,7 @@ export {
|
|
|
32778
33154
|
PrimeManager,
|
|
32779
33155
|
PROFILE_TTL_MS,
|
|
32780
33156
|
PRODUCTION_CLAUSTRUM_CONNECTION_FILE_NAME,
|
|
33157
|
+
PRIVATE_FILES_UNAVAILABLE_MESSAGE,
|
|
32781
33158
|
PRIME_TICK_MS,
|
|
32782
33159
|
PRIME_REQUEST_BODY,
|
|
32783
33160
|
PRIME_POST_FIRE_REFRESH_MS,
|
|
@@ -32793,6 +33170,7 @@ export {
|
|
|
32793
33170
|
NativeTransientAccountError,
|
|
32794
33171
|
NativeRuntimeError,
|
|
32795
33172
|
NativeQuotaObservations,
|
|
33173
|
+
NativePrivateFilesUnavailableError,
|
|
32796
33174
|
PiSlotError as NativePiAuthSlotError,
|
|
32797
33175
|
NativeMigrationError,
|
|
32798
33176
|
NativeHostAuthError,
|
|
@@ -32845,6 +33223,7 @@ export {
|
|
|
32845
33223
|
CLAUDE_OPUS_5_5_ADAPTIVE_THINKING,
|
|
32846
33224
|
CLAUDE_MYTHOS_5_MODEL_ID,
|
|
32847
33225
|
CLAUDE_MYTHOS_5_1_MODEL_ID,
|
|
33226
|
+
CLAUDE_MODEL_CAPABILITIES,
|
|
32848
33227
|
CLAUDE_LOGGING_COMMAND_NAME,
|
|
32849
33228
|
CLAUDE_HAIKU_5_5_RELEASE_DATE,
|
|
32850
33229
|
CLAUDE_HAIKU_5_5_PRICING,
|
|
@@ -32879,6 +33258,7 @@ export {
|
|
|
32879
33258
|
CLAUDE_CODE_GZIPS_REQUEST_BODIES,
|
|
32880
33259
|
CLAUDE_CODE_FULL_AGENT_BETAS,
|
|
32881
33260
|
CLAUDE_CODE_ENTRYPOINT,
|
|
33261
|
+
CLAUDE_CODE_DEFAULT_BETAS,
|
|
32882
33262
|
CLAUDE_CACHE_KEEP_COMMAND_NAME,
|
|
32883
33263
|
CLAUDE_ACCOUNT_COMMAND_NAME,
|
|
32884
33264
|
CCH_SALT,
|