@cortexkit/anthropic-auth-core 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import type { QuotaObservation } from '../quota/index.js';
3
3
  import type { RoutingRow } from '../routing/index.js';
4
4
  import { type ClaustrumFamily, type ClaustrumScopedAttempt, type ClaustrumScopedClient, type IdentityParser, type KeptReceiptState, type VaultGrantReach } from './custody.js';
5
5
  import { type ClaustrumLogger } from './errors.js';
6
- import { type InsulaQuotaOptions } from './insula.js';
6
+ import { type InsulaQuotaOptions, type InsulaQuotaResult } from './insula.js';
7
7
  import { type AccountMapper, type QuotaReceipt, type VaultRosterFile } from './roster.js';
8
8
  import { type WatchMode } from './watch.js';
9
9
  export interface ClaustrumConsumerOptions<Q = QuotaObservation> {
@@ -134,6 +134,10 @@ export declare class ClaustrumConsumer<Q = QuotaObservation> {
134
134
  * A route without a known provider account cannot join an insula entry.
135
135
  */
136
136
  cachedInsulaQuotaForRoute(routeId: string): Promise<Q | undefined>;
137
+ /** Cache-only background lookup, preserving the reason a route has no reading. */
138
+ lookupInsulaQuotaForRoute(routeId: string): Promise<InsulaQuotaResult<Q>>;
139
+ /** Skip the fallback poll while insula is cold or its upstream fetch failed. */
140
+ pollInsulaQuotaForRoute(routeId: string, fallback: () => Promise<Q | undefined>): Promise<Q | undefined>;
137
141
  /**
138
142
  * Authorize one physical send on a vault route. The roster file is re-read
139
143
  * first, so a decline committed by another process applies before the next
@@ -7,7 +7,7 @@ export { type AccountIdentitySource, type ClaustrumFamily, type ClaustrumRosterW
7
7
  export { type ClaustrumEnrollmentClient, type ClaustrumEnrollmentConnection, type ClaustrumEnrollmentDisconnectResult, ClaustrumEnrollmentManager, type ClaustrumEnrollmentPaths, type ClaustrumEnrollmentResetResult, type ClaustrumEnrollmentStatus, classifyEnrollmentError, connectClaustrumEnrollmentClient, disconnectClaustrumEnrollment, type EnrollmentDisposition, enrollmentAuthority, enrollmentName, getClaustrumEnrollmentPaths, hostEnrollmentPaths, RETRYABLE_ENROLLMENT_CODES, readClaustrumEnrollmentStatus, readClaustrumEnrollmentToken, resetClaustrumEnrollmentState, TERMINAL_ENROLLMENT_CODES, } from './enrollment.js';
8
8
  export { ClaustrumConsumerError, type ClaustrumConsumerFailureKind, type ClaustrumLogger, } from './errors.js';
9
9
  export { assertHostSlotMatchesMode, assertNotCustodyPlaceholder, CUSTODY_PLACEHOLDER_PREFIX, classifyHostSlot, custodyPlaceholder, custodyPlaceholderKey, type HostSlotContent, isCustodyPlaceholder, isCustodyPlaceholderValue, } from './host-slot.js';
10
- export { acquireInsulaQuotaSource, type InsulaQuotaContext, type InsulaQuotaOptions, type InsulaQuotaSource, type InsulaUsageEntry, type InsulaUsageTransport, type InsulaUsageWatch, type InsulaUsageWindow, type InsulaWatchOptions, } from './insula.js';
10
+ export { acquireInsulaQuotaSource, type InsulaQuotaContext, type InsulaQuotaLookup, type InsulaQuotaMiss, type InsulaQuotaOptions, type InsulaQuotaReading, type InsulaQuotaResult, type InsulaQuotaSource, type InsulaUsageEntry, type InsulaUsageTransport, type InsulaUsageWatch, type InsulaUsageWindow, type InsulaWatchOptions, } from './insula.js';
11
11
  export { acceptAccount, type DeclinedAccount, declineAccount, isDeclined, } from './interlock.js';
12
12
  export { type AccountMapper, acceptVaultRoute, DEFAULT_ROUTE_PREFIX, declineVaultRoute, type MutateVaultRosterOptions, mutateVaultRoster, type ProjectionOptions, projectVaultRoster, type QuotaReceipt, readVaultRoster, recordVaultAccountQuota, recordVaultQuota, refreshVaultRoster, resolveVaultPrimary, type VaultPrimary, type VaultPrimaryBinding, type VaultPrimaryUnavailableReason, type VaultRosterFile, type VaultRosterLockContext, type VaultRosterRow, vaultRoutingRows, } from './roster.js';
13
13
  export { type ChangeNotice, ChangeNoticeReader, RESUBSCRIBE_BACKOFF_MS, SAFETY_POLL_MS, ScopedRosterWatch, type ScopedRosterWatchOptions, type ScopedWatchEnd, type ScopedWatchHandle, type ScopedWatchNoticeShape, type ScopedWatchSource, WATCH_RETRY_MS, type WatchMode, } from './watch.js';
@@ -34,6 +34,27 @@ export interface InsulaQuotaContext {
34
34
  fetchedAt: number;
35
35
  source?: string;
36
36
  }
37
+ export type InsulaQuotaMiss = 'cold' | 'stale' | 'absent' | 'upstream-failed' | 'credential' | 'unreachable';
38
+ export interface InsulaQuotaReading {
39
+ entry: InsulaUsageEntry;
40
+ context: InsulaQuotaContext;
41
+ }
42
+ /** A miss may retain a dated reading; it is not a current quota observation. */
43
+ export type InsulaQuotaLookup = {
44
+ reading: InsulaQuotaReading;
45
+ miss?: never;
46
+ } | {
47
+ miss: InsulaQuotaMiss;
48
+ reading?: InsulaQuotaReading;
49
+ };
50
+ /** The normalized equivalent of a source lookup, for a plugin's quota type. */
51
+ export type InsulaQuotaResult<Q> = {
52
+ reading: Q;
53
+ miss?: never;
54
+ } | {
55
+ miss: InsulaQuotaMiss;
56
+ reading?: Q;
57
+ };
37
58
  export interface InsulaQuotaOptions<Q> {
38
59
  provider: 'codex' | 'claude' | 'antigravity';
39
60
  /**
@@ -110,6 +131,8 @@ export declare class InsulaQuotaSource {
110
131
  entry: InsulaUsageEntry;
111
132
  context: InsulaQuotaContext;
112
133
  } | undefined;
134
+ /** Cache-only background lookup; current() retains its original miss behavior. */
135
+ lookup(provider: string, accountId: string, now: number): InsulaQuotaLookup;
113
136
  }
114
137
  export declare function acquireInsulaQuotaSource(transport: InsulaUsageTransport, tokenPath: string): {
115
138
  source: InsulaQuotaSource;
@@ -0,0 +1,25 @@
1
+ import { type PrivateWriteOutcome } from './private-files.js';
2
+ export interface AtomicWriteOptions {
3
+ serialize?: (value: unknown) => string;
4
+ beforeRename?: () => Promise<void>;
5
+ /** Test seam for forcing staging-name collisions; defaults to randomUUID. */
6
+ stageName?: () => string;
7
+ /** Sync the staged file and, after rename, its parent directory. Opt-in. */
8
+ durable?: boolean;
9
+ /** Windows opt-in: flush file bytes, without promising directory metadata durability. */
10
+ durability?: 'file-only-on-windows';
11
+ /** Reports Windows rename success, file/directory durability, retry counts and error codes, never file bytes. */
12
+ onOutcome?: (outcome: PrivateWriteOutcome) => void;
13
+ }
14
+ /** Internal classification of fsync failures, including a failure after rename. */
15
+ export declare class AtomicSyncError extends Error {
16
+ constructor(cause: unknown);
17
+ }
18
+ export declare function writeJsonAtomic(path: string, value: unknown, options?: AtomicWriteOptions): Promise<void>;
19
+ /**
20
+ * Notify internal callers at the rename. The store records committed writes
21
+ * and removed ids here, because a later directory sync cannot undo the rename.
22
+ */
23
+ export declare function writeJsonAtomicTracked(path: string, value: unknown, options: AtomicWriteOptions, onRenamed?: () => void): Promise<void>;
24
+ /** Make an already renamed file and its directory durable without rewriting bytes. */
25
+ export declare function syncJsonFile(path: string): Promise<void>;
@@ -0,0 +1,9 @@
1
+ export type { AtomicWriteOptions } from './atomic-write.js';
2
+ export { writeJsonAtomic } from './atomic-write.js';
3
+ export { WRITER_LOCK_CONSTANTS } from './lock-constants.js';
4
+ export type { PrivateWriteOutcome } from './private-files.js';
5
+ export { PrivateFileError } from './private-files.js';
6
+ export type { LockLoss, RefreshFileLock } from './refresh-file-lock.js';
7
+ export { acquireRefreshFileLock, isLostMarkerRaceError, } from './refresh-file-lock.js';
8
+ export type { LockOptions, LockOwnershipDetails } from './with-lock.js';
9
+ export { LockContentionError, LockOwnershipError, lockPathFor, withLock, } from './with-lock.js';
@@ -0,0 +1,14 @@
1
+ export declare const WRITER_LOCK_CONSTANTS: Readonly<{
2
+ sidebar: Readonly<{
3
+ name: "sidebar-write";
4
+ ttlMs: 10000;
5
+ timeoutMs: 15000;
6
+ renew: true;
7
+ }>;
8
+ preferences: Readonly<{
9
+ name: "preferences";
10
+ ttlMs: 10000;
11
+ timeoutMs: 2000;
12
+ renew: true;
13
+ }>;
14
+ }>;
@@ -0,0 +1,66 @@
1
+ import { rename } from 'node:fs/promises';
2
+ import type { PosixOwnerOnlyPathAsyncOptions } from '@cortexkit/private-files';
3
+ export declare const windowsPrivateFiles: boolean;
4
+ type Backend = typeof import('@cortexkit/private-files');
5
+ type Kind = 'file' | 'directory';
6
+ /** Tests inject a backend here; production always imports the private-files package. */
7
+ export declare function setPrivateFilesBackendForTest(api?: Backend): void;
8
+ export declare class PrivateFileError extends Error {
9
+ readonly path: string;
10
+ readonly stage: string;
11
+ readonly code: string;
12
+ readonly win32Code?: number;
13
+ readonly reason?: string;
14
+ published: boolean;
15
+ durabilityConfirmed: boolean;
16
+ fileDurable: boolean;
17
+ attempts: number;
18
+ elapsedMs: number;
19
+ orphanPath?: string;
20
+ constructor(path: string, stage: string, cause: unknown);
21
+ }
22
+ export declare function privateOperation<T>(path: string, stage: string, operation: () => Promise<T>): Promise<T>;
23
+ /** Tests only: policy options used by safe-parent checks that pass none. */
24
+ export declare function setSafeParentOptionsForTest(options?: PosixOwnerOnlyPathAsyncOptions): void;
25
+ /** Existing containing directories use the shared entry-integrity policy, not secret-file permissions. */
26
+ export declare function verifySafeDirectory(path: string, options?: PosixOwnerOnlyPathAsyncOptions): Promise<void>;
27
+ /** Repair only the specific owned secret file supplied by a caller, never an existing directory tree. */
28
+ export declare function verifyPrivate(path: string, kind: Kind, migrate?: boolean): Promise<void>;
29
+ /** Create missing components privately; inspect existing ancestors without modifying them. */
30
+ export declare function ensurePrivateDirectory(path: string, _migrate?: boolean, options?: PosixOwnerOnlyPathAsyncOptions): Promise<void>;
31
+ export declare function readPrivateText(path: string, migrate?: boolean): Promise<string>;
32
+ export declare function readPrivateBuffer(path: string, migrate?: boolean): Promise<Buffer>;
33
+ export declare function createPrivateBytes(path: string, bytes: string): Promise<void>;
34
+ export declare function createPrivateDirectoryExclusive(path: string): Promise<void>;
35
+ export interface ReplaceOptions {
36
+ beforeRename?: () => Promise<void>;
37
+ /** Absolute monotonic deadline, for an expiring lease. */
38
+ deadline?: number;
39
+ now?: () => number;
40
+ sleep?: (ms: number) => Promise<void>;
41
+ rename?: typeof rename;
42
+ }
43
+ /** Retry Windows rename sharing/access errors within a budget; they never prove lease contention. */
44
+ export declare function replaceWindowsFile(from: string, to: string, options?: ReplaceOptions): Promise<{
45
+ attempts: number;
46
+ elapsedMs: number;
47
+ }>;
48
+ export interface PrivateWriteOutcome {
49
+ path: string;
50
+ stage: string;
51
+ published: boolean;
52
+ fileDurable: boolean;
53
+ durabilityConfirmed: boolean;
54
+ attempts: number;
55
+ elapsedMs: number;
56
+ code?: string;
57
+ win32Code?: number;
58
+ }
59
+ export declare function writePrivateAtomic(path: string, bytes: string, options?: ReplaceOptions & {
60
+ stagePath?: string;
61
+ onRenamed?: () => void;
62
+ durable?: boolean;
63
+ durability?: 'file-only-on-windows';
64
+ onOutcome?: (outcome: PrivateWriteOutcome) => void;
65
+ }): Promise<void>;
66
+ export {};
@@ -0,0 +1,36 @@
1
+ import { acquireRefreshFileLock } from './refresh-file-lock.js';
2
+ export declare function lockPathFor(target: string, name: string): string;
3
+ export declare class LockContentionError extends Error {
4
+ readonly details: {
5
+ target: string;
6
+ name: string;
7
+ timeoutMs: number;
8
+ };
9
+ constructor(details: {
10
+ target: string;
11
+ name: string;
12
+ timeoutMs: number;
13
+ });
14
+ }
15
+ export interface LockOwnershipDetails {
16
+ target: string;
17
+ name: string;
18
+ expectedOwnerId?: string;
19
+ observedOwnerId?: string;
20
+ observedExpiresAt?: number;
21
+ }
22
+ export declare class LockOwnershipError extends Error {
23
+ readonly details: LockOwnershipDetails;
24
+ constructor(details: LockOwnershipDetails);
25
+ }
26
+ export interface LockOptions {
27
+ name: string;
28
+ ttlMs: number;
29
+ timeoutMs: number;
30
+ renew?: boolean;
31
+ onStep?: Parameters<typeof acquireRefreshFileLock>[0]['onStep'];
32
+ onRenewalTimer?: Parameters<typeof acquireRefreshFileLock>[0]['onRenewalTimer'];
33
+ }
34
+ export declare function withLock<T>(target: string, options: LockOptions, fn: (lock: {
35
+ assertOwned(): Promise<void>;
36
+ }) => Promise<T>): Promise<T>;
@@ -5,6 +5,7 @@ import { type NativeAccountMetadataPatch, type NativeAccountSnapshot, type Nativ
5
5
  import { type NativeCustodyReceipt } from './native-custody.ts';
6
6
  import { type NativeLocalCredentialServiceOptions } from './native-local-credential-service.ts';
7
7
  import type { NativeLocalExternalPolicy } from './native-local-runtime-readers.ts';
8
+ import { type NativeLockEvent } from './native-lock-observer.ts';
8
9
  import { type NativeQuotaObservations } from './native-quota-observations.ts';
9
10
  import type { NativeKnownCredentialSubject, NativeRefreshResult, NativeRefreshSubject } from './native-refresh-coordinator.ts';
10
11
  import { type NativeDisplayProfile, type NativeVaultQuotaPurpose, type NativeVaultRuntime, type NativeVaultRuntimeOptions } from './native-vault-runtime.ts';
@@ -18,7 +19,7 @@ export interface NativeAccountRuntimeOptions {
18
19
  host: 'opencode' | 'pi';
19
20
  /** The opencode-anthropic-auth setup command rechecks that hosts are stopped before credential-file writes, so migration cannot change credentials used by a running host. */
20
21
  beforePoolWrite?: () => Promise<void>;
21
- local?: Partial<Pick<NativeLocalCredentialServiceOptions, 'refreshToken' | 'resolveIdentity' | 'failurePolicy' | 'now'>>;
22
+ local?: Partial<Pick<NativeLocalCredentialServiceOptions, 'refreshToken' | 'resolveIdentity' | 'failurePolicy' | 'now' | 'onLockEvent'>>;
22
23
  vault?: Omit<NativeVaultRuntimeOptions, 'paths' | 'host'>;
23
24
  }
24
25
  export interface NativeLocalAuthorizeOptions {
@@ -45,9 +46,11 @@ export type NativeRelayUpdate = Partial<Omit<RelayConfig, 'token'>> & {
45
46
  token?: string | null;
46
47
  };
47
48
  export interface NativeAccountRuntime {
49
+ readonly onLockEvent?: (event: NativeLockEvent) => void;
48
50
  readonly vault: NativeVaultRuntime;
49
51
  readonly quotaObservations: NativeQuotaObservations;
50
52
  drainQuotaPublications(): Promise<void>;
53
+ drainRoutingPublications(): Promise<void>;
51
54
  /** Fresh private relay authorization for transport only; never include it in a status snapshot. */
52
55
  getRelayConfig(): Promise<RelayConfig | null>;
53
56
  updateRelay(patch: NativeRelayUpdate): Promise<void>;
@@ -111,7 +114,7 @@ export interface NativeAccountRuntime {
111
114
  fetchProfile(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<OAuthAccountProfile>;
112
115
  /** Like fetchProfile, but returns before the profile is saved; see NativeDisplayProfile. */
113
116
  fetchProfileForDisplay(routeId: string, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<NativeDisplayProfile>;
114
- close(): void;
117
+ close(): void | Promise<void>;
115
118
  getSettingsPath(): Promise<string>;
116
119
  }
117
120
  /** Host instances own leases, while stores and the vault connection live until the last release. */
@@ -1,4 +1,5 @@
1
1
  import { type NativeLocalExternalPolicy } from './native-local-runtime-readers.ts';
2
+ import type { NativeLockEvent } from './native-lock-observer.ts';
2
3
  import { type NativeRefreshCoordinatorOptions, type NativeRefreshObservation, type NativeRefreshRequest, type NativeRefreshResult, type NativeRefreshSubject } from './native-refresh-coordinator.ts';
3
4
  import { type NativeLocalFailureAttribution, type NativeLocalFailurePolicy } from './native-runtime.ts';
4
5
  import type { NativePoolPaths } from './pool-paths.ts';
@@ -46,6 +47,7 @@ export interface NativeLocalCredentialServiceOptions {
46
47
  readonly refreshToken?: NativeRefreshCoordinatorOptions['refreshToken'];
47
48
  /** Account lookup for new access; defaults to the Claude Code identity lookup. */
48
49
  readonly resolveIdentity?: NativeRefreshCoordinatorOptions['resolveIdentity'];
50
+ readonly onLockEvent?: (event: NativeLockEvent) => void;
49
51
  }
50
52
  /**
51
53
  * Hosts receive an access token only after its Claude account has been checked.
@@ -1,6 +1,11 @@
1
+ import { withLock } from "./internal-types/fs/index.js";
2
+ /** Mark work as background-origin without changing how it acquires or releases locks. */
3
+ export declare function withDetachedNativeLocks<T>(work: () => Promise<T>): Promise<T>;
1
4
  /** Diagnostic evidence, not an ownership assertion or a control hook. */
2
5
  export type NativeLockEvent = {
3
- type: 'acquired' | 'released' | 'contended';
6
+ type: 'acquiring' | 'acquired' | 'released' | 'contended';
7
+ /** Marks background-origin work; callers may still await the same shared refresh. */
8
+ detached?: boolean;
4
9
  name: string;
5
10
  path: string;
6
11
  };
@@ -10,3 +15,13 @@ export type NativeLockEvent = {
10
15
  * With no observer, leave the producer callback absent and allocate no wrapper.
11
16
  */
12
17
  export declare function nativeLockObserver(observer: ((event: NativeLockEvent) => void) | undefined): ((event: NativeLockEvent) => void) | undefined;
18
+ /** Observe the real lease without changing acquisition, ownership or release. */
19
+ export declare function withNativeLock<T>(path: string, options: Parameters<typeof withLock>[1] & {
20
+ onLockEvent?: (event: NativeLockEvent) => void;
21
+ }, run: (lease: {
22
+ assertOwned(): Promise<void>;
23
+ }) => Promise<T>, acquire?: typeof withLock): Promise<T>;
24
+ /** Resolve the supplied acquisition function for each operation. */
25
+ export declare function observeNativeLocks(acquire: () => typeof withLock, observer?: (event: NativeLockEvent) => void): <T>(path: string, options: Parameters<typeof withNativeLock>[1], run: (lease: {
26
+ assertOwned(): Promise<void>;
27
+ }) => Promise<T>) => Promise<T>;
@@ -201,7 +201,7 @@ export interface NativeRefreshRequest {
201
201
  intent: 'serve' | 'refresh';
202
202
  mode: 'local' | 'claustrum';
203
203
  binding: NativeLocalPoolBinding;
204
- /** A 401's dispatched access token, used only for replacement adoption. */
204
+ /** The access token dispatched on a 401; it must not be served again. */
205
205
  rejectedAccessToken?: string;
206
206
  signal?: AbortSignal;
207
207
  }
@@ -1,5 +1,6 @@
1
1
  import type { AccountOperationError, OAuthAccountProfile, PrimeUsageCounters } from './accounts.ts';
2
2
  import { type NativeLocalCredentialValidation } from './native-credential-validation.ts';
3
+ import { type NativeLockEvent } from './native-lock-observer.ts';
3
4
  import { type NativeQuotaMap } from './native-quota-codec.ts';
4
5
  import type { NativeRefreshObservation, NativeRefreshSubject } from './native-refresh-coordinator.ts';
5
6
  import { type OwnerOnlyOptions } from './owner-only.ts';
@@ -72,6 +73,8 @@ export interface NativeRuntimeState {
72
73
  relay?: {
73
74
  token: string;
74
75
  };
76
+ /** Binds the private relay token (including its removal) to relay settings. */
77
+ relayGeneration?: string;
75
78
  }
76
79
  export type NativeRuntimeRead = {
77
80
  status: 'missing';
@@ -80,13 +83,16 @@ export type NativeRuntimeRead = {
80
83
  state: NativeRuntimeState;
81
84
  };
82
85
  export declare class NativeRuntimeError extends Error {
83
- readonly code: 'invalid-runtime' | 'unsafe-runtime' | 'runtime-io' | 'runtime-conflict' | 'publication-refused';
84
- constructor(code: 'invalid-runtime' | 'unsafe-runtime' | 'runtime-io' | 'runtime-conflict' | 'publication-refused');
86
+ readonly code: 'invalid-runtime' | 'unsafe-runtime' | 'runtime-io' | 'runtime-conflict' | 'publication-refused' | 'relay-inconsistent';
87
+ readonly status?: 400;
88
+ readonly retryable?: false;
89
+ constructor(code: 'invalid-runtime' | 'unsafe-runtime' | 'runtime-io' | 'runtime-conflict' | 'publication-refused' | 'relay-inconsistent');
85
90
  }
86
91
  /** Validate structure and internal identifier consistency. The publisher separately checks these identifiers against the current pool or vault roster. */
87
92
  export declare function decodeNativeRuntime(value: unknown, storageId: string): NativeRuntimeState;
88
93
  export declare function readNativeRuntime(path: string, storageId: string, ownership?: OwnerOnlyOptions): Promise<NativeRuntimeRead>;
89
94
  export interface NativeRuntimeWriteHooks {
95
+ onLockEvent?: (event: NativeLockEvent) => void;
90
96
  publication?: PublicationOptions;
91
97
  /** Verify that the observed account still matches the current pool record or vault roster and that the caller still owns the locks protecting those records. */
92
98
  beforeRename?: () => Promise<void>;
@@ -115,6 +121,7 @@ export type NativeRuntimeOptionalPublication = {
115
121
  status: 'skipped';
116
122
  };
117
123
  export interface NativeRuntimeOptionalWriteHooks {
124
+ onLockEvent?: (event: NativeLockEvent) => void;
118
125
  publication?: PublicationOptions;
119
126
  /**
120
127
  * Same checks as NativeRuntimeWriteHooks.beforeRename, run at the same
@@ -136,14 +143,14 @@ export declare function updateNativeRuntimeOptional(path: string, storageId: str
136
143
  * account permission to make another model request; admission checks still apply.
137
144
  * No caller mutator or publication callback can widen this transition.
138
145
  */
139
- export declare function publishNativeLocalFirstIdentity(paths: NativePoolPaths, observation: NativeRefreshObservation, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish'>): Promise<NativeRuntimeState>;
146
+ export declare function publishNativeLocalFirstIdentity(paths: NativePoolPaths, observation: NativeRefreshObservation, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish' | 'onLockEvent'>): Promise<NativeRuntimeState>;
140
147
  /**
141
148
  * Record successful credential validation for a local account with a known UUID.
142
149
  * Bootstrap must provide the state captured before its request and the exact
143
150
  * credentials it checked. An unidentified entry requires first-identity publication.
144
151
  * Recording validation for a disabled entry does not enable it or permit serving.
145
152
  */
146
- export declare function publishNativeLocalCredentialValidation(paths: NativePoolPaths, observation: NativeRefreshObservation, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish'>): Promise<NativeRuntimeState>;
153
+ export declare function publishNativeLocalCredentialValidation(paths: NativePoolPaths, observation: NativeRefreshObservation, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish' | 'onLockEvent'>): Promise<NativeRuntimeState>;
147
154
  export interface NativeLocalFailurePolicy {
148
155
  readonly checkedAt: number;
149
156
  /** A nextRetryAt equal to checkedAt adds no delay beyond the recorded failure time. */
@@ -205,4 +212,4 @@ export declare function classifyNativeLocalFailure(observation: NativeRefreshObs
205
212
  * This does not validate credentials or repair their account identity. Credentials
206
213
  * are saved separately; a metadata write failure cannot undo a token exchange.
207
214
  */
208
- export declare function publishNativeLocalRefreshFailure(paths: NativePoolPaths, observation: NativeRefreshObservation, policy: NativeLocalFailurePolicy, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish'>): Promise<NativeLocalFailurePublication>;
215
+ export declare function publishNativeLocalRefreshFailure(paths: NativePoolPaths, observation: NativeRefreshObservation, policy: NativeLocalFailurePolicy, hooks?: Pick<NativeRuntimeWriteHooks, 'beforePublish' | 'onLockEvent'>): Promise<NativeLocalFailurePublication>;
@@ -1,8 +1,9 @@
1
+ import { type NativeLockEvent } from './native-lock-observer.ts';
1
2
  import { type NativePoolStorePaths } from './pool-store.ts';
2
3
  /**
3
- * A local account could not be authorized because another writer was part
4
- * way through saving it (for example the refresh that records its first
5
- * account UUID) and did not finish within the short wait Core allows.
4
+ * A local account could not be authorized because the caller's short wait for
5
+ * an account write or a refresh replacing a provider-rejected token expired.
6
+ * The shared write or refresh may still finish after the caller stops waiting.
6
7
  *
7
8
  * The request should be retried. `code: 'ECONNRESET'` is how this package
8
9
  * marks an error retryable for its hosts. A host must surface it rather than
@@ -34,4 +35,4 @@ export declare function isNativeTransientAccountError(value: unknown): value is
34
35
  * every attempt too, so a cancelled caller never takes a lock. All pool
35
36
  * leases use wall time, independently of logical observation timestamps.
36
37
  */
37
- export declare function joinNativePoolWrite(paths: NativePoolStorePaths, signals: readonly AbortSignal[], check: () => void): Promise<'joined' | 'deadline'>;
38
+ export declare function joinNativePoolWrite(paths: NativePoolStorePaths, signals: readonly AbortSignal[], check: () => void, onLockEvent?: (event: NativeLockEvent) => void): Promise<'joined' | 'deadline'>;
@@ -2,12 +2,13 @@ import type { ClaustrumClientOptions } from '@cortexkit/claustrum-client';
2
2
  import { type OAuthAccountProfile, type OAuthQuotaSnapshot, type PrimeUsageDelta } from './accounts.ts';
3
3
  import { type NativeAccountMetadataPatch } from './native-account-view.ts';
4
4
  import { type NativeCustodyClient, type NativeCustodyInventory, type NativeCustodyReceipt, type NativeCustodyReporterSource, type NativeCustodyRetry } from './native-custody.ts';
5
+ import { type NativeLockEvent } from './native-lock-observer.ts';
5
6
  import { NativeQuotaObservations } from './native-quota-observations.ts';
6
7
  import { type NativeRosterSeedInput, type NativeVaultRosterDocument, type NativeVaultRosterSeed } from './native-roster-seed.ts';
7
8
  import { type NativeRuntimeState } from './native-runtime.ts';
8
9
  import type { NativeVaultPaths } from './native-vault-paths.ts';
9
10
  import type { NativePoolPaths } from './pool-paths.ts';
10
- import type { QuotaReadingPurpose, QuotaRequestDispatch } from './quota-manager.ts';
11
+ import { type QuotaReadingPurpose, type QuotaRequestDispatch } from './quota-manager.ts';
11
12
  export interface NativeVaultRuntimeOptions {
12
13
  paths: NativePoolPaths;
13
14
  host: 'opencode' | 'pi';
@@ -21,6 +22,7 @@ export interface NativeVaultRuntimeOptions {
21
22
  }>;
22
23
  env?: NodeJS.ProcessEnv;
23
24
  now?: () => number;
25
+ onLockEvent?: (event: NativeLockEvent) => void;
24
26
  /**
25
27
  * Timer functions for the vault custody's outage probe and roster watch
26
28
  * retries. Defaults to the global ones; tests pass their own.
@@ -41,10 +43,12 @@ export interface NativeVaultRuntimeOptions {
41
43
  * background quota cache may answer instead of Anthropic's usage endpoint.
42
44
  * - 'background': a periodic sweep. Refresh insula's cache (at most once a
43
45
  * minute per daemon and enrollment), look the route's account up in it,
44
- * and skip the usage GET when it holds a current reading.
46
+ * and skip the usage GET for a current reading, a cold cache or an upstream
47
+ * failure. Skipped misses leave the account due for the next sweep.
45
48
  * - 'admission': a request needs a reading. Look the served credential's
46
49
  * account up in insula's cache only, never refreshing it, then poll on a
47
- * miss.
50
+ * miss except an upstream failure, which uses a dated reading if attached
51
+ * and otherwise leaves quota unknown.
48
52
  * Omitted: poll Anthropic directly (explicit user refreshes and other
49
53
  * callers that must see the provider's own reading).
50
54
  */
@@ -24,6 +24,9 @@ export type QuotaRefreshResult = {
24
24
  * means poll the provider directly.
25
25
  */
26
26
  export type QuotaReadingPurpose = 'background' | 'admission';
27
+ /** Insula is still fetching or its upstream failed; preserve quota without recording a poll. */
28
+ export declare class QuotaRefreshDeferred extends Error {
29
+ }
27
30
  /** Pace a physical usage GET and verify the selected credential is still eligible before sending. */
28
31
  export type QuotaRequestDispatch = (send: () => Promise<Response>, revalidate: () => Promise<void>) => Promise<Response>;
29
32
  export type QuotaManagerOptions = {
@@ -1,4 +1,5 @@
1
1
  import { type AccountOperationError, type AccountStorage, type OAuthQuotaSnapshot } from './accounts.ts';
2
+ import { type NativeLockEvent } from './native-lock-observer.ts';
2
3
  import type { NativeVaultRosterDocument } from './native-roster-seed.ts';
3
4
  import { type NativeVaultRoutingSeed } from './native-vault-seed.ts';
4
5
  export declare const STICKY_ROUTING_MAIN_ACCOUNT_ID = "main";
@@ -99,7 +100,9 @@ export declare class StickySessionRouter {
99
100
  private loaded;
100
101
  private state;
101
102
  private stateMtimeNs;
102
- private touchChain;
103
+ private publicationChain;
104
+ private seedPublication;
105
+ private readonly changes;
103
106
  private seedFinalized;
104
107
  constructor(options: {
105
108
  path: string;
@@ -107,6 +110,7 @@ export declare class StickySessionRouter {
107
110
  assignmentTtlMs?: number;
108
111
  vaultSeed?: NativeVaultRoutingSeed;
109
112
  localRecoveryPath?: string;
113
+ onLockEvent?: (event: NativeLockEvent) => void;
110
114
  });
111
115
  private now;
112
116
  private readState;
@@ -119,11 +123,17 @@ export declare class StickySessionRouter {
119
123
  private prune;
120
124
  private writeState;
121
125
  private writeResolutionState;
122
- /** Import legacy session pins only after vault account discovery produces a complete verified roster. No empty routing file is published while that roster is incomplete. */
126
+ /** Queue legacy-pin import in the background; take its writer lease only after verifying a complete roster. */
123
127
  prepareLegacySeed(knownRoster?: NativeVaultRosterDocument | null): Promise<void>;
124
128
  private logicalAccountId;
125
129
  setVaultSeed(seed: NativeVaultRoutingSeed | undefined): void;
126
130
  private scheduleTouch;
131
+ private overlayChanges;
132
+ private enqueuePublication;
133
+ private scheduleChange;
134
+ private retryChange;
135
+ /** Wait for owned background publications during host disposal or fixture cleanup. */
136
+ drain(): Promise<void>;
127
137
  private selectCandidate;
128
138
  resolve(input: {
129
139
  sessionId: string;
@@ -0,0 +1,19 @@
1
+ export declare const TURN_END_NOTE_BETA = "mid-conversation-system-clear-at-2026-08-21";
2
+ export declare const TURN_END_NOTE_MIN_VISIBLE_CHARACTERS = 350;
3
+ export declare const 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.";
4
+ /**
5
+ * Model families that get turn-end notes. The note is a turn-scoped system
6
+ * message (`clear_at: "next_user_message"`), which needs the
7
+ * mid-conversation-system-clear-at beta that Claude Code sends for these models.
8
+ */
9
+ export declare function supportsTurnEndNote(model: unknown): boolean;
10
+ /**
11
+ * Call only on OAuth histories, after effort-marker validation and stripping.
12
+ * Map configured host names with the same stateless mapping used for history,
13
+ * never with the currently declared tool set: declarations can change later.
14
+ */
15
+ export declare function applyTurnEndNotes(body: Record<string, unknown>, options?: {
16
+ tools?: readonly string[];
17
+ mapToolName?: (name: string) => string;
18
+ visibleText?: (message: Record<string, unknown>) => string;
19
+ }): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/anthropic-auth-core",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,7 +30,7 @@
30
30
  "prepublishOnly": "bun run build"
31
31
  },
32
32
  "devDependencies": {
33
- "@cortexkit/common-auth": "0.21.1"
33
+ "@cortexkit/common-auth": "0.22.0"
34
34
  },
35
35
  "dependencies": {
36
36
  "@cortexkit/claustrum-client": "0.12.0",