@indigoai-us/hq-cli 5.345.107 → 5.345.109
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 +15 -0
- package/dist/command-catalog.generated.d.ts +40 -1
- package/dist/command-catalog.generated.js +48 -1
- package/dist/commands/capacity.d.ts +1 -1
- package/dist/commands/capacity.js +74 -11
- package/dist/commands/core-checkpoint-stop-gate-native.js +17 -5
- package/dist/commands/lanes.js +72 -12
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +612 -460
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +38 -1
- package/dist/lib/capacity/ledger.d.ts +1 -0
- package/dist/lib/capacity/ledger.js +10 -0
- package/dist/lib/capacity/route.d.ts +146 -0
- package/dist/lib/capacity/route.js +452 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/lanes/store.js +4 -4
- package/dist/lib/lanes/types.d.ts +20 -4
- package/dist/lib/lanes/types.js +1 -1
- package/dist/utils/package-use-lease.d.ts +15 -1
- package/dist/utils/package-use-lease.js +45 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"hq-cli-daemon-sync-runner","type":"module","version":"6.18.
|
|
1
|
+
{"name":"hq-cli-daemon-sync-runner","type":"module","version":"6.18.67","bundleSha256":"6d94ad9a9dbfa34fd81040eff69d68a1da68ab0d1318566832fe19393bffe589","formatVersion":1}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,13 +5,21 @@ import { isVersionRequest } from "./version-request.js";
|
|
|
5
5
|
import { isFastCoreRequest } from "./fast-scaffold.js";
|
|
6
6
|
type PackageUseLeaseLoader = () => Promise<void>;
|
|
7
7
|
type PackageUseUpdateProbe = () => Promise<boolean>;
|
|
8
|
+
/** Resolves true once the command was re-run (exit code already set). */
|
|
9
|
+
type PackageUseUpdateReexec = () => Promise<boolean>;
|
|
10
|
+
/**
|
|
11
|
+
* Wait (bounded) for a live updater to finish, then re-run this command from
|
|
12
|
+
* the new install via the same bin path. Guarded against loops by an env flag.
|
|
13
|
+
*/
|
|
14
|
+
declare function waitForUpdateThenReexec(argv?: readonly string[], env?: NodeJS.ProcessEnv, waitForUpdate?: () => Promise<boolean>, run?: (command: string, args: string[], childEnv: NodeJS.ProcessEnv) => Promise<number>): Promise<boolean>;
|
|
8
15
|
declare function isNpmPackageEntry(entryUrl: string): boolean;
|
|
9
|
-
declare function dispatchWithPackageUseLease(entryUrl: string, dispatch: () => void, loadLease?: PackageUseLeaseLoader, updateRequestPending?: PackageUseUpdateProbe): void | Promise<void>;
|
|
16
|
+
declare function dispatchWithPackageUseLease(entryUrl: string, dispatch: () => void, loadLease?: PackageUseLeaseLoader, updateRequestPending?: PackageUseUpdateProbe, waitThenReexec?: PackageUseUpdateReexec): void | Promise<void>;
|
|
10
17
|
declare function runCliEntry(entryUrl: string, dispatch: () => void, loadLease?: PackageUseLeaseLoader): void | Promise<void>;
|
|
11
18
|
export declare const __test__: {
|
|
12
19
|
isVersionRequest: typeof isVersionRequest;
|
|
13
20
|
isFastCoreRequest: typeof isFastCoreRequest;
|
|
14
21
|
dispatchWithPackageUseLease: typeof dispatchWithPackageUseLease;
|
|
22
|
+
waitForUpdateThenReexec: typeof waitForUpdateThenReexec;
|
|
15
23
|
runCliEntry: typeof runCliEntry;
|
|
16
24
|
isNpmPackageEntry: typeof isNpmPackageEntry;
|
|
17
25
|
acquirePackageUseLease: (prefix: string, version: string, stateDirectory?: string) => Promise<import("./utils/package-use-lease.js").PackageUseLease>;
|
package/dist/index.js
CHANGED
|
@@ -230,6 +230,36 @@ function dispatchCliEntry() {
|
|
|
230
230
|
void runMainWithInstallTreeRecovery();
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
|
+
const REEXEC_ENV = "HQ_CLI_UPDATE_REEXEC";
|
|
234
|
+
/**
|
|
235
|
+
* Wait (bounded) for a live updater to finish, then re-run this command from
|
|
236
|
+
* the new install via the same bin path. Guarded against loops by an env flag.
|
|
237
|
+
*/
|
|
238
|
+
async function waitForUpdateThenReexec(argv = process.argv, env = process.env, waitForUpdate = async () => {
|
|
239
|
+
const { waitForCurrentPackageUseUpdate } = await import("./utils/package-use-lease.js");
|
|
240
|
+
return waitForCurrentPackageUseUpdate();
|
|
241
|
+
}, run = async (command, args, childEnv) => {
|
|
242
|
+
const { spawn } = await import("node:child_process");
|
|
243
|
+
return await new Promise((resolve) => {
|
|
244
|
+
const child = spawn(command, args, { stdio: "inherit", env: childEnv });
|
|
245
|
+
child.on("error", () => resolve(1));
|
|
246
|
+
child.on("exit", (code, signal) => resolve(code ?? (signal ? 128 : 1)));
|
|
247
|
+
});
|
|
248
|
+
}) {
|
|
249
|
+
if (env[REEXEC_ENV] === "1" || !argv[1])
|
|
250
|
+
return false;
|
|
251
|
+
let finished = false;
|
|
252
|
+
try {
|
|
253
|
+
finished = await waitForUpdate();
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
if (!finished)
|
|
259
|
+
return false;
|
|
260
|
+
process.exitCode = await run(process.execPath, argv.slice(1), { ...env, [REEXEC_ENV]: "1" });
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
233
263
|
function isNpmPackageEntry(entryUrl) {
|
|
234
264
|
return /\/node_modules\/@indigoai-us\/hq-cli\/dist\/index\.js$/i.test(entryUrl);
|
|
235
265
|
}
|
|
@@ -260,7 +290,7 @@ function dispatchWithPackageUseLease(entryUrl, dispatch, loadLease = async () =>
|
|
|
260
290
|
}, updateRequestPending = async () => {
|
|
261
291
|
const { currentPackageUseUpdatePending } = await import("./utils/package-use-lease.js");
|
|
262
292
|
return currentPackageUseUpdatePending();
|
|
263
|
-
}) {
|
|
293
|
+
}, waitThenReexec = waitForUpdateThenReexec) {
|
|
264
294
|
if (!isNpmPackageEntry(entryUrl)) {
|
|
265
295
|
dispatch();
|
|
266
296
|
return;
|
|
@@ -270,6 +300,12 @@ function dispatchWithPackageUseLease(entryUrl, dispatch, loadLease = async () =>
|
|
|
270
300
|
throw error;
|
|
271
301
|
try {
|
|
272
302
|
if (await updateRequestPending()) {
|
|
303
|
+
// The install tree is being replaced under this process, so the lease
|
|
304
|
+
// module (or a dependency) failed to load. Wait for the updater, then
|
|
305
|
+
// run the command again from the freshly installed package instead of
|
|
306
|
+
// failing a running session's command outright.
|
|
307
|
+
if (await waitThenReexec())
|
|
308
|
+
return;
|
|
273
309
|
const pending = new Error("The HQ CLI package is being updated; retry after the update finishes");
|
|
274
310
|
pending.name = "PackageUseUpdatePendingError";
|
|
275
311
|
throw pending;
|
|
@@ -311,6 +347,7 @@ export const __test__ = {
|
|
|
311
347
|
isVersionRequest,
|
|
312
348
|
isFastCoreRequest,
|
|
313
349
|
dispatchWithPackageUseLease,
|
|
350
|
+
waitForUpdateThenReexec,
|
|
314
351
|
runCliEntry,
|
|
315
352
|
isNpmPackageEntry,
|
|
316
353
|
acquirePackageUseLease: async (prefix, version, stateDirectory) => {
|
|
@@ -369,6 +369,7 @@ export interface LedgerOptions {
|
|
|
369
369
|
pid?: number;
|
|
370
370
|
lockTtlMs?: number;
|
|
371
371
|
}
|
|
372
|
+
export declare function capacityOptionsFromEnv(env?: NodeJS.ProcessEnv): LedgerOptions;
|
|
372
373
|
export declare function capacityRoot(env?: NodeJS.ProcessEnv, home?: string): string;
|
|
373
374
|
/** Shown for a credential that exists and is past expiry. Never a login. */
|
|
374
375
|
export declare const EXPIRED_REASON = "expired: refreshes the next time Claude Code is used with this account";
|
|
@@ -169,6 +169,16 @@ export const nowViewJsonSchema = {
|
|
|
169
169
|
},
|
|
170
170
|
},
|
|
171
171
|
};
|
|
172
|
+
export function capacityOptionsFromEnv(env = process.env) {
|
|
173
|
+
const raw = env.HQ_CAPACITY_NOW?.trim();
|
|
174
|
+
if (!raw)
|
|
175
|
+
return { env };
|
|
176
|
+
const parsed = Date.parse(raw);
|
|
177
|
+
if (Number.isNaN(parsed)) {
|
|
178
|
+
throw new Error(`HQ_CAPACITY_NOW must be a UTC timestamp, got '${raw}'`);
|
|
179
|
+
}
|
|
180
|
+
return { env, now: () => new Date(raw) };
|
|
181
|
+
}
|
|
172
182
|
export function capacityRoot(env = process.env, home = os.homedir()) {
|
|
173
183
|
const override = env.HQ_CAPACITY_ROOT?.trim();
|
|
174
184
|
if (override)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { LaneRecord, LaneState, LanesConfig } from "../lanes/types.js";
|
|
2
|
+
import { type LaneProvider } from "../lanes/types.js";
|
|
3
|
+
import type { NowLimit, NowView } from "./ledger.js";
|
|
4
|
+
/** All lane providers, in the stable order boss-route uses for ranking ties. */
|
|
5
|
+
export declare const ROUTE_PROVIDERS: readonly LaneProvider[];
|
|
6
|
+
/** Lane states that count against an account's live load. */
|
|
7
|
+
export declare const LIVE_STATES: ReadonlySet<LaneState>;
|
|
8
|
+
/** Limit kinds the router scores against. */
|
|
9
|
+
export declare const LIMIT_KINDS: Set<string>;
|
|
10
|
+
/** A reading older than this is treated as no reading at all. */
|
|
11
|
+
export declare const STALE_SKIP_MS: number;
|
|
12
|
+
/** Headroom below this percent is "nearly used up"; the account is skipped. */
|
|
13
|
+
export declare const NEARLY_OUT = 5;
|
|
14
|
+
/** Score penalty per live lane already on the account. */
|
|
15
|
+
export declare const LANE_PENALTY = 3;
|
|
16
|
+
/** Weekly reset within this window boosts an otherwise idle account. */
|
|
17
|
+
export declare const RESET_SOON_MS: number;
|
|
18
|
+
/** Score bonus for a weekly that resets within RESET_SOON_MS. */
|
|
19
|
+
export declare const RESET_SOON_BONUS = 10;
|
|
20
|
+
/** A limit reading older than this is dropped as unknown until its window resets. */
|
|
21
|
+
export declare const LIMIT_STALE_MS: number;
|
|
22
|
+
/** Readings older than this rank below fresh ones by OLD_READING_PENALTY. */
|
|
23
|
+
export declare const FRESH_MS: number;
|
|
24
|
+
/** Score penalty for an account whose binding limit reading is not fresh. */
|
|
25
|
+
export declare const OLD_READING_PENALTY = 10;
|
|
26
|
+
/** Default --floor applied by the CLI (percent headroom to clear). */
|
|
27
|
+
export declare const DEFAULT_FLOOR = 15;
|
|
28
|
+
/** Default --prefer order applied by the CLI. */
|
|
29
|
+
export declare const DEFAULT_PREFER: readonly LaneProvider[];
|
|
30
|
+
/** Sign-in states a lane can still run on. */
|
|
31
|
+
export declare const RUNNABLE_AUTH: Set<string>;
|
|
32
|
+
/** Map a model id to its lane provider, or null when the model is unmapped. */
|
|
33
|
+
export declare function providerForModel(model: string): LaneProvider | null;
|
|
34
|
+
/** True when the limit should factor into the pick for this request. */
|
|
35
|
+
export declare function limitApplies(provider: LaneProvider, limit: NowLimit, model: string): boolean;
|
|
36
|
+
/** Human label for the limit a reason or binding row quotes. */
|
|
37
|
+
export declare function labelLimit(limit: NowLimit): string;
|
|
38
|
+
/** Lane account whose canonical home matches one of the ledger account's homes. */
|
|
39
|
+
export declare function laneAccountFor(provider: LaneProvider, homes: readonly string[] | undefined, lanesConfig: LanesConfig): {
|
|
40
|
+
id: string;
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
} | null;
|
|
43
|
+
/** Request payload echoed in the output. */
|
|
44
|
+
export interface RouteRequest {
|
|
45
|
+
providers: LaneProvider[];
|
|
46
|
+
model: string | null;
|
|
47
|
+
prefer: LaneProvider[];
|
|
48
|
+
floor: number;
|
|
49
|
+
}
|
|
50
|
+
export interface RouteBindingSummary {
|
|
51
|
+
limit: string;
|
|
52
|
+
used_percent: number;
|
|
53
|
+
resets_at: string | null;
|
|
54
|
+
}
|
|
55
|
+
/** One account the router could not route to, with the reason the operator sees. */
|
|
56
|
+
export interface RouteSkipped {
|
|
57
|
+
provider: LaneProvider;
|
|
58
|
+
account: string | null;
|
|
59
|
+
label: string;
|
|
60
|
+
organization: string | null;
|
|
61
|
+
reason: string;
|
|
62
|
+
fix?: string | null;
|
|
63
|
+
resets_at?: string | null;
|
|
64
|
+
}
|
|
65
|
+
/** One account the router scored, in rank order after sorting. */
|
|
66
|
+
export interface RouteRanked {
|
|
67
|
+
provider: LaneProvider;
|
|
68
|
+
account: string;
|
|
69
|
+
label: string;
|
|
70
|
+
organization: string | null;
|
|
71
|
+
headroom: number;
|
|
72
|
+
score: number;
|
|
73
|
+
live_lanes: number;
|
|
74
|
+
reset_soon: boolean;
|
|
75
|
+
token_expired: boolean;
|
|
76
|
+
reading_age_h: number;
|
|
77
|
+
binding: RouteBindingSummary;
|
|
78
|
+
weekly_resets_at: string | null;
|
|
79
|
+
why: string;
|
|
80
|
+
lane_flags: string;
|
|
81
|
+
}
|
|
82
|
+
/** Live lane on an account the router would avoid; command names a replacement. */
|
|
83
|
+
export interface RouteMove {
|
|
84
|
+
lane_id: string;
|
|
85
|
+
provider: LaneProvider;
|
|
86
|
+
from: string | null;
|
|
87
|
+
reason: string;
|
|
88
|
+
to: string | null;
|
|
89
|
+
command: string | null;
|
|
90
|
+
}
|
|
91
|
+
export interface RouteCapacityMeta {
|
|
92
|
+
generated_at: string | null;
|
|
93
|
+
stale: boolean;
|
|
94
|
+
collector_enabled: boolean | null;
|
|
95
|
+
}
|
|
96
|
+
export interface RouteResult {
|
|
97
|
+
ok: boolean;
|
|
98
|
+
at: string;
|
|
99
|
+
request: RouteRequest;
|
|
100
|
+
pick: RouteRanked | null;
|
|
101
|
+
ranked: RouteRanked[];
|
|
102
|
+
skipped: RouteSkipped[];
|
|
103
|
+
moves: RouteMove[];
|
|
104
|
+
next_reset: string | null;
|
|
105
|
+
capacity: RouteCapacityMeta;
|
|
106
|
+
lanes_error: string | null;
|
|
107
|
+
}
|
|
108
|
+
export interface PickAccountInput {
|
|
109
|
+
view: NowView;
|
|
110
|
+
lanes: readonly LaneRecord[];
|
|
111
|
+
lanesConfig: LanesConfig;
|
|
112
|
+
/** Requested providers; "any" expands to the model's provider or every provider. */
|
|
113
|
+
providers?: readonly string[];
|
|
114
|
+
model?: string | null;
|
|
115
|
+
prefer?: readonly string[];
|
|
116
|
+
floor?: number;
|
|
117
|
+
now: Date;
|
|
118
|
+
/** Reserved for future use; routing today does not read env. */
|
|
119
|
+
env?: NodeJS.ProcessEnv;
|
|
120
|
+
/** Collector enabled flag threaded from the mark file. */
|
|
121
|
+
collectorEnabled?: boolean | null;
|
|
122
|
+
/** Overall ledger freshness flag threaded from AdvisoryNow. */
|
|
123
|
+
capacityStale?: boolean;
|
|
124
|
+
/** Error summary when the lanes list could not be read. */
|
|
125
|
+
lanesError?: string | null;
|
|
126
|
+
}
|
|
127
|
+
export declare class RouteUsageError extends Error {
|
|
128
|
+
readonly code = "route_usage";
|
|
129
|
+
constructor(message: string);
|
|
130
|
+
}
|
|
131
|
+
/** Parse `--provider any|claude|codex|grok[,..]` honouring the model expansion rule. */
|
|
132
|
+
export declare function resolveRequestedProviders(raw: readonly string[] | undefined, model: string): LaneProvider[];
|
|
133
|
+
/** Parse `--prefer claude,codex,grok`. */
|
|
134
|
+
export declare function resolvePreferOrder(raw: readonly string[] | undefined): LaneProvider[];
|
|
135
|
+
/** Parse `--floor <n>`; 0..100 inclusive, default DEFAULT_FLOOR when missing. */
|
|
136
|
+
export declare function resolveFloor(raw: string | number | undefined): number;
|
|
137
|
+
/**
|
|
138
|
+
* Pure routing decision over a snapshot: scores every signed-in lane account,
|
|
139
|
+
* applies the --prefer order under the --floor headroom, returns the pick (or
|
|
140
|
+
* null when nothing has room), and the lane-move suggestions for live lanes
|
|
141
|
+
* sitting on bad accounts.
|
|
142
|
+
*/
|
|
143
|
+
export declare function pickAccount(input: PickAccountInput): RouteResult;
|
|
144
|
+
/** One-line text output used by `--text` and by `--account auto` admission messages. */
|
|
145
|
+
export declare function formatRouteText(result: RouteResult): string;
|
|
146
|
+
//# sourceMappingURL=route.d.ts.map
|