@victor-software-house/pi-acp 0.7.0 → 0.9.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/{client-CTg5Oiz5.mjs → client-BjK2BnaD.mjs} +4 -4
- package/dist/{client-CTg5Oiz5.mjs.map → client-BjK2BnaD.mjs.map} +1 -1
- package/dist/{serve-DLukbpF4.mjs → daemon-tHPrf3qs.mjs} +801 -26
- package/dist/daemon-tHPrf3qs.mjs.map +1 -0
- package/dist/index.mjs +20 -23
- package/dist/index.mjs.map +1 -1
- package/dist/operator-AtBT_SZT.mjs +52 -0
- package/dist/operator-AtBT_SZT.mjs.map +1 -0
- package/dist/pi-package-DFOfbtij.mjs +3 -0
- package/dist/pi-package-aHs6rWNo.mjs +29 -0
- package/dist/pi-package-aHs6rWNo.mjs.map +1 -0
- package/dist/{socket-BUNWxnAN.mjs → socket-wvV053VI.mjs} +28 -25
- package/dist/socket-wvV053VI.mjs.map +1 -0
- package/package.json +5 -3
- package/dist/daemon-irIzm1zJ.mjs +0 -189
- package/dist/daemon-irIzm1zJ.mjs.map +0 -1
- package/dist/in-process-DcAV6Sgx.mjs +0 -31
- package/dist/in-process-DcAV6Sgx.mjs.map +0 -1
- package/dist/serve-DLukbpF4.mjs.map +0 -1
- package/dist/socket-BUNWxnAN.mjs.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { n as controlSocketPath } from "./socket-wvV053VI.mjs";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
//#region src/client/operator.ts
|
|
5
|
+
/**
|
|
6
|
+
* Operator client modes: pi-acp --daemon-status, pi-acp --daemon-stop.
|
|
7
|
+
*
|
|
8
|
+
* Talks to the daemon's control plane (Hono over Unix-domain HTTP) using
|
|
9
|
+
* Bun.fetch's `unix` option. The control socket is separate from the ACP
|
|
10
|
+
* socket, so these commands never disturb live ACP traffic.
|
|
11
|
+
*/
|
|
12
|
+
const CONTROL_TIMEOUT_MS = 5e3;
|
|
13
|
+
async function controlFetch(path, init = {}) {
|
|
14
|
+
const sock = controlSocketPath();
|
|
15
|
+
if (!existsSync(sock)) return null;
|
|
16
|
+
try {
|
|
17
|
+
return await Bun.fetch(`http://daemon${path}`, {
|
|
18
|
+
...init,
|
|
19
|
+
unix: sock,
|
|
20
|
+
signal: AbortSignal.timeout(CONTROL_TIMEOUT_MS)
|
|
21
|
+
});
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function runDaemonStatus() {
|
|
27
|
+
const res = await controlFetch("/status");
|
|
28
|
+
if (res === null) {
|
|
29
|
+
process.stderr.write("pi-acp daemon: not running\n");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const body = await res.text();
|
|
33
|
+
process.stdout.write(`${body}\n`);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
async function runDaemonStop() {
|
|
37
|
+
const res = await controlFetch("/shutdown", { method: "POST" });
|
|
38
|
+
if (res === null) {
|
|
39
|
+
process.stderr.write("pi-acp daemon: not running\n");
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
process.stderr.write(`pi-acp daemon: shutdown failed (HTTP ${res.status})\n`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
process.stderr.write("pi-acp daemon: stopped\n");
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { runDaemonStatus, runDaemonStop };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=operator-AtBT_SZT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator-AtBT_SZT.mjs","names":[],"sources":["../src/client/operator.ts"],"sourcesContent":["/**\n * Operator client modes: pi-acp --daemon-status, pi-acp --daemon-stop.\n *\n * Talks to the daemon's control plane (Hono over Unix-domain HTTP) using\n * Bun.fetch's `unix` option. The control socket is separate from the ACP\n * socket, so these commands never disturb live ACP traffic.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { controlSocketPath } from \"@pi-acp/daemon/socket\";\n\nconst CONTROL_TIMEOUT_MS = 5000;\n\nasync function controlFetch(path: string, init: RequestInit = {}): Promise<Response | null> {\n\tconst sock = controlSocketPath();\n\tif (!existsSync(sock)) return null;\n\ttry {\n\t\treturn await Bun.fetch(`http://daemon${path}`, {\n\t\t\t...init,\n\t\t\tunix: sock,\n\t\t\tsignal: AbortSignal.timeout(CONTROL_TIMEOUT_MS),\n\t\t});\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function runDaemonStatus(): Promise<void> {\n\tconst res = await controlFetch(\"/status\");\n\tif (res === null) {\n\t\tprocess.stderr.write(\"pi-acp daemon: not running\\n\");\n\t\tprocess.exit(1);\n\t}\n\tconst body = await res.text();\n\tprocess.stdout.write(`${body}\\n`);\n\tprocess.exit(0);\n}\n\nexport async function runDaemonStop(): Promise<void> {\n\tconst res = await controlFetch(\"/shutdown\", { method: \"POST\" });\n\tif (res === null) {\n\t\tprocess.stderr.write(\"pi-acp daemon: not running\\n\");\n\t\tprocess.exit(0);\n\t}\n\tif (!res.ok) {\n\t\tprocess.stderr.write(`pi-acp daemon: shutdown failed (HTTP ${res.status})\\n`);\n\t\tprocess.exit(1);\n\t}\n\tprocess.stderr.write(\"pi-acp daemon: stopped\\n\");\n\tprocess.exit(0);\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,qBAAqB;AAE3B,eAAe,aAAa,MAAc,OAAoB,EAAE,EAA4B;CAC3F,MAAM,OAAO,mBAAmB;AAChC,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO;AAC9B,KAAI;AACH,SAAO,MAAM,IAAI,MAAM,gBAAgB,QAAQ;GAC9C,GAAG;GACH,MAAM;GACN,QAAQ,YAAY,QAAQ,mBAAmB;GAC/C,CAAC;SACK;AACP,SAAO;;;AAIT,eAAsB,kBAAiC;CACtD,MAAM,MAAM,MAAM,aAAa,UAAU;AACzC,KAAI,QAAQ,MAAM;AACjB,UAAQ,OAAO,MAAM,+BAA+B;AACpD,UAAQ,KAAK,EAAE;;CAEhB,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,SAAQ,OAAO,MAAM,GAAG,KAAK,IAAI;AACjC,SAAQ,KAAK,EAAE;;AAGhB,eAAsB,gBAA+B;CACpD,MAAM,MAAM,MAAM,aAAa,aAAa,EAAE,QAAQ,QAAQ,CAAC;AAC/D,KAAI,QAAQ,MAAM;AACjB,UAAQ,OAAO,MAAM,+BAA+B;AACpD,UAAQ,KAAK,EAAE;;AAEhB,KAAI,CAAC,IAAI,IAAI;AACZ,UAAQ,OAAO,MAAM,wCAAwC,IAAI,OAAO,KAAK;AAC7E,UAAQ,KAAK,EAAE;;AAEhB,SAAQ,OAAO,MAAM,2BAA2B;AAChD,SAAQ,KAAK,EAAE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
//#region src/pi-package.ts
|
|
5
|
+
/**
|
|
6
|
+
* Helpers to locate the bundled `@earendil-works/pi-coding-agent` package on
|
|
7
|
+
* disk so we can resolve its CLI binary and CHANGELOG without depending on a
|
|
8
|
+
* `pi` command being globally on PATH.
|
|
9
|
+
*
|
|
10
|
+
* Pi is a regular npm dependency — it's installed alongside pi-acp under
|
|
11
|
+
* node_modules. `import.meta.resolve` finds its `package.json`; we derive the
|
|
12
|
+
* sibling paths from there.
|
|
13
|
+
*/
|
|
14
|
+
let cached;
|
|
15
|
+
function piPackageRoot() {
|
|
16
|
+
if (cached !== void 0) return cached;
|
|
17
|
+
cached = dirname(fileURLToPath(import.meta.resolve("@earendil-works/pi-coding-agent/package.json")));
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
function piCliEntry() {
|
|
21
|
+
return join(piPackageRoot(), "dist", "cli.js");
|
|
22
|
+
}
|
|
23
|
+
function piChangelogPath() {
|
|
24
|
+
return join(piPackageRoot(), "CHANGELOG.md");
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { piCliEntry as n, piPackageRoot as r, piChangelogPath as t };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=pi-package-aHs6rWNo.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-package-aHs6rWNo.mjs","names":[],"sources":["../src/pi-package.ts"],"sourcesContent":["/**\n * Helpers to locate the bundled `@earendil-works/pi-coding-agent` package on\n * disk so we can resolve its CLI binary and CHANGELOG without depending on a\n * `pi` command being globally on PATH.\n *\n * Pi is a regular npm dependency — it's installed alongside pi-acp under\n * node_modules. `import.meta.resolve` finds its `package.json`; we derive the\n * sibling paths from there.\n */\n\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nlet cached: string | undefined;\n\nexport function piPackageRoot(): string {\n\tif (cached !== undefined) return cached;\n\tconst pkgUrl = import.meta.resolve(\"@earendil-works/pi-coding-agent/package.json\");\n\tcached = dirname(fileURLToPath(pkgUrl));\n\treturn cached;\n}\n\nexport function piCliEntry(): string {\n\treturn join(piPackageRoot(), \"dist\", \"cli.js\");\n}\n\nexport function piChangelogPath(): string {\n\treturn join(piPackageRoot(), \"CHANGELOG.md\");\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAI;AAEJ,SAAgB,gBAAwB;AACvC,KAAI,WAAW,KAAA,EAAW,QAAO;AAEjC,UAAS,QAAQ,cADF,OAAO,KAAK,QAAQ,+CACE,CAAC,CAAC;AACvC,QAAO;;AAGR,SAAgB,aAAqB;AACpC,QAAO,KAAK,eAAe,EAAE,QAAQ,SAAS;;AAG/C,SAAgB,kBAA0B;AACzC,QAAO,KAAK,eAAe,EAAE,eAAe"}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { closeSync, constants, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
//#region src/daemon/socket.ts
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Socket + lockfile live under ~/.pi/run/ by default so everything pi-related
|
|
8
|
+
* stays under one tree. PI_ACP_SOCKET_DIR overrides for tests / sandboxing.
|
|
9
9
|
*/
|
|
10
|
+
function baseDir() {
|
|
11
|
+
return process.env["PI_ACP_SOCKET_DIR"] ?? join(homedir(), ".pi", "run");
|
|
12
|
+
}
|
|
10
13
|
function socketPath() {
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
return join(baseDir(), "pi-acp.sock");
|
|
15
|
+
}
|
|
16
|
+
function controlSocketPath() {
|
|
17
|
+
return join(baseDir(), "pi-acp-control.sock");
|
|
13
18
|
}
|
|
14
19
|
function lockfilePath() {
|
|
15
|
-
|
|
16
|
-
return `${socketPath()}.lock`;
|
|
20
|
+
return join(baseDir(), "pi-acp.lock");
|
|
17
21
|
}
|
|
18
22
|
function errnoCode(err) {
|
|
19
23
|
if (typeof err === "object" && err !== null && "code" in err) {
|
|
@@ -35,6 +39,7 @@ function pidIsAlive(pid) {
|
|
|
35
39
|
* and its PID is alive, refuse. If the PID is dead, reclaim.
|
|
36
40
|
*/
|
|
37
41
|
function acquireLock() {
|
|
42
|
+
ensureSocketParentDir();
|
|
38
43
|
const path = lockfilePath();
|
|
39
44
|
for (let attempt = 0; attempt < 2; attempt++) try {
|
|
40
45
|
const fd = openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 384);
|
|
@@ -71,30 +76,28 @@ function readPidFromLockfile(path) {
|
|
|
71
76
|
return;
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
|
-
|
|
75
|
-
* Remove a socket file left behind by a dead daemon. Safe no-op on Windows
|
|
76
|
-
* (named pipes have no filesystem residue) or if the path doesn't exist.
|
|
77
|
-
*/
|
|
78
|
-
function removeStaleSocketIfAny() {
|
|
79
|
-
if (process.platform === "win32") return;
|
|
80
|
-
const path = socketPath();
|
|
79
|
+
function removeIfExists(path) {
|
|
81
80
|
try {
|
|
82
81
|
statSync(path);
|
|
83
82
|
unlinkSync(path);
|
|
84
83
|
} catch {}
|
|
85
84
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
function removeStaleSocketIfAny() {
|
|
86
|
+
removeIfExists(socketPath());
|
|
87
|
+
removeIfExists(controlSocketPath());
|
|
88
|
+
}
|
|
90
89
|
function ensureSocketParentDir() {
|
|
91
|
-
if (process.platform === "win32") return;
|
|
92
90
|
const dir = dirname(socketPath());
|
|
93
91
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
mkdirSync(dir, {
|
|
93
|
+
recursive: true,
|
|
94
|
+
mode: 448
|
|
95
|
+
});
|
|
96
|
+
} catch (err) {
|
|
97
|
+
if (errnoCode(err) !== "EEXIST") throw err;
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
//#endregion
|
|
98
|
-
export {
|
|
101
|
+
export { removeStaleSocketIfAny as a, releaseLock as i, controlSocketPath as n, socketPath as o, ensureSocketParentDir as r, acquireLock as t };
|
|
99
102
|
|
|
100
|
-
//# sourceMappingURL=socket-
|
|
103
|
+
//# sourceMappingURL=socket-wvV053VI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-wvV053VI.mjs","names":["fsConstants"],"sources":["../src/daemon/socket.ts"],"sourcesContent":["import {\n\tcloseSync,\n\tconstants as fsConstants,\n\tmkdirSync,\n\topenSync,\n\treadFileSync,\n\tstatSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Socket + lockfile live under ~/.pi/run/ by default so everything pi-related\n * stays under one tree. PI_ACP_SOCKET_DIR overrides for tests / sandboxing.\n */\nfunction baseDir(): string {\n\treturn process.env[\"PI_ACP_SOCKET_DIR\"] ?? join(homedir(), \".pi\", \"run\");\n}\n\nexport function socketPath(): string {\n\treturn join(baseDir(), \"pi-acp.sock\");\n}\n\nexport function controlSocketPath(): string {\n\treturn join(baseDir(), \"pi-acp-control.sock\");\n}\n\nexport function lockfilePath(): string {\n\treturn join(baseDir(), \"pi-acp.lock\");\n}\n\nfunction errnoCode(err: unknown): string | undefined {\n\tif (typeof err === \"object\" && err !== null && \"code\" in err) {\n\t\tconst code = (err as { code: unknown }).code;\n\t\treturn typeof code === \"string\" ? code : undefined;\n\t}\n\treturn undefined;\n}\n\nfunction pidIsAlive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (err) {\n\t\tconst code = errnoCode(err);\n\t\tif (code === \"EPERM\") return true;\n\t\treturn false;\n\t}\n}\n\nexport interface LockAcquireResult {\n\tok: boolean;\n\theldByPid?: number;\n}\n\n/**\n * Acquire the daemon lockfile by writing our PID. If a lockfile already exists\n * and its PID is alive, refuse. If the PID is dead, reclaim.\n */\nexport function acquireLock(): LockAcquireResult {\n\tensureSocketParentDir();\n\tconst path = lockfilePath();\n\tfor (let attempt = 0; attempt < 2; attempt++) {\n\t\ttry {\n\t\t\tconst fd = openSync(\n\t\t\t\tpath,\n\t\t\t\tfsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY,\n\t\t\t\t0o600,\n\t\t\t);\n\t\t\ttry {\n\t\t\t\twriteFileSync(fd, String(process.pid));\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t\treturn { ok: true };\n\t\t} catch (err) {\n\t\t\tconst code = errnoCode(err);\n\t\t\tif (code !== \"EEXIST\") throw err;\n\t\t\tconst existing = readPidFromLockfile(path);\n\t\t\tif (existing !== undefined && pidIsAlive(existing)) {\n\t\t\t\treturn { ok: false, heldByPid: existing };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tunlinkSync(path);\n\t\t\t} catch {\n\t\t\t\t/* ignore — next attempt */\n\t\t\t}\n\t\t}\n\t}\n\treturn { ok: false };\n}\n\nexport function releaseLock(): void {\n\ttry {\n\t\tunlinkSync(lockfilePath());\n\t} catch {\n\t\t/* ignore */\n\t}\n}\n\nfunction readPidFromLockfile(path: string): number | undefined {\n\ttry {\n\t\tconst raw = readFileSync(path, \"utf8\").trim();\n\t\tconst n = Number.parseInt(raw, 10);\n\t\treturn Number.isFinite(n) ? n : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction removeIfExists(path: string): void {\n\ttry {\n\t\tstatSync(path);\n\t\tunlinkSync(path);\n\t} catch {\n\t\t/* not present — fine */\n\t}\n}\n\nexport function removeStaleSocketIfAny(): void {\n\tremoveIfExists(socketPath());\n\tremoveIfExists(controlSocketPath());\n}\n\nexport function ensureSocketParentDir(): void {\n\tconst dir = dirname(socketPath());\n\ttry {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t} catch (err) {\n\t\tif (errnoCode(err) !== \"EEXIST\") throw err;\n\t}\n}\n"],"mappings":";;;;;;;;;AAiBA,SAAS,UAAkB;AAC1B,QAAO,QAAQ,IAAI,wBAAwB,KAAK,SAAS,EAAE,OAAO,MAAM;;AAGzE,SAAgB,aAAqB;AACpC,QAAO,KAAK,SAAS,EAAE,cAAc;;AAGtC,SAAgB,oBAA4B;AAC3C,QAAO,KAAK,SAAS,EAAE,sBAAsB;;AAG9C,SAAgB,eAAuB;AACtC,QAAO,KAAK,SAAS,EAAE,cAAc;;AAGtC,SAAS,UAAU,KAAkC;AACpD,KAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU,KAAK;EAC7D,MAAM,OAAQ,IAA0B;AACxC,SAAO,OAAO,SAAS,WAAW,OAAO,KAAA;;;AAK3C,SAAS,WAAW,KAAsB;AACzC,KAAI;AACH,UAAQ,KAAK,KAAK,EAAE;AACpB,SAAO;UACC,KAAK;AAEb,MADa,UAAU,IACf,KAAK,QAAS,QAAO;AAC7B,SAAO;;;;;;;AAaT,SAAgB,cAAiC;AAChD,wBAAuB;CACvB,MAAM,OAAO,cAAc;AAC3B,MAAK,IAAI,UAAU,GAAG,UAAU,GAAG,UAClC,KAAI;EACH,MAAM,KAAK,SACV,MACAA,UAAY,UAAUA,UAAY,SAASA,UAAY,UACvD,IACA;AACD,MAAI;AACH,iBAAc,IAAI,OAAO,QAAQ,IAAI,CAAC;YAC7B;AACT,aAAU,GAAG;;AAEd,SAAO,EAAE,IAAI,MAAM;UACX,KAAK;AAEb,MADa,UAAU,IACf,KAAK,SAAU,OAAM;EAC7B,MAAM,WAAW,oBAAoB,KAAK;AAC1C,MAAI,aAAa,KAAA,KAAa,WAAW,SAAS,CACjD,QAAO;GAAE,IAAI;GAAO,WAAW;GAAU;AAE1C,MAAI;AACH,cAAW,KAAK;UACT;;AAKV,QAAO,EAAE,IAAI,OAAO;;AAGrB,SAAgB,cAAoB;AACnC,KAAI;AACH,aAAW,cAAc,CAAC;SACnB;;AAKT,SAAS,oBAAoB,MAAkC;AAC9D,KAAI;EACH,MAAM,MAAM,aAAa,MAAM,OAAO,CAAC,MAAM;EAC7C,MAAM,IAAI,OAAO,SAAS,KAAK,GAAG;AAClC,SAAO,OAAO,SAAS,EAAE,GAAG,IAAI,KAAA;SACzB;AACP;;;AAIF,SAAS,eAAe,MAAoB;AAC3C,KAAI;AACH,WAAS,KAAK;AACd,aAAW,KAAK;SACT;;AAKT,SAAgB,yBAA+B;AAC9C,gBAAe,YAAY,CAAC;AAC5B,gBAAe,mBAAmB,CAAC;;AAGpC,SAAgB,wBAA8B;CAC7C,MAAM,MAAM,QAAQ,YAAY,CAAC;AACjC,KAAI;AACH,YAAU,KAAK;GAAE,WAAW;GAAM,MAAM;GAAO,CAAC;UACxC,KAAK;AACb,MAAI,UAAU,IAAI,KAAK,SAAU,OAAM"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@victor-software-house/pi-acp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "ACP adapter for pi coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Victor Software House",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"adapter"
|
|
24
24
|
],
|
|
25
25
|
"engines": {
|
|
26
|
-
"
|
|
26
|
+
"bun": ">=1.3"
|
|
27
27
|
},
|
|
28
28
|
"type": "module",
|
|
29
29
|
"main": "dist/index.mjs",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"scripts": {
|
|
37
37
|
"dev": "bun src/index.ts",
|
|
38
38
|
"build": "tsdown",
|
|
39
|
-
"start": "
|
|
39
|
+
"start": "bun dist/index.mjs",
|
|
40
40
|
"typecheck": "tsc --noEmit",
|
|
41
41
|
"lint": "bun run lint:biome && bun run lint:oxlint",
|
|
42
42
|
"lint:biome": "biome check .",
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@agentclientprotocol/sdk": "^0.22.1",
|
|
52
52
|
"@earendil-works/pi-coding-agent": "^0.75.3",
|
|
53
|
+
"hono": "^4.12.21",
|
|
54
|
+
"yaml": "^2.9.0",
|
|
53
55
|
"zod": "^4.3.6"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
package/dist/daemon-irIzm1zJ.mjs
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { a as socketPath, i as removeStaleSocketIfAny, n as ensureSocketParentDir, r as releaseLock, t as acquireLock } from "./socket-BUNWxnAN.mjs";
|
|
3
|
-
import { t as serveAcp } from "./serve-DLukbpF4.mjs";
|
|
4
|
-
import { createServer } from "node:net";
|
|
5
|
-
//#region src/daemon/session-registry.ts
|
|
6
|
-
function createSessionRegistry() {
|
|
7
|
-
const map = /* @__PURE__ */ new Map();
|
|
8
|
-
return {
|
|
9
|
-
register(input) {
|
|
10
|
-
const entry = {
|
|
11
|
-
sessionId: input.sessionId,
|
|
12
|
-
piSession: input.piSession,
|
|
13
|
-
ownerConnectionId: input.ownerConnectionId,
|
|
14
|
-
alsoHeldBy: /* @__PURE__ */ new Set(),
|
|
15
|
-
cwd: input.cwd,
|
|
16
|
-
sessionFile: input.sessionFile,
|
|
17
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
18
|
-
};
|
|
19
|
-
map.set(input.sessionId, entry);
|
|
20
|
-
},
|
|
21
|
-
attach(sessionId, connectionId) {
|
|
22
|
-
const entry = map.get(sessionId);
|
|
23
|
-
if (entry === void 0) return void 0;
|
|
24
|
-
if (entry.ownerConnectionId !== connectionId) {
|
|
25
|
-
entry.alsoHeldBy.add(connectionId);
|
|
26
|
-
entry.updatedAt = /* @__PURE__ */ new Date();
|
|
27
|
-
}
|
|
28
|
-
return entry;
|
|
29
|
-
},
|
|
30
|
-
release(sessionId, connectionId) {
|
|
31
|
-
const entry = map.get(sessionId);
|
|
32
|
-
if (entry === void 0) return { kind: "unknown" };
|
|
33
|
-
if (entry.alsoHeldBy.delete(connectionId)) {
|
|
34
|
-
entry.updatedAt = /* @__PURE__ */ new Date();
|
|
35
|
-
if (entry.ownerConnectionId === connectionId && entry.alsoHeldBy.size === 0) {
|
|
36
|
-
map.delete(sessionId);
|
|
37
|
-
return {
|
|
38
|
-
kind: "disposed",
|
|
39
|
-
entry
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
kind: "still-held",
|
|
44
|
-
entry
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
if (entry.ownerConnectionId === connectionId) {
|
|
48
|
-
if (entry.alsoHeldBy.size > 0) {
|
|
49
|
-
const next = entry.alsoHeldBy.values().next().value;
|
|
50
|
-
if (next !== void 0) {
|
|
51
|
-
entry.alsoHeldBy.delete(next);
|
|
52
|
-
entry.ownerConnectionId = next;
|
|
53
|
-
entry.updatedAt = /* @__PURE__ */ new Date();
|
|
54
|
-
return {
|
|
55
|
-
kind: "still-held",
|
|
56
|
-
entry
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
map.delete(sessionId);
|
|
61
|
-
return {
|
|
62
|
-
kind: "disposed",
|
|
63
|
-
entry
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
return {
|
|
67
|
-
kind: "still-held",
|
|
68
|
-
entry
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
get(sessionId) {
|
|
72
|
-
return map.get(sessionId);
|
|
73
|
-
},
|
|
74
|
-
listAll() {
|
|
75
|
-
return Array.from(map.values());
|
|
76
|
-
},
|
|
77
|
-
listOwnedBy(connectionId) {
|
|
78
|
-
return Array.from(map.values()).filter((e) => e.ownerConnectionId === connectionId || e.alsoHeldBy.has(connectionId));
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/daemon/context.ts
|
|
84
|
-
/**
|
|
85
|
-
* Daemon-level shared state injected into per-connection PiAcpAgent instances.
|
|
86
|
-
*
|
|
87
|
-
* Phase 1 landed the interface + stub IdleTracker.
|
|
88
|
-
* Phase 2 wires the real SessionRegistry.
|
|
89
|
-
* Phase 3 will replace IdleTracker.
|
|
90
|
-
*/
|
|
91
|
-
function createNoopIdleTracker() {
|
|
92
|
-
return {
|
|
93
|
-
bump() {},
|
|
94
|
-
dispose() {}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
function createDaemonContext() {
|
|
98
|
-
return {
|
|
99
|
-
sessionRegistry: createSessionRegistry(),
|
|
100
|
-
idleTracker: createNoopIdleTracker()
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/daemon/index.ts
|
|
105
|
-
/**
|
|
106
|
-
* Daemon entry point. Invoked when pi-acp is launched with `--daemon`.
|
|
107
|
-
*
|
|
108
|
-
* Lifecycle:
|
|
109
|
-
* 1. Acquire per-UID lockfile (refuses if another daemon alive).
|
|
110
|
-
* 2. Remove stale socket file if any (left by a dead prior daemon).
|
|
111
|
-
* 3. Construct DaemonContext shared singletons (Phase 1: stubs).
|
|
112
|
-
* 4. Bind socket; accept loop spawns a per-connection serveAcp instance.
|
|
113
|
-
* 5. SIGINT / SIGTERM → graceful shutdown.
|
|
114
|
-
*/
|
|
115
|
-
async function runDaemon() {
|
|
116
|
-
const lockResult = acquireLock();
|
|
117
|
-
if (!lockResult.ok) {
|
|
118
|
-
process.stderr.write(`pi-acp daemon: already running (pid ${lockResult.heldByPid ?? "unknown"})\n`);
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
ensureSocketParentDir();
|
|
122
|
-
removeStaleSocketIfAny();
|
|
123
|
-
const ctx = createDaemonContext();
|
|
124
|
-
const connections = /* @__PURE__ */ new Set();
|
|
125
|
-
let shuttingDown = false;
|
|
126
|
-
const server = createServer((socket) => {
|
|
127
|
-
if (shuttingDown) {
|
|
128
|
-
socket.destroy();
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const handle = serveAcp({
|
|
132
|
-
input: socket,
|
|
133
|
-
output: socket,
|
|
134
|
-
daemonContext: ctx
|
|
135
|
-
});
|
|
136
|
-
const entry = {
|
|
137
|
-
socket,
|
|
138
|
-
handle
|
|
139
|
-
};
|
|
140
|
-
connections.add(entry);
|
|
141
|
-
ctx.idleTracker.bump(1);
|
|
142
|
-
const cleanup = () => {
|
|
143
|
-
if (!connections.delete(entry)) return;
|
|
144
|
-
try {
|
|
145
|
-
handle.dispose();
|
|
146
|
-
} catch {}
|
|
147
|
-
ctx.idleTracker.bump(-1);
|
|
148
|
-
};
|
|
149
|
-
socket.on("close", cleanup);
|
|
150
|
-
socket.on("error", cleanup);
|
|
151
|
-
});
|
|
152
|
-
server.on("error", (err) => {
|
|
153
|
-
process.stderr.write(`pi-acp daemon: server error: ${err.message}\n`);
|
|
154
|
-
});
|
|
155
|
-
await new Promise((resolve, reject) => {
|
|
156
|
-
const path = socketPath();
|
|
157
|
-
server.listen(path, () => resolve());
|
|
158
|
-
server.once("error", reject);
|
|
159
|
-
});
|
|
160
|
-
if (process.env["PI_ACP_DAEMON_DEBUG"] === "1") process.stderr.write(`pi-acp daemon: listening on ${socketPath()} (pid ${process.pid})\n`);
|
|
161
|
-
const shutdown = async () => {
|
|
162
|
-
if (shuttingDown) return;
|
|
163
|
-
shuttingDown = true;
|
|
164
|
-
server.close();
|
|
165
|
-
for (const entry of connections) {
|
|
166
|
-
try {
|
|
167
|
-
entry.handle.dispose();
|
|
168
|
-
} catch {}
|
|
169
|
-
try {
|
|
170
|
-
entry.socket.destroy();
|
|
171
|
-
} catch {}
|
|
172
|
-
}
|
|
173
|
-
connections.clear();
|
|
174
|
-
ctx.idleTracker.dispose();
|
|
175
|
-
removeStaleSocketIfAny();
|
|
176
|
-
releaseLock();
|
|
177
|
-
process.exit(0);
|
|
178
|
-
};
|
|
179
|
-
process.on("SIGINT", () => {
|
|
180
|
-
shutdown();
|
|
181
|
-
});
|
|
182
|
-
process.on("SIGTERM", () => {
|
|
183
|
-
shutdown();
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
//#endregion
|
|
187
|
-
export { runDaemon };
|
|
188
|
-
|
|
189
|
-
//# sourceMappingURL=daemon-irIzm1zJ.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-irIzm1zJ.mjs","names":[],"sources":["../src/daemon/session-registry.ts","../src/daemon/context.ts","../src/daemon/index.ts"],"sourcesContent":["/**\n * Daemon-level session registry. Maps sessionId -> live AgentSession plus\n * ownership refcount so that closing a session from one client does NOT\n * dispose the underlying pi runtime if another client also holds it.\n */\n\nimport type { AgentSession } from \"@earendil-works/pi-coding-agent\";\n\nexport interface SessionEntry {\n\tsessionId: string;\n\tpiSession: AgentSession;\n\townerConnectionId: string;\n\talsoHeldBy: Set<string>;\n\tcwd: string;\n\tsessionFile: string | undefined;\n\tupdatedAt: Date;\n}\n\nexport interface SessionRegistry {\n\tregister(entry: NewSessionEntry): void;\n\tattach(sessionId: string, connectionId: string): SessionEntry | undefined;\n\trelease(sessionId: string, connectionId: string): ReleaseResult;\n\tget(sessionId: string): SessionEntry | undefined;\n\tlistAll(): SessionEntry[];\n\tlistOwnedBy(connectionId: string): SessionEntry[];\n}\n\nexport interface NewSessionEntry {\n\tsessionId: string;\n\tpiSession: AgentSession;\n\townerConnectionId: string;\n\tcwd: string;\n\tsessionFile: string | undefined;\n}\n\nexport type ReleaseResult =\n\t| { kind: \"disposed\"; entry: SessionEntry }\n\t| { kind: \"still-held\"; entry: SessionEntry }\n\t| { kind: \"unknown\" };\n\nexport function createSessionRegistry(): SessionRegistry {\n\tconst map = new Map<string, SessionEntry>();\n\n\treturn {\n\t\tregister(input) {\n\t\t\tconst entry: SessionEntry = {\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpiSession: input.piSession,\n\t\t\t\townerConnectionId: input.ownerConnectionId,\n\t\t\t\talsoHeldBy: new Set<string>(),\n\t\t\t\tcwd: input.cwd,\n\t\t\t\tsessionFile: input.sessionFile,\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t};\n\t\t\tmap.set(input.sessionId, entry);\n\t\t},\n\n\t\tattach(sessionId, connectionId) {\n\t\t\tconst entry = map.get(sessionId);\n\t\t\tif (entry === undefined) return undefined;\n\t\t\tif (entry.ownerConnectionId !== connectionId) {\n\t\t\t\tentry.alsoHeldBy.add(connectionId);\n\t\t\t\tentry.updatedAt = new Date();\n\t\t\t}\n\t\t\treturn entry;\n\t\t},\n\n\t\trelease(sessionId, connectionId) {\n\t\t\tconst entry = map.get(sessionId);\n\t\t\tif (entry === undefined) return { kind: \"unknown\" };\n\n\t\t\tif (entry.alsoHeldBy.delete(connectionId)) {\n\t\t\t\tentry.updatedAt = new Date();\n\t\t\t\tif (entry.ownerConnectionId === connectionId && entry.alsoHeldBy.size === 0) {\n\t\t\t\t\tmap.delete(sessionId);\n\t\t\t\t\treturn { kind: \"disposed\", entry };\n\t\t\t\t}\n\t\t\t\treturn { kind: \"still-held\", entry };\n\t\t\t}\n\n\t\t\tif (entry.ownerConnectionId === connectionId) {\n\t\t\t\tif (entry.alsoHeldBy.size > 0) {\n\t\t\t\t\t// Hand ownership to one of the still-holders so the entry\n\t\t\t\t\t// keeps a coherent owner record. Pick first by iteration.\n\t\t\t\t\tconst next = entry.alsoHeldBy.values().next().value;\n\t\t\t\t\tif (next !== undefined) {\n\t\t\t\t\t\tentry.alsoHeldBy.delete(next);\n\t\t\t\t\t\tentry.ownerConnectionId = next;\n\t\t\t\t\t\tentry.updatedAt = new Date();\n\t\t\t\t\t\treturn { kind: \"still-held\", entry };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmap.delete(sessionId);\n\t\t\t\treturn { kind: \"disposed\", entry };\n\t\t\t}\n\n\t\t\treturn { kind: \"still-held\", entry };\n\t\t},\n\n\t\tget(sessionId) {\n\t\t\treturn map.get(sessionId);\n\t\t},\n\n\t\tlistAll() {\n\t\t\treturn Array.from(map.values());\n\t\t},\n\n\t\tlistOwnedBy(connectionId) {\n\t\t\treturn Array.from(map.values()).filter(\n\t\t\t\t(e) => e.ownerConnectionId === connectionId || e.alsoHeldBy.has(connectionId),\n\t\t\t);\n\t\t},\n\t};\n}\n","/**\n * Daemon-level shared state injected into per-connection PiAcpAgent instances.\n *\n * Phase 1 landed the interface + stub IdleTracker.\n * Phase 2 wires the real SessionRegistry.\n * Phase 3 will replace IdleTracker.\n */\n\nimport { createSessionRegistry, type SessionRegistry } from \"@pi-acp/daemon/session-registry\";\n\nexport interface DaemonContext {\n\t/** Cross-window session registry. PRD-003 FR-5. */\n\tsessionRegistry: SessionRegistry;\n\t/** Idle-shutdown tracker. Stub in Phase 1-2; real in Phase 3. */\n\tidleTracker: IdleTracker;\n}\n\n/** Phase-3 stub. Replaced when idle shutdown lands. */\nexport interface IdleTracker {\n\tbump(delta: 1 | -1): void;\n\tdispose(): void;\n}\n\nexport type { SessionEntry, SessionRegistry } from \"@pi-acp/daemon/session-registry\";\nexport { createSessionRegistry } from \"@pi-acp/daemon/session-registry\";\n\nexport function createNoopIdleTracker(): IdleTracker {\n\treturn {\n\t\tbump() {\n\t\t\t/* phase 3 wires this */\n\t\t},\n\t\tdispose() {\n\t\t\t/* phase 3 wires this */\n\t\t},\n\t};\n}\n\nexport function createDaemonContext(): DaemonContext {\n\treturn {\n\t\tsessionRegistry: createSessionRegistry(),\n\t\tidleTracker: createNoopIdleTracker(),\n\t};\n}\n","/**\n * Daemon entry point. Invoked when pi-acp is launched with `--daemon`.\n *\n * Lifecycle:\n * 1. Acquire per-UID lockfile (refuses if another daemon alive).\n * 2. Remove stale socket file if any (left by a dead prior daemon).\n * 3. Construct DaemonContext shared singletons (Phase 1: stubs).\n * 4. Bind socket; accept loop spawns a per-connection serveAcp instance.\n * 5. SIGINT / SIGTERM → graceful shutdown.\n */\n\nimport { createServer, type Server, type Socket } from \"node:net\";\nimport { createDaemonContext, type DaemonContext } from \"@pi-acp/daemon/context\";\nimport {\n\tacquireLock,\n\tensureSocketParentDir,\n\treleaseLock,\n\tremoveStaleSocketIfAny,\n\tsocketPath,\n} from \"@pi-acp/daemon/socket\";\nimport { type ServeHandle, serveAcp } from \"@pi-acp/runtime/serve\";\n\ninterface Connection {\n\tsocket: Socket;\n\thandle: ServeHandle;\n}\n\nexport async function runDaemon(): Promise<void> {\n\tconst lockResult = acquireLock();\n\tif (!lockResult.ok) {\n\t\tprocess.stderr.write(\n\t\t\t`pi-acp daemon: already running (pid ${lockResult.heldByPid ?? \"unknown\"})\\n`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tensureSocketParentDir();\n\tremoveStaleSocketIfAny();\n\n\tconst ctx: DaemonContext = createDaemonContext();\n\tconst connections = new Set<Connection>();\n\tlet shuttingDown = false;\n\n\tconst server: Server = createServer((socket) => {\n\t\tif (shuttingDown) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tconst handle = serveAcp({ input: socket, output: socket, daemonContext: ctx });\n\t\tconst entry: Connection = { socket, handle };\n\t\tconnections.add(entry);\n\t\tctx.idleTracker.bump(1);\n\n\t\tconst cleanup = (): void => {\n\t\t\tif (!connections.delete(entry)) return;\n\t\t\ttry {\n\t\t\t\thandle.dispose();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t\tctx.idleTracker.bump(-1);\n\t\t};\n\n\t\tsocket.on(\"close\", cleanup);\n\t\tsocket.on(\"error\", cleanup);\n\t});\n\n\tserver.on(\"error\", (err) => {\n\t\tprocess.stderr.write(`pi-acp daemon: server error: ${err.message}\\n`);\n\t});\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst path = socketPath();\n\t\tserver.listen(path, () => resolve());\n\t\tserver.once(\"error\", reject);\n\t});\n\n\tif (process.env[\"PI_ACP_DAEMON_DEBUG\"] === \"1\") {\n\t\tprocess.stderr.write(`pi-acp daemon: listening on ${socketPath()} (pid ${process.pid})\\n`);\n\t}\n\n\tconst shutdown = async (): Promise<void> => {\n\t\tif (shuttingDown) return;\n\t\tshuttingDown = true;\n\t\tserver.close();\n\t\tfor (const entry of connections) {\n\t\t\ttry {\n\t\t\t\tentry.handle.dispose();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tentry.socket.destroy();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tconnections.clear();\n\t\tctx.idleTracker.dispose();\n\t\tremoveStaleSocketIfAny();\n\t\treleaseLock();\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown();\n\t});\n}\n"],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { t as serveAcp } from "./serve-DLukbpF4.mjs";
|
|
3
|
-
//#region src/runtime/in-process.ts
|
|
4
|
-
/**
|
|
5
|
-
* In-process ACP server. The v0.5 codepath, preserved as the `PI_ACP_NO_DAEMON`
|
|
6
|
-
* escape hatch and reused by the daemon's own stdio-bridge fallback.
|
|
7
|
-
*
|
|
8
|
-
* Treats process.stdin/stdout as the ACP transport. Owns the shutdown
|
|
9
|
-
* lifecycle (AgentSideConnection.closed + SIGINT/SIGTERM).
|
|
10
|
-
*/
|
|
11
|
-
function runInProcess() {
|
|
12
|
-
const handle = serveAcp({
|
|
13
|
-
input: process.stdin,
|
|
14
|
-
output: process.stdout
|
|
15
|
-
});
|
|
16
|
-
let shuttingDown = false;
|
|
17
|
-
const shutdown = () => {
|
|
18
|
-
if (shuttingDown) return;
|
|
19
|
-
shuttingDown = true;
|
|
20
|
-
handle.dispose();
|
|
21
|
-
process.exit(0);
|
|
22
|
-
};
|
|
23
|
-
handle.connection.closed.then(shutdown);
|
|
24
|
-
process.on("SIGINT", shutdown);
|
|
25
|
-
process.on("SIGTERM", shutdown);
|
|
26
|
-
process.stdout.on("error", () => process.exit(0));
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
|
-
export { runInProcess };
|
|
30
|
-
|
|
31
|
-
//# sourceMappingURL=in-process-DcAV6Sgx.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"in-process-DcAV6Sgx.mjs","names":[],"sources":["../src/runtime/in-process.ts"],"sourcesContent":["/**\n * In-process ACP server. The v0.5 codepath, preserved as the `PI_ACP_NO_DAEMON`\n * escape hatch and reused by the daemon's own stdio-bridge fallback.\n *\n * Treats process.stdin/stdout as the ACP transport. Owns the shutdown\n * lifecycle (AgentSideConnection.closed + SIGINT/SIGTERM).\n */\n\nimport { serveAcp } from \"@pi-acp/runtime/serve\";\n\nexport function runInProcess(): void {\n\tconst handle = serveAcp({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t\t// No DaemonContext: behavior identical to v0.5.\n\t});\n\n\tlet shuttingDown = false;\n\tconst shutdown = (): void => {\n\t\tif (shuttingDown) return;\n\t\tshuttingDown = true;\n\t\thandle.dispose();\n\t\tprocess.exit(0);\n\t};\n\n\tvoid handle.connection.closed.then(shutdown);\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n\tprocess.stdout.on(\"error\", () => process.exit(0));\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,eAAqB;CACpC,MAAM,SAAS,SAAS;EACvB,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAEhB,CAAC;CAEF,IAAI,eAAe;CACnB,MAAM,iBAAuB;AAC5B,MAAI,aAAc;AAClB,iBAAe;AACf,SAAO,SAAS;AAChB,UAAQ,KAAK,EAAE;;AAGX,QAAO,WAAW,OAAO,KAAK,SAAS;AAE5C,SAAQ,GAAG,UAAU,SAAS;AAC9B,SAAQ,GAAG,WAAW,SAAS;AAC/B,SAAQ,OAAO,GAAG,eAAe,QAAQ,KAAK,EAAE,CAAC"}
|