@modelprofile.com/authswitch 6.5.0 → 8.0.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/authority-contract.d.ts +300 -6
- package/dist_ts/authority-contract.js +1 -1
- package/dist_ts/authority-runtime-contract.d.ts +13 -0
- package/dist_ts/classes.accountlist.js +4 -3
- package/dist_ts/classes.authoritybroker.d.ts +25 -5
- package/dist_ts/classes.authoritybroker.js +388 -123
- package/dist_ts/classes.authoritycli.d.ts +24 -0
- package/dist_ts/classes.authoritycli.js +675 -0
- package/dist_ts/classes.authorityclient.d.ts +19 -7
- package/dist_ts/classes.authorityclient.js +51 -14
- package/dist_ts/classes.authoritydaemon.d.ts +28 -1
- package/dist_ts/classes.authoritydaemon.js +477 -36
- package/dist_ts/classes.authoritydatabase.d.ts +155 -11
- package/dist_ts/classes.authoritydatabase.js +1037 -69
- package/dist_ts/classes.authoritymodels.d.ts +229 -23
- package/dist_ts/classes.authoritymodels.js +867 -128
- package/dist_ts/classes.authoritypreuse.d.ts +47 -0
- package/dist_ts/classes.authoritypreuse.js +277 -0
- package/dist_ts/classes.authorityregistry.d.ts +9 -0
- package/dist_ts/classes.authorityregistry.js +32 -0
- package/dist_ts/classes.authoritysecrets.d.ts +1 -1
- package/dist_ts/classes.authoritysecrets.js +2 -2
- package/dist_ts/classes.authorityusage.d.ts +160 -0
- package/dist_ts/classes.authorityusage.js +429 -0
- package/dist_ts/classes.claudeauthority.d.ts +66 -0
- package/dist_ts/classes.claudeauthority.js +528 -0
- package/dist_ts/classes.claudecodeharness.js +3 -2
- package/dist_ts/classes.claudecodelocks.d.ts +13 -0
- package/dist_ts/classes.claudecodelocks.js +75 -3
- package/dist_ts/classes.claudenative.d.ts +130 -0
- package/dist_ts/classes.claudenative.js +708 -0
- package/dist_ts/classes.claudestatus.d.ts +9 -0
- package/dist_ts/classes.claudestatus.js +26 -9
- package/dist_ts/classes.claudetokenrefresh.d.ts +15 -1
- package/dist_ts/classes.claudetokenrefresh.js +74 -21
- package/dist_ts/classes.codexharness.js +4 -2
- package/dist_ts/classes.codexmanaged.d.ts +12 -1
- package/dist_ts/classes.codexmanaged.js +75 -14
- package/dist_ts/classes.codexpreuse.d.ts +8 -0
- package/dist_ts/classes.codexpreuse.js +24 -6
- package/dist_ts/classes.fileharness.d.ts +2 -0
- package/dist_ts/classes.fileharness.js +6 -4
- package/dist_ts/classes.limits.js +12 -7
- package/dist_ts/classes.opencodeharness.js +2 -2
- package/dist_ts/claudehttp.d.ts +10 -0
- package/dist_ts/claudehttp.js +29 -3
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +7 -1
- package/dist_ts/interfaces.harness.d.ts +6 -0
- package/dist_ts/interfaces.list.d.ts +9 -3
- package/dist_ts/plugins.d.ts +6 -3
- package/dist_ts/plugins.js +8 -4
- package/dist_ts/ts_migration/0001_authority_meta.d.ts +13 -0
- package/dist_ts/ts_migration/0001_authority_meta.js +44 -0
- package/dist_ts/ts_migration/0002_remove_backup_records.d.ts +17 -0
- package/dist_ts/ts_migration/0002_remove_backup_records.js +48 -0
- package/dist_ts/ts_migration/index.d.ts +6 -0
- package/dist_ts/ts_migration/index.js +12 -0
- package/package.json +3 -3
- package/readme.md +177 -14
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/authority-contract.ts +262 -9
- package/ts/authority-runtime-contract.ts +14 -0
- package/ts/classes.accountlist.ts +3 -2
- package/ts/classes.authoritybroker.ts +385 -121
- package/ts/classes.authoritycli.ts +719 -0
- package/ts/classes.authorityclient.ts +75 -18
- package/ts/classes.authoritydaemon.ts +444 -36
- package/ts/classes.authoritydatabase.ts +1076 -75
- package/ts/classes.authoritymodels.ts +642 -144
- package/ts/classes.authoritypreuse.ts +296 -0
- package/ts/classes.authorityregistry.ts +47 -0
- package/ts/classes.authoritysecrets.ts +1 -1
- package/ts/classes.authorityusage.ts +527 -0
- package/ts/classes.claudeauthority.ts +537 -0
- package/ts/classes.claudecodeharness.ts +2 -1
- package/ts/classes.claudecodelocks.ts +70 -1
- package/ts/classes.claudenative.ts +785 -0
- package/ts/classes.claudestatus.ts +38 -9
- package/ts/classes.claudetokenrefresh.ts +82 -19
- package/ts/classes.codexharness.ts +3 -1
- package/ts/classes.codexmanaged.ts +76 -13
- package/ts/classes.codexpreuse.ts +33 -5
- package/ts/classes.fileharness.ts +7 -3
- package/ts/classes.limits.ts +11 -6
- package/ts/classes.opencodeharness.ts +1 -1
- package/ts/claudehttp.ts +31 -2
- package/ts/index.ts +6 -0
- package/ts/interfaces.harness.ts +6 -0
- package/ts/interfaces.list.ts +9 -3
- package/ts/plugins.ts +8 -3
- package/ts/ts_migration/0001_authority_meta.ts +45 -0
- package/ts/ts_migration/0002_remove_backup_records.ts +49 -0
- package/ts/ts_migration/index.ts +12 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import type { IAuthSwitchPreuseOperation } from './authority-contract.js';
|
|
3
|
+
import { AuthSwitchAuthorityBroker } from './classes.authoritybroker.js';
|
|
4
|
+
import { AuthSwitchAuthorityDatabase } from './classes.authoritydatabase.js';
|
|
5
|
+
import { type ICodexPreuseLifecycle } from './classes.codexpreuse.js';
|
|
6
|
+
import type { IHarnessPreuseOptions, IHarnessPreuseResult } from './interfaces.harness.js';
|
|
7
|
+
export interface IAuthSwitchAuthorityPreuseExecutor {
|
|
8
|
+
runAccess(credential: plugins.flexAccounts.IOpenAiChatGptAccessCredential, options: IHarnessPreuseOptions, lifecycle: ICodexPreuseLifecycle): Promise<IHarnessPreuseResult>;
|
|
9
|
+
}
|
|
10
|
+
export interface IAuthSwitchAuthorityPreuseOptions {
|
|
11
|
+
executor?: IAuthSwitchAuthorityPreuseExecutor;
|
|
12
|
+
now?: () => number;
|
|
13
|
+
minAccessValidityMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface IAuthSwitchAuthorityPreuseRequest {
|
|
16
|
+
operationId: string;
|
|
17
|
+
accountId: string;
|
|
18
|
+
loginId: string;
|
|
19
|
+
purpose: 'openai_managed';
|
|
20
|
+
prompt: string;
|
|
21
|
+
model?: string;
|
|
22
|
+
}
|
|
23
|
+
export type TAuthSwitchAuthorityPreuseFreshAdmission = () => 'admitted' | 'account_busy';
|
|
24
|
+
/** Durable, at-most-once owner of one quota-consuming inference for one exact login. */
|
|
25
|
+
export declare class AuthSwitchAuthorityPreuse {
|
|
26
|
+
private readonly database;
|
|
27
|
+
private readonly broker;
|
|
28
|
+
private readonly executor;
|
|
29
|
+
private readonly now;
|
|
30
|
+
private readonly minAccessValidityMs;
|
|
31
|
+
private readonly starts;
|
|
32
|
+
private readonly running;
|
|
33
|
+
private closed;
|
|
34
|
+
constructor(database: AuthSwitchAuthorityDatabase, broker: AuthSwitchAuthorityBroker, options?: IAuthSwitchAuthorityPreuseOptions);
|
|
35
|
+
/** Terminalize every abandoned record before management admission opens. */
|
|
36
|
+
start(): Promise<void>;
|
|
37
|
+
begin(input: IAuthSwitchAuthorityPreuseRequest, admitFresh: TAuthSwitchAuthorityPreuseFreshAdmission): Promise<IAuthSwitchPreuseOperation>;
|
|
38
|
+
private admit;
|
|
39
|
+
private perform;
|
|
40
|
+
private fail;
|
|
41
|
+
private readStored;
|
|
42
|
+
get(operationId: string): Promise<IAuthSwitchPreuseOperation>;
|
|
43
|
+
cancel(operationId: string): Promise<IAuthSwitchPreuseOperation>;
|
|
44
|
+
wait(operationId: string): Promise<void>;
|
|
45
|
+
hasActive(operationId: string): boolean;
|
|
46
|
+
close(): Promise<void>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { AuthSwitchAuthorityBroker } from './classes.authoritybroker.js';
|
|
3
|
+
import { AuthSwitchAuthorityDatabase } from './classes.authoritydatabase.js';
|
|
4
|
+
import { CodexPreuse } from './classes.codexpreuse.js';
|
|
5
|
+
import { validatePreuseOptions } from './preuse.js';
|
|
6
|
+
const uuid = (value) => typeof value === 'string' && /^[a-f0-9-]{36}$/.test(value);
|
|
7
|
+
const hash = (value) => typeof value === 'string' && /^[a-f0-9]{64}$/.test(value);
|
|
8
|
+
const publicOperation = (operation) => ({
|
|
9
|
+
id: operation.id, accountId: operation.accountId, loginId: operation.grantId,
|
|
10
|
+
purpose: operation.purpose, requestedModel: operation.requestedModel, model: operation.model,
|
|
11
|
+
state: operation.state, result: operation.result, problem: operation.problem,
|
|
12
|
+
createdAt: operation.createdAt, updatedAt: operation.updatedAt,
|
|
13
|
+
finishedAt: operation.finishedAt, revision: operation.revision,
|
|
14
|
+
});
|
|
15
|
+
/** Durable, at-most-once owner of one quota-consuming inference for one exact login. */
|
|
16
|
+
export class AuthSwitchAuthorityPreuse {
|
|
17
|
+
database;
|
|
18
|
+
broker;
|
|
19
|
+
executor;
|
|
20
|
+
now;
|
|
21
|
+
minAccessValidityMs;
|
|
22
|
+
starts = new Map();
|
|
23
|
+
running = new Map();
|
|
24
|
+
closed = false;
|
|
25
|
+
constructor(database, broker, options = {}) {
|
|
26
|
+
this.database = database;
|
|
27
|
+
this.broker = broker;
|
|
28
|
+
this.executor = options.executor ?? new CodexPreuse();
|
|
29
|
+
this.now = options.now ?? Date.now;
|
|
30
|
+
this.minAccessValidityMs = options.minAccessValidityMs ?? 300_000;
|
|
31
|
+
}
|
|
32
|
+
/** Terminalize every abandoned record before management admission opens. */
|
|
33
|
+
async start() {
|
|
34
|
+
for (const state of ['preparing', 'request_may_have_started']) {
|
|
35
|
+
let after = null;
|
|
36
|
+
while (true) {
|
|
37
|
+
const page = await this.database.preuseOperationsByState(state, after);
|
|
38
|
+
if (!page.length)
|
|
39
|
+
break;
|
|
40
|
+
for (const operation of page) {
|
|
41
|
+
const updateId = plugins.crypto.randomUUID();
|
|
42
|
+
const now = new Date(this.now()).toISOString();
|
|
43
|
+
await this.database.changePreuseOperation(updateId, operation.id, current => {
|
|
44
|
+
if (current.state !== state)
|
|
45
|
+
throw new Error('Preuse recovery changed concurrently.');
|
|
46
|
+
return { ...current, state: state === 'preparing' ? 'not_sent' : 'outcome_unknown',
|
|
47
|
+
problem: state === 'preparing' ? 'interrupted' : 'request_uncertain',
|
|
48
|
+
updatedAt: now, finishedAt: now, revision: current.revision + 1, updateId };
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
after = page.at(-1).id;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
begin(input, admitFresh) {
|
|
56
|
+
if (this.closed)
|
|
57
|
+
return Promise.reject(new Error('Authswitch preuse is closing.'));
|
|
58
|
+
if (!uuid(input.operationId) || !hash(input.accountId) || !hash(input.loginId)
|
|
59
|
+
|| input.purpose !== 'openai_managed') {
|
|
60
|
+
return Promise.reject(new Error('Invalid preuse target.'));
|
|
61
|
+
}
|
|
62
|
+
validatePreuseOptions({ prompt: input.prompt, model: input.model });
|
|
63
|
+
const requestedModel = input.model ?? null;
|
|
64
|
+
const requestHash = plugins.crypto.createHash('sha256').update(JSON.stringify([
|
|
65
|
+
'authswitch-preuse-v1', input.accountId, input.loginId, input.purpose, input.prompt, requestedModel,
|
|
66
|
+
])).digest('hex');
|
|
67
|
+
const active = this.running.get(input.operationId);
|
|
68
|
+
if (active) {
|
|
69
|
+
if (active.requestHash !== requestHash)
|
|
70
|
+
return Promise.reject(new Error('Preuse operation ID belongs to a different request.'));
|
|
71
|
+
return this.get(input.operationId);
|
|
72
|
+
}
|
|
73
|
+
const starting = this.starts.get(input.operationId);
|
|
74
|
+
if (starting) {
|
|
75
|
+
if (starting.requestHash !== requestHash)
|
|
76
|
+
return Promise.reject(new Error('Preuse operation ID belongs to a different request.'));
|
|
77
|
+
return starting.promise;
|
|
78
|
+
}
|
|
79
|
+
const promise = this.admit(input, requestHash, requestedModel, admitFresh).finally(() => {
|
|
80
|
+
if (this.starts.get(input.operationId)?.promise === promise)
|
|
81
|
+
this.starts.delete(input.operationId);
|
|
82
|
+
});
|
|
83
|
+
this.starts.set(input.operationId, { requestHash, promise });
|
|
84
|
+
return promise;
|
|
85
|
+
}
|
|
86
|
+
async admit(input, requestHash, requestedModel, admitFresh) {
|
|
87
|
+
if (this.closed)
|
|
88
|
+
throw new Error('Authswitch preuse is closing.');
|
|
89
|
+
const prior = await this.database.readOperation(input.operationId);
|
|
90
|
+
if (prior) {
|
|
91
|
+
if (prior.kind !== 'preuse_openai' || prior.accountId !== input.accountId || prior.grantId !== input.loginId
|
|
92
|
+
|| prior.purpose !== input.purpose || prior.requestHash !== requestHash
|
|
93
|
+
|| prior.requestedModel !== requestedModel) {
|
|
94
|
+
throw new Error('Preuse operation ID belongs to a different request.');
|
|
95
|
+
}
|
|
96
|
+
if (prior.state !== 'preparing')
|
|
97
|
+
return publicOperation(prior);
|
|
98
|
+
const updateId = plugins.crypto.randomUUID();
|
|
99
|
+
const interruptedAt = new Date(this.now()).toISOString();
|
|
100
|
+
return publicOperation(await this.database.changePreuseOperation(updateId, prior.id, current => ({
|
|
101
|
+
...current, state: 'not_sent', problem: 'interrupted', updatedAt: interruptedAt,
|
|
102
|
+
finishedAt: interruptedAt, revision: current.revision + 1, updateId,
|
|
103
|
+
})));
|
|
104
|
+
}
|
|
105
|
+
const context = await this.database.readUsageContext(input.accountId, input.loginId);
|
|
106
|
+
if (!context || context.providerId !== 'openai' || context.purpose !== input.purpose
|
|
107
|
+
|| context.owner !== 'daemon' || context.removed
|
|
108
|
+
|| !['ready', 'retry_wait'].includes(context.grantState)) {
|
|
109
|
+
throw new Error('Selected OpenAI login is unavailable for preuse.');
|
|
110
|
+
}
|
|
111
|
+
if (this.closed)
|
|
112
|
+
throw new Error('Authswitch preuse is closing.');
|
|
113
|
+
const freshAdmission = admitFresh();
|
|
114
|
+
if (freshAdmission === 'admitted' && this.running.size >= 32) {
|
|
115
|
+
throw new Error('Too many active preuse operations.');
|
|
116
|
+
}
|
|
117
|
+
const now = new Date(this.now()).toISOString();
|
|
118
|
+
const admitted = await this.database.createPreuseOperation({
|
|
119
|
+
id: input.operationId, kind: 'preuse_openai', purpose: input.purpose,
|
|
120
|
+
accountId: input.accountId, grantId: input.loginId, requestHash, requestedModel,
|
|
121
|
+
model: null, authorizationGeneration: context.authorizationGeneration, grantGeneration: null,
|
|
122
|
+
state: 'preparing', result: null, problem: 'none', createdAt: now, updatedAt: now,
|
|
123
|
+
finishedAt: null, revision: 1, updateId: plugins.crypto.randomUUID(),
|
|
124
|
+
});
|
|
125
|
+
if (!admitted.created) {
|
|
126
|
+
if (admitted.operation.state !== 'preparing')
|
|
127
|
+
return publicOperation(admitted.operation);
|
|
128
|
+
const updateId = plugins.crypto.randomUUID();
|
|
129
|
+
const interruptedAt = new Date(this.now()).toISOString();
|
|
130
|
+
const interrupted = await this.database.changePreuseOperation(updateId, admitted.operation.id, current => ({
|
|
131
|
+
...current, state: 'not_sent', problem: 'interrupted', updatedAt: interruptedAt,
|
|
132
|
+
finishedAt: interruptedAt, revision: current.revision + 1, updateId,
|
|
133
|
+
}));
|
|
134
|
+
return publicOperation(interrupted);
|
|
135
|
+
}
|
|
136
|
+
if (freshAdmission === 'account_busy') {
|
|
137
|
+
const updateId = plugins.crypto.randomUUID();
|
|
138
|
+
const finishedAt = new Date(this.now()).toISOString();
|
|
139
|
+
const busy = await this.database.changePreuseOperation(updateId, admitted.operation.id, current => ({
|
|
140
|
+
...current, state: 'not_sent', problem: 'account_busy', updatedAt: finishedAt,
|
|
141
|
+
finishedAt, revision: current.revision + 1, updateId,
|
|
142
|
+
}));
|
|
143
|
+
return publicOperation(busy);
|
|
144
|
+
}
|
|
145
|
+
if (this.closed) {
|
|
146
|
+
const updateId = plugins.crypto.randomUUID();
|
|
147
|
+
const closedAt = new Date(this.now()).toISOString();
|
|
148
|
+
const closed = await this.database.changePreuseOperation(updateId, admitted.operation.id, current => ({
|
|
149
|
+
...current, state: 'not_sent', problem: 'authority_closing', updatedAt: closedAt,
|
|
150
|
+
finishedAt: closedAt, revision: current.revision + 1, updateId,
|
|
151
|
+
}));
|
|
152
|
+
return publicOperation(closed);
|
|
153
|
+
}
|
|
154
|
+
const controller = new AbortController();
|
|
155
|
+
const owned = { requestHash, controller, task: Promise.resolve() };
|
|
156
|
+
this.running.set(input.operationId, owned);
|
|
157
|
+
owned.task = this.perform(admitted.operation, input.prompt, controller.signal).finally(() => {
|
|
158
|
+
if (this.running.get(input.operationId) === owned)
|
|
159
|
+
this.running.delete(input.operationId);
|
|
160
|
+
});
|
|
161
|
+
void owned.task.catch(() => { });
|
|
162
|
+
return publicOperation(admitted.operation);
|
|
163
|
+
}
|
|
164
|
+
async perform(operation, prompt, signal) {
|
|
165
|
+
let phase = 'target';
|
|
166
|
+
try {
|
|
167
|
+
signal.throwIfAborted();
|
|
168
|
+
const context = await this.database.readUsageContext(operation.accountId, operation.grantId);
|
|
169
|
+
if (!context || context.providerId !== 'openai' || context.purpose !== operation.purpose
|
|
170
|
+
|| context.owner !== 'daemon' || context.removed
|
|
171
|
+
|| context.authorizationGeneration !== operation.authorizationGeneration
|
|
172
|
+
|| !['ready', 'retry_wait'].includes(context.grantState)) {
|
|
173
|
+
throw new Error('Preuse target changed.');
|
|
174
|
+
}
|
|
175
|
+
phase = 'access';
|
|
176
|
+
const access = await this.broker.resolveUsageAccess(context, undefined, this.minAccessValidityMs);
|
|
177
|
+
signal.throwIfAborted();
|
|
178
|
+
phase = operation.requestedModel === null ? 'catalog' : 'access';
|
|
179
|
+
const credential = {
|
|
180
|
+
kind: 'chatgptAccess', providerId: 'openai', accessToken: access.accessToken,
|
|
181
|
+
accountId: access.accountId, isFedrampAccount: access.isFedrampAccount,
|
|
182
|
+
};
|
|
183
|
+
const result = await this.executor.runAccess(credential, { prompt, ...(operation.requestedModel === null ? {} : { model: operation.requestedModel }), signal }, { beforeRequest: async (model) => {
|
|
184
|
+
signal.throwIfAborted();
|
|
185
|
+
await this.database.markPreuseRequestMayHaveStarted(operation.id, plugins.crypto.randomUUID(), model, access.grantGeneration, new Date(this.now()).toISOString());
|
|
186
|
+
} });
|
|
187
|
+
const current = await this.readStored(operation.id);
|
|
188
|
+
if (current.state !== 'request_may_have_started')
|
|
189
|
+
return;
|
|
190
|
+
const count = (value) => Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
191
|
+
const updateId = plugins.crypto.randomUUID();
|
|
192
|
+
const now = new Date(this.now()).toISOString();
|
|
193
|
+
await this.database.changePreuseOperation(updateId, operation.id, prior => ({ ...prior,
|
|
194
|
+
state: 'complete', result: { inputTokens: count(result.inputTokens), outputTokens: count(result.outputTokens),
|
|
195
|
+
totalTokens: count(result.totalTokens) }, problem: 'none', updatedAt: now, finishedAt: now,
|
|
196
|
+
revision: prior.revision + 1, updateId }));
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
await this.fail(operation.id, phase, signal);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async fail(operationId, phase, signal) {
|
|
203
|
+
let current;
|
|
204
|
+
try {
|
|
205
|
+
current = await this.readStored(operationId);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (!['preparing', 'request_may_have_started'].includes(current.state))
|
|
211
|
+
return;
|
|
212
|
+
const marked = current.state === 'request_may_have_started';
|
|
213
|
+
const problem = marked
|
|
214
|
+
? this.closed ? 'authority_closing' : signal.aborted ? 'cancelled' : 'request_uncertain'
|
|
215
|
+
: this.closed ? 'authority_closing' : signal.aborted ? 'cancelled'
|
|
216
|
+
: phase === 'target' ? 'target_unavailable' : phase === 'catalog' ? 'catalog_unavailable' : 'access_unavailable';
|
|
217
|
+
const updateId = plugins.crypto.randomUUID();
|
|
218
|
+
const now = new Date(this.now()).toISOString();
|
|
219
|
+
try {
|
|
220
|
+
await this.database.changePreuseOperation(updateId, operationId, prior => ({ ...prior,
|
|
221
|
+
state: marked ? 'outcome_unknown' : 'not_sent', problem,
|
|
222
|
+
updatedAt: now, finishedAt: now, revision: prior.revision + 1, updateId }));
|
|
223
|
+
}
|
|
224
|
+
catch { /* A durable request marker remains recoverable as outcome_unknown on restart. */ }
|
|
225
|
+
}
|
|
226
|
+
async readStored(operationId) {
|
|
227
|
+
if (!uuid(operationId))
|
|
228
|
+
throw new Error('Invalid preuse operation ID.');
|
|
229
|
+
const operation = await this.database.readOperation(operationId);
|
|
230
|
+
if (!operation || operation.kind !== 'preuse_openai')
|
|
231
|
+
throw new Error('Preuse operation was not found.');
|
|
232
|
+
return operation;
|
|
233
|
+
}
|
|
234
|
+
async get(operationId) {
|
|
235
|
+
return publicOperation(await this.readStored(operationId));
|
|
236
|
+
}
|
|
237
|
+
async cancel(operationId) {
|
|
238
|
+
let current = await this.readStored(operationId);
|
|
239
|
+
if (!['preparing', 'request_may_have_started'].includes(current.state))
|
|
240
|
+
return publicOperation(current);
|
|
241
|
+
this.running.get(operationId)?.controller.abort(new Error('Preuse cancelled.'));
|
|
242
|
+
const updateId = plugins.crypto.randomUUID();
|
|
243
|
+
const now = new Date(this.now()).toISOString();
|
|
244
|
+
try {
|
|
245
|
+
current = await this.database.changePreuseOperation(updateId, operationId, prior => ({ ...prior,
|
|
246
|
+
state: prior.state === 'preparing' ? 'not_sent' : 'outcome_unknown', problem: 'cancelled',
|
|
247
|
+
updatedAt: now, finishedAt: now, revision: prior.revision + 1, updateId }));
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
current = await this.readStored(operationId);
|
|
251
|
+
if (['preparing', 'request_may_have_started'].includes(current.state))
|
|
252
|
+
throw new Error('Preuse cancellation outcome is unknown.');
|
|
253
|
+
}
|
|
254
|
+
return publicOperation(current);
|
|
255
|
+
}
|
|
256
|
+
async wait(operationId) {
|
|
257
|
+
const starting = this.starts.get(operationId);
|
|
258
|
+
if (starting)
|
|
259
|
+
await starting.promise;
|
|
260
|
+
const running = this.running.get(operationId);
|
|
261
|
+
if (running)
|
|
262
|
+
await running.task;
|
|
263
|
+
}
|
|
264
|
+
hasActive(operationId) {
|
|
265
|
+
return this.starts.has(operationId) || this.running.has(operationId);
|
|
266
|
+
}
|
|
267
|
+
async close() {
|
|
268
|
+
if (this.closed)
|
|
269
|
+
return;
|
|
270
|
+
this.closed = true;
|
|
271
|
+
await Promise.allSettled([...this.starts.values()].map(item => item.promise));
|
|
272
|
+
for (const running of this.running.values())
|
|
273
|
+
running.controller.abort(new Error('Authswitch authority is closing.'));
|
|
274
|
+
await Promise.allSettled([...this.running.values()].map(item => item.task));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRob3JpdHlwcmV1c2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLmF1dGhvcml0eXByZXVzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUU3RSxPQUFPLEVBQUUsV0FBVyxFQUE4QixNQUFNLDBCQUEwQixDQUFDO0FBRW5GLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQThCcEQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxLQUFjLEVBQW1CLEVBQUUsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzdHLE1BQU0sSUFBSSxHQUFHLENBQUMsS0FBYyxFQUFtQixFQUFFLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM1RyxNQUFNLGVBQWUsR0FBRyxDQUFDLFNBQTBDLEVBQThCLEVBQUUsQ0FBQyxDQUFDO0lBQ25HLEVBQUUsRUFBRSxTQUFTLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTztJQUM1RSxPQUFPLEVBQUUsU0FBUyxDQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsU0FBUyxDQUFDLGNBQWMsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7SUFDNUYsS0FBSyxFQUFFLFNBQVMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxPQUFPO0lBQzVFLFNBQVMsRUFBRSxTQUFTLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsU0FBUztJQUM5RCxVQUFVLEVBQUUsU0FBUyxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVE7Q0FDL0QsQ0FBQyxDQUFDO0FBRUgsd0ZBQXdGO0FBQ3hGLE1BQU0sT0FBTyx5QkFBeUI7SUFRUDtJQUNWO0lBUkYsUUFBUSxDQUFxQztJQUM3QyxHQUFHLENBQWU7SUFDbEIsbUJBQW1CLENBQVM7SUFDNUIsTUFBTSxHQUFHLElBQUksR0FBRyxFQUFpRixDQUFDO0lBQ2xHLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBMEIsQ0FBQztJQUNyRCxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBRXZCLFlBQTZCLFFBQXFDLEVBQy9DLE1BQWlDLEVBQUUsVUFBNkMsRUFBRTtRQUR4RSxhQUFRLEdBQVIsUUFBUSxDQUE2QjtRQUMvQyxXQUFNLEdBQU4sTUFBTSxDQUEyQjtRQUNsRCxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLElBQUksSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUN0RCxJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUNuQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixJQUFJLE9BQU8sQ0FBQztJQUNwRSxDQUFDO0lBRUQsNEVBQTRFO0lBQ3JFLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLEtBQUssTUFBTSxLQUFLLElBQUksQ0FBQyxXQUFXLEVBQUUsMEJBQTBCLENBQVUsRUFBRSxDQUFDO1lBQ3ZFLElBQUksS0FBSyxHQUFrQixJQUFJLENBQUM7WUFDaEMsT0FBTyxJQUFJLEVBQUUsQ0FBQztnQkFDWixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsdUJBQXVCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN2RSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07b0JBQUUsTUFBTTtnQkFDeEIsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztvQkFDN0IsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztvQkFDN0MsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQy9DLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRTt3QkFDMUUsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLEtBQUs7NEJBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO3dCQUN0RixPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsaUJBQWlCOzRCQUNoRixPQUFPLEVBQUUsS0FBSyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxtQkFBbUI7NEJBQ3BFLFNBQVMsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUM7b0JBQ2hGLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUM7Z0JBQ0QsS0FBSyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUUsQ0FBQyxFQUFFLENBQUM7WUFDMUIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQXdDLEVBQ25ELFVBQW9EO1FBQ3BELElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQyxDQUFDO1FBQ25GLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDO2VBQ3pFLEtBQUssQ0FBQyxPQUFPLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztZQUN4QyxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDO1FBQzdELENBQUM7UUFDRCxxQkFBcUIsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNwRSxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQztRQUMzQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUM1RSxzQkFBc0IsRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLGNBQWM7U0FDcEcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuRCxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsSUFBSSxNQUFNLENBQUMsV0FBVyxLQUFLLFdBQVc7Z0JBQUUsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLHFEQUFxRCxDQUFDLENBQUMsQ0FBQztZQUNoSSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDcEQsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLElBQUksUUFBUSxDQUFDLFdBQVcsS0FBSyxXQUFXO2dCQUFFLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDLENBQUM7WUFDbEksT0FBTyxRQUFRLENBQUMsT0FBTyxDQUFDO1FBQzFCLENBQUM7UUFDRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLFVBQVUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDdEYsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsT0FBTyxLQUFLLE9BQU87Z0JBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3JHLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzdELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFTyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQXdDLEVBQUUsV0FBbUIsRUFDL0UsY0FBNkIsRUFDN0IsVUFBb0Q7UUFDcEQsSUFBSSxJQUFJLENBQUMsTUFBTTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUNsRSxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuRSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGVBQWUsSUFBSSxLQUFLLENBQUMsU0FBUyxLQUFLLEtBQUssQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLE9BQU8sS0FBSyxLQUFLLENBQUMsT0FBTzttQkFDdkcsS0FBSyxDQUFDLE9BQU8sS0FBSyxLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssV0FBVzttQkFDcEUsS0FBSyxDQUFDLGNBQWMsS0FBSyxjQUFjLEVBQUUsQ0FBQztnQkFDN0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO1lBQ3pFLENBQUM7WUFDRCxJQUFJLEtBQUssQ0FBQyxLQUFLLEtBQUssV0FBVztnQkFBRSxPQUFPLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMvRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzdDLE1BQU0sYUFBYSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3pELE9BQU8sZUFBZSxDQUFDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQy9GLEdBQUcsT0FBTyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsYUFBYTtnQkFDL0UsVUFBVSxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsUUFBUTthQUNwRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNyRixJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEtBQUssS0FBSyxDQUFDLE9BQU87ZUFDL0UsT0FBTyxDQUFDLEtBQUssS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLE9BQU87ZUFDN0MsQ0FBQyxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDM0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sY0FBYyxHQUFHLFVBQVUsRUFBRSxDQUFDO1FBQ3BDLElBQUksY0FBYyxLQUFLLFVBQVUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUM3RCxNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUNELE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQy9DLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQztZQUN6RCxFQUFFLEVBQUUsS0FBSyxDQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztZQUNwRSxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYztZQUMvRSxLQUFLLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixFQUFFLE9BQU8sQ0FBQyx1QkFBdUIsRUFBRSxlQUFlLEVBQUUsSUFBSTtZQUM1RixLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxHQUFHO1lBQ2pGLFVBQVUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7U0FDckUsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN0QixJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxLQUFLLFdBQVc7Z0JBQUUsT0FBTyxlQUFlLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3pGLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDN0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDekQsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3pHLEdBQUcsT0FBTyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsYUFBYTtnQkFDL0UsVUFBVSxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsUUFBUTthQUNwRSxDQUFDLENBQUMsQ0FBQztZQUNKLE9BQU8sZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFDRCxJQUFJLGNBQWMsS0FBSyxjQUFjLEVBQUUsQ0FBQztZQUN0QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzdDLE1BQU0sVUFBVSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3RELE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRyxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsU0FBUyxFQUFFLFVBQVU7Z0JBQzdFLFVBQVUsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsUUFBUTthQUNyRCxDQUFDLENBQUMsQ0FBQztZQUNKLE9BQU8sZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQy9CLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQixNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzdDLE1BQU0sUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3BELE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRyxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxTQUFTLEVBQUUsUUFBUTtnQkFDaEYsVUFBVSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsUUFBUTthQUMvRCxDQUFDLENBQUMsQ0FBQztZQUNKLE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sS0FBSyxHQUFtQixFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ25GLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDM0MsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRTtZQUMxRixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxLQUFLO2dCQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1RixDQUFDLENBQUMsQ0FBQztRQUNILEtBQUssS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEMsT0FBTyxlQUFlLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFTyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQTBDLEVBQUUsTUFBYyxFQUFFLE1BQW1CO1FBQ25HLElBQUksS0FBSyxHQUFvQyxRQUFRLENBQUM7UUFDdEQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM3RixJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEtBQUssU0FBUyxDQUFDLE9BQU87bUJBQ25GLE9BQU8sQ0FBQyxLQUFLLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxPQUFPO21CQUM3QyxPQUFPLENBQUMsdUJBQXVCLEtBQUssU0FBUyxDQUFDLHVCQUF1QjttQkFDckUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQzNELE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztZQUM1QyxDQUFDO1lBQ0QsS0FBSyxHQUFHLFFBQVEsQ0FBQztZQUNqQixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNsRyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDeEIsS0FBSyxHQUFHLFNBQVMsQ0FBQyxjQUFjLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztZQUNqRSxNQUFNLFVBQVUsR0FBd0Q7Z0JBQ3RFLElBQUksRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVc7Z0JBQzVFLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxnQkFBZ0I7YUFDdkUsQ0FBQztZQUNGLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUNyRCxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsU0FBUyxDQUFDLGNBQWMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQ3JHLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBQyxLQUFLLEVBQUMsRUFBRTtvQkFDN0IsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO29CQUN4QixNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsK0JBQStCLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxFQUMzRixLQUFLLEVBQUUsTUFBTSxDQUFDLGVBQWUsRUFBRSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO2dCQUN2RSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ1AsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwRCxJQUFJLE9BQU8sQ0FBQyxLQUFLLEtBQUssMEJBQTBCO2dCQUFFLE9BQU87WUFDekQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUF5QixFQUFpQixFQUFFLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUN2SCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzdDLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQy9DLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEtBQUs7Z0JBQ3BGLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsWUFBWSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDO29CQUMzRyxXQUFXLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsR0FBRztnQkFDNUYsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLEdBQUcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQy9DLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFtQixFQUFFLEtBQXNDLEVBQUUsTUFBbUI7UUFDakcsSUFBSSxPQUF3QyxDQUFDO1FBQzdDLElBQUksQ0FBQztZQUFDLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7UUFBQyxDQUFDO1FBQ3JELE1BQU0sQ0FBQztZQUFDLE9BQU87UUFBQyxDQUFDO1FBQ2pCLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSwwQkFBMEIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTztRQUMvRSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxLQUFLLDBCQUEwQixDQUFDO1FBQzVELE1BQU0sT0FBTyxHQUFrQyxNQUFNO1lBQ25ELENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxtQkFBbUI7WUFDeEYsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxXQUFXO2dCQUNoRSxDQUFDLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQztRQUNySCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzdDLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQy9DLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSztnQkFDbkYsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxPQUFPO2dCQUN2RCxTQUFTLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLEdBQUcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBQUMsTUFBTSxDQUFDLENBQUMsaUZBQWlGLENBQUMsQ0FBQztJQUMvRixDQUFDO0lBRU8sS0FBSyxDQUFDLFVBQVUsQ0FBQyxXQUFtQjtRQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUN4RSxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxlQUFlO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO1FBQ3pHLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFTSxLQUFLLENBQUMsR0FBRyxDQUFDLFdBQW1CO1FBQ2xDLE9BQU8sZUFBZSxDQUFDLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFTSxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQW1CO1FBQ3JDLElBQUksT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsMEJBQTBCLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO1FBQ2hGLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDN0MsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDL0MsSUFBSSxDQUFDO1lBQ0gsT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSztnQkFDN0YsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxXQUFXO2dCQUN6RixTQUFTLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLEdBQUcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsV0FBVyxFQUFFLDBCQUEwQixDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7Z0JBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO1FBQ3BJLENBQUM7UUFDRCxPQUFPLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRU0sS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFtQjtRQUNuQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5QyxJQUFJLFFBQVE7WUFBRSxNQUFNLFFBQVEsQ0FBQyxPQUFPLENBQUM7UUFDckMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDOUMsSUFBSSxPQUFPO1lBQUUsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQ2xDLENBQUM7SUFFTSxTQUFTLENBQUMsV0FBbUI7UUFDbEMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUs7UUFDaEIsSUFBSSxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU87UUFDeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDOUUsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRTtZQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUMsQ0FBQztRQUNySCxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM5RSxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
interface IAuthorityModelEntry {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
initialize(db: plugins.nosqldb.SmartdataDb): Promise<void>;
|
|
5
|
+
prepare(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
/** The sole authority collection inventory: startup admits exactly these collections and prepares each one. */
|
|
8
|
+
export declare const authorityModelRegistry: readonly IAuthorityModelEntry[];
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { AuthSwitchAuthorityAccountModel, AuthSwitchAuthorityBindingModel, AuthSwitchAuthorityClaudeHandoffModel, AuthSwitchAuthorityClaudeHomeModel, AuthSwitchAuthorityCodexHomeModel, AuthSwitchAuthorityEnrollmentModel, AuthSwitchAuthorityEventModel, AuthSwitchAuthorityGrantModel, AuthSwitchAuthorityHandoffModel, AuthSwitchAuthorityMetaModel, AuthSwitchAuthorityMigrationLedgerModel, AuthSwitchAuthorityOperationModel, AuthSwitchAuthorityUsageModel, } from './classes.authoritymodels.js';
|
|
3
|
+
const define = (name, model) => Object.freeze({
|
|
4
|
+
name,
|
|
5
|
+
initialize: async (db) => {
|
|
6
|
+
plugins.nosqldb.setDefaultManagerForDoc({ db }, model);
|
|
7
|
+
await model.init();
|
|
8
|
+
},
|
|
9
|
+
prepare: () => model.exact.prepare(),
|
|
10
|
+
});
|
|
11
|
+
/** The sole authority collection inventory: startup admits exactly these collections and prepares each one. */
|
|
12
|
+
export const authorityModelRegistry = Object.freeze([
|
|
13
|
+
define('authswitch_authority_accounts', AuthSwitchAuthorityAccountModel),
|
|
14
|
+
define('authswitch_authority_bindings', AuthSwitchAuthorityBindingModel),
|
|
15
|
+
define('authswitch_authority_claude_handoffs', AuthSwitchAuthorityClaudeHandoffModel),
|
|
16
|
+
define('authswitch_authority_claude_homes', AuthSwitchAuthorityClaudeHomeModel),
|
|
17
|
+
define('authswitch_authority_codex_homes', AuthSwitchAuthorityCodexHomeModel),
|
|
18
|
+
define('authswitch_authority_enrollments', AuthSwitchAuthorityEnrollmentModel),
|
|
19
|
+
define('authswitch_authority_events', AuthSwitchAuthorityEventModel),
|
|
20
|
+
define('authswitch_authority_grants', AuthSwitchAuthorityGrantModel),
|
|
21
|
+
define('authswitch_authority_handoffs', AuthSwitchAuthorityHandoffModel),
|
|
22
|
+
define('authswitch_authority_meta', AuthSwitchAuthorityMetaModel),
|
|
23
|
+
define('authswitch_authority_migration_ledger', AuthSwitchAuthorityMigrationLedgerModel),
|
|
24
|
+
define('authswitch_authority_operations', AuthSwitchAuthorityOperationModel),
|
|
25
|
+
define('authswitch_authority_usage', AuthSwitchAuthorityUsageModel),
|
|
26
|
+
]);
|
|
27
|
+
for (let index = 1; index < authorityModelRegistry.length; index++) {
|
|
28
|
+
if (authorityModelRegistry[index - 1].name >= authorityModelRegistry[index].name) {
|
|
29
|
+
throw new Error('Authority model registry must be unique and sorted.');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRob3JpdHlyZWdpc3RyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuYXV0aG9yaXR5cmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUNMLCtCQUErQixFQUFFLCtCQUErQixFQUFFLHFDQUFxQyxFQUN2RyxrQ0FBa0MsRUFBRSxpQ0FBaUMsRUFBRSxrQ0FBa0MsRUFDekcsNkJBQTZCLEVBQUUsNkJBQTZCLEVBQUUsK0JBQStCLEVBQzdGLDRCQUE0QixFQUFFLHVDQUF1QyxFQUFFLGlDQUFpQyxFQUN4Ryw2QkFBNkIsR0FDOUIsTUFBTSw4QkFBOEIsQ0FBQztBQVF0QyxNQUFNLE1BQU0sR0FBRyxDQUFDLElBQVksRUFBRSxLQUFxRSxFQUF3QixFQUFFLENBQzNILE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDWixJQUFJO0lBQ0osVUFBVSxFQUFFLEtBQUssRUFBRSxFQUErQixFQUFFLEVBQUU7UUFDcEQsT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFDRCxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUU7Q0FDckMsQ0FBQyxDQUFDO0FBRUwsK0dBQStHO0FBQy9HLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFvQyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ25GLE1BQU0sQ0FBQywrQkFBK0IsRUFBRSwrQkFBK0IsQ0FBQztJQUN4RSxNQUFNLENBQUMsK0JBQStCLEVBQUUsK0JBQStCLENBQUM7SUFDeEUsTUFBTSxDQUFDLHNDQUFzQyxFQUFFLHFDQUFxQyxDQUFDO0lBQ3JGLE1BQU0sQ0FBQyxtQ0FBbUMsRUFBRSxrQ0FBa0MsQ0FBQztJQUMvRSxNQUFNLENBQUMsa0NBQWtDLEVBQUUsaUNBQWlDLENBQUM7SUFDN0UsTUFBTSxDQUFDLGtDQUFrQyxFQUFFLGtDQUFrQyxDQUFDO0lBQzlFLE1BQU0sQ0FBQyw2QkFBNkIsRUFBRSw2QkFBNkIsQ0FBQztJQUNwRSxNQUFNLENBQUMsNkJBQTZCLEVBQUUsNkJBQTZCLENBQUM7SUFDcEUsTUFBTSxDQUFDLCtCQUErQixFQUFFLCtCQUErQixDQUFDO0lBQ3hFLE1BQU0sQ0FBQywyQkFBMkIsRUFBRSw0QkFBNEIsQ0FBQztJQUNqRSxNQUFNLENBQUMsdUNBQXVDLEVBQUUsdUNBQXVDLENBQUM7SUFDeEYsTUFBTSxDQUFDLGlDQUFpQyxFQUFFLGlDQUFpQyxDQUFDO0lBQzVFLE1BQU0sQ0FBQyw0QkFBNEIsRUFBRSw2QkFBNkIsQ0FBQztDQUNwRSxDQUFDLENBQUM7QUFFSCxLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsc0JBQXNCLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7SUFDbkUsSUFBSSxzQkFBc0IsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2pGLE1BQU0sSUFBSSxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztJQUN6RSxDQUFDO0FBQ0gsQ0FBQyJ9
|
|
@@ -2,7 +2,7 @@ export interface IAuthSwitchSecretCodec {
|
|
|
2
2
|
seal(accountId: string, plaintext: Uint8Array): Promise<string>;
|
|
3
3
|
unseal(accountId: string, ciphertext: string): Promise<Uint8Array>;
|
|
4
4
|
}
|
|
5
|
-
/** TPM-sealed byte payloads live only as ciphertext in
|
|
5
|
+
/** TPM-sealed byte payloads live only as ciphertext in NoSQLDB. */
|
|
6
6
|
export declare class AuthSwitchTpmSecretCodec implements IAuthSwitchSecretCodec {
|
|
7
7
|
seal(accountId: string, plaintext: Uint8Array): Promise<string>;
|
|
8
8
|
unseal(accountId: string, ciphertext: string): Promise<Uint8Array>;
|
|
@@ -4,7 +4,7 @@ const secretName = (accountId) => {
|
|
|
4
4
|
throw new Error('Invalid account identity for secret custody.');
|
|
5
5
|
return `authswitch.account.${accountId}`;
|
|
6
6
|
};
|
|
7
|
-
/** TPM-sealed byte payloads live only as ciphertext in
|
|
7
|
+
/** TPM-sealed byte payloads live only as ciphertext in NoSQLDB. */
|
|
8
8
|
export class AuthSwitchTpmSecretCodec {
|
|
9
9
|
async seal(accountId, plaintext) {
|
|
10
10
|
const ciphertext = await plugins.smartsecret.sealSmartSecretTpm2Credential(secretName(accountId), plaintext);
|
|
@@ -27,4 +27,4 @@ export class AuthSwitchTpmSecretCodec {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRob3JpdHlzZWNyZXRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5hdXRob3JpdHlzZWNyZXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBT3hDLE1BQU0sVUFBVSxHQUFHLENBQUMsU0FBaUIsRUFBVSxFQUFFO0lBQy9DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO0lBQ3ZHLE9BQU8sc0JBQXNCLFNBQVMsRUFBRSxDQUFDO0FBQzNDLENBQUMsQ0FBQztBQUVGLG1FQUFtRTtBQUNuRSxNQUFNLE9BQU8sd0JBQXdCO0lBQzVCLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBaUIsRUFBRSxTQUFxQjtRQUN4RCxNQUFNLFVBQVUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxXQUFXLENBQUMsNkJBQTZCLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzdHLElBQUksQ0FBQztZQUFDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7UUFBQyxDQUFDO2dCQUNyRCxDQUFDO1lBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUFDLENBQUM7SUFDakMsQ0FBQztJQUVNLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBaUIsRUFBRSxVQUFrQjtRQUN2RCxJQUFJLENBQUMsMkJBQTJCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUN6RyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNuRCxJQUFJLENBQUM7WUFBQyxPQUFPLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQywrQkFBK0IsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFBQyxDQUFDO2dCQUMvRixDQUFDO1lBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import type { IClaudeLogin, IClaudeStatusRead } from './classes.claudestatus.js';
|
|
3
|
+
type TRateLimits = plugins.flexAccounts.ISmartAiProviderAccountRateLimits;
|
|
4
|
+
export type TAuthSwitchUsageProblem = 'none' | 'unsupported' | 'access_unavailable' | 'provider_unavailable' | 'provider_rejected' | 'profile_unavailable' | 'usage_unavailable' | 'context_changed' | 'expired';
|
|
5
|
+
export interface IAuthSwitchNativeUsageSource {
|
|
6
|
+
homeId: string;
|
|
7
|
+
credentialDigest: string;
|
|
8
|
+
configDigest: string;
|
|
9
|
+
accessTokenDigest: string;
|
|
10
|
+
}
|
|
11
|
+
/** A credential-free, exact view of the account and login used for one usage read. */
|
|
12
|
+
export interface IAuthSwitchUsageContext {
|
|
13
|
+
epoch: string;
|
|
14
|
+
accountId: string;
|
|
15
|
+
loginId: string;
|
|
16
|
+
subjectId: string;
|
|
17
|
+
workspaceId: string;
|
|
18
|
+
providerId: string;
|
|
19
|
+
purpose: string;
|
|
20
|
+
owner: string;
|
|
21
|
+
grantState: string;
|
|
22
|
+
removed: boolean;
|
|
23
|
+
authorizationGeneration: number;
|
|
24
|
+
grantGeneration: number;
|
|
25
|
+
nativeSource: IAuthSwitchNativeUsageSource | null;
|
|
26
|
+
}
|
|
27
|
+
/** A bounded, credential-free projection; it is independent of the legacy harness API. */
|
|
28
|
+
export interface IAuthSwitchClaudeStatus {
|
|
29
|
+
plan: {
|
|
30
|
+
name: string;
|
|
31
|
+
source: 'live' | 'stored';
|
|
32
|
+
} | null;
|
|
33
|
+
windows: {
|
|
34
|
+
label: string;
|
|
35
|
+
scope: 'account' | 'feature';
|
|
36
|
+
durationSeconds: number;
|
|
37
|
+
usedPercent: number;
|
|
38
|
+
resetAt: string | null;
|
|
39
|
+
severity?: 'normal' | 'warning' | 'critical';
|
|
40
|
+
headline?: true;
|
|
41
|
+
}[] | null;
|
|
42
|
+
facts: {
|
|
43
|
+
section: string | null;
|
|
44
|
+
label: string;
|
|
45
|
+
value: string;
|
|
46
|
+
summaryKey?: 'subscription' | 'billing' | 'usageWindows' | 'resets' | 'resetDetails';
|
|
47
|
+
}[];
|
|
48
|
+
problems: string[];
|
|
49
|
+
rateLimit: {
|
|
50
|
+
retryAt: string | null;
|
|
51
|
+
} | null;
|
|
52
|
+
}
|
|
53
|
+
export type TAuthSwitchUsageReading = {
|
|
54
|
+
kind: 'openai';
|
|
55
|
+
rateLimits: TRateLimits;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'anthropic';
|
|
58
|
+
status: IAuthSwitchClaudeStatus;
|
|
59
|
+
};
|
|
60
|
+
export interface IAuthSwitchUsageAccess {
|
|
61
|
+
accessToken: string;
|
|
62
|
+
accountId: string;
|
|
63
|
+
isFedrampAccount: boolean;
|
|
64
|
+
expiresAt: string;
|
|
65
|
+
grantGeneration: number;
|
|
66
|
+
}
|
|
67
|
+
/** Persist through NoSQLDB in the authority integration. No credential belongs in this record. */
|
|
68
|
+
export interface IAuthSwitchStoredUsage {
|
|
69
|
+
context: IAuthSwitchUsageContext;
|
|
70
|
+
updateId: string;
|
|
71
|
+
reading: TAuthSwitchUsageReading | null;
|
|
72
|
+
observedAt: string | null;
|
|
73
|
+
currentUntil: string | null;
|
|
74
|
+
staleUntil: string | null;
|
|
75
|
+
lastAttemptAt: string;
|
|
76
|
+
nextAttemptAt: string;
|
|
77
|
+
failures: number;
|
|
78
|
+
problem: Exclude<TAuthSwitchUsageProblem, 'context_changed' | 'expired'>;
|
|
79
|
+
}
|
|
80
|
+
export interface IAuthSwitchUsageSnapshot {
|
|
81
|
+
accountId: string;
|
|
82
|
+
loginId: string;
|
|
83
|
+
state: 'current' | 'partial' | 'stale' | 'unavailable';
|
|
84
|
+
reading: TAuthSwitchUsageReading | null;
|
|
85
|
+
observedAt: string | null;
|
|
86
|
+
currentUntil: string | null;
|
|
87
|
+
staleUntil: string | null;
|
|
88
|
+
lastAttemptAt: string | null;
|
|
89
|
+
nextAttemptAt: string | null;
|
|
90
|
+
problem: TAuthSwitchUsageProblem;
|
|
91
|
+
}
|
|
92
|
+
export interface IAuthSwitchUsageStore {
|
|
93
|
+
/** Read only the exact login's record. The helper discards a mismatched context. */
|
|
94
|
+
read(accountId: string, loginId: string): Promise<IAuthSwitchStoredUsage | null>;
|
|
95
|
+
/**
|
|
96
|
+
* In one NoSQLDB transaction, re-read epoch/account/login and compare every semantic
|
|
97
|
+
* context field, compare the previous usage update ID, write next, and append a revisioned
|
|
98
|
+
* account event. The account row revision may increase in that transaction; it is not
|
|
99
|
+
* part of the usage validity key and must not invalidate the reading just published.
|
|
100
|
+
* A null previousUpdateId also permits replacing a record for a different context;
|
|
101
|
+
* it must reject a concurrently written record for this same context.
|
|
102
|
+
* Return false on either conflict; do not publish an old provider callback.
|
|
103
|
+
*/
|
|
104
|
+
publishIfCurrent(context: IAuthSwitchUsageContext, previousUpdateId: string | null, next: IAuthSwitchStoredUsage): Promise<boolean>;
|
|
105
|
+
}
|
|
106
|
+
export interface IAuthSwitchAuthorityUsageOptions {
|
|
107
|
+
/** Re-read from the owning NoSQLDB authority. Return null for an absent login. */
|
|
108
|
+
readContext(accountId: string, loginId: string): Promise<IAuthSwitchUsageContext | null>;
|
|
109
|
+
/** Broker-owned access resolution; rejected generation may perform at most one durable refresh. */
|
|
110
|
+
resolveAccess(context: IAuthSwitchUsageContext, rejectedGrantGeneration: number | undefined, minValidityMs: number): Promise<IAuthSwitchUsageAccess>;
|
|
111
|
+
resolveClaudeLogin?(context: IAuthSwitchUsageContext, rejectedGrantGeneration: number | undefined, minValidityMs: number): Promise<{
|
|
112
|
+
login: IClaudeLogin;
|
|
113
|
+
grantGeneration: number;
|
|
114
|
+
expiresAt: string | null;
|
|
115
|
+
}>;
|
|
116
|
+
claudeStatus?: Pick<{
|
|
117
|
+
readDetailed(login: IClaudeLogin): Promise<IClaudeStatusRead>;
|
|
118
|
+
}, 'readDetailed'>;
|
|
119
|
+
/** The callback holds the qualified vendor lease through the whole read and publication. */
|
|
120
|
+
withNativeSource?(context: IAuthSwitchUsageContext, action: (source: {
|
|
121
|
+
context: IAuthSwitchUsageContext;
|
|
122
|
+
login: IClaudeLogin;
|
|
123
|
+
readContext(): Promise<IAuthSwitchUsageContext | null>;
|
|
124
|
+
}) => Promise<IAuthSwitchUsageSnapshot>): Promise<IAuthSwitchUsageSnapshot>;
|
|
125
|
+
store: IAuthSwitchUsageStore;
|
|
126
|
+
provider: Pick<plugins.flexAccounts.ISmartAiProviderAdapter, 'getAccountRateLimits'>;
|
|
127
|
+
now?: () => number;
|
|
128
|
+
currentMaxAgeMs?: number;
|
|
129
|
+
maxStaleAgeMs?: number;
|
|
130
|
+
minAttemptIntervalMs?: number;
|
|
131
|
+
retryBaseMs?: number;
|
|
132
|
+
retryMaxMs?: number;
|
|
133
|
+
providerTimeoutMs?: number;
|
|
134
|
+
minAccessValidityMs?: number;
|
|
135
|
+
}
|
|
136
|
+
/** On-demand daemon cache coordinator. The injected store is the only publication authority. */
|
|
137
|
+
export declare class AuthSwitchAuthorityUsage {
|
|
138
|
+
private readonly options;
|
|
139
|
+
private readonly now;
|
|
140
|
+
private readonly policy;
|
|
141
|
+
private readonly pending;
|
|
142
|
+
private readonly admitted;
|
|
143
|
+
private closed;
|
|
144
|
+
private closing?;
|
|
145
|
+
constructor(options: IAuthSwitchAuthorityUsageOptions);
|
|
146
|
+
private unavailable;
|
|
147
|
+
private snapshot;
|
|
148
|
+
private currentContext;
|
|
149
|
+
get(accountId: string, loginId: string, force?: boolean): Promise<IAuthSwitchUsageSnapshot>;
|
|
150
|
+
private read;
|
|
151
|
+
private readWithContext;
|
|
152
|
+
/** Coalesce the entire read/decision/fetch lifecycle, including the first stored read. */
|
|
153
|
+
private readForContext;
|
|
154
|
+
private refresh;
|
|
155
|
+
private validAccess;
|
|
156
|
+
private query;
|
|
157
|
+
/** Wait for admitted reads before the daemon disposes the shared provider or database. */
|
|
158
|
+
close(): Promise<void>;
|
|
159
|
+
}
|
|
160
|
+
export {};
|