@indigoai-us/hq-cli 5.202.1 → 5.203.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/CHANGELOG.md +7 -0
- package/README.md +24 -0
- package/assets/lanes-hooks/hq-lanes-drain.mjs +36 -15
- package/dist/command-catalog.generated.d.ts +168 -0
- package/dist/command-catalog.generated.js +214 -0
- package/dist/command-registration-plan.d.ts +6 -0
- package/dist/command-registration-plan.js +1 -0
- package/dist/commands/lanes.d.ts +1 -0
- package/dist/commands/lanes.js +150 -83
- package/dist/commands/monitor.d.ts +58 -0
- package/dist/commands/monitor.js +965 -0
- package/dist/lib/lanes/delivery-core.d.ts +15 -0
- package/dist/lib/lanes/delivery-core.js +21 -0
- package/dist/lib/lanes/delivery.d.ts +21 -5
- package/dist/lib/lanes/delivery.js +71 -7
- package/dist/lib/lanes/dropbox.d.ts +13 -1
- package/dist/lib/lanes/dropbox.js +61 -5
- package/dist/lib/lanes/index.d.ts +1 -1
- package/dist/lib/lanes/index.js +1 -1
- package/dist/lib/lanes/move-account.js +1 -1
- package/dist/lib/lanes/spawn.d.ts +6 -3
- package/dist/lib/lanes/spawn.js +41 -8
- package/dist/lib/lanes/types.d.ts +3 -0
- package/dist/lib/monitor.d.ts +153 -0
- package/dist/lib/monitor.js +519 -0
- package/dist/main.js +40 -28
- package/dist/utils/cli-network-lifecycle.d.ts +4 -0
- package/dist/utils/cli-network-lifecycle.js +11 -0
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -53,6 +53,7 @@ import { registerCommandsWithRecovery } from "./startup-registration.js";
|
|
|
53
53
|
import { installTreeTornCaptureContext, installTreeTornStderrLine, isInstallTreeTornError, } from "./utils/install-tree-torn.js";
|
|
54
54
|
import { isVaultAccessDeniedError, vaultAccessDeniedMessage, } from "./utils/vault-access-denied-error.js";
|
|
55
55
|
import { fallbackOperatorMessage, unexpectedCliErrorMessage } from "./utils/unexpected-cli-error.js";
|
|
56
|
+
import { runGlobalNetworkLifecycle } from "./utils/cli-network-lifecycle.js";
|
|
56
57
|
/**
|
|
57
58
|
* Total time one CLI invocation may await foreground network work. This spans
|
|
58
59
|
* the hard version decision, pre-action observability, and release-health
|
|
@@ -152,7 +153,7 @@ export function handleStreamError(err, deps = defaultStreamErrorDependencies) {
|
|
|
152
153
|
}
|
|
153
154
|
process.stdout.on("error", (err) => handleStreamError(err));
|
|
154
155
|
process.stderr.on("error", (err) => handleStreamError(err));
|
|
155
|
-
initSentry();
|
|
156
|
+
runGlobalNetworkLifecycle(process.argv, () => initSentry());
|
|
156
157
|
const program = new Command();
|
|
157
158
|
program
|
|
158
159
|
.name("hq")
|
|
@@ -166,13 +167,15 @@ program.hook("preAction", async () => {
|
|
|
166
167
|
// regardless, because the timer cannot be serviced while the event loop is
|
|
167
168
|
// blocked. Keep anything added here asynchronous, or separately cheap: this
|
|
168
169
|
// hook is on the path of EVERY hq command.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
await runGlobalNetworkLifecycle(process.argv, async () => {
|
|
171
|
+
const budget = activeForegroundNetworkBudget;
|
|
172
|
+
if (!budget)
|
|
173
|
+
return;
|
|
174
|
+
await budget.waitFor(OBSERVABILITY_FOREGROUND_WAIT_MS, FINALIZATION_FOREGROUND_WAIT_MS, (timeoutMs) => Promise.all([
|
|
175
|
+
emitCliSessionStarted(timeoutMs),
|
|
176
|
+
reportCliClientHealthInvocation({ timeoutMs }),
|
|
177
|
+
]));
|
|
178
|
+
});
|
|
176
179
|
});
|
|
177
180
|
export async function runCli() {
|
|
178
181
|
const foregroundNetworkBudget = new ForegroundNetworkBudget();
|
|
@@ -180,17 +183,19 @@ export async function runCli() {
|
|
|
180
183
|
// Begin one registry refresh without awaiting it. Every command gate reads
|
|
181
184
|
// only the client's held snapshot and falls back locally, so an offline or
|
|
182
185
|
// slow registry cannot delay command parsing or alter a command failure.
|
|
183
|
-
|
|
186
|
+
runGlobalNetworkLifecycle(process.argv, () => {
|
|
187
|
+
void kickFlagRegistryReadiness();
|
|
188
|
+
});
|
|
184
189
|
// Set when a self-update re-exec'd this command on a newer CLI: the child
|
|
185
190
|
// already did the work, so this process only has to carry its exit status
|
|
186
191
|
// out (after the finally block's telemetry, hence not process.exit here).
|
|
187
192
|
let reexecStatus = null;
|
|
188
193
|
try {
|
|
189
|
-
Sentry.addBreadcrumb({
|
|
194
|
+
runGlobalNetworkLifecycle(process.argv, () => Sentry.addBreadcrumb({
|
|
190
195
|
category: "command",
|
|
191
196
|
message: sanitizeArgv(process.argv.slice(2)).join(" "),
|
|
192
197
|
level: "info",
|
|
193
|
-
});
|
|
198
|
+
}));
|
|
194
199
|
// Version handling, both halves. Skipped for inspection flags
|
|
195
200
|
// (`--version`, `--help`) so users debugging a broken install can still
|
|
196
201
|
// introspect what they have, and silent on any failure — neither half may
|
|
@@ -204,7 +209,9 @@ export async function runCli() {
|
|
|
204
209
|
// it (hq-pro's `updateRecommended` and the cached npm latest from
|
|
205
210
|
// `version-check.ts`); whichever fires first re-execs, and the child
|
|
206
211
|
// carries a guard env so it can never update again.
|
|
207
|
-
|
|
212
|
+
const versionAction = await runGlobalNetworkLifecycle(process.argv, async () => {
|
|
213
|
+
if (shouldSkipGate(process.argv))
|
|
214
|
+
return "continue";
|
|
208
215
|
const gate = (await foregroundNetworkBudget.waitFor(VERSION_GATE_FOREGROUND_WAIT_MS, FINALIZATION_FOREGROUND_WAIT_MS, (timeoutMs) => enforceVersionGate(async (decision) => {
|
|
209
216
|
const outcome = await autoUpdateAndReexec(process.argv, decision.latestVersion);
|
|
210
217
|
if (outcome.action === "reexec")
|
|
@@ -212,16 +219,19 @@ export async function runCli() {
|
|
|
212
219
|
return outcome.action === "reexec";
|
|
213
220
|
}, { timeoutMs }))) ?? "continue";
|
|
214
221
|
if (gate === "reexec")
|
|
215
|
-
return;
|
|
222
|
+
return "reexec";
|
|
216
223
|
const cachedLatest = staleAgainstCachedLatest();
|
|
217
224
|
if (cachedLatest) {
|
|
218
225
|
const outcome = await autoUpdateAndReexec(process.argv, cachedLatest);
|
|
219
226
|
if (outcome.action === "reexec") {
|
|
220
227
|
reexecStatus = outcome.reexecStatus ?? 0;
|
|
221
|
-
return;
|
|
228
|
+
return "reexec";
|
|
222
229
|
}
|
|
223
230
|
}
|
|
224
|
-
|
|
231
|
+
return "continue";
|
|
232
|
+
});
|
|
233
|
+
if (versionAction === "reexec")
|
|
234
|
+
return;
|
|
225
235
|
// Register every contributor for the selected root only. Root help and
|
|
226
236
|
// unknown-command recovery use generated metadata, so they keep the full
|
|
227
237
|
// Commander surface without evaluating every command implementation.
|
|
@@ -256,19 +266,21 @@ export async function runCli() {
|
|
|
256
266
|
finally {
|
|
257
267
|
// Plan-limit nag (US-016): stderr-only, never throws, never touches
|
|
258
268
|
// process.exitCode — safe to run after exit codes have been set.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
await runGlobalNetworkLifecycle(process.argv, async () => {
|
|
270
|
+
emitPlanLimitNag();
|
|
271
|
+
// Release health: finalize the per-run session before the flush.
|
|
272
|
+
finishSentrySession();
|
|
273
|
+
// Neither task may turn a successful command into Node's
|
|
274
|
+
// `unsettled top-level await` exit. They are observability-only after the
|
|
275
|
+
// command has completed, so a bounded best-effort wait is the terminal
|
|
276
|
+
// lifecycle boundary for this invocation. The budget reserves this 500 ms
|
|
277
|
+
// slice even when the command itself was long-running.
|
|
278
|
+
const releaseHealthTimeoutMs = foregroundNetworkBudget.timeoutFor(FINALIZATION_FOREGROUND_WAIT_MS);
|
|
279
|
+
await settleWithin([
|
|
280
|
+
refreshVersionCache({ timeoutMs: releaseHealthTimeoutMs }),
|
|
281
|
+
Sentry.flush(releaseHealthTimeoutMs),
|
|
282
|
+
], releaseHealthTimeoutMs);
|
|
283
|
+
});
|
|
272
284
|
// Last, so it wins over anything the (skipped) command path would have
|
|
273
285
|
// set: the re-exec'd child's status IS this invocation's result.
|
|
274
286
|
if (reexecStatus !== null)
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function isMonitorFastPathCommand(argv: readonly string[]): boolean;
|
|
2
|
+
/** Skip process-wide network lifecycle work for hooks and detached monitor supervisors. */
|
|
3
|
+
export declare function runGlobalNetworkLifecycle<T>(argv: readonly string[], operation: () => T): T | undefined;
|
|
4
|
+
//# sourceMappingURL=cli-network-lifecycle.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const MONITOR_HIDDEN_NETWORK_BYPASS = new Set(["drain", "wait", "enabled", "_run"]);
|
|
2
|
+
export function isMonitorFastPathCommand(argv) {
|
|
3
|
+
return argv[2] === "monitor" && MONITOR_HIDDEN_NETWORK_BYPASS.has(argv[3] ?? "");
|
|
4
|
+
}
|
|
5
|
+
/** Skip process-wide network lifecycle work for hooks and detached monitor supervisors. */
|
|
6
|
+
export function runGlobalNetworkLifecycle(argv, operation) {
|
|
7
|
+
if (isMonitorFastPathCommand(argv))
|
|
8
|
+
return undefined;
|
|
9
|
+
return operation();
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=cli-network-lifecycle.js.map
|