@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.
@@ -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;