@indigoai-us/hq-cli 5.180.0 → 5.182.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 +12 -0
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/mesh.d.ts +11 -0
- package/dist/commands/mesh.js +7 -5
- package/dist/lib/daemon/catalog.d.ts +7 -4
- package/dist/lib/daemon/catalog.js +15 -6
- package/dist/lib/daemon/hq-cloud.d.ts +3 -1
- package/dist/lib/daemon/hq-cloud.js +6 -2
- package/dist/lib/daemon/run.js +2 -1
- package/dist/lib/mesh/live/daemon/index.d.ts +1 -1
- package/dist/lib/mesh/live/daemon/index.js +1 -1
- package/dist/lib/mesh/live/daemon/install.d.ts +5 -0
- package/dist/lib/mesh/live/daemon/install.js +15 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.182.0] — 2026-09-24
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `hq mesh daemon status` now asks the service manager whether the daemon is loaded (`launchctl print` on macOS, `systemctl --user is-active` on Linux). Before, it never probed and always reported "installed (not loaded)" or "installed (inactive)", even while the daemon was running.
|
|
10
|
+
|
|
11
|
+
## [5.181.0] — 2026-09-24
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `hq daemon` runs the session host from the hq-cloud copy it keeps up to date (hq-cloud's `hq-outpost-session-host`, when that copy has it), the same way it already runs sync and the outpost heartbeat, and restarts it after an hq-cloud update. Session-host fixes, such as starting on an Outpost that signs in with machine credentials, now reach boxes without an hq CLI release.
|
|
16
|
+
|
|
5
17
|
## [5.180.0] — 2026-09-24
|
|
6
18
|
|
|
7
19
|
## [5.179.1] — 2026-09-24
|
package/dist/commands/daemon.js
CHANGED
|
@@ -432,7 +432,7 @@ async function runServiceSelfUpdate(d) {
|
|
|
432
432
|
updateCli: cliSelfUpdatable() ? () => daemonSelfUpdate({ env }) : null,
|
|
433
433
|
tools: TOOL_NAMES.map((name) => hostToolUpdater(name, env, d.home)),
|
|
434
434
|
updateHqCloud: async () => updateManagedHqCloud(paths.root, env),
|
|
435
|
-
hqCloudUnits: hqCloudUnits(detected.type),
|
|
435
|
+
hqCloudUnits: hqCloudUnits(detected.type, enabledServices(detected.type, readDaemonConfig(paths.configPath))),
|
|
436
436
|
requestDaemonRestart: () => writeControlRequest(paths.requestsDir, { action: "restart-daemon" }),
|
|
437
437
|
requestRestart: (unit) => writeControlRequest(paths.requestsDir, { action: "restart", unit }),
|
|
438
438
|
log: d.out,
|
package/dist/commands/mesh.d.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
import { type MeshCompany, type MeshThread } from "../lib/mesh/api.js";
|
|
10
|
+
import { type DaemonInstallPlatform, type InstallPaths } from "../lib/mesh/live/daemon/index.js";
|
|
11
|
+
import { type RunCommand } from "../lib/service-manager/launchd.js";
|
|
10
12
|
export declare function formatCheckLines(threads: MeshThread[], company: MeshCompany, projectId?: string): string[];
|
|
11
13
|
/** Injectable confirmation seam for `hq mesh context correct` (stubbed in tests). */
|
|
12
14
|
export type MeshConfirmFn = (message: string) => Promise<boolean>;
|
|
@@ -24,4 +26,13 @@ export declare function runContextCorrect(opts: {
|
|
|
24
26
|
confirm?: MeshConfirmFn;
|
|
25
27
|
}): Promise<void>;
|
|
26
28
|
export declare function registerMeshCommand(program: Command): void;
|
|
29
|
+
export declare function runDaemonStatus(opts: {
|
|
30
|
+
json?: boolean;
|
|
31
|
+
}, deps?: {
|
|
32
|
+
platform?: DaemonInstallPlatform;
|
|
33
|
+
paths?: InstallPaths;
|
|
34
|
+
/** launchctl/systemctl runner for the loaded probe (tests inject). */
|
|
35
|
+
run?: RunCommand;
|
|
36
|
+
uid?: number;
|
|
37
|
+
}): Promise<void>;
|
|
27
38
|
//# sourceMappingURL=mesh.d.ts.map
|
package/dist/commands/mesh.js
CHANGED
|
@@ -35,7 +35,7 @@ import { generateUlid } from "../lib/mesh/live/ulid.js";
|
|
|
35
35
|
import { readLegacyBacklog } from "../lib/mesh/live/emit-replay.js";
|
|
36
36
|
import { resolveMeshEmitMode, writeMeshConfigMode, } from "../lib/mesh/live/daemon/mode.js";
|
|
37
37
|
import { workMeshRoot } from "../lib/mesh/live/paths.js";
|
|
38
|
-
import { buildInstallPaths, collectDaemonDoctor, daemonServiceStatus, findAncestorHqRoot, resolveInstallHqRoot, detectPlatform, formatCliIdentityLines, formatDaemonDoctor, installDaemonIfStale, installDaemonService, readDaemonState, resolveAbsoluteNodeBinary, resolveRunningCliEntry, runMeshDaemon, uninstallDaemonService,
|
|
38
|
+
import { buildInstallPaths, collectDaemonDoctor, daemonServiceIsLoaded, daemonServiceStatus, findAncestorHqRoot, resolveInstallHqRoot, detectPlatform, formatCliIdentityLines, formatDaemonDoctor, installDaemonIfStale, installDaemonService, readDaemonState, resolveAbsoluteNodeBinary, resolveRunningCliEntry, runMeshDaemon, uninstallDaemonService, } from "../lib/mesh/live/daemon/index.js";
|
|
39
39
|
import { defaultRunCommand } from "../lib/service-manager/launchd.js";
|
|
40
40
|
import { workContextRoot } from "../lib/work-context/paths.js";
|
|
41
41
|
import { formatMigrateConfirmation, submitSessionMigration, } from "../lib/work-context/migrate.js";
|
|
@@ -2122,12 +2122,14 @@ async function runDaemonUninstall(opts) {
|
|
|
2122
2122
|
}
|
|
2123
2123
|
console.log(result.message);
|
|
2124
2124
|
}
|
|
2125
|
-
async function runDaemonStatus(opts) {
|
|
2125
|
+
export async function runDaemonStatus(opts, deps = {}) {
|
|
2126
|
+
const paths = deps.paths ?? buildInstallPaths({});
|
|
2126
2127
|
const result = daemonServiceStatus({
|
|
2127
|
-
platform: detectPlatform(),
|
|
2128
|
-
paths
|
|
2128
|
+
platform: deps.platform ?? detectPlatform(),
|
|
2129
|
+
paths,
|
|
2130
|
+
isLoaded: daemonServiceIsLoaded(deps.run ?? defaultRunCommand, deps.uid),
|
|
2129
2131
|
});
|
|
2130
|
-
const state = readDaemonState(daemonDir
|
|
2132
|
+
const state = readDaemonState(paths.daemonDir);
|
|
2131
2133
|
const presenceRefusal = state?.presenceRefusal ?? null;
|
|
2132
2134
|
if (opts.json) {
|
|
2133
2135
|
console.log(JSON.stringify({
|
|
@@ -64,6 +64,8 @@ export interface PlanContext {
|
|
|
64
64
|
syncRunnerPath: string | null;
|
|
65
65
|
/** hq-cloud's `hq-outpost-heartbeat` bin, when the hq-cloud in use has one. */
|
|
66
66
|
heartbeatRunnerPath: string | null;
|
|
67
|
+
/** hq-cloud's `hq-outpost-session-host` bin, when the hq-cloud in use has one. */
|
|
68
|
+
sessionHostRunnerPath: string | null;
|
|
67
69
|
signedIn: boolean;
|
|
68
70
|
/** ~/.hq-agent/kit.json exists. */
|
|
69
71
|
kitConfigured: boolean;
|
|
@@ -89,11 +91,12 @@ export interface PlanContext {
|
|
|
89
91
|
codexRunnerScript: string | null;
|
|
90
92
|
}
|
|
91
93
|
/**
|
|
92
|
-
* The units that run hq-cloud's code on
|
|
93
|
-
*
|
|
94
|
-
*
|
|
94
|
+
* The units that run hq-cloud's code on this host, restarted after the updater
|
|
95
|
+
* installs a new hq-cloud. Only outposts and self-hosted machines run the
|
|
96
|
+
* outpost heartbeat (agent machines run the agent kit's own); the session host
|
|
97
|
+
* is included wherever it is enabled.
|
|
95
98
|
*/
|
|
96
|
-
export declare function hqCloudUnits(machineType: MachineType): ServiceName[];
|
|
99
|
+
export declare function hqCloudUnits(machineType: MachineType, enabled: readonly ServiceName[]): ServiceName[];
|
|
97
100
|
/** Written by outpost provisioning; the daemon runs it rather than re-implementing Codex login and relay setup. */
|
|
98
101
|
export declare const CODEX_RUNNER_SCRIPT = "/usr/local/bin/outpost-codex-runner.sh";
|
|
99
102
|
/** The outpost's Claude runner script, read for the session name it uses. */
|
|
@@ -97,12 +97,18 @@ function firstBlock(checks) {
|
|
|
97
97
|
return hit ? { state: "waiting", reason: hit[1] } : undefined;
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
|
-
* The units that run hq-cloud's code on
|
|
101
|
-
*
|
|
102
|
-
*
|
|
100
|
+
* The units that run hq-cloud's code on this host, restarted after the updater
|
|
101
|
+
* installs a new hq-cloud. Only outposts and self-hosted machines run the
|
|
102
|
+
* outpost heartbeat (agent machines run the agent kit's own); the session host
|
|
103
|
+
* is included wherever it is enabled.
|
|
103
104
|
*/
|
|
104
|
-
export function hqCloudUnits(machineType) {
|
|
105
|
-
|
|
105
|
+
export function hqCloudUnits(machineType, enabled) {
|
|
106
|
+
const units = ["sync"];
|
|
107
|
+
if (machineType === "outpost" || machineType === "self-hosted")
|
|
108
|
+
units.push("heartbeat");
|
|
109
|
+
if (enabled.includes("session-host"))
|
|
110
|
+
units.push("session-host");
|
|
111
|
+
return units;
|
|
106
112
|
}
|
|
107
113
|
/** Written by outpost provisioning; the daemon runs it rather than re-implementing Codex login and relay setup. */
|
|
108
114
|
export const CODEX_RUNNER_SCRIPT = "/usr/local/bin/outpost-codex-runner.sh";
|
|
@@ -181,7 +187,10 @@ function planService(service, ctx) {
|
|
|
181
187
|
case "session-host":
|
|
182
188
|
return [
|
|
183
189
|
base(service, {
|
|
184
|
-
|
|
190
|
+
// hq-cloud's own session host picks up hq-cloud updates without a CLI release.
|
|
191
|
+
command: ctx.sessionHostRunnerPath
|
|
192
|
+
? { type: "node", script: ctx.sessionHostRunnerPath, args: [] }
|
|
193
|
+
: { type: "hq", args: ["outposts", "session-host"] },
|
|
185
194
|
env: ctx.hqRoot ? { HQ_ROOT: ctx.hqRoot } : {},
|
|
186
195
|
blocked: firstBlock([[!ctx.signedIn, NOT_SIGNED_IN]]),
|
|
187
196
|
}),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which hq-cloud the daemon runs sync
|
|
2
|
+
* Which hq-cloud the daemon runs sync, the outpost heartbeat and the session host from.
|
|
3
3
|
*
|
|
4
4
|
* The hq CLI ships with a copy of hq-cloud, but hq-cloud releases more often
|
|
5
5
|
* than the CLI. The updater keeps a newer copy of the same major version in
|
|
@@ -27,6 +27,8 @@ export interface HqCloudRunners {
|
|
|
27
27
|
syncRunner: string | null;
|
|
28
28
|
/** `hq-outpost-heartbeat`, which older hq-cloud releases do not have. */
|
|
29
29
|
heartbeat: string | null;
|
|
30
|
+
/** `hq-outpost-session-host`, which older hq-cloud releases do not have. */
|
|
31
|
+
sessionHost: string | null;
|
|
30
32
|
}
|
|
31
33
|
export declare function hqCloudRunners(root: string, exists?: (p: string) => boolean): HqCloudRunners;
|
|
32
34
|
/** Install the newest release of the bundled major version, never older than the bundled copy. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which hq-cloud the daemon runs sync
|
|
2
|
+
* Which hq-cloud the daemon runs sync, the outpost heartbeat and the session host from.
|
|
3
3
|
*
|
|
4
4
|
* The hq CLI ships with a copy of hq-cloud, but hq-cloud releases more often
|
|
5
5
|
* than the CLI. The updater keeps a newer copy of the same major version in
|
|
@@ -48,7 +48,11 @@ export function hqCloudRunners(root, exists = fs.existsSync) {
|
|
|
48
48
|
const p = path.join(root, "dist", "bin", name);
|
|
49
49
|
return exists(p) ? p : null;
|
|
50
50
|
};
|
|
51
|
-
return {
|
|
51
|
+
return {
|
|
52
|
+
syncRunner: bin("sync-runner.js"),
|
|
53
|
+
heartbeat: bin("outpost-heartbeat.js"),
|
|
54
|
+
sessionHost: bin("outpost-session-host.js"),
|
|
55
|
+
};
|
|
52
56
|
}
|
|
53
57
|
/** Install the newest release of the bundled major version, never older than the bundled copy. */
|
|
54
58
|
export function hqCloudInstallCommand(prefix, bundledVersion, platform = process.platform) {
|
package/dist/lib/daemon/run.js
CHANGED
|
@@ -249,7 +249,7 @@ export async function runDaemon(opts) {
|
|
|
249
249
|
const hqRoot = configured && fs.existsSync(configured) ? configured : undefined;
|
|
250
250
|
// Re-picked every reconcile, so a newer hq-cloud from the updater is used as soon as it lands.
|
|
251
251
|
const hqCloud = currentHqCloud(paths.root);
|
|
252
|
-
const runners = hqCloud ? hqCloudRunners(hqCloud.root) : { syncRunner: null, heartbeat: null };
|
|
252
|
+
const runners = hqCloud ? hqCloudRunners(hqCloud.root) : { syncRunner: null, heartbeat: null, sessionHost: null };
|
|
253
253
|
return planUnits(enabledServices(machineType, config), {
|
|
254
254
|
machineType,
|
|
255
255
|
platform,
|
|
@@ -257,6 +257,7 @@ export async function runDaemon(opts) {
|
|
|
257
257
|
hqRoot,
|
|
258
258
|
syncRunnerPath: runners.syncRunner,
|
|
259
259
|
heartbeatRunnerPath: runners.heartbeat,
|
|
260
|
+
sessionHostRunnerPath: runners.sessionHost,
|
|
260
261
|
signedIn: signedIn(env, home, log),
|
|
261
262
|
kitConfigured: fs.existsSync(agentKitPaths(home, env).kitConfigPath),
|
|
262
263
|
desktopAppManagesSync: machineType === "desktop" &&
|
|
@@ -12,7 +12,7 @@ export type { DaemonStateFile, PresenceRefusalState } from "./state.js";
|
|
|
12
12
|
export { appendDaemonLog, daemonLogLine, ensureDaemonLog, resolveDaemonAssetDir, rotateDaemonLogIfNeeded, } from "./log.js";
|
|
13
13
|
export { BOARD_REFRESH_INTERVAL_MS, createVaultBoardReader, formatBoardMarkdown, refreshBoundSessionBoards, writeBoardMarkdown, } from "./board-refresh.js";
|
|
14
14
|
export type { BoardReader, BoardRefreshDeps, BoardStorySnapshot } from "./board-refresh.js";
|
|
15
|
-
export { buildInstallPaths, daemonServiceStatus, detectPlatform, installDaemonIfStale, installDaemonService, isNewerCliVersion, readAssetTemplate, restartDaemonServiceIfInstalled, renderLaunchdPlist, renderSystemdSystemUnit, renderSystemdUserUnit, resolveAbsoluteNodeBinary, resolveHqBinary, resolveNodeBinary, resolveRunningCliEntry, parseSchtasksLastResult, parseWindowsTaskHqRoot, readRecordedWindowsHqRoot, schtasksLastResultFailed, uninstallDaemonService, windowsLaunchMode, windowsLogonNotice, } from "./install.js";
|
|
15
|
+
export { buildInstallPaths, daemonServiceIsLoaded, daemonServiceStatus, detectPlatform, installDaemonIfStale, installDaemonService, isNewerCliVersion, readAssetTemplate, restartDaemonServiceIfInstalled, renderLaunchdPlist, renderSystemdSystemUnit, renderSystemdUserUnit, resolveAbsoluteNodeBinary, resolveHqBinary, resolveNodeBinary, resolveRunningCliEntry, parseSchtasksLastResult, parseWindowsTaskHqRoot, readRecordedWindowsHqRoot, schtasksLastResultFailed, uninstallDaemonService, windowsLaunchMode, windowsLogonNotice, } from "./install.js";
|
|
16
16
|
export type { DaemonInstallPlatform, InstallIfStaleResult, InstallPaths, InstallResult, } from "./install.js";
|
|
17
17
|
export { daemonConfigPath, findAncestorHqRoot, isInstallableHqRoot, readDaemonConfig, registerTrustedHqRoot, resolveInstallHqRoot, verifyHqRoot, } from "./config.js";
|
|
18
18
|
export type { InstallHqRootResolution } from "./config.js";
|
|
@@ -6,7 +6,7 @@ export { CLOSE_LOG_ALWAYS_COUNT, CLOSE_LOG_INTERVAL_MS, CONNECT_STABLE_GRACE_MS,
|
|
|
6
6
|
export { defaultDaemonState, patchDaemonState, readDaemonState, writeDaemonState, } from "./state.js";
|
|
7
7
|
export { appendDaemonLog, daemonLogLine, ensureDaemonLog, resolveDaemonAssetDir, rotateDaemonLogIfNeeded, } from "./log.js";
|
|
8
8
|
export { BOARD_REFRESH_INTERVAL_MS, createVaultBoardReader, formatBoardMarkdown, refreshBoundSessionBoards, writeBoardMarkdown, } from "./board-refresh.js";
|
|
9
|
-
export { buildInstallPaths, daemonServiceStatus, detectPlatform, installDaemonIfStale, installDaemonService, isNewerCliVersion, readAssetTemplate, restartDaemonServiceIfInstalled, renderLaunchdPlist, renderSystemdSystemUnit, renderSystemdUserUnit, resolveAbsoluteNodeBinary, resolveHqBinary, resolveNodeBinary, resolveRunningCliEntry, parseSchtasksLastResult, parseWindowsTaskHqRoot, readRecordedWindowsHqRoot, schtasksLastResultFailed, uninstallDaemonService, windowsLaunchMode, windowsLogonNotice, } from "./install.js";
|
|
9
|
+
export { buildInstallPaths, daemonServiceIsLoaded, daemonServiceStatus, detectPlatform, installDaemonIfStale, installDaemonService, isNewerCliVersion, readAssetTemplate, restartDaemonServiceIfInstalled, renderLaunchdPlist, renderSystemdSystemUnit, renderSystemdUserUnit, resolveAbsoluteNodeBinary, resolveHqBinary, resolveNodeBinary, resolveRunningCliEntry, parseSchtasksLastResult, parseWindowsTaskHqRoot, readRecordedWindowsHqRoot, schtasksLastResultFailed, uninstallDaemonService, windowsLaunchMode, windowsLogonNotice, } from "./install.js";
|
|
10
10
|
export { daemonConfigPath, findAncestorHqRoot, isInstallableHqRoot, readDaemonConfig, registerTrustedHqRoot, resolveInstallHqRoot, verifyHqRoot, } from "./config.js";
|
|
11
11
|
export { UNHEALTHY_SPOOL_AGE_MS, collectDaemonDoctor, formatCliIdentityLines, formatCliMismatchLine, formatDaemonDoctor, listHqBinariesOnPath, } from "./doctor.js";
|
|
12
12
|
export { scopeBundleToAgentIdentity, } from "./credentials.js";
|
|
@@ -312,6 +312,11 @@ export declare function uninstallDaemonService(opts: {
|
|
|
312
312
|
/** Windows: terminate the recorded daemon pid after `schtasks /End` (tests inject). */
|
|
313
313
|
kill?: (pid: number) => void;
|
|
314
314
|
}): InstallResult;
|
|
315
|
+
/**
|
|
316
|
+
* Live service-manager probe for `daemonServiceStatus`: `launchctl print
|
|
317
|
+
* gui/<uid>/<label>` on macOS, `systemctl --user is-active` on Linux.
|
|
318
|
+
*/
|
|
319
|
+
export declare function daemonServiceIsLoaded(run: RunCommand, uid?: number): (platform: DaemonInstallPlatform, dest: string) => boolean;
|
|
315
320
|
export declare function daemonServiceStatus(opts: {
|
|
316
321
|
platform?: DaemonInstallPlatform;
|
|
317
322
|
paths?: InstallPaths;
|
|
@@ -22,8 +22,8 @@ import { isInstallableHqRoot, readDaemonConfig, registerTrustedHqRoot, verifyHqR
|
|
|
22
22
|
import { defaultPidLockDeps, pidLockStatus, readPidLock } from "./pid-lock.js";
|
|
23
23
|
import { retireLegacyListen } from "./legacy-listen.js";
|
|
24
24
|
import { readDaemonState } from "./state.js";
|
|
25
|
-
import { activateLaunchd, launchdPlistProgramArguments, launchdProgramArgumentsDiffer, parseLaunchctlPrintArguments, } from "../../../service-manager/launchd.js";
|
|
26
|
-
import { activateSystemd } from "../../../service-manager/systemd.js";
|
|
25
|
+
import { activateLaunchd, launchdIsLoaded, launchdPlistProgramArguments, launchdProgramArgumentsDiffer, parseLaunchctlPrintArguments, } from "../../../service-manager/launchd.js";
|
|
26
|
+
import { activateSystemd, systemdIsActive } from "../../../service-manager/systemd.js";
|
|
27
27
|
import { nodeBinaryProblem, preferStableNodeBinary } from "../../../node-binary.js";
|
|
28
28
|
/**
|
|
29
29
|
* `schtasks /End` terminates the task's root process only. The daemon is
|
|
@@ -990,6 +990,19 @@ export function uninstallDaemonService(opts) {
|
|
|
990
990
|
message: "Nothing to uninstall on this platform",
|
|
991
991
|
};
|
|
992
992
|
}
|
|
993
|
+
/**
|
|
994
|
+
* Live service-manager probe for `daemonServiceStatus`: `launchctl print
|
|
995
|
+
* gui/<uid>/<label>` on macOS, `systemctl --user is-active` on Linux.
|
|
996
|
+
*/
|
|
997
|
+
export function daemonServiceIsLoaded(run, uid) {
|
|
998
|
+
return (platform) => {
|
|
999
|
+
if (platform === "darwin")
|
|
1000
|
+
return launchdIsLoaded(LAUNCHD_LABEL, run, uid);
|
|
1001
|
+
if (platform === "linux")
|
|
1002
|
+
return systemdIsActive(SYSTEMD_UNIT_NAME, run);
|
|
1003
|
+
return false;
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
993
1006
|
export function daemonServiceStatus(opts) {
|
|
994
1007
|
const platform = opts.platform ?? detectPlatform();
|
|
995
1008
|
const paths = opts.paths ?? buildInstallPaths({});
|