@albinocrabs/o-switcher 0.3.0 → 0.4.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/CHANGELOG.md +11 -0
- package/dist/{chunk-XXH633FY.js → chunk-2EYMYNKS.js} +3 -101
- package/dist/chunk-BHHR2U5B.cjs +123 -0
- package/dist/chunk-HAEEX3KB.js +106 -0
- package/dist/chunk-I6RDAZBR.js +231 -0
- package/dist/chunk-QKEHCM2F.cjs +234 -0
- package/dist/{chunk-H72U2MNG.cjs → chunk-TGYAV5TV.cjs} +18 -128
- package/dist/index.cjs +104 -103
- package/dist/index.js +3 -2
- package/dist/plugin.cjs +60 -67
- package/dist/plugin.js +41 -48
- package/dist/proxy/cli.cjs +91 -0
- package/dist/proxy/cli.d.cts +1 -0
- package/dist/proxy/cli.d.ts +1 -0
- package/dist/proxy/cli.js +89 -0
- package/package.json +4 -1
- package/src/tui.tsx +11 -3
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkBHHR2U5B_cjs = require('./chunk-BHHR2U5B.cjs');
|
|
4
|
+
var promises = require('fs/promises');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var os = require('os');
|
|
7
|
+
var http = require('http');
|
|
8
|
+
|
|
9
|
+
var STATE_DIR = path.join(os.homedir(), ".local", "share", "o-switcher");
|
|
10
|
+
var STATE_FILE = path.join(STATE_DIR, "tui-state.json");
|
|
11
|
+
var STATE_TMP = path.join(STATE_DIR, "tui-state.json.tmp");
|
|
12
|
+
var writeStateAtomic = async (state) => {
|
|
13
|
+
await promises.mkdir(path.dirname(STATE_FILE), { recursive: true });
|
|
14
|
+
const json = JSON.stringify(state);
|
|
15
|
+
await promises.writeFile(STATE_TMP, json, "utf8");
|
|
16
|
+
await promises.rename(STATE_TMP, STATE_FILE);
|
|
17
|
+
};
|
|
18
|
+
var createStateWriter = (debounceMs = 500) => {
|
|
19
|
+
let pending;
|
|
20
|
+
let timer;
|
|
21
|
+
let writePromise = Promise.resolve();
|
|
22
|
+
const doWrite = () => {
|
|
23
|
+
if (!pending) return;
|
|
24
|
+
const snapshot = pending;
|
|
25
|
+
pending = void 0;
|
|
26
|
+
writePromise = writeStateAtomic(snapshot).catch(() => void 0);
|
|
27
|
+
};
|
|
28
|
+
const write = (state) => {
|
|
29
|
+
pending = state;
|
|
30
|
+
if (timer) clearTimeout(timer);
|
|
31
|
+
timer = setTimeout(doWrite, debounceMs);
|
|
32
|
+
};
|
|
33
|
+
const flush = async () => {
|
|
34
|
+
if (timer) {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
timer = void 0;
|
|
37
|
+
}
|
|
38
|
+
doWrite();
|
|
39
|
+
await writePromise;
|
|
40
|
+
};
|
|
41
|
+
return { write, flush };
|
|
42
|
+
};
|
|
43
|
+
var DEFAULT_CONFIG = {
|
|
44
|
+
port: 4444,
|
|
45
|
+
upstream: "https://api.openai.com",
|
|
46
|
+
maxRetries: 3,
|
|
47
|
+
provider: "openai"
|
|
48
|
+
};
|
|
49
|
+
var buildProfilePool = (profiles) => profiles.sort((a, b) => a.consecutiveFailures - b.consecutiveFailures);
|
|
50
|
+
var getBearerToken = (profile) => {
|
|
51
|
+
const creds = profile.entry.credentials;
|
|
52
|
+
if (creds.type === "api-key") {
|
|
53
|
+
return creds.key;
|
|
54
|
+
}
|
|
55
|
+
if (creds.type === "oauth") {
|
|
56
|
+
return creds.access;
|
|
57
|
+
}
|
|
58
|
+
return void 0;
|
|
59
|
+
};
|
|
60
|
+
var readBody = (req) => new Promise((resolve, reject) => {
|
|
61
|
+
const chunks = [];
|
|
62
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
63
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
64
|
+
req.on("error", reject);
|
|
65
|
+
});
|
|
66
|
+
var forwardRequest = async (method, path, headers, body, upstream) => {
|
|
67
|
+
const url = `${upstream}${path}`;
|
|
68
|
+
const reqHeaders = { ...headers };
|
|
69
|
+
delete reqHeaders["host"];
|
|
70
|
+
const response = await fetch(url, {
|
|
71
|
+
method,
|
|
72
|
+
headers: reqHeaders,
|
|
73
|
+
body: method !== "GET" && method !== "HEAD" ? body : void 0
|
|
74
|
+
});
|
|
75
|
+
const respHeaders = {};
|
|
76
|
+
response.headers.forEach((value, key) => {
|
|
77
|
+
respHeaders[key] = value;
|
|
78
|
+
});
|
|
79
|
+
if (respHeaders["content-type"]?.includes("text/event-stream") && response.body) {
|
|
80
|
+
return { status: response.status, headers: respHeaders, body: response.body };
|
|
81
|
+
}
|
|
82
|
+
const respBody = Buffer.from(await response.arrayBuffer());
|
|
83
|
+
return { status: response.status, headers: respHeaders, body: respBody };
|
|
84
|
+
};
|
|
85
|
+
var publishState = (stateWriter, profiles, activeId) => {
|
|
86
|
+
const targets = profiles.map((p) => ({
|
|
87
|
+
target_id: p.entry.id,
|
|
88
|
+
provider_id: p.entry.provider,
|
|
89
|
+
profile: p.entry.id,
|
|
90
|
+
state: p.consecutiveFailures > 0 ? "CoolingDown" : "Active",
|
|
91
|
+
health_score: Math.max(0, 1 - p.consecutiveFailures * 0.25),
|
|
92
|
+
latency_ema_ms: 0,
|
|
93
|
+
enabled: true
|
|
94
|
+
}));
|
|
95
|
+
const snapshot = {
|
|
96
|
+
version: 1,
|
|
97
|
+
updated_at: Date.now(),
|
|
98
|
+
active_target_id: activeId,
|
|
99
|
+
targets
|
|
100
|
+
};
|
|
101
|
+
stateWriter.write(snapshot);
|
|
102
|
+
};
|
|
103
|
+
var createProxy = async (userConfig = {}) => {
|
|
104
|
+
const config = { ...DEFAULT_CONFIG, ...userConfig };
|
|
105
|
+
const logger = chunkBHHR2U5B_cjs.createAuditLogger({ level: "info" });
|
|
106
|
+
const stateWriter = createStateWriter(300);
|
|
107
|
+
const store = await chunkBHHR2U5B_cjs.loadProfiles();
|
|
108
|
+
const providerProfiles = Object.values(store).filter(
|
|
109
|
+
(p) => p.provider === config.provider
|
|
110
|
+
);
|
|
111
|
+
if (providerProfiles.length === 0) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`No API key profiles found for provider "${config.provider}". Run o-switcher profile tools to add profiles first.`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const profiles = providerProfiles.map((entry) => ({
|
|
117
|
+
entry,
|
|
118
|
+
failedAt: null,
|
|
119
|
+
consecutiveFailures: 0
|
|
120
|
+
}));
|
|
121
|
+
logger.info(
|
|
122
|
+
{ provider: config.provider, profiles: profiles.map((p) => p.entry.id), port: config.port },
|
|
123
|
+
"O-Switcher proxy initialized"
|
|
124
|
+
);
|
|
125
|
+
publishState(stateWriter, profiles, profiles[0]?.entry.id);
|
|
126
|
+
const handleRequest = async (req, res) => {
|
|
127
|
+
const method = req.method ?? "GET";
|
|
128
|
+
const path = req.url ?? "/";
|
|
129
|
+
if (path === "/health") {
|
|
130
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
131
|
+
res.end(JSON.stringify({ status: "ok", profiles: profiles.length }));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const body = await readBody(req);
|
|
135
|
+
const pool = buildProfilePool(profiles);
|
|
136
|
+
if (pool.length === 0) {
|
|
137
|
+
res.writeHead(503, { "content-type": "application/json" });
|
|
138
|
+
res.end(JSON.stringify({ error: "All profiles exhausted" }));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const maxAttempts = Math.min(config.maxRetries, pool.length);
|
|
142
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
143
|
+
const profile = pool[attempt];
|
|
144
|
+
const token = getBearerToken(profile);
|
|
145
|
+
if (!token) continue;
|
|
146
|
+
const headers = {};
|
|
147
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
148
|
+
if (value && typeof value === "string") {
|
|
149
|
+
headers[key] = value;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
headers["authorization"] = `Bearer ${token}`;
|
|
153
|
+
logger.info(
|
|
154
|
+
{ profile: profile.entry.id, attempt: attempt + 1, path },
|
|
155
|
+
"Forwarding request"
|
|
156
|
+
);
|
|
157
|
+
try {
|
|
158
|
+
const result = await forwardRequest(method, path, headers, body, config.upstream);
|
|
159
|
+
if (result.status === 429) {
|
|
160
|
+
profile.consecutiveFailures += 1;
|
|
161
|
+
profile.failedAt = Date.now();
|
|
162
|
+
logger.warn(
|
|
163
|
+
{ profile: profile.entry.id, attempt: attempt + 1, consecutiveFailures: profile.consecutiveFailures },
|
|
164
|
+
"Rate limited \u2014 trying next profile"
|
|
165
|
+
);
|
|
166
|
+
publishState(stateWriter, profiles, pool[attempt + 1]?.entry.id);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
profile.consecutiveFailures = 0;
|
|
170
|
+
profile.failedAt = null;
|
|
171
|
+
publishState(stateWriter, profiles, profile.entry.id);
|
|
172
|
+
res.writeHead(result.status, result.headers);
|
|
173
|
+
if (result.body instanceof ReadableStream) {
|
|
174
|
+
const reader = result.body.getReader();
|
|
175
|
+
const pump = async () => {
|
|
176
|
+
const { done, value } = await reader.read();
|
|
177
|
+
if (done) {
|
|
178
|
+
res.end();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
res.write(value);
|
|
182
|
+
await pump();
|
|
183
|
+
};
|
|
184
|
+
await pump();
|
|
185
|
+
} else {
|
|
186
|
+
res.end(result.body);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
} catch (err) {
|
|
190
|
+
profile.consecutiveFailures += 1;
|
|
191
|
+
profile.failedAt = Date.now();
|
|
192
|
+
logger.error(
|
|
193
|
+
{ profile: profile.entry.id, attempt: attempt + 1, err },
|
|
194
|
+
"Request failed \u2014 trying next profile"
|
|
195
|
+
);
|
|
196
|
+
publishState(stateWriter, profiles, pool[attempt + 1]?.entry.id);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
res.writeHead(429, { "content-type": "application/json" });
|
|
201
|
+
res.end(JSON.stringify({
|
|
202
|
+
error: {
|
|
203
|
+
message: `All ${maxAttempts} profiles rate-limited. Try again later.`,
|
|
204
|
+
type: "rate_limit_error",
|
|
205
|
+
code: "all_profiles_exhausted"
|
|
206
|
+
}
|
|
207
|
+
}));
|
|
208
|
+
};
|
|
209
|
+
const start = () => new Promise((resolve) => {
|
|
210
|
+
const server = http.createServer((req, res) => {
|
|
211
|
+
handleRequest(req, res).catch((err) => {
|
|
212
|
+
logger.error({ err }, "Unhandled request error");
|
|
213
|
+
if (!res.headersSent) {
|
|
214
|
+
res.writeHead(500, { "content-type": "application/json" });
|
|
215
|
+
}
|
|
216
|
+
res.end(JSON.stringify({ error: "Internal proxy error" }));
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
server.listen(config.port, () => {
|
|
220
|
+
logger.info({ port: config.port, upstream: config.upstream }, "O-Switcher proxy listening");
|
|
221
|
+
resolve({
|
|
222
|
+
port: config.port,
|
|
223
|
+
close: () => {
|
|
224
|
+
server.close();
|
|
225
|
+
stateWriter.flush();
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
return { start };
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
exports.createProxy = createProxy;
|
|
234
|
+
exports.createStateWriter = createStateWriter;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkBHHR2U5B_cjs = require('./chunk-BHHR2U5B.cjs');
|
|
3
4
|
var zod = require('zod');
|
|
4
|
-
var pino = require('pino');
|
|
5
|
-
var crypto = require('crypto');
|
|
6
5
|
var eventemitter3 = require('eventemitter3');
|
|
7
6
|
var cockatiel = require('cockatiel');
|
|
8
7
|
var PQueue = require('p-queue');
|
|
@@ -13,8 +12,6 @@ var path = require('path');
|
|
|
13
12
|
|
|
14
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
14
|
|
|
16
|
-
var pino__default = /*#__PURE__*/_interopDefault(pino);
|
|
17
|
-
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
18
15
|
var PQueue__default = /*#__PURE__*/_interopDefault(PQueue);
|
|
19
16
|
|
|
20
17
|
// src/config/defaults.ts
|
|
@@ -313,37 +310,6 @@ var TARGET_STATES = [
|
|
|
313
310
|
"Draining",
|
|
314
311
|
"Disabled"
|
|
315
312
|
];
|
|
316
|
-
var REDACT_PATHS = [
|
|
317
|
-
"api_key",
|
|
318
|
-
"token",
|
|
319
|
-
"secret",
|
|
320
|
-
"password",
|
|
321
|
-
"authorization",
|
|
322
|
-
"credential",
|
|
323
|
-
"credentials",
|
|
324
|
-
"*.api_key",
|
|
325
|
-
"*.token",
|
|
326
|
-
"*.secret",
|
|
327
|
-
"*.password",
|
|
328
|
-
"*.authorization",
|
|
329
|
-
"*.credential",
|
|
330
|
-
"*.credentials"
|
|
331
|
-
];
|
|
332
|
-
var createAuditLogger = (options) => {
|
|
333
|
-
const opts = {
|
|
334
|
-
level: options?.level ?? "info",
|
|
335
|
-
redact: {
|
|
336
|
-
paths: [...REDACT_PATHS],
|
|
337
|
-
censor: "[Redacted]"
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
if (options?.destination) {
|
|
341
|
-
return pino__default.default(opts, options.destination);
|
|
342
|
-
}
|
|
343
|
-
return pino__default.default(opts);
|
|
344
|
-
};
|
|
345
|
-
var createRequestLogger = (baseLogger, requestId) => baseLogger.child({ request_id: requestId });
|
|
346
|
-
var generateCorrelationId = () => crypto__default.default.randomUUID();
|
|
347
313
|
var RateLimitedSchema = zod.z.object({
|
|
348
314
|
class: zod.z.literal("RateLimited"),
|
|
349
315
|
retryable: zod.z.literal(true),
|
|
@@ -1435,72 +1401,6 @@ var createOperatorTools = (deps) => ({
|
|
|
1435
1401
|
}
|
|
1436
1402
|
})
|
|
1437
1403
|
});
|
|
1438
|
-
var PROFILES_DIR = path.join(os.homedir(), ".local", "share", "o-switcher");
|
|
1439
|
-
var PROFILES_PATH = path.join(PROFILES_DIR, "profiles.json");
|
|
1440
|
-
var loadProfiles = async (path = PROFILES_PATH) => {
|
|
1441
|
-
try {
|
|
1442
|
-
const content = await promises.readFile(path, "utf-8");
|
|
1443
|
-
return JSON.parse(content);
|
|
1444
|
-
} catch (err) {
|
|
1445
|
-
const code = err.code;
|
|
1446
|
-
if (code === "ENOENT") {
|
|
1447
|
-
return {};
|
|
1448
|
-
}
|
|
1449
|
-
throw err;
|
|
1450
|
-
}
|
|
1451
|
-
};
|
|
1452
|
-
var saveProfiles = async (store, path$1 = PROFILES_PATH, logger) => {
|
|
1453
|
-
const dir = path.dirname(path$1);
|
|
1454
|
-
await promises.mkdir(dir, { recursive: true });
|
|
1455
|
-
const tmpPath = `${path$1}.tmp`;
|
|
1456
|
-
await promises.writeFile(tmpPath, JSON.stringify(store, null, 2), "utf-8");
|
|
1457
|
-
await promises.rename(tmpPath, path$1);
|
|
1458
|
-
logger?.info({ path: path$1 }, "Profiles saved to disk");
|
|
1459
|
-
};
|
|
1460
|
-
var credentialsMatch = (a, b) => {
|
|
1461
|
-
if (a.type !== b.type) return false;
|
|
1462
|
-
if (a.type === "api-key" && b.type === "api-key") {
|
|
1463
|
-
return a.key === b.key;
|
|
1464
|
-
}
|
|
1465
|
-
if (a.type === "oauth" && b.type === "oauth") {
|
|
1466
|
-
return a.refresh === b.refresh && a.access === b.access && a.expires === b.expires && a.accountId === b.accountId;
|
|
1467
|
-
}
|
|
1468
|
-
return false;
|
|
1469
|
-
};
|
|
1470
|
-
var addProfile = (store, provider, credentials) => {
|
|
1471
|
-
const isDuplicate = Object.values(store).some(
|
|
1472
|
-
(entry2) => entry2.provider === provider && credentialsMatch(entry2.credentials, credentials)
|
|
1473
|
-
);
|
|
1474
|
-
if (isDuplicate) {
|
|
1475
|
-
return store;
|
|
1476
|
-
}
|
|
1477
|
-
const id = nextProfileId(store, provider);
|
|
1478
|
-
const entry = {
|
|
1479
|
-
id,
|
|
1480
|
-
provider,
|
|
1481
|
-
type: credentials.type,
|
|
1482
|
-
credentials,
|
|
1483
|
-
created: (/* @__PURE__ */ new Date()).toISOString()
|
|
1484
|
-
};
|
|
1485
|
-
return { ...store, [id]: entry };
|
|
1486
|
-
};
|
|
1487
|
-
var removeProfile = (store, id) => {
|
|
1488
|
-
if (store[id] === void 0) {
|
|
1489
|
-
return { store, removed: false };
|
|
1490
|
-
}
|
|
1491
|
-
const { [id]: _removed, ...rest } = store;
|
|
1492
|
-
return { store: rest, removed: true };
|
|
1493
|
-
};
|
|
1494
|
-
var listProfiles = (store) => {
|
|
1495
|
-
return Object.values(store).sort(
|
|
1496
|
-
(a, b) => new Date(a.created).getTime() - new Date(b.created).getTime()
|
|
1497
|
-
);
|
|
1498
|
-
};
|
|
1499
|
-
var nextProfileId = (store, provider) => {
|
|
1500
|
-
const prefix = `${provider}-`;
|
|
1501
|
-
const maxN = Object.keys(store).filter((key) => key.startsWith(prefix)).map((key) => Number(key.slice(prefix.length))).filter((n) => !Number.isNaN(n)).reduce((max, n) => Math.max(max, n), 0);
|
|
1502
|
-
return `${provider}-${maxN + 1}`;
|
|
1503
|
-
};
|
|
1504
1404
|
var AUTH_JSON_PATH = path.join(os.homedir(), ".local", "share", "opencode", "auth.json");
|
|
1505
1405
|
var AUTH_DIR = path.join(os.homedir(), ".local", "share", "opencode");
|
|
1506
1406
|
var isAuthFile = (filename) => filename === "auth.json" || /^auth-work\d+\.json$/.test(filename);
|
|
@@ -1551,14 +1451,14 @@ var entriesEqual = (a, b) => {
|
|
|
1551
1451
|
};
|
|
1552
1452
|
var createAuthWatcher = (options) => {
|
|
1553
1453
|
const authDir = options?.authJsonPath ? path.dirname(options.authJsonPath) : AUTH_DIR;
|
|
1554
|
-
const profPath = options?.profilesPath ?? PROFILES_PATH;
|
|
1454
|
+
const profPath = options?.profilesPath ?? chunkBHHR2U5B_cjs.PROFILES_PATH;
|
|
1555
1455
|
const log = options?.logger?.child({ component: "profile-watcher" });
|
|
1556
1456
|
let lastKnownAuth = {};
|
|
1557
1457
|
let abortController = null;
|
|
1558
1458
|
let debounceTimer = null;
|
|
1559
1459
|
const processChange = async () => {
|
|
1560
1460
|
const newAuth = await readAllAuthFiles(authDir);
|
|
1561
|
-
let store = await loadProfiles(profPath);
|
|
1461
|
+
let store = await chunkBHHR2U5B_cjs.loadProfiles(profPath);
|
|
1562
1462
|
let changed = false;
|
|
1563
1463
|
for (const [compositeKey, entry] of Object.entries(newAuth)) {
|
|
1564
1464
|
if (!entry) continue;
|
|
@@ -1570,7 +1470,7 @@ var createAuthWatcher = (options) => {
|
|
|
1570
1470
|
"Credential change detected \u2014 saving previous credential"
|
|
1571
1471
|
);
|
|
1572
1472
|
const prevCredential = toCredential(previousEntry);
|
|
1573
|
-
const newStore = addProfile(store, provider, prevCredential);
|
|
1473
|
+
const newStore = chunkBHHR2U5B_cjs.addProfile(store, provider, prevCredential);
|
|
1574
1474
|
if (newStore !== store) {
|
|
1575
1475
|
store = newStore;
|
|
1576
1476
|
changed = true;
|
|
@@ -1578,7 +1478,7 @@ var createAuthWatcher = (options) => {
|
|
|
1578
1478
|
} else if (previousEntry === void 0) {
|
|
1579
1479
|
log?.info({ provider, source: compositeKey, action: "new_provider" }, "New auth file detected");
|
|
1580
1480
|
const credential = toCredential(entry);
|
|
1581
|
-
const newStore = addProfile(store, provider, credential);
|
|
1481
|
+
const newStore = chunkBHHR2U5B_cjs.addProfile(store, provider, credential);
|
|
1582
1482
|
if (newStore !== store) {
|
|
1583
1483
|
store = newStore;
|
|
1584
1484
|
changed = true;
|
|
@@ -1586,7 +1486,7 @@ var createAuthWatcher = (options) => {
|
|
|
1586
1486
|
}
|
|
1587
1487
|
}
|
|
1588
1488
|
if (changed) {
|
|
1589
|
-
await saveProfiles(store, profPath);
|
|
1489
|
+
await chunkBHHR2U5B_cjs.saveProfiles(store, profPath);
|
|
1590
1490
|
log?.info({ profiles_saved: true }, "Profiles saved to disk");
|
|
1591
1491
|
}
|
|
1592
1492
|
lastKnownAuth = newAuth;
|
|
@@ -1604,7 +1504,7 @@ var createAuthWatcher = (options) => {
|
|
|
1604
1504
|
};
|
|
1605
1505
|
const start = async () => {
|
|
1606
1506
|
const currentAuth = await readAllAuthFiles(authDir);
|
|
1607
|
-
const currentStore = await loadProfiles(profPath);
|
|
1507
|
+
const currentStore = await chunkBHHR2U5B_cjs.loadProfiles(profPath);
|
|
1608
1508
|
log?.info({ auth_keys: Object.keys(currentAuth).length }, "Auth watcher started");
|
|
1609
1509
|
if (Object.keys(currentStore).length === 0 && Object.keys(currentAuth).length > 0) {
|
|
1610
1510
|
let store = {};
|
|
@@ -1612,9 +1512,9 @@ var createAuthWatcher = (options) => {
|
|
|
1612
1512
|
if (!entry) continue;
|
|
1613
1513
|
const provider = compositeKey.split(":")[0] ?? compositeKey;
|
|
1614
1514
|
const credential = toCredential(entry);
|
|
1615
|
-
store = addProfile(store, provider, credential);
|
|
1515
|
+
store = chunkBHHR2U5B_cjs.addProfile(store, provider, credential);
|
|
1616
1516
|
}
|
|
1617
|
-
await saveProfiles(store, profPath);
|
|
1517
|
+
await chunkBHHR2U5B_cjs.saveProfiles(store, profPath);
|
|
1618
1518
|
log?.info(
|
|
1619
1519
|
{ profiles_initialized: Object.keys(store).length },
|
|
1620
1520
|
"Initialized profiles from auth files"
|
|
@@ -1674,10 +1574,10 @@ var readCurrentAuth = async (authPath) => {
|
|
|
1674
1574
|
}
|
|
1675
1575
|
};
|
|
1676
1576
|
var switchProfile = async (options) => {
|
|
1677
|
-
const profPath = options.profilesPath ?? PROFILES_PATH;
|
|
1577
|
+
const profPath = options.profilesPath ?? chunkBHHR2U5B_cjs.PROFILES_PATH;
|
|
1678
1578
|
const authPath = options.authJsonPath ?? AUTH_JSON_PATH;
|
|
1679
1579
|
const log = options.logger?.child({ component: "profile-switcher" });
|
|
1680
|
-
const store = await loadProfiles(profPath);
|
|
1580
|
+
const store = await chunkBHHR2U5B_cjs.loadProfiles(profPath);
|
|
1681
1581
|
const target = store[options.targetProfileId];
|
|
1682
1582
|
if (target === void 0) {
|
|
1683
1583
|
log?.warn({ profileId: options.targetProfileId }, "Profile not found");
|
|
@@ -1708,9 +1608,9 @@ var switchProfile = async (options) => {
|
|
|
1708
1608
|
};
|
|
1709
1609
|
};
|
|
1710
1610
|
var switchToNextProfile = async (options) => {
|
|
1711
|
-
const profPath = options.profilesPath ?? PROFILES_PATH;
|
|
1611
|
+
const profPath = options.profilesPath ?? chunkBHHR2U5B_cjs.PROFILES_PATH;
|
|
1712
1612
|
const log = options.logger?.child({ component: "profile-switcher" });
|
|
1713
|
-
const store = await loadProfiles(profPath);
|
|
1613
|
+
const store = await chunkBHHR2U5B_cjs.loadProfiles(profPath);
|
|
1714
1614
|
const excludeSet = new Set(options.excludeProfileIds ?? []);
|
|
1715
1615
|
if (options.currentProfileId) {
|
|
1716
1616
|
excludeSet.add(options.currentProfileId);
|
|
@@ -1738,8 +1638,8 @@ var createProfileTools = (options) => ({
|
|
|
1738
1638
|
description: "List all saved auth profiles with provider, type, and creation date.",
|
|
1739
1639
|
args: {},
|
|
1740
1640
|
async execute() {
|
|
1741
|
-
const store = await loadProfiles(options?.profilesPath);
|
|
1742
|
-
const profiles = listProfiles(store);
|
|
1641
|
+
const store = await chunkBHHR2U5B_cjs.loadProfiles(options?.profilesPath);
|
|
1642
|
+
const profiles = chunkBHHR2U5B_cjs.listProfiles(store);
|
|
1743
1643
|
const result = profiles.map((entry) => ({
|
|
1744
1644
|
id: entry.id,
|
|
1745
1645
|
provider: entry.provider,
|
|
@@ -1753,10 +1653,10 @@ var createProfileTools = (options) => ({
|
|
|
1753
1653
|
description: "Remove a saved auth profile by ID.",
|
|
1754
1654
|
args: { id: z4.string().min(1) },
|
|
1755
1655
|
async execute(args) {
|
|
1756
|
-
const store = await loadProfiles(options?.profilesPath);
|
|
1757
|
-
const { store: newStore, removed } = removeProfile(store, args.id);
|
|
1656
|
+
const store = await chunkBHHR2U5B_cjs.loadProfiles(options?.profilesPath);
|
|
1657
|
+
const { store: newStore, removed } = chunkBHHR2U5B_cjs.removeProfile(store, args.id);
|
|
1758
1658
|
if (removed) {
|
|
1759
|
-
await saveProfiles(newStore, options?.profilesPath);
|
|
1659
|
+
await chunkBHHR2U5B_cjs.saveProfiles(newStore, options?.profilesPath);
|
|
1760
1660
|
return JSON.stringify({ success: true, id: args.id });
|
|
1761
1661
|
}
|
|
1762
1662
|
return JSON.stringify({
|
|
@@ -1785,12 +1685,10 @@ exports.DualBreaker = DualBreaker;
|
|
|
1785
1685
|
exports.EXCLUSION_REASONS = EXCLUSION_REASONS;
|
|
1786
1686
|
exports.ErrorClassSchema = ErrorClassSchema;
|
|
1787
1687
|
exports.INITIAL_HEALTH_SCORE = INITIAL_HEALTH_SCORE;
|
|
1788
|
-
exports.REDACT_PATHS = REDACT_PATHS;
|
|
1789
1688
|
exports.SwitcherConfigSchema = SwitcherConfigSchema;
|
|
1790
1689
|
exports.TARGET_STATES = TARGET_STATES;
|
|
1791
1690
|
exports.TargetConfigSchema = TargetConfigSchema;
|
|
1792
1691
|
exports.TargetRegistry = TargetRegistry;
|
|
1793
|
-
exports.addProfile = addProfile;
|
|
1794
1692
|
exports.applyConfigDiff = applyConfigDiff;
|
|
1795
1693
|
exports.checkHardRejects = checkHardRejects;
|
|
1796
1694
|
exports.computeBackoffMs = computeBackoffMs;
|
|
@@ -1798,7 +1696,6 @@ exports.computeConfigDiff = computeConfigDiff;
|
|
|
1798
1696
|
exports.computeCooldownMs = computeCooldownMs;
|
|
1799
1697
|
exports.computeScore = computeScore;
|
|
1800
1698
|
exports.createAdmissionController = createAdmissionController;
|
|
1801
|
-
exports.createAuditLogger = createAuditLogger;
|
|
1802
1699
|
exports.createAuthWatcher = createAuthWatcher;
|
|
1803
1700
|
exports.createCircuitBreaker = createCircuitBreaker;
|
|
1804
1701
|
exports.createConcurrencyTracker = createConcurrencyTracker;
|
|
@@ -1808,7 +1705,6 @@ exports.createLogSubscriber = createLogSubscriber;
|
|
|
1808
1705
|
exports.createOperatorTools = createOperatorTools;
|
|
1809
1706
|
exports.createProfileTools = createProfileTools;
|
|
1810
1707
|
exports.createRegistry = createRegistry;
|
|
1811
|
-
exports.createRequestLogger = createRequestLogger;
|
|
1812
1708
|
exports.createRequestTraceBuffer = createRequestTraceBuffer;
|
|
1813
1709
|
exports.createRetryPolicy = createRetryPolicy;
|
|
1814
1710
|
exports.createRoutingEventBus = createRoutingEventBus;
|
|
@@ -1816,21 +1712,15 @@ exports.disableTarget = disableTarget;
|
|
|
1816
1712
|
exports.discoverTargets = discoverTargets;
|
|
1817
1713
|
exports.discoverTargetsFromProfiles = discoverTargetsFromProfiles;
|
|
1818
1714
|
exports.drainTarget = drainTarget;
|
|
1819
|
-
exports.generateCorrelationId = generateCorrelationId;
|
|
1820
1715
|
exports.getExclusionReason = getExclusionReason;
|
|
1821
1716
|
exports.getTargetStateTransition = getTargetStateTransition;
|
|
1822
1717
|
exports.inspectRequest = inspectRequest;
|
|
1823
1718
|
exports.isRetryable = isRetryable;
|
|
1824
|
-
exports.listProfiles = listProfiles;
|
|
1825
1719
|
exports.listTargets = listTargets;
|
|
1826
|
-
exports.loadProfiles = loadProfiles;
|
|
1827
|
-
exports.nextProfileId = nextProfileId;
|
|
1828
1720
|
exports.normalizeLatency = normalizeLatency;
|
|
1829
1721
|
exports.pauseTarget = pauseTarget;
|
|
1830
1722
|
exports.reloadConfig = reloadConfig;
|
|
1831
|
-
exports.removeProfile = removeProfile;
|
|
1832
1723
|
exports.resumeTarget = resumeTarget;
|
|
1833
|
-
exports.saveProfiles = saveProfiles;
|
|
1834
1724
|
exports.selectTarget = selectTarget;
|
|
1835
1725
|
exports.switchProfile = switchProfile;
|
|
1836
1726
|
exports.switchToNextProfile = switchToNextProfile;
|