@cortexkit/anthropic-auth-core 2.2.5 → 2.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -21380,6 +21380,77 @@ function createNativeLocalCredentialService(options) {
|
|
|
21380
21380
|
return Object.freeze({ authorize: authorize2 });
|
|
21381
21381
|
}
|
|
21382
21382
|
|
|
21383
|
+
// src/native-local-publication.ts
|
|
21384
|
+
var publishers = new Map;
|
|
21385
|
+
function acquireNativeLocalPublisher(key) {
|
|
21386
|
+
let owned = publishers.get(key);
|
|
21387
|
+
if (!owned) {
|
|
21388
|
+
owned = { writer: createPublisher(), leases: 0 };
|
|
21389
|
+
publishers.set(key, owned);
|
|
21390
|
+
}
|
|
21391
|
+
owned.leases++;
|
|
21392
|
+
let released = false;
|
|
21393
|
+
return {
|
|
21394
|
+
...owned.writer,
|
|
21395
|
+
release() {
|
|
21396
|
+
if (released)
|
|
21397
|
+
return;
|
|
21398
|
+
released = true;
|
|
21399
|
+
if (--owned.leases === 0)
|
|
21400
|
+
publishers.delete(key);
|
|
21401
|
+
}
|
|
21402
|
+
};
|
|
21403
|
+
}
|
|
21404
|
+
function createPublisher() {
|
|
21405
|
+
let tail = Promise.resolve();
|
|
21406
|
+
const pending = new Map;
|
|
21407
|
+
const run = (write) => {
|
|
21408
|
+
const result = tail.then(write);
|
|
21409
|
+
tail = result.catch(() => {});
|
|
21410
|
+
return result;
|
|
21411
|
+
};
|
|
21412
|
+
return {
|
|
21413
|
+
run,
|
|
21414
|
+
enqueue(key, patch, write) {
|
|
21415
|
+
const queued = pending.get(key);
|
|
21416
|
+
if (queued) {
|
|
21417
|
+
const previous = queued.patch;
|
|
21418
|
+
if (previous.quota && patch.quota && patch.quota.source !== "headers" && quotaSnapshotCheckedAt(previous.quota) > quotaSnapshotCheckedAt(patch.quota))
|
|
21419
|
+
return Promise.resolve(false);
|
|
21420
|
+
queued.patch = { ...previous, ...patch };
|
|
21421
|
+
if (previous.quota && patch.quota)
|
|
21422
|
+
queued.patch.quota = fromNativeQuotaMap(nativeQuotaCodec.merge(toNativeQuotaMap(previous.quota), toNativeQuotaMap(patch.quota)));
|
|
21423
|
+
if (previous.lastUsed !== undefined || patch.lastUsed !== undefined)
|
|
21424
|
+
queued.patch.lastUsed = Math.max(previous.lastUsed ?? 0, patch.lastUsed ?? 0);
|
|
21425
|
+
for (const field of [
|
|
21426
|
+
"quotaErrorClearedAt",
|
|
21427
|
+
"quotaErrorGeneration"
|
|
21428
|
+
])
|
|
21429
|
+
if (previous[field] !== undefined || patch[field] !== undefined)
|
|
21430
|
+
queued.patch[field] = Math.max(previous[field] ?? 0, patch[field] ?? 0);
|
|
21431
|
+
if (previous.lastQuotaRefreshError && patch.lastQuotaRefreshError && previous.lastQuotaRefreshError.checkedAt > patch.lastQuotaRefreshError.checkedAt)
|
|
21432
|
+
queued.patch.lastQuotaRefreshError = previous.lastQuotaRefreshError;
|
|
21433
|
+
return queued.result;
|
|
21434
|
+
}
|
|
21435
|
+
const batch = { patch, result: Promise.resolve(false) };
|
|
21436
|
+
pending.set(key, batch);
|
|
21437
|
+
batch.result = run(async () => {
|
|
21438
|
+
await new Promise((resolve10) => setTimeout(resolve10, 0));
|
|
21439
|
+
pending.delete(key);
|
|
21440
|
+
return write(batch.patch);
|
|
21441
|
+
});
|
|
21442
|
+
return batch.result;
|
|
21443
|
+
},
|
|
21444
|
+
async drain() {
|
|
21445
|
+
let observed;
|
|
21446
|
+
do {
|
|
21447
|
+
observed = tail;
|
|
21448
|
+
await observed;
|
|
21449
|
+
} while (observed !== tail);
|
|
21450
|
+
}
|
|
21451
|
+
};
|
|
21452
|
+
}
|
|
21453
|
+
|
|
21383
21454
|
// src/native-usage-publication.ts
|
|
21384
21455
|
import { types as types3 } from "node:util";
|
|
21385
21456
|
function usagePublicationRefusalIsFatal(error) {
|
|
@@ -21526,7 +21597,7 @@ class NativeQuotaObservations extends Map {
|
|
|
21526
21597
|
let clearAt;
|
|
21527
21598
|
let matched = false;
|
|
21528
21599
|
for (const observation of this.values()) {
|
|
21529
|
-
if (observation.entry.quota.source === "headers")
|
|
21600
|
+
if (observation.entry.quota.source === "headers" && observation.routeBeforeSave !== true)
|
|
21530
21601
|
continue;
|
|
21531
21602
|
if (observation.lineage !== lineage || observation.accountUuid !== accountUuid2 || getQuotaNextRefreshAt(observation.entry.quota, storage, observation.entry.checkedAt) <= now)
|
|
21532
21603
|
continue;
|
|
@@ -21556,6 +21627,17 @@ class NativeQuotaObservations extends Map {
|
|
|
21556
21627
|
}
|
|
21557
21628
|
}));
|
|
21558
21629
|
}
|
|
21630
|
+
hold(accountId, observation) {
|
|
21631
|
+
const current = this.get(accountId);
|
|
21632
|
+
if (current && current.lineage === observation.lineage && quotaSnapshotCheckedAt(current.entry.quota) > quotaSnapshotCheckedAt(observation.entry.quota))
|
|
21633
|
+
return false;
|
|
21634
|
+
this.set(accountId, observation);
|
|
21635
|
+
return true;
|
|
21636
|
+
}
|
|
21637
|
+
forget(accountId, observation) {
|
|
21638
|
+
if (this.get(accountId) === observation)
|
|
21639
|
+
this.delete(accountId);
|
|
21640
|
+
}
|
|
21559
21641
|
drain() {
|
|
21560
21642
|
return this.publications.drain();
|
|
21561
21643
|
}
|
|
@@ -24111,27 +24193,30 @@ function decideStickyQuotaFailure(input) {
|
|
|
24111
24193
|
const quota2 = knownQuota(input.quota);
|
|
24112
24194
|
if (!quota2)
|
|
24113
24195
|
return { action: "retain", reason: "unknown" };
|
|
24114
|
-
|
|
24115
|
-
|
|
24116
|
-
|
|
24117
|
-
|
|
24118
|
-
|
|
24119
|
-
|
|
24120
|
-
|
|
24121
|
-
|
|
24122
|
-
|
|
24123
|
-
|
|
24124
|
-
|
|
24125
|
-
if (
|
|
24126
|
-
|
|
24127
|
-
|
|
24128
|
-
|
|
24129
|
-
|
|
24130
|
-
|
|
24131
|
-
|
|
24132
|
-
|
|
24196
|
+
let blocking;
|
|
24197
|
+
for (const [reason, window2] of [
|
|
24198
|
+
["model-scoped", getScopedQuotaWindowForModel(quota2, input.modelId)],
|
|
24199
|
+
["seven-day", quota2.seven_day],
|
|
24200
|
+
["five-hour", quota2.five_hour]
|
|
24201
|
+
]) {
|
|
24202
|
+
if (!window2 || !Number.isFinite(window2.remainingPercent) || window2.remainingPercent > 0)
|
|
24203
|
+
continue;
|
|
24204
|
+
const resetAt = window2.resetsAt ? Date.parse(window2.resetsAt) : NaN;
|
|
24205
|
+
if (!Number.isFinite(resetAt) || resetAt <= now)
|
|
24206
|
+
return { action: "migrate", reason };
|
|
24207
|
+
if (!blocking || resetAt > blocking.resetAt)
|
|
24208
|
+
blocking = { resetAt, reason };
|
|
24209
|
+
}
|
|
24210
|
+
if (!blocking)
|
|
24211
|
+
return { action: "retain", reason: "not-exhausted" };
|
|
24212
|
+
if (blocking.resetAt - now <= STICKY_ROUTING_SHORT_RESET_GRACE_MS) {
|
|
24213
|
+
return {
|
|
24214
|
+
action: "hold",
|
|
24215
|
+
reason: `${blocking.reason}-short-reset`,
|
|
24216
|
+
retryAfterSeconds: Math.max(1, Math.ceil((blocking.resetAt - now) / 1000))
|
|
24217
|
+
};
|
|
24133
24218
|
}
|
|
24134
|
-
return { action: "
|
|
24219
|
+
return { action: "migrate", reason: blocking.reason };
|
|
24135
24220
|
}
|
|
24136
24221
|
function getStickyRoutingStatePath(accountStoragePath) {
|
|
24137
24222
|
const name = basename6(accountStoragePath);
|
|
@@ -25782,6 +25867,11 @@ async function sendViaRelay(options) {
|
|
|
25782
25867
|
responseMode ??= requestResponseMode(bodyText);
|
|
25783
25868
|
return responseMode;
|
|
25784
25869
|
};
|
|
25870
|
+
let directFallbackStarted = false;
|
|
25871
|
+
const directFallback = () => {
|
|
25872
|
+
directFallbackStarted = true;
|
|
25873
|
+
return fallback();
|
|
25874
|
+
};
|
|
25785
25875
|
try {
|
|
25786
25876
|
let result;
|
|
25787
25877
|
const sendStart = perfNowMs();
|
|
@@ -25802,7 +25892,7 @@ async function sendViaRelay(options) {
|
|
|
25802
25892
|
payload,
|
|
25803
25893
|
bodyText,
|
|
25804
25894
|
requestMode,
|
|
25805
|
-
fallback,
|
|
25895
|
+
fallback: directFallback,
|
|
25806
25896
|
signal: init?.signal,
|
|
25807
25897
|
authorizeAttempt
|
|
25808
25898
|
});
|
|
@@ -25813,7 +25903,7 @@ async function sendViaRelay(options) {
|
|
|
25813
25903
|
payload,
|
|
25814
25904
|
bodyText,
|
|
25815
25905
|
requestMode,
|
|
25816
|
-
fallback,
|
|
25906
|
+
fallback: directFallback,
|
|
25817
25907
|
signal: init?.signal,
|
|
25818
25908
|
authorizeAttempt
|
|
25819
25909
|
});
|
|
@@ -25873,6 +25963,10 @@ async function sendViaRelay(options) {
|
|
|
25873
25963
|
throw error.failure;
|
|
25874
25964
|
if (error instanceof RelayResponseMetadataError)
|
|
25875
25965
|
throw error;
|
|
25966
|
+
if (directFallbackStarted) {
|
|
25967
|
+
relayLog(`direct fallback failed session=${shortAffinity2(affinity)}; not sending it again code=relay_transport_error`);
|
|
25968
|
+
throw error;
|
|
25969
|
+
}
|
|
25876
25970
|
if (!config.fallbackToDirect) {
|
|
25877
25971
|
relayLog(`relay failed session=${shortAffinity2(affinity)} and fallbackToDirect=false code=relay_transport_error`);
|
|
25878
25972
|
throw error;
|
|
@@ -26265,11 +26359,12 @@ function acquireNativeAccountRuntime(options) {
|
|
|
26265
26359
|
const quotaObservations = use().quotaObservations;
|
|
26266
26360
|
const onLockEvent = use().onLockEvent;
|
|
26267
26361
|
const drainRoutingPublications = use().drainRoutingPublications;
|
|
26362
|
+
const drainQuotaPublications = use().drainQuotaPublications;
|
|
26268
26363
|
return {
|
|
26269
26364
|
onLockEvent,
|
|
26270
26365
|
vault,
|
|
26271
26366
|
quotaObservations,
|
|
26272
|
-
drainQuotaPublications
|
|
26367
|
+
drainQuotaPublications,
|
|
26273
26368
|
drainRoutingPublications,
|
|
26274
26369
|
getRelayConfig: () => use().getRelayConfig(),
|
|
26275
26370
|
getSettingsPath: () => use().getSettingsPath(),
|
|
@@ -26297,7 +26392,10 @@ function acquireNativeAccountRuntime(options) {
|
|
|
26297
26392
|
fetchProfileForDisplay: (id2, transport, signal) => use().fetchProfileForDisplay(id2, transport, signal),
|
|
26298
26393
|
close: () => {
|
|
26299
26394
|
vault.close();
|
|
26300
|
-
return
|
|
26395
|
+
return Promise.all([
|
|
26396
|
+
drainQuotaPublications(),
|
|
26397
|
+
drainRoutingPublications()
|
|
26398
|
+
]).then(() => {});
|
|
26301
26399
|
}
|
|
26302
26400
|
};
|
|
26303
26401
|
}
|
|
@@ -26337,6 +26435,9 @@ function createNativeAccountRuntime(options) {
|
|
|
26337
26435
|
}
|
|
26338
26436
|
});
|
|
26339
26437
|
const shutdown = new AbortController;
|
|
26438
|
+
let closing;
|
|
26439
|
+
const quotaPublications = acquireNativeLocalPublisher(paths.config);
|
|
26440
|
+
const metadataPublications = acquireNativeLocalPublisher(paths.runtime);
|
|
26340
26441
|
const store = createNativePoolStore({
|
|
26341
26442
|
paths,
|
|
26342
26443
|
quota: nativeQuotaCodec,
|
|
@@ -26459,6 +26560,51 @@ function createNativeAccountRuntime(options) {
|
|
|
26459
26560
|
throw error;
|
|
26460
26561
|
}
|
|
26461
26562
|
}
|
|
26563
|
+
async function localMetadataMatches(subject) {
|
|
26564
|
+
const binding2 = subject.binding;
|
|
26565
|
+
const row = await poolRow(binding2.rowId);
|
|
26566
|
+
if (row?.stamp !== "bound" || !row.credential || !nativeLocalPoolBindingMatches(binding2, paths, row))
|
|
26567
|
+
return false;
|
|
26568
|
+
if ("kind" in subject)
|
|
26569
|
+
return row.credential.type === "api" && fingerprintOf(row.credential) === subject.credentialFingerprint && row.credential.baseURL === subject.baseURL && row.credential.authHeader === subject.authHeader;
|
|
26570
|
+
return row.credential.type === "oauth" && fingerprintOf(row.credential) === subject.credentialFingerprint && nativeLocalCredentialValidationMatches(subject, binding2, row.credential);
|
|
26571
|
+
}
|
|
26572
|
+
async function localMetadataWrite(subject, change) {
|
|
26573
|
+
const binding2 = subject.binding;
|
|
26574
|
+
if (await authority() !== "local")
|
|
26575
|
+
return false;
|
|
26576
|
+
const matches2 = await localMetadataMatches(subject);
|
|
26577
|
+
await localAuthority();
|
|
26578
|
+
if (!matches2)
|
|
26579
|
+
return false;
|
|
26580
|
+
try {
|
|
26581
|
+
await updateNativeRuntime(paths.runtime, paths.storageId, (current) => {
|
|
26582
|
+
const old = current.accounts[binding2.rowId];
|
|
26583
|
+
const previous = old?.binding;
|
|
26584
|
+
const same = previous?.kind === "local" && previous.rowId === binding2.rowId && previous.identity === binding2.identity && previous.credentialEpoch === binding2.credentialEpoch;
|
|
26585
|
+
current.accounts[binding2.rowId] = change(same && old ? old : { binding: binding2 });
|
|
26586
|
+
return current;
|
|
26587
|
+
}, {
|
|
26588
|
+
onLockEvent: options.local?.onLockEvent,
|
|
26589
|
+
beforeRename: async () => {
|
|
26590
|
+
if (!await localMetadataMatches(subject))
|
|
26591
|
+
throw new NativeRuntimeError("publication-refused");
|
|
26592
|
+
await localAuthority();
|
|
26593
|
+
},
|
|
26594
|
+
beforePublish: () => localAuthority()
|
|
26595
|
+
});
|
|
26596
|
+
if (await authority() !== "local")
|
|
26597
|
+
throw new NativeRuntimeError("publication-refused");
|
|
26598
|
+
return true;
|
|
26599
|
+
} catch (error) {
|
|
26600
|
+
if (error instanceof NativeRuntimeError && (error.code === "runtime-conflict" || error.code === "publication-refused")) {
|
|
26601
|
+
if (await authority() !== "local")
|
|
26602
|
+
throw error;
|
|
26603
|
+
return false;
|
|
26604
|
+
}
|
|
26605
|
+
throw error;
|
|
26606
|
+
}
|
|
26607
|
+
}
|
|
26462
26608
|
async function initializeCredentialEpoch(id2) {
|
|
26463
26609
|
const row = await poolRow(id2);
|
|
26464
26610
|
if (!row?.credential || row.credentialEpoch === undefined)
|
|
@@ -26594,7 +26740,13 @@ function createNativeAccountRuntime(options) {
|
|
|
26594
26740
|
onLockEvent,
|
|
26595
26741
|
vault,
|
|
26596
26742
|
quotaObservations: vault.quotaObservations,
|
|
26597
|
-
drainQuotaPublications: () =>
|
|
26743
|
+
drainQuotaPublications: async () => {
|
|
26744
|
+
await vault.quotaObservations.drain();
|
|
26745
|
+
await Promise.all([
|
|
26746
|
+
quotaPublications.drain(),
|
|
26747
|
+
metadataPublications.drain()
|
|
26748
|
+
]);
|
|
26749
|
+
},
|
|
26598
26750
|
drainRoutingPublications: () => vaultRouter.drain(),
|
|
26599
26751
|
async getRelayConfig() {
|
|
26600
26752
|
const { mode, paths: paths2, store: store2 } = await selectedStorage();
|
|
@@ -26857,11 +27009,12 @@ function createNativeAccountRuntime(options) {
|
|
|
26857
27009
|
} catch {
|
|
26858
27010
|
throw new Error("Claude account identity could not be verified; retry sign-in. No account changes were saved.");
|
|
26859
27011
|
}
|
|
27012
|
+
const { access, refresh, expires } = input.credential;
|
|
26860
27013
|
return runtime2.putAccount({
|
|
26861
27014
|
...input,
|
|
26862
27015
|
accountIdentity,
|
|
26863
27016
|
replace: input.replace ?? true,
|
|
26864
|
-
credential: { type: "oauth",
|
|
27017
|
+
credential: { type: "oauth", access, refresh, expires }
|
|
26865
27018
|
});
|
|
26866
27019
|
},
|
|
26867
27020
|
async putAccount(input) {
|
|
@@ -27052,30 +27205,45 @@ function createNativeAccountRuntime(options) {
|
|
|
27052
27205
|
};
|
|
27053
27206
|
},
|
|
27054
27207
|
async publishLocal(subject, rawPatch) {
|
|
27055
|
-
const
|
|
27056
|
-
|
|
27057
|
-
|
|
27058
|
-
|
|
27059
|
-
const
|
|
27060
|
-
|
|
27061
|
-
if (row?.stamp !== "bound" || row.credential?.type !== "oauth" || !nativeLocalPoolBindingMatches(subject.binding, paths, row) || !quotaOnly && !nativeLocalCredentialValidationMatches(subject, subject.binding, row.credential))
|
|
27062
|
-
return false;
|
|
27063
|
-
if (quota2) {
|
|
27064
|
-
if (quota2.source !== "headers" && row.quota && quotaSnapshotCheckedAt(fromNativeQuotaMap(row.quota)) > quotaSnapshotCheckedAt(quota2))
|
|
27208
|
+
const captured = captureNativeMetadataPatch(rawPatch);
|
|
27209
|
+
const { quota: _quota, ...metadata2 } = captured;
|
|
27210
|
+
const mixed = captured.quota !== undefined && Object.keys(metadata2).length > 0;
|
|
27211
|
+
let admission;
|
|
27212
|
+
const admitted = () => admission ??= (async () => {
|
|
27213
|
+
if (await authority() !== "local")
|
|
27065
27214
|
return false;
|
|
27066
|
-
|
|
27067
|
-
|
|
27068
|
-
|
|
27069
|
-
|
|
27070
|
-
|
|
27071
|
-
|
|
27072
|
-
|
|
27073
|
-
|
|
27215
|
+
const matches2 = await localMetadataMatches(subject);
|
|
27216
|
+
await localAuthority();
|
|
27217
|
+
return matches2;
|
|
27218
|
+
})();
|
|
27219
|
+
const key = JSON.stringify(subject);
|
|
27220
|
+
const writes = [];
|
|
27221
|
+
if (captured.quota)
|
|
27222
|
+
writes.push(quotaPublications.enqueue(mixed ? `${key}:mixed` : key, { quota: captured.quota }, async ({ quota: quota2 }) => {
|
|
27223
|
+
if (mixed && !await admitted())
|
|
27224
|
+
return false;
|
|
27225
|
+
if (!quota2 || await authority() !== "local")
|
|
27226
|
+
return false;
|
|
27227
|
+
const row = await poolRow(subject.binding.rowId);
|
|
27228
|
+
if (row?.stamp !== "bound" || row.credential?.type !== "oauth" || !nativeLocalPoolBindingMatches(subject.binding, paths, row) || quota2.accountIdentity !== subject.binding.identity)
|
|
27229
|
+
return false;
|
|
27230
|
+
if (quota2.source !== "headers" && row.quota && quotaSnapshotCheckedAt(fromNativeQuotaMap(row.quota)) > quotaSnapshotCheckedAt(quota2))
|
|
27231
|
+
return false;
|
|
27232
|
+
await store.recordQuota(subject.binding.rowId, {
|
|
27233
|
+
credentialEpoch: subject.binding.credentialEpoch,
|
|
27234
|
+
identity: subject.binding.identity
|
|
27235
|
+
}, toNativeQuotaMap(quota2));
|
|
27236
|
+
return true;
|
|
27237
|
+
}));
|
|
27238
|
+
if (Object.keys(metadata2).length)
|
|
27239
|
+
writes.push(metadataPublications.enqueue(mixed ? `${key}:mixed` : key, metadata2, async (patch) => {
|
|
27240
|
+
if (mixed && !await admitted())
|
|
27241
|
+
return false;
|
|
27242
|
+
return localMetadataWrite(subject, (old) => applyNativeMetadataPatch(old, patch));
|
|
27243
|
+
}));
|
|
27244
|
+
return (await Promise.all(writes)).every(Boolean);
|
|
27074
27245
|
},
|
|
27075
|
-
publishApi: (subject, patch) =>
|
|
27076
|
-
...old,
|
|
27077
|
-
lastUsed: Math.max(old.lastUsed ?? 0, patch.lastUsed)
|
|
27078
|
-
})),
|
|
27246
|
+
publishApi: (subject, patch) => metadataPublications.enqueue(JSON.stringify(subject), patch, (merged) => localMetadataWrite(subject, (old) => applyNativeMetadataPatch(old, merged))),
|
|
27079
27247
|
async resetBackoff(routeId, fence, kind = "all") {
|
|
27080
27248
|
if ("accessToken" in fence)
|
|
27081
27249
|
return vault.resetBackoff(fence, kind);
|
|
@@ -27107,13 +27275,13 @@ function createNativeAccountRuntime(options) {
|
|
|
27107
27275
|
if (await physicalId(routeId) !== fence.binding.rowId)
|
|
27108
27276
|
return;
|
|
27109
27277
|
let lineage;
|
|
27110
|
-
const kept = await
|
|
27278
|
+
const kept = await metadataPublications.run(() => localMetadataWrite(fence, (old) => {
|
|
27111
27279
|
lineage = old.authLineageId ?? randomUUID15();
|
|
27112
27280
|
return {
|
|
27113
27281
|
...old,
|
|
27114
27282
|
authLineageId: lineage
|
|
27115
27283
|
};
|
|
27116
|
-
});
|
|
27284
|
+
}));
|
|
27117
27285
|
return kept ? lineage : undefined;
|
|
27118
27286
|
},
|
|
27119
27287
|
async incrementPrimeUsage(routeId, fence, delta = {}) {
|
|
@@ -27124,7 +27292,7 @@ function createNativeAccountRuntime(options) {
|
|
|
27124
27292
|
if (await physicalId(routeId) !== fence.binding.rowId)
|
|
27125
27293
|
return false;
|
|
27126
27294
|
const captured = primeDelta(delta);
|
|
27127
|
-
return
|
|
27295
|
+
return metadataPublications.run(() => localMetadataWrite(fence, (old) => ({
|
|
27128
27296
|
...old,
|
|
27129
27297
|
prime: {
|
|
27130
27298
|
count: (old.prime?.count ?? 0) + 1,
|
|
@@ -27132,7 +27300,7 @@ function createNativeAccountRuntime(options) {
|
|
|
27132
27300
|
outputTokens: (old.prime?.outputTokens ?? 0) + captured.outputTokens,
|
|
27133
27301
|
since: old.prime?.since ?? now()
|
|
27134
27302
|
}
|
|
27135
|
-
}));
|
|
27303
|
+
})));
|
|
27136
27304
|
},
|
|
27137
27305
|
async fetchQuota(routeId, fetchImpl = fetch, signal, dispatch, purpose) {
|
|
27138
27306
|
const snapshot = await runtime2.read();
|
|
@@ -27196,11 +27364,16 @@ function createNativeAccountRuntime(options) {
|
|
|
27196
27364
|
});
|
|
27197
27365
|
},
|
|
27198
27366
|
close() {
|
|
27199
|
-
if (
|
|
27367
|
+
if (closing)
|
|
27368
|
+
return closing;
|
|
27369
|
+
const draining = runtime2.drainQuotaPublications();
|
|
27370
|
+
vault.close();
|
|
27371
|
+
closing = Promise.all([draining, vaultRouter.drain()]).then(() => {}).finally(() => {
|
|
27200
27372
|
shutdown.abort(new NativeCustodyError("closed"));
|
|
27201
|
-
|
|
27202
|
-
|
|
27203
|
-
|
|
27373
|
+
quotaPublications.release();
|
|
27374
|
+
metadataPublications.release();
|
|
27375
|
+
});
|
|
27376
|
+
return closing;
|
|
27204
27377
|
}
|
|
27205
27378
|
};
|
|
27206
27379
|
function readLocalProfile(id2, fetchImpl, signal) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NativeAccountMetadataPatch } from './native-account-view.ts';
|
|
2
|
+
/** Share one replaceable bookkeeping mailbox per destination in this process, never for credential writes. */
|
|
3
|
+
export declare function acquireNativeLocalPublisher(key: string): {
|
|
4
|
+
release(): void;
|
|
5
|
+
run: <T>(write: () => Promise<T>) => Promise<T>;
|
|
6
|
+
enqueue(key: string, patch: NativeAccountMetadataPatch, write: (patch: NativeAccountMetadataPatch) => Promise<boolean>): Promise<boolean>;
|
|
7
|
+
drain(): Promise<void>;
|
|
8
|
+
};
|
|
@@ -7,6 +7,14 @@ export type NativeQuotaObservation = {
|
|
|
7
7
|
entry: QuotaEntry;
|
|
8
8
|
generalExhausted: boolean;
|
|
9
9
|
quotaErrorClearedAt?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Set on a response-header reading from a host that routes on native
|
|
12
|
+
* snapshots (OpenCode 2). The snapshot overlay then applies it while its
|
|
13
|
+
* detached save is still pending, as it does for poll readings. Header
|
|
14
|
+
* readings without it stay host-owned: OpenCode 1 applies its own routing
|
|
15
|
+
* and display rules to them.
|
|
16
|
+
*/
|
|
17
|
+
routeBeforeSave?: boolean;
|
|
10
18
|
};
|
|
11
19
|
export declare function nativePollQuotaGenerallyExhausted(quota: OAuthQuotaSnapshot): boolean;
|
|
12
20
|
export declare function nativeLocalQuotaLineage(binding: NativeLocalPoolBinding & {
|
|
@@ -22,5 +30,14 @@ export declare class NativeQuotaObservations extends Map<string, NativeQuotaObse
|
|
|
22
30
|
clearAt?: number;
|
|
23
31
|
} | undefined;
|
|
24
32
|
publish(accountId: string, observation: NativeQuotaObservation, write: () => Promise<boolean>): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Registers a response-header reading before its detached save starts, so
|
|
35
|
+
* routing in this process sees it while the save waits on file locks. A
|
|
36
|
+
* reading older than the one already held for the same credential lineage
|
|
37
|
+
* is not registered, so an older reading never replaces a newer one.
|
|
38
|
+
*/
|
|
39
|
+
hold(accountId: string, observation: NativeQuotaObservation): boolean;
|
|
40
|
+
/** Forgets a held reading whose save was refused, unless a later reading already replaced it. */
|
|
41
|
+
forget(accountId: string, observation: NativeQuotaObservation): void;
|
|
25
42
|
drain(): Promise<void>;
|
|
26
43
|
}
|
package/dist/native-runtime.d.ts
CHANGED
|
@@ -104,10 +104,10 @@ export interface NativeRuntimeWriteHooks {
|
|
|
104
104
|
/** This writer alone uses `<leaf>.native-runtime.<UUID v4>.partial`. */
|
|
105
105
|
export declare function isNativeRuntimeStagingName(path: string, name: string): boolean;
|
|
106
106
|
/**
|
|
107
|
-
* This file has its own update lock.
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
107
|
+
* This file has its own update lock. Advisory account publishers recheck the
|
|
108
|
+
* pool or roster binding without taking its lock immediately before replacement;
|
|
109
|
+
* readers reject metadata whose binding no longer matches. Credential writers
|
|
110
|
+
* retain their separate ownership and custody checks.
|
|
111
111
|
*/
|
|
112
112
|
export declare function updateNativeRuntime(path: string, storageId: string, change: (current: NativeRuntimeState) => NativeRuntimeState | Promise<NativeRuntimeState>, hooks?: NativeRuntimeWriteHooks): Promise<NativeRuntimeState>;
|
|
113
113
|
/**
|
package/dist/pool-store.d.ts
CHANGED
|
@@ -15,8 +15,9 @@ export interface NativePoolStoreOptions extends Pick<OpenPoolStoreOptions, 'now'
|
|
|
15
15
|
onLockEvent?: (event: NativeLockEvent) => void;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* These
|
|
19
|
-
*
|
|
18
|
+
* These locks serialize pool transactions, including credential changes and
|
|
19
|
+
* quota publication. Runtime bookkeeping has its own lock and binding checks.
|
|
20
|
+
* Legacy sidecar writers use different files and locks.
|
|
20
21
|
*/
|
|
21
22
|
export declare function nativePoolStoreLocks(paths: NativePoolStorePaths): readonly [{
|
|
22
23
|
readonly path: string;
|
package/dist/sticky-routing.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export type StickyQuotaFailureDecision = {
|
|
|
45
45
|
reason: 'not-exhausted' | 'unknown';
|
|
46
46
|
} | {
|
|
47
47
|
action: 'hold';
|
|
48
|
-
reason: 'five-hour-short-reset';
|
|
48
|
+
reason: 'five-hour-short-reset' | 'seven-day-short-reset' | 'model-scoped-short-reset';
|
|
49
49
|
retryAfterSeconds: number;
|
|
50
50
|
} | {
|
|
51
51
|
action: 'migrate';
|