openlimiter 2.0.3 → 2.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/README.md +3 -1
- package/dist/api-spend.d.ts +1 -3
- package/dist/api-spend.d.ts.map +1 -1
- package/dist/api-spend.js +11 -15
- package/dist/api-spend.js.map +1 -1
- package/dist/bin.js +1 -15
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts +8 -21
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +129 -56
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +10 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +65 -29
- package/dist/config.js.map +1 -1
- package/dist/hub-sync.d.ts +4 -2
- package/dist/hub-sync.d.ts.map +1 -1
- package/dist/hub-sync.js +43 -10
- package/dist/hub-sync.js.map +1 -1
- package/dist/ingest.d.ts +2 -0
- package/dist/ingest.d.ts.map +1 -1
- package/dist/ingest.js +14 -62
- package/dist/ingest.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +42 -11
- package/dist/render.js.map +1 -1
- package/dist/statusline.d.ts +8 -3
- package/dist/statusline.d.ts.map +1 -1
- package/dist/statusline.js +231 -69
- package/dist/statusline.js.map +1 -1
- package/dist/terminal-launcher.d.ts +5 -0
- package/dist/terminal-launcher.d.ts.map +1 -1
- package/dist/terminal-launcher.js +188 -13
- package/dist/terminal-launcher.js.map +1 -1
- package/dist/terminal.d.ts.map +1 -1
- package/dist/terminal.js +11 -10
- package/dist/terminal.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ openlimiter status --agent-context
|
|
|
65
65
|
|
|
66
66
|
| Provider | Connects by | Reads |
|
|
67
67
|
|---|---|---|
|
|
68
|
-
| Claude |
|
|
68
|
+
| Claude | Setup asks once in a terminal | The Claude Code status line automatically; the recorded `providers.claude.poll` choice controls direct usage requests when Claude Code is closed |
|
|
69
69
|
| Codex | Use the login already there, or sign in from inside OpenLimiter | The login the Codex CLI stored |
|
|
70
70
|
| Gemini CLI | Read only, from the login already there | The login the Gemini CLI stored |
|
|
71
71
|
| Antigravity | Read only, from the credential already there | The credential the Antigravity CLI stored |
|
|
@@ -77,4 +77,6 @@ openlimiter status --agent-context
|
|
|
77
77
|
|
|
78
78
|
`openlimiter refresh` is what reaches the network, at most once every fifteen minutes per provider: it reads the logins your provider tools already stored and asks each provider for its own usage. It stands down while the desktop app is running, and `statusline`, `snapshot` and `setup` all start it in the background on their own. OpenLimiter never asks for a vendor password, never impersonates a vendor tool, and never uploads a token.
|
|
79
79
|
|
|
80
|
+
Claude has two independent switches. Show Fable limit in the desktop app controls the desktop process. To stop it, open Settings, then Show Fable limit, then turn it off. `providers.claude.poll` controls the command line process. To stop it, run `openlimiter config set providers.claude.poll false`. Terminal setup asks once, and unattended setup records off. When the poll is off, the Claude status line shows the session bar only. The request goes directly to the usage endpoint with your local Claude credentials. Anthropic's policy for tools like this is unresolved.
|
|
81
|
+
|
|
80
82
|
Read the [documentation](https://openlimiter.com/docs) or browse the [repository](https://github.com/lucaswebsystems/openlimiter).
|
package/dist/api-spend.d.ts
CHANGED
|
@@ -20,9 +20,7 @@ export interface MoneyCell {
|
|
|
20
20
|
}
|
|
21
21
|
export interface MoneyOptions {
|
|
22
22
|
readonly now: string;
|
|
23
|
-
/**
|
|
24
|
-
readonly hasOpenRouter: boolean;
|
|
25
|
-
/** Whether a provider name (`openai`, `openrouter`...) may be drawn. */
|
|
23
|
+
/** Whether a provider name may be drawn. */
|
|
26
24
|
readonly allowed: (provider: string) => boolean;
|
|
27
25
|
}
|
|
28
26
|
export declare function moneyCells(document: unknown, options: MoneyOptions): readonly MoneyCell[];
|
package/dist/api-spend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-spend.d.ts","sourceRoot":"","sources":["../src/api-spend.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,8EAA8E;AAC9E,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMvD,CAAC;
|
|
1
|
+
{"version":3,"file":"api-spend.d.ts","sourceRoot":"","sources":["../src/api-spend.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,8EAA8E;AAC9E,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMvD,CAAC;AAMF,wBAAsB,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG3E;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD;AAuBD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,SAAS,SAAS,EAAE,CAsDzF"}
|
package/dist/api-spend.js
CHANGED
|
@@ -18,6 +18,7 @@ export const MONEY_TAGS = {
|
|
|
18
18
|
moonshot: "ms",
|
|
19
19
|
deepseek: "ds"
|
|
20
20
|
};
|
|
21
|
+
const BALANCE_PROVIDERS = new Set(["moonshot", "deepseek"]);
|
|
21
22
|
const MAX_SOURCES = 64;
|
|
22
23
|
export async function readApiSpend(stateDirectory) {
|
|
23
24
|
const result = await readJsonFileSafely(path.join(stateDirectory, API_SPEND_FILE_NAME)).catch(() => null);
|
|
@@ -58,7 +59,6 @@ export function moneyCells(document, options) {
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
const cells = [];
|
|
61
|
-
let openRouter;
|
|
62
62
|
for (const source of document["sources"].slice(0, MAX_SOURCES)) {
|
|
63
63
|
if (!isRecord(source) || source["enabled"] !== true || typeof source["id"] !== "string")
|
|
64
64
|
continue;
|
|
@@ -68,8 +68,11 @@ export function moneyCells(document, options) {
|
|
|
68
68
|
const sample = newest.get(source["id"]);
|
|
69
69
|
if (sample === undefined)
|
|
70
70
|
continue;
|
|
71
|
-
|
|
72
|
-
if (
|
|
71
|
+
// OpenRouter monthly spend is not the account's remaining credit balance.
|
|
72
|
+
if (provider === "openrouter")
|
|
73
|
+
continue;
|
|
74
|
+
const tag = MONEY_TAGS[provider];
|
|
75
|
+
if (tag === undefined)
|
|
73
76
|
continue;
|
|
74
77
|
const stale = freshnessPolicy({
|
|
75
78
|
sourceClass: "internal_payload", observedAt: String(sample["observedAt"]), now: options.now, writer: "desktop"
|
|
@@ -77,7 +80,9 @@ export function moneyCells(document, options) {
|
|
|
77
80
|
const prefix = tag + " ";
|
|
78
81
|
const mark = stale ? "~" : "";
|
|
79
82
|
const usd = sample["currencySource"] === "provider_usd";
|
|
80
|
-
|
|
83
|
+
/* Moonshot's available_balance and DeepSeek's balance are current balances,
|
|
84
|
+
never spend for the current month. */
|
|
85
|
+
if (BALANCE_PROVIDERS.has(provider)) {
|
|
81
86
|
const balance = decimal(sample["balanceUsd"]);
|
|
82
87
|
const tooLow = source["status"] === "too_low_for_api_calls";
|
|
83
88
|
if (usd && balance !== null) {
|
|
@@ -97,17 +102,8 @@ export function moneyCells(document, options) {
|
|
|
97
102
|
if (!usd || spend === null || sample["month"] !== month)
|
|
98
103
|
continue;
|
|
99
104
|
const amount = mark + money(spend);
|
|
100
|
-
|
|
101
|
-
const cell = { plain: prefix + amount + suffix, prefix, amount: amount + suffix, band: budgetBand(spend, source["budgetUsd"]) };
|
|
102
|
-
if (provider === "openrouter") {
|
|
103
|
-
// One `or` cell at most: the most recently observed source wins, the first on a tie.
|
|
104
|
-
const observedAt = Date.parse(String(sample["observedAt"]));
|
|
105
|
-
if (openRouter !== undefined && observedAt <= openRouter.observedAt)
|
|
106
|
-
continue;
|
|
107
|
-
openRouter = { cell, observedAt };
|
|
108
|
-
}
|
|
109
|
-
cells.push(cell);
|
|
105
|
+
cells.push({ plain: prefix + amount, prefix, amount, band: budgetBand(spend, source["budgetUsd"]) });
|
|
110
106
|
}
|
|
111
|
-
return cells
|
|
107
|
+
return cells;
|
|
112
108
|
}
|
|
113
109
|
//# sourceMappingURL=api-spend.js.map
|
package/dist/api-spend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-spend.js","sourceRoot":"","sources":["../src/api-spend.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAExE;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEvD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,UAAU,GAAqC;IAC1D,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,GAAG,EAAE,IAAI;IACT,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;CACf,CAAC;AAEF,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,cAAsB;IACvD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC1G,OAAO,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;
|
|
1
|
+
{"version":3,"file":"api-spend.js","sourceRoot":"","sources":["../src/api-spend.ts"],"names":[],"mappings":"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"}
|
package/dist/bin.js
CHANGED
|
@@ -4,20 +4,6 @@ import { HOOK_INPUT_MAX_BYTES } from "@openlimiter/adapters";
|
|
|
4
4
|
import { runCli, runtimeDependencies } from "./cli.js";
|
|
5
5
|
import { readStandardInputBuffer, readStandardInputText } from "./ingest.js";
|
|
6
6
|
import { decodeWrappedStatuslineCommand, runStatuslineWrapper } from "./statusline-wrapper.js";
|
|
7
|
-
async function promptForSecret() {
|
|
8
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
9
|
-
return "";
|
|
10
|
-
const interfaceHandle = createInterface({
|
|
11
|
-
input: process.stdin,
|
|
12
|
-
output: process.stdout
|
|
13
|
-
});
|
|
14
|
-
try {
|
|
15
|
-
return await interfaceHandle.question("OpenRouter key: ");
|
|
16
|
-
}
|
|
17
|
-
finally {
|
|
18
|
-
interfaceHandle.close();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
7
|
async function promptChoice(question) {
|
|
22
8
|
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
23
9
|
return "";
|
|
@@ -90,8 +76,8 @@ else {
|
|
|
90
76
|
process.on("SIGINT", onInterrupt);
|
|
91
77
|
const result = await runCli(argumentsList, {
|
|
92
78
|
...runtime,
|
|
93
|
-
promptForSecret,
|
|
94
79
|
promptChoice,
|
|
80
|
+
interactive: process.stdin.isTTY === true && process.stdout.isTTY === true,
|
|
95
81
|
...(controller === null ? {} : { interruptSignal: controller.signal }),
|
|
96
82
|
readStandardInput: async (signal) => argumentsList[0] === "event"
|
|
97
83
|
? (await import("./activity/event.js")).readEventInput(signal)
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,8BAA8B,EAC9B,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AAEjC,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type AcquisitionSpec, type AcquisitionTransport, type CredentialCommandRunner, type DetachedSpawn, type ProviderFailure, type Snapshot } from "@openlimiter/core";
|
|
2
2
|
import { type AgentId, type AgentInstallation, type HostedContextTrust, type HostedTrustLoadOptions } from "@openlimiter/adapters";
|
|
3
3
|
import { type ProvidersConfig } from "./config.js";
|
|
4
4
|
import { type CredentialStore } from "./credentials.js";
|
|
@@ -8,7 +8,8 @@ export interface CliDependencies {
|
|
|
8
8
|
environment: Readonly<Record<string, string | undefined>>;
|
|
9
9
|
stateDirectory?: string;
|
|
10
10
|
credentialStore: CredentialStore;
|
|
11
|
-
|
|
11
|
+
/** Legacy injection is accepted for in process callers, but init never prompts. */
|
|
12
|
+
promptForSecret?: () => Promise<string>;
|
|
12
13
|
now: () => string;
|
|
13
14
|
payloads: Readonly<Record<string, unknown>>;
|
|
14
15
|
/**
|
|
@@ -62,30 +63,16 @@ export interface CliDependencies {
|
|
|
62
63
|
/**
|
|
63
64
|
* How the Windows Credential Manager is asked for one entry.
|
|
64
65
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
66
|
+
* This remains injectable so terminal shell discovery never touches a real
|
|
67
|
+
* user profile in tests.
|
|
67
68
|
*/
|
|
68
69
|
windowsCredentialRunner?: CredentialCommandRunner;
|
|
69
|
-
/**
|
|
70
|
-
* Probe running Antigravity instances on loopback ports.
|
|
71
|
-
*
|
|
72
|
-
* Reaches nothing by default in tests. The real executable injects the real
|
|
73
|
-
* loopback probe.
|
|
74
|
-
*/
|
|
75
|
-
probeAntigravity?: (options?: AntigravityProbeOptions) => Promise<AntigravityProbeResult>;
|
|
76
|
-
/**
|
|
77
|
-
* Turn a pid the Antigravity probe found listening into the executable path
|
|
78
|
-
* it checks against the trusted install roots.
|
|
79
|
-
*
|
|
80
|
-
* Reaches nothing by default in tests, exactly like `probeAntigravity`
|
|
81
|
-
* above: an unresolved pid is a pid the probe skips, never one it trusts on
|
|
82
|
-
* a bare process name. The real executable injects `resolveAgyExecutablePath`.
|
|
83
|
-
*/
|
|
84
|
-
resolveExecutablePath?: (pid: string) => Promise<string | null>;
|
|
85
70
|
/**
|
|
86
71
|
* Interactive prompt choice helper.
|
|
87
72
|
*/
|
|
88
73
|
promptChoice?: (question: string) => Promise<string>;
|
|
74
|
+
/** True only when both terminal input and output can answer a question. */
|
|
75
|
+
interactive?: boolean;
|
|
89
76
|
/**
|
|
90
77
|
* How a hub request leaves this machine.
|
|
91
78
|
*
|
|
@@ -149,7 +136,7 @@ export interface BrowserOpenInvocation {
|
|
|
149
136
|
}
|
|
150
137
|
/** Build a direct browser opener invocation without a command shell. */
|
|
151
138
|
export declare function browserOpenInvocation(url: string, platform: NodeJS.Platform, environment?: Readonly<Record<string, string | undefined>>): BrowserOpenInvocation | null;
|
|
152
|
-
export declare function runtimeDependencies(): Pick<CliDependencies, "acquisitionTransport" | "spawnDetached" | "windowsCredentialRunner" | "
|
|
139
|
+
export declare function runtimeDependencies(): Pick<CliDependencies, "acquisitionTransport" | "spawnDetached" | "windowsCredentialRunner" | "hubTransport" | "openBrowser" | "emit" | "windowsAclRunner" | "codexDeviceLoginRunnerFactory">;
|
|
153
140
|
export interface RefreshResult {
|
|
154
141
|
snapshots: Snapshot[];
|
|
155
142
|
/** Only genuine failures. A connector offered nothing is not one. */
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { ACQUISITION_OUTCOME_SENTENCE, captureStatuslineAccount, pruneSnapshotCache, ACQUISITION_PROVIDERS, registerManagedCodexAccount, CREDENTIAL_FAILURE_SENTENCE, PROVIDER_CODES, acquireRefreshLock, clearRefreshSpawnFailure, mergeAcquiredSnapshots, createFetchTransport, readRefreshSpawnFailure,
|
|
2
|
-
import { antigravityFixture, claudeFixture, codexFixture, grokFixture, kimiFixture, connectors, manualFixture, opencodeFixture, openrouterFixture,
|
|
3
|
-
import { AGENT_COMPATIBILITY, agentContextFromCache, agentContextSpillFromCache, agentVersionCompatibility, changeAgentHook, detectAgentInstallation, readAgentHookStatus, runAgentHook, validateAgentExecutableStamp, writeAgentContextSnapshot, loadHostedContextTrust,
|
|
1
|
+
import { ACQUISITION_OUTCOME_SENTENCE, captureStatuslineAccount, pruneSnapshotCache, ACQUISITION_PROVIDERS, registerManagedCodexAccount, CREDENTIAL_FAILURE_SENTENCE, PROVIDER_CODES, acquireRefreshLock, clearRefreshSpawnFailure, mergeAcquiredSnapshots, mergeAuthoritativeSnapshotCache, createFetchTransport, readRefreshSpawnFailure, buildAdvice, canonicalJson, claudeSpec, codexSpec, cursorSpec, dedupeFailures, desktopHoldsCache, failureFromConnectorReason, freshness, geminiCliSpec, grokSpec, isProviderDue, kimiSpec, mergeSnapshotCache, mergeSnapshots, normalizeMeters, normalizeMetersReport, openrouterSpec, readAcquisitionCredential, readAcquisitionSchedule, readSnapshotCache, readWindowsCredentialWith, resolveStateDirectory, runAcquisition, spawnDetachedRefresh, trustedHelperWorkingDirectory, writeAcquisitionSchedule, windowsSystemTool } from "@openlimiter/core";
|
|
2
|
+
import { antigravityFixture, claudeFixture, codexFixture, grokFixture, kimiFixture, connectors, manualFixture, opencodeFixture, openrouterFixture, parseAntigravityPayload, parseClaudePayload, parseCodexPayload, parseCursorPayload, parseGeminiCliPayload, parseGrokPayload, parseKimiPayload, parseManualPayload, parseOpencodePayload, parseOpenrouterPayload } from "@openlimiter/connectors";
|
|
3
|
+
import { AGENT_COMPATIBILITY, agentContextFromCache, agentContextSpillFromCache, agentVersionCompatibility, changeAgentHook, detectAgentInstallation, readAgentHookStatus, runAgentHook, validateAgentExecutableStamp, writeAgentContextSnapshot, loadHostedContextTrust, } from "@openlimiter/adapters";
|
|
4
4
|
import { execFile, spawn } from "node:child_process";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
import packageJson from "../package.json" with { type: "json" };
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
import { PROVIDER_KEYS, STATUSLINE_KEYS, defaultConfig, initialize, isProviderKey, isStatuslineKey, providerValueText, readConfig, readProvidersConfig, readStatuslineConfig, setProviderValue, setStatuslineValue, statuslineValueText
|
|
10
|
-
import { ACQUISITION_PROVENANCE, ANTIGRAVITY_STATUSLINE_PROVENANCE, GROK_STATUSLINE_PROVENANCE, INGEST_PROVENANCE, MANUAL_PROVENANCE, STATUSLINE_PROVENANCE, environmentWithLocalMarkers, STDIN_BYTE_LIMIT, parseAntigravityStatuslinePayload, parseGrokStatuslinePayload, parseJsonText, persistSnapshots, clearStatuslineFailure, readStatuslineFailure, recordStatuslineFailure, readManualDocument, withProvenance } from "./ingest.js";
|
|
9
|
+
import { PROVIDER_KEYS, STATUSLINE_KEYS, defaultConfig, initialize, isProviderKey, isStatuslineKey, providerValueText, readConfig, readProvidersConfig, readStatuslineConfig, setProviderValue, updateConfig, setStatuslineValue, statuslineValueText } from "./config.js";
|
|
10
|
+
import { ACQUISITION_PROVENANCE, ANTIGRAVITY_STATUSLINE_PROVENANCE, GROK_STATUSLINE_PROVENANCE, INGEST_PROVENANCE, MANUAL_PROVENANCE, STATUSLINE_PROVENANCE, environmentWithLocalMarkers, STDIN_BYTE_LIMIT, parseAntigravityStatuslinePayload, antigravityStatuslineAccount, parseGrokStatuslinePayload, parseJsonText, persistSnapshots, clearStatuslineFailure, readStatuslineFailure, recordStatuslineFailure, readManualDocument, withProvenance } from "./ingest.js";
|
|
11
11
|
import { UnavailableCredentialStore } from "./credentials.js";
|
|
12
12
|
import { failureLine, failureLines, renderTable, supportsColor } from "./render.js";
|
|
13
|
-
import { isStatuslineHost, renderStatuslineLayout, statuslineColor, statuslineUnicode } from "./statusline.js";
|
|
13
|
+
import { isStatuslineHost, HOST_PROVIDER, renderPlainStatusline, renderStatuslineLayout, resolveProviderOrder, statuslineColor, statuslineUnicode } from "./statusline.js";
|
|
14
14
|
import { parseStatuslineSession } from "./statusline-ingest.js";
|
|
15
15
|
import { readApiSpend } from "./api-spend.js";
|
|
16
|
-
import { TERMINAL_HOST_NAMES, installHost, terminalHide, terminalShow, terminalStatusTable, uninstallHost } from "./terminal.js";
|
|
16
|
+
import { TERMINAL_HOST_NAMES, installHost, terminalHide, terminalShow, terminalStatusTable, uninstallHost, hostStatus } from "./terminal.js";
|
|
17
|
+
import { installLauncher } from "./terminal-launcher.js";
|
|
17
18
|
import { createFetchHubTransport, hubConfigured } from "./hub.js";
|
|
18
19
|
import { DELIVERY_UNCONFIRMED_SENTENCE, REVOKED_SENTENCE, ensureFreshSession, isAborted, runDeviceLogin } from "./hub-auth.js";
|
|
19
20
|
import { runSync, syncIsDue, recordSyncAttempt } from "./hub-sync.js";
|
|
@@ -28,7 +29,6 @@ function defaults() {
|
|
|
28
29
|
return {
|
|
29
30
|
environment: process.env,
|
|
30
31
|
credentialStore: new UnavailableCredentialStore(),
|
|
31
|
-
promptForSecret: async () => "",
|
|
32
32
|
now: () => new Date().toISOString(),
|
|
33
33
|
payloads: {},
|
|
34
34
|
readStandardInput: async () => null,
|
|
@@ -49,8 +49,8 @@ function defaults() {
|
|
|
49
49
|
throw new Error("No acquisition transport was injected");
|
|
50
50
|
},
|
|
51
51
|
spawnDetached: () => undefined,
|
|
52
|
-
probeAntigravity: async () => ({ ok: false, reason: "not_running" }),
|
|
53
52
|
promptChoice: async () => "",
|
|
53
|
+
interactive: false,
|
|
54
54
|
hubTransport: async () => {
|
|
55
55
|
throw new Error("No hub transport was injected");
|
|
56
56
|
},
|
|
@@ -169,11 +169,6 @@ function openBrowserPlatform(url, platform) {
|
|
|
169
169
|
export function runtimeDependencies() {
|
|
170
170
|
return {
|
|
171
171
|
acquisitionTransport: createFetchTransport(),
|
|
172
|
-
probeAntigravity: (options) => probeAntigravity({
|
|
173
|
-
...options,
|
|
174
|
-
runCommand: options?.runCommand ?? execFileRunner
|
|
175
|
-
}),
|
|
176
|
-
resolveExecutablePath: resolveAgyExecutablePath,
|
|
177
172
|
spawnDetached: (executable, argumentsList, options) => {
|
|
178
173
|
const child = spawn(executable, [...argumentsList], {
|
|
179
174
|
cwd: options.cwd,
|
|
@@ -320,11 +315,13 @@ async function refresh(dependencies, now) {
|
|
|
320
315
|
*/
|
|
321
316
|
export function acquisitionSpecs(providers) {
|
|
322
317
|
return [
|
|
323
|
-
claudeSpec({
|
|
318
|
+
claudeSpec({
|
|
319
|
+
parse: parseClaudePayload,
|
|
320
|
+
enabled: providers.claude.recorded && providers.claude.poll
|
|
321
|
+
}),
|
|
324
322
|
codexSpec(parseCodexPayload),
|
|
325
323
|
cursorSpec(parseCursorPayload),
|
|
326
324
|
geminiCliSpec(parseGeminiCliPayload),
|
|
327
|
-
antigravitySpec(parseAntigravityCodeAssistPayload),
|
|
328
325
|
grokSpec(parseGrokPayload),
|
|
329
326
|
kimiSpec(parseKimiPayload),
|
|
330
327
|
openrouterSpec(parseOpenrouterPayload)
|
|
@@ -369,7 +366,7 @@ function credentialReader(dependencies) {
|
|
|
369
366
|
}
|
|
370
367
|
};
|
|
371
368
|
}
|
|
372
|
-
|
|
369
|
+
const result = await readAcquisitionCredential(provider, {
|
|
373
370
|
...(dependencies.stateDirectory === undefined ? {} : { stateDirectory: dependencies.stateDirectory }),
|
|
374
371
|
platform: dependencies.platform,
|
|
375
372
|
environment: dependencies.environment,
|
|
@@ -381,6 +378,26 @@ function credentialReader(dependencies) {
|
|
|
381
378
|
readWindowsCredential: async (target) => await readWindowsCredentialWith(target, { runCommand: runner })
|
|
382
379
|
})
|
|
383
380
|
});
|
|
381
|
+
if (provider !== "CODEX" || !result.ok)
|
|
382
|
+
return result;
|
|
383
|
+
const installation = Object.prototype.hasOwnProperty.call(dependencies.detectedAgentInstallations, "codex")
|
|
384
|
+
? dependencies.detectedAgentInstallations.codex ?? null
|
|
385
|
+
: await detectAgentInstallation("codex", {
|
|
386
|
+
environment: dependencies.environment,
|
|
387
|
+
platform: dependencies.platform,
|
|
388
|
+
runCommand: async (executable, argumentsList, timeoutMilliseconds) => {
|
|
389
|
+
const command = await execFileRunner(executable, argumentsList, timeoutMilliseconds);
|
|
390
|
+
return command.ok
|
|
391
|
+
? { ok: true, stdout: command.stdout, stderr: "" }
|
|
392
|
+
: command;
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
if (installation === null)
|
|
396
|
+
return { ok: false, reason: "absent" };
|
|
397
|
+
return {
|
|
398
|
+
ok: true,
|
|
399
|
+
credential: { ...result.credential, executable: installation.executable }
|
|
400
|
+
};
|
|
384
401
|
};
|
|
385
402
|
}
|
|
386
403
|
/**
|
|
@@ -489,27 +506,9 @@ async function acquisitionDoctorRows(dependencies, snapshots, now) {
|
|
|
489
506
|
}
|
|
490
507
|
return [ACQUISITION_HEADER, ...rows].join(NEWLINE);
|
|
491
508
|
}
|
|
492
|
-
/**
|
|
493
|
-
* Where a person can still see a reading this row could not take.
|
|
494
|
-
*
|
|
495
|
-
* Antigravity and Gemini CLI meter the same Google Code Assist pool. When
|
|
496
|
-
* Google withholds the reading from this client but another tool on the machine
|
|
497
|
-
* has already written one, the honest thing is to point at it rather than leave
|
|
498
|
-
* a bare refusal, so the person knows the number exists and where.
|
|
499
|
-
*/
|
|
500
|
-
function sharedQuotaNote(row, snapshots) {
|
|
501
|
-
if (row.provider !== "ANTIGRAVITY")
|
|
502
|
-
return null;
|
|
503
|
-
return snapshots.some((snapshot) => snapshot.provider === "GEMINI_CLI")
|
|
504
|
-
? "the shared Code Assist quota is shown under gemini_cli"
|
|
505
|
-
: null;
|
|
506
|
-
}
|
|
507
509
|
/** One row of the refresh report, in the space separated grammar doctor uses. */
|
|
508
|
-
function acquisitionLine(row,
|
|
509
|
-
const
|
|
510
|
-
const note = [row.reason ?? row.disclosure ?? "", shared ?? ""]
|
|
511
|
-
.filter((part) => part !== "")
|
|
512
|
-
.join(", ");
|
|
510
|
+
function acquisitionLine(row, _snapshots = []) {
|
|
511
|
+
const note = row.reason ?? row.disclosure ?? "";
|
|
513
512
|
return [
|
|
514
513
|
row.provider.toLowerCase(),
|
|
515
514
|
row.detected ? "yes" : "no",
|
|
@@ -560,13 +559,7 @@ async function refreshCommand(dependencies, now) {
|
|
|
560
559
|
now,
|
|
561
560
|
schedule,
|
|
562
561
|
readCredential: credentialReader(dependencies),
|
|
563
|
-
stamp: acquisitionStamp
|
|
564
|
-
...(dependencies.probeAntigravity === undefined
|
|
565
|
-
? {}
|
|
566
|
-
: { probeAntigravity: dependencies.probeAntigravity }),
|
|
567
|
-
...(dependencies.resolveExecutablePath === undefined
|
|
568
|
-
? {}
|
|
569
|
-
: { resolveExecutablePath: dependencies.resolveExecutablePath })
|
|
562
|
+
stamp: acquisitionStamp
|
|
570
563
|
});
|
|
571
564
|
/*
|
|
572
565
|
* Ownership is checked before every write, not once at the start. A round
|
|
@@ -588,7 +581,14 @@ async function refreshCommand(dependencies, now) {
|
|
|
588
581
|
if (!report.ok)
|
|
589
582
|
continue;
|
|
590
583
|
try {
|
|
591
|
-
|
|
584
|
+
const pollRows = report.snapshots.filter((row) => row.provider === "CLAUDE" && row.meter.startsWith("SEVEN_DAY"));
|
|
585
|
+
if (pollRows.length > 0) {
|
|
586
|
+
await mergeAuthoritativeSnapshotCache(pollRows, dependencies.stateDirectory, now);
|
|
587
|
+
}
|
|
588
|
+
await mergeAcquiredSnapshots({
|
|
589
|
+
...report,
|
|
590
|
+
snapshots: report.snapshots.filter((row) => !pollRows.includes(row))
|
|
591
|
+
}, dependencies.stateDirectory);
|
|
592
592
|
}
|
|
593
593
|
catch {
|
|
594
594
|
/* One provider's write failing is that provider's problem. The rest of
|
|
@@ -752,12 +752,15 @@ async function ingestStandardInput(dependencies, now, host = "claude") {
|
|
|
752
752
|
if (host === "codex" || host === "shell")
|
|
753
753
|
return null;
|
|
754
754
|
try {
|
|
755
|
-
const
|
|
755
|
+
const accountIdBeforePayload = host === "antigravity" ? null : await captureStatuslineAccount(host === "grok" ? "GROK" : "CLAUDE", {
|
|
756
756
|
environment: dependencies.environment, homeDirectory: dependencies.homeDirectory, platform: dependencies.platform, ...(dependencies.stateDirectory ? { stateDirectory: dependencies.stateDirectory } : {}), now
|
|
757
757
|
});
|
|
758
758
|
const document = parseJsonText(await dependencies.readStandardInput());
|
|
759
759
|
if (!document.ok)
|
|
760
760
|
return null;
|
|
761
|
+
const accountId = host === "antigravity"
|
|
762
|
+
? antigravityStatuslineAccount(document.value)
|
|
763
|
+
: accountIdBeforePayload;
|
|
761
764
|
const meters = host === "antigravity"
|
|
762
765
|
? parseAntigravityStatuslinePayload(document.value, now)
|
|
763
766
|
: host === "grok"
|
|
@@ -803,12 +806,19 @@ async function ingestStandardInput(dependencies, now, host = "claude") {
|
|
|
803
806
|
async function initCommand(dependencies) {
|
|
804
807
|
const environment = await environmentWithLocalMarkers(dependencies.environment, dependencies.stateDirectory);
|
|
805
808
|
try {
|
|
806
|
-
|
|
809
|
+
if (!(await ensureClaudePollChoice(dependencies))) {
|
|
810
|
+
return fail(EXIT_FAILURE, "openlimiter init: configuration could not be written, so Claude usage stays off.");
|
|
811
|
+
}
|
|
812
|
+
const result = await initialize(environment, dependencies.credentialStore, dependencies.stateDirectory);
|
|
807
813
|
const detected = result.config.connectors
|
|
808
814
|
.filter((connector) => connector.detected)
|
|
809
815
|
.map((connector) => connector.id)
|
|
810
816
|
.join(",");
|
|
811
|
-
|
|
817
|
+
const openrouterNotice = environment["OPENLIMITER_OPENROUTER_KEY"] !== undefined &&
|
|
818
|
+
!result.credentialStored
|
|
819
|
+
? " OpenRouter: set OPENLIMITER_OPENROUTER_KEY in your shell for the key allowance cell, or add the key in the desktop app."
|
|
820
|
+
: "";
|
|
821
|
+
return succeed("Configuration saved. Detected: " + (detected === "" ? "none" : detected) + openrouterNotice);
|
|
812
822
|
}
|
|
813
823
|
catch {
|
|
814
824
|
return fail(EXIT_FAILURE, "openlimiter init: configuration could not be written.");
|
|
@@ -1000,7 +1010,10 @@ async function statuslineCommand(dependencies, argumentsList, now) {
|
|
|
1000
1010
|
? hostFlag.toLowerCase()
|
|
1001
1011
|
: "claude";
|
|
1002
1012
|
const ingested = await ingestStandardInput(dependencies, now, host);
|
|
1003
|
-
const
|
|
1013
|
+
const cached = await cachedSnapshots(dependencies.stateDirectory);
|
|
1014
|
+
const snapshots = ingested?.snapshots === null || ingested === null
|
|
1015
|
+
? cached
|
|
1016
|
+
: mergeSnapshots(cached, ingested.snapshots);
|
|
1004
1017
|
/*
|
|
1005
1018
|
* The refresh that keeps the other providers current starts here and is never
|
|
1006
1019
|
* waited for. This render draws whatever the cache already holds, the child
|
|
@@ -1013,8 +1026,16 @@ async function statuslineCommand(dependencies, argumentsList, now) {
|
|
|
1013
1026
|
}
|
|
1014
1027
|
const advice = buildAdvice(snapshots, now, PROVIDER_CODES);
|
|
1015
1028
|
const config = await readStatuslineConfig(dependencies.stateDirectory);
|
|
1016
|
-
|
|
1017
|
-
|
|
1029
|
+
const providers = await readProvidersConfig(dependencies.stateDirectory);
|
|
1030
|
+
const weeklyFresh = snapshots.some((snapshot) => snapshot.provider === "CLAUDE" && snapshot.meter.startsWith("SEVEN_DAY") &&
|
|
1031
|
+
freshness(snapshot.observedAt, snapshot.expiresAt, now) === "fresh");
|
|
1032
|
+
const hasClaudeReading = snapshots.some((snapshot) => snapshot.provider === "CLAUDE");
|
|
1033
|
+
const pollHint = host === "claude" && hasClaudeReading && !weeklyFresh
|
|
1034
|
+
? providers.claude.poll ? "7d poll pending" : "7d poll off"
|
|
1035
|
+
: undefined;
|
|
1036
|
+
if (!config.bars) {
|
|
1037
|
+
return succeed(renderPlainStatusline(advice, snapshots, now, resolveProviderOrder(config.order), config.meters, pollHint, HOST_PROVIDER[host]));
|
|
1038
|
+
}
|
|
1018
1039
|
return succeed(renderStatuslineLayout({
|
|
1019
1040
|
advice,
|
|
1020
1041
|
snapshots,
|
|
@@ -1024,7 +1045,8 @@ async function statuslineCommand(dependencies, argumentsList, now) {
|
|
|
1024
1045
|
apiSpend: await readApiSpend(dependencies.stateDirectory ?? resolveStateDirectory()),
|
|
1025
1046
|
color: statuslineColor(config.color, dependencies.environment, dependencies.colorOutput, host),
|
|
1026
1047
|
unicode: statuslineUnicode(dependencies.environment),
|
|
1027
|
-
host
|
|
1048
|
+
host,
|
|
1049
|
+
...(pollHint === undefined ? {} : { pollHint })
|
|
1028
1050
|
}));
|
|
1029
1051
|
}
|
|
1030
1052
|
const agentAliases = {
|
|
@@ -1261,7 +1283,10 @@ async function providersConfigCommand(dependencies, action, key, value) {
|
|
|
1261
1283
|
if (!update.ok)
|
|
1262
1284
|
return fail(EXIT_USAGE, "openlimiter config: " + update.message);
|
|
1263
1285
|
try {
|
|
1264
|
-
await
|
|
1286
|
+
await updateConfig((latest) => {
|
|
1287
|
+
const next = setProviderValue(latest.providers, key, value);
|
|
1288
|
+
return { ...latest, providers: next.ok ? next.providers : update.providers };
|
|
1289
|
+
}, dependencies.environment, dependencies.stateDirectory);
|
|
1265
1290
|
}
|
|
1266
1291
|
catch {
|
|
1267
1292
|
return fail(EXIT_FAILURE, "openlimiter config: configuration could not be written.");
|
|
@@ -1316,7 +1341,10 @@ async function configCommand(dependencies, argumentsList) {
|
|
|
1316
1341
|
if (!update.ok)
|
|
1317
1342
|
return fail(EXIT_USAGE, "openlimiter config: " + update.message);
|
|
1318
1343
|
try {
|
|
1319
|
-
await
|
|
1344
|
+
await updateConfig((latest) => {
|
|
1345
|
+
const next = setStatuslineValue(latest.statusline, target.key, value);
|
|
1346
|
+
return { ...latest, statusline: next.ok ? next.statusline : update.statusline };
|
|
1347
|
+
}, dependencies.environment, dependencies.stateDirectory);
|
|
1320
1348
|
}
|
|
1321
1349
|
catch {
|
|
1322
1350
|
return fail(EXIT_FAILURE, "openlimiter config: configuration could not be written.");
|
|
@@ -1595,10 +1623,39 @@ async function triggerSyncAfterRefresh(dependencies, now) {
|
|
|
1595
1623
|
}
|
|
1596
1624
|
/* -------------------------------------------------------------- setup */
|
|
1597
1625
|
const SETUP_SIGN_IN_PROMPT = "Sign in to sync your bars to the hub and your phone (free)";
|
|
1626
|
+
const CLAUDE_POLL_DISCLOSURE = "OpenLimiter can read the same usage Claude shows by sending a direct usage request with your Claude sign in on this computer. Anthropic's policy for tools like this is unresolved.";
|
|
1627
|
+
const CLAUDE_POLL_QUESTION = "Show Fable limit? Enter to turn it on, N to keep it off: ";
|
|
1598
1628
|
async function promptOrSkip(dependencies, question) {
|
|
1629
|
+
if (!dependencies.interactive)
|
|
1630
|
+
return false;
|
|
1599
1631
|
const answer = await dependencies.promptChoice?.(question) ?? "";
|
|
1600
1632
|
return !answer.trim().toLowerCase().startsWith("s");
|
|
1601
1633
|
}
|
|
1634
|
+
/** Record one real Claude polling choice before any terminal acquisition. */
|
|
1635
|
+
async function ensureClaudePollChoice(dependencies) {
|
|
1636
|
+
const stored = await readConfig(dependencies.stateDirectory);
|
|
1637
|
+
if (!stored.ok && stored.reason !== "missing")
|
|
1638
|
+
return false;
|
|
1639
|
+
const config = stored.ok ? stored.config : defaultConfig(dependencies.environment);
|
|
1640
|
+
if (config.providers.claude.recorded)
|
|
1641
|
+
return true;
|
|
1642
|
+
let enabled = false;
|
|
1643
|
+
if (dependencies.interactive) {
|
|
1644
|
+
dependencies.emit(CLAUDE_POLL_DISCLOSURE);
|
|
1645
|
+
const answer = await dependencies.promptChoice?.(CLAUDE_POLL_QUESTION) ?? "n";
|
|
1646
|
+
enabled = !answer.trim().toLowerCase().startsWith("n");
|
|
1647
|
+
}
|
|
1648
|
+
try {
|
|
1649
|
+
await updateConfig((latest) => ({
|
|
1650
|
+
...latest,
|
|
1651
|
+
providers: { claude: { poll: enabled, recorded: true } }
|
|
1652
|
+
}), dependencies.environment, dependencies.stateDirectory);
|
|
1653
|
+
return true;
|
|
1654
|
+
}
|
|
1655
|
+
catch {
|
|
1656
|
+
return false;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1602
1659
|
/** Step one: sign in, or say plainly why this machine did not. */
|
|
1603
1660
|
async function setupSignInStep(dependencies) {
|
|
1604
1661
|
const lines = ["1. Sign in", SETUP_SIGN_IN_PROMPT];
|
|
@@ -1653,7 +1710,6 @@ const AGENT_CREDENTIAL_PROVIDER = {
|
|
|
1653
1710
|
codex: "CODEX",
|
|
1654
1711
|
cursor: "CURSOR",
|
|
1655
1712
|
gemini: "GEMINI_CLI",
|
|
1656
|
-
antigravity: "ANTIGRAVITY",
|
|
1657
1713
|
grok: "GROK",
|
|
1658
1714
|
kimi: "KIMI"
|
|
1659
1715
|
};
|
|
@@ -1667,9 +1723,12 @@ const CONNECT_ROW_LABEL = {
|
|
|
1667
1723
|
use_current_login: "use current login",
|
|
1668
1724
|
sign_in: "sign in",
|
|
1669
1725
|
install: "install",
|
|
1670
|
-
verified_on_install: "verified on install"
|
|
1726
|
+
verified_on_install: "verified on install",
|
|
1727
|
+
status_line: "reads its status line, wire it in step 3"
|
|
1671
1728
|
};
|
|
1672
1729
|
async function connectRowState(agent, installed, readCredential) {
|
|
1730
|
+
if (agent === "antigravity")
|
|
1731
|
+
return "status_line";
|
|
1673
1732
|
if (installed === null) {
|
|
1674
1733
|
return UNVERIFIED_DEVICE_LOGIN_AGENTS.has(agent) ? "verified_on_install" : "install";
|
|
1675
1734
|
}
|
|
@@ -1797,7 +1856,16 @@ async function setupShowBarsStep(dependencies) {
|
|
|
1797
1856
|
const result = await terminalCommand(dependencies, ["terminal"]);
|
|
1798
1857
|
const lines = ["3. Show bars in", result.stdout];
|
|
1799
1858
|
lines.forEach(dependencies.emit);
|
|
1859
|
+
const detected = await detectedProviderIds(dependencies);
|
|
1860
|
+
const context = terminalContext(dependencies, detected);
|
|
1800
1861
|
for (const host of TERMINAL_HOST_NAMES) {
|
|
1862
|
+
if (host !== "codex" && await hostStatus(host, context) === "Wired") {
|
|
1863
|
+
await installLauncher(context.stateDirectory ?? path.join(context.homeDirectory, ".openlimiter"));
|
|
1864
|
+
const line = host + ": already wired, status line runtime updated.";
|
|
1865
|
+
lines.push(line);
|
|
1866
|
+
dependencies.emit(line);
|
|
1867
|
+
continue;
|
|
1868
|
+
}
|
|
1801
1869
|
if (await promptOrSkip(dependencies, host + ": Enter to install, S to skip: ")) {
|
|
1802
1870
|
const installed = await terminalCommand(dependencies, ["terminal", "install", host]);
|
|
1803
1871
|
lines.push(installed.stdout || installed.stderr);
|
|
@@ -1813,6 +1881,9 @@ async function setupShowBarsStep(dependencies) {
|
|
|
1813
1881
|
async function setupCommand(dependencies, now) {
|
|
1814
1882
|
await setupSignInStep(dependencies);
|
|
1815
1883
|
await setupConnectStep(dependencies);
|
|
1884
|
+
if (!(await ensureClaudePollChoice(dependencies))) {
|
|
1885
|
+
dependencies.emit("Claude usage stays off because the choice could not be saved.");
|
|
1886
|
+
}
|
|
1816
1887
|
const collected = await refreshCommand(dependencies, now);
|
|
1817
1888
|
if (collected.exitCode !== 0 && collected.stderr !== "")
|
|
1818
1889
|
dependencies.emit(collected.stderr);
|
|
@@ -1824,9 +1895,11 @@ async function setupCommand(dependencies, now) {
|
|
|
1824
1895
|
export async function runCli(argumentsList, overrides = {}) {
|
|
1825
1896
|
const setupOutput = [];
|
|
1826
1897
|
const hasOutputSink = overrides.emit !== undefined;
|
|
1898
|
+
const interactive = overrides.interactive ?? overrides.promptChoice !== undefined;
|
|
1827
1899
|
const dependencies = {
|
|
1828
1900
|
...defaults(),
|
|
1829
1901
|
...overrides,
|
|
1902
|
+
interactive,
|
|
1830
1903
|
...(hasOutputSink ? {} : { emit: (line) => setupOutput.push(line) })
|
|
1831
1904
|
};
|
|
1832
1905
|
const command = argumentsList[0] ?? "setup";
|