kojee-mcp 0.6.0 → 0.7.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/README.md +13 -8
- package/dist/ancestry-A2F5KQ6A.js +10 -0
- package/dist/cc-session-id-RURNIHHC.js +10 -0
- package/dist/{chunk-KH5YEJIM.js → chunk-247WFMCJ.js} +7 -20
- package/dist/{chunk-BYV7CWNY.js → chunk-5H75AEZ2.js} +22 -9
- package/dist/{chunk-YH27B6SW.js → chunk-5SZHXYPK.js} +16 -3
- package/dist/{chunk-DO42NPNR.js → chunk-67F67AQ6.js} +14 -3
- package/dist/{chunk-CH32ELFX.js → chunk-6G6YYST6.js} +1 -1
- package/dist/chunk-D6JKFJ6A.js +11 -0
- package/dist/chunk-E6WMFMM2.js +100 -0
- package/dist/chunk-EIAUW6KO.js +82 -0
- package/dist/chunk-EIH2LNF4.js +45 -0
- package/dist/{chunk-XN3IC4B5.js → chunk-FSKGQ6GT.js} +30 -5
- package/dist/{chunk-GI2CKKBL.js → chunk-GKXHKR3B.js} +1 -1
- package/dist/{setup-handler-7HOFAD7C.js → chunk-GVWYW7MY.js} +247 -246
- package/dist/{chunk-JXMVZEQ7.js → chunk-I67C2HYA.js} +1 -1
- package/dist/chunk-KNEJTD6G.js +31 -0
- package/dist/{chunk-NR4Y54OL.js → chunk-MIEI4PLB.js} +1 -19
- package/dist/chunk-NE2F5CKS.js +113 -0
- package/dist/{chunk-N35X22G7.js → chunk-OB5T6P24.js} +1 -1
- package/dist/{chunk-65KRRDHP.js → chunk-OBIJ6WQP.js} +82 -27
- package/dist/{chunk-Q7T3WAST.js → chunk-QEJUNP3X.js} +2 -1
- package/dist/chunk-QJFMU4QC.js +33 -0
- package/dist/{chunk-EW72ZNQL.js → chunk-RDLF4NQC.js} +1 -1
- package/dist/{chunk-ALZX3SGI.js → chunk-SGRVG4HW.js} +8 -3
- package/dist/{chunk-DURRQDYI.js → chunk-TNZITJAB.js} +45 -15
- package/dist/chunk-U5HHHRXA.js +103 -0
- package/dist/chunk-WBXU27BF.js +35 -0
- package/dist/chunk-WIU5WGDF.js +10 -0
- package/dist/chunk-XJEBJIQE.js +52 -0
- package/dist/chunk-Z5LPNJQ6.js +20 -0
- package/dist/cli.js +62 -25
- package/dist/{chunk-KFDZWNQO.js → codex-stop-hook-EOMQD3J4.js} +11 -15
- package/dist/connect-handler-HIRM624N.js +137 -0
- package/dist/{control-token-4BUCTYQB.js → control-token-KXSZ3GBY.js} +2 -2
- package/dist/{doctor-WVX3WCYX.js → doctor-PLKLHTJM.js} +48 -22
- package/dist/{doctor-codex-Z5M4SFBG.js → doctor-codex-HARAAH4Y.js} +23 -6
- package/dist/doctor-openclaw-LL6NSPLC.js +86 -0
- package/dist/{event-log-HOBO3ECB.js → event-log-2NBJEIEP.js} +5 -3
- package/dist/{event-stream-SYBUJ5EH.js → event-stream-KRYWEYWO.js} +7 -4
- package/dist/index.js +12 -10
- package/dist/{install-LJY2CHKG.js → install-V7LSQCYZ.js} +37 -22
- package/dist/{keystore-XLEV3FL5.js → keystore-LQNFDHGO.js} +2 -2
- package/dist/lib.d.ts +4 -1
- package/dist/lib.js +11 -8
- package/dist/pair-HTCVSMR6.js +11 -0
- package/dist/{paired-config-JTFLHMZ2.js → paired-config-GUDDO2CH.js} +4 -2
- package/dist/{parent-watchdog-TLU355FB.js → parent-watchdog-LTUNF7PD.js} +24 -5
- package/dist/{registry-YLOFZDI2.js → registry-VRFHKOPP.js} +193 -24
- package/dist/resolve-slot-BFIB46Y5.js +13 -0
- package/dist/{runtime-record-WO4IECM6.js → runtime-record-OXRLTOLC.js} +2 -2
- package/dist/{send-cli-IYJF32PE.js → send-cli-45RLGYIC.js} +22 -10
- package/dist/{server-R24AVNTI.js → server-YTHOMA4H.js} +4 -2
- package/dist/{session-discovery-FNMJGFPM.js → session-discovery-NHCZ2XWA.js} +2 -2
- package/dist/setup-handler-UHVKSX7E.js +159 -0
- package/dist/{stop-hook-TCPJFGFF.js → stop-hook-YI4KRKF2.js} +17 -20
- package/dist/{tail-stream-4IMXI44S.js → tail-stream-NBGHHBS4.js} +40 -22
- package/dist/{user-prompt-submit-hook-FQ43NIHC.js → user-prompt-submit-hook-DTXXFDSD.js} +11 -14
- package/package.json +1 -1
- package/dist/ancestry-ONFBQEP5.js +0 -8
- package/dist/chunk-BLEGIR35.js +0 -43
- package/dist/chunk-CLKCNV2A.js +0 -100
- package/dist/chunk-OGHDTFAX.js +0 -50
- package/dist/chunk-VHKPWUX7.js +0 -41
- package/dist/codex-stop-hook-RWQSZTST.js +0 -16
- package/dist/doctor-openclaw-SS2TMQOX.js +0 -95
- package/dist/pair-P4ILCMT7.js +0 -10
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
import "./chunk-XLKGPGZT.js";
|
|
2
|
+
import {
|
|
3
|
+
loadControlToken
|
|
4
|
+
} from "./chunk-GKXHKR3B.js";
|
|
2
5
|
import {
|
|
3
6
|
monitorHeartbeatPath,
|
|
4
7
|
statusLogPath
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TNZITJAB.js";
|
|
6
9
|
import {
|
|
7
10
|
discoveryPathForKey,
|
|
8
11
|
readSessionDiscoveryByKey,
|
|
9
12
|
sessionDiscoveryDir
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import {
|
|
12
|
-
loadControlToken
|
|
13
|
-
} from "./chunk-GI2CKKBL.js";
|
|
13
|
+
} from "./chunk-67F67AQ6.js";
|
|
14
14
|
import {
|
|
15
15
|
loadPairedConfig
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-5SZHXYPK.js";
|
|
17
|
+
import "./chunk-U5HHHRXA.js";
|
|
18
18
|
import {
|
|
19
19
|
buildMonitorSpawn,
|
|
20
20
|
buildReplyRecipe
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-QEJUNP3X.js";
|
|
22
22
|
import {
|
|
23
23
|
deriveDiscoveryKey,
|
|
24
24
|
findClaudeAncestorPid
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-XJEBJIQE.js";
|
|
26
|
+
import {
|
|
27
|
+
resolveSharedSessionId
|
|
28
|
+
} from "./chunk-KNEJTD6G.js";
|
|
26
29
|
|
|
27
30
|
// src/doctor.ts
|
|
28
31
|
import fs from "fs";
|
|
@@ -95,7 +98,8 @@ function defaultIsPidAlive(pid) {
|
|
|
95
98
|
process.kill(pid, 0);
|
|
96
99
|
return true;
|
|
97
100
|
} catch (err) {
|
|
98
|
-
|
|
101
|
+
const code = err.code;
|
|
102
|
+
if (code === "EPERM" || code === "EACCES") return true;
|
|
99
103
|
return false;
|
|
100
104
|
}
|
|
101
105
|
}
|
|
@@ -132,6 +136,19 @@ function defaultReadLastStatusLine(path2) {
|
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
}
|
|
139
|
+
async function resolveDefaultPairedScope() {
|
|
140
|
+
const { resolvePairedSlot } = await import("./resolve-slot-BFIB46Y5.js");
|
|
141
|
+
const { readRecordedRuntime } = await import("./runtime-record-OXRLTOLC.js");
|
|
142
|
+
const { deriveKeystorePath } = await import("./keystore-LQNFDHGO.js");
|
|
143
|
+
const runtime = readRecordedRuntime() ?? process.env["KOJEE_RUNTIME"];
|
|
144
|
+
const resolution = resolvePairedSlot({ ...runtime ? { runtime } : {} });
|
|
145
|
+
const cfg = loadPairedConfig(resolution.configPath);
|
|
146
|
+
let present = cfg !== null && typeof cfg.token === "string" && cfg.token !== "";
|
|
147
|
+
if (present && resolution.scope === "paired" && cfg) {
|
|
148
|
+
present = fs.existsSync(deriveKeystorePath(cfg.token));
|
|
149
|
+
}
|
|
150
|
+
return { scope: resolution.scope, present, ...runtime ? { runtime } : {} };
|
|
151
|
+
}
|
|
135
152
|
async function collectDoctorReport(deps = {}) {
|
|
136
153
|
const fetchFn = deps.fetchFn ?? fetch;
|
|
137
154
|
const isPidAlive = deps.isPidAlive ?? defaultIsPidAlive;
|
|
@@ -140,23 +157,32 @@ async function collectDoctorReport(deps = {}) {
|
|
|
140
157
|
const readDiscovery = deps.readDiscovery ?? readSessionDiscoveryByKey;
|
|
141
158
|
const projectDir = deps.projectDir ?? process.env["CLAUDE_PROJECT_DIR"];
|
|
142
159
|
const ccPid = deps.ccPid !== void 0 ? deps.ccPid : await findClaudeAncestorPid();
|
|
143
|
-
const
|
|
160
|
+
const sessionId = deps.sessionId !== void 0 ? deps.sessionId : resolveSharedSessionId();
|
|
161
|
+
const discoveryKey = deriveDiscoveryKey(projectDir, ccPid, sessionId);
|
|
144
162
|
const discoveryPath = discoveryPathForKey(discoveryKey);
|
|
145
163
|
const checks = [];
|
|
146
164
|
const discovery = readDiscovery(discoveryKey);
|
|
147
165
|
const tokenMode = discovery?.authMode === "token";
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
166
|
+
const pairedScope = deps.pairedScope ?? (deps.pairedConfigPresent !== void 0 ? { scope: "legacy", present: deps.pairedConfigPresent } : await resolveDefaultPairedScope());
|
|
167
|
+
if (tokenMode) {
|
|
168
|
+
checks.push({
|
|
151
169
|
name: "paired config",
|
|
152
170
|
ok: true,
|
|
153
171
|
detail: "n/a (token mode) \u2014 proxy launched with --token; no ~/.kojee/config.json by design"
|
|
154
|
-
}
|
|
172
|
+
});
|
|
173
|
+
} else if (pairedScope.scope === "paired") {
|
|
174
|
+
checks.push({
|
|
155
175
|
name: "paired config",
|
|
156
|
-
ok:
|
|
157
|
-
detail:
|
|
158
|
-
}
|
|
159
|
-
|
|
176
|
+
ok: pairedScope.present,
|
|
177
|
+
detail: pairedScope.present ? `present (per-runtime: ${pairedScope.runtime ?? "?"}) + token-derived keystore` : `MISSING per-runtime slot for ${pairedScope.runtime ?? "?"} \u2014 run \`kojee-mcp connect <code> --runtime ${pairedScope.runtime ?? "<id>"}\``
|
|
178
|
+
});
|
|
179
|
+
} else {
|
|
180
|
+
checks.push({
|
|
181
|
+
name: "paired config",
|
|
182
|
+
ok: pairedScope.present,
|
|
183
|
+
detail: pairedScope.present ? "present (legacy global slot)" : "MISSING \u2014 run `kojee-mcp connect <code> --runtime <id>` (or `kojee-mcp pair`)"
|
|
184
|
+
});
|
|
185
|
+
}
|
|
160
186
|
let logPath = null;
|
|
161
187
|
if (!discovery) {
|
|
162
188
|
checks.push({
|
|
@@ -326,15 +352,15 @@ function formatDoctorReport(report) {
|
|
|
326
352
|
return lines.join("\n");
|
|
327
353
|
}
|
|
328
354
|
async function runDoctor() {
|
|
329
|
-
const { readRecordedRuntime } = await import("./runtime-record-
|
|
355
|
+
const { readRecordedRuntime } = await import("./runtime-record-OXRLTOLC.js");
|
|
330
356
|
if (readRecordedRuntime() === "codex") {
|
|
331
|
-
const { collectCodexDoctorReport, formatCodexDoctorReport } = await import("./doctor-codex-
|
|
357
|
+
const { collectCodexDoctorReport, formatCodexDoctorReport } = await import("./doctor-codex-HARAAH4Y.js");
|
|
332
358
|
const report2 = collectCodexDoctorReport();
|
|
333
359
|
console.error(formatCodexDoctorReport(report2));
|
|
334
360
|
return report2.verdict === "broken" ? 1 : 0;
|
|
335
361
|
}
|
|
336
362
|
if (readRecordedRuntime() === "openclaw") {
|
|
337
|
-
const { collectOpenclawDoctorReport, formatOpenclawDoctorReport } = await import("./doctor-openclaw-
|
|
363
|
+
const { collectOpenclawDoctorReport, formatOpenclawDoctorReport } = await import("./doctor-openclaw-LL6NSPLC.js");
|
|
338
364
|
const report2 = collectOpenclawDoctorReport();
|
|
339
365
|
console.error(formatOpenclawDoctorReport(report2));
|
|
340
366
|
return report2.verdict === "broken" ? 1 : 0;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defaultCodexConfigPath,
|
|
3
3
|
defaultCodexHooksPath
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OBIJ6WQP.js";
|
|
5
|
+
import "./chunk-QJFMU4QC.js";
|
|
6
|
+
import "./chunk-D6JKFJ6A.js";
|
|
5
7
|
import "./chunk-SQL56SEB.js";
|
|
6
8
|
import {
|
|
7
9
|
resolveWebhookConfig
|
|
8
10
|
} from "./chunk-V5VZPYMZ.js";
|
|
9
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-U5HHHRXA.js";
|
|
10
12
|
import {
|
|
11
13
|
CODEX_LISTEN_CAP_MS
|
|
12
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-QEJUNP3X.js";
|
|
13
15
|
|
|
14
16
|
// src/doctor-codex.ts
|
|
15
17
|
import fs from "fs";
|
|
@@ -39,6 +41,10 @@ function parseCodexEnvFromToml(toml) {
|
|
|
39
41
|
return env;
|
|
40
42
|
}
|
|
41
43
|
var WIZARD_RERUN = "re-run `kojee-mcp init --runtime codex`";
|
|
44
|
+
function extractPairedConfigPath(toml) {
|
|
45
|
+
const m = toml.match(/args\s*=\s*\[[^\]]*"--paired-config"\s*,\s*"([^"]+)"/);
|
|
46
|
+
return m ? m[1].replace(/\\\\/g, "\\") : null;
|
|
47
|
+
}
|
|
42
48
|
function defaultReadFile(path) {
|
|
43
49
|
return () => {
|
|
44
50
|
try {
|
|
@@ -100,8 +106,17 @@ function collectCodexDoctorReport(deps = {}) {
|
|
|
100
106
|
} else {
|
|
101
107
|
checks.push({
|
|
102
108
|
name: "webhook sink",
|
|
103
|
-
ok:
|
|
104
|
-
detail:
|
|
109
|
+
ok: true,
|
|
110
|
+
detail: "optional \u2014 OFF (no KOJEE_WEBHOOK_URL). Codex wake is self-contained: the proxy refreshes the stop-hook pending marker on every event. Configure a receiver only for an extra low-latency push path."
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const pairedPath = extractPairedConfigPath(toml);
|
|
114
|
+
if (pairedPath) {
|
|
115
|
+
const present = fs.existsSync(pairedPath);
|
|
116
|
+
checks.push({
|
|
117
|
+
name: "paired-config slot",
|
|
118
|
+
ok: present,
|
|
119
|
+
detail: present ? `present \u2014 proxy launches with --paired-config ${pairedPath}` : `MISSING referenced config ${pairedPath} \u2014 re-run \`kojee-mcp connect <code> --runtime codex\``
|
|
105
120
|
});
|
|
106
121
|
}
|
|
107
122
|
if (deps.pingReceiver) {
|
|
@@ -120,7 +135,9 @@ function formatCodexDoctorReport(report) {
|
|
|
120
135
|
const lines = [];
|
|
121
136
|
lines.push(`kojee-mcp doctor (codex) \u2014 verdict: ${report.verdict.toUpperCase()}`);
|
|
122
137
|
lines.push("");
|
|
123
|
-
lines.push(
|
|
138
|
+
lines.push(
|
|
139
|
+
" Wake mode: self-contained (proxy-written pending marker) + stop-hook peek (Codex has no channel injection). Webhook OPTIONAL, never required."
|
|
140
|
+
);
|
|
124
141
|
lines.push(` Bounded-listen cap: ${CODEX_LISTEN_CAP_MS}ms (model picks listen vs drain vs ignore).`);
|
|
125
142
|
lines.push("");
|
|
126
143
|
for (const c of report.checks) {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MCP_SERVER_NAME,
|
|
3
|
+
defaultOpenclawConfigPath
|
|
4
|
+
} from "./chunk-E6WMFMM2.js";
|
|
5
|
+
import "./chunk-D6JKFJ6A.js";
|
|
6
|
+
import {
|
|
7
|
+
resolveOpenclawWakeTarget
|
|
8
|
+
} from "./chunk-NE2F5CKS.js";
|
|
9
|
+
import "./chunk-SQL56SEB.js";
|
|
10
|
+
import {
|
|
11
|
+
loadPairedConfig,
|
|
12
|
+
pairedConfigPath,
|
|
13
|
+
perRuntimeConfigPath
|
|
14
|
+
} from "./chunk-5SZHXYPK.js";
|
|
15
|
+
import "./chunk-U5HHHRXA.js";
|
|
16
|
+
|
|
17
|
+
// src/doctor-openclaw.ts
|
|
18
|
+
import fs from "fs";
|
|
19
|
+
var WIZARD_RERUN = "re-run `kojee-mcp connect <code> --runtime openclaw`";
|
|
20
|
+
function readOpenclawConfig() {
|
|
21
|
+
try {
|
|
22
|
+
const parsed = JSON.parse(fs.readFileSync(defaultOpenclawConfigPath(), "utf8"));
|
|
23
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
24
|
+
} catch {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function loadOpenclawPaired() {
|
|
29
|
+
const perRuntime = loadPairedConfig(perRuntimeConfigPath("openclaw"));
|
|
30
|
+
if (perRuntime?.token) return { config: perRuntime, source: "per-runtime" };
|
|
31
|
+
const global = loadPairedConfig(pairedConfigPath());
|
|
32
|
+
if (global?.token) return { config: global, source: "global" };
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function collectOpenclawDoctorReport(deps = {}) {
|
|
36
|
+
const readConfig = deps.readConfig ?? readOpenclawConfig;
|
|
37
|
+
const resolveWake = deps.resolveWake ?? (() => resolveOpenclawWakeTarget());
|
|
38
|
+
const loadPaired = deps.loadPaired ?? loadOpenclawPaired;
|
|
39
|
+
const checks = [];
|
|
40
|
+
const cfg = readConfig();
|
|
41
|
+
const mcp = cfg.mcp && typeof cfg.mcp === "object" ? cfg.mcp : {};
|
|
42
|
+
const servers = mcp.servers && typeof mcp.servers === "object" ? mcp.servers : {};
|
|
43
|
+
const server = servers[MCP_SERVER_NAME] && typeof servers[MCP_SERVER_NAME] === "object" ? servers[MCP_SERVER_NAME] : null;
|
|
44
|
+
const args = server && Array.isArray(server.args) ? server.args : [];
|
|
45
|
+
const pairedConfigThreaded = args.includes("--paired-config");
|
|
46
|
+
checks.push({
|
|
47
|
+
name: `~/.openclaw/openclaw.json mcp.servers.${MCP_SERVER_NAME}`,
|
|
48
|
+
ok: server !== null,
|
|
49
|
+
detail: server ? pairedConfigThreaded ? "present \u2014 OpenClaw spawns kojee-mcp with --paired-config (per-runtime slot)" : "present (WARN: no --paired-config in args \u2014 the proxy will use the global slot)" : `MISSING mcp.servers.${MCP_SERVER_NAME} block \u2014 ${WIZARD_RERUN}`
|
|
50
|
+
});
|
|
51
|
+
const wake = resolveWake();
|
|
52
|
+
checks.push({
|
|
53
|
+
name: "hooks wake receiver",
|
|
54
|
+
ok: wake.ok,
|
|
55
|
+
detail: wake.ok ? `mounted \u2014 /wake target: ${wake.target.url} (Bearer hooks.token; token value never printed)` : `${wake.reason} \u2014 ${WIZARD_RERUN}`
|
|
56
|
+
});
|
|
57
|
+
const paired = loadPaired();
|
|
58
|
+
checks.push({
|
|
59
|
+
name: "gateway credential",
|
|
60
|
+
ok: paired !== null,
|
|
61
|
+
detail: paired ? `resolves \u2014 source: ${paired.source} paired slot (token value never printed)` : `NONE resolves (no ~/.kojee/agents/openclaw/config.json or ~/.kojee/config.json token) \u2014 ${WIZARD_RERUN}`
|
|
62
|
+
});
|
|
63
|
+
const verdict = checks.some((c) => c.ok === false) ? "broken" : checks.some((c) => c.ok === "warn") ? "degraded" : "healthy";
|
|
64
|
+
return { checks, verdict };
|
|
65
|
+
}
|
|
66
|
+
function formatOpenclawDoctorReport(report) {
|
|
67
|
+
const mark = (ok) => ok === true ? "\u2713" : ok === "warn" ? "\u26A0" : ok === "unknown" ? "?" : "\u2717";
|
|
68
|
+
const lines = [];
|
|
69
|
+
lines.push(`kojee-mcp doctor (openclaw) \u2014 verdict: ${report.verdict.toUpperCase()}`);
|
|
70
|
+
lines.push("");
|
|
71
|
+
lines.push(" Wake mode: OpenClaw MCP server + /hooks/wake injector.");
|
|
72
|
+
lines.push(" OpenClaw spawns kojee-mcp (mcp.servers.kojee); wakes arrive via POST <gateway>/hooks/wake.");
|
|
73
|
+
lines.push("");
|
|
74
|
+
for (const c of report.checks) {
|
|
75
|
+
lines.push(` ${mark(c.ok)} ${c.name}: ${c.detail}`);
|
|
76
|
+
}
|
|
77
|
+
lines.push("");
|
|
78
|
+
lines.push(
|
|
79
|
+
"NOTE: live verification (gateway running, proxy spawned) is an owner step \u2014 start the OpenClaw gateway and send a Tandem message."
|
|
80
|
+
);
|
|
81
|
+
return lines.join("\n");
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
collectOpenclawDoctorReport,
|
|
85
|
+
formatOpenclawDoctorReport
|
|
86
|
+
};
|
|
@@ -2,16 +2,18 @@ import {
|
|
|
2
2
|
STATUS_LINE_PREFIX,
|
|
3
3
|
monitorHeartbeatPath,
|
|
4
4
|
nudgeSentinelPath,
|
|
5
|
+
resolveEventLogPath,
|
|
5
6
|
startEventLog,
|
|
6
7
|
statusLogPath,
|
|
7
8
|
sweepStaleEventLogs
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-TNZITJAB.js";
|
|
10
|
+
import "./chunk-67F67AQ6.js";
|
|
11
|
+
import "./chunk-U5HHHRXA.js";
|
|
11
12
|
export {
|
|
12
13
|
STATUS_LINE_PREFIX,
|
|
13
14
|
monitorHeartbeatPath,
|
|
14
15
|
nudgeSentinelPath,
|
|
16
|
+
resolveEventLogPath,
|
|
15
17
|
startEventLog,
|
|
16
18
|
statusLogPath,
|
|
17
19
|
sweepStaleEventLogs
|
|
@@ -5,9 +5,11 @@ import {
|
|
|
5
5
|
normalizeBackendEvent,
|
|
6
6
|
sanitizeDisplayname,
|
|
7
7
|
serializeCursorMap,
|
|
8
|
-
startEventStream
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
startEventStream,
|
|
9
|
+
statusReason
|
|
10
|
+
} from "./chunk-FSKGQ6GT.js";
|
|
11
|
+
import "./chunk-Z5LPNJQ6.js";
|
|
12
|
+
import "./chunk-MIEI4PLB.js";
|
|
11
13
|
export {
|
|
12
14
|
UNDICI_DEFAULT_BODY_TIMEOUT_MS,
|
|
13
15
|
createAdaptiveWatchdog,
|
|
@@ -15,5 +17,6 @@ export {
|
|
|
15
17
|
normalizeBackendEvent,
|
|
16
18
|
sanitizeDisplayname,
|
|
17
19
|
serializeCursorMap,
|
|
18
|
-
startEventStream
|
|
20
|
+
startEventStream,
|
|
21
|
+
statusReason
|
|
19
22
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
listTandemIds,
|
|
3
3
|
startProxy
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-5H75AEZ2.js";
|
|
5
|
+
import "./chunk-OB5T6P24.js";
|
|
6
|
+
import "./chunk-247WFMCJ.js";
|
|
7
|
+
import "./chunk-I67C2HYA.js";
|
|
8
|
+
import "./chunk-Z5LPNJQ6.js";
|
|
9
|
+
import "./chunk-MIEI4PLB.js";
|
|
10
|
+
import "./chunk-6G6YYST6.js";
|
|
11
|
+
import "./chunk-U5HHHRXA.js";
|
|
12
|
+
import "./chunk-SGRVG4HW.js";
|
|
13
|
+
import "./chunk-QEJUNP3X.js";
|
|
13
14
|
import "./chunk-PPTKGWFF.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-XJEBJIQE.js";
|
|
16
|
+
import "./chunk-KNEJTD6G.js";
|
|
15
17
|
export {
|
|
16
18
|
listTandemIds,
|
|
17
19
|
startProxy
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildHookCommand,
|
|
3
|
+
isKojeeHookCommand
|
|
4
|
+
} from "./chunk-QJFMU4QC.js";
|
|
5
|
+
import {
|
|
6
|
+
wrapNpxLauncher
|
|
7
|
+
} from "./chunk-D6JKFJ6A.js";
|
|
1
8
|
import {
|
|
2
9
|
secureFile
|
|
3
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-U5HHHRXA.js";
|
|
4
11
|
|
|
5
12
|
// src/hooks/install.ts
|
|
6
13
|
import fs from "fs";
|
|
@@ -27,8 +34,6 @@ function discoverInstallTargets() {
|
|
|
27
34
|
}
|
|
28
35
|
return targets;
|
|
29
36
|
}
|
|
30
|
-
var STOP_COMMAND = "npx -y kojee-mcp hook --type=stop";
|
|
31
|
-
var UPS_COMMAND = "npx -y kojee-mcp hook --type=user-prompt-submit";
|
|
32
37
|
var MCP_SERVER_CMD = "npx";
|
|
33
38
|
var MCP_SERVER_ARGS = ["kojee-mcp"];
|
|
34
39
|
var MCP_SERVER_ENV = { KOJEE_RUNTIME: "claude-code" };
|
|
@@ -54,14 +59,18 @@ function writeConfig(p, cfg) {
|
|
|
54
59
|
fs.writeFileSync(p, JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
55
60
|
secureFile(p);
|
|
56
61
|
}
|
|
57
|
-
function hasKojeeEntry(arr, command) {
|
|
58
|
-
if (!arr) return false;
|
|
59
|
-
return arr.some((e) => e.hooks.some((h) => h.command === command));
|
|
60
|
-
}
|
|
61
62
|
function installHookEntry(cfg, event, command) {
|
|
62
63
|
cfg.hooks ??= {};
|
|
63
64
|
cfg.hooks[event] ??= [];
|
|
64
|
-
|
|
65
|
+
for (const entry of cfg.hooks[event]) {
|
|
66
|
+
for (const h of entry.hooks) {
|
|
67
|
+
if (h.command === command) return "already-installed";
|
|
68
|
+
if (isKojeeHookCommand(h.command)) {
|
|
69
|
+
h.command = command;
|
|
70
|
+
return "updated";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
65
74
|
cfg.hooks[event].push({ hooks: [{ type: "command", command }] });
|
|
66
75
|
return "added";
|
|
67
76
|
}
|
|
@@ -73,7 +82,7 @@ function uninstallHookEntries(cfg) {
|
|
|
73
82
|
if (!arr) continue;
|
|
74
83
|
const before = arr.length;
|
|
75
84
|
cfg.hooks[event] = arr.filter(
|
|
76
|
-
(entry) => !entry.hooks.some((h) => h.command
|
|
85
|
+
(entry) => !entry.hooks.some((h) => isKojeeHookCommand(h.command))
|
|
77
86
|
);
|
|
78
87
|
if (cfg.hooks[event].length !== before) removed = true;
|
|
79
88
|
}
|
|
@@ -82,8 +91,8 @@ function uninstallHookEntries(cfg) {
|
|
|
82
91
|
function installHooks(opts = {}) {
|
|
83
92
|
const p = opts.hooksPath ?? (opts.configPath ? deriveHooksPath(opts.configPath) : defaultHooksPath());
|
|
84
93
|
const cfg = readConfig(p);
|
|
85
|
-
const stop = installHookEntry(cfg, "Stop",
|
|
86
|
-
const ups = installHookEntry(cfg, "UserPromptSubmit",
|
|
94
|
+
const stop = installHookEntry(cfg, "Stop", buildHookCommand("stop"));
|
|
95
|
+
const ups = installHookEntry(cfg, "UserPromptSubmit", buildHookCommand("user-prompt-submit"));
|
|
87
96
|
writeConfig(p, cfg);
|
|
88
97
|
return { stop, ups };
|
|
89
98
|
}
|
|
@@ -98,26 +107,29 @@ function mcpServerArgs(opts) {
|
|
|
98
107
|
if (opts.token && opts.url) {
|
|
99
108
|
return [...MCP_SERVER_ARGS, "--token", opts.token, "--url", opts.url];
|
|
100
109
|
}
|
|
110
|
+
if (opts.pairedConfigPath) {
|
|
111
|
+
return [...MCP_SERVER_ARGS, "--paired-config", opts.pairedConfigPath];
|
|
112
|
+
}
|
|
101
113
|
return [...MCP_SERVER_ARGS];
|
|
102
114
|
}
|
|
103
115
|
function installMcpServer(opts = {}) {
|
|
104
116
|
const p = opts.configPath ?? defaultConfigPath();
|
|
105
117
|
const cfg = readConfig(p);
|
|
106
118
|
cfg.mcpServers ??= {};
|
|
107
|
-
const args = mcpServerArgs(opts);
|
|
119
|
+
const { command, args } = wrapNpxLauncher(MCP_SERVER_CMD, mcpServerArgs(opts));
|
|
120
|
+
const env = { ...MCP_SERVER_ENV };
|
|
108
121
|
const existing = cfg.mcpServers["kojee"];
|
|
109
122
|
if (existing) {
|
|
110
|
-
const sameCommand = existing.command ===
|
|
123
|
+
const sameCommand = existing.command === command;
|
|
111
124
|
const sameArgs = JSON.stringify(existing.args ?? []) === JSON.stringify(args);
|
|
112
|
-
const sameEnv = JSON.stringify(existing.env ?? {}) === JSON.stringify(
|
|
125
|
+
const sameEnv = JSON.stringify(existing.env ?? {}) === JSON.stringify(env);
|
|
113
126
|
if (sameCommand && sameArgs && sameEnv) return "already-installed";
|
|
114
|
-
return "preserved-different";
|
|
127
|
+
if (!opts.overwrite) return "preserved-different";
|
|
128
|
+
cfg.mcpServers["kojee"] = { ...existing, command, args, env };
|
|
129
|
+
writeConfig(p, cfg);
|
|
130
|
+
return "updated";
|
|
115
131
|
}
|
|
116
|
-
cfg.mcpServers["kojee"] = {
|
|
117
|
-
command: MCP_SERVER_CMD,
|
|
118
|
-
args,
|
|
119
|
-
env: { ...MCP_SERVER_ENV }
|
|
120
|
-
};
|
|
132
|
+
cfg.mcpServers["kojee"] = { command, args, env };
|
|
121
133
|
writeConfig(p, cfg);
|
|
122
134
|
return "added";
|
|
123
135
|
}
|
|
@@ -130,12 +142,13 @@ function uninstallMcpServer(opts = {}) {
|
|
|
130
142
|
return true;
|
|
131
143
|
}
|
|
132
144
|
function runInit(opts = {}) {
|
|
133
|
-
const
|
|
145
|
+
const discovered = opts.configPath ? [{
|
|
134
146
|
kind: "cli",
|
|
135
147
|
path: opts.configPath,
|
|
136
148
|
exists: true,
|
|
137
149
|
hooksPath: opts.hooksPath ?? deriveHooksPath(opts.configPath)
|
|
138
150
|
}] : discoverInstallTargets();
|
|
151
|
+
const targets = opts.ensureCli ? discovered.map((t) => t.kind === "cli" ? { ...t, exists: true } : t) : discovered;
|
|
139
152
|
const reports = [];
|
|
140
153
|
for (const t of targets) {
|
|
141
154
|
if (!t.exists) {
|
|
@@ -145,7 +158,9 @@ function runInit(opts = {}) {
|
|
|
145
158
|
const mcpServer = installMcpServer({
|
|
146
159
|
configPath: t.path,
|
|
147
160
|
...opts.token ? { token: opts.token } : {},
|
|
148
|
-
...opts.url ? { url: opts.url } : {}
|
|
161
|
+
...opts.url ? { url: opts.url } : {},
|
|
162
|
+
...opts.pairedConfigPath ? { pairedConfigPath: opts.pairedConfigPath } : {},
|
|
163
|
+
...opts.overwrite ? { overwrite: true } : {}
|
|
149
164
|
});
|
|
150
165
|
let stopHook;
|
|
151
166
|
let upsHook;
|
package/dist/lib.d.ts
CHANGED
|
@@ -129,13 +129,16 @@ interface PairedConfig {
|
|
|
129
129
|
token: string;
|
|
130
130
|
broker_url: string;
|
|
131
131
|
paired_at: string;
|
|
132
|
+
/** Stamped at connect time; used by doctor + launch cross-check. */
|
|
133
|
+
runtime?: string;
|
|
132
134
|
principal_id?: string;
|
|
133
135
|
agent_id?: string;
|
|
134
136
|
}
|
|
137
|
+
/** Legacy global paired slot (fallback only). */
|
|
135
138
|
declare function pairedConfigPath(): string;
|
|
136
139
|
declare function loadPairedConfig(filePath?: string): PairedConfig | null;
|
|
137
140
|
|
|
138
|
-
type Runtime = "claude-code" | "codex" | "unknown";
|
|
141
|
+
type Runtime = "claude-code" | "codex" | "openclaw" | "unknown";
|
|
139
142
|
|
|
140
143
|
/**
|
|
141
144
|
* Per-harness adapter. Today: minimal — only what's needed for the
|
package/dist/lib.js
CHANGED
|
@@ -5,31 +5,34 @@ import {
|
|
|
5
5
|
normalizeBackendEvent,
|
|
6
6
|
sanitizeDisplayname,
|
|
7
7
|
startEventStream
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FSKGQ6GT.js";
|
|
9
9
|
import {
|
|
10
10
|
loadPairedConfig,
|
|
11
11
|
pairedConfigPath
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5SZHXYPK.js";
|
|
13
13
|
import {
|
|
14
14
|
GatewayClient,
|
|
15
15
|
applyStableSessionId
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-247WFMCJ.js";
|
|
17
17
|
import {
|
|
18
18
|
AuthModule
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-I67C2HYA.js";
|
|
20
20
|
import {
|
|
21
|
-
createDPoPProof,
|
|
22
21
|
deriveStableSessionId
|
|
23
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-Z5LPNJQ6.js";
|
|
23
|
+
import {
|
|
24
|
+
createDPoPProof
|
|
25
|
+
} from "./chunk-MIEI4PLB.js";
|
|
24
26
|
import {
|
|
25
27
|
defaultPairedKeystorePath,
|
|
26
28
|
deriveKeystorePath,
|
|
27
29
|
generateES256KeyPair,
|
|
28
30
|
loadKeystore,
|
|
29
31
|
saveKeystore
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
+
} from "./chunk-6G6YYST6.js";
|
|
33
|
+
import "./chunk-U5HHHRXA.js";
|
|
32
34
|
import "./chunk-PPTKGWFF.js";
|
|
35
|
+
import "./chunk-KNEJTD6G.js";
|
|
33
36
|
export {
|
|
34
37
|
AuthModule,
|
|
35
38
|
GatewayClient,
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadPairedConfig,
|
|
3
3
|
pairedConfigPath,
|
|
4
|
+
perRuntimeConfigPath,
|
|
4
5
|
savePairedConfig
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-5SZHXYPK.js";
|
|
7
|
+
import "./chunk-U5HHHRXA.js";
|
|
7
8
|
export {
|
|
8
9
|
loadPairedConfig,
|
|
9
10
|
pairedConfigPath,
|
|
11
|
+
perRuntimeConfigPath,
|
|
10
12
|
savePairedConfig
|
|
11
13
|
};
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
findClaudeAncestorPid
|
|
3
|
-
|
|
2
|
+
findClaudeAncestorPid,
|
|
3
|
+
pidLooksLikeClaude
|
|
4
|
+
} from "./chunk-XJEBJIQE.js";
|
|
4
5
|
|
|
5
6
|
// src/runtime/parent-watchdog.ts
|
|
7
|
+
function shouldArmWatchdog(ccPid) {
|
|
8
|
+
return ccPid !== null;
|
|
9
|
+
}
|
|
6
10
|
function defaultIsPidAlive(pid) {
|
|
7
11
|
try {
|
|
8
12
|
process.kill(pid, 0);
|
|
9
13
|
return true;
|
|
10
14
|
} catch (err) {
|
|
11
|
-
|
|
15
|
+
const code = err.code;
|
|
16
|
+
if (code === "EPERM" || code === "EACCES") return true;
|
|
12
17
|
return false;
|
|
13
18
|
}
|
|
14
19
|
}
|
|
@@ -16,9 +21,12 @@ function createParentWatchdog(opts) {
|
|
|
16
21
|
const intervalMs = opts.intervalMs ?? 7e3;
|
|
17
22
|
const isPidAlive = opts.isPidAlive ?? defaultIsPidAlive;
|
|
18
23
|
const resolveAncestor = opts.resolveAncestor ?? (() => findClaudeAncestorPid());
|
|
24
|
+
const verifyPidIdentity = opts.verifyPidIdentity ?? pidLooksLikeClaude;
|
|
25
|
+
const identityCheckEveryNTicks = opts.identityCheckEveryNTicks ?? 4;
|
|
19
26
|
let timer = null;
|
|
20
27
|
let fired = false;
|
|
21
28
|
let checking = false;
|
|
29
|
+
let tick = 0;
|
|
22
30
|
function stop() {
|
|
23
31
|
if (timer !== null) {
|
|
24
32
|
clearInterval(timer);
|
|
@@ -30,7 +38,17 @@ function createParentWatchdog(opts) {
|
|
|
30
38
|
checking = true;
|
|
31
39
|
try {
|
|
32
40
|
const ccPidAlive = isPidAlive(opts.ccPid);
|
|
33
|
-
if (ccPidAlive)
|
|
41
|
+
if (ccPidAlive) {
|
|
42
|
+
tick++;
|
|
43
|
+
if (tick % identityCheckEveryNTicks !== 0) return;
|
|
44
|
+
let identity = null;
|
|
45
|
+
try {
|
|
46
|
+
identity = await verifyPidIdentity(opts.ccPid);
|
|
47
|
+
} catch {
|
|
48
|
+
identity = null;
|
|
49
|
+
}
|
|
50
|
+
if (identity !== false) return;
|
|
51
|
+
}
|
|
34
52
|
let ancestor = null;
|
|
35
53
|
try {
|
|
36
54
|
ancestor = await resolveAncestor();
|
|
@@ -61,5 +79,6 @@ function createParentWatchdog(opts) {
|
|
|
61
79
|
}
|
|
62
80
|
export {
|
|
63
81
|
createParentWatchdog,
|
|
64
|
-
defaultIsPidAlive
|
|
82
|
+
defaultIsPidAlive,
|
|
83
|
+
shouldArmWatchdog
|
|
65
84
|
};
|