openlimiter 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js ADDED
@@ -0,0 +1,355 @@
1
+ import { PROVIDER_CODES, buildAdvice, canonicalJson, floorFixed, freshness, mergeSnapshots, normalizeMeters, readSnapshotCache } from "@openlimiter/core";
2
+ import { antigravityFixture, claudeFixture, codexFixture, connectors, manualFixture, opencodeFixture, openrouterFixture, parseAntigravityPayload, parseClaudePayload, parseCodexPayload, parseManualPayload, parseOpencodePayload, parseOpenrouterPayload } from "@openlimiter/connectors";
3
+ import { agentContextFromCache, renderClaudeStatusline } from "@openlimiter/adapters";
4
+ import { initialize } from "./config.js";
5
+ import { environmentWithLocalMarkers, parseJsonText, persistSnapshots, readManualDocument } from "./ingest.js";
6
+ import { UnavailableCredentialStore } from "./credentials.js";
7
+ import { DEFAULT_SERVE_PORT, serveBanner, startQuotaServer } from "./serve.js";
8
+ /** Exit codes. Enumerated so a script can tell these cases apart. */
9
+ export const EXIT_OK = 0;
10
+ export const EXIT_FAILURE = 1;
11
+ export const EXIT_USAGE = 2;
12
+ export const EXIT_NO_DATA = 3;
13
+ function defaults() {
14
+ return {
15
+ environment: process.env,
16
+ credentialStore: new UnavailableCredentialStore(),
17
+ promptForSecret: async () => "",
18
+ now: () => new Date().toISOString(),
19
+ payloads: {},
20
+ readStandardInput: async () => null,
21
+ colorOutput: process.stdout.isTTY === true
22
+ };
23
+ }
24
+ function succeed(stdout) {
25
+ return { exitCode: EXIT_OK, stdout, stderr: "" };
26
+ }
27
+ function fail(exitCode, message, stdout = "") {
28
+ return { exitCode, stdout, stderr: message };
29
+ }
30
+ function renderTable(snapshots, now) {
31
+ if (snapshots.length === 0)
32
+ return "No bounded quota data is available.";
33
+ const lines = ["PROVIDER METER USAGE STATE RESET"];
34
+ for (const snapshot of snapshots) {
35
+ lines.push([
36
+ snapshot.provider,
37
+ snapshot.meter,
38
+ floorFixed(snapshot.value, 2) + snapshot.unit,
39
+ freshness(snapshot.observedAt, snapshot.expiresAt, now),
40
+ snapshot.resetAt ?? "NONE"
41
+ ].join(" "));
42
+ }
43
+ return lines.join("\n");
44
+ }
45
+ async function cachedSnapshots(directory) {
46
+ const cached = await readSnapshotCache(directory);
47
+ return cached.ok ? cached.snapshots : [];
48
+ }
49
+ function flagValue(argumentsList, flag) {
50
+ const index = argumentsList.indexOf(flag);
51
+ return index < 0 ? undefined : argumentsList[index + 1];
52
+ }
53
+ /**
54
+ * Collect meters from every connector.
55
+ *
56
+ * Payloads stay caller supplied. The one local source this command reads on its
57
+ * own is the manual document in the state directory, which is the documented
58
+ * way to feed a provider that has no interface at all.
59
+ */
60
+ async function refresh(dependencies, now) {
61
+ const supplied = dependencies.payloads["manual"];
62
+ const manual = supplied === undefined
63
+ ? await readManualDocument(dependencies.stateDirectory)
64
+ : supplied;
65
+ const environment = await environmentWithLocalMarkers(dependencies.environment, dependencies.stateDirectory);
66
+ const raw = [];
67
+ for (const connector of connectors) {
68
+ const payload = connector.id === "manual"
69
+ ? manual
70
+ : dependencies.payloads[connector.id];
71
+ const result = await connector.read({ payload, now, environment });
72
+ if (result.ok)
73
+ raw.push(...result.meters);
74
+ }
75
+ const snapshots = normalizeMeters(raw);
76
+ if (snapshots.length === 0)
77
+ return [];
78
+ return (await persistSnapshots(snapshots, dependencies.stateDirectory)).merged;
79
+ }
80
+ function demoSnapshots(now) {
81
+ const raw = [
82
+ ...(parseClaudePayload(claudeFixture(now), now) ?? []),
83
+ ...(parseOpenrouterPayload(openrouterFixture(), now) ?? []),
84
+ ...(parseCodexPayload(codexFixture(now), now) ?? []),
85
+ ...(parseAntigravityPayload(antigravityFixture(now), now) ?? []),
86
+ ...(parseOpencodePayload(opencodeFixture(now), now) ?? []),
87
+ ...(parseManualPayload(manualFixture(now), now) ?? [])
88
+ ];
89
+ return normalizeMeters(raw);
90
+ }
91
+ function doctorRows(snapshots, environment, now) {
92
+ const lines = ["CONNECTOR DETECTED FRESHNESS DRIFT"];
93
+ for (const connector of connectors) {
94
+ const provider = connector.id.toUpperCase();
95
+ const states = snapshots
96
+ .filter((snapshot) => snapshot.provider === provider)
97
+ .map((snapshot) => freshness(snapshot.observedAt, snapshot.expiresAt, now));
98
+ const state = states.includes("fresh")
99
+ ? "fresh"
100
+ : states.includes("stale")
101
+ ? "stale"
102
+ : "unknown";
103
+ lines.push([
104
+ connector.id,
105
+ connector.detect(environment) ? "yes" : "no",
106
+ state,
107
+ "UNVERIFIED"
108
+ ].join(" "));
109
+ }
110
+ return lines.join("\n");
111
+ }
112
+ const help = [
113
+ "openlimiter init",
114
+ "openlimiter snapshot [--refresh]",
115
+ "openlimiter statusline",
116
+ "openlimiter hook [--dry-run]",
117
+ "openlimiter ingest [--provider <id>] [--payload <json>]",
118
+ "openlimiter doctor",
119
+ "openlimiter demo",
120
+ "openlimiter export",
121
+ "openlimiter serve [--port <n>] [--host <address>] [--no-qr]",
122
+ "",
123
+ "statusline and ingest read JSON from standard input when it is piped in.",
124
+ "serve publishes read only quota on your local network, behind a token that",
125
+ "changes on every start. It is for a trusted network, not the internet.",
126
+ "Exit codes: 0 success, 1 failure, 2 usage, 3 no bounded quota data."
127
+ ].join("\n");
128
+ /**
129
+ * Parse a Claude Code statusline payload from standard input and cache it.
130
+ *
131
+ * This is the path that gives the tool something to meter. It performs no
132
+ * network access at all: it validates the JSON that Claude Code already wrote
133
+ * to this process. Every failure returns null so the caller can fall back to
134
+ * the cache instead of breaking the host tool.
135
+ */
136
+ async function ingestStandardInput(dependencies, now) {
137
+ try {
138
+ const document = parseJsonText(await dependencies.readStandardInput());
139
+ if (!document.ok)
140
+ return null;
141
+ const meters = parseClaudePayload(document.value, now);
142
+ if (meters === null)
143
+ return null;
144
+ const incoming = normalizeMeters(meters);
145
+ if (incoming.length === 0)
146
+ return null;
147
+ try {
148
+ return (await persistSnapshots(incoming, dependencies.stateDirectory)).merged;
149
+ }
150
+ catch {
151
+ const existing = await cachedSnapshots(dependencies.stateDirectory);
152
+ return mergeSnapshots(existing, incoming);
153
+ }
154
+ }
155
+ catch {
156
+ return null;
157
+ }
158
+ }
159
+ async function initCommand(dependencies) {
160
+ const environment = await environmentWithLocalMarkers(dependencies.environment, dependencies.stateDirectory);
161
+ try {
162
+ const result = await initialize(environment, dependencies.credentialStore, dependencies.promptForSecret, dependencies.stateDirectory);
163
+ const detected = result.config.connectors
164
+ .filter((connector) => connector.detected)
165
+ .map((connector) => connector.id)
166
+ .join(",");
167
+ return succeed("Configuration saved. Detected: " + (detected === "" ? "none" : detected));
168
+ }
169
+ catch {
170
+ return fail(EXIT_FAILURE, "openlimiter init: configuration could not be written.");
171
+ }
172
+ }
173
+ async function snapshotCommand(dependencies, argumentsList, now) {
174
+ if (argumentsList.includes("--refresh")) {
175
+ try {
176
+ await refresh(dependencies, now);
177
+ }
178
+ catch {
179
+ return fail(EXIT_FAILURE, "openlimiter snapshot: the cache could not be written.");
180
+ }
181
+ }
182
+ const cached = await readSnapshotCache(dependencies.stateDirectory);
183
+ if (!cached.ok && cached.reason !== "missing") {
184
+ return fail(EXIT_FAILURE, "openlimiter snapshot: quota state could not be read.");
185
+ }
186
+ const snapshots = cached.ok ? cached.snapshots : [];
187
+ const stdout = renderTable(snapshots, now);
188
+ return snapshots.length === 0
189
+ ? fail(EXIT_NO_DATA, "openlimiter snapshot: no bounded quota data is available.", stdout)
190
+ : succeed(stdout);
191
+ }
192
+ async function exportCommand(dependencies) {
193
+ const cached = await readSnapshotCache(dependencies.stateDirectory);
194
+ if (!cached.ok && cached.reason !== "missing") {
195
+ return fail(EXIT_FAILURE, "openlimiter export: quota state could not be read.");
196
+ }
197
+ const snapshots = cached.ok ? cached.snapshots : [];
198
+ const stdout = canonicalJson(snapshots);
199
+ return snapshots.length === 0
200
+ ? fail(EXIT_NO_DATA, "openlimiter export: no bounded quota data is available.", stdout)
201
+ : succeed(stdout);
202
+ }
203
+ async function doctorCommand(dependencies, now) {
204
+ const environment = await environmentWithLocalMarkers(dependencies.environment, dependencies.stateDirectory);
205
+ const cached = await readSnapshotCache(dependencies.stateDirectory);
206
+ const snapshots = cached.ok ? cached.snapshots : [];
207
+ const status = cached.ok ? "ok" : cached.reason;
208
+ const dropped = cached.ok ? cached.dropped : 0;
209
+ const stdout = doctorRows(snapshots, environment, now) +
210
+ "\nCACHE " + status + " DROPPED " + String(dropped);
211
+ if (!cached.ok && cached.reason !== "missing") {
212
+ return fail(EXIT_FAILURE, "openlimiter doctor: quota state could not be read.", stdout);
213
+ }
214
+ return succeed(stdout);
215
+ }
216
+ /**
217
+ * Accept quota data from any script or agent.
218
+ *
219
+ * Without a provider flag the document is a manual quota document, the same
220
+ * shape the manual connector reads from disk. With a provider flag the document
221
+ * is handed to that connector's own parser, so the resulting snapshot keeps
222
+ * that connector's honest labels. Nothing here reaches the network.
223
+ */
224
+ async function ingestCommand(dependencies, argumentsList, now) {
225
+ const provider = flagValue(argumentsList, "--provider");
226
+ const inline = flagValue(argumentsList, "--payload");
227
+ if (argumentsList.includes("--provider") && provider === undefined) {
228
+ return fail(EXIT_USAGE, "openlimiter ingest: the provider flag needs a value.");
229
+ }
230
+ if (argumentsList.includes("--payload") && inline === undefined) {
231
+ return fail(EXIT_USAGE, "openlimiter ingest: the payload flag needs a value.");
232
+ }
233
+ const text = inline ?? await dependencies.readStandardInput();
234
+ const document = parseJsonText(text);
235
+ if (!document.ok) {
236
+ return text === null || text.trim() === ""
237
+ ? fail(EXIT_USAGE, "openlimiter ingest: no input was supplied on standard input.")
238
+ : fail(EXIT_FAILURE, "openlimiter ingest: input is not valid JSON.");
239
+ }
240
+ let meters;
241
+ if (provider === undefined) {
242
+ meters = parseManualPayload(document.value, now);
243
+ }
244
+ else {
245
+ const connector = connectors.find((candidate) => candidate.id === provider);
246
+ if (connector === undefined) {
247
+ return fail(EXIT_USAGE, "openlimiter ingest: unknown provider.");
248
+ }
249
+ const result = await connector.read({
250
+ payload: document.value,
251
+ now,
252
+ environment: dependencies.environment
253
+ });
254
+ meters = result.ok ? result.meters : null;
255
+ }
256
+ const incoming = meters === null ? [] : normalizeMeters([...meters]);
257
+ if (incoming.length === 0) {
258
+ return fail(EXIT_FAILURE, "openlimiter ingest: no bounded meter survived validation.");
259
+ }
260
+ try {
261
+ const persisted = await persistSnapshots(incoming, dependencies.stateDirectory);
262
+ return succeed("Ingested " + String(incoming.length) +
263
+ " bounded meters. Cached meters: " + String(persisted.merged.length) + ".");
264
+ }
265
+ catch {
266
+ return fail(EXIT_FAILURE, "openlimiter ingest: the cache could not be written.");
267
+ }
268
+ }
269
+ /**
270
+ * Publish the cached quota on the local network, read only.
271
+ *
272
+ * This is the one command that does not finish. It returns its banner as soon
273
+ * as the socket is bound, and the listening socket is what keeps the process
274
+ * alive afterwards, so the caller writes the banner exactly once and then gets
275
+ * out of the way.
276
+ */
277
+ async function serveCommand(dependencies, argumentsList) {
278
+ const portText = flagValue(argumentsList, "--port");
279
+ if (argumentsList.includes("--port") && portText === undefined) {
280
+ return fail(EXIT_USAGE, "openlimiter serve: the port flag needs a value.");
281
+ }
282
+ const port = portText === undefined ? DEFAULT_SERVE_PORT : Number(portText);
283
+ if (!Number.isInteger(port) || port < 0 || port > 65_535) {
284
+ return fail(EXIT_USAGE, "openlimiter serve: the port must be a whole number from 0 to 65535.");
285
+ }
286
+ const host = flagValue(argumentsList, "--host");
287
+ if (argumentsList.includes("--host") && host === undefined) {
288
+ return fail(EXIT_USAGE, "openlimiter serve: the host flag needs a value.");
289
+ }
290
+ try {
291
+ const handle = await startQuotaServer({
292
+ port,
293
+ ...(host === undefined ? {} : { host }),
294
+ stateDirectory: dependencies.stateDirectory,
295
+ now: dependencies.now
296
+ });
297
+ dependencies.onListening?.(handle);
298
+ return succeed(serveBanner(handle, {
299
+ color: dependencies.colorOutput,
300
+ withoutQr: argumentsList.includes("--no-qr")
301
+ }));
302
+ }
303
+ catch {
304
+ return fail(EXIT_FAILURE, "openlimiter serve: that address and port could not be opened.");
305
+ }
306
+ }
307
+ export async function runCli(argumentsList, overrides = {}) {
308
+ const dependencies = { ...defaults(), ...overrides };
309
+ const command = argumentsList[0] ?? "help";
310
+ const now = dependencies.now();
311
+ try {
312
+ if (command === "init")
313
+ return await initCommand(dependencies);
314
+ if (command === "snapshot") {
315
+ return await snapshotCommand(dependencies, argumentsList, now);
316
+ }
317
+ if (command === "statusline") {
318
+ const ingested = await ingestStandardInput(dependencies, now);
319
+ const snapshots = ingested ?? await cachedSnapshots(dependencies.stateDirectory);
320
+ return succeed(renderClaudeStatusline(buildAdvice(snapshots, now, PROVIDER_CODES)));
321
+ }
322
+ if (command === "hook") {
323
+ return succeed(await agentContextFromCache(dependencies.stateDirectory, now, PROVIDER_CODES));
324
+ }
325
+ if (command === "doctor")
326
+ return await doctorCommand(dependencies, now);
327
+ if (command === "demo")
328
+ return succeed(renderTable(demoSnapshots(now), now));
329
+ if (command === "export")
330
+ return await exportCommand(dependencies);
331
+ if (command === "ingest") {
332
+ return await ingestCommand(dependencies, argumentsList, now);
333
+ }
334
+ if (command === "serve")
335
+ return await serveCommand(dependencies, argumentsList);
336
+ if (command === "help" || command === "--help" || command === "-h") {
337
+ return succeed(help);
338
+ }
339
+ return fail(EXIT_USAGE, "openlimiter: unknown command.", help);
340
+ }
341
+ catch {
342
+ /*
343
+ * The hook and statusline paths are invoked by another tool. They report
344
+ * nothing rather than breaking their host. Every other command surfaces the
345
+ * failure with a redacted message so a script can react to it.
346
+ */
347
+ if (command === "hook")
348
+ return { exitCode: EXIT_OK, stdout: "", stderr: "" };
349
+ if (command === "statusline") {
350
+ return { exitCode: EXIT_OK, stdout: "OpenLimiter UNKNOWN", stderr: "" };
351
+ }
352
+ return fail(EXIT_FAILURE, "openlimiter: the command did not complete.");
353
+ }
354
+ }
355
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,iBAAiB,EAIlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,2BAA2B,EAC3B,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAE3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAwCpB,qEAAqE;AACrE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,SAAS,QAAQ;IACf,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,GAAG;QACxB,eAAe,EAAE,IAAI,0BAA0B,EAAE;QACjD,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;QAC/B,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,QAAQ,EAAE,EAAE;QACZ,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;QACnC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,MAAc;IAC7B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,IAAI,CAAC,QAAgB,EAAE,OAAe,EAAE,MAAM,GAAG,EAAE;IAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,SAA8B,EAAE,GAAW;IAC9D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,qCAAqC,CAAC;IACzE,MAAM,KAAK,GAAG,CAAC,kCAAkC,CAAC,CAAC;IACnD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC;YACT,QAAQ,CAAC,QAAQ;YACjB,QAAQ,CAAC,KAAK;YACd,UAAU,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI;YAC7C,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;YACvD,QAAQ,CAAC,OAAO,IAAI,MAAM;SAC3B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,SAAkB;IAC/C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAClD,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,SAAS,CAChB,aAAgC,EAChC,IAAY;IAEZ,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,OAAO,CACpB,YAA6B,EAC7B,GAAW;IAEX,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,QAAQ,KAAK,SAAS;QACnC,CAAC,CAAC,MAAM,kBAAkB,CAAC,YAAY,CAAC,cAAc,CAAC;QACvD,CAAC,CAAC,QAAQ,CAAC;IACb,MAAM,WAAW,GAAG,MAAM,2BAA2B,CACnD,YAAY,CAAC,WAAW,EACxB,YAAY,CAAC,cAAc,CAC5B,CAAC;IACF,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,KAAK,QAAQ;YACvC,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;QACnE,IAAI,MAAM,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,OAAO,CAAC,MAAM,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC;AACjF,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,GAAG,GAAG;QACV,GAAG,CAAC,kBAAkB,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QACtD,GAAG,CAAC,sBAAsB,CAAC,iBAAiB,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3D,GAAG,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QACpD,GAAG,CAAC,uBAAuB,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QAChE,GAAG,CAAC,oBAAoB,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1D,GAAG,CAAC,kBAAkB,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;KACvD,CAAC;IACF,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,UAAU,CACjB,SAA8B,EAC9B,WAAyD,EACzD,GAAW;IAEX,MAAM,KAAK,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACrD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC,WAAW,EAAkB,CAAC;QAC5D,MAAM,MAAM,GAAG,SAAS;aACrB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC;aACpD,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YACpC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACxB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,SAAS,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC;YACT,SAAS,CAAC,EAAE;YACZ,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YAC5C,KAAK;YACL,YAAY;SACb,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,IAAI,GAAG;IACX,kBAAkB;IAClB,kCAAkC;IAClC,wBAAwB;IACxB,8BAA8B;IAC9B,yDAAyD;IACzD,oBAAoB;IACpB,kBAAkB;IAClB,oBAAoB;IACpB,6DAA6D;IAC7D,EAAE;IACF,0EAA0E;IAC1E,4EAA4E;IAC5E,wEAAwE;IACxE,qEAAqE;CACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;;GAOG;AACH,KAAK,UAAU,mBAAmB,CAChC,YAA6B,EAC7B,GAAW;IAEX,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,YAAY,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACjC,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACvC,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YACpE,OAAO,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,YAA6B;IACtD,MAAM,WAAW,GAAG,MAAM,2BAA2B,CACnD,YAAY,CAAC,WAAW,EACxB,YAAY,CAAC,cAAc,CAC5B,CAAC;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,WAAW,EACX,YAAY,CAAC,eAAe,EAC5B,YAAY,CAAC,eAAe,EAC5B,YAAY,CAAC,cAAc,CAC5B,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU;aACtC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC;aACzC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;aAChC,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,OAAO,CACZ,iCAAiC,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAC1E,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,YAAY,EAAE,uDAAuD,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,YAA6B,EAC7B,aAAgC,EAChC,GAAW;IAEX,IAAI,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,YAAY,EAAE,uDAAuD,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,YAAY,EAAE,sDAAsD,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3C,OAAO,SAAS,CAAC,MAAM,KAAK,CAAC;QAC3B,CAAC,CAAC,IAAI,CACF,YAAY,EACZ,2DAA2D,EAC3D,MAAM,CACP;QACH,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,YAA6B;IACxD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,YAAY,EAAE,oDAAoD,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACxC,OAAO,SAAS,CAAC,MAAM,KAAK,CAAC;QAC3B,CAAC,CAAC,IAAI,CACF,YAAY,EACZ,yDAAyD,EACzD,MAAM,CACP;QACH,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,YAA6B,EAC7B,GAAW;IAEX,MAAM,WAAW,GAAG,MAAM,2BAA2B,CACnD,YAAY,CAAC,WAAW,EACxB,YAAY,CAAC,cAAc,CAC5B,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC;QACpD,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,YAAY,EAAE,oDAAoD,EAAE,MAAM,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,aAAa,CAC1B,YAA6B,EAC7B,aAAgC,EAChC,GAAW;IAEX,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACrD,IAAI,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC,UAAU,EAAE,sDAAsD,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,UAAU,EAAE,qDAAqD,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,IAAI,MAAM,YAAY,CAAC,iBAAiB,EAAE,CAAC;IAC9D,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YACxC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,8DAA8D,CAAC;YAClF,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,8CAA8C,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,MAAkC,CAAC;IACvC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC5E,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,UAAU,EAAE,uCAAuC,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC;YAClC,OAAO,EAAE,QAAQ,CAAC,KAAK;YACvB,GAAG;YACH,WAAW,EAAE,YAAY,CAAC,WAAW;SACtC,CAAC,CAAC;QACH,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IACrE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CACT,YAAY,EACZ,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;QAChF,OAAO,OAAO,CACZ,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACrC,kCAAkC,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAC3E,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,YAAY,EAAE,qDAAqD,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,YAAY,CACzB,YAA6B,EAC7B,aAAgC;IAEhC,MAAM,QAAQ,GAAG,SAAS,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACpD,IAAI,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC/D,OAAO,IAAI,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;QACzD,OAAO,IAAI,CACT,UAAU,EACV,qEAAqE,CACtE,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,IAAI;YACJ,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACvC,cAAc,EAAE,YAAY,CAAC,cAAc;YAC3C,GAAG,EAAE,YAAY,CAAC,GAAG;SACtB,CAAC,CAAC;QACH,YAAY,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,OAAO,CACZ,WAAW,CAAC,MAAM,EAAE;YAClB,KAAK,EAAE,YAAY,CAAC,WAAW;YAC/B,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;SAC7C,CAAC,CACH,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CACT,YAAY,EACZ,+DAA+D,CAChE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,aAAgC,EAChC,YAAsC,EAAE;IAExC,MAAM,YAAY,GAAG,EAAE,GAAG,QAAQ,EAAE,EAAE,GAAG,SAAS,EAAE,CAAC;IACrD,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAC3C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;QAC/D,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YAC3B,OAAO,MAAM,eAAe,CAAC,YAAY,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YAC9D,MAAM,SAAS,GAAG,QAAQ,IAAI,MAAM,eAAe,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YACjF,OAAO,OAAO,CACZ,sBAAsB,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC,MAAM,qBAAqB,CACxC,YAAY,CAAC,cAAc,EAC3B,GAAG,EACH,cAAc,CACf,CAAC,CAAC;QACL,CAAC;QACD,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO,MAAM,aAAa,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACxE,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,OAAO,MAAM,aAAa,CAAC,YAAY,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO,MAAM,YAAY,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAChF,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACnE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,EAAE,+BAA+B,EAAE,IAAI,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP;;;;WAIG;QACH,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC7E,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;YAC7B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,EAAE,4CAA4C,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { CredentialStore } from "./credentials.js";
2
+ export declare const CONFIG_FILE_NAME = "openlimiter-config.json";
3
+ export interface OpenLimiterConfig {
4
+ version: 1;
5
+ connectors: readonly {
6
+ id: string;
7
+ enabled: true;
8
+ detected: boolean;
9
+ }[];
10
+ }
11
+ export declare function writeConfig(config: OpenLimiterConfig, directory?: string): Promise<void>;
12
+ export declare function initialize(environment: Readonly<Record<string, string | undefined>>, credentialStore: CredentialStore, promptForSecret: () => Promise<string>, directory?: string): Promise<{
13
+ config: OpenLimiterConfig;
14
+ credentialStored: boolean;
15
+ }>;
16
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,SAAS;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,IAAI,CAAC;QACd,QAAQ,EAAE,OAAO,CAAC;KACnB,EAAE,CAAC;CACL;AAUD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,EACzB,SAAS,SAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,UAAU,CAC9B,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACzD,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EACtC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAAC,CA2BnE"}
package/dist/config.js ADDED
@@ -0,0 +1,53 @@
1
+ import { lstat, mkdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { canonicalJson, resolveStateDirectory, writeFileAtomically } from "@openlimiter/core";
4
+ import { connectors } from "@openlimiter/connectors";
5
+ export const CONFIG_FILE_NAME = "openlimiter-config.json";
6
+ async function rejectSymlink(target) {
7
+ try {
8
+ if ((await lstat(target)).isSymbolicLink())
9
+ throw new Error("Unsafe state path");
10
+ }
11
+ catch (error) {
12
+ if (error.code !== "ENOENT")
13
+ throw error;
14
+ }
15
+ }
16
+ export async function writeConfig(config, directory = resolveStateDirectory()) {
17
+ await rejectSymlink(directory);
18
+ await mkdir(directory, { recursive: true, mode: 0o700 });
19
+ await rejectSymlink(directory);
20
+ const target = path.join(directory, CONFIG_FILE_NAME);
21
+ await rejectSymlink(target);
22
+ await writeFileAtomically(target, canonicalJson(config));
23
+ }
24
+ export async function initialize(environment, credentialStore, promptForSecret, directory) {
25
+ const config = {
26
+ version: 1,
27
+ connectors: connectors.map((connector) => ({
28
+ id: connector.id,
29
+ enabled: true,
30
+ detected: connector.detect(environment)
31
+ }))
32
+ };
33
+ let credentialStored = false;
34
+ const openrouter = config.connectors.find((connector) => connector.id === "openrouter");
35
+ if (openrouter?.detected === true) {
36
+ try {
37
+ const existing = await credentialStore.get("openlimiter", "openrouter");
38
+ if (existing === null) {
39
+ const secret = await promptForSecret();
40
+ if (secret.length > 0 && secret.length <= 8_192) {
41
+ await credentialStore.set("openlimiter", "openrouter", secret);
42
+ credentialStored = true;
43
+ }
44
+ }
45
+ }
46
+ catch {
47
+ credentialStored = false;
48
+ }
49
+ }
50
+ await writeConfig(config, directory);
51
+ return { config, credentialStored };
52
+ }
53
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAW1D,KAAK,UAAU,aAAa,CAAC,MAAc;IACzC,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACnF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,KAAK,CAAC;IACtE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB,EACzB,SAAS,GAAG,qBAAqB,EAAE;IAEnC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACtD,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,mBAAmB,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,WAAyD,EACzD,eAAgC,EAChC,eAAsC,EACtC,SAAkB;IAElB,MAAM,MAAM,GAAsB;QAChC,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACzC,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC;SACxC,CAAC,CAAC;KACJ,CAAC;IACF,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IACxF,IAAI,UAAU,EAAE,QAAQ,KAAK,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;YACxE,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACtB,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;gBACvC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;oBAChD,MAAM,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;oBAC/D,gBAAgB,GAAG,IAAI,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB,GAAG,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,MAAM,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,19 @@
1
+ export interface CredentialStore {
2
+ get(service: string, account: string): Promise<string | null>;
3
+ set(service: string, account: string, secret: string): Promise<void>;
4
+ }
5
+ export interface CredentialDriver {
6
+ getPassword(service: string, account: string): Promise<string | null>;
7
+ setPassword(service: string, account: string, secret: string): Promise<void>;
8
+ }
9
+ export declare class OperatingSystemCredentialStore implements CredentialStore {
10
+ private readonly driver;
11
+ constructor(driver: CredentialDriver);
12
+ get(service: string, account: string): Promise<string | null>;
13
+ set(service: string, account: string, secret: string): Promise<void>;
14
+ }
15
+ export declare class UnavailableCredentialStore implements CredentialStore {
16
+ get(): Promise<string | null>;
17
+ set(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9D,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,qBAAa,8BAA+B,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAErD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI7D,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGrE;AAED,qBAAa,0BAA2B,YAAW,eAAe;IAC1D,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI7B,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAG3B"}
@@ -0,0 +1,21 @@
1
+ export class OperatingSystemCredentialStore {
2
+ driver;
3
+ constructor(driver) {
4
+ this.driver = driver;
5
+ }
6
+ get(service, account) {
7
+ return this.driver.getPassword(service, account);
8
+ }
9
+ set(service, account, secret) {
10
+ return this.driver.setPassword(service, account, secret);
11
+ }
12
+ }
13
+ export class UnavailableCredentialStore {
14
+ async get() {
15
+ return null;
16
+ }
17
+ async set() {
18
+ throw new Error("Credential store is unavailable");
19
+ }
20
+ }
21
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,8BAA8B;IACZ;IAA7B,YAA6B,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;IAAG,CAAC;IAEzD,GAAG,CAAC,OAAe,EAAE,OAAe;QAClC,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,GAAG,CAAC,OAAe,EAAE,OAAe,EAAE,MAAc;QAClD,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;CACF;AAED,MAAM,OAAO,0BAA0B;IACrC,KAAK,CAAC,GAAG;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export * from "./cli.js";
2
+ export * from "./config.js";
3
+ export * from "./credentials.js";
4
+ export * from "./ingest.js";
5
+ export * from "./qr.js";
6
+ export * from "./serve.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from "./cli.js";
2
+ export * from "./config.js";
3
+ export * from "./credentials.js";
4
+ export * from "./ingest.js";
5
+ export * from "./qr.js";
6
+ export * from "./serve.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { type CacheMergeResult, type Snapshot } from "@openlimiter/core";
2
+ /** Largest document accepted on standard input. */
3
+ export declare const STDIN_BYTE_LIMIT = 262144;
4
+ /** Hard ceiling on how long a command waits for standard input. */
5
+ export declare const STDIN_TIMEOUT_MILLISECONDS = 500;
6
+ /** Largest manual document accepted from the state directory. */
7
+ export declare const MANUAL_FILE_BYTE_LIMIT = 65536;
8
+ export type JsonText = {
9
+ ok: true;
10
+ value: unknown;
11
+ } | {
12
+ ok: false;
13
+ };
14
+ /**
15
+ * Read standard input without ever blocking a caller forever.
16
+ *
17
+ * A terminal is treated as no input at all, the stream is bounded by size, and
18
+ * a stream that never ends still resolves once the timeout elapses. Claude Code
19
+ * writes its statusline payload and closes the pipe, so the common path costs
20
+ * one tick rather than the full timeout.
21
+ */
22
+ export declare function readStandardInputText(stream?: NodeJS.ReadStream, byteLimit?: number, timeoutMilliseconds?: number): Promise<string | null>;
23
+ /** Parse untrusted text as JSON without throwing. */
24
+ export declare function parseJsonText(text: string | null): JsonText;
25
+ /**
26
+ * Read the manual quota document from the state directory.
27
+ *
28
+ * The document is untrusted input. It is bounded by size, opened through the
29
+ * same descriptor first read as the cache, and handed to the manual connector
30
+ * for validation. A missing or unreadable file is simply no data.
31
+ */
32
+ export declare function readManualDocument(directory: string | undefined): Promise<unknown>;
33
+ /** Report whether a manual document is present, without reading it. */
34
+ export declare function manualFilePresent(directory: string | undefined): Promise<boolean>;
35
+ /**
36
+ * Build the environment map a connector sees.
37
+ *
38
+ * Local facts that only the CLI can observe become explicit markers, so
39
+ * detection stays a pure function of the environment and doctor never claims a
40
+ * connector is ready when it can receive no data.
41
+ */
42
+ export declare function environmentWithLocalMarkers(environment: Readonly<Record<string, string | undefined>>, directory: string | undefined): Promise<Record<string, string | undefined>>;
43
+ /**
44
+ * Merge validated snapshots into the cache.
45
+ *
46
+ * Quota observed by one command stays visible to the next one. The read, the
47
+ * merge, and the write happen under one lock inside the core, so a concurrent
48
+ * writer cannot drop these rows.
49
+ */
50
+ export declare function persistSnapshots(incoming: readonly Snapshot[], directory: string | undefined): Promise<CacheMergeResult>;
51
+ //# sourceMappingURL=ingest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../src/ingest.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,mBAAmB,CAAC;AAE3B,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,SAAU,CAAC;AAExC,mEAAmE;AACnE,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,iEAAiE;AACjE,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,MAAM,MAAM,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpE;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,GAAE,MAAM,CAAC,UAA0B,EACzC,SAAS,SAAmB,EAC5B,mBAAmB,SAA6B,GAC/C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkCxB;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAS3D;AAMD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED,uEAAuE;AACvE,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAMvF;AAED;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACzD,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAQ7C;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,SAAS,QAAQ,EAAE,EAC7B,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAK3B"}