@cortexkit/anthropic-auth-core 1.21.0 → 1.23.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.
- package/README.md +1 -1
- package/dist/accounts.d.ts +100 -3
- package/dist/accounts.js +1099 -169
- package/dist/auth.js +6 -10
- package/dist/cachekeep.d.ts +18 -1
- package/dist/cachekeep.js +108 -82
- package/dist/cch.d.ts +23 -9
- package/dist/cch.js +104 -21
- package/dist/claude-code.d.ts +8 -3
- package/dist/claude-code.js +24 -7
- package/dist/claustrum-enrollment-registry.d.ts +17 -0
- package/dist/claustrum-enrollment-registry.js +194 -0
- package/dist/claustrum-enrollment.d.ts +70 -0
- package/dist/claustrum-enrollment.js +485 -0
- package/dist/claustrum-scoped-roster.d.ts +23 -0
- package/dist/claustrum-scoped-roster.js +194 -0
- package/dist/claustrum-scoped-runtime.d.ts +28 -0
- package/dist/claustrum-scoped-runtime.js +230 -0
- package/dist/claustrum-scoped.d.ts +39 -0
- package/dist/claustrum-scoped.js +193 -0
- package/dist/claustrum.d.ts +252 -0
- package/dist/claustrum.js +1471 -0
- package/dist/commands/account.d.ts +43 -11
- package/dist/commands/account.js +147 -4
- package/dist/constants.d.ts +5 -5
- package/dist/constants.js +5 -5
- package/dist/custom-headers.d.ts +3 -0
- package/dist/custom-headers.js +102 -0
- package/dist/dump.js +2 -1
- package/dist/fast.js +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/json.d.ts +1 -0
- package/dist/json.js +10 -0
- package/dist/logger.js +3 -1
- package/dist/mid-conversation-output-config.d.ts +13 -0
- package/dist/mid-conversation-output-config.js +89 -0
- package/dist/model-remap.d.ts +27 -0
- package/dist/model-remap.js +72 -0
- package/dist/models.d.ts +46 -1
- package/dist/models.js +87 -8
- package/dist/network-errors.d.ts +1 -0
- package/dist/network-errors.js +27 -0
- package/dist/oauth-profile.d.ts +2 -1
- package/dist/oauth-profile.js +6 -0
- package/dist/prime.d.ts +11 -3
- package/dist/prime.js +25 -7
- package/dist/quota-header-feed.d.ts +32 -7
- package/dist/quota-header-feed.js +93 -10
- package/dist/quota-headers.js +59 -6
- package/dist/quota-manager.d.ts +20 -2
- package/dist/quota-manager.js +101 -24
- package/dist/relay.d.ts +8 -0
- package/dist/relay.js +72 -12
- package/dist/sticky-routing.d.ts +2 -0
- package/dist/sticky-routing.js +19 -1
- package/dist/thinking-binding.d.ts +7 -0
- package/dist/thinking-binding.js +54 -0
- package/package.json +4 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import { ClaustrumEnrollmentManager, getClaustrumEnrollmentPaths, } from './claustrum-enrollment.js';
|
|
4
|
+
const REGISTRY_SYMBOL = Symbol.for('cortexkit.anthropic-auth.claustrum-enrollments.v2');
|
|
5
|
+
const PENDING_POLL_MS = 5_000;
|
|
6
|
+
const RETRY_POLL_MS = 60_000;
|
|
7
|
+
const UNAVAILABLE_RETRY_MS = 5_000;
|
|
8
|
+
export function getHostClaustrumEnrollmentPaths(host, env = process.env, cwd = process.cwd()) {
|
|
9
|
+
const configured = env[`${host.toUpperCase()}_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE`]?.trim();
|
|
10
|
+
const tokenPath = configured
|
|
11
|
+
? isAbsolute(configured)
|
|
12
|
+
? configured
|
|
13
|
+
: resolve(cwd, configured)
|
|
14
|
+
: join(env.XDG_STATE_HOME || join(homedir(), '.local', 'state'), 'cortexkit', 'anthropic-auth', `${host}-enrollment.json`);
|
|
15
|
+
return getClaustrumEnrollmentPaths(tokenPath);
|
|
16
|
+
}
|
|
17
|
+
function registry() {
|
|
18
|
+
const global = globalThis;
|
|
19
|
+
if (!global[REGISTRY_SYMBOL])
|
|
20
|
+
global[REGISTRY_SYMBOL] = new Map();
|
|
21
|
+
return global[REGISTRY_SYMBOL];
|
|
22
|
+
}
|
|
23
|
+
function notify(entry, status) {
|
|
24
|
+
entry.status = status;
|
|
25
|
+
for (const listener of entry.leases.values())
|
|
26
|
+
listener(status);
|
|
27
|
+
}
|
|
28
|
+
function schedule(entry, delayMs) {
|
|
29
|
+
if (entry.closed || entry.timer)
|
|
30
|
+
return;
|
|
31
|
+
entry.timer = entry.setTimeoutImpl(() => {
|
|
32
|
+
entry.timer = undefined;
|
|
33
|
+
void run(entry);
|
|
34
|
+
}, delayMs);
|
|
35
|
+
if (typeof entry.timer === 'object' &&
|
|
36
|
+
entry.timer &&
|
|
37
|
+
'unref' in entry.timer) {
|
|
38
|
+
entry.timer.unref();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function nextDelay(status, pollIntervalMs) {
|
|
42
|
+
if (pollIntervalMs === 0 ||
|
|
43
|
+
status.state === 'approved' ||
|
|
44
|
+
status.state === 'denied' ||
|
|
45
|
+
status.state === 'blocked') {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
if (status.state === 'pending') {
|
|
49
|
+
return status.retryCode ? RETRY_POLL_MS : pollIntervalMs;
|
|
50
|
+
}
|
|
51
|
+
return UNAVAILABLE_RETRY_MS;
|
|
52
|
+
}
|
|
53
|
+
async function getClient(entry) {
|
|
54
|
+
if (entry.closed)
|
|
55
|
+
throw new Error('Claustrum enrollment registry is closed');
|
|
56
|
+
if (entry.client)
|
|
57
|
+
return entry.client;
|
|
58
|
+
if (!entry.clientPromise) {
|
|
59
|
+
entry.clientPromise = entry
|
|
60
|
+
.connect()
|
|
61
|
+
.then((client) => {
|
|
62
|
+
if (entry.closed) {
|
|
63
|
+
client.close();
|
|
64
|
+
throw new Error('Claustrum enrollment registry is closed');
|
|
65
|
+
}
|
|
66
|
+
entry.client = client;
|
|
67
|
+
return client;
|
|
68
|
+
})
|
|
69
|
+
.finally(() => {
|
|
70
|
+
entry.clientPromise = undefined;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return entry.clientPromise;
|
|
74
|
+
}
|
|
75
|
+
async function run(entry) {
|
|
76
|
+
if (entry.closed)
|
|
77
|
+
return;
|
|
78
|
+
if (entry.run)
|
|
79
|
+
return entry.run;
|
|
80
|
+
entry.run = (async () => {
|
|
81
|
+
let status;
|
|
82
|
+
try {
|
|
83
|
+
status = await entry.manager.reconcile();
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
status = {
|
|
87
|
+
state: 'unavailable',
|
|
88
|
+
proposedName: entry.proposedName,
|
|
89
|
+
// Unknown transport/storage errors may echo one-shot bearer material.
|
|
90
|
+
code: 'unavailable',
|
|
91
|
+
};
|
|
92
|
+
// A transport or filesystem failure is not a durable ceremony verdict. Keep
|
|
93
|
+
// retrying while the process is alive; only the manager persists protocol-terminal
|
|
94
|
+
// outcomes such as denied, superseded, or already_consumed.
|
|
95
|
+
if (entry.closed)
|
|
96
|
+
return;
|
|
97
|
+
notify(entry, status);
|
|
98
|
+
if (entry.pollIntervalMs !== 0)
|
|
99
|
+
schedule(entry, UNAVAILABLE_RETRY_MS);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (entry.closed)
|
|
103
|
+
return;
|
|
104
|
+
notify(entry, status);
|
|
105
|
+
const delay = nextDelay(status, entry.pollIntervalMs);
|
|
106
|
+
if (delay !== undefined)
|
|
107
|
+
schedule(entry, delay);
|
|
108
|
+
})().finally(() => {
|
|
109
|
+
entry.run = undefined;
|
|
110
|
+
});
|
|
111
|
+
return entry.run;
|
|
112
|
+
}
|
|
113
|
+
export function adoptClaustrumEnrollment(options) {
|
|
114
|
+
const key = resolve(options.paths.tokenPath);
|
|
115
|
+
const entries = registry();
|
|
116
|
+
let entry = entries.get(key);
|
|
117
|
+
if (entry && entry.proposedName !== options.proposedName) {
|
|
118
|
+
throw new Error('Claustrum enrollment path is already owned by a different consumer');
|
|
119
|
+
}
|
|
120
|
+
if (!entry) {
|
|
121
|
+
const connect = options.connect;
|
|
122
|
+
const setTimeoutImpl = options.setTimeoutImpl ?? setTimeout;
|
|
123
|
+
const clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout;
|
|
124
|
+
const lazyClient = {
|
|
125
|
+
enrollPropose: async (input) => {
|
|
126
|
+
const current = entry;
|
|
127
|
+
const client = await getClient(current);
|
|
128
|
+
if (current.closed)
|
|
129
|
+
throw new Error('Claustrum enrollment registry is closed');
|
|
130
|
+
return client.enrollPropose(input);
|
|
131
|
+
},
|
|
132
|
+
enrollPoll: async (input) => {
|
|
133
|
+
const current = entry;
|
|
134
|
+
const client = await getClient(current);
|
|
135
|
+
if (current.closed)
|
|
136
|
+
throw new Error('Claustrum enrollment registry is closed');
|
|
137
|
+
// Once a poll has been sent, let the manager durably collect its one-shot
|
|
138
|
+
// approval even if release wins meanwhile. Only later calls are fenced.
|
|
139
|
+
return client.enrollPoll(input);
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
entry = {
|
|
143
|
+
key,
|
|
144
|
+
proposedName: options.proposedName,
|
|
145
|
+
leases: new Map(),
|
|
146
|
+
manager: new ClaustrumEnrollmentManager({
|
|
147
|
+
client: lazyClient,
|
|
148
|
+
paths: options.paths,
|
|
149
|
+
proposedName: options.proposedName,
|
|
150
|
+
}),
|
|
151
|
+
connect,
|
|
152
|
+
setTimeoutImpl,
|
|
153
|
+
clearTimeoutImpl,
|
|
154
|
+
pollIntervalMs: options.pollIntervalMs ?? PENDING_POLL_MS,
|
|
155
|
+
status: { state: 'idle' },
|
|
156
|
+
closed: false,
|
|
157
|
+
};
|
|
158
|
+
entries.set(key, entry);
|
|
159
|
+
}
|
|
160
|
+
const lease = Symbol(key);
|
|
161
|
+
entry.leases.set(lease, options.onStatus ?? (() => { }));
|
|
162
|
+
options.onStatus?.(entry.status);
|
|
163
|
+
void run(entry);
|
|
164
|
+
let released = false;
|
|
165
|
+
return {
|
|
166
|
+
status: () => entry?.status ?? { state: 'idle' },
|
|
167
|
+
reconcileNow: () => (entry ? run(entry) : Promise.resolve()),
|
|
168
|
+
resetTerminal: async () => {
|
|
169
|
+
if (!entry)
|
|
170
|
+
return 'idle';
|
|
171
|
+
const result = await entry.manager.resetTerminal();
|
|
172
|
+
if (result === 'reset') {
|
|
173
|
+
notify(entry, { state: 'idle' });
|
|
174
|
+
await run(entry);
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
},
|
|
178
|
+
release: () => {
|
|
179
|
+
if (released || !entry)
|
|
180
|
+
return;
|
|
181
|
+
released = true;
|
|
182
|
+
entry.leases.delete(lease);
|
|
183
|
+
if (entry.leases.size > 0)
|
|
184
|
+
return;
|
|
185
|
+
entry.closed = true;
|
|
186
|
+
if (entry.timer) {
|
|
187
|
+
entry.clearTimeoutImpl(entry.timer);
|
|
188
|
+
entry.timer = undefined;
|
|
189
|
+
}
|
|
190
|
+
entry.client?.close();
|
|
191
|
+
entries.delete(key);
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type ClaustrumClientOptions as ClaustrumEnrollmentClientOptions, type EnrollmentPollOutcome, type EnrollmentTokenFile, writeEnrollmentTokenFile } from '@cortexkit/claustrum-client';
|
|
2
|
+
export declare const CLAUSTRUM_OPENCODE_ENROLLMENT_NAME = "anthropic-auth-opencode";
|
|
3
|
+
export declare const CLAUSTRUM_PI_ENROLLMENT_NAME = "anthropic-auth-pi";
|
|
4
|
+
export interface ClaustrumEnrollmentClient {
|
|
5
|
+
enrollPropose(input: {
|
|
6
|
+
name: string;
|
|
7
|
+
requestSecretHash: string;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
requestId: string;
|
|
10
|
+
}>;
|
|
11
|
+
enrollPoll(input: {
|
|
12
|
+
requestId: string;
|
|
13
|
+
requestSecret: string;
|
|
14
|
+
}): Promise<EnrollmentPollOutcome>;
|
|
15
|
+
}
|
|
16
|
+
export interface ClaustrumEnrollmentConnection extends ClaustrumEnrollmentClient {
|
|
17
|
+
close(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function connectClaustrumEnrollmentClient(options?: ClaustrumEnrollmentClientOptions): Promise<ClaustrumEnrollmentConnection>;
|
|
20
|
+
export type ClaustrumEnrollmentStatus = {
|
|
21
|
+
state: 'idle';
|
|
22
|
+
} | {
|
|
23
|
+
state: 'pending';
|
|
24
|
+
proposedName: string;
|
|
25
|
+
requestId?: string;
|
|
26
|
+
retryCode?: string;
|
|
27
|
+
} | {
|
|
28
|
+
state: 'approved';
|
|
29
|
+
proposedName: string;
|
|
30
|
+
approvedName?: string;
|
|
31
|
+
tokenGeneration: number;
|
|
32
|
+
} | {
|
|
33
|
+
state: 'denied';
|
|
34
|
+
proposedName: string;
|
|
35
|
+
} | {
|
|
36
|
+
state: 'blocked';
|
|
37
|
+
proposedName: string;
|
|
38
|
+
code: string;
|
|
39
|
+
} | {
|
|
40
|
+
state: 'unavailable';
|
|
41
|
+
proposedName: string;
|
|
42
|
+
code: string;
|
|
43
|
+
} | {
|
|
44
|
+
state: 'busy';
|
|
45
|
+
};
|
|
46
|
+
export interface ClaustrumEnrollmentPaths {
|
|
47
|
+
statePath: string;
|
|
48
|
+
tokenPath: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function getClaustrumEnrollmentPaths(tokenPath: string): ClaustrumEnrollmentPaths;
|
|
51
|
+
export declare function readClaustrumEnrollmentStatus(paths: ClaustrumEnrollmentPaths, proposedName?: string): Promise<ClaustrumEnrollmentStatus>;
|
|
52
|
+
/** Read fresh bearer material for a scoped operation; never publish this value. */
|
|
53
|
+
export declare function readClaustrumEnrollmentToken(tokenPath: string): Promise<EnrollmentTokenFile>;
|
|
54
|
+
export declare class ClaustrumEnrollmentManager {
|
|
55
|
+
#private;
|
|
56
|
+
constructor(options: {
|
|
57
|
+
client: ClaustrumEnrollmentClient;
|
|
58
|
+
paths: ClaustrumEnrollmentPaths;
|
|
59
|
+
proposedName: string;
|
|
60
|
+
now?: () => number;
|
|
61
|
+
mintSecret?: () => string;
|
|
62
|
+
writeTokenFile?: typeof writeEnrollmentTokenFile;
|
|
63
|
+
});
|
|
64
|
+
status(): Promise<ClaustrumEnrollmentStatus>;
|
|
65
|
+
resetTerminal(): Promise<ClaustrumEnrollmentResetResult>;
|
|
66
|
+
reconcile(): Promise<ClaustrumEnrollmentStatus>;
|
|
67
|
+
}
|
|
68
|
+
export type ClaustrumEnrollmentResetResult = 'reset' | 'idle' | 'refused-pending' | 'refused-approved' | 'busy';
|
|
69
|
+
/** Reset local terminal metadata without connecting to the credential daemon. */
|
|
70
|
+
export declare function resetClaustrumEnrollmentState(paths: ClaustrumEnrollmentPaths, proposedName: string): Promise<ClaustrumEnrollmentResetResult>;
|