@phnx-labs/agents-cli 1.22.45 → 1.22.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +303 -0
- package/LICENSE +102 -182
- package/README.md +54 -17
- package/dist/cli/command-registry.d.ts +2 -1
- package/dist/cli/command-registry.js +6 -2
- package/dist/commands/accounts.js +56 -12
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +229 -0
- package/dist/commands/browser-sessions-picker.js +9 -7
- package/dist/commands/browser.js +266 -15
- package/dist/commands/config.js +26 -4
- package/dist/commands/cost.d.ts +1 -1
- package/dist/commands/detach.d.ts +13 -0
- package/dist/commands/detach.js +11 -8
- package/dist/commands/exec.js +55 -38
- package/dist/commands/feed-watch.d.ts +2 -0
- package/dist/commands/feed-watch.js +28 -0
- package/dist/commands/feed.js +27 -0
- package/dist/commands/feedback.js +3 -19
- package/dist/commands/insights.d.ts +1 -1
- package/dist/commands/insights.js +2 -2
- package/dist/commands/lease.js +3 -3
- package/dist/commands/routines.js +1 -1
- package/dist/commands/sessions-picker-factory.d.ts +2 -1
- package/dist/commands/sessions-picker-factory.js +1 -1
- package/dist/commands/sessions-stop.d.ts +24 -0
- package/dist/commands/sessions-stop.js +66 -0
- package/dist/commands/sessions-trace.d.ts +82 -0
- package/dist/commands/sessions-trace.js +387 -0
- package/dist/commands/sessions.js +4 -0
- package/dist/commands/ssh.d.ts +15 -0
- package/dist/commands/ssh.js +194 -16
- package/dist/commands/teams.js +34 -2
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +19 -32
- package/dist/commands/watchdog.js +9 -14
- package/dist/lib/account-capabilities.d.ts +4 -0
- package/dist/lib/account-capabilities.js +13 -9
- package/dist/lib/account-registry.d.ts +2 -0
- package/dist/lib/account-registry.js +30 -2
- package/dist/lib/accounting/rotate.d.ts +9 -0
- package/dist/lib/accounting/rotate.js +12 -2
- package/dist/lib/accounting/usage.d.ts +92 -6
- package/dist/lib/accounting/usage.js +329 -75
- package/dist/lib/agent-modes.js +29 -1
- package/dist/lib/agent-spec/agents.d.ts +4 -3
- package/dist/lib/agent-spec/agents.js +20 -7
- package/dist/lib/analytics/mix-commands.d.ts +1 -1
- package/dist/lib/analytics/mix-commands.js +2 -2
- package/dist/lib/auth-health.d.ts +13 -3
- package/dist/lib/auth-health.js +50 -8
- package/dist/lib/browser/devices.d.ts +19 -0
- package/dist/lib/browser/devices.js +23 -0
- package/dist/lib/browser/ipc.d.ts +1 -1
- package/dist/lib/browser/ipc.js +33 -7
- package/dist/lib/browser/profiles.d.ts +106 -1
- package/dist/lib/browser/profiles.js +300 -17
- package/dist/lib/browser/remote-control.d.ts +26 -2
- package/dist/lib/browser/remote-control.js +33 -3
- package/dist/lib/browser/runtime-state.d.ts +9 -0
- package/dist/lib/browser/runtime-state.js +24 -8
- package/dist/lib/browser/service.d.ts +37 -0
- package/dist/lib/browser/service.js +78 -20
- package/dist/lib/browser/sessions-list.d.ts +1 -3
- package/dist/lib/browser/sessions-list.js +3 -16
- package/dist/lib/browser/types.d.ts +12 -1
- package/dist/lib/cli-resources.js +17 -15
- package/dist/lib/codex-policy.d.ts +11 -1
- package/dist/lib/codex-policy.js +20 -5
- package/dist/lib/config-keys.d.ts +4 -3
- package/dist/lib/config-keys.js +17 -7
- package/dist/lib/daemon/runner.js +15 -2
- package/dist/lib/daemon-ticks.js +2 -2
- package/dist/lib/device-config.d.ts +25 -8
- package/dist/lib/device-config.js +90 -17
- package/dist/lib/devices/config-migration.d.ts +7 -0
- package/dist/lib/devices/config-migration.js +67 -3
- package/dist/lib/devices/harness-inventory.js +20 -3
- package/dist/lib/devices/health.d.ts +27 -2
- package/dist/lib/devices/health.js +39 -9
- package/dist/lib/devices/interactive-host.d.ts +15 -0
- package/dist/lib/devices/interactive-host.js +53 -0
- package/dist/lib/devices/registry.d.ts +61 -4
- package/dist/lib/devices/registry.js +94 -38
- package/dist/lib/devices/stats-cache.d.ts +6 -0
- package/dist/lib/devices/stats-cache.js +10 -2
- package/dist/lib/exec.d.ts +25 -3
- package/dist/lib/exec.js +75 -22
- package/dist/lib/feed/answer.d.ts +29 -0
- package/dist/lib/feed/answer.js +145 -0
- package/dist/lib/feed/attention.d.ts +83 -0
- package/dist/lib/feed/attention.js +0 -0
- package/dist/lib/feed/feed.d.ts +109 -0
- package/dist/lib/feed/feed.js +154 -3
- package/dist/lib/feed/pr-status.d.ts +14 -0
- package/dist/lib/feed/pr-status.js +47 -0
- package/dist/lib/feed/watch.d.ts +59 -0
- package/dist/lib/feed/watch.js +180 -0
- package/dist/lib/fleet/capture.js +6 -0
- package/dist/lib/fleet/remote-login.js +8 -3
- package/dist/lib/fleet/types.d.ts +17 -0
- package/dist/lib/harness/adapter.d.ts +11 -0
- package/dist/lib/harness/adapters/claude.js +38 -24
- package/dist/lib/harness/adapters/codex.js +2 -4
- package/dist/lib/hooks/cache.js +8 -0
- package/dist/lib/hooks/match.d.ts +3 -0
- package/dist/lib/hooks/match.js +25 -0
- package/dist/lib/hosts/passthrough.js +16 -0
- package/dist/lib/hosts/registry.js +7 -0
- package/dist/lib/identity/client.d.ts +53 -0
- package/dist/lib/identity/client.js +106 -0
- package/dist/lib/identity/index.d.ts +115 -0
- package/dist/lib/identity/index.js +82 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/install-menubar.d.ts +13 -0
- package/dist/lib/menubar/install-menubar.js +26 -2
- package/dist/lib/open-url.d.ts +60 -2
- package/dist/lib/open-url.js +167 -12
- package/dist/lib/probe.d.ts +8 -0
- package/dist/lib/probe.js +105 -0
- package/dist/lib/refresh-coordinator.d.ts +1 -1
- package/dist/lib/refresh-coordinator.js +1 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +2 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +13 -1
- package/dist/lib/session/active.d.ts +67 -0
- package/dist/lib/session/active.js +69 -1
- package/dist/lib/session/db.js +4 -2
- package/dist/lib/session/discover.d.ts +2 -0
- package/dist/lib/session/discover.js +12 -6
- package/dist/lib/session/prompt.d.ts +35 -0
- package/dist/lib/session/prompt.js +56 -0
- package/dist/lib/session/remote/watch.d.ts +1 -1
- package/dist/lib/session/remote/watch.js +6 -1
- package/dist/lib/session/render.js +7 -3
- package/dist/lib/session/session-cache.js +5 -1
- package/dist/lib/session/trajectory-compare.d.ts +47 -0
- package/dist/lib/session/trajectory-compare.js +116 -0
- package/dist/lib/session/trajectory-html.d.ts +15 -0
- package/dist/lib/session/trajectory-html.js +750 -0
- package/dist/lib/session/trajectory-lineage.d.ts +92 -0
- package/dist/lib/session/trajectory-lineage.js +195 -0
- package/dist/lib/session/trajectory-text.d.ts +37 -0
- package/dist/lib/session/trajectory-text.js +277 -0
- package/dist/lib/session/trajectory.d.ts +102 -0
- package/dist/lib/session/trajectory.js +335 -0
- package/dist/lib/startup/command-registry.d.ts +5 -2
- package/dist/lib/startup/command-registry.js +8 -5
- package/dist/lib/state.d.ts +1 -1
- package/dist/lib/state.js +4 -2
- package/dist/lib/teams/agents.js +9 -0
- package/dist/lib/terminal/inject.d.ts +19 -0
- package/dist/lib/terminal/inject.js +19 -9
- package/dist/lib/tmux/session.d.ts +46 -13
- package/dist/lib/tmux/session.js +173 -27
- package/dist/lib/types.d.ts +16 -0
- package/dist/lib/usage-backoff.d.ts +2 -1
- package/dist/lib/usage-backoff.js +60 -19
- package/dist/lib/usage-refresh.d.ts +17 -3
- package/dist/lib/usage-refresh.js +57 -11
- package/dist/lib/view-types.d.ts +2 -2
- package/dist/lib/watchdog/log.d.ts +1 -1
- package/dist/lib/watchdog/log.js +1 -1
- package/dist/lib/watchdog/runner.d.ts +36 -45
- package/dist/lib/watchdog/runner.js +150 -119
- package/dist/lib/watchdog/service.d.ts +0 -1
- package/dist/lib/watchdog/service.js +0 -1
- package/dist/lib/watchdog/watchdog-agent.d.ts +38 -0
- package/dist/lib/watchdog/watchdog-agent.js +59 -0
- package/dist/lib/watchdog/watchdog.d.ts +11 -2
- package/dist/lib/watchdog/watchdog.js +37 -104
- package/package.json +2 -2
- package/dist/commands/usage.d.ts +0 -27
- package/dist/commands/usage.js +0 -96
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
/** Native-login selector coverage required by RUSH-3053. */
|
|
2
|
+
export const NATIVE_ACCOUNT_SELECTOR_AGENTS = ['claude', 'codex', 'cursor', 'grok', 'kimi'];
|
|
3
|
+
/** Explicit dispositions for config-isolated harnesses outside that selector. */
|
|
4
|
+
export const NATIVE_ACCOUNT_SELECTOR_EXCLUSIONS = {
|
|
5
|
+
copilot: 'no inspectable native identity',
|
|
6
|
+
opencode: 'provider-set identity is not safely attributable to one native login',
|
|
7
|
+
muse: 'email-only conditional identity is outside the RUSH-3053 harness contract',
|
|
8
|
+
};
|
|
1
9
|
/** Canonical truth for native-account naming and attachment semantics. */
|
|
2
10
|
export const NATIVE_ACCOUNT_CAPABILITIES = {
|
|
3
|
-
//
|
|
4
|
-
//
|
|
11
|
+
// Config-isolated harnesses with a stable native identity. A labeled launch
|
|
12
|
+
// may use the auth/config home from one installed version with another binary.
|
|
5
13
|
claude: { inspection: 'strong', scope: 'version', status: 'supported' },
|
|
6
14
|
codex: { inspection: 'strong', scope: 'version', status: 'supported' },
|
|
7
15
|
grok: { inspection: 'strong', scope: 'version', status: 'supported' },
|
|
16
|
+
cursor: { inspection: 'strong', scope: 'version', status: 'supported' },
|
|
17
|
+
// Kimi exposes a stable opaque id but no email, so it requires a manual label.
|
|
18
|
+
kimi: { inspection: 'opaque', scope: 'version', status: 'supported' },
|
|
8
19
|
// Version-scoped but only an email identity — nameable only when that email is
|
|
9
20
|
// present (the resolver rejects an emailless Muse login).
|
|
10
21
|
muse: { inspection: 'email', scope: 'version', status: 'conditional' },
|
|
@@ -17,12 +28,8 @@ export const NATIVE_ACCOUNT_CAPABILITIES = {
|
|
|
17
28
|
// "unsupported" is correct until a device-scoped identity key (with a stable
|
|
18
29
|
// device id) exists to validate against.
|
|
19
30
|
antigravity: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
|
|
20
|
-
kimi: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
|
|
21
31
|
droid: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
|
|
22
32
|
opencode: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
|
|
23
|
-
// Cursor multi-account isolation is unresolved (RUSH-2400) — blocked from
|
|
24
|
-
// native naming/attachment; its API-key path is a provider account instead.
|
|
25
|
-
cursor: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
|
|
26
33
|
// Discoverable in the list, but not nameable.
|
|
27
34
|
gemini: { inspection: 'email', scope: 'unsupported', status: 'discovery-only' },
|
|
28
35
|
copilot: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
|
|
@@ -62,9 +69,6 @@ export function nativeAccountNamingRefusal(agent) {
|
|
|
62
69
|
if (cap.scope === 'device') {
|
|
63
70
|
return `${agent} accounts can't be isolated by agents-cli yet (device-scoped login). ${suffix}`;
|
|
64
71
|
}
|
|
65
|
-
if (agent === 'cursor') {
|
|
66
|
-
return `${agent} accounts can't be isolated by agents-cli yet (multi-account isolation unresolved). ${suffix}`;
|
|
67
|
-
}
|
|
68
72
|
if (cap.status === 'discovery-only') {
|
|
69
73
|
return `${agent} native accounts are discovery-only; agents-cli cannot name or attach this login. ${suffix}`;
|
|
70
74
|
}
|
|
@@ -48,6 +48,8 @@ export declare function listNativeAccounts(meta: Pick<Meta, 'accounts'>): Native
|
|
|
48
48
|
*/
|
|
49
49
|
export declare function findUnifiedAccount(nameOrId: string, meta: Pick<Meta, 'accounts'>, doc?: AccountRegistryDocument): UnifiedAccount | null;
|
|
50
50
|
export declare function addNativeAccount(name: string, agent: AgentId, identityKey: string, identityLabel: string | undefined, scope: 'version' | 'device'): NativeAccount;
|
|
51
|
+
/** Create or replace the version-independent label for one native identity. */
|
|
52
|
+
export declare function labelNativeAccount(agent: AgentId, identityKey: string, identityLabel: string | undefined, label: string | undefined, scope: 'version' | 'device'): NativeAccount;
|
|
51
53
|
export declare function bindAccount(nameOrId: string, target: string): UnifiedAccount;
|
|
52
54
|
export declare function unbindAccount(nameOrId: string, target: string): void;
|
|
53
55
|
export declare function accountBindings(accountId: string, meta: Pick<Meta, 'accounts'>): string[];
|
|
@@ -25,12 +25,17 @@ import { bundleExists, deleteBundle, listBundles, readBundle, renameBundle, writ
|
|
|
25
25
|
import { getAccountProvider } from './account-provider-registry.js';
|
|
26
26
|
import { accountSecretItem, buildAccountBundle, parseAccountBundle } from './account-schema.js';
|
|
27
27
|
const NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
28
|
+
const NATIVE_LABEL = /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*$/;
|
|
28
29
|
const AUTH_KINDS = ['api-key', 'setup-token', 'bearer-token'];
|
|
29
30
|
export function accountRegistryPath(base = getUserAgentsDir()) { return path.join(base, 'accounts.yaml'); }
|
|
30
31
|
function assertName(name) {
|
|
31
32
|
if (!NAME.test(name))
|
|
32
33
|
throw new Error('Account name must start with a letter or number and contain only letters, numbers, dot, underscore, or dash.');
|
|
33
34
|
}
|
|
35
|
+
function assertNativeLabel(label) {
|
|
36
|
+
if (!NATIVE_LABEL.test(label))
|
|
37
|
+
throw new Error('Account label must start with a letter or number and contain only letters, numbers, @, dot, underscore, plus, or dash.');
|
|
38
|
+
}
|
|
34
39
|
function isAccountAuthKind(value) {
|
|
35
40
|
return typeof value === 'string' && AUTH_KINDS.includes(value);
|
|
36
41
|
}
|
|
@@ -143,7 +148,8 @@ export function listNativeAccounts(meta) {
|
|
|
143
148
|
* able to omit it.
|
|
144
149
|
*/
|
|
145
150
|
export function findUnifiedAccount(nameOrId, meta, doc) {
|
|
146
|
-
const
|
|
151
|
+
const needle = nameOrId.toLowerCase();
|
|
152
|
+
const native = listNativeAccounts(meta).find(account => account.id === nameOrId || account.name.toLowerCase() === needle || account.identityLabel?.toLowerCase() === needle);
|
|
147
153
|
if (native)
|
|
148
154
|
return native;
|
|
149
155
|
const provider = findAccount(nameOrId, doc ?? readAccountRegistry());
|
|
@@ -154,7 +160,7 @@ function assertUniqueUnifiedName(name, meta, doc) {
|
|
|
154
160
|
throw new Error(`Account '${name}' already exists.`);
|
|
155
161
|
}
|
|
156
162
|
export function addNativeAccount(name, agent, identityKey, identityLabel, scope) {
|
|
157
|
-
|
|
163
|
+
assertNativeLabel(name);
|
|
158
164
|
const meta = readMeta();
|
|
159
165
|
assertUniqueUnifiedName(name, meta);
|
|
160
166
|
const duplicate = listNativeAccounts(meta).find(account => account.agent === agent && account.identityKey === identityKey);
|
|
@@ -170,6 +176,28 @@ export function addNativeAccount(name, agent, identityKey, identityLabel, scope)
|
|
|
170
176
|
}));
|
|
171
177
|
return account;
|
|
172
178
|
}
|
|
179
|
+
/** Create or replace the version-independent label for one native identity. */
|
|
180
|
+
export function labelNativeAccount(agent, identityKey, identityLabel, label, scope) {
|
|
181
|
+
const resolvedLabel = label ?? identityLabel;
|
|
182
|
+
if (!resolvedLabel)
|
|
183
|
+
throw new Error(`${agent} does not expose an email; pass a manual label.`);
|
|
184
|
+
assertNativeLabel(resolvedLabel);
|
|
185
|
+
const meta = readMeta();
|
|
186
|
+
const existing = listNativeAccounts(meta).find(account => account.agent === agent && account.identityKey === identityKey);
|
|
187
|
+
const collision = findUnifiedAccount(resolvedLabel, meta);
|
|
188
|
+
if (collision && collision.id !== existing?.id)
|
|
189
|
+
throw new Error(`Account '${resolvedLabel}' already exists.`);
|
|
190
|
+
if (!existing)
|
|
191
|
+
return addNativeAccount(resolvedLabel, agent, identityKey, identityLabel, scope);
|
|
192
|
+
updateMeta(current => ({
|
|
193
|
+
...current,
|
|
194
|
+
accounts: {
|
|
195
|
+
...current.accounts,
|
|
196
|
+
native: { ...current.accounts?.native, [existing.id]: { ...current.accounts?.native?.[existing.id], name: resolvedLabel, identityLabel } },
|
|
197
|
+
},
|
|
198
|
+
}));
|
|
199
|
+
return { ...existing, name: resolvedLabel, identityLabel };
|
|
200
|
+
}
|
|
173
201
|
export function bindAccount(nameOrId, target) {
|
|
174
202
|
const meta = readMeta();
|
|
175
203
|
const account = findUnifiedAccount(nameOrId, meta);
|
|
@@ -118,6 +118,15 @@ export declare const USAGE_DECISION_MAX_AGE_MS: number;
|
|
|
118
118
|
/**
|
|
119
119
|
* Whether this candidate's usage number is recent enough to route on. A missing
|
|
120
120
|
* snapshot is unverified by definition — there is no number to trust.
|
|
121
|
+
*
|
|
122
|
+
* A snapshot with NO windows is unverified for the same reason, however fresh
|
|
123
|
+
* it is: it carries a subscription plan and no utilization, so there is still
|
|
124
|
+
* no number. Freshness alone would make a meterless harness (Grok reports a
|
|
125
|
+
* tier and no meters) verify against nothing — and since `preferVerified`
|
|
126
|
+
* narrows the pool to verified candidates, the one account whose billing log
|
|
127
|
+
* was touched most recently would win every draw, then win again because
|
|
128
|
+
* running it refreshes that log. That self-reinforcing pin is exactly what the
|
|
129
|
+
* narrowing rule below exists to prevent.
|
|
121
130
|
*/
|
|
122
131
|
export declare function isUsageVerified(candidate: RotateCandidate, nowMs?: number): boolean;
|
|
123
132
|
/**
|
|
@@ -113,10 +113,20 @@ export const USAGE_DECISION_MAX_AGE_MS = 5 * 60 * 1000;
|
|
|
113
113
|
/**
|
|
114
114
|
* Whether this candidate's usage number is recent enough to route on. A missing
|
|
115
115
|
* snapshot is unverified by definition — there is no number to trust.
|
|
116
|
+
*
|
|
117
|
+
* A snapshot with NO windows is unverified for the same reason, however fresh
|
|
118
|
+
* it is: it carries a subscription plan and no utilization, so there is still
|
|
119
|
+
* no number. Freshness alone would make a meterless harness (Grok reports a
|
|
120
|
+
* tier and no meters) verify against nothing — and since `preferVerified`
|
|
121
|
+
* narrows the pool to verified candidates, the one account whose billing log
|
|
122
|
+
* was touched most recently would win every draw, then win again because
|
|
123
|
+
* running it refreshes that log. That self-reinforcing pin is exactly what the
|
|
124
|
+
* narrowing rule below exists to prevent.
|
|
116
125
|
*/
|
|
117
126
|
export function isUsageVerified(candidate, nowMs = Date.now()) {
|
|
118
|
-
const
|
|
119
|
-
|
|
127
|
+
const snapshot = candidate.usageSnapshot;
|
|
128
|
+
const capturedAt = snapshot?.capturedAt;
|
|
129
|
+
if (!capturedAt || !snapshot?.windows.length)
|
|
120
130
|
return false;
|
|
121
131
|
return nowMs - capturedAt.getTime() <= USAGE_DECISION_MAX_AGE_MS;
|
|
122
132
|
}
|
|
@@ -60,6 +60,40 @@ export declare function isClaudeUsageScopeDenied(status: number, bodyText: strin
|
|
|
60
60
|
*/
|
|
61
61
|
export declare function usageThrottledError(agent: string, untilMs: number): string;
|
|
62
62
|
export declare function usageUnreachableError(agent: string, cause?: unknown): string;
|
|
63
|
+
/**
|
|
64
|
+
* Marker for a log-based (`network: false`) provider — Codex, Grok — that has
|
|
65
|
+
* simply never recorded a rate-limit event on this machine yet: no session
|
|
66
|
+
* log exists, or no session in it carries usage data. Distinct on purpose from
|
|
67
|
+
* `usageUnreachableError`: that one means the local log COULDN'T be read (a
|
|
68
|
+
* real failure worth surfacing distinctly); this one means there is nothing to
|
|
69
|
+
* read because the account has not run here, which is expected for a fresh
|
|
70
|
+
* install and should render as a benign state, not an error (RUSH-3040).
|
|
71
|
+
*/
|
|
72
|
+
export declare const USAGE_NO_RECENT_USAGE_MARKER = "no usage recorded yet";
|
|
73
|
+
export declare const USAGE_BENIGN_STATE: unique symbol;
|
|
74
|
+
export type UsageBenignState = 'no-recent-usage';
|
|
75
|
+
/**
|
|
76
|
+
* Shared error-classification + 429 backoff for a networked usage fetch whose
|
|
77
|
+
* only signal is an HTTP status (or none at all, on a network failure) —
|
|
78
|
+
* Antigravity's :retrieveUserQuota and Muse's Meta Model API probe are both
|
|
79
|
+
* this shape. They were added to `USAGE_SOURCES` after the four original
|
|
80
|
+
* `usageXError` constructors and did not get their own scheme (usage.ts's
|
|
81
|
+
* error handling was written for "four networked providers"; RUSH-3040).
|
|
82
|
+
* Route every no-snapshot outcome for either through this one function so a
|
|
83
|
+
* future entry cannot be added second-class again — it owns noting the 429
|
|
84
|
+
* backoff, so callers must NOT also call {@link noteUsageRateLimited} for the
|
|
85
|
+
* same response.
|
|
86
|
+
*/
|
|
87
|
+
export declare function classifyUsageFetchFailure(agent: string, agentId: 'antigravity' | 'muse', status: number | null, retryAfterHeader: string | null | undefined, usageScope?: string | null): string;
|
|
88
|
+
/**
|
|
89
|
+
* The specific cause behind a `UsageInfo.error`, so a renderer can name the
|
|
90
|
+
* exact state instead of a generic "usage unavailable" for one of several
|
|
91
|
+
* distinct causes (RUSH-3040). Matched against the canonical strings this file
|
|
92
|
+
* constructs — never re-derive these prefixes at a call site.
|
|
93
|
+
*/
|
|
94
|
+
export type UsageErrorKind = 'no-credential' | 'expired-credential' | 'rate-limited' | 'rejected' | 'headless-scope' | 'unreachable';
|
|
95
|
+
/** Classify a `UsageInfo.error` string into its {@link UsageErrorKind}, or null when there is no error. */
|
|
96
|
+
export declare function classifyUsageErrorKind(error: string | null | undefined): UsageErrorKind | null;
|
|
63
97
|
/**
|
|
64
98
|
* True when a Claude OAuth access token is within the refresh leeway of expiry
|
|
65
99
|
* (or already expired) — i.e. it "would need a refresh" before the next use.
|
|
@@ -91,17 +125,29 @@ export interface UsageSnapshot {
|
|
|
91
125
|
capturedAt: Date | null;
|
|
92
126
|
windows: UsageWindow[];
|
|
93
127
|
plan?: string | null;
|
|
94
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* A refusal observed from a real harness run, independent of API windows.
|
|
130
|
+
* `session_limit` recovers on a clock (`resetsAt`). `out_of_credits` is a
|
|
131
|
+
* tokens/balance exhaustion that does NOT reset on a clock — it has no
|
|
132
|
+
* `resetsAt` and is cleared only by a later successful run on the account
|
|
133
|
+
* (clearClaudeAccountRefusal). Both exclude the account from rotation while set.
|
|
134
|
+
*/
|
|
95
135
|
unavailable?: {
|
|
96
|
-
reason: 'session_limit';
|
|
97
|
-
resetsAt
|
|
136
|
+
reason: 'session_limit' | 'out_of_credits';
|
|
137
|
+
resetsAt?: Date;
|
|
98
138
|
};
|
|
99
139
|
}
|
|
100
140
|
/** Usage data plus any error encountered while fetching. */
|
|
101
141
|
export interface UsageInfo {
|
|
102
142
|
snapshot: UsageSnapshot | null;
|
|
103
143
|
error: string | null;
|
|
144
|
+
/** Benign local state, symbol-backed so `--json` keeps its existing shape. */
|
|
145
|
+
[USAGE_BENIGN_STATE]?: UsageBenignState;
|
|
104
146
|
}
|
|
147
|
+
/** Construct the benign no-local-log result without overloading `error`. */
|
|
148
|
+
export declare function usageNoRecentUsageInfo(): UsageInfo;
|
|
149
|
+
/** Read a benign state for the human renderer; symbols are omitted by JSON serialization. */
|
|
150
|
+
export declare function getUsageBenignState(info: UsageInfo): UsageBenignState | null;
|
|
105
151
|
/** Input needed to identify an account for usage lookup. */
|
|
106
152
|
export interface UsageIdentityInput {
|
|
107
153
|
agentId: AgentId;
|
|
@@ -114,6 +160,13 @@ interface UsageOptions {
|
|
|
114
160
|
home?: string;
|
|
115
161
|
cliVersion?: string | null;
|
|
116
162
|
organizationId?: string | null;
|
|
163
|
+
/**
|
|
164
|
+
* The account's usage key (`claude:org=…`, `kimi:user=…`, …) when the caller
|
|
165
|
+
* knows which account this fetch is for. Scopes the 429 backoff to that
|
|
166
|
+
* account (RUSH-3036) so one throttled account cannot park its siblings;
|
|
167
|
+
* absent, the backoff stays provider-wide.
|
|
168
|
+
*/
|
|
169
|
+
usageScope?: string | null;
|
|
117
170
|
/**
|
|
118
171
|
* When true, never open the ACL-bound OS keychain item (macOS Touch ID).
|
|
119
172
|
* Daemon usage refresh sets this so a background tick cannot pop biometrics.
|
|
@@ -253,6 +306,26 @@ export interface FormatUsageSummaryOpts {
|
|
|
253
306
|
* column width; single-agent and detail views leave this unset.
|
|
254
307
|
*/
|
|
255
308
|
maxWindows?: number;
|
|
309
|
+
/**
|
|
310
|
+
* The classified cause of `usageInfo.error` (RUSH-3040), from
|
|
311
|
+
* {@link classifyUsageErrorKind}. Lets the no-bars branch below name the
|
|
312
|
+
* SPECIFIC reason ('re-auth for usage', 'sign in / provision a long-lived
|
|
313
|
+
* token', 'rate-limited (retry ~12m)') instead of
|
|
314
|
+
* the generic 'usage unavailable' that used to cover ~6 distinct causes.
|
|
315
|
+
* Only consulted when `unavailable` is set — a snapshot WITH bars still
|
|
316
|
+
* renders 'unverified'/`headless` as before. `--json` output is unaffected:
|
|
317
|
+
* `UsageInfo.error` keeps carrying the full message; this only changes the
|
|
318
|
+
* short human string rendered here.
|
|
319
|
+
*/
|
|
320
|
+
errorKind?: UsageErrorKind | null;
|
|
321
|
+
/**
|
|
322
|
+
* The raw `UsageInfo.error` string, read only to pull the retry-time hint
|
|
323
|
+
* out of a `rate-limited` classification (the exact duration lives in the
|
|
324
|
+
* message text, not the kind).
|
|
325
|
+
*/
|
|
326
|
+
errorDetail?: string | null;
|
|
327
|
+
/** Benign state from {@link getUsageBenignState}; never sourced from `UsageInfo.error`. */
|
|
328
|
+
benignState?: UsageBenignState | null;
|
|
256
329
|
}
|
|
257
330
|
/** Format a one-line usage summary with compact bars for inline display. */
|
|
258
331
|
export declare function formatUsageSummary(plan: string | null, snapshot: UsageSnapshot | null, planWidth?: number, opts?: FormatUsageSummaryOpts): string;
|
|
@@ -446,11 +519,11 @@ export interface ProviderProbe {
|
|
|
446
519
|
reason?: 'usage_scope';
|
|
447
520
|
}
|
|
448
521
|
/** Probe Claude's OAuth token against the usage endpoint. Never refreshes — reports `expired` for a near-expiry token; see the comment below (RUSH-1822). */
|
|
449
|
-
export declare function probeClaudeStatus(home?: string, cliVersion?: string | null): Promise<ProviderProbe>;
|
|
522
|
+
export declare function probeClaudeStatus(home?: string, cliVersion?: string | null, usageScope?: string | null): Promise<ProviderProbe>;
|
|
450
523
|
/** Probe Kimi's OAuth token against the /usages endpoint. Never refreshes (single-use rotation — see getKimiUsageInfo). */
|
|
451
|
-
export declare function probeKimiStatus(home?: string): Promise<ProviderProbe>;
|
|
524
|
+
export declare function probeKimiStatus(home?: string, usageScope?: string | null): Promise<ProviderProbe>;
|
|
452
525
|
/** Probe Droid's WorkOS token against the billing-limits endpoint. Never refreshes (single-use rotation — see getDroidUsageInfo). */
|
|
453
|
-
export declare function probeDroidStatus(home?: string): Promise<ProviderProbe>;
|
|
526
|
+
export declare function probeDroidStatus(home?: string, usageScope?: string | null): Promise<ProviderProbe>;
|
|
454
527
|
/**
|
|
455
528
|
* Normalize the Factory billing-limits payload into the common UsageWindow
|
|
456
529
|
* shape. Orgs on the legacy (non token-rate-limit) billing model have no
|
|
@@ -515,6 +588,19 @@ export declare function readClaudeUsageCache(usageKey: string, cachePath?: strin
|
|
|
515
588
|
export declare function pruneExpiredClaudeUsageCacheEntry(usageKey: string, cachePath?: string, now?: Date): void;
|
|
516
589
|
/** Write a usage snapshot to the on-disk cache. */
|
|
517
590
|
export declare function writeClaudeUsageCache(usageKey: string, snapshot: UsageSnapshot, cachePath?: string): void;
|
|
591
|
+
/**
|
|
592
|
+
* Persist a Claude tokens/credits exhaustion (`out of usage credits` / `monthly
|
|
593
|
+
* spend limit`) from a real run. Unlike a rate/session limit this does NOT reset
|
|
594
|
+
* on a clock, so no reset time is stored — rotation excludes the account until a
|
|
595
|
+
* later successful run clears it via {@link clearClaudeAccountRefusal}.
|
|
596
|
+
*/
|
|
597
|
+
export declare function noteClaudeOutOfCredits(usageKey: string, cachePath?: string): void;
|
|
598
|
+
/**
|
|
599
|
+
* Clear any persisted refusal marker for an account after a run SUCCEEDS on it.
|
|
600
|
+
* This is the recovery path for `out_of_credits` (which has no clock) and also
|
|
601
|
+
* proactively clears a stale `session_limit` the moment the account serves again.
|
|
602
|
+
*/
|
|
603
|
+
export declare function clearClaudeAccountRefusal(usageKey: string, cachePath?: string): void;
|
|
518
604
|
/**
|
|
519
605
|
* Persist a Claude session-limit refusal from a real run until its stated reset.
|
|
520
606
|
* This quota is not part of Anthropic's five-hour/weekly usage response.
|