@cortexkit/anthropic-auth-core 2.2.1 → 2.2.2

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.
@@ -169,8 +169,10 @@ export declare class ClaustrumConsumer<Q = QuotaObservation> {
169
169
  * a served credential (an insula reading from `cachedInsulaQuotaForRoute`).
170
170
  * It lands only while the route is still bound to that known account, so no
171
171
  * credential fetch is needed and a replaced account's reading is dropped.
172
- * The in-memory roster is reloaded from the file, without a vault call.
172
+ * Memory updates immediately; durable publication is detached and coalesced.
173
173
  */
174
174
  recordAccountQuota(routeId: string, accountIdentity: string, observation: QuotaObservation): Promise<boolean>;
175
175
  close(): void;
176
+ /** Close immediately; the last consumer also waits for the writer's bounded drain. */
177
+ dispose(): Promise<void>;
176
178
  }
@@ -9,6 +9,7 @@ export { ClaustrumConsumerError, type ClaustrumConsumerFailureKind, type Claustr
9
9
  export { assertHostSlotMatchesMode, assertNotCustodyPlaceholder, CUSTODY_PLACEHOLDER_PREFIX, classifyHostSlot, custodyPlaceholder, custodyPlaceholderKey, type HostSlotContent, isCustodyPlaceholder, isCustodyPlaceholderValue, } from './host-slot.js';
10
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
+ export { drainVaultQuota } from './quota-writer.js';
12
13
  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
14
  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';
14
15
  /**
@@ -0,0 +1,18 @@
1
+ import { type QuotaObservation } from '../quota/index.js';
2
+ import { type QuotaReceipt, type VaultRosterFile } from './roster.js';
3
+ export type VaultQuotaPublication = {
4
+ routeId: string;
5
+ accountIdentity?: string;
6
+ receipt?: QuotaReceipt;
7
+ observation: QuotaObservation;
8
+ };
9
+ type Listener = (publication: VaultQuotaPublication) => void;
10
+ /** Retain the shared writer; the last consumer's close drains it. */
11
+ export declare function retainVaultQuotaWriter(path: string, listener: Listener): () => Promise<void>;
12
+ /** Enqueue without filesystem work; each quota field retains its own receipt fence. */
13
+ export declare function enqueueVaultQuota(path: string, publication: VaultQuotaPublication): Promise<boolean>;
14
+ /** Overlay uncommitted observations when a consumer reloads the durable roster. */
15
+ export declare function pendingVaultQuota(path: string, roster: VaultRosterFile | undefined): VaultRosterFile | undefined;
16
+ /** Wait at most timeoutMs for detached publication; shutdown loss is acceptable. */
17
+ export declare function drainVaultQuota(path: string, timeoutMs?: number): Promise<void>;
18
+ export {};
@@ -2,6 +2,8 @@ import { type QuotaMap, type QuotaObservation } from '../quota/index.js';
2
2
  import type { RoutingRow } from '../routing/index.js';
3
3
  import type { ClaustrumScopedAttempt, ClaustrumScopedCustody, SkippedVaultRecord, VaultCredential, VaultCredentialType, VaultInventory } from './custody.js';
4
4
  import { type DeclinedAccount } from './interlock.js';
5
+ import { type VaultQuotaPublication } from './quota-writer.js';
6
+ export { drainVaultQuota } from './quota-writer.js';
5
7
  /**
6
8
  * One vault account as the pool sees it. It carries no bearer material: the
7
9
  * access token is fetched from the vault for every send. Several vault
@@ -91,6 +93,7 @@ export interface VaultRosterLockContext {
91
93
  assertOwned: () => Promise<void>;
92
94
  }
93
95
  export interface MutateVaultRosterOptions {
96
+ signal?: AbortSignal;
94
97
  /**
95
98
  * Runs when the new roster is fully staged on disk, immediately before the
96
99
  * rename that publishes it, so a caller can confirm a lease of its own at
@@ -127,7 +130,10 @@ export type QuotaReceipt = Pick<ClaustrumScopedAttempt, 'credentialId' | 'accoun
127
130
  * write is fenced on the receipt the reading was taken with: it lands only
128
131
  * while the row still holds that receipt's credential (as representative or
129
132
  * alias) and account, so a slow read for a replaced account can never land on
130
- * its successor. Returns whether the observation was kept.
133
+ * its successor. Resolves false when the fence refuses the reading against the
134
+ * roster as it stands now (on disk, plus readings this process has not
135
+ * written yet), and true once the reading is queued for the next write. The
136
+ * write applies the fence again, so a rebind between the two still refuses.
131
137
  */
132
138
  export declare function recordVaultQuota(path: string, input: QuotaReceipt & {
133
139
  routeId: string;
@@ -139,19 +145,28 @@ export declare function recordVaultQuota(path: string, input: QuotaReceipt & {
139
145
  * lands only while the row is still bound to that exact known account, so a
140
146
  * reading taken before a replacement never reaches the successor. Unlike
141
147
  * `recordVaultQuota` it never binds an account: a row without a known account
142
- * is refused. Returns whether the observation was kept.
148
+ * is refused. Resolves false when the row is not bound to that account now,
149
+ * and true once the reading is queued, as `recordVaultQuota` does.
143
150
  */
144
151
  export declare function recordVaultAccountQuota(path: string, input: {
145
152
  routeId: string;
146
153
  accountIdentity: string;
147
154
  observation: QuotaObservation;
148
155
  }): Promise<boolean>;
156
+ /** Apply the same identity fence to memory overlays and durable quota batches. */
157
+ export declare function applyVaultQuota(current: VaultRosterFile | undefined, input: VaultQuotaPublication): {
158
+ roster: VaultRosterFile | undefined;
159
+ kept: boolean;
160
+ };
161
+ export declare function forgetPendingVaultDiscovery(path: string): void;
149
162
  /**
150
163
  * Discover and commit the roster. The lease covers the list call and the
151
164
  * commit, not just the write: an opaque view cannot tell a delayed old reply
152
165
  * from a newer one, so a run that lost its lease is refused at commit. A
153
166
  * failed list, or custody switching off mid-run, never writes anything; a
154
167
  * peer holding the lease means its last committed roster is served instead.
168
+ * A write-lock timeout keeps the discovered inventory for the next poll,
169
+ * unless a peer has superseded its base view in the meantime.
155
170
  */
156
171
  export declare function refreshVaultRoster(options: {
157
172
  path: string;
@@ -159,6 +174,7 @@ export declare function refreshVaultRoster(options: {
159
174
  isActive?: () => boolean | Promise<boolean>;
160
175
  signal?: AbortSignal;
161
176
  projection?: ProjectionOptions | (() => ProjectionOptions);
177
+ onInventory?: (inventory: VaultInventory) => void;
162
178
  }): Promise<VaultRosterFile | undefined>;
163
179
  /**
164
180
  * A host-owned main account as last verified from the vault: the plugin's
@@ -28,6 +28,7 @@ export interface LockOptions {
28
28
  ttlMs: number;
29
29
  timeoutMs: number;
30
30
  renew?: boolean;
31
+ signal?: AbortSignal;
31
32
  onStep?: Parameters<typeof acquireRefreshFileLock>[0]['onStep'];
32
33
  onRenewalTimer?: Parameters<typeof acquireRefreshFileLock>[0]['onRenewalTimer'];
33
34
  }
@@ -1,3 +1,4 @@
1
+ import { type QuotaCredits } from './map.js';
1
2
  import type { ProjectedLimit, ProjectedQuota } from './projection.js';
2
3
  /** A reading older than this is marked with its age. */
3
4
  export declare const QUOTA_STALE_AFTER_MS: number;
@@ -31,6 +32,13 @@ export interface QuotaWindowPart {
31
32
  kind: 'window' | 'budget';
32
33
  /** The display name of a quota window, or `credits` for the budget. */
33
34
  name: string;
35
+ /**
36
+ * The label the narrow line gives this item: an account-wide window keeps
37
+ * its name (`5h`), a model-scoped window reads as its model's short name
38
+ * (`Fa` for Fable, extended until names in the same reading differ), and
39
+ * the budget reads `cr`. For layouts too narrow for the full name.
40
+ */
41
+ short: string;
34
42
  /** The shared figure wording, including `credits` for budget figures. */
35
43
  figure: string;
36
44
  /** The unrounded remaining percentage, clamped to 0–100, when known. */
@@ -84,3 +92,14 @@ export declare function quotaTextParts(quota: ProjectedQuota | undefined, option
84
92
  * provider answered without a limit for any window.
85
93
  */
86
94
  export declare function formatQuota(quota: ProjectedQuota | undefined, options: QuotaTextOptions): string;
95
+ /**
96
+ * Prepaid credits as one short value, worded as the official Codex client's
97
+ * status view words them: `Unlimited` for unlimited credits, `<n> credits`
98
+ * for a finite positive balance (rounded to a whole number), `Available` when
99
+ * the account has credits but no usable balance was reported, and undefined
100
+ * when the account has no credits (or `credits` is undefined), so a caller
101
+ * shows no credits row at all. Unlimited wins even when `hasCredits` is false.
102
+ * No other formatter adds this text; a caller that wants a credits row asks
103
+ * for it.
104
+ */
105
+ export declare function quotaCreditsText(credits: Pick<QuotaCredits, 'hasCredits' | 'unlimited' | 'balance'> | undefined): string | undefined;
@@ -1,9 +1,9 @@
1
1
  export type { QuotaCodec } from './codec.js';
2
2
  export { quotaCodec } from './codec.js';
3
3
  export type { QuotaParts, QuotaTextForm, QuotaTextOptions, QuotaWindowPart, } from './format.js';
4
- export { formatQuota, isQuotaStale, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaTextParts, quotaWindowName, quotaWindowParts, } from './format.js';
5
- export type { CreditBudgetCleared, CreditBudgetEntry, CreditBudgetReading, QuotaAbsentEntry, QuotaCounter, QuotaEntry, QuotaMap, QuotaReadingEntry, QuotaRetiredEntry, } from './map.js';
6
- export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, decodeQuotaMap, emptyQuotaMap, isQuotaMap, } from './map.js';
4
+ export { formatQuota, isQuotaStale, NO_LIMITS_REPORTED, NO_QUOTA_READING, QUOTA_STALE_AFTER_MS, quotaCreditsText, quotaTextParts, quotaWindowName, quotaWindowParts, } from './format.js';
5
+ export type { CreditBudgetCleared, CreditBudgetEntry, CreditBudgetReading, QuotaAbsentEntry, QuotaCounter, QuotaCredits, QuotaEntry, QuotaMap, QuotaReadingEntry, QuotaRetiredEntry, } from './map.js';
6
+ export { ALL_SCOPE, DEFAULT_REQUIRED_LABELS, decodeQuotaMap, emptyQuotaMap, isQuotaCredits, isQuotaMap, } from './map.js';
7
7
  export type { ObservedBudget, ObservedPair, ObservedReading, QuotaObservation, } from './merge.js';
8
8
  export { isQuotaObservation, mergeQuotaObservation, QuotaCodecError, } from './merge.js';
9
9
  export type { ExhaustionReset, ProjectedBudget, ProjectedLimit, ProjectedQuota, QuotaGroup, } from './projection.js';
@@ -48,12 +48,30 @@ export interface QuotaCounter {
48
48
  value: number;
49
49
  checkedAt: number;
50
50
  }
51
+ /**
52
+ * Prepaid credits a provider account holds beside its rate-limit windows (for
53
+ * example a ChatGPT workspace's credits, which keep requests working after a
54
+ * window is used up). This is a state, not a count or the spend budget: the
55
+ * account has credits or not, they may be unlimited, and the provider may
56
+ * report a balance. It carries its own observation time.
57
+ */
58
+ export interface QuotaCredits {
59
+ hasCredits: boolean;
60
+ unlimited: boolean;
61
+ /** The balance the provider reported, when it reported one. */
62
+ balance?: number;
63
+ /** The provider's verdict that the overage allowance is used up. */
64
+ overageLimitReached?: boolean;
65
+ checkedAt: number;
66
+ }
51
67
  export interface QuotaMap {
52
68
  limits: QuotaEntry[];
53
69
  /** Absent means no observation has reported on the budget yet. */
54
70
  budget?: CreditBudgetEntry;
55
71
  /** Provider-named counts, each with its own observation time. */
56
72
  counters?: Record<string, QuotaCounter>;
73
+ /** Absent means no observation has reported on prepaid credits yet. */
74
+ credits?: QuotaCredits;
57
75
  }
58
76
  export declare function emptyQuotaMap(): QuotaMap;
59
77
  /** The time an entry speaks for: its reading, retirement or absence time. */
@@ -61,9 +79,14 @@ export declare function entryTime(entry: QuotaEntry): number;
61
79
  export declare function limitKey(scope: string, label: string): string;
62
80
  export declare function isCreditBudgetEntry(value: unknown): value is CreditBudgetEntry;
63
81
  export declare function isQuotaCounters(value: unknown): value is Record<string, QuotaCounter>;
82
+ /** True when `value` is a well-formed prepaid-credits record. */
83
+ export declare function isQuotaCredits(value: unknown): value is QuotaCredits;
64
84
  /** Keep usable counters without letting one malformed count hide a quota map. */
65
85
  export declare function readQuotaCounters(value: unknown): Record<string, QuotaCounter> | undefined;
66
- /** Decode persisted quota, dropping malformed counters but not limit evidence. */
86
+ /**
87
+ * Decode persisted quota, dropping malformed counters or a malformed credits
88
+ * record but not limit or budget evidence.
89
+ */
67
90
  export declare function decodeQuotaMap(value: unknown): QuotaMap | undefined;
68
91
  /**
69
92
  * True when `value` is a well-formed quota map. Unrecognised top-level keys
@@ -1,4 +1,4 @@
1
- import { type QuotaCounter, type QuotaMap } from './map.js';
1
+ import { type QuotaCounter, type QuotaCredits, type QuotaMap } from './map.js';
2
2
  export interface ObservedReading {
3
3
  /** Defaults to `all`. */
4
4
  scope?: string;
@@ -34,6 +34,11 @@ export interface QuotaObservation {
34
34
  budget?: ObservedBudget;
35
35
  /** Each named count uses its own time, independently of limits and budget. */
36
36
  counters?: Record<string, QuotaCounter>;
37
+ /**
38
+ * Prepaid credits, judged by their own time independently of limits, budget
39
+ * and counters. Absent means the observation says nothing about credits.
40
+ */
41
+ credits?: QuotaCredits;
37
42
  }
38
43
  /** Thrown by `mergeQuotaObservation` when either argument is malformed. */
39
44
  export declare class QuotaCodecError extends TypeError {
@@ -1,4 +1,4 @@
1
- import { type QuotaCounter, type QuotaMap } from './map.js';
1
+ import { type QuotaCounter, type QuotaCredits, type QuotaMap } from './map.js';
2
2
  export interface ProjectedLimit {
3
3
  scope: string;
4
4
  label: string;
@@ -40,6 +40,8 @@ export interface ProjectedQuota {
40
40
  /** Present only when the stored budget is a reading, not cleared. */
41
41
  budget?: ProjectedBudget;
42
42
  counters?: Record<string, QuotaCounter>;
43
+ /** The stored prepaid credits, unchanged in every scope. */
44
+ credits?: QuotaCredits;
43
45
  /**
44
46
  * The named groups the windows belong to, in the order the plugin lists
45
47
  * them. Set only by a plugin whose windows all belong to such groups; the
@@ -33,11 +33,18 @@ export declare function listSetupProcesses(runner?: CommandRunner, options?: {
33
33
  onStep?: (details: ProcessInspectionStep) => void;
34
34
  /** False skips the Windows PowerShell query for Node and Bun command lines. */
35
35
  inspectRuntimes?: boolean;
36
+ /**
37
+ * The process to leave out, the running setup itself. Defaults to
38
+ * `process.pid`; tests pass a value no listed process can have, because in
39
+ * a container this process can hold any small PID a fixture uses.
40
+ */
41
+ selfPid?: number;
36
42
  }): Promise<Array<{
37
43
  pid: number;
38
44
  command: string;
39
45
  }>>;
40
46
  export declare function createProcessFence(runner?: CommandRunner, options?: {
41
47
  platform?: string;
48
+ selfPid?: number;
42
49
  }): ProcessFence;
43
50
  export declare function assertHostsStopped(fence: ProcessFence, env?: SetupEnvironment): Promise<void>;
@@ -122,7 +122,7 @@ export interface NativeVaultRuntime {
122
122
  export declare function publishNativeVaultRosterSeed(paths: Pick<NativeVaultPaths, 'roster'>, input: NativeRosterSeedInput, options?: {
123
123
  assertOwned?: () => Promise<void>;
124
124
  }): Promise<NativeVaultRosterSeed>;
125
- /** Match imported metadata to the held vault roster before publishing it. The caller's assertOwned fences its captured input; the roster lease separately prevents account replacement during the metadata write. */
125
+ /** Match imported custody metadata to the current roster without blocking roster writers. The optional assertOwned callback separately rechecks the caller's captured input before rename. */
126
126
  export declare function publishNativeVaultRuntimeSeed(paths: Pick<NativeVaultPaths, 'roster' | 'runtime' | 'storageId'>, state: NativeRuntimeState, options?: {
127
127
  assertOwned?: () => Promise<void>;
128
128
  }): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/anthropic-auth-core",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
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.22.0"
33
+ "@cortexkit/common-auth": "0.23.0"
34
34
  },
35
35
  "dependencies": {
36
36
  "@cortexkit/claustrum-client": "0.12.0",