@indigoai-us/hq-cli 5.345.178 → 5.345.180
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 +39 -0
- package/dist/command-catalog.generated.d.ts +197 -1
- package/dist/command-catalog.generated.js +241 -1
- package/dist/commands/bot-jobs.d.ts +11 -9
- package/dist/commands/bot-jobs.js +56 -21
- package/dist/commands/bot.d.ts +37 -1
- package/dist/commands/bot.js +289 -13
- package/dist/commands/channels.d.ts +18 -1
- package/dist/commands/channels.js +185 -1
- package/dist/commands/daemon.d.ts +2 -0
- package/dist/commands/daemon.js +15 -4
- package/dist/commands/integrations-core.d.ts +2 -0
- package/dist/commands/integrations-core.js +1 -0
- package/dist/commands/lanes.d.ts +1 -1
- package/dist/commands/lanes.js +6 -2
- package/dist/commands/mesh.js +19 -0
- package/dist/commands/sources.d.ts +89 -0
- package/dist/commands/sources.js +363 -1
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2285 -1743
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/bot/config.d.ts +8 -0
- package/dist/lib/bot/fleet-local.d.ts +1 -1
- package/dist/lib/bot/fleet-local.js +82 -30
- package/dist/lib/bot/jobs/hot-signal-sync.d.ts +109 -0
- package/dist/lib/bot/jobs/hot-signal-sync.js +177 -0
- package/dist/lib/bot/local-jobs.d.ts +40 -4
- package/dist/lib/bot/local-jobs.js +72 -5
- package/dist/lib/bot/run.d.ts +15 -0
- package/dist/lib/bot/run.js +99 -1
- package/dist/lib/bot/runtime-auth.d.ts +119 -0
- package/dist/lib/bot/runtime-auth.js +251 -0
- package/dist/lib/daemon/catalog.d.ts +1 -0
- package/dist/lib/daemon/catalog.js +1 -1
- package/dist/lib/daemon/handoff.d.ts +4 -0
- package/dist/lib/daemon/handoff.js +6 -2
- package/dist/lib/daemon/install.d.ts +70 -2
- package/dist/lib/daemon/install.js +185 -27
- package/dist/lib/daemon/legacy.d.ts +9 -3
- package/dist/lib/daemon/legacy.js +11 -4
- package/dist/lib/daemon/migrate.js +1 -1
- package/dist/lib/daemon/run.d.ts +5 -2
- package/dist/lib/daemon/run.js +74 -22
- package/dist/lib/doctor/checks/anywhere.d.ts +6 -0
- package/dist/lib/doctor/checks/anywhere.js +35 -6
- 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/hot-channels/adapters/__fixtures__/dummy.d.ts +33 -0
- package/dist/lib/hot-channels/adapters/__fixtures__/dummy.js +53 -0
- package/dist/lib/hot-channels/adapters/__fixtures__/meeting-providers.d.ts +38 -0
- package/dist/lib/hot-channels/adapters/__fixtures__/meeting-providers.js +64 -0
- package/dist/lib/hot-channels/adapters/attio.d.ts +67 -0
- package/dist/lib/hot-channels/adapters/attio.js +374 -0
- package/dist/lib/hot-channels/adapters/gmail.d.ts +111 -0
- package/dist/lib/hot-channels/adapters/gmail.js +413 -0
- package/dist/lib/hot-channels/adapters/index.d.ts +23 -0
- package/dist/lib/hot-channels/adapters/index.js +39 -0
- package/dist/lib/hot-channels/adapters/linear.d.ts +79 -0
- package/dist/lib/hot-channels/adapters/linear.js +321 -0
- package/dist/lib/hot-channels/adapters/meeting-providers.d.ts +86 -0
- package/dist/lib/hot-channels/adapters/meeting-providers.js +253 -0
- package/dist/lib/hot-channels/adapters/meetings.d.ts +81 -0
- package/dist/lib/hot-channels/adapters/meetings.js +525 -0
- package/dist/lib/hot-channels/adapters/slack.d.ts +70 -0
- package/dist/lib/hot-channels/adapters/slack.js +277 -0
- package/dist/lib/hot-channels/alert.d.ts +78 -0
- package/dist/lib/hot-channels/alert.js +179 -0
- package/dist/lib/hot-channels/audience.d.ts +15 -0
- package/dist/lib/hot-channels/audience.js +25 -0
- package/dist/lib/hot-channels/contract.d.ts +146 -0
- package/dist/lib/hot-channels/contract.js +20 -0
- package/dist/lib/hot-channels/cursors.d.ts +41 -0
- package/dist/lib/hot-channels/cursors.js +84 -0
- package/dist/lib/hot-channels/index.d.ts +10 -0
- package/dist/lib/hot-channels/index.js +10 -0
- package/dist/lib/hot-channels/landing.d.ts +83 -0
- package/dist/lib/hot-channels/landing.js +175 -0
- package/dist/lib/hot-channels/ledger.d.ts +101 -0
- package/dist/lib/hot-channels/ledger.js +203 -0
- package/dist/lib/hot-channels/loop.d.ts +74 -0
- package/dist/lib/hot-channels/loop.js +221 -0
- package/dist/lib/hot-channels/prompts/signals-pass.md +22 -0
- package/dist/lib/hot-channels/registry.d.ts +28 -0
- package/dist/lib/hot-channels/registry.js +121 -0
- package/dist/lib/hot-channels/run.d.ts +137 -0
- package/dist/lib/hot-channels/run.js +324 -0
- package/dist/lib/hot-channels/signals-pass.d.ts +150 -0
- package/dist/lib/hot-channels/signals-pass.js +581 -0
- package/dist/lib/hot-channels/sync-lock.d.ts +51 -0
- package/dist/lib/hot-channels/sync-lock.js +224 -0
- package/dist/lib/install/hook-target.d.ts +6 -2
- package/dist/lib/install/hook-target.js +9 -4
- package/dist/lib/lanes/accounts.d.ts +1 -17
- package/dist/lib/lanes/accounts.js +5 -45
- package/dist/lib/lanes/loop.d.ts +10 -0
- package/dist/lib/lanes/loop.js +18 -1
- package/dist/lib/lanes/provider-home.d.ts +24 -0
- package/dist/lib/lanes/provider-home.js +52 -0
- package/dist/lib/lanes/spawn.d.ts +12 -0
- package/dist/lib/lanes/spawn.js +27 -0
- package/dist/lib/mesh/live/daemon/doctor.d.ts +3 -0
- package/dist/lib/mesh/live/daemon/doctor.js +13 -0
- package/dist/lib/mesh/live/daemon/owner-inbox-push.d.ts +94 -0
- package/dist/lib/mesh/live/daemon/owner-inbox-push.js +273 -0
- package/dist/lib/mesh/live/daemon/run.js +31 -0
- package/dist/lib/mesh/live/daemon/work-subscribe.d.ts +14 -0
- package/dist/lib/mesh/live/daemon/work-subscribe.js +210 -3
- package/dist/lib/mesh/live/paths.d.ts +2 -0
- package/dist/lib/mesh/live/paths.js +2 -0
- package/dist/lib/sync-core/flag.d.ts +1 -1
- package/dist/lib/sync-core/flag.js +1 -1
- package/dist/lib/sync-core/reconcile.d.ts +1 -1
- package/dist/lib/sync-core/reconcile.js +9 -7
- package/dist/lib/sync-core/release.d.ts +3 -3
- package/dist/lib/sync-core/release.js +4 -4
- package/dist/lib/sync-core/rollout-state.d.ts +1 -0
- package/dist/lib/sync-core/rollout-state.js +1 -0
- package/package.json +8 -8
package/dist/lib/daemon/run.js
CHANGED
|
@@ -23,6 +23,7 @@ import { botsRoot } from "../bot/paths.js";
|
|
|
23
23
|
import { CLAUDE_RUNNER_SCRIPT, CODEX_RUNNER_SCRIPT, enabledServices, planUnits } from "./catalog.js";
|
|
24
24
|
import { effectiveSyncOwner, readDaemonConfig } from "./config.js";
|
|
25
25
|
import { inspectEngineHome } from "../sync-core/engine-home.js";
|
|
26
|
+
import { fullModeHold } from "../sync-core/reconcile.js";
|
|
26
27
|
import { readSyncCoreRolloutState } from "../sync-core/rollout-state.js";
|
|
27
28
|
import { assertPersonalServiceSessionCapability, readRemoteControlPoolsConfig, remoteControlPoolSecretsEnv, } from "./remote-control-pools.js";
|
|
28
29
|
import { loadLanesConfig } from "../lanes/config.js";
|
|
@@ -32,16 +33,16 @@ import { SUPERVISOR_HANDOFF_FLAG, readDaemonFlag } from "./flag.js";
|
|
|
32
33
|
import { createBoundedDaemonFlagMonitor } from "./flag-monitor.js";
|
|
33
34
|
import { DAEMON_CHILD_BOOTSTRAP_HANDOFF_WATCH_FLAG, DAEMON_LANES_RECONCILE_FILE_WATCH_FLAG, DAEMON_SEARCH_INDEX_RUNNER_OWNS_INDEX_FLAG, DAEMON_SYNC_PROCESS_SCAN_ON_MISSING_FLAG, } from "./kill-switch-flags.js";
|
|
34
35
|
import { createLanesReconcileWatcher } from "./lanes-reconcile-watcher.js";
|
|
35
|
-
import { findLegacyUnits, legacyMeshUnitsToRetire, legacyOwnerLookup } from "./legacy.js";
|
|
36
|
+
import { findLegacyUnits, legacyMeshUnitsToRetire, legacyOwnerLookup, } from "./legacy.js";
|
|
36
37
|
import { readLegacySyncEnv } from "./legacy-sync-env.js";
|
|
37
|
-
import { readVaultSyncSwitches, unreadableSwitchesWarning } from "../vault-sync-switches.js";
|
|
38
|
+
import { readVaultSyncSwitches, unreadableSwitchesWarning, writeVaultSyncSwitches } from "../vault-sync-switches.js";
|
|
38
39
|
import { acquireDaemonLock, isProcessAlive, processCommandLine, releaseDaemonLock } from "./lock.js";
|
|
39
40
|
import { retireLegacyMeshUnits } from "./migrate.js";
|
|
40
41
|
import { daemonDir as meshDaemonDir, daemonPidPath as meshDaemonPidPath } from "../mesh/live/daemon/paths.js";
|
|
41
42
|
import { readPidLock } from "../mesh/live/daemon/pid-lock.js";
|
|
42
43
|
import { registryDir, registryFile } from "../registry/registry.js";
|
|
43
44
|
import { updateAnywhereRuntimeRevocationMarker } from "../anywhere-runtime-revocation-marker.js";
|
|
44
|
-
import { daemonRootRefusal } from "./install.js";
|
|
45
|
+
import { classifyWindowsTask, currentWindowsIdentity, daemonRootRefusal } from "./install.js";
|
|
45
46
|
import { detectMachineType } from "./machine-type.js";
|
|
46
47
|
import { appendPrivate, daemonPaths, ensurePrivateDir, openPrivateAppend } from "./paths.js";
|
|
47
48
|
import { hqdSocketPath } from "./protocol.js";
|
|
@@ -65,24 +66,29 @@ export const LOG_ROTATE_BYTES = 5 * 1024 * 1024;
|
|
|
65
66
|
export const RESTART_EXIT_CODE = 75;
|
|
66
67
|
const NON_SYNC_SHUTDOWN_CAP_MS = STOP_ESCALATION_MS + 5_000;
|
|
67
68
|
const SYNC_RUNNER_SHUTDOWN_CAP_MS = STOP_ESCALATION_MS + SYNC_RUNNER_PERSIST_GRACE_MS + 5_000;
|
|
68
|
-
function syncCoreVaultPlans(home, hqRoot, platform) {
|
|
69
|
+
export function syncCoreVaultPlans(home, hqRoot, platform) {
|
|
69
70
|
const state = readSyncCoreRolloutState(home);
|
|
70
71
|
if (!state)
|
|
71
72
|
return [];
|
|
72
|
-
return state.vaults.map((vault) =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
return state.vaults.map((vault) => {
|
|
74
|
+
const plan = inspectEngineHome(home, hqRoot, {
|
|
75
|
+
uid: vault.uid,
|
|
76
|
+
kind: vault.kind,
|
|
77
|
+
...(vault.slug ? { slug: vault.slug } : {}),
|
|
78
|
+
phase: vault.phase,
|
|
79
|
+
engineHome: vault.engineHome,
|
|
80
|
+
binaryPath: state.binaryPath,
|
|
81
|
+
release: state.release,
|
|
82
|
+
...(vault.legacyOffSince ? { legacyOffSince: vault.legacyOffSince } : {}),
|
|
83
|
+
}, platform);
|
|
84
|
+
const releaseHold = vault.phase === "full" ? fullModeHold(vault, state.release) : undefined;
|
|
85
|
+
return releaseHold ? { ...plan, blockedReason: releaseHold } : plan;
|
|
86
|
+
});
|
|
82
87
|
}
|
|
83
88
|
const rememberedSyncCoreVaults = new Map();
|
|
84
89
|
export function planUnitsWithSyncCoreInterlock(services, context, supervisor) {
|
|
85
90
|
const companies = new Set();
|
|
91
|
+
const runningVaults = new Set();
|
|
86
92
|
let personal = false;
|
|
87
93
|
for (const vault of context.syncCoreVaults ?? []) {
|
|
88
94
|
rememberedSyncCoreVaults.set(vault.uid, { kind: vault.kind, slug: vault.slug, full: vault.phase === "full" });
|
|
@@ -90,7 +96,9 @@ export function planUnitsWithSyncCoreInterlock(services, context, supervisor) {
|
|
|
90
96
|
for (const unit of supervisor?.state().units ?? []) {
|
|
91
97
|
if (!unit.id.startsWith("sync-core:") || supervisor?.runningPlanKey(unit.id) === undefined)
|
|
92
98
|
continue;
|
|
93
|
-
const
|
|
99
|
+
const uid = unit.id.slice("sync-core:".length);
|
|
100
|
+
runningVaults.add(uid);
|
|
101
|
+
const vault = rememberedSyncCoreVaults.get(uid);
|
|
94
102
|
if (!vault?.full)
|
|
95
103
|
continue;
|
|
96
104
|
if (vault.kind === "personal")
|
|
@@ -98,13 +106,53 @@ export function planUnitsWithSyncCoreInterlock(services, context, supervisor) {
|
|
|
98
106
|
else if (vault.slug)
|
|
99
107
|
companies.add(vault.slug);
|
|
100
108
|
}
|
|
101
|
-
|
|
109
|
+
let vaultSync = context.vaultSync;
|
|
110
|
+
let fallbackPersistenceFailed = false;
|
|
111
|
+
if (context.vaultSync && !context.vaultSync.allOff) {
|
|
112
|
+
let personalOff = context.vaultSync.personalOff;
|
|
113
|
+
const offCompanies = new Set(context.vaultSync.offCompanies);
|
|
114
|
+
let restorePersonal = false;
|
|
115
|
+
const restoreCompanies = {};
|
|
116
|
+
for (const vault of context.syncCoreVaults ?? []) {
|
|
117
|
+
if (vault.phase !== "full" || runningVaults.has(vault.uid) || !fullModeHold(vault, vault.release))
|
|
118
|
+
continue;
|
|
119
|
+
if (vault.kind === "personal") {
|
|
120
|
+
restorePersonal = personalOff;
|
|
121
|
+
personalOff = false;
|
|
122
|
+
}
|
|
123
|
+
else if (vault.slug) {
|
|
124
|
+
if (offCompanies.has(vault.slug))
|
|
125
|
+
restoreCompanies[vault.slug] = true;
|
|
126
|
+
offCompanies.delete(vault.slug);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (restorePersonal || Object.keys(restoreCompanies).length > 0) {
|
|
130
|
+
try {
|
|
131
|
+
writeVaultSyncSwitches(context.home, {
|
|
132
|
+
...(restorePersonal ? { personal: true } : {}),
|
|
133
|
+
companies: restoreCompanies,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
fallbackPersistenceFailed = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
vaultSync = { ...context.vaultSync, personalOff, offCompanies };
|
|
141
|
+
}
|
|
142
|
+
let transitionContext = {
|
|
102
143
|
...context,
|
|
144
|
+
vaultSync,
|
|
103
145
|
syncCoreRunning: { personal, companies },
|
|
104
146
|
legacySyncReadyForCore: false,
|
|
105
147
|
};
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
let waiting = planUnits(services, transitionContext);
|
|
149
|
+
let legacy = waiting.find((unit) => unit.id === "sync");
|
|
150
|
+
if (fallbackPersistenceFailed && (legacy === undefined || legacy.blocked !== undefined)) {
|
|
151
|
+
vaultSync = context.vaultSync;
|
|
152
|
+
transitionContext = { ...transitionContext, vaultSync };
|
|
153
|
+
waiting = planUnits(services, transitionContext);
|
|
154
|
+
legacy = waiting.find((unit) => unit.id === "sync");
|
|
155
|
+
}
|
|
108
156
|
const legacySyncReadyForCore = legacy !== undefined
|
|
109
157
|
&& (legacy.blocked !== undefined || supervisor?.runningPlanKey("sync") === planKey(legacy, CLI_VERSION));
|
|
110
158
|
return planUnits(services, { ...transitionContext, legacySyncReadyForCore });
|
|
@@ -310,9 +358,13 @@ export function listLocalBots(root = botsRoot()) {
|
|
|
310
358
|
.map((d) => d.name)
|
|
311
359
|
.sort();
|
|
312
360
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
361
|
+
/** Whose task `taskName` is: only the current user's own task may be taken over. */
|
|
362
|
+
export function windowsTaskOwner(taskName) {
|
|
363
|
+
const run = (cmd, args) => {
|
|
364
|
+
const r = spawnSync(cmd, args, { encoding: "utf8", windowsHide: true });
|
|
365
|
+
return { status: r.status ?? 1, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
366
|
+
};
|
|
367
|
+
return classifyWindowsTask(run, taskName, currentWindowsIdentity(run)).state;
|
|
316
368
|
}
|
|
317
369
|
export function probeLegacyUnits(platform, home) {
|
|
318
370
|
return findLegacyUnits({
|
|
@@ -331,7 +383,7 @@ export function probeLegacyUnits(platform, home) {
|
|
|
331
383
|
});
|
|
332
384
|
return result.status === 0;
|
|
333
385
|
},
|
|
334
|
-
|
|
386
|
+
windowsTaskOwner,
|
|
335
387
|
});
|
|
336
388
|
}
|
|
337
389
|
/** Absolute path of `name` on PATH, or null. */
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* on this machine the family reports a single NA line.
|
|
10
10
|
*/
|
|
11
11
|
import { type HqdHealthResult } from "../../daemon/protocol.js";
|
|
12
|
+
import { type DaemonHost } from "../../daemon/install.js";
|
|
13
|
+
import type { RunCommand } from "../../service-manager/launchd.js";
|
|
12
14
|
import type { CheckFamily } from "../types.js";
|
|
13
15
|
export declare const REMEDIATION: {
|
|
14
16
|
readonly installClaude: "hq install --global --runtime claude";
|
|
@@ -31,6 +33,10 @@ export interface DaemonServiceProbeOptions {
|
|
|
31
33
|
launchdProbe?: (target: string) => boolean;
|
|
32
34
|
/** Test seam for the desktop app's live managed daemon state. */
|
|
33
35
|
hostedDaemonProbe?: () => boolean;
|
|
36
|
+
/** Test seam for the schtasks calls the Windows probe makes. */
|
|
37
|
+
run?: RunCommand;
|
|
38
|
+
/** Test seam for the Windows account the task name is built from. */
|
|
39
|
+
windowsIdentity?: Pick<DaemonHost, "windowsSid" | "windowsUser">;
|
|
34
40
|
}
|
|
35
41
|
export interface AnywhereDeps {
|
|
36
42
|
home?: string;
|
|
@@ -20,7 +20,7 @@ import { CHATGPT_MODE } from "../../install/chatgpt-targets.js";
|
|
|
20
20
|
import { GROK_MODE } from "../../install/grok-targets.js";
|
|
21
21
|
import { HqdClientError, hqdRequest } from "../../daemon/protocol.js";
|
|
22
22
|
import { daemonPresenceLabel, heartbeatFile, readHeartbeat } from "../../daemon/heartbeat.js";
|
|
23
|
-
import { DAEMON_LAUNCHD_LABEL, DAEMON_SYSTEMD_UNIT,
|
|
23
|
+
import { DAEMON_LAUNCHD_LABEL, DAEMON_SYSTEMD_UNIT, LEGACY_DAEMON_WINDOWS_TASK, currentWindowsIdentity, legacyWindowsTask, windowsTaskName, } from "../../daemon/install.js";
|
|
24
24
|
import { hostedDaemonRunning } from "../../daemon/handoff.js";
|
|
25
25
|
import { daemonPaths } from "../../daemon/paths.js";
|
|
26
26
|
import { runningDaemonPid } from "../../daemon/lock.js";
|
|
@@ -40,6 +40,15 @@ export const REMEDIATION = {
|
|
|
40
40
|
daemonStatus: "hq daemon status",
|
|
41
41
|
link: "hq link <repo-dir> <company>",
|
|
42
42
|
};
|
|
43
|
+
/** schtasks with the same 5s cap the probe always had, so a hung query cannot stall the doctor. */
|
|
44
|
+
const runSchtasksWithTimeout = (cmd, args) => {
|
|
45
|
+
const r = spawnSync(cmd, args, { encoding: "utf8", timeout: 5_000, windowsHide: true });
|
|
46
|
+
return {
|
|
47
|
+
status: r.status,
|
|
48
|
+
stdout: typeof r.stdout === "string" ? r.stdout : "",
|
|
49
|
+
stderr: r.error ? r.error.message : (typeof r.stderr === "string" ? r.stderr : ""),
|
|
50
|
+
};
|
|
51
|
+
};
|
|
43
52
|
export function createAnywhereFamily(deps = {}) {
|
|
44
53
|
return { id: ANYWHERE_FAMILY_ID, title: "HQ anywhere runtime", run: (context) => runAnywhereChecks(context, deps) };
|
|
45
54
|
}
|
|
@@ -451,11 +460,31 @@ export function defaultServiceState(home, options = {}) {
|
|
|
451
460
|
return { installed: true, loaded: probe.status === 0, detail: `systemd ${systemScope ? "system" : "user"} ${DAEMON_SYSTEMD_UNIT}` };
|
|
452
461
|
}
|
|
453
462
|
if (platform === "win32") {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const
|
|
458
|
-
|
|
463
|
+
// Each Windows user has their own task. The shared task an older install
|
|
464
|
+
// registered counts only when it runs as this user.
|
|
465
|
+
const run = options.run ?? runSchtasksWithTimeout;
|
|
466
|
+
const identity = options.windowsIdentity ?? currentWindowsIdentity(run);
|
|
467
|
+
const task = windowsTaskName(identity);
|
|
468
|
+
const probe = run("schtasks.exe", ["/Query", "/TN", task, "/FO", "CSV", "/NH"]);
|
|
469
|
+
if (probe.status !== 0) {
|
|
470
|
+
const legacy = legacyWindowsTask(run, identity);
|
|
471
|
+
if (legacy.state === "mine") {
|
|
472
|
+
// Still this user's daemon until install moves it to the per-user name.
|
|
473
|
+
const legacyProbe = run("schtasks.exe", ["/Query", "/TN", LEGACY_DAEMON_WINDOWS_TASK, "/FO", "CSV", "/NH"]);
|
|
474
|
+
const legacyLoaded = legacyProbe.status === 0 && /,\s*"?Running"?\s*$/i.test(legacyProbe.stdout.replace(/\0/g, "").trim());
|
|
475
|
+
return {
|
|
476
|
+
installed: true,
|
|
477
|
+
loaded: legacyLoaded,
|
|
478
|
+
detail: `your daemon runs from the shared task ${LEGACY_DAEMON_WINDOWS_TASK} from an older install${legacyLoaded ? " (running)" : " (not running)"}. Run hq daemon install to move it to your own task ${task}`,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const someoneElse = legacy.state === "other" || legacy.state === "unreadable"
|
|
482
|
+
? ` (${LEGACY_DAEMON_WINDOWS_TASK} belongs to another Windows user and is not yours)`
|
|
483
|
+
: "";
|
|
484
|
+
return { installed: false, loaded: false, detail: `no Scheduled Task ${task}${someoneElse}` };
|
|
485
|
+
}
|
|
486
|
+
const loaded = /,\s*"?Running"?\s*$/i.test(probe.stdout.replace(/\0/g, "").trim());
|
|
487
|
+
return { installed: true, loaded, detail: `Scheduled Task ${task}${loaded ? " is running" : " is not running"}` };
|
|
459
488
|
}
|
|
460
489
|
return { installed: false, loaded: false, detail: `${platform}: service probe not available` };
|
|
461
490
|
}
|