@gtc6244/immediacy-daemon 0.1.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/dist/src/actions.d.ts +22 -0
- package/dist/src/actions.js +44 -0
- package/dist/src/actions.js.map +1 -0
- package/dist/src/agent/agent.d.ts +89 -0
- package/dist/src/agent/agent.js +22 -0
- package/dist/src/agent/agent.js.map +1 -0
- package/dist/src/agent/claude.d.ts +70 -0
- package/dist/src/agent/claude.js +404 -0
- package/dist/src/agent/claude.js.map +1 -0
- package/dist/src/agent/codex.d.ts +44 -0
- package/dist/src/agent/codex.js +303 -0
- package/dist/src/agent/codex.js.map +1 -0
- package/dist/src/agent/mock.d.ts +31 -0
- package/dist/src/agent/mock.js +155 -0
- package/dist/src/agent/mock.js.map +1 -0
- package/dist/src/agent/model-error.d.ts +8 -0
- package/dist/src/agent/model-error.js +25 -0
- package/dist/src/agent/model-error.js.map +1 -0
- package/dist/src/agent/openrouter.d.ts +38 -0
- package/dist/src/agent/openrouter.js +60 -0
- package/dist/src/agent/openrouter.js.map +1 -0
- package/dist/src/agent/workspace-scope.d.ts +25 -0
- package/dist/src/agent/workspace-scope.js +71 -0
- package/dist/src/agent/workspace-scope.js.map +1 -0
- package/dist/src/allowlist.d.ts +56 -0
- package/dist/src/allowlist.js +141 -0
- package/dist/src/allowlist.js.map +1 -0
- package/dist/src/chatlog.d.ts +50 -0
- package/dist/src/chatlog.js +179 -0
- package/dist/src/chatlog.js.map +1 -0
- package/dist/src/cli/paths.d.ts +40 -0
- package/dist/src/cli/paths.js +76 -0
- package/dist/src/cli/paths.js.map +1 -0
- package/dist/src/cli/service.d.ts +20 -0
- package/dist/src/cli/service.js +245 -0
- package/dist/src/cli/service.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +227 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +33 -0
- package/dist/src/config.js +122 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/credentials.d.ts +38 -0
- package/dist/src/credentials.js +120 -0
- package/dist/src/credentials.js.map +1 -0
- package/dist/src/crypto.d.ts +49 -0
- package/dist/src/crypto.js +202 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/daemon-identity.d.ts +31 -0
- package/dist/src/daemon-identity.js +97 -0
- package/dist/src/daemon-identity.js.map +1 -0
- package/dist/src/envelope.d.ts +14 -0
- package/dist/src/envelope.js +28 -0
- package/dist/src/envelope.js.map +1 -0
- package/dist/src/events.d.ts +40 -0
- package/dist/src/events.js +24 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/forward.d.ts +51 -0
- package/dist/src/forward.js +170 -0
- package/dist/src/forward.js.map +1 -0
- package/dist/src/fs-scope.d.ts +17 -0
- package/dist/src/fs-scope.js +47 -0
- package/dist/src/fs-scope.js.map +1 -0
- package/dist/src/github.d.ts +70 -0
- package/dist/src/github.js +178 -0
- package/dist/src/github.js.map +1 -0
- package/dist/src/gitops.d.ts +113 -0
- package/dist/src/gitops.js +557 -0
- package/dist/src/gitops.js.map +1 -0
- package/dist/src/hub.d.ts +50 -0
- package/dist/src/hub.js +92 -0
- package/dist/src/hub.js.map +1 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.js +56 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jobs/scheduler.d.ts +94 -0
- package/dist/src/jobs/scheduler.js +373 -0
- package/dist/src/jobs/scheduler.js.map +1 -0
- package/dist/src/jobs/store.d.ts +33 -0
- package/dist/src/jobs/store.js +111 -0
- package/dist/src/jobs/store.js.map +1 -0
- package/dist/src/log.d.ts +61 -0
- package/dist/src/log.js +166 -0
- package/dist/src/log.js.map +1 -0
- package/dist/src/migrate-state-dir.d.ts +1 -0
- package/dist/src/migrate-state-dir.js +47 -0
- package/dist/src/migrate-state-dir.js.map +1 -0
- package/dist/src/models.d.ts +36 -0
- package/dist/src/models.js +71 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/permission-gate.d.ts +48 -0
- package/dist/src/permission-gate.js +93 -0
- package/dist/src/permission-gate.js.map +1 -0
- package/dist/src/permission-scope.d.ts +77 -0
- package/dist/src/permission-scope.js +244 -0
- package/dist/src/permission-scope.js.map +1 -0
- package/dist/src/ports.d.ts +71 -0
- package/dist/src/ports.js +216 -0
- package/dist/src/ports.js.map +1 -0
- package/dist/src/projects.d.ts +83 -0
- package/dist/src/projects.js +205 -0
- package/dist/src/projects.js.map +1 -0
- package/dist/src/protocol.d.ts +1226 -0
- package/dist/src/protocol.js +16 -0
- package/dist/src/protocol.js.map +1 -0
- package/dist/src/repo-sync.d.ts +49 -0
- package/dist/src/repo-sync.js +83 -0
- package/dist/src/repo-sync.js.map +1 -0
- package/dist/src/server.d.ts +33 -0
- package/dist/src/server.js +973 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/terminal.d.ts +32 -0
- package/dist/src/terminal.js +92 -0
- package/dist/src/terminal.js.map +1 -0
- package/dist/src/titler.d.ts +15 -0
- package/dist/src/titler.js +72 -0
- package/dist/src/titler.js.map +1 -0
- package/dist/src/types.d.ts +99 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/usage-limit.d.ts +49 -0
- package/dist/src/usage-limit.js +83 -0
- package/dist/src/usage-limit.js.map +1 -0
- package/dist/src/usage.d.ts +23 -0
- package/dist/src/usage.js +63 -0
- package/dist/src/usage.js.map +1 -0
- package/dist/src/workspace.d.ts +303 -0
- package/dist/src/workspace.js +1086 -0
- package/dist/src/workspace.js.map +1 -0
- package/dist/src/worktree.d.ts +133 -0
- package/dist/src/worktree.js +561 -0
- package/dist/src/worktree.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** launchd Label / systemd unit stem. Matches deploy/launchd/*.plist. */
|
|
2
|
+
export declare const SERVICE_LABEL = "com.ixiomsoftware.immediacy.daemon";
|
|
3
|
+
/** systemd wants a plain unit name, not a reverse-DNS label. */
|
|
4
|
+
export declare const SYSTEMD_UNIT = "immediacy-daemon";
|
|
5
|
+
/**
|
|
6
|
+
* Absolute path to the compiled daemon entrypoint. cli.js lives at
|
|
7
|
+
* `dist/src/cli.js`; index.js is its sibling. Resolving relative to this
|
|
8
|
+
* module (not cwd) means the service points at *this* installed copy —
|
|
9
|
+
* whether that's a global npm prefix, an nvm dir, or a checkout.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DAEMON_ENTRY: string;
|
|
12
|
+
/** The daemon's persistent state dir (keys, credentials, projects, jobs…). */
|
|
13
|
+
export declare const STATE_DIR: string;
|
|
14
|
+
/**
|
|
15
|
+
* Log destinations. macOS convention is ~/Library/Logs (matches the existing
|
|
16
|
+
* plist); Linux user services journal to systemd, but we still point stdout/err
|
|
17
|
+
* at files under the state dir so `logs` works uniformly and nothing is lost if
|
|
18
|
+
* journald is unavailable.
|
|
19
|
+
*/
|
|
20
|
+
export declare function logPaths(): {
|
|
21
|
+
out: string;
|
|
22
|
+
err: string;
|
|
23
|
+
};
|
|
24
|
+
/** Read the published version out of package.json (two dirs up from dist/src). */
|
|
25
|
+
export declare function packageVersion(): string;
|
|
26
|
+
/** Runtime config baked into a service unit's environment. */
|
|
27
|
+
export interface ServiceEnv {
|
|
28
|
+
port: number;
|
|
29
|
+
host: string;
|
|
30
|
+
agentMode: string;
|
|
31
|
+
e2e: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare const DEFAULT_ENV: ServiceEnv;
|
|
34
|
+
/**
|
|
35
|
+
* PATH baked into the unit so the daemon can resolve `git`, `gh`, `claude`,
|
|
36
|
+
* `codex`. launchd/systemd start with a minimal PATH, so we prepend the usual
|
|
37
|
+
* package-manager bin dirs (Homebrew arm64 + Intel, /usr/local) ahead of the
|
|
38
|
+
* system defaults. Mirrors the PATH in the existing plist template.
|
|
39
|
+
*/
|
|
40
|
+
export declare function servicePath(): string;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared identifiers and filesystem paths for the CLI + service units.
|
|
3
|
+
*
|
|
4
|
+
* The single source of truth for the launchd/systemd label, the compiled
|
|
5
|
+
* daemon entrypoint, and log locations — so `install`, `uninstall`, `status`,
|
|
6
|
+
* and `logs` all agree on where things live. Kept dependency-free (only node
|
|
7
|
+
* builtins) so the bin starts instantly without pulling in the daemon graph.
|
|
8
|
+
*/
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { readFileSync } from "node:fs";
|
|
13
|
+
/** launchd Label / systemd unit stem. Matches deploy/launchd/*.plist. */
|
|
14
|
+
export const SERVICE_LABEL = "com.ixiomsoftware.immediacy.daemon";
|
|
15
|
+
/** systemd wants a plain unit name, not a reverse-DNS label. */
|
|
16
|
+
export const SYSTEMD_UNIT = "immediacy-daemon";
|
|
17
|
+
/**
|
|
18
|
+
* Absolute path to the compiled daemon entrypoint. cli.js lives at
|
|
19
|
+
* `dist/src/cli.js`; index.js is its sibling. Resolving relative to this
|
|
20
|
+
* module (not cwd) means the service points at *this* installed copy —
|
|
21
|
+
* whether that's a global npm prefix, an nvm dir, or a checkout.
|
|
22
|
+
*/
|
|
23
|
+
export const DAEMON_ENTRY = fileURLToPath(new URL("../index.js", import.meta.url));
|
|
24
|
+
/** The daemon's persistent state dir (keys, credentials, projects, jobs…). */
|
|
25
|
+
export const STATE_DIR = join(homedir(), ".immediacy");
|
|
26
|
+
/**
|
|
27
|
+
* Log destinations. macOS convention is ~/Library/Logs (matches the existing
|
|
28
|
+
* plist); Linux user services journal to systemd, but we still point stdout/err
|
|
29
|
+
* at files under the state dir so `logs` works uniformly and nothing is lost if
|
|
30
|
+
* journald is unavailable.
|
|
31
|
+
*/
|
|
32
|
+
export function logPaths() {
|
|
33
|
+
if (process.platform === "darwin") {
|
|
34
|
+
const logs = join(homedir(), "Library", "Logs");
|
|
35
|
+
return {
|
|
36
|
+
out: join(logs, "immediacy-daemon.out.log"),
|
|
37
|
+
err: join(logs, "immediacy-daemon.err.log"),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
out: join(STATE_DIR, "daemon.out.log"),
|
|
42
|
+
err: join(STATE_DIR, "daemon.err.log"),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Read the published version out of package.json (two dirs up from dist/src). */
|
|
46
|
+
export function packageVersion() {
|
|
47
|
+
try {
|
|
48
|
+
// This module compiles to dist/src/cli/paths.js — three levels below the
|
|
49
|
+
// package root where package.json lives (cli/ → src/ → dist/ → root).
|
|
50
|
+
const pkgUrl = new URL("../../../package.json", import.meta.url);
|
|
51
|
+
const pkg = JSON.parse(readFileSync(pkgUrl, "utf8"));
|
|
52
|
+
return pkg.version ?? "0.0.0";
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return "0.0.0";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export const DEFAULT_ENV = {
|
|
59
|
+
port: 8787,
|
|
60
|
+
host: "127.0.0.1",
|
|
61
|
+
agentMode: "claude",
|
|
62
|
+
e2e: false,
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* PATH baked into the unit so the daemon can resolve `git`, `gh`, `claude`,
|
|
66
|
+
* `codex`. launchd/systemd start with a minimal PATH, so we prepend the usual
|
|
67
|
+
* package-manager bin dirs (Homebrew arm64 + Intel, /usr/local) ahead of the
|
|
68
|
+
* system defaults. Mirrors the PATH in the existing plist template.
|
|
69
|
+
*/
|
|
70
|
+
export function servicePath() {
|
|
71
|
+
const base = process.platform === "darwin"
|
|
72
|
+
? ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"]
|
|
73
|
+
: ["/usr/local/bin", "/usr/bin", "/bin"];
|
|
74
|
+
return base.join(":");
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/cli/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,yEAAyE;AACzE,MAAM,CAAC,MAAM,aAAa,GAAG,oCAAoC,CAAC;AAClE,gEAAgE;AAChE,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEnF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,UAAU,QAAQ;IACtB,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAChD,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,0BAA0B,CAAC;YAC3C,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,0BAA0B,CAAC;SAC5C,CAAC;IACJ,CAAC;IACD,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;QACtC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,yEAAyE;QACzE,sEAAsE;QACtE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAyB,CAAC;QAC7E,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAUD,MAAM,CAAC,MAAM,WAAW,GAAe;IACrC,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,WAAW;IACjB,SAAS,EAAE,QAAQ;IACnB,GAAG,EAAE,KAAK;CACX,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,GACR,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAC3B,CAAC,CAAC,CAAC,mBAAmB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,CAAC;QAC7D,CAAC,CAAC,CAAC,gBAAgB,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ServiceEnv } from "./paths.js";
|
|
2
|
+
export declare function detectPlatform(): "darwin" | "linux";
|
|
3
|
+
export declare function installService(env: ServiceEnv): string;
|
|
4
|
+
/**
|
|
5
|
+
* Render the service unit that `install` *would* write, without any side
|
|
6
|
+
* effects (no file writes, no launchctl/systemctl). Backs `install --print`,
|
|
7
|
+
* so you can review exactly what will be installed — and where — first.
|
|
8
|
+
*/
|
|
9
|
+
export declare function renderServiceUnit(env: ServiceEnv): {
|
|
10
|
+
path: string;
|
|
11
|
+
contents: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function uninstallService(): void;
|
|
14
|
+
export declare function restartService(): void;
|
|
15
|
+
export declare function printServiceStatus(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Linux-only hint: --user services stop at logout unless lingering is enabled.
|
|
18
|
+
* Returns a hint string when relevant, else null.
|
|
19
|
+
*/
|
|
20
|
+
export declare function lingerHint(): string | null;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform service supervision for the daemon.
|
|
3
|
+
*
|
|
4
|
+
* macOS → launchd LaunchAgent (~/Library/LaunchAgents), managed with launchctl.
|
|
5
|
+
* Linux → systemd --user unit (~/.config/systemd/user), managed with systemctl.
|
|
6
|
+
*
|
|
7
|
+
* Both keep the daemon alive across crashes but let a clean/graceful stop stick
|
|
8
|
+
* (launchd KeepAlive.SuccessfulExit=false; systemd Restart=on-failure), matching
|
|
9
|
+
* the behavior documented in the original plist. We deliberately point the unit
|
|
10
|
+
* at the exact `node` running this CLI (process.execPath) and at DAEMON_ENTRY
|
|
11
|
+
* next to it — no PATH guessing for the runtime, and it works under nvm/asdf.
|
|
12
|
+
*/
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
14
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { SERVICE_LABEL, SYSTEMD_UNIT, DAEMON_ENTRY, logPaths, servicePath, } from "./paths.js";
|
|
18
|
+
function run(cmd, args) {
|
|
19
|
+
const r = spawnSync(cmd, args, { encoding: "utf8" });
|
|
20
|
+
return {
|
|
21
|
+
code: r.status ?? 1,
|
|
22
|
+
stdout: (r.stdout ?? "").trim(),
|
|
23
|
+
stderr: (r.stderr ?? r.error?.message ?? "").trim(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function detectPlatform() {
|
|
27
|
+
if (process.platform === "darwin")
|
|
28
|
+
return "darwin";
|
|
29
|
+
if (process.platform === "linux")
|
|
30
|
+
return "linux";
|
|
31
|
+
throw new Error(`unsupported platform '${process.platform}' — install/uninstall/restart ` +
|
|
32
|
+
`support macOS (launchd) and Linux (systemd). Use \`start\` to run in the ` +
|
|
33
|
+
`foreground, or run the daemon in Docker.`);
|
|
34
|
+
}
|
|
35
|
+
function xmlEscape(s) {
|
|
36
|
+
return s
|
|
37
|
+
.replace(/&/g, "&")
|
|
38
|
+
.replace(/</g, "<")
|
|
39
|
+
.replace(/>/g, ">");
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------- launchd ----
|
|
42
|
+
function plistPath() {
|
|
43
|
+
return join(homedir(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
44
|
+
}
|
|
45
|
+
function renderPlist(env) {
|
|
46
|
+
const { out, err } = logPaths();
|
|
47
|
+
const envEntries = {
|
|
48
|
+
DAEMON_PORT: String(env.port),
|
|
49
|
+
DAEMON_HOST: env.host,
|
|
50
|
+
AGENT_MODE: env.agentMode,
|
|
51
|
+
PATH: servicePath(),
|
|
52
|
+
};
|
|
53
|
+
if (env.e2e)
|
|
54
|
+
envEntries.E2E = "1";
|
|
55
|
+
const envXml = Object.entries(envEntries)
|
|
56
|
+
.map(([k, v]) => ` <key>${k}</key>\n <string>${xmlEscape(v)}</string>`)
|
|
57
|
+
.join("\n");
|
|
58
|
+
// ProgramArguments: the exact node running this CLI, then the sibling entry.
|
|
59
|
+
const args = [process.execPath, DAEMON_ENTRY]
|
|
60
|
+
.map((a) => ` <string>${xmlEscape(a)}</string>`)
|
|
61
|
+
.join("\n");
|
|
62
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
63
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
64
|
+
<plist version="1.0">
|
|
65
|
+
<dict>
|
|
66
|
+
<key>Label</key>
|
|
67
|
+
<string>${SERVICE_LABEL}</string>
|
|
68
|
+
|
|
69
|
+
<key>ProgramArguments</key>
|
|
70
|
+
<array>
|
|
71
|
+
${args}
|
|
72
|
+
</array>
|
|
73
|
+
|
|
74
|
+
<key>EnvironmentVariables</key>
|
|
75
|
+
<dict>
|
|
76
|
+
${envXml}
|
|
77
|
+
</dict>
|
|
78
|
+
|
|
79
|
+
<key>RunAtLoad</key>
|
|
80
|
+
<true/>
|
|
81
|
+
|
|
82
|
+
<!-- Restart on crash, but let a clean/graceful stop stick. -->
|
|
83
|
+
<key>KeepAlive</key>
|
|
84
|
+
<dict>
|
|
85
|
+
<key>SuccessfulExit</key>
|
|
86
|
+
<false/>
|
|
87
|
+
</dict>
|
|
88
|
+
|
|
89
|
+
<key>ThrottleInterval</key>
|
|
90
|
+
<integer>10</integer>
|
|
91
|
+
|
|
92
|
+
<key>StandardOutPath</key>
|
|
93
|
+
<string>${xmlEscape(out)}</string>
|
|
94
|
+
<key>StandardErrorPath</key>
|
|
95
|
+
<string>${xmlEscape(err)}</string>
|
|
96
|
+
</dict>
|
|
97
|
+
</plist>
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
function launchdDomain() {
|
|
101
|
+
// gui/<uid> is the aqua session domain a LaunchAgent belongs to.
|
|
102
|
+
return `gui/${process.getuid?.() ?? ""}`;
|
|
103
|
+
}
|
|
104
|
+
function installLaunchd(env) {
|
|
105
|
+
const path = plistPath();
|
|
106
|
+
mkdirSync(join(homedir(), "Library", "LaunchAgents"), { recursive: true });
|
|
107
|
+
writeFileSync(path, renderPlist(env));
|
|
108
|
+
const domain = launchdDomain();
|
|
109
|
+
// Idempotent: bootout any prior instance (ignore "not loaded"), then bootstrap.
|
|
110
|
+
run("launchctl", ["bootout", domain, path]);
|
|
111
|
+
const boot = run("launchctl", ["bootstrap", domain, path]);
|
|
112
|
+
if (boot.code !== 0) {
|
|
113
|
+
// Older macOS: fall back to the legacy verb.
|
|
114
|
+
const legacy = run("launchctl", ["load", "-w", path]);
|
|
115
|
+
if (legacy.code !== 0) {
|
|
116
|
+
throw new Error(`launchctl bootstrap failed: ${boot.stderr || legacy.stderr}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
run("launchctl", ["kickstart", "-k", `${domain}/${SERVICE_LABEL}`]);
|
|
120
|
+
}
|
|
121
|
+
function uninstallLaunchd() {
|
|
122
|
+
const path = plistPath();
|
|
123
|
+
run("launchctl", ["bootout", launchdDomain(), path]);
|
|
124
|
+
if (existsSync(path))
|
|
125
|
+
rmSync(path);
|
|
126
|
+
}
|
|
127
|
+
function restartLaunchd() {
|
|
128
|
+
run("launchctl", ["kickstart", "-k", `${launchdDomain()}/${SERVICE_LABEL}`]);
|
|
129
|
+
}
|
|
130
|
+
function statusLaunchd() {
|
|
131
|
+
return run("launchctl", ["print", `${launchdDomain()}/${SERVICE_LABEL}`]);
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------- systemd ----
|
|
134
|
+
function unitPath() {
|
|
135
|
+
return join(homedir(), ".config", "systemd", "user", `${SYSTEMD_UNIT}.service`);
|
|
136
|
+
}
|
|
137
|
+
function renderUnit(env) {
|
|
138
|
+
const { out, err } = logPaths();
|
|
139
|
+
const environment = [
|
|
140
|
+
`DAEMON_PORT=${env.port}`,
|
|
141
|
+
`DAEMON_HOST=${env.host}`,
|
|
142
|
+
`AGENT_MODE=${env.agentMode}`,
|
|
143
|
+
`PATH=${servicePath()}`,
|
|
144
|
+
...(env.e2e ? ["E2E=1"] : []),
|
|
145
|
+
]
|
|
146
|
+
.map((e) => `Environment=${e}`)
|
|
147
|
+
.join("\n");
|
|
148
|
+
return `[Unit]
|
|
149
|
+
Description=Immediacy daemon — worktrees + headless Claude Code sessions over WSS
|
|
150
|
+
After=network-online.target
|
|
151
|
+
Wants=network-online.target
|
|
152
|
+
|
|
153
|
+
[Service]
|
|
154
|
+
Type=simple
|
|
155
|
+
ExecStart=${process.execPath} ${DAEMON_ENTRY}
|
|
156
|
+
${environment}
|
|
157
|
+
# Restart on crash, but let a clean/graceful stop stick.
|
|
158
|
+
Restart=on-failure
|
|
159
|
+
RestartSec=10
|
|
160
|
+
StandardOutput=append:${out}
|
|
161
|
+
StandardError=append:${err}
|
|
162
|
+
|
|
163
|
+
[Install]
|
|
164
|
+
WantedBy=default.target
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
function systemctl(args) {
|
|
168
|
+
return run("systemctl", ["--user", ...args]);
|
|
169
|
+
}
|
|
170
|
+
function installSystemd(env) {
|
|
171
|
+
const path = unitPath();
|
|
172
|
+
mkdirSync(join(homedir(), ".config", "systemd", "user"), { recursive: true });
|
|
173
|
+
mkdirSync(join(homedir(), ".immediacy"), { recursive: true }); // for log files
|
|
174
|
+
writeFileSync(path, renderUnit(env));
|
|
175
|
+
systemctl(["daemon-reload"]);
|
|
176
|
+
const enable = systemctl(["enable", "--now", `${SYSTEMD_UNIT}.service`]);
|
|
177
|
+
if (enable.code !== 0) {
|
|
178
|
+
throw new Error(`systemctl enable failed: ${enable.stderr}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function uninstallSystemd() {
|
|
182
|
+
systemctl(["disable", "--now", `${SYSTEMD_UNIT}.service`]);
|
|
183
|
+
const path = unitPath();
|
|
184
|
+
if (existsSync(path))
|
|
185
|
+
rmSync(path);
|
|
186
|
+
systemctl(["daemon-reload"]);
|
|
187
|
+
}
|
|
188
|
+
function restartSystemd() {
|
|
189
|
+
systemctl(["restart", `${SYSTEMD_UNIT}.service`]);
|
|
190
|
+
}
|
|
191
|
+
function statusSystemd() {
|
|
192
|
+
return systemctl(["status", "--no-pager", `${SYSTEMD_UNIT}.service`]);
|
|
193
|
+
}
|
|
194
|
+
// ------------------------------------------------------------------ public ---
|
|
195
|
+
export function installService(env) {
|
|
196
|
+
const platform = detectPlatform();
|
|
197
|
+
if (platform === "darwin") {
|
|
198
|
+
installLaunchd(env);
|
|
199
|
+
return plistPath();
|
|
200
|
+
}
|
|
201
|
+
installSystemd(env);
|
|
202
|
+
return unitPath();
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Render the service unit that `install` *would* write, without any side
|
|
206
|
+
* effects (no file writes, no launchctl/systemctl). Backs `install --print`,
|
|
207
|
+
* so you can review exactly what will be installed — and where — first.
|
|
208
|
+
*/
|
|
209
|
+
export function renderServiceUnit(env) {
|
|
210
|
+
if (detectPlatform() === "darwin") {
|
|
211
|
+
return { path: plistPath(), contents: renderPlist(env) };
|
|
212
|
+
}
|
|
213
|
+
return { path: unitPath(), contents: renderUnit(env) };
|
|
214
|
+
}
|
|
215
|
+
export function uninstallService() {
|
|
216
|
+
const platform = detectPlatform();
|
|
217
|
+
if (platform === "darwin")
|
|
218
|
+
uninstallLaunchd();
|
|
219
|
+
else
|
|
220
|
+
uninstallSystemd();
|
|
221
|
+
}
|
|
222
|
+
export function restartService() {
|
|
223
|
+
const platform = detectPlatform();
|
|
224
|
+
if (platform === "darwin")
|
|
225
|
+
restartLaunchd();
|
|
226
|
+
else
|
|
227
|
+
restartSystemd();
|
|
228
|
+
}
|
|
229
|
+
export function printServiceStatus() {
|
|
230
|
+
const platform = detectPlatform();
|
|
231
|
+
const r = platform === "darwin" ? statusLaunchd() : statusSystemd();
|
|
232
|
+
process.stdout.write((r.stdout || r.stderr || "(no status output)") + "\n");
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Linux-only hint: --user services stop at logout unless lingering is enabled.
|
|
236
|
+
* Returns a hint string when relevant, else null.
|
|
237
|
+
*/
|
|
238
|
+
export function lingerHint() {
|
|
239
|
+
if (detectPlatform() !== "linux")
|
|
240
|
+
return null;
|
|
241
|
+
const user = process.env.USER ?? "$(whoami)";
|
|
242
|
+
return (`Tip: on a headless VPS, enable lingering so the daemon survives logout:\n` +
|
|
243
|
+
` sudo loginctl enable-linger ${user}`);
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/cli/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,WAAW,GAEZ,MAAM,YAAY,CAAC;AASpB,SAAS,GAAG,CAAC,GAAW,EAAE,IAAc;IACtC,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACrD,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;QACnB,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QAC/B,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACnD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IACjD,MAAM,IAAI,KAAK,CACb,yBAAyB,OAAO,CAAC,QAAQ,gCAAgC;QACvE,2EAA2E;QAC3E,0CAA0C,CAC7C,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,gFAAgF;AAEhF,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,aAAa,QAAQ,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,GAAe;IAClC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;IAChC,MAAM,UAAU,GAA2B;QACzC,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QAC7B,WAAW,EAAE,GAAG,CAAC,IAAI;QACrB,UAAU,EAAE,GAAG,CAAC,SAAS;QACzB,IAAI,EAAE,WAAW,EAAE;KACpB,CAAC;IACF,IAAI,GAAG,CAAC,GAAG;QAAE,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC;IAElC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACtC,GAAG,CACF,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CACT,gBAAgB,CAAC,2BAA2B,SAAS,CAAC,CAAC,CAAC,WAAW,CACtE;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,6EAA6E;IAC7E,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mBAAmB,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;SACtD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;;;;;cAKK,aAAa;;;;EAIzB,IAAI;;;;;EAKJ,MAAM;;;;;;;;;;;;;;;;;cAiBM,SAAS,CAAC,GAAG,CAAC;;cAEd,SAAS,CAAC,GAAG,CAAC;;;CAG3B,CAAC;AACF,CAAC;AAED,SAAS,aAAa;IACpB,iEAAiE;IACjE,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,GAAe;IACrC,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,gFAAgF;IAChF,GAAG,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,6CAA6C;QAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IACD,GAAG,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,GAAG,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,cAAc;IACrB,GAAG,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,GAAG,aAAa,EAAE,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,gFAAgF;AAEhF,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,YAAY,UAAU,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,UAAU,CAAC,GAAe;IACjC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;IAChC,MAAM,WAAW,GAAG;QAClB,eAAe,GAAG,CAAC,IAAI,EAAE;QACzB,eAAe,GAAG,CAAC,IAAI,EAAE;QACzB,cAAc,GAAG,CAAC,SAAS,EAAE;QAC7B,QAAQ,WAAW,EAAE,EAAE;QACvB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B;SACE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;SAC9B,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;;;;;;;YAOG,OAAO,CAAC,QAAQ,IAAI,YAAY;EAC1C,WAAW;;;;wBAIW,GAAG;uBACJ,GAAG;;;;CAIzB,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,cAAc,CAAC,GAAe;IACrC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,gBAAgB;IAC/E,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAErC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,UAAU,CAAC,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB;IACvB,SAAS,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,YAAY,UAAU,CAAC,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,cAAc;IACrB,SAAS,CAAC,CAAC,SAAS,EAAE,GAAG,YAAY,UAAU,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,SAAS,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,YAAY,UAAU,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,cAAc,CAAC,GAAe;IAC5C,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,OAAO,SAAS,EAAE,CAAC;IACrB,CAAC;IACD,cAAc,CAAC,GAAG,CAAC,CAAC;IACpB,OAAO,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAe;IAI/C,IAAI,cAAc,EAAE,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,IAAI,QAAQ,KAAK,QAAQ;QAAE,gBAAgB,EAAE,CAAC;;QACzC,gBAAgB,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,IAAI,QAAQ,KAAK,QAAQ;QAAE,cAAc,EAAE,CAAC;;QACvC,cAAc,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,MAAM,CAAC,GAAG,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACpE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,oBAAoB,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,cAAc,EAAE,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,WAAW,CAAC;IAC7C,OAAO,CACL,2EAA2E;QAC3E,iCAAiC,IAAI,EAAE,CACxC,CAAC;AACJ,CAAC"}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* immediacy-daemon — the CLI shipped as this package's `bin`.
|
|
4
|
+
*
|
|
5
|
+
* One entrypoint for every deployment target: run it in the foreground (Docker,
|
|
6
|
+
* ad-hoc), or install it as a supervised service (launchd on macOS, systemd on
|
|
7
|
+
* Linux). Because an installed npm package knows its own path, the service unit
|
|
8
|
+
* points back at *this* copy — no __REPO__/__USER__ template editing like the
|
|
9
|
+
* old hand-managed plist.
|
|
10
|
+
*
|
|
11
|
+
* immediacy-daemon start # run in the foreground
|
|
12
|
+
* immediacy-daemon install [--port …] # install + start the service
|
|
13
|
+
* immediacy-daemon restart # rebuild? just restart to pick it up
|
|
14
|
+
* immediacy-daemon status # service state + /healthz probe
|
|
15
|
+
* immediacy-daemon logs [-f] # print (or follow) the log files
|
|
16
|
+
* immediacy-daemon uninstall # stop + remove the service
|
|
17
|
+
* immediacy-daemon doctor # check node/git/gh + reachability
|
|
18
|
+
*
|
|
19
|
+
* The bin stays dependency-light and lazy: heavy work (the daemon graph, native
|
|
20
|
+
* modules) is only imported by the command that needs it, so `--help`/`--version`
|
|
21
|
+
* and the service verbs start instantly.
|
|
22
|
+
*/
|
|
23
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
24
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
25
|
+
import { DEFAULT_ENV, logPaths, packageVersion, STATE_DIR, } from "./cli/paths.js";
|
|
26
|
+
import { installService, uninstallService, restartService, printServiceStatus, renderServiceUnit, lingerHint, } from "./cli/service.js";
|
|
27
|
+
const HELP = `immediacy-daemon v${packageVersion()}
|
|
28
|
+
|
|
29
|
+
Usage: immediacy-daemon <command> [options]
|
|
30
|
+
|
|
31
|
+
Commands:
|
|
32
|
+
start Run the daemon in the foreground (Ctrl-C to stop).
|
|
33
|
+
install [--print] Install + start the supervised service (launchd/systemd).
|
|
34
|
+
--print renders the unit to stdout without installing.
|
|
35
|
+
uninstall Stop and remove the service.
|
|
36
|
+
restart Restart the running service.
|
|
37
|
+
status Show service state and probe http://127.0.0.1:<port>/healthz.
|
|
38
|
+
logs [-f|--follow] Print the daemon's stdout/stderr logs (‑f to tail).
|
|
39
|
+
doctor Check node/git/gh on PATH and whether the daemon responds.
|
|
40
|
+
help Show this help.
|
|
41
|
+
|
|
42
|
+
Install/run options (also read from the environment):
|
|
43
|
+
--port <n> Local port to bind (DAEMON_PORT, default 8787)
|
|
44
|
+
--host <addr> Bind address (DAEMON_HOST, default 127.0.0.1)
|
|
45
|
+
--agent-mode <m> claude | mock (AGENT_MODE, default claude)
|
|
46
|
+
--e2e Enable the NaCl box layer (E2E=1)
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
immediacy-daemon install --port 8787
|
|
50
|
+
immediacy-daemon install --host 0.0.0.0 --agent-mode mock
|
|
51
|
+
immediacy-daemon status
|
|
52
|
+
`;
|
|
53
|
+
/** Minimal flag parser: collects --key value / --bool flags and bare args. */
|
|
54
|
+
function parseArgs(argv) {
|
|
55
|
+
const [command = "help", ...rest] = argv;
|
|
56
|
+
const flags = {};
|
|
57
|
+
for (let i = 0; i < rest.length; i++) {
|
|
58
|
+
const tok = rest[i];
|
|
59
|
+
if (!tok.startsWith("--") && !tok.startsWith("-"))
|
|
60
|
+
continue;
|
|
61
|
+
const key = tok.replace(/^--?/, "");
|
|
62
|
+
const next = rest[i + 1];
|
|
63
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
64
|
+
flags[key] = next;
|
|
65
|
+
i++;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
flags[key] = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { command, flags };
|
|
72
|
+
}
|
|
73
|
+
/** Resolve the effective ServiceEnv from flags, then env, then defaults. */
|
|
74
|
+
function resolveEnv(flags) {
|
|
75
|
+
const flagStr = (k) => typeof flags[k] === "string" ? flags[k] : undefined;
|
|
76
|
+
const port = Number(flagStr("port") ?? process.env.DAEMON_PORT ?? DEFAULT_ENV.port);
|
|
77
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
78
|
+
throw new Error(`invalid --port '${flagStr("port")}'`);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
port,
|
|
82
|
+
host: flagStr("host") ?? process.env.DAEMON_HOST ?? DEFAULT_ENV.host,
|
|
83
|
+
agentMode: flagStr("agent-mode") ?? process.env.AGENT_MODE ?? DEFAULT_ENV.agentMode,
|
|
84
|
+
e2e: flags.e2e === true || process.env.E2E === "1",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function which(cmd) {
|
|
88
|
+
const finder = process.platform === "win32" ? "where" : "which";
|
|
89
|
+
const r = spawnSync(finder, [cmd], { encoding: "utf8" });
|
|
90
|
+
return r.status === 0 ? (r.stdout.split("\n")[0]?.trim() ?? null) : null;
|
|
91
|
+
}
|
|
92
|
+
/** GET /healthz; returns true if the daemon answers 2xx within the timeout. */
|
|
93
|
+
async function probeHealth(port) {
|
|
94
|
+
try {
|
|
95
|
+
const ctl = AbortSignal.timeout(1500);
|
|
96
|
+
const res = await fetch(`http://127.0.0.1:${port}/healthz`, { signal: ctl });
|
|
97
|
+
return res.ok;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// --------------------------------------------------------------- commands ----
|
|
104
|
+
/** Run the daemon in-process by importing the entrypoint (side-effecting). */
|
|
105
|
+
async function cmdStart(env) {
|
|
106
|
+
process.env.DAEMON_PORT = String(env.port);
|
|
107
|
+
process.env.DAEMON_HOST = env.host;
|
|
108
|
+
process.env.AGENT_MODE = env.agentMode;
|
|
109
|
+
if (env.e2e)
|
|
110
|
+
process.env.E2E = "1";
|
|
111
|
+
await import("./index.js"); // boots the server; installs its own signal traps
|
|
112
|
+
}
|
|
113
|
+
function cmdInstall(env, dryRun) {
|
|
114
|
+
if (dryRun) {
|
|
115
|
+
const { path, contents } = renderServiceUnit(env);
|
|
116
|
+
console.log(`# would write to: ${path}\n`);
|
|
117
|
+
process.stdout.write(contents);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const path = installService(env);
|
|
121
|
+
console.log(`✓ installed and started service\n` +
|
|
122
|
+
` unit: ${path}\n` +
|
|
123
|
+
` bind: ${env.host}:${env.port} (agent: ${env.agentMode}${env.e2e ? ", e2e" : ""})`);
|
|
124
|
+
const hint = lingerHint();
|
|
125
|
+
if (hint)
|
|
126
|
+
console.log("\n" + hint);
|
|
127
|
+
console.log(`\nCheck it: immediacy-daemon status`);
|
|
128
|
+
}
|
|
129
|
+
function cmdUninstall() {
|
|
130
|
+
uninstallService();
|
|
131
|
+
console.log("✓ service stopped and removed");
|
|
132
|
+
}
|
|
133
|
+
function cmdRestart() {
|
|
134
|
+
restartService();
|
|
135
|
+
console.log("✓ service restarted");
|
|
136
|
+
}
|
|
137
|
+
async function cmdStatus(env) {
|
|
138
|
+
printServiceStatus();
|
|
139
|
+
const healthy = await probeHealth(env.port);
|
|
140
|
+
console.log(`\nhealth: ${healthy
|
|
141
|
+
? `✓ http://127.0.0.1:${env.port}/healthz responding`
|
|
142
|
+
: `✗ no response on http://127.0.0.1:${env.port}/healthz`}`);
|
|
143
|
+
}
|
|
144
|
+
function cmdLogs(follow) {
|
|
145
|
+
const { out, err } = logPaths();
|
|
146
|
+
const files = [out, err].filter(existsSync);
|
|
147
|
+
if (files.length === 0) {
|
|
148
|
+
console.log(`no log files yet at:\n ${out}\n ${err}`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (follow) {
|
|
152
|
+
// Hand off to `tail -f` so Ctrl-C behaves and we don't reimplement polling.
|
|
153
|
+
const child = spawn("tail", ["-n", "50", "-F", ...files], {
|
|
154
|
+
stdio: "inherit",
|
|
155
|
+
});
|
|
156
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
for (const f of files) {
|
|
160
|
+
console.log(`\n=== ${f} ===`);
|
|
161
|
+
process.stdout.write(readFileSync(f, "utf8"));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function cmdDoctor(env) {
|
|
165
|
+
const checks = [];
|
|
166
|
+
const node = process.version;
|
|
167
|
+
checks.push(["node", true, `${node} (${process.execPath})`]);
|
|
168
|
+
for (const tool of ["git", "gh", "claude"]) {
|
|
169
|
+
const p = which(tool);
|
|
170
|
+
checks.push([tool, p !== null, p ?? "not found on PATH"]);
|
|
171
|
+
}
|
|
172
|
+
checks.push([
|
|
173
|
+
"state dir",
|
|
174
|
+
existsSync(STATE_DIR),
|
|
175
|
+
existsSync(STATE_DIR) ? STATE_DIR : `${STATE_DIR} (created on first run)`,
|
|
176
|
+
]);
|
|
177
|
+
const healthy = await probeHealth(env.port);
|
|
178
|
+
checks.push([
|
|
179
|
+
"daemon",
|
|
180
|
+
healthy,
|
|
181
|
+
healthy ? `responding on :${env.port}` : `not responding on :${env.port}`,
|
|
182
|
+
]);
|
|
183
|
+
for (const [name, ok, detail] of checks) {
|
|
184
|
+
console.log(` ${ok ? "✓" : "✗"} ${name.padEnd(10)} ${detail}`);
|
|
185
|
+
}
|
|
186
|
+
// gh is optional-ish; git is not. Exit non-zero only on hard failures.
|
|
187
|
+
const gitOk = checks.find(([n]) => n === "git")?.[1] ?? false;
|
|
188
|
+
if (!gitOk)
|
|
189
|
+
process.exitCode = 1;
|
|
190
|
+
}
|
|
191
|
+
// ------------------------------------------------------------------- main ----
|
|
192
|
+
async function main() {
|
|
193
|
+
const { command, flags } = parseArgs(process.argv.slice(2));
|
|
194
|
+
if (command === "help" || flags.help || flags.h) {
|
|
195
|
+
console.log(HELP);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (command === "version" || flags.version || flags.v) {
|
|
199
|
+
console.log(packageVersion());
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
switch (command) {
|
|
203
|
+
case "start":
|
|
204
|
+
return cmdStart(resolveEnv(flags));
|
|
205
|
+
case "install":
|
|
206
|
+
return cmdInstall(resolveEnv(flags), flags.print === true || flags["dry-run"] === true);
|
|
207
|
+
case "uninstall":
|
|
208
|
+
return cmdUninstall();
|
|
209
|
+
case "restart":
|
|
210
|
+
return cmdRestart();
|
|
211
|
+
case "status":
|
|
212
|
+
return cmdStatus(resolveEnv(flags));
|
|
213
|
+
case "logs":
|
|
214
|
+
return cmdLogs(flags.f === true || flags.follow === true);
|
|
215
|
+
case "doctor":
|
|
216
|
+
return cmdDoctor(resolveEnv(flags));
|
|
217
|
+
default:
|
|
218
|
+
console.error(`unknown command '${command}'\n`);
|
|
219
|
+
console.log(HELP);
|
|
220
|
+
process.exitCode = 2;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
main().catch((err) => {
|
|
224
|
+
console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
|
|
225
|
+
process.exitCode = 1;
|
|
226
|
+
});
|
|
227
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|