replicas-engine 0.1.667 → 0.1.671
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 +4 -4
- package/dist/src/app-server-process-S2SD6PQE.js +10 -0
- package/dist/src/chunk-4FTBKGMO.js +162 -0
- package/dist/src/chunk-6GXXZQID.js +448 -0
- package/dist/src/chunk-6WY7NPCL.js +407 -0
- package/dist/src/{chunk-P2Q47GLV.js → chunk-TMERKNQV.js} +200 -747
- package/dist/src/chunk-XQW4B35Y.js +108 -0
- package/dist/src/codex-token-manager-RX4N2W22.js +13 -0
- package/dist/src/engine-env-A2FZA66L.js +14 -0
- package/dist/src/headless-agent.js +49 -34
- package/dist/src/index.js +428 -833
- package/package.json +1 -1
- package/workspace-sdk/shared/routes/plugins.d.ts +29 -7
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ENGINE_ENV,
|
|
4
|
+
setAgentCredentialSnapshot
|
|
5
|
+
} from "./chunk-4FTBKGMO.js";
|
|
6
|
+
import {
|
|
7
|
+
CODEX_AUTH_ENV_KEYS,
|
|
8
|
+
CODEX_AUTH_ENV_KEYS_BY_METHOD,
|
|
9
|
+
codexAuthEnvFromResponse,
|
|
10
|
+
createErrorResult,
|
|
11
|
+
createSuccessResult,
|
|
12
|
+
isRecord,
|
|
13
|
+
isValidAgentProvider
|
|
14
|
+
} from "./chunk-TMERKNQV.js";
|
|
15
|
+
|
|
16
|
+
// src/managers/codex-token-manager.ts
|
|
17
|
+
import { promises as fs } from "fs";
|
|
18
|
+
import path from "path";
|
|
19
|
+
|
|
20
|
+
// src/managers/auth-env-transition.ts
|
|
21
|
+
function applyAuthEnvTransition(params) {
|
|
22
|
+
const newOwned = new Set(params.authKeysByMethod[params.newMethod]);
|
|
23
|
+
const prevOwned = new Set(params.authKeysByMethod[params.prevMethod]);
|
|
24
|
+
for (const key of params.authKeys) {
|
|
25
|
+
const value = params.newEnvVars[key];
|
|
26
|
+
if (value !== void 0) {
|
|
27
|
+
for (const env of params.envs) {
|
|
28
|
+
env[key] = value;
|
|
29
|
+
}
|
|
30
|
+
} else if (prevOwned.has(key) && !newOwned.has(key)) {
|
|
31
|
+
for (const env of params.envs) {
|
|
32
|
+
delete env[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/services/credential-fallbacks.ts
|
|
39
|
+
var fallbacksByAgent = /* @__PURE__ */ new Map();
|
|
40
|
+
var exhaustedByAgent = /* @__PURE__ */ new Map();
|
|
41
|
+
function recordCredentialFallback(notice) {
|
|
42
|
+
fallbacksByAgent.set(notice.provider, notice);
|
|
43
|
+
}
|
|
44
|
+
function listCredentialFallbacks() {
|
|
45
|
+
return [...fallbacksByAgent.values()].filter((notice) => {
|
|
46
|
+
const live = ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS[notice.provider];
|
|
47
|
+
if (!live) return false;
|
|
48
|
+
return notice.status === "switched" ? live.method === notice.candidateMethod && live.scope === notice.candidateScope : live.method === notice.exhaustedMethod && live.scope === notice.exhaustedScope;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function listExhaustedCredentials(provider) {
|
|
52
|
+
return [...exhaustedByAgent.get(provider)?.values() ?? []];
|
|
53
|
+
}
|
|
54
|
+
function recordExhaustedCredential(provider, credential) {
|
|
55
|
+
const spent = exhaustedByAgent.get(provider) ?? /* @__PURE__ */ new Map();
|
|
56
|
+
spent.set(`${credential.method}|${credential.scope}`, credential);
|
|
57
|
+
exhaustedByAgent.set(provider, spent);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/managers/base-refresh-manager.ts
|
|
61
|
+
var BaseRefreshManager = class {
|
|
62
|
+
constructor(managerName, intervalMs = 15 * 60 * 1e3) {
|
|
63
|
+
this.managerName = managerName;
|
|
64
|
+
this.intervalMs = intervalMs;
|
|
65
|
+
this.health = {
|
|
66
|
+
isRunning: false,
|
|
67
|
+
intervalMs: this.intervalMs,
|
|
68
|
+
lastAttemptAt: null,
|
|
69
|
+
lastSuccessAt: null,
|
|
70
|
+
lastErrorAt: null,
|
|
71
|
+
lastErrorMessage: null
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
managerName;
|
|
75
|
+
intervalMs;
|
|
76
|
+
intervalHandle = null;
|
|
77
|
+
health;
|
|
78
|
+
async start() {
|
|
79
|
+
if (this.intervalHandle) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const skipReason = this.getSkipReason();
|
|
83
|
+
if (skipReason) {
|
|
84
|
+
console.log(`[${this.managerName}] Skipping: ${skipReason}`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(`[${this.managerName}] Starting token refresh service`);
|
|
88
|
+
this.health.isRunning = true;
|
|
89
|
+
const config = this.getRuntimeConfig();
|
|
90
|
+
if (config) {
|
|
91
|
+
this.health.lastAttemptAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
92
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
93
|
+
try {
|
|
94
|
+
await this.doRefresh(config);
|
|
95
|
+
this.health.lastSuccessAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
96
|
+
this.health.lastErrorAt = null;
|
|
97
|
+
this.health.lastErrorMessage = null;
|
|
98
|
+
break;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
101
|
+
this.health.lastErrorAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
102
|
+
this.health.lastErrorMessage = message;
|
|
103
|
+
if (attempt < 3) {
|
|
104
|
+
console.warn(`[${this.managerName}] Initial refresh attempt ${attempt} failed, retrying in 2s...`);
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
106
|
+
} else {
|
|
107
|
+
console.error(`[${this.managerName}] Initial refresh failed after 3 attempts:`, error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.scheduleNextRefresh();
|
|
113
|
+
}
|
|
114
|
+
async swapCredentials(params) {
|
|
115
|
+
if (!this.getRuntimeConfig()) {
|
|
116
|
+
return createErrorResult({ message: `${this.managerName} has no runtime config`, code: "not_configured" });
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
console.log(`[${this.managerName}] Fetching fresh credentials from monolith (${params.failureKind})...`);
|
|
120
|
+
const excludeCredentials = listExhaustedCredentials(params.provider);
|
|
121
|
+
await params.refresh(excludeCredentials.length > 0 ? { excludeCredentials } : {});
|
|
122
|
+
if (params.isOauthNow()) {
|
|
123
|
+
this.start().catch((error) => {
|
|
124
|
+
console.error(`[${this.managerName}] Failed to restart OAuth refresh service after fallback:`, error);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return createSuccessResult();
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
130
|
+
console.error(`[${this.managerName}] Failed to fetch fresh credentials:`, error);
|
|
131
|
+
return createErrorResult({
|
|
132
|
+
message,
|
|
133
|
+
code: message.includes('"code":"no_credentials"') ? "no_credentials" : "refresh_failed"
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
stop() {
|
|
138
|
+
if (!this.intervalHandle) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
clearTimeout(this.intervalHandle);
|
|
142
|
+
this.intervalHandle = null;
|
|
143
|
+
this.health.isRunning = false;
|
|
144
|
+
console.log(`[${this.managerName}] Stopped`);
|
|
145
|
+
}
|
|
146
|
+
getHealthStatus() {
|
|
147
|
+
return { ...this.health };
|
|
148
|
+
}
|
|
149
|
+
getSkipReason() {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
getNextRefreshDelayMs() {
|
|
153
|
+
return this.intervalMs;
|
|
154
|
+
}
|
|
155
|
+
getRuntimeConfig() {
|
|
156
|
+
if (!ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
monolithUrl: ENGINE_ENV.REPLICAS_MONOLITH_URL,
|
|
161
|
+
workspaceId: ENGINE_ENV.REPLICAS_WORKSPACE_ID,
|
|
162
|
+
engineSecret: ENGINE_ENV.REPLICAS_ENGINE_SECRET
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
scheduleNextRefresh() {
|
|
166
|
+
const delayMs = this.getNextRefreshDelayMs();
|
|
167
|
+
this.health.intervalMs = delayMs;
|
|
168
|
+
this.intervalHandle = setTimeout(async () => {
|
|
169
|
+
await this.refreshOnce();
|
|
170
|
+
if (this.intervalHandle) this.scheduleNextRefresh();
|
|
171
|
+
}, delayMs);
|
|
172
|
+
console.log(`[${this.managerName}] Token refresh scheduled in ${Math.round(delayMs / 1e3)} seconds`);
|
|
173
|
+
}
|
|
174
|
+
async refreshOnce() {
|
|
175
|
+
if (this.getSkipReason()) {
|
|
176
|
+
return createSuccessResult();
|
|
177
|
+
}
|
|
178
|
+
const config = this.getRuntimeConfig();
|
|
179
|
+
if (!config) return createSuccessResult();
|
|
180
|
+
this.health.lastAttemptAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
181
|
+
try {
|
|
182
|
+
await this.doRefresh(config);
|
|
183
|
+
this.health.lastSuccessAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
184
|
+
this.health.lastErrorAt = null;
|
|
185
|
+
this.health.lastErrorMessage = null;
|
|
186
|
+
return createSuccessResult();
|
|
187
|
+
} catch (error) {
|
|
188
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
189
|
+
this.health.lastErrorAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
190
|
+
this.health.lastErrorMessage = message;
|
|
191
|
+
console.error(`[${this.managerName}] Failed to refresh credentials:`, error);
|
|
192
|
+
return createErrorResult({ message });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// src/services/monolith-service.ts
|
|
198
|
+
async function monolithRequest(path2, init = {}) {
|
|
199
|
+
if (!ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
|
|
200
|
+
throw new Error("REPLICAS_WORKSPACE_ID is not set; cannot call monolith");
|
|
201
|
+
}
|
|
202
|
+
const headers = {
|
|
203
|
+
Authorization: `Bearer ${ENGINE_ENV.REPLICAS_ENGINE_SECRET}`,
|
|
204
|
+
"X-Workspace-Id": ENGINE_ENV.REPLICAS_WORKSPACE_ID
|
|
205
|
+
};
|
|
206
|
+
if (!(init.body instanceof FormData)) headers["Content-Type"] = "application/json";
|
|
207
|
+
return fetch(`${ENGINE_ENV.REPLICAS_MONOLITH_URL}${path2}`, {
|
|
208
|
+
method: init.method ?? "POST",
|
|
209
|
+
headers,
|
|
210
|
+
body: init.body === void 0 ? void 0 : init.body instanceof FormData ? init.body : JSON.stringify(init.body),
|
|
211
|
+
signal: init.signal
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
var MonolithService = class {
|
|
215
|
+
async getRelaySubagentProviders() {
|
|
216
|
+
try {
|
|
217
|
+
const response = await monolithRequest("/v1/engine/relay-subagent-providers", { method: "GET" });
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
const body = await response.json();
|
|
222
|
+
return isRecord(body) && Array.isArray(body.providers) && body.providers.every((provider) => typeof provider === "string" && isValidAgentProvider(provider)) ? body.providers : null;
|
|
223
|
+
} catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async getOpenRouterModels() {
|
|
228
|
+
try {
|
|
229
|
+
const response = await monolithRequest("/v1/engine/openrouter-models", { method: "GET" });
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const body = await response.json();
|
|
234
|
+
return isRecord(body) && Array.isArray(body.models) && body.models.every((model) => typeof model === "string") ? body.models : null;
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async sendEvent(event) {
|
|
240
|
+
if (!ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const response = await monolithRequest("/v1/engine/webhook", { body: event });
|
|
245
|
+
if (!response.ok) {
|
|
246
|
+
const errorText = await response.text();
|
|
247
|
+
console.error(`[MonolithService] Failed to send event: ${response.status} ${errorText}`);
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error("[MonolithService] Failed to send event:", error);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
var monolithService = new MonolithService();
|
|
255
|
+
|
|
256
|
+
// src/managers/codex-token-manager.ts
|
|
257
|
+
var CodexAspAuthMethodChangedError = class extends Error {
|
|
258
|
+
};
|
|
259
|
+
var CodexTokenManager = class extends BaseRefreshManager {
|
|
260
|
+
constructor() {
|
|
261
|
+
super("CodexTokenManager");
|
|
262
|
+
}
|
|
263
|
+
getSkipReason() {
|
|
264
|
+
if (ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD === "api_key" || ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD === "foundry") {
|
|
265
|
+
return `auth method is ${ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD}`;
|
|
266
|
+
}
|
|
267
|
+
if (!ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD && ENGINE_ENV.OPENAI_API_KEY) {
|
|
268
|
+
return "OPENAI_API_KEY is set";
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
async doRefresh(_config) {
|
|
273
|
+
await this.refreshWithRequest();
|
|
274
|
+
}
|
|
275
|
+
async refreshWithRequest(request) {
|
|
276
|
+
console.log("[CodexTokenManager] Refreshing Codex credentials...");
|
|
277
|
+
const response = await monolithRequest("/v1/engine/codex/refresh-credentials", {
|
|
278
|
+
body: request
|
|
279
|
+
});
|
|
280
|
+
if (!response.ok) {
|
|
281
|
+
const errorText = await response.text();
|
|
282
|
+
throw new Error(`Credentials refresh failed: ${response.status} ${errorText}`);
|
|
283
|
+
}
|
|
284
|
+
const data = await response.json();
|
|
285
|
+
await this.applyCredentialsResponse(data);
|
|
286
|
+
if (data.scope) {
|
|
287
|
+
setAgentCredentialSnapshot("codex", {
|
|
288
|
+
method: data.type,
|
|
289
|
+
scope: data.scope,
|
|
290
|
+
...data.revision ? { revision: data.revision } : {}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
console.log(`[CodexTokenManager] Credentials refreshed (method=${data.type})`);
|
|
294
|
+
return data;
|
|
295
|
+
}
|
|
296
|
+
async prepareAspOauthOptions() {
|
|
297
|
+
if (ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD !== "oauth") return {};
|
|
298
|
+
const response = await this.refreshWithRequest();
|
|
299
|
+
if (response.type !== "oauth") return {};
|
|
300
|
+
const login = this.buildAspOauthLogin(response);
|
|
301
|
+
let credential = login.credential;
|
|
302
|
+
return {
|
|
303
|
+
chatgptAuthTokens: login.tokens,
|
|
304
|
+
refreshChatgptAuthTokens: async (params) => {
|
|
305
|
+
const refreshed = await this.refreshAspOauthCredentials(
|
|
306
|
+
credential,
|
|
307
|
+
`Codex ASP requested an external token refresh (${params.reason})`
|
|
308
|
+
);
|
|
309
|
+
if (!refreshed.ok) {
|
|
310
|
+
if (refreshed.error.code === "method_changed") {
|
|
311
|
+
throw new CodexAspAuthMethodChangedError(refreshed.error.message);
|
|
312
|
+
}
|
|
313
|
+
throw new Error(refreshed.error.message);
|
|
314
|
+
}
|
|
315
|
+
credential = refreshed.data.credential;
|
|
316
|
+
return refreshed.data.tokens;
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
async refreshAspOauthCredentials(failedCredential, failureReason) {
|
|
321
|
+
try {
|
|
322
|
+
const response = await this.refreshWithRequest({
|
|
323
|
+
failedMethod: "oauth",
|
|
324
|
+
...failedCredential?.method === "oauth" ? { failedCredential } : {},
|
|
325
|
+
failureKind: "rejected",
|
|
326
|
+
failureReason
|
|
327
|
+
});
|
|
328
|
+
if (response.type !== "oauth") {
|
|
329
|
+
return createErrorResult({
|
|
330
|
+
message: `${failureReason}; credentials changed to ${response.type}, so the app server must restart`,
|
|
331
|
+
code: "method_changed"
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
return createSuccessResult(this.buildAspOauthLogin(response));
|
|
335
|
+
} catch (error) {
|
|
336
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
337
|
+
return createErrorResult({
|
|
338
|
+
message,
|
|
339
|
+
code: message.includes('"code":"no_credentials"') ? "no_credentials" : "refresh_failed"
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async fetchFreshCredentials(failureReason, failureKind = "rejected", failedCredential = ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS.codex) {
|
|
344
|
+
const failedMethod = failedCredential?.method === "oauth" || failedCredential?.method === "api_key" || failedCredential?.method === "foundry" ? failedCredential.method : ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD;
|
|
345
|
+
return this.swapCredentials({
|
|
346
|
+
provider: "codex",
|
|
347
|
+
failureKind,
|
|
348
|
+
refresh: async (exclusions) => {
|
|
349
|
+
await this.refreshWithRequest(
|
|
350
|
+
failedMethod === "oauth" || failedMethod === "api_key" || failedMethod === "foundry" ? {
|
|
351
|
+
failedMethod,
|
|
352
|
+
...failedCredential?.method === failedMethod ? { failedCredential } : {},
|
|
353
|
+
failureReason,
|
|
354
|
+
failureKind,
|
|
355
|
+
...exclusions
|
|
356
|
+
} : exclusions
|
|
357
|
+
);
|
|
358
|
+
},
|
|
359
|
+
isOauthNow: () => ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD === "oauth"
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
async applyCredentialsResponse(response) {
|
|
363
|
+
await this.removeOauthCredentialsFile();
|
|
364
|
+
const envVars = codexAuthEnvFromResponse(response);
|
|
365
|
+
applyAuthEnvTransition({
|
|
366
|
+
prevMethod: ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD ?? "none",
|
|
367
|
+
newMethod: envVars.REPLICAS_CODEX_AUTH_METHOD ?? "none",
|
|
368
|
+
authKeys: CODEX_AUTH_ENV_KEYS,
|
|
369
|
+
authKeysByMethod: CODEX_AUTH_ENV_KEYS_BY_METHOD,
|
|
370
|
+
newEnvVars: envVars,
|
|
371
|
+
envs: [ENGINE_ENV, process.env]
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
buildAspOauthLogin(response) {
|
|
375
|
+
const credential = ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS.codex;
|
|
376
|
+
return {
|
|
377
|
+
tokens: {
|
|
378
|
+
accessToken: response.accessToken,
|
|
379
|
+
chatgptAccountId: response.accountId,
|
|
380
|
+
chatgptPlanType: null
|
|
381
|
+
},
|
|
382
|
+
...credential?.method === "oauth" ? { credential } : {}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
async removeOauthCredentialsFile() {
|
|
386
|
+
const authPath = path.join(ENGINE_ENV.HOME_DIR, ".codex", "auth.json");
|
|
387
|
+
try {
|
|
388
|
+
await fs.unlink(authPath);
|
|
389
|
+
} catch (error) {
|
|
390
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
var codexTokenManager = new CodexTokenManager();
|
|
395
|
+
|
|
396
|
+
export {
|
|
397
|
+
applyAuthEnvTransition,
|
|
398
|
+
recordCredentialFallback,
|
|
399
|
+
listCredentialFallbacks,
|
|
400
|
+
recordExhaustedCredential,
|
|
401
|
+
BaseRefreshManager,
|
|
402
|
+
monolithRequest,
|
|
403
|
+
monolithService,
|
|
404
|
+
CodexAspAuthMethodChangedError,
|
|
405
|
+
CodexTokenManager,
|
|
406
|
+
codexTokenManager
|
|
407
|
+
};
|