@indigoai-us/hq-cli 5.310.0 → 5.311.1
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 +20 -0
- package/assets/scaffold/core/scripts/jobs-validate.sh +1 -1
- package/dist/command-catalog.generated.d.ts +2 -2
- package/dist/command-catalog.generated.js +2 -2
- package/dist/commands/channels.d.ts +1 -9
- package/dist/commands/channels.js +2 -2
- package/dist/commands/company-transfer.d.ts +4 -28
- package/dist/commands/company-transfer.js +5 -49
- package/dist/commands/core-checkpoint-stop-gate-native.d.ts +34 -0
- package/dist/commands/core-checkpoint-stop-gate-native.js +713 -0
- package/dist/commands/core-checkpoint.d.ts +0 -24
- package/dist/commands/core-checkpoint.js +4 -4
- package/dist/commands/core-command-catalog.js +1 -1
- package/dist/commands/core-delegate-w1b.js +111 -14
- package/dist/commands/core-delegate.d.ts +9 -0
- package/dist/commands/core-delegate.js +44 -23
- package/dist/commands/core-hq-session-native.d.ts +39 -0
- package/dist/commands/core-hq-session-native.js +579 -0
- package/dist/commands/core-jobs-native.js +1 -4
- package/dist/commands/core-native-session-flag.d.ts +4 -0
- package/dist/commands/core-native-session-flag.js +7 -0
- package/dist/commands/core-native-worker-skills-flag.d.ts +4 -0
- package/dist/commands/core-native-worker-skills-flag.js +7 -0
- package/dist/commands/core-worker-lint-native.d.ts +4 -0
- package/dist/commands/core-worker-lint-native.js +160 -0
- package/dist/commands/core-worker-share-native.d.ts +5 -0
- package/dist/commands/core-worker-share-native.js +260 -0
- package/dist/commands/core-worker-skills-command.d.ts +8 -0
- package/dist/commands/core-worker-skills-command.js +33 -0
- package/dist/commands/core-worker-skills-runtime.d.ts +33 -0
- package/dist/commands/core-worker-skills-runtime.js +86 -0
- package/dist/commands/core.js +4 -2
- package/dist/commands/dm.d.ts +3 -7
- package/dist/commands/dm.js +3 -3
- package/dist/commands/integrations-core.d.ts +2 -0
- package/dist/commands/integrations-core.js +4 -0
- package/dist/commands/integrations-import.d.ts +1 -1
- package/dist/commands/integrations-import.js +34 -19
- package/dist/commands/integrations.js +2 -2
- package/dist/commands/lanes-accounts.js +3 -1
- package/dist/commands/lanes-message.js +84 -10
- package/dist/commands/lanes-shared.d.ts +4 -1
- package/dist/commands/lanes.d.ts +4 -1
- package/dist/commands/lanes.js +48 -7
- package/dist/commands/personal-connector-settings-flag.d.ts +4 -0
- package/dist/commands/personal-connector-settings-flag.js +7 -0
- package/dist/commands/report.d.ts +1 -26
- package/dist/commands/report.js +6 -6
- package/dist/fast-core.js +15 -2
- package/dist/fast-scaffold.js +25 -2
- package/dist/index.js +8 -0
- package/dist/lib/bot/continuity.d.ts +2 -1
- package/dist/lib/bot/job-completions.d.ts +0 -2
- package/dist/lib/bot/job-completions.js +2 -2
- package/dist/lib/bot/local-config.d.ts +0 -10
- package/dist/lib/bot/local-config.js +3 -9
- package/dist/lib/bot/owner-context.d.ts +2 -6
- package/dist/lib/bot/owner-context.js +3 -3
- package/dist/lib/bot/setup-explain.d.ts +0 -4
- package/dist/lib/bot/setup-explain.js +2 -2
- package/dist/lib/daemon/catalog.d.ts +3 -2
- package/dist/lib/daemon/hq-cloud.d.ts +2 -2
- package/dist/lib/daemon/hq-cloud.js +1 -1
- package/dist/lib/daemon/machine-type.d.ts +3 -4
- package/dist/lib/daemon/machine-type.js +2 -2
- package/dist/lib/daemon/remote-control.d.ts +0 -1
- package/dist/lib/daemon/remote-control.js +1 -1
- package/dist/lib/daemon/supervisor.d.ts +4 -9
- package/dist/lib/daemon/supervisor.js +5 -5
- package/dist/lib/lanes/admission-host.d.ts +3 -0
- package/dist/lib/lanes/admission-host.js +4 -0
- package/dist/lib/lanes/autopilot-registry.d.ts +62 -0
- package/dist/lib/lanes/autopilot-registry.js +192 -0
- package/dist/lib/lanes/autopilot.d.ts +2 -0
- package/dist/lib/lanes/autopilot.js +18 -5
- package/dist/lib/lanes/claude-balance.d.ts +6 -0
- package/dist/lib/lanes/claude-balance.js +17 -2
- package/dist/lib/lanes/keep-alive.d.ts +3 -0
- package/dist/lib/lanes/keep-alive.js +3 -0
- package/dist/lib/lanes/reconcile.js +14 -6
- package/dist/lib/lanes/spawn.js +2 -0
- package/dist/lib/mesh/live/daemon/credentials.d.ts +2 -17
- package/dist/lib/mesh/live/daemon/credentials.js +9 -9
- package/dist/lib/mesh/live/daemon/index.d.ts +5 -5
- package/dist/lib/mesh/live/daemon/index.js +2 -2
- package/dist/lib/mesh/live/daemon/state.d.ts +1 -1
- package/dist/lib/mesh/live/daemon/transcript-watch.d.ts +4 -11
- package/dist/lib/mesh/live/daemon/transcript-watch.js +5 -5
- package/dist/lib/work-context/company.d.ts +2 -25
- package/dist/lib/work-context/company.js +3 -3
- package/dist/lib/work-context/config.d.ts +3 -8
- package/dist/lib/work-context/config.js +2 -13
- package/dist/lib/work-context/state.d.ts +4 -13
- package/dist/lib/work-context/state.js +2 -30
- package/dist/utils/run-bundled-script.d.ts +6 -0
- package/dist/utils/run-bundled-script.js +14 -3
- package/package.json +1 -1
package/dist/commands/report.js
CHANGED
|
@@ -99,7 +99,7 @@ async function listReportChannels(token) {
|
|
|
99
99
|
return Array.isArray(listed.channels) ? listed.channels : [];
|
|
100
100
|
}
|
|
101
101
|
/** Any company-owned channel (company or project scope) can carry reports; personal channels cannot. */
|
|
102
|
-
|
|
102
|
+
function isCompanyReportChannel(channel) {
|
|
103
103
|
if (channel.scope === "personal")
|
|
104
104
|
return false;
|
|
105
105
|
return channel.scope === "company" || channel.scope === "project" || Boolean(channel.companyUid);
|
|
@@ -125,7 +125,7 @@ async function readReportInChannel(token, channelId, reportId) {
|
|
|
125
125
|
* caller can see knows its company, and publish needs it to pick the deploy
|
|
126
126
|
* org, so fill it from there rather than failing every publish.
|
|
127
127
|
*/
|
|
128
|
-
|
|
128
|
+
function withChannelCompany(report, channels) {
|
|
129
129
|
if (report.companyUid)
|
|
130
130
|
return report;
|
|
131
131
|
const companyUid = channels.find((row) => row.channelId === report.channelId)?.companyUid;
|
|
@@ -232,7 +232,7 @@ async function deployJson(token, route, method, body, extraHeaders = {}) {
|
|
|
232
232
|
return await res.json();
|
|
233
233
|
}
|
|
234
234
|
/** hq-deploy refused the subdomain: another app, not visible to this caller, holds it. */
|
|
235
|
-
|
|
235
|
+
class SubdomainTakenError extends ReportPublishError {
|
|
236
236
|
constructor() {
|
|
237
237
|
super("hq-deploy rejected the report deployment.");
|
|
238
238
|
}
|
|
@@ -245,7 +245,7 @@ export class SubdomainTakenError extends ReportPublishError {
|
|
|
245
245
|
export function candidateSlugs(slug, attempts = 3) {
|
|
246
246
|
return [slug, ...Array.from({ length: attempts }, (_, i) => `${slug}-${i + 2}`)];
|
|
247
247
|
}
|
|
248
|
-
|
|
248
|
+
async function resolveCompanySlug(token, companyUid) {
|
|
249
249
|
const res = await vaultApiFetch({ token, path: `/entity/${encodeURIComponent(companyUid)}` });
|
|
250
250
|
if (!res.ok)
|
|
251
251
|
throw new ReportPublishError("Could not resolve the report's company for deploy.");
|
|
@@ -290,7 +290,7 @@ export async function findOrCreateApp(token, slug, org) {
|
|
|
290
290
|
throw new ReportPublishError("hq-deploy returned an incomplete app record.");
|
|
291
291
|
return { id, subdomain };
|
|
292
292
|
}
|
|
293
|
-
|
|
293
|
+
async function deployReportStatic(token, input) {
|
|
294
294
|
const app = await findOrCreateApp(token, input.slug, input.org);
|
|
295
295
|
await deployJson(token, `/api/apps/${encodeURIComponent(app.id)}/access-policy`, "PUT", input.access, input.org.headers);
|
|
296
296
|
const tarball = buildReportTarball(input.files);
|
|
@@ -525,7 +525,7 @@ export function registerReportCommand(program) {
|
|
|
525
525
|
print(templates, options.json === true);
|
|
526
526
|
});
|
|
527
527
|
}
|
|
528
|
-
|
|
528
|
+
async function runReportCommand(action) {
|
|
529
529
|
try {
|
|
530
530
|
await action();
|
|
531
531
|
}
|
package/dist/fast-core.js
CHANGED
|
@@ -21,8 +21,11 @@ export async function runFastCore(argv) {
|
|
|
21
21
|
const entry = parsed.entry;
|
|
22
22
|
// The full graph's process gate accepts textual true/false overrides. It ignores
|
|
23
23
|
// numeric env values, so preserve that behavior for family flags here too.
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
let familyEnabled = true;
|
|
25
|
+
if (entry.kind === "native" && entry.familyFlagKey) {
|
|
26
|
+
const envOverride = localBooleanFlagOverride(entry.familyFlagKey, process.env);
|
|
27
|
+
familyEnabled = envOverride ?? await (await import("./native-fast-route.js")).fastFlagEnabled(entry.familyFlagKey, process.env, { numericEnvironmentOverride: false });
|
|
28
|
+
}
|
|
26
29
|
const useShell = entry.kind === "native" && Boolean(entry.familyFlagKey) && !familyEnabled;
|
|
27
30
|
const shouldInjectRoot = useShell
|
|
28
31
|
? entry.shellHqRoot === "live" || (entry.shellHqRoot === "reconcile-default" &&
|
|
@@ -87,4 +90,14 @@ export async function runFastCore(argv) {
|
|
|
87
90
|
// Propagate verbatim: these scripts use their exit code as their interface.
|
|
88
91
|
process.exit(code);
|
|
89
92
|
}
|
|
93
|
+
/** Match hq-flags-client's literal true/false env override without loading its module. */
|
|
94
|
+
function localBooleanFlagOverride(flagKey, env) {
|
|
95
|
+
const envKey = `HQ_FLAG_${flagKey.replace(/[.-]/g, "_").toUpperCase()}`;
|
|
96
|
+
const value = env[envKey];
|
|
97
|
+
if (value === "true")
|
|
98
|
+
return true;
|
|
99
|
+
if (value === "false")
|
|
100
|
+
return false;
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
90
103
|
//# sourceMappingURL=fast-core.js.map
|
package/dist/fast-scaffold.js
CHANGED
|
@@ -11,8 +11,31 @@
|
|
|
11
11
|
*/
|
|
12
12
|
/** The relocated scripts that qualify for the entrypoint fast path. */
|
|
13
13
|
export const FAST_SCAFFOLD_SCRIPTS = [
|
|
14
|
-
{
|
|
15
|
-
|
|
14
|
+
{
|
|
15
|
+
name: "checkpoint-stop-gate",
|
|
16
|
+
kind: "native",
|
|
17
|
+
modulePath: "./commands/core-checkpoint-stop-gate-native.js",
|
|
18
|
+
exportName: "runCheckpointStopGateFast",
|
|
19
|
+
flagKey: "hq-core-native-fast-route",
|
|
20
|
+
familyFlagKey: "core-native-session",
|
|
21
|
+
asset: "core/scripts/checkpoint-stop-gate.sh",
|
|
22
|
+
root: "live",
|
|
23
|
+
shellCwd: "live",
|
|
24
|
+
shellHqRoot: "live",
|
|
25
|
+
readsStdin: true,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "hq-session",
|
|
29
|
+
kind: "native",
|
|
30
|
+
modulePath: "./commands/core-hq-session-native.js",
|
|
31
|
+
exportName: "runHqSessionFast",
|
|
32
|
+
flagKey: "hq-core-native-fast-route",
|
|
33
|
+
familyFlagKey: "core-native-session",
|
|
34
|
+
asset: "core/scripts/hq-session.sh",
|
|
35
|
+
root: "live",
|
|
36
|
+
shellCwd: "live",
|
|
37
|
+
shellHqRoot: "live",
|
|
38
|
+
},
|
|
16
39
|
{
|
|
17
40
|
name: "timeout-guard",
|
|
18
41
|
kind: "native",
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,14 @@ if (isVersionRequest(process.argv)) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
else if (parseFastCore(process.argv)?.entry.kind === "native" &&
|
|
39
|
+
(process.env.HQ_FLAG_HQ_CORE_NATIVE_FAST_ROUTE === "true" ||
|
|
40
|
+
process.env.HQ_FLAG_HQ_CORE_NATIVE_FAST_ROUTE === "1")) {
|
|
41
|
+
// An explicit enabled override has already decided the global gate. Skip the
|
|
42
|
+
// snapshot reader import on hot native plumbing paths; runFastCore still
|
|
43
|
+
// checks the command-family flag before choosing native or shell rollback.
|
|
44
|
+
void import("./fast-core.js").then(({ runFastCore }) => runFastCore(process.argv));
|
|
45
|
+
}
|
|
38
46
|
else if (parseFastCore(process.argv)?.entry.kind === "native") {
|
|
39
47
|
// Native routes are default-off. Resolve the company-scoped persisted flag
|
|
40
48
|
// without loading the command graph; a miss or stale snapshot takes the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BotConfig } from "./config.js";
|
|
2
|
-
|
|
2
|
+
interface ContinuityFile {
|
|
3
3
|
area: "worker" | "memory";
|
|
4
4
|
path: string;
|
|
5
5
|
bytes: number;
|
|
@@ -63,4 +63,5 @@ export declare function planFleetContinuity(bundle: BotContinuityBundle, target:
|
|
|
63
63
|
sha256: string;
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
|
+
export {};
|
|
66
67
|
//# sourceMappingURL=continuity.d.ts.map
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
* everything it needs in its own prompt.
|
|
46
46
|
*/
|
|
47
47
|
import type { JobRunStatus } from "./api.js";
|
|
48
|
-
export declare const BOT_JOB_COMPLETIONS_NAME = "job-completions.json";
|
|
49
48
|
/** First retry gap; each failure doubles it. */
|
|
50
49
|
export declare const COMPLETION_RETRY_BASE_MS = 2000;
|
|
51
50
|
/** Never wait longer than this between retries. */
|
|
@@ -75,7 +74,6 @@ export interface PendingJobCompletion {
|
|
|
75
74
|
/** Epoch ms before which this must not be retried (exponential backoff). */
|
|
76
75
|
nextAttemptAt: number;
|
|
77
76
|
}
|
|
78
|
-
export declare function botJobCompletionsPath(dir: string): string;
|
|
79
77
|
export declare function readPendingJobCompletions(dir: string): PendingJobCompletion[];
|
|
80
78
|
/** The gap before attempt N (1-based), doubling and capped. */
|
|
81
79
|
export declare function completionRetryDelayMs(attempts: number): number;
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
*/
|
|
47
47
|
import * as fs from "node:fs";
|
|
48
48
|
import * as path from "node:path";
|
|
49
|
-
|
|
49
|
+
const BOT_JOB_COMPLETIONS_NAME = "job-completions.json";
|
|
50
50
|
/** First retry gap; each failure doubles it. */
|
|
51
51
|
export const COMPLETION_RETRY_BASE_MS = 2_000;
|
|
52
52
|
/** Never wait longer than this between retries. */
|
|
@@ -57,7 +57,7 @@ export const COMPLETION_RETRY_MAX_MS = 5 * 60_000;
|
|
|
57
57
|
* in-progress slot on its own, so a later report changes nothing.
|
|
58
58
|
*/
|
|
59
59
|
export const MAX_COMPLETION_AGE_MS = 60 * 60_000;
|
|
60
|
-
|
|
60
|
+
function botJobCompletionsPath(dir) {
|
|
61
61
|
return path.join(dir, BOT_JOB_COMPLETIONS_NAME);
|
|
62
62
|
}
|
|
63
63
|
function isPending(raw) {
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
* live only in ~/.hq/bots/<name>/machine-creds.json and never travel here.
|
|
11
11
|
*/
|
|
12
12
|
import { type BotConfig, type BotKind, type BotMemoryMode, type BotRuntimeId } from "./config.js";
|
|
13
|
-
/** Same limit the server enforces on the stored value. */
|
|
14
|
-
export declare const BOT_LOCAL_CONFIG_MAX_BYTES: number;
|
|
15
|
-
/** Key names the server rejects outright (case-insensitive, substring). */
|
|
16
|
-
export declare const BOT_LOCAL_CONFIG_FORBIDDEN_KEY_RE: RegExp;
|
|
17
13
|
/**
|
|
18
14
|
* Everything needed to rebuild a bot here, minus anything secret. Written on
|
|
19
15
|
* create, returned by `GET /v1/agents/mine?local=1` and by the credential
|
|
@@ -62,10 +58,4 @@ export declare const BOT_RESTORE_DEFAULTS: {
|
|
|
62
58
|
};
|
|
63
59
|
/** Human summary of the settings a restore is about to apply. */
|
|
64
60
|
export declare function describeBotLocalConfig(local: BotLocalConfig | null): string;
|
|
65
|
-
/** Exported so callers can present the accepted values without importing config.ts. */
|
|
66
|
-
export declare const BOT_LOCAL_CONFIG_VALUES: {
|
|
67
|
-
readonly runtimes: readonly ["claude", "codex", "grok"];
|
|
68
|
-
readonly kinds: readonly ["personal", "company"];
|
|
69
|
-
readonly memoryModes: readonly ["synced", "local"];
|
|
70
|
-
};
|
|
71
61
|
//# sourceMappingURL=local-config.d.ts.map
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
* checks the result before it leaves this machine: a bot's machine credentials
|
|
10
10
|
* live only in ~/.hq/bots/<name>/machine-creds.json and never travel here.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import { botMemoryMode, effectiveBotCompanies, effectiveBotKind, isBotKind, isBotMemoryMode, isBotRuntimeId, } from "./config.js";
|
|
13
13
|
/** Same limit the server enforces on the stored value. */
|
|
14
|
-
|
|
14
|
+
const BOT_LOCAL_CONFIG_MAX_BYTES = 8 * 1024;
|
|
15
15
|
/** Key names the server rejects outright (case-insensitive, substring). */
|
|
16
|
-
|
|
16
|
+
const BOT_LOCAL_CONFIG_FORBIDDEN_KEY_RE = /secret|token|password|creds/i;
|
|
17
17
|
/** Walks a value and throws when any key looks like it could carry a secret. */
|
|
18
18
|
export function assertNoSecretKeys(value, path = "localConfig") {
|
|
19
19
|
if (Array.isArray(value)) {
|
|
@@ -142,10 +142,4 @@ export function describeBotLocalConfig(local) {
|
|
|
142
142
|
bits.push(local.model);
|
|
143
143
|
return bits.join(", ");
|
|
144
144
|
}
|
|
145
|
-
/** Exported so callers can present the accepted values without importing config.ts. */
|
|
146
|
-
export const BOT_LOCAL_CONFIG_VALUES = {
|
|
147
|
-
runtimes: BOT_RUNTIMES,
|
|
148
|
-
kinds: BOT_KINDS,
|
|
149
|
-
memoryModes: BOT_MEMORY_MODES,
|
|
150
|
-
};
|
|
151
145
|
//# sourceMappingURL=local-config.js.map
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* slugs, uids, roles) reaches the model; the owner's token never does. A failed
|
|
14
14
|
* lookup is reported as "could not check", never as "no companies".
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
interface OwnerCompany {
|
|
17
17
|
companyUid: string;
|
|
18
18
|
/** Present when the server enriched it. */
|
|
19
19
|
companySlug?: string;
|
|
@@ -55,15 +55,10 @@ export interface OwnerLookupIo {
|
|
|
55
55
|
/** Test seam for the retry pause. */
|
|
56
56
|
sleep?: (ms: number) => Promise<void>;
|
|
57
57
|
}
|
|
58
|
-
export declare const defaultOwnerLookupIo: OwnerLookupIo;
|
|
59
|
-
/** A read right after sign-in or bot start can fail once; try again before reporting it. */
|
|
60
|
-
export declare const OWNER_LOOKUP_RETRY_DELAYS_MS: number[];
|
|
61
58
|
export declare function lookupOwnerContext(ownerUid: string, io?: OwnerLookupIo): Promise<OwnerContext>;
|
|
62
59
|
/** Successful lookups are reused for 5 minutes, failures retried after 1 minute. */
|
|
63
60
|
export declare const OWNER_CONTEXT_TTL_MS: number;
|
|
64
61
|
export declare const OWNER_CONTEXT_RETRY_MS = 60000;
|
|
65
|
-
/** A turn never waits longer than this for a refresh; the lookup keeps going in the background. */
|
|
66
|
-
export declare const OWNER_CONTEXT_WAIT_MS = 8000;
|
|
67
62
|
export declare class OwnerContextCache {
|
|
68
63
|
private readonly lookup;
|
|
69
64
|
private readonly nowMs;
|
|
@@ -80,4 +75,5 @@ export declare class OwnerContextCache {
|
|
|
80
75
|
* model cannot confuse the owner's memberships with its own.
|
|
81
76
|
*/
|
|
82
77
|
export declare function ownerContextBlock(ctx: OwnerContext, agentUid: string): string;
|
|
78
|
+
export {};
|
|
83
79
|
//# sourceMappingURL=owner-context.d.ts.map
|
|
@@ -18,7 +18,7 @@ import { resolveCallerPersonUid, vaultApiFetch } from "../../utils/vault-api.js"
|
|
|
18
18
|
function message(err) {
|
|
19
19
|
return err instanceof Error ? err.message : String(err);
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const defaultOwnerLookupIo = {
|
|
22
22
|
// tokenSource "person" never uses the bot's machine creds, even though
|
|
23
23
|
// HQ_MACHINE_CREDS_FILE is set for this process.
|
|
24
24
|
personToken: () => ensureCognitoToken({ tokenSource: "person", interactive: false }),
|
|
@@ -34,7 +34,7 @@ export const defaultOwnerLookupIo = {
|
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
36
|
/** A read right after sign-in or bot start can fail once; try again before reporting it. */
|
|
37
|
-
|
|
37
|
+
const OWNER_LOOKUP_RETRY_DELAYS_MS = [1_000, 2_000];
|
|
38
38
|
async function withRetry(fn, io) {
|
|
39
39
|
const sleep = io.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
40
40
|
let lastErr;
|
|
@@ -84,7 +84,7 @@ export async function lookupOwnerContext(ownerUid, io = defaultOwnerLookupIo) {
|
|
|
84
84
|
export const OWNER_CONTEXT_TTL_MS = 5 * 60_000;
|
|
85
85
|
export const OWNER_CONTEXT_RETRY_MS = 60_000;
|
|
86
86
|
/** A turn never waits longer than this for a refresh; the lookup keeps going in the background. */
|
|
87
|
-
|
|
87
|
+
const OWNER_CONTEXT_WAIT_MS = 8_000;
|
|
88
88
|
export class OwnerContextCache {
|
|
89
89
|
lookup;
|
|
90
90
|
nowMs;
|
|
@@ -16,10 +16,6 @@
|
|
|
16
16
|
export declare const EXPLAIN_HQ_SUGGESTION = "Explain HQ first";
|
|
17
17
|
/** Where the explanation lives, relative to the setup worker folder. */
|
|
18
18
|
export declare const EXPLAIN_HQ_FILE: string;
|
|
19
|
-
/** The setup bot's progress note in its memory folder (setup worker.yaml). */
|
|
20
|
-
export declare const SETUP_PROGRESS_FILE = "setup-progress.md";
|
|
21
|
-
/** Runner-owned state, in the bot's own folder (never the model's memory). */
|
|
22
|
-
export declare const SETUP_INTRO_STATE_FILE = "setup-intro.json";
|
|
23
19
|
/**
|
|
24
20
|
* Put in front of the next message from the person, so the model knows the
|
|
25
21
|
* explanation went out without it. It never reaches the person.
|
|
@@ -19,9 +19,9 @@ export const EXPLAIN_HQ_SUGGESTION = "Explain HQ first";
|
|
|
19
19
|
/** Where the explanation lives, relative to the setup worker folder. */
|
|
20
20
|
export const EXPLAIN_HQ_FILE = path.join("skills", "explain-hq.md");
|
|
21
21
|
/** The setup bot's progress note in its memory folder (setup worker.yaml). */
|
|
22
|
-
|
|
22
|
+
const SETUP_PROGRESS_FILE = "setup-progress.md";
|
|
23
23
|
/** Runner-owned state, in the bot's own folder (never the model's memory). */
|
|
24
|
-
|
|
24
|
+
const SETUP_INTRO_STATE_FILE = "setup-intro.json";
|
|
25
25
|
const EXPLANATION_HEADING = /^##[ \t]+The explanation[ \t]*$/m;
|
|
26
26
|
const CLOSING_HEADING = /^##[ \t]+After the explanation, when the app sends it[ \t]*$/m;
|
|
27
27
|
/**
|
|
@@ -23,7 +23,7 @@ export declare function enabledServices(machineType: MachineType, overrides: {
|
|
|
23
23
|
enable: readonly string[];
|
|
24
24
|
disable: readonly string[];
|
|
25
25
|
}): ServiceName[];
|
|
26
|
-
|
|
26
|
+
type UnitCommand = {
|
|
27
27
|
type: "hq";
|
|
28
28
|
args: string[];
|
|
29
29
|
} | {
|
|
@@ -38,7 +38,7 @@ export type UnitCommand = {
|
|
|
38
38
|
type: "internal";
|
|
39
39
|
task: "rotate-logs";
|
|
40
40
|
};
|
|
41
|
-
|
|
41
|
+
interface UnitBlock {
|
|
42
42
|
/** `waiting` clears on its own once the requirement appears; `unavailable` needs a newer CLI. */
|
|
43
43
|
state: "waiting" | "unavailable";
|
|
44
44
|
reason: string;
|
|
@@ -128,4 +128,5 @@ export declare const CODEX_RUNNER_SCRIPT = "/usr/local/bin/outpost-codex-runner.
|
|
|
128
128
|
export declare const CLAUDE_RUNNER_SCRIPT = "/usr/local/bin/outpost-runner.sh";
|
|
129
129
|
/** Turn enabled services into concrete units for this host. */
|
|
130
130
|
export declare function planUnits(services: readonly ServiceName[], ctx: PlanContext): UnitPlan[];
|
|
131
|
+
export {};
|
|
131
132
|
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -52,7 +52,6 @@ export declare function hqCloudInstallCommand(prefix: string, version: string, p
|
|
|
52
52
|
args: string[];
|
|
53
53
|
shell: boolean;
|
|
54
54
|
};
|
|
55
|
-
export declare function readHqCloudCopy(root: string): HqCloudCopy | null;
|
|
56
55
|
/** The copy bundled with this CLI. */
|
|
57
56
|
export declare function bundledHqCloud(): HqCloudCopy | null;
|
|
58
57
|
/** The hq-cloud the daemon should run right now. */
|
|
@@ -63,7 +62,7 @@ export interface HqCloudUpdateOutcome {
|
|
|
63
62
|
to: string | null;
|
|
64
63
|
detail?: string;
|
|
65
64
|
}
|
|
66
|
-
|
|
65
|
+
interface NpmRunResult {
|
|
67
66
|
status: number | null;
|
|
68
67
|
stdout?: string | null;
|
|
69
68
|
stderr?: string | null;
|
|
@@ -76,4 +75,5 @@ export interface UpdateHqCloudDeps {
|
|
|
76
75
|
}
|
|
77
76
|
/** Install or update the updater's copy, as this (the login) user. */
|
|
78
77
|
export declare function updateManagedHqCloud(daemonRoot: string, env: NodeJS.ProcessEnv, deps?: UpdateHqCloudDeps): HqCloudUpdateOutcome;
|
|
78
|
+
export {};
|
|
79
79
|
//# sourceMappingURL=hq-cloud.d.ts.map
|
|
@@ -108,7 +108,7 @@ export function hqCloudInstallCommand(prefix, version, platform = process.platfo
|
|
|
108
108
|
const plan = buildSpawnPlan("npm", ["install", "--prefix", prefix, "--no-audit", "--no-fund", "--omit=dev", `${HQ_CLOUD_PACKAGE}@${version}`], platform);
|
|
109
109
|
return { file: plan.cmd, args: plan.args, shell: plan.shell };
|
|
110
110
|
}
|
|
111
|
-
|
|
111
|
+
function readHqCloudCopy(root) {
|
|
112
112
|
try {
|
|
113
113
|
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
|
|
114
114
|
return typeof pkg.version === "string" ? { root, version: pkg.version } : null;
|
|
@@ -12,12 +12,10 @@
|
|
|
12
12
|
* 6. macOS or Windows → desktop
|
|
13
13
|
* 7. any other host → self-hosted
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
declare const MACHINE_TYPES: readonly ["desktop", "self-hosted", "outpost", "agent-box", "agent-kit"];
|
|
16
16
|
export type MachineType = (typeof MACHINE_TYPES)[number];
|
|
17
17
|
export declare const MACHINE_TYPE_MARKER_PATH = "/etc/hq/machine-type";
|
|
18
|
-
|
|
19
|
-
/** The Claude runner unit outpost provisioning installs; its `User=` is the box's login user. */
|
|
20
|
-
export declare const OUTPOST_RUNNER_UNIT = "/etc/systemd/system/outpost-runner.service";
|
|
18
|
+
type MachineTypeSource = "flag" | "config" | "marker" | "outpost-units" | "agent-kit-creds" | "container" | "platform";
|
|
21
19
|
export interface MachineTypeResult {
|
|
22
20
|
type: MachineType;
|
|
23
21
|
source: MachineTypeSource;
|
|
@@ -48,4 +46,5 @@ export declare function parseMachineTypeMarker(text: string): {
|
|
|
48
46
|
export declare function detectMachineType(flag: string | undefined, deps: DetectMachineTypeDeps): MachineTypeResult;
|
|
49
47
|
/** The home directory of `user` in passwd-format text, or null when the account is not listed. */
|
|
50
48
|
export declare function homeFromPasswd(passwd: string, user: string): string | null;
|
|
49
|
+
export {};
|
|
51
50
|
//# sourceMappingURL=machine-type.d.ts.map
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import * as path from "node:path";
|
|
16
16
|
import { AGENT_DIR_ENV, MACHINE_CREDS_NAME, agentRootDir } from "../agent-kit/paths.js";
|
|
17
|
-
|
|
17
|
+
const MACHINE_TYPES = ["desktop", "self-hosted", "outpost", "agent-box", "agent-kit"];
|
|
18
18
|
export const MACHINE_TYPE_MARKER_PATH = "/etc/hq/machine-type";
|
|
19
19
|
/** The Claude runner unit outpost provisioning installs; its `User=` is the box's login user. */
|
|
20
|
-
|
|
20
|
+
const OUTPOST_RUNNER_UNIT = "/etc/systemd/system/outpost-runner.service";
|
|
21
21
|
export function isMachineType(value) {
|
|
22
22
|
return typeof value === "string" && MACHINE_TYPES.includes(value);
|
|
23
23
|
}
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
* user's own tmux sessions.
|
|
22
22
|
*/
|
|
23
23
|
import type { RunCommand } from "../service-manager/launchd.js";
|
|
24
|
-
export declare const TMUX_SOCKET = "hq-daemon";
|
|
25
24
|
export declare const TMUX_SESSION = "remote-control";
|
|
26
25
|
export declare const CODEX_TMUX_SESSION = "codex-remote-control";
|
|
27
26
|
export declare function remoteControlArgs(opts: {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import * as fs from "node:fs";
|
|
24
24
|
import * as path from "node:path";
|
|
25
|
-
|
|
25
|
+
const TMUX_SOCKET = "hq-daemon";
|
|
26
26
|
export const TMUX_SESSION = "remote-control";
|
|
27
27
|
export const CODEX_TMUX_SESSION = "codex-remote-control";
|
|
28
28
|
export function remoteControlArgs(opts) {
|
|
@@ -25,9 +25,6 @@ import type { UnitPlan } from "./catalog.js";
|
|
|
25
25
|
import type { MachineType } from "./machine-type.js";
|
|
26
26
|
import type { ControlRequest } from "./requests.js";
|
|
27
27
|
import { syncPassResult } from "./sync-runner.js";
|
|
28
|
-
export declare const BACKOFF_BASE_MS = 1000;
|
|
29
|
-
export declare const BACKOFF_MAX_MS = 60000;
|
|
30
|
-
export declare const HEALTHY_RUN_MS = 60000;
|
|
31
28
|
export declare const STOP_ESCALATION_MS = 10000;
|
|
32
29
|
/** After a handoff, how long a replaced unit must stay up before the next one is replaced. */
|
|
33
30
|
export declare const HANDOFF_STAGGER_MS = 15000;
|
|
@@ -42,8 +39,8 @@ export interface SupervisedChild {
|
|
|
42
39
|
on(event: "error", handler: (err: Error) => void): unknown;
|
|
43
40
|
kill(signal?: NodeJS.Signals | number): boolean;
|
|
44
41
|
}
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
type UnitStatus = "running" | "waiting" | "unavailable" | "backoff" | "exited" | "idle" | "stopped";
|
|
43
|
+
interface UnitState {
|
|
47
44
|
id: string;
|
|
48
45
|
service: string;
|
|
49
46
|
kind: UnitPlan["kind"];
|
|
@@ -83,7 +80,7 @@ export interface AdoptedUnit {
|
|
|
83
80
|
child: SupervisedChild;
|
|
84
81
|
}
|
|
85
82
|
/** A long-running service left running by release(). */
|
|
86
|
-
|
|
83
|
+
interface ReleasedUnit {
|
|
87
84
|
id: string;
|
|
88
85
|
pid: number;
|
|
89
86
|
key: string;
|
|
@@ -123,9 +120,6 @@ export interface Supervisor {
|
|
|
123
120
|
/** Stop supervising without signalling any child; returns the long-running units left running. */
|
|
124
121
|
release(): ReleasedUnit[];
|
|
125
122
|
}
|
|
126
|
-
/** Plan reads in a row that must find a running remote-control host blocked before it is paused. */
|
|
127
|
-
export declare const BLOCKED_READS_BEFORE_PAUSE = 2;
|
|
128
|
-
export declare function backoffMs(attempt: number): number;
|
|
129
123
|
/**
|
|
130
124
|
* What a unit's process was started from; a unit whose key changes is
|
|
131
125
|
* restarted. The CLI version counts only for `hq` commands, so a CLI update
|
|
@@ -134,4 +128,5 @@ export declare function backoffMs(attempt: number): number;
|
|
|
134
128
|
*/
|
|
135
129
|
export declare function planKey(plan: UnitPlan, cliVersion?: string): string;
|
|
136
130
|
export declare function createSupervisor(deps: SupervisorDeps): Supervisor;
|
|
131
|
+
export {};
|
|
137
132
|
//# sourceMappingURL=supervisor.d.ts.map
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { StringDecoder } from "node:string_decoder";
|
|
25
25
|
import { SYNC_RUNNER_LEASE_CONFLICT_EXIT, SYNC_RUNNER_LEASE_RETRY_MS, parseSyncRunnerProtocolLine, syncPassResult, } from "./sync-runner.js";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const BACKOFF_BASE_MS = 1_000;
|
|
27
|
+
const BACKOFF_MAX_MS = 60_000;
|
|
28
|
+
const HEALTHY_RUN_MS = 60_000;
|
|
29
29
|
export const STOP_ESCALATION_MS = 10_000;
|
|
30
30
|
const MESH_OWNER_RECHECK_MS = 15_000;
|
|
31
31
|
const MESH_OWNER_LOG_INTERVAL_MS = 10 * 60_000;
|
|
@@ -34,8 +34,8 @@ export const HANDOFF_STAGGER_MS = 15_000;
|
|
|
34
34
|
/** How long a draining unit may take to finish its work before it gets SIGTERM. */
|
|
35
35
|
export const HANDOFF_DRAIN_MAX_MS = 15 * 60_000;
|
|
36
36
|
/** Plan reads in a row that must find a running remote-control host blocked before it is paused. */
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const BLOCKED_READS_BEFORE_PAUSE = 2;
|
|
38
|
+
function backoffMs(attempt) {
|
|
39
39
|
return Math.min(BACKOFF_MAX_MS, BACKOFF_BASE_MS * 2 ** Math.max(0, attempt));
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AdmissionHost } from "./admission.js";
|
|
2
|
+
import type { LaneHost } from "./types.js";
|
|
2
3
|
export declare const OUTPOST_ID_PATH = "/etc/outpost/outpost-id";
|
|
3
4
|
export declare const OUTPOST_DIR = "/etc/outpost";
|
|
4
5
|
export type OutpostIdentity = {
|
|
@@ -16,4 +17,6 @@ export declare function resolveAdmissionHost(deps?: {
|
|
|
16
17
|
existsSync?: (p: string) => boolean;
|
|
17
18
|
readFileSync?: (p: string) => string;
|
|
18
19
|
}): AdmissionHost;
|
|
20
|
+
/** `primary` names the controller registry unless the caller is a different Outpost. */
|
|
21
|
+
export declare function isControllerAliasOutpostId(outpostId: string, localHost: LaneHost): boolean;
|
|
19
22
|
//# sourceMappingURL=admission-host.d.ts.map
|
|
@@ -30,4 +30,8 @@ export function resolveAdmissionHost(deps = {}) {
|
|
|
30
30
|
outpostId: identity.kind === "id" ? identity.id : null,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
/** `primary` names the controller registry unless the caller is a different Outpost. */
|
|
34
|
+
export function isControllerAliasOutpostId(outpostId, localHost) {
|
|
35
|
+
return outpostId === "primary" && !(localHost.kind === "outpost" && localHost.id !== "primary");
|
|
36
|
+
}
|
|
33
37
|
//# sourceMappingURL=admission-host.js.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { LaneCompanyRef, LaneHost } from "./types.js";
|
|
2
|
+
export declare const OUTPOST_LEAD_REGISTRY_SCHEMA = "hq-lanes-outpost-lead-registry.v1";
|
|
3
|
+
export declare const OUTPOST_LEAD_REGISTRY_MAX_AGE_MS: number;
|
|
4
|
+
export declare const OUTPOST_LEAD_REGISTRY_REFRESH_MS: number;
|
|
5
|
+
export declare const LEAD_REGISTRY_REL: string;
|
|
6
|
+
export declare const OUTPOST_LEAD_REGISTRY_STATE_REL: string;
|
|
7
|
+
export declare const LEAD_AUTOPILOT_FLAG = "lanes.lead-autopilot";
|
|
8
|
+
export interface LeadRegistryRow {
|
|
9
|
+
team: string;
|
|
10
|
+
lane: string;
|
|
11
|
+
host: string;
|
|
12
|
+
status: string;
|
|
13
|
+
prd: string;
|
|
14
|
+
}
|
|
15
|
+
export interface OutpostLeadRegistry {
|
|
16
|
+
schema_version: typeof OUTPOST_LEAD_REGISTRY_SCHEMA;
|
|
17
|
+
outpost_id: string;
|
|
18
|
+
generated_at: string;
|
|
19
|
+
juniors: LeadRegistryRow[];
|
|
20
|
+
}
|
|
21
|
+
export declare function buildOutpostLeadRegistry(input: {
|
|
22
|
+
rows: readonly LeadRegistryRow[];
|
|
23
|
+
outpostId: string;
|
|
24
|
+
generatedAt: string;
|
|
25
|
+
}): OutpostLeadRegistry;
|
|
26
|
+
/** Stage a host-filtered registry on the Outpost using an atomic local rename. */
|
|
27
|
+
export declare function buildOutpostLeadRegistryInstallCommand(registry: OutpostLeadRegistry): string;
|
|
28
|
+
export declare function syncOutpostLeadRegistries(input: {
|
|
29
|
+
hqRoot: string;
|
|
30
|
+
outpostIds: readonly string[];
|
|
31
|
+
generatedAt: string;
|
|
32
|
+
localHost: LaneHost;
|
|
33
|
+
resolveCompany: (slug: string) => Promise<LaneCompanyRef>;
|
|
34
|
+
readFlag: (flag: string, options: {
|
|
35
|
+
company: LaneCompanyRef;
|
|
36
|
+
}) => Promise<boolean>;
|
|
37
|
+
dispatch: (request: {
|
|
38
|
+
outpostId: string;
|
|
39
|
+
command: string;
|
|
40
|
+
timeoutSeconds?: number;
|
|
41
|
+
waitMs?: number;
|
|
42
|
+
}) => Promise<{
|
|
43
|
+
done?: boolean;
|
|
44
|
+
exitCode: number | null;
|
|
45
|
+
stdout: string;
|
|
46
|
+
stderr: string;
|
|
47
|
+
}>;
|
|
48
|
+
}): Promise<Array<{
|
|
49
|
+
outpost_id: string;
|
|
50
|
+
row_count: number;
|
|
51
|
+
skipped: Array<{
|
|
52
|
+
lane: string;
|
|
53
|
+
reason: string;
|
|
54
|
+
}>;
|
|
55
|
+
dispatched: boolean;
|
|
56
|
+
}>>;
|
|
57
|
+
export declare function validateOutpostLeadRegistry(input: {
|
|
58
|
+
registry: unknown;
|
|
59
|
+
outpostId: string;
|
|
60
|
+
now: Date;
|
|
61
|
+
}): OutpostLeadRegistry;
|
|
62
|
+
//# sourceMappingURL=autopilot-registry.d.ts.map
|