@albinocrabs/o-switcher 0.1.0 → 0.1.1

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.
@@ -1,3 +1,14 @@
1
+ import { z } from 'zod';
2
+ import pino from 'pino';
3
+ import crypto from 'crypto';
4
+ import { EventEmitter } from 'eventemitter3';
5
+ import { CircuitState, ConsecutiveBreaker, CountBreaker, BrokenCircuitError, IsolatedCircuitError, circuitBreaker, handleAll } from 'cockatiel';
6
+ import PQueue from 'p-queue';
7
+ import { readFile, mkdir, writeFile, rename, watch } from 'fs/promises';
8
+ import { homedir } from 'os';
9
+ import { join, dirname } from 'path';
10
+ import { tool } from '@opencode-ai/plugin/tool';
11
+
1
12
  // src/config/defaults.ts
2
13
  var DEFAULT_RETRY_BUDGET = 3;
3
14
  var DEFAULT_FAILOVER_BUDGET = 2;
@@ -21,9 +32,6 @@ var DEFAULT_CB_HALF_OPEN_MAX_PROBES = 1;
21
32
  var DEFAULT_CB_SUCCESS_THRESHOLD = 2;
22
33
  var DEFAULT_RETRY = 3;
23
34
  var DEFAULT_TIMEOUT_MS = 3e4;
24
-
25
- // src/config/schema.ts
26
- import { z } from "zod";
27
35
  var BackoffConfigSchema = z.object({
28
36
  base_ms: z.number().positive().default(DEFAULT_BACKOFF_BASE_MS),
29
37
  multiplier: z.number().positive().default(DEFAULT_BACKOFF_MULTIPLIER),
@@ -133,13 +141,11 @@ var validateConfig = (raw) => {
133
141
  }
134
142
  return Object.freeze(data);
135
143
  }
136
- const diagnostics = result.error.issues.map(
137
- (issue) => ({
138
- path: issue.path.join("."),
139
- message: issue.message,
140
- received: "expected" in issue ? issue.expected : void 0
141
- })
142
- );
144
+ const diagnostics = result.error.issues.map((issue) => ({
145
+ path: issue.path.join("."),
146
+ message: issue.message,
147
+ received: "expected" in issue ? issue.expected : void 0
148
+ }));
143
149
  throw new ConfigValidationError(diagnostics);
144
150
  };
145
151
 
@@ -240,10 +246,7 @@ var TargetRegistry = class {
240
246
  if (!target) {
241
247
  return;
242
248
  }
243
- const newHealthScore = updateHealthScore(
244
- target.health_score,
245
- observation
246
- );
249
+ const newHealthScore = updateHealthScore(target.health_score, observation);
247
250
  this.targets.set(id, { ...target, health_score: newHealthScore });
248
251
  }
249
252
  /** Sets the cooldown_until timestamp for a target. */
@@ -302,10 +305,6 @@ var TARGET_STATES = [
302
305
  "Draining",
303
306
  "Disabled"
304
307
  ];
305
-
306
- // src/audit/logger.ts
307
- import pino from "pino";
308
- import crypto from "crypto";
309
308
  var REDACT_PATHS = [
310
309
  "api_key",
311
310
  "token",
@@ -337,57 +336,54 @@ var createAuditLogger = (options) => {
337
336
  };
338
337
  var createRequestLogger = (baseLogger, requestId) => baseLogger.child({ request_id: requestId });
339
338
  var generateCorrelationId = () => crypto.randomUUID();
340
-
341
- // src/errors/taxonomy.ts
342
- import { z as z2 } from "zod";
343
- var RateLimitedSchema = z2.object({
344
- class: z2.literal("RateLimited"),
345
- retryable: z2.literal(true),
346
- retry_after_ms: z2.number().optional(),
347
- provider_reason: z2.string().optional()
339
+ var RateLimitedSchema = z.object({
340
+ class: z.literal("RateLimited"),
341
+ retryable: z.literal(true),
342
+ retry_after_ms: z.number().optional(),
343
+ provider_reason: z.string().optional()
348
344
  });
349
- var QuotaExhaustedSchema = z2.object({
350
- class: z2.literal("QuotaExhausted"),
351
- retryable: z2.literal(false),
352
- provider_reason: z2.string().optional()
345
+ var QuotaExhaustedSchema = z.object({
346
+ class: z.literal("QuotaExhausted"),
347
+ retryable: z.literal(false),
348
+ provider_reason: z.string().optional()
353
349
  });
354
- var AuthFailureSchema = z2.object({
355
- class: z2.literal("AuthFailure"),
356
- retryable: z2.literal(false),
357
- recovery_attempted: z2.boolean().default(false)
350
+ var AuthFailureSchema = z.object({
351
+ class: z.literal("AuthFailure"),
352
+ retryable: z.literal(false),
353
+ recovery_attempted: z.boolean().default(false)
358
354
  });
359
- var PermissionFailureSchema = z2.object({
360
- class: z2.literal("PermissionFailure"),
361
- retryable: z2.literal(false)
355
+ var PermissionFailureSchema = z.object({
356
+ class: z.literal("PermissionFailure"),
357
+ retryable: z.literal(false)
362
358
  });
363
- var PolicyFailureSchema = z2.object({
364
- class: z2.literal("PolicyFailure"),
365
- retryable: z2.literal(false)
359
+ var PolicyFailureSchema = z.object({
360
+ class: z.literal("PolicyFailure"),
361
+ retryable: z.literal(false)
366
362
  });
367
- var RegionRestrictionSchema = z2.object({
368
- class: z2.literal("RegionRestriction"),
369
- retryable: z2.literal(false)
363
+ var RegionRestrictionSchema = z.object({
364
+ class: z.literal("RegionRestriction"),
365
+ retryable: z.literal(false)
370
366
  });
371
- var ModelUnavailableSchema = z2.object({
372
- class: z2.literal("ModelUnavailable"),
373
- retryable: z2.literal(false),
374
- failover_eligible: z2.literal(true)
367
+ var ModelUnavailableSchema = z.object({
368
+ class: z.literal("ModelUnavailable"),
369
+ retryable: z.literal(false),
370
+ failover_eligible: z.literal(true)
375
371
  });
376
- var TransientServerFailureSchema = z2.object({
377
- class: z2.literal("TransientServerFailure"),
378
- retryable: z2.literal(true),
379
- http_status: z2.number().optional()
372
+ var TransientServerFailureSchema = z.object({
373
+ class: z.literal("TransientServerFailure"),
374
+ retryable: z.literal(true),
375
+ http_status: z.number().optional()
380
376
  });
381
- var TransportFailureSchema = z2.object({
382
- class: z2.literal("TransportFailure"),
383
- retryable: z2.literal(true)
377
+ var TransportFailureSchema = z.object({
378
+ class: z.literal("TransportFailure"),
379
+ retryable: z.literal(true)
384
380
  });
385
- var InterruptedExecutionSchema = z2.object({
386
- class: z2.literal("InterruptedExecution"),
387
- retryable: z2.literal(true),
388
- partial_output_bytes: z2.number().optional()
381
+ var InterruptedExecutionSchema = z.object({
382
+ class: z.literal("InterruptedExecution"),
383
+ retryable: z.literal(true),
384
+ partial_output_bytes: z.number().optional()
389
385
  });
390
- var ErrorClassSchema = z2.discriminatedUnion("class", [
386
+ var ErrorClassSchema = z.discriminatedUnion("class", [
391
387
  RateLimitedSchema,
392
388
  QuotaExhaustedSchema,
393
389
  AuthFailureSchema,
@@ -433,10 +429,7 @@ var DEFAULT_BACKOFF_PARAMS = {
433
429
  jitter: "full"
434
430
  };
435
431
  var computeBackoffMs = (attempt, params, retryAfterMs) => {
436
- const rawDelay = Math.min(
437
- params.base_ms * Math.pow(params.multiplier, attempt),
438
- params.max_ms
439
- );
432
+ const rawDelay = Math.min(params.base_ms * Math.pow(params.multiplier, attempt), params.max_ms);
440
433
  const jitteredDelay = params.jitter === "full" ? Math.random() * rawDelay : params.jitter === "equal" ? rawDelay / 2 + Math.random() * (rawDelay / 2) : rawDelay;
441
434
  return Math.max(jitteredDelay, retryAfterMs ?? 0);
442
435
  };
@@ -480,22 +473,8 @@ var EXCLUSION_REASONS = [
480
473
  "capability_mismatch",
481
474
  "draining"
482
475
  ];
483
- var ADMISSION_RESULTS = [
484
- "admitted",
485
- "queued",
486
- "degraded",
487
- "rejected"
488
- ];
489
-
490
- // src/routing/events.ts
491
- import { EventEmitter } from "eventemitter3";
476
+ var ADMISSION_RESULTS = ["admitted", "queued", "degraded", "rejected"];
492
477
  var createRoutingEventBus = () => new EventEmitter();
493
-
494
- // src/routing/dual-breaker.ts
495
- import {
496
- ConsecutiveBreaker,
497
- CountBreaker
498
- } from "cockatiel";
499
478
  var DualBreaker = class {
500
479
  consecutive;
501
480
  count;
@@ -537,21 +516,11 @@ var DualBreaker = class {
537
516
  return consecutiveTripped || countTripped;
538
517
  }
539
518
  };
540
-
541
- // src/routing/circuit-breaker.ts
542
- import {
543
- CircuitState as CircuitState2,
544
- handleAll,
545
- circuitBreaker,
546
- BrokenCircuitError,
547
- IsolatedCircuitError
548
- } from "cockatiel";
549
- import "eventemitter3";
550
519
  var COCKATIEL_TO_TARGET = /* @__PURE__ */ new Map([
551
- [CircuitState2.Closed, "Active"],
552
- [CircuitState2.Open, "CircuitOpen"],
553
- [CircuitState2.HalfOpen, "CircuitHalfOpen"],
554
- [CircuitState2.Isolated, "Disabled"]
520
+ [CircuitState.Closed, "Active"],
521
+ [CircuitState.Open, "CircuitOpen"],
522
+ [CircuitState.HalfOpen, "CircuitHalfOpen"],
523
+ [CircuitState.Isolated, "Disabled"]
555
524
  ]);
556
525
  var toTargetState = (state) => COCKATIEL_TO_TARGET.get(state) ?? "Disabled";
557
526
  var createCircuitBreaker = (targetId, config, eventBus) => {
@@ -567,11 +536,11 @@ var createCircuitBreaker = (targetId, config, eventBus) => {
567
536
  return { policy, breaker };
568
537
  };
569
538
  let current = createPolicy();
570
- let previousState = CircuitState2.Closed;
539
+ let previousState = CircuitState.Closed;
571
540
  let openedAtMs = 0;
572
541
  const subscribeEvents = (policy) => {
573
542
  policy.onStateChange((newState) => {
574
- if (newState === CircuitState2.Open) {
543
+ if (newState === CircuitState.Open) {
575
544
  openedAtMs = Date.now();
576
545
  }
577
546
  const from = toTargetState(previousState);
@@ -590,8 +559,8 @@ var createCircuitBreaker = (targetId, config, eventBus) => {
590
559
  subscribeEvents(current.policy);
591
560
  const effectiveState = () => {
592
561
  const raw = current.policy.state;
593
- if (raw === CircuitState2.Open && openedAtMs > 0 && Date.now() - openedAtMs >= config.half_open_after_ms) {
594
- return CircuitState2.HalfOpen;
562
+ if (raw === CircuitState.Open && openedAtMs > 0 && Date.now() - openedAtMs >= config.half_open_after_ms) {
563
+ return CircuitState.HalfOpen;
595
564
  }
596
565
  return raw;
597
566
  };
@@ -618,11 +587,11 @@ var createCircuitBreaker = (targetId, config, eventBus) => {
618
587
  }
619
588
  },
620
589
  allowRequest() {
621
- return effectiveState() !== CircuitState2.Open;
590
+ return effectiveState() !== CircuitState.Open;
622
591
  },
623
592
  reset() {
624
593
  current = createPolicy();
625
- previousState = CircuitState2.Closed;
594
+ previousState = CircuitState.Closed;
626
595
  openedAtMs = 0;
627
596
  subscribeEvents(current.policy);
628
597
  }
@@ -824,9 +793,6 @@ var createCooldownManager = (registry, eventBus) => ({
824
793
  return target.cooldown_until !== null && target.cooldown_until > nowMs;
825
794
  }
826
795
  });
827
-
828
- // src/routing/admission.ts
829
- import PQueue from "p-queue";
830
796
  var checkHardRejects = (ctx) => {
831
797
  if (!ctx.hasEligibleTargets) {
832
798
  return { result: "rejected", reason: "no eligible targets available" };
@@ -997,7 +963,11 @@ var createFailoverOrchestrator = (deps) => ({
997
963
  let totalFailovers = 0;
998
964
  let lastErrorClass;
999
965
  log?.info(
1000
- { event: "failover_start", retry_budget: deps.retryBudget, failover_budget: deps.failoverBudget },
966
+ {
967
+ event: "failover_start",
968
+ retry_budget: deps.retryBudget,
969
+ failover_budget: deps.failoverBudget
970
+ },
1001
971
  "Failover loop started"
1002
972
  );
1003
973
  for (let failoverNo = 0; failoverNo <= deps.failoverBudget; failoverNo++) {
@@ -1028,10 +998,7 @@ var createFailoverOrchestrator = (deps) => ({
1028
998
  };
1029
999
  }
1030
1000
  const targetId = selection.selected.target_id;
1031
- const retryPolicy = createRetryPolicy(
1032
- deps.retryBudget,
1033
- deps.backoffParams
1034
- );
1001
+ const retryPolicy = createRetryPolicy(deps.retryBudget, deps.backoffParams);
1035
1002
  for (let retry = 0; retry <= deps.retryBudget; retry++) {
1036
1003
  const attemptNo = retry + 1;
1037
1004
  const acquired = deps.concurrency.acquire(targetId);
@@ -1057,7 +1024,13 @@ var createFailoverOrchestrator = (deps) => ({
1057
1024
  deps.registry.recordObservation(targetId, 1);
1058
1025
  deps.registry.updateLatency(targetId, attemptResult.latency_ms);
1059
1026
  log?.info(
1060
- { event: "attempt_success", target_id: targetId, attempt_no: attemptNo, failover_no: failoverNo, latency_ms: attemptResult.latency_ms },
1027
+ {
1028
+ event: "attempt_success",
1029
+ target_id: targetId,
1030
+ attempt_no: attemptNo,
1031
+ failover_no: failoverNo,
1032
+ latency_ms: attemptResult.latency_ms
1033
+ },
1061
1034
  "Attempt succeeded"
1062
1035
  );
1063
1036
  attempts.push({
@@ -1095,15 +1068,16 @@ var createFailoverOrchestrator = (deps) => ({
1095
1068
  deps.backoffParams,
1096
1069
  deps.backoffParams.max_ms
1097
1070
  );
1098
- deps.cooldownManager.setCooldown(
1099
- targetId,
1100
- cooldownMs,
1101
- errorClass.class
1102
- );
1071
+ deps.cooldownManager.setCooldown(targetId, cooldownMs, errorClass.class);
1103
1072
  }
1104
1073
  if (errorClass.class === "ModelUnavailable") {
1105
1074
  log?.info(
1106
- { event: "early_failover", target_id: targetId, error_class: errorClass.class, failover_no: failoverNo },
1075
+ {
1076
+ event: "early_failover",
1077
+ target_id: targetId,
1078
+ error_class: errorClass.class,
1079
+ failover_no: failoverNo
1080
+ },
1107
1081
  "Early failover \u2014 ModelUnavailable"
1108
1082
  );
1109
1083
  attempts.push({
@@ -1181,17 +1155,25 @@ var createFailoverOrchestrator = (deps) => ({
1181
1155
  totalRetries++;
1182
1156
  if (decision.action === "retry") {
1183
1157
  log?.info(
1184
- { event: "retry", target_id: targetId, attempt_no: attemptNo, error_class: errorClass.class, delay_ms: decision.delay_ms },
1158
+ {
1159
+ event: "retry",
1160
+ target_id: targetId,
1161
+ attempt_no: attemptNo,
1162
+ error_class: errorClass.class,
1163
+ delay_ms: decision.delay_ms
1164
+ },
1185
1165
  "Retrying after delay"
1186
1166
  );
1187
- await new Promise(
1188
- (resolve) => setTimeout(resolve, decision.delay_ms)
1189
- );
1167
+ await new Promise((resolve) => setTimeout(resolve, decision.delay_ms));
1190
1168
  }
1191
1169
  }
1192
1170
  }
1193
1171
  log?.warn(
1194
- { event: "failover_budget_exhausted", total_retries: totalRetries, total_failovers: totalFailovers },
1172
+ {
1173
+ event: "failover_budget_exhausted",
1174
+ total_retries: totalRetries,
1175
+ total_failovers: totalFailovers
1176
+ },
1195
1177
  "Failover budget exhausted"
1196
1178
  );
1197
1179
  return {
@@ -1231,7 +1213,8 @@ var hasConfigChanged = (oldTarget, newTarget) => {
1231
1213
  if (oldTarget.enabled !== newTarget.enabled) return true;
1232
1214
  if (oldTarget.operator_priority !== newTarget.operator_priority) return true;
1233
1215
  if (JSON.stringify(oldTarget.policy_tags) !== JSON.stringify(newTarget.policy_tags)) return true;
1234
- if (JSON.stringify(oldTarget.capabilities) !== JSON.stringify(newTarget.capabilities)) return true;
1216
+ if (JSON.stringify(oldTarget.capabilities) !== JSON.stringify(newTarget.capabilities))
1217
+ return true;
1235
1218
  if (oldTarget.retry_budget !== newTarget.retry_budget) return true;
1236
1219
  if (oldTarget.failover_budget !== newTarget.failover_budget) return true;
1237
1220
  if (oldTarget.concurrency_limit !== newTarget.concurrency_limit) return true;
@@ -1372,95 +1355,6 @@ var reloadConfig = (deps, rawConfig) => {
1372
1355
  throw err;
1373
1356
  }
1374
1357
  };
1375
-
1376
- // src/operator/plugin-tools.ts
1377
- import { tool } from "@opencode-ai/plugin/tool";
1378
- var { schema: z3 } = tool;
1379
- var createOperatorTools = (deps) => ({
1380
- listTargets: tool({
1381
- description: "List all routing targets with health scores, states, and circuit breaker status.",
1382
- args: {},
1383
- async execute() {
1384
- deps.logger.info({ op: "listTargets" }, "operator: listTargets");
1385
- const result = listTargets(deps);
1386
- return JSON.stringify(result, null, 2);
1387
- }
1388
- }),
1389
- pauseTarget: tool({
1390
- description: "Pause a target, preventing new requests from being routed to it.",
1391
- args: { target_id: z3.string().min(1) },
1392
- async execute(args) {
1393
- deps.logger.info(
1394
- { op: "pauseTarget", target_id: args.target_id },
1395
- "operator: pauseTarget"
1396
- );
1397
- const result = pauseTarget(deps, args.target_id);
1398
- return JSON.stringify(result, null, 2);
1399
- }
1400
- }),
1401
- resumeTarget: tool({
1402
- description: "Resume a previously paused or disabled target, allowing new requests.",
1403
- args: { target_id: z3.string().min(1) },
1404
- async execute(args) {
1405
- deps.logger.info(
1406
- { op: "resumeTarget", target_id: args.target_id },
1407
- "operator: resumeTarget"
1408
- );
1409
- const result = resumeTarget(deps, args.target_id);
1410
- return JSON.stringify(result, null, 2);
1411
- }
1412
- }),
1413
- drainTarget: tool({
1414
- description: "Drain a target, allowing in-flight requests to complete but preventing new ones.",
1415
- args: { target_id: z3.string().min(1) },
1416
- async execute(args) {
1417
- deps.logger.info(
1418
- { op: "drainTarget", target_id: args.target_id },
1419
- "operator: drainTarget"
1420
- );
1421
- const result = drainTarget(deps, args.target_id);
1422
- return JSON.stringify(result, null, 2);
1423
- }
1424
- }),
1425
- disableTarget: tool({
1426
- description: "Disable a target entirely, removing it from routing.",
1427
- args: { target_id: z3.string().min(1) },
1428
- async execute(args) {
1429
- deps.logger.info(
1430
- { op: "disableTarget", target_id: args.target_id },
1431
- "operator: disableTarget"
1432
- );
1433
- const result = disableTarget(deps, args.target_id);
1434
- return JSON.stringify(result, null, 2);
1435
- }
1436
- }),
1437
- inspectRequest: tool({
1438
- description: "Inspect a request trace by ID, showing attempts, segments, and outcome.",
1439
- args: { request_id: z3.string().min(1) },
1440
- async execute(args) {
1441
- deps.logger.info(
1442
- { op: "inspectRequest", request_id: args.request_id },
1443
- "operator: inspectRequest"
1444
- );
1445
- const result = inspectRequest(deps, args.request_id);
1446
- return JSON.stringify(result, null, 2);
1447
- }
1448
- }),
1449
- reloadConfig: tool({
1450
- description: "Reload routing configuration with diff-apply. Validates new config before applying.",
1451
- args: { config: z3.record(z3.string(), z3.unknown()) },
1452
- async execute(args) {
1453
- deps.logger.info({ op: "reloadConfig" }, "operator: reloadConfig");
1454
- const result = reloadConfig(deps, args.config);
1455
- return JSON.stringify(result, null, 2);
1456
- }
1457
- })
1458
- });
1459
-
1460
- // src/profiles/store.ts
1461
- import { readFile, writeFile, rename, mkdir } from "fs/promises";
1462
- import { homedir } from "os";
1463
- import { join, dirname } from "path";
1464
1358
  var PROFILES_DIR = join(homedir(), ".local", "share", "o-switcher");
1465
1359
  var PROFILES_PATH = join(PROFILES_DIR, "profiles.json");
1466
1360
  var loadProfiles = async (path = PROFILES_PATH) => {
@@ -1527,22 +1421,11 @@ var nextProfileId = (store, provider) => {
1527
1421
  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);
1528
1422
  return `${provider}-${maxN + 1}`;
1529
1423
  };
1530
-
1531
- // src/profiles/watcher.ts
1532
- import { readFile as readFile2, watch } from "fs/promises";
1533
- import { homedir as homedir2 } from "os";
1534
- import { join as join2, dirname as dirname2 } from "path";
1535
- var AUTH_JSON_PATH = join2(
1536
- homedir2(),
1537
- ".local",
1538
- "share",
1539
- "opencode",
1540
- "auth.json"
1541
- );
1424
+ var AUTH_JSON_PATH = join(homedir(), ".local", "share", "opencode", "auth.json");
1542
1425
  var DEBOUNCE_MS = 100;
1543
1426
  var readAuthJson = async (path) => {
1544
1427
  try {
1545
- const content = await readFile2(path, "utf-8");
1428
+ const content = await readFile(path, "utf-8");
1546
1429
  return JSON.parse(content);
1547
1430
  } catch {
1548
1431
  return {};
@@ -1575,7 +1458,6 @@ var createAuthWatcher = (options) => {
1575
1458
  let lastKnownAuth = {};
1576
1459
  let abortController = null;
1577
1460
  let debounceTimer = null;
1578
- let watchPromise = null;
1579
1461
  const processChange = async () => {
1580
1462
  const newAuth = await readAuthJson(authPath);
1581
1463
  let store = await loadProfiles(profPath);
@@ -1584,7 +1466,10 @@ var createAuthWatcher = (options) => {
1584
1466
  if (!entry) continue;
1585
1467
  const previousEntry = lastKnownAuth[provider];
1586
1468
  if (previousEntry !== void 0 && !entriesEqual(previousEntry, entry)) {
1587
- log?.info({ provider, action: "credential_changed" }, "Credential change detected \u2014 saving previous credential");
1469
+ log?.info(
1470
+ { provider, action: "credential_changed" },
1471
+ "Credential change detected \u2014 saving previous credential"
1472
+ );
1588
1473
  const prevCredential = toCredential(previousEntry);
1589
1474
  const newStore = addProfile(store, provider, prevCredential);
1590
1475
  if (newStore !== store) {
@@ -1630,12 +1515,15 @@ var createAuthWatcher = (options) => {
1630
1515
  store = addProfile(store, provider, credential);
1631
1516
  }
1632
1517
  await saveProfiles(store, profPath);
1633
- log?.info({ profiles_initialized: Object.keys(store).length }, "Initialized profiles from auth.json");
1518
+ log?.info(
1519
+ { profiles_initialized: Object.keys(store).length },
1520
+ "Initialized profiles from auth.json"
1521
+ );
1634
1522
  }
1635
1523
  lastKnownAuth = currentAuth;
1636
1524
  abortController = new AbortController();
1637
- const parentDir = dirname2(authPath);
1638
- watchPromise = (async () => {
1525
+ const parentDir = dirname(authPath);
1526
+ (async () => {
1639
1527
  try {
1640
1528
  const watcher = watch(parentDir, {
1641
1529
  signal: abortController.signal
@@ -1646,9 +1534,7 @@ var createAuthWatcher = (options) => {
1646
1534
  }
1647
1535
  }
1648
1536
  } catch (err) {
1649
- const name = err.name;
1650
- if (name !== "AbortError") {
1651
- }
1537
+ err.name;
1652
1538
  }
1653
1539
  })();
1654
1540
  };
@@ -1661,17 +1547,13 @@ var createAuthWatcher = (options) => {
1661
1547
  abortController.abort();
1662
1548
  abortController = null;
1663
1549
  }
1664
- watchPromise = null;
1665
1550
  log?.info("Auth watcher stopped");
1666
1551
  };
1667
1552
  return { start, stop };
1668
1553
  };
1669
-
1670
- // src/profiles/tools.ts
1671
- import { tool as tool2 } from "@opencode-ai/plugin/tool";
1672
- var { schema: z4 } = tool2;
1554
+ var { schema: z3 } = tool;
1673
1555
  var createProfileTools = (options) => ({
1674
- profilesList: tool2({
1556
+ profilesList: tool({
1675
1557
  description: "List all saved auth profiles with provider, type, and creation date.",
1676
1558
  args: {},
1677
1559
  async execute() {
@@ -1686,9 +1568,9 @@ var createProfileTools = (options) => ({
1686
1568
  return JSON.stringify(result, null, 2);
1687
1569
  }
1688
1570
  }),
1689
- profilesRemove: tool2({
1571
+ profilesRemove: tool({
1690
1572
  description: "Remove a saved auth profile by ID.",
1691
- args: { id: z4.string().min(1) },
1573
+ args: { id: z3.string().min(1) },
1692
1574
  async execute(args) {
1693
1575
  const store = await loadProfiles(options?.profilesPath);
1694
1576
  const { store: newStore, removed } = removeProfile(store, args.id);
@@ -1705,73 +1587,4 @@ var createProfileTools = (options) => ({
1705
1587
  })
1706
1588
  });
1707
1589
 
1708
- export {
1709
- DEFAULT_RETRY_BUDGET,
1710
- DEFAULT_FAILOVER_BUDGET,
1711
- DEFAULT_BACKOFF_BASE_MS,
1712
- DEFAULT_BACKOFF_MULTIPLIER,
1713
- DEFAULT_BACKOFF_MAX_MS,
1714
- DEFAULT_BACKOFF_JITTER,
1715
- DEFAULT_RETRY,
1716
- DEFAULT_TIMEOUT_MS,
1717
- BackoffConfigSchema,
1718
- TargetConfigSchema,
1719
- SwitcherConfigSchema,
1720
- ConfigValidationError,
1721
- validateConfig,
1722
- discoverTargets,
1723
- discoverTargetsFromProfiles,
1724
- INITIAL_HEALTH_SCORE,
1725
- DEFAULT_ALPHA,
1726
- updateHealthScore,
1727
- updateLatencyEma,
1728
- TargetRegistry,
1729
- createRegistry,
1730
- TARGET_STATES,
1731
- REDACT_PATHS,
1732
- createAuditLogger,
1733
- createRequestLogger,
1734
- generateCorrelationId,
1735
- ErrorClassSchema,
1736
- isRetryable,
1737
- getTargetStateTransition,
1738
- DEFAULT_BACKOFF_PARAMS,
1739
- computeBackoffMs,
1740
- createRetryPolicy,
1741
- EXCLUSION_REASONS,
1742
- ADMISSION_RESULTS,
1743
- createRoutingEventBus,
1744
- DualBreaker,
1745
- createCircuitBreaker,
1746
- createConcurrencyTracker,
1747
- normalizeLatency,
1748
- computeScore,
1749
- getExclusionReason,
1750
- selectTarget,
1751
- computeCooldownMs,
1752
- createCooldownManager,
1753
- checkHardRejects,
1754
- createAdmissionController,
1755
- createLogSubscriber,
1756
- createFailoverOrchestrator,
1757
- computeConfigDiff,
1758
- applyConfigDiff,
1759
- createRequestTraceBuffer,
1760
- listTargets,
1761
- pauseTarget,
1762
- resumeTarget,
1763
- drainTarget,
1764
- disableTarget,
1765
- inspectRequest,
1766
- reloadConfig,
1767
- createOperatorTools,
1768
- loadProfiles,
1769
- saveProfiles,
1770
- addProfile,
1771
- removeProfile,
1772
- listProfiles,
1773
- nextProfileId,
1774
- createAuthWatcher,
1775
- createProfileTools
1776
- };
1777
- //# sourceMappingURL=chunk-BTDKGS7P.js.map
1590
+ export { ADMISSION_RESULTS, BackoffConfigSchema, ConfigValidationError, DEFAULT_ALPHA, DEFAULT_BACKOFF_BASE_MS, DEFAULT_BACKOFF_JITTER, DEFAULT_BACKOFF_MAX_MS, DEFAULT_BACKOFF_MULTIPLIER, DEFAULT_BACKOFF_PARAMS, DEFAULT_FAILOVER_BUDGET, DEFAULT_RETRY, DEFAULT_RETRY_BUDGET, DEFAULT_TIMEOUT_MS, DualBreaker, EXCLUSION_REASONS, ErrorClassSchema, INITIAL_HEALTH_SCORE, REDACT_PATHS, SwitcherConfigSchema, TARGET_STATES, TargetConfigSchema, TargetRegistry, addProfile, applyConfigDiff, checkHardRejects, computeBackoffMs, computeConfigDiff, computeCooldownMs, computeScore, createAdmissionController, createAuditLogger, createAuthWatcher, createCircuitBreaker, createConcurrencyTracker, createCooldownManager, createFailoverOrchestrator, createLogSubscriber, createProfileTools, createRegistry, createRequestLogger, createRequestTraceBuffer, createRetryPolicy, createRoutingEventBus, disableTarget, discoverTargets, discoverTargetsFromProfiles, drainTarget, generateCorrelationId, getExclusionReason, getTargetStateTransition, inspectRequest, isRetryable, listProfiles, listTargets, loadProfiles, nextProfileId, normalizeLatency, pauseTarget, reloadConfig, removeProfile, resumeTarget, saveProfiles, selectTarget, updateHealthScore, updateLatencyEma, validateConfig };