@shield-agent/kya 0.1.36 → 0.1.38
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/.mcp.json +1 -1
- package/README.md +15 -5
- package/amp/README.md +1 -1
- package/amp/settings.example.json +1 -1
- package/claude/claude_desktop_config.example.json +1 -1
- package/cline/cline_mcp_settings.example.json +1 -1
- package/copilot/mcp-config.example.json +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +37 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/connect.d.ts +2 -0
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +7 -1
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/receipt-serve.d.ts +11 -0
- package/dist/commands/receipt-serve.d.ts.map +1 -0
- package/dist/commands/receipt-serve.js +23 -0
- package/dist/commands/receipt-serve.js.map +1 -0
- package/dist/commands/receipt.d.ts +6 -3
- package/dist/commands/receipt.d.ts.map +1 -1
- package/dist/commands/receipt.js +10 -11
- package/dist/commands/receipt.js.map +1 -1
- package/dist/commands/start.d.ts +3 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +27 -9
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/stop.d.ts +7 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +31 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/host-reload.d.ts +19 -0
- package/dist/host-reload.d.ts.map +1 -0
- package/dist/host-reload.js +155 -0
- package/dist/host-reload.js.map +1 -0
- package/dist/node-upgrade.d.ts +30 -0
- package/dist/node-upgrade.d.ts.map +1 -0
- package/dist/node-upgrade.js +140 -0
- package/dist/node-upgrade.js.map +1 -0
- package/dist/receipt/daemon.d.ts +29 -0
- package/dist/receipt/daemon.d.ts.map +1 -0
- package/dist/receipt/daemon.js +107 -0
- package/dist/receipt/daemon.js.map +1 -0
- package/droid/README.md +1 -1
- package/droid/mcp.example.json +1 -1
- package/gemini/settings.example.json +1 -1
- package/grok/README.md +1 -1
- package/kilo/kilo.example.json +1 -1
- package/kimi/mcp.example.json +1 -1
- package/kiro/mcp.example.json +1 -1
- package/manifest.json +1 -1
- package/mastracode/mcp.example.json +1 -1
- package/mcp.json +1 -1
- package/openai/codex.config.example.toml +1 -1
- package/opencode/opencode.example.json +1 -1
- package/package.json +1 -1
- package/qwen/settings.example.json +1 -1
- package/server.json +2 -2
package/dist/commands/start.js
CHANGED
|
@@ -5,8 +5,10 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { runInit } from "./init.js";
|
|
8
|
-
import { runReceipt } from "./receipt.js";
|
|
8
|
+
import { openPath, runReceipt } from "./receipt.js";
|
|
9
|
+
import { ensureReceiptDaemon } from "../receipt/daemon.js";
|
|
9
10
|
import { appendTrail, defaultSessionId } from "../trail.js";
|
|
11
|
+
import { hostReload, hostRunning, listProcessNames, reloadMessage } from "../host-reload.js";
|
|
10
12
|
function cliJsPath() {
|
|
11
13
|
// start.ts → ../cli.js in dist; when running from dist/commands/start.js
|
|
12
14
|
return fileURLToPath(new URL("../cli.js", import.meta.url));
|
|
@@ -82,21 +84,37 @@ export async function runStart(config, input = {}) {
|
|
|
82
84
|
}
|
|
83
85
|
seedTrailIfEmpty(config.cwd);
|
|
84
86
|
let liveUrl;
|
|
85
|
-
let
|
|
87
|
+
let reportPid;
|
|
88
|
+
let reportReused;
|
|
86
89
|
if (open) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
// Static artifacts first, then the live report as a detached background
|
|
91
|
+
// server so the user gets their terminal back.
|
|
92
|
+
await runReceipt(config, { open: false, days: 3 });
|
|
93
|
+
const daemon = await ensureReceiptDaemon(config, { days: 3 });
|
|
94
|
+
liveUrl = daemon.url;
|
|
95
|
+
reportPid = daemon.pid;
|
|
96
|
+
reportReused = daemon.reused;
|
|
97
|
+
openPath(daemon.url);
|
|
90
98
|
}
|
|
99
|
+
// start wires the configs Claude Code (.mcp.json / mcp.json) and Cursor
|
|
100
|
+
// (.cursor/mcp.json) read — the reload note is per-host, not a blanket
|
|
101
|
+
// "restart everything".
|
|
102
|
+
const procs = input.procs ?? listProcessNames();
|
|
103
|
+
const hostNotes = ["cursor", "claude"]
|
|
104
|
+
.map((id) => hostReload(id))
|
|
105
|
+
.filter((info) => Boolean(info))
|
|
106
|
+
.map((info) => reloadMessage(info, info.id === "claude" ? "Claude Code" : "Cursor", hostRunning(info, procs)))
|
|
107
|
+
.join(" ");
|
|
91
108
|
return {
|
|
92
109
|
initCreated: init.created,
|
|
93
110
|
wired,
|
|
94
111
|
skipped,
|
|
95
112
|
liveUrl,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"
|
|
113
|
+
reportPid,
|
|
114
|
+
reportReused,
|
|
115
|
+
next: `${hostNotes} ` +
|
|
116
|
+
"The report runs in the background — reopen with `kya receipt --open`, " +
|
|
117
|
+
"stop with `kya stop`.",
|
|
100
118
|
};
|
|
101
119
|
}
|
|
102
120
|
export function formatStartHuman(r) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAe9D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAIrD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kya stop` — stop the background live-receipt server started by `kya start`.
|
|
3
|
+
*/
|
|
4
|
+
import { clearDaemonState, pidAlive, readDaemonState, } from "../receipt/daemon.js";
|
|
5
|
+
function sleep(ms) {
|
|
6
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7
|
+
}
|
|
8
|
+
export async function runStop(cwd) {
|
|
9
|
+
const state = readDaemonState(cwd);
|
|
10
|
+
if (!state)
|
|
11
|
+
return { stopped: false };
|
|
12
|
+
if (pidAlive(state.pid)) {
|
|
13
|
+
try {
|
|
14
|
+
process.kill(state.pid, "SIGTERM");
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
/* raced exit */
|
|
18
|
+
}
|
|
19
|
+
for (let waited = 0; waited < 3_000 && pidAlive(state.pid); waited += 100) {
|
|
20
|
+
await sleep(100);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
clearDaemonState(cwd);
|
|
24
|
+
return { stopped: true, pid: state.pid };
|
|
25
|
+
}
|
|
26
|
+
export function formatStopHuman(r) {
|
|
27
|
+
return r.stopped
|
|
28
|
+
? `stopped report server (pid ${r.pid})`
|
|
29
|
+
: "no report server running";
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAO9B,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACtC,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;QACD,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,GAAG,EAAE,CAAC;YAC1E,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,CAAa;IAC3C,OAAO,CAAC,CAAC,OAAO;QACd,CAAC,CAAC,8BAA8B,CAAC,CAAC,GAAG,GAAG;QACxC,CAAC,CAAC,0BAA0B,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ReloadClass = "auto" | "session" | "restart";
|
|
2
|
+
export interface HostReload {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly reload: ReloadClass;
|
|
5
|
+
/** One-line mechanism note, shown verbatim to users. */
|
|
6
|
+
readonly detail: string;
|
|
7
|
+
/** Process-name fragments (basename, lowercase) for running detection. */
|
|
8
|
+
readonly processNames: readonly string[];
|
|
9
|
+
/** Context-preserving relaunch tip, when the host has one. */
|
|
10
|
+
readonly resumeTip?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const HOST_RELOAD: Readonly<Record<string, HostReload>>;
|
|
13
|
+
export declare function hostReload(id: string): HostReload | undefined;
|
|
14
|
+
/** Basenames of running processes (lowercase). POSIX ps; empty on failure. */
|
|
15
|
+
export declare function listProcessNames(platform?: NodeJS.Platform): ReadonlySet<string>;
|
|
16
|
+
export declare function hostRunning(info: HostReload, procs: ReadonlySet<string>): boolean;
|
|
17
|
+
/** Human next-step line for a just-wired host, accurate about restarts. */
|
|
18
|
+
export declare function reloadMessage(info: HostReload, label: string, running: boolean): string;
|
|
19
|
+
//# sourceMappingURL=host-reload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-reload.d.ts","sourceRoot":"","sources":["../src/host-reload.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CA4F5D,CAAC;AAEF,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE7D;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,WAAW,CAAC,MAAM,CAAC,CA2BlG;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAEjF;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAavF"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-host MCP reload behavior — researched against official docs, 2026-09.
|
|
3
|
+
* The blanket "restart your host" instruction was wrong for most hosts: many
|
|
4
|
+
* watch their config file (or offer an in-session reload) and pick up a new
|
|
5
|
+
* server with no restart at all. Messaging in `connect` / `start` is built
|
|
6
|
+
* from this table, and docs/hosts/<id>.md pages mirror it.
|
|
7
|
+
*
|
|
8
|
+
* Classes:
|
|
9
|
+
* auto — new server is picked up in the running host (file watcher or
|
|
10
|
+
* in-session refresh; detail says which)
|
|
11
|
+
* session — loads in the next session/conversation; app stays open
|
|
12
|
+
* restart — process must be relaunched (resumeTip preserves context if any)
|
|
13
|
+
*/
|
|
14
|
+
import { execFileSync } from "node:child_process";
|
|
15
|
+
export const HOST_RELOAD = {
|
|
16
|
+
cursor: {
|
|
17
|
+
id: "cursor",
|
|
18
|
+
reload: "auto",
|
|
19
|
+
detail: "Cursor watches mcp.json and starts new stdio servers on its own",
|
|
20
|
+
processNames: ["cursor", "cursor-agent"],
|
|
21
|
+
},
|
|
22
|
+
kiro: {
|
|
23
|
+
id: "kiro",
|
|
24
|
+
reload: "auto",
|
|
25
|
+
detail: "Kiro hot-reloads mcp.json on save — only the new server starts",
|
|
26
|
+
processNames: ["kiro", "kiro-cli"],
|
|
27
|
+
},
|
|
28
|
+
qwen: {
|
|
29
|
+
id: "qwen",
|
|
30
|
+
reload: "auto",
|
|
31
|
+
detail: "Qwen Code live-reconciles MCP servers when settings.json changes",
|
|
32
|
+
processNames: ["qwen"],
|
|
33
|
+
},
|
|
34
|
+
amp: {
|
|
35
|
+
id: "amp",
|
|
36
|
+
reload: "auto",
|
|
37
|
+
detail: "Amp applies settings.json changes live (workspace entries need one approval)",
|
|
38
|
+
processNames: ["amp"],
|
|
39
|
+
},
|
|
40
|
+
droid: {
|
|
41
|
+
id: "droid",
|
|
42
|
+
reload: "auto",
|
|
43
|
+
detail: "Droid reloads automatically when mcp.json changes",
|
|
44
|
+
processNames: ["droid"],
|
|
45
|
+
},
|
|
46
|
+
cline: {
|
|
47
|
+
id: "cline",
|
|
48
|
+
reload: "auto",
|
|
49
|
+
detail: "Cline watches cline_mcp_settings.json and connects new servers on save",
|
|
50
|
+
processNames: ["code", "code-insiders"],
|
|
51
|
+
},
|
|
52
|
+
grok: {
|
|
53
|
+
id: "grok",
|
|
54
|
+
reload: "auto",
|
|
55
|
+
detail: "in a running Grok session press r in /mcps to refresh after config edits",
|
|
56
|
+
processNames: ["grok"],
|
|
57
|
+
},
|
|
58
|
+
mastracode: {
|
|
59
|
+
id: "mastracode",
|
|
60
|
+
reload: "auto",
|
|
61
|
+
detail: "in a running MastraCode session run /mcp to reload connections",
|
|
62
|
+
processNames: ["mastracode"],
|
|
63
|
+
},
|
|
64
|
+
kimi: {
|
|
65
|
+
id: "kimi",
|
|
66
|
+
reload: "session",
|
|
67
|
+
detail: "Kimi Code registers MCP servers at session start — a new session is enough",
|
|
68
|
+
processNames: ["kimi"],
|
|
69
|
+
},
|
|
70
|
+
claude: {
|
|
71
|
+
id: "claude",
|
|
72
|
+
reload: "restart",
|
|
73
|
+
detail: "Claude Code loads MCP servers at process start",
|
|
74
|
+
processNames: ["claude"],
|
|
75
|
+
resumeTip: "claude --resume keeps the conversation",
|
|
76
|
+
},
|
|
77
|
+
codex: {
|
|
78
|
+
id: "codex",
|
|
79
|
+
reload: "restart",
|
|
80
|
+
detail: "Codex loads MCP servers at process start",
|
|
81
|
+
processNames: ["codex"],
|
|
82
|
+
},
|
|
83
|
+
gemini: {
|
|
84
|
+
id: "gemini",
|
|
85
|
+
reload: "restart",
|
|
86
|
+
detail: "Gemini CLI reads mcpServers once at startup (marked requiresRestart)",
|
|
87
|
+
processNames: ["gemini"],
|
|
88
|
+
},
|
|
89
|
+
copilot: {
|
|
90
|
+
id: "copilot",
|
|
91
|
+
reload: "restart",
|
|
92
|
+
detail: "Copilot CLI loads MCP servers at startup",
|
|
93
|
+
processNames: ["copilot"],
|
|
94
|
+
},
|
|
95
|
+
opencode: {
|
|
96
|
+
id: "opencode",
|
|
97
|
+
reload: "restart",
|
|
98
|
+
detail: "OpenCode connects MCP servers once at startup (hot-reload lands in v2)",
|
|
99
|
+
processNames: ["opencode"],
|
|
100
|
+
},
|
|
101
|
+
kilo: {
|
|
102
|
+
id: "kilo",
|
|
103
|
+
reload: "restart",
|
|
104
|
+
detail: "Kilo Code CLI reads kilo.json at startup (the VS Code extension hot-reloads instead)",
|
|
105
|
+
processNames: ["kilo"],
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
export function hostReload(id) {
|
|
109
|
+
return HOST_RELOAD[id];
|
|
110
|
+
}
|
|
111
|
+
/** Basenames of running processes (lowercase). POSIX ps; empty on failure. */
|
|
112
|
+
export function listProcessNames(platform = process.platform) {
|
|
113
|
+
try {
|
|
114
|
+
if (platform === "win32") {
|
|
115
|
+
const out = execFileSync("tasklist", ["/fo", "csv", "/nh"], {
|
|
116
|
+
encoding: "utf8",
|
|
117
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
118
|
+
});
|
|
119
|
+
return new Set(out
|
|
120
|
+
.split("\n")
|
|
121
|
+
.map((line) => line.split('","')[0]?.replace(/^"|"$/g, "").toLowerCase())
|
|
122
|
+
.filter((name) => Boolean(name)));
|
|
123
|
+
}
|
|
124
|
+
const out = execFileSync("ps", ["-axo", "comm="], {
|
|
125
|
+
encoding: "utf8",
|
|
126
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
127
|
+
});
|
|
128
|
+
return new Set(out
|
|
129
|
+
.split("\n")
|
|
130
|
+
.map((line) => line.trim().split("/").pop()?.toLowerCase())
|
|
131
|
+
.filter((name) => Boolean(name)));
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return new Set();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export function hostRunning(info, procs) {
|
|
138
|
+
return info.processNames.some((name) => procs.has(name));
|
|
139
|
+
}
|
|
140
|
+
/** Human next-step line for a just-wired host, accurate about restarts. */
|
|
141
|
+
export function reloadMessage(info, label, running) {
|
|
142
|
+
switch (info.reload) {
|
|
143
|
+
case "auto":
|
|
144
|
+
return `No restart needed — ${info.detail}.`;
|
|
145
|
+
case "session":
|
|
146
|
+
return running
|
|
147
|
+
? `${label} is running — start a new session to load shield-kya (${info.detail}). No app restart.`
|
|
148
|
+
: `shield-kya loads in your next ${label} session — no restart needed.`;
|
|
149
|
+
case "restart":
|
|
150
|
+
return running
|
|
151
|
+
? `${label} is running — relaunch it to load shield-kya (${info.detail}${info.resumeTip ? `; ${info.resumeTip}` : ""}).`
|
|
152
|
+
: `shield-kya loads when you next start ${label} — it is not running, so nothing to restart.`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=host-reload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-reload.js","sourceRoot":"","sources":["../src/host-reload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAelD,MAAM,CAAC,MAAM,WAAW,GAAyC;IAC/D,MAAM,EAAE;QACN,EAAE,EAAE,QAAQ;QACZ,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,iEAAiE;QACzE,YAAY,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC;KACzC;IACD,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,gEAAgE;QACxE,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;KACnC;IACD,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,kEAAkE;QAC1E,YAAY,EAAE,CAAC,MAAM,CAAC;KACvB;IACD,GAAG,EAAE;QACH,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,8EAA8E;QACtF,YAAY,EAAE,CAAC,KAAK,CAAC;KACtB;IACD,KAAK,EAAE;QACL,EAAE,EAAE,OAAO;QACX,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,mDAAmD;QAC3D,YAAY,EAAE,CAAC,OAAO,CAAC;KACxB;IACD,KAAK,EAAE;QACL,EAAE,EAAE,OAAO;QACX,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,wEAAwE;QAChF,YAAY,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;KACxC;IACD,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,0EAA0E;QAClF,YAAY,EAAE,CAAC,MAAM,CAAC;KACvB;IACD,UAAU,EAAE;QACV,EAAE,EAAE,YAAY;QAChB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,gEAAgE;QACxE,YAAY,EAAE,CAAC,YAAY,CAAC;KAC7B;IACD,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,4EAA4E;QACpF,YAAY,EAAE,CAAC,MAAM,CAAC;KACvB;IACD,MAAM,EAAE;QACN,EAAE,EAAE,QAAQ;QACZ,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,gDAAgD;QACxD,YAAY,EAAE,CAAC,QAAQ,CAAC;QACxB,SAAS,EAAE,wCAAwC;KACpD;IACD,KAAK,EAAE;QACL,EAAE,EAAE,OAAO;QACX,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,0CAA0C;QAClD,YAAY,EAAE,CAAC,OAAO,CAAC;KACxB;IACD,MAAM,EAAE;QACN,EAAE,EAAE,QAAQ;QACZ,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,sEAAsE;QAC9E,YAAY,EAAE,CAAC,QAAQ,CAAC;KACzB;IACD,OAAO,EAAE;QACP,EAAE,EAAE,SAAS;QACb,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,0CAA0C;QAClD,YAAY,EAAE,CAAC,SAAS,CAAC;KAC1B;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,UAAU;QACd,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,wEAAwE;QAChF,YAAY,EAAE,CAAC,UAAU,CAAC;KAC3B;IACD,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,sFAAsF;QAC9F,YAAY,EAAE,CAAC,MAAM,CAAC;KACvB;CACF,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,WAA4B,OAAO,CAAC,QAAQ;IAC3E,IAAI,CAAC;QACH,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE;gBAC1D,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;aACpC,CAAC,CAAC;YACH,OAAO,IAAI,GAAG,CACZ,GAAG;iBACA,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;iBACxE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CACnD,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;YAChD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,OAAO,IAAI,GAAG,CACZ,GAAG;aACA,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;aAC1D,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CACnD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAgB,EAAE,KAA0B;IACtE,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,KAAa,EAAE,OAAgB;IAC7E,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,uBAAuB,IAAI,CAAC,MAAM,GAAG,CAAC;QAC/C,KAAK,SAAS;YACZ,OAAO,OAAO;gBACZ,CAAC,CAAC,GAAG,KAAK,yDAAyD,IAAI,CAAC,MAAM,oBAAoB;gBAClG,CAAC,CAAC,iCAAiC,KAAK,+BAA+B,CAAC;QAC5E,KAAK,SAAS;YACZ,OAAO,OAAO;gBACZ,CAAC,CAAC,GAAG,KAAK,iDAAiD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI;gBACxH,CAAC,CAAC,wCAAwC,KAAK,8CAA8C,CAAC;IACpG,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const REQUIRED_NODE_MAJOR = 24;
|
|
2
|
+
export type NodeManager = "volta" | "fnm" | "nvm" | "brew";
|
|
3
|
+
export interface NodeGateDeps {
|
|
4
|
+
readonly version?: string;
|
|
5
|
+
readonly platform?: NodeJS.Platform;
|
|
6
|
+
readonly hasCmd?: (cmd: string) => boolean;
|
|
7
|
+
readonly hasFile?: (path: string) => boolean;
|
|
8
|
+
readonly run?: (shell: string, args: readonly string[]) => Promise<number>;
|
|
9
|
+
}
|
|
10
|
+
export declare function currentNodeMajor(version?: string): number;
|
|
11
|
+
export declare function nodeSatisfied(version?: string): boolean;
|
|
12
|
+
/** Priority: dedicated managers first, brew last (shared global prefix). */
|
|
13
|
+
export declare function detectNodeManager(env: NodeJS.ProcessEnv, deps?: NodeGateDeps): NodeManager | undefined;
|
|
14
|
+
/** Shell script that installs Node 24, reinstalls the CLI, and re-runs argv. */
|
|
15
|
+
export declare function buildUpgradeScript(manager: NodeManager, env: NodeJS.ProcessEnv, argv: readonly string[]): {
|
|
16
|
+
shell: string;
|
|
17
|
+
args: readonly string[];
|
|
18
|
+
};
|
|
19
|
+
export interface NodeGateIo {
|
|
20
|
+
readonly error: (msg: string) => void;
|
|
21
|
+
readonly isTty?: boolean;
|
|
22
|
+
readonly confirm?: (question: string) => Promise<boolean>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns an exit code when the upgrade ran and the original command was
|
|
26
|
+
* handed off to the new Node; undefined when the current process should
|
|
27
|
+
* continue normally.
|
|
28
|
+
*/
|
|
29
|
+
export declare function ensureSupportedNode(io: NodeGateIo, env: NodeJS.ProcessEnv, argv: readonly string[], command: string | undefined, deps?: NodeGateDeps): Promise<number | undefined>;
|
|
30
|
+
//# sourceMappingURL=node-upgrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-upgrade.d.ts","sourceRoot":"","sources":["../src/node-upgrade.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5E;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,MAAwB,GAAG,MAAM,CAG1E;AAED,wBAAgB,aAAa,CAAC,OAAO,GAAE,MAAwB,GAAG,OAAO,CAExE;AAkBD,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,GAAE,YAAiB,GACtB,WAAW,GAAG,SAAS,CASzB;AASD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CA8B5C;AAoBD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAID;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,UAAU,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4B7B"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node version gate with a guided upgrade. The package declares
|
|
3
|
+
* `engines.node: >=24`; on an older runtime the CLI warns, and on a TTY it
|
|
4
|
+
* offers to install Node 24 via the detected version manager, reinstall the
|
|
5
|
+
* global package under it, and re-run the original command. Declining (or a
|
|
6
|
+
* non-TTY run) continues with a warning — the gate never blocks outright.
|
|
7
|
+
*
|
|
8
|
+
* Escape hatches: KYA_SKIP_NODE_CHECK=1 skips entirely; KYA_NODE_CHECKED=1 is
|
|
9
|
+
* set by the upgrade re-exec and by the receipt daemon child so the check
|
|
10
|
+
* never loops.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { spawn } from "node:child_process";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { createInterface } from "node:readline";
|
|
16
|
+
export const REQUIRED_NODE_MAJOR = 24;
|
|
17
|
+
export function currentNodeMajor(version = process.version) {
|
|
18
|
+
const match = /^v?(\d+)/.exec(version);
|
|
19
|
+
return match ? Number.parseInt(match[1], 10) : 0;
|
|
20
|
+
}
|
|
21
|
+
export function nodeSatisfied(version = process.version) {
|
|
22
|
+
return currentNodeMajor(version) >= REQUIRED_NODE_MAJOR;
|
|
23
|
+
}
|
|
24
|
+
function defaultHasCmd(cmd) {
|
|
25
|
+
const pathEnv = process.env.PATH ?? "";
|
|
26
|
+
const exts = process.platform === "win32" ? [".cmd", ".exe", ".bat", ""] : [""];
|
|
27
|
+
for (const dir of pathEnv.split(process.platform === "win32" ? ";" : ":")) {
|
|
28
|
+
if (!dir)
|
|
29
|
+
continue;
|
|
30
|
+
for (const ext of exts) {
|
|
31
|
+
if (existsSync(join(dir, cmd + ext)))
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
function nvmScriptPath(env) {
|
|
38
|
+
return join(env.NVM_DIR ?? join(env.HOME ?? "", ".nvm"), "nvm.sh");
|
|
39
|
+
}
|
|
40
|
+
/** Priority: dedicated managers first, brew last (shared global prefix). */
|
|
41
|
+
export function detectNodeManager(env, deps = {}) {
|
|
42
|
+
const hasCmd = deps.hasCmd ?? defaultHasCmd;
|
|
43
|
+
const hasFile = deps.hasFile ?? existsSync;
|
|
44
|
+
const platform = deps.platform ?? process.platform;
|
|
45
|
+
if (hasCmd("volta"))
|
|
46
|
+
return "volta";
|
|
47
|
+
if (hasCmd("fnm"))
|
|
48
|
+
return "fnm";
|
|
49
|
+
if (platform !== "win32" && hasFile(nvmScriptPath(env)))
|
|
50
|
+
return "nvm";
|
|
51
|
+
if (platform !== "win32" && hasCmd("brew"))
|
|
52
|
+
return "brew";
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
function rerunTail(argv) {
|
|
56
|
+
// --force on start so MCP blocks are rewritten to the new node's execPath.
|
|
57
|
+
const needsForce = argv[0] === "start" && !argv.includes("--force");
|
|
58
|
+
const args = [...argv, ...(needsForce ? ["--force"] : [])];
|
|
59
|
+
return `npm i -g @shield-agent/kya@latest && KYA_NODE_CHECKED=1 kya ${args.join(" ")}`;
|
|
60
|
+
}
|
|
61
|
+
/** Shell script that installs Node 24, reinstalls the CLI, and re-runs argv. */
|
|
62
|
+
export function buildUpgradeScript(manager, env, argv) {
|
|
63
|
+
const tail = rerunTail(argv);
|
|
64
|
+
const platform = process.platform;
|
|
65
|
+
if (platform === "win32") {
|
|
66
|
+
// Only volta/fnm are supported on Windows; && chaining works in cmd.
|
|
67
|
+
const install = manager === "volta" ? "volta install node@24" : "fnm install 24 && fnm default 24";
|
|
68
|
+
return { shell: "cmd", args: ["/c", `${install} && ${tail}`] };
|
|
69
|
+
}
|
|
70
|
+
const lines = ["set -e"];
|
|
71
|
+
switch (manager) {
|
|
72
|
+
case "volta":
|
|
73
|
+
lines.push("volta install node@24");
|
|
74
|
+
break;
|
|
75
|
+
case "fnm":
|
|
76
|
+
lines.push("fnm install 24", "fnm default 24", 'eval "$(fnm env --shell bash)"');
|
|
77
|
+
break;
|
|
78
|
+
case "nvm":
|
|
79
|
+
lines.push(`export NVM_DIR="${env.NVM_DIR ?? "$HOME/.nvm"}"`, '. "$NVM_DIR/nvm.sh"', "nvm install 24", "nvm alias default 24");
|
|
80
|
+
break;
|
|
81
|
+
case "brew":
|
|
82
|
+
lines.push("brew install node || brew upgrade node");
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
lines.push(tail);
|
|
86
|
+
return { shell: "bash", args: ["-c", lines.join("\n")] };
|
|
87
|
+
}
|
|
88
|
+
async function defaultRun(shell, args) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const child = spawn(shell, [...args], { stdio: "inherit" });
|
|
91
|
+
child.on("error", reject);
|
|
92
|
+
child.on("close", (code) => resolve(code ?? 1));
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function defaultConfirm(question) {
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
98
|
+
rl.question(`${question} `, (answer) => {
|
|
99
|
+
rl.close();
|
|
100
|
+
resolve(!/^n(o)?$/i.test(answer.trim()));
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const SKIP_COMMANDS = new Set(["help", "serve-mcp", "receipt-serve"]);
|
|
105
|
+
/**
|
|
106
|
+
* Returns an exit code when the upgrade ran and the original command was
|
|
107
|
+
* handed off to the new Node; undefined when the current process should
|
|
108
|
+
* continue normally.
|
|
109
|
+
*/
|
|
110
|
+
export async function ensureSupportedNode(io, env, argv, command, deps = {}) {
|
|
111
|
+
if (!command || SKIP_COMMANDS.has(command))
|
|
112
|
+
return undefined;
|
|
113
|
+
if (env.KYA_SKIP_NODE_CHECK === "1" || env.KYA_NODE_CHECKED === "1")
|
|
114
|
+
return undefined;
|
|
115
|
+
const version = deps.version ?? process.version;
|
|
116
|
+
if (nodeSatisfied(version))
|
|
117
|
+
return undefined;
|
|
118
|
+
const warn = `KYA needs Node.js ${REQUIRED_NODE_MAJOR}+ (you have ${version}).`;
|
|
119
|
+
const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
120
|
+
const confirm = io.confirm ?? defaultConfirm;
|
|
121
|
+
if (!isTty) {
|
|
122
|
+
io.error(`${warn} Continuing anyway — some features may break.`);
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
const manager = detectNodeManager(env, deps);
|
|
126
|
+
const question = manager
|
|
127
|
+
? `${warn} Upgrade to Node 24 via ${manager} now and continue? [Y/n]`
|
|
128
|
+
: `${warn} No version manager found (nodejs.org/en/download). Continue anyway? [Y/n]`;
|
|
129
|
+
const ok = await confirm(question);
|
|
130
|
+
if (!ok) {
|
|
131
|
+
io.error("Continuing on an unsupported Node — some features may break.");
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
if (!manager)
|
|
135
|
+
return undefined;
|
|
136
|
+
const script = buildUpgradeScript(manager, env, argv);
|
|
137
|
+
const run = deps.run ?? defaultRun;
|
|
138
|
+
return run(script.shell, script.args);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=node-upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-upgrade.js","sourceRoot":"","sources":["../src/node-upgrade.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ResolvedConfig } from "../config.js";
|
|
2
|
+
export interface ReceiptDaemonState {
|
|
3
|
+
readonly pid: number;
|
|
4
|
+
readonly url: string;
|
|
5
|
+
readonly token: string;
|
|
6
|
+
readonly port: number;
|
|
7
|
+
readonly startedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ReceiptDaemonHandle {
|
|
10
|
+
readonly url: string;
|
|
11
|
+
readonly pid: number;
|
|
12
|
+
readonly reused: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function daemonStatePath(cwd: string): string;
|
|
15
|
+
export declare function daemonLogPath(cwd: string): string;
|
|
16
|
+
export declare function readDaemonState(cwd: string): ReceiptDaemonState | undefined;
|
|
17
|
+
export declare function writeDaemonState(cwd: string, state: ReceiptDaemonState): void;
|
|
18
|
+
export declare function clearDaemonState(cwd: string): void;
|
|
19
|
+
export declare function pidAlive(pid: number): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Reuse the running daemon when its pid is alive; otherwise spawn a fresh
|
|
22
|
+
* detached one and wait for it to publish its state file.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ensureReceiptDaemon(config: ResolvedConfig, input: {
|
|
25
|
+
days: number;
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
env?: NodeJS.ProcessEnv;
|
|
28
|
+
}): Promise<ReceiptDaemonHandle>;
|
|
29
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/receipt/daemon.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAiB3E;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAM7E;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAS7C;AAWD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,GACnE,OAAO,CAAC,mBAAmB,CAAC,CAqC9B"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background live-receipt daemon: `kya start` spawns it detached and returns
|
|
3
|
+
* to the terminal. State (pid, url, token) lives in `.kya/receipt-server.json`
|
|
4
|
+
* (mode 0600 — it carries the loopback auth token); stdout/stderr go to
|
|
5
|
+
* `.kya/receipt-server.log`. The daemon child is the hidden `receipt-serve`
|
|
6
|
+
* command, which writes the state file once it is listening and removes it on
|
|
7
|
+
* shutdown.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { configDir } from "../config.js";
|
|
14
|
+
import { KyaError } from "../errors.js";
|
|
15
|
+
export function daemonStatePath(cwd) {
|
|
16
|
+
return join(configDir(cwd), "receipt-server.json");
|
|
17
|
+
}
|
|
18
|
+
export function daemonLogPath(cwd) {
|
|
19
|
+
return join(configDir(cwd), "receipt-server.log");
|
|
20
|
+
}
|
|
21
|
+
export function readDaemonState(cwd) {
|
|
22
|
+
const path = daemonStatePath(cwd);
|
|
23
|
+
if (!existsSync(path))
|
|
24
|
+
return undefined;
|
|
25
|
+
try {
|
|
26
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
27
|
+
if (typeof raw.pid === "number" &&
|
|
28
|
+
typeof raw.url === "string" &&
|
|
29
|
+
typeof raw.token === "string" &&
|
|
30
|
+
typeof raw.port === "number") {
|
|
31
|
+
return raw;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
/* corrupt state — treat as absent */
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
export function writeDaemonState(cwd, state) {
|
|
40
|
+
mkdirSync(configDir(cwd), { recursive: true });
|
|
41
|
+
writeFileSync(daemonStatePath(cwd), `${JSON.stringify(state, null, 2)}\n`, {
|
|
42
|
+
encoding: "utf8",
|
|
43
|
+
mode: 0o600,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function clearDaemonState(cwd) {
|
|
47
|
+
rmSync(daemonStatePath(cwd), { force: true });
|
|
48
|
+
}
|
|
49
|
+
export function pidAlive(pid) {
|
|
50
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
51
|
+
return false;
|
|
52
|
+
try {
|
|
53
|
+
process.kill(pid, 0);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// EPERM: process exists but owned by someone else — still alive.
|
|
58
|
+
return err.code === "EPERM";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function sleep(ms) {
|
|
62
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
63
|
+
}
|
|
64
|
+
function cliJsPath() {
|
|
65
|
+
// dist/receipt/daemon.js → dist/cli.js
|
|
66
|
+
return fileURLToPath(new URL("../cli.js", import.meta.url));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Reuse the running daemon when its pid is alive; otherwise spawn a fresh
|
|
70
|
+
* detached one and wait for it to publish its state file.
|
|
71
|
+
*/
|
|
72
|
+
export async function ensureReceiptDaemon(config, input) {
|
|
73
|
+
const existing = readDaemonState(config.cwd);
|
|
74
|
+
if (existing && pidAlive(existing.pid)) {
|
|
75
|
+
return { url: existing.url, pid: existing.pid, reused: true };
|
|
76
|
+
}
|
|
77
|
+
clearDaemonState(config.cwd);
|
|
78
|
+
mkdirSync(configDir(config.cwd), { recursive: true });
|
|
79
|
+
const logFd = openSync(daemonLogPath(config.cwd), "a");
|
|
80
|
+
const args = [cliJsPath(), "receipt-serve", "--days", String(input.days)];
|
|
81
|
+
if (input.sessionId)
|
|
82
|
+
args.push("--session", input.sessionId);
|
|
83
|
+
const child = spawn(process.execPath, args, {
|
|
84
|
+
cwd: config.cwd,
|
|
85
|
+
detached: true,
|
|
86
|
+
stdio: ["ignore", logFd, logFd],
|
|
87
|
+
env: {
|
|
88
|
+
...process.env,
|
|
89
|
+
...input.env,
|
|
90
|
+
KYA_NO_BROWSER: "1",
|
|
91
|
+
KYA_NODE_CHECKED: "1",
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
child.unref();
|
|
95
|
+
const pid = child.pid ?? -1;
|
|
96
|
+
for (let waited = 0; waited < 10_000; waited += 100) {
|
|
97
|
+
const state = readDaemonState(config.cwd);
|
|
98
|
+
if (state && state.pid === pid && pidAlive(pid)) {
|
|
99
|
+
return { url: state.url, pid, reused: false };
|
|
100
|
+
}
|
|
101
|
+
if (child.exitCode !== null)
|
|
102
|
+
break;
|
|
103
|
+
await sleep(100);
|
|
104
|
+
}
|
|
105
|
+
throw new KyaError(`receipt server failed to start — see ${daemonLogPath(config.cwd)}`, "RECEIPT_DAEMON_FAILED");
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=daemon.js.map
|