kojee-mcp 0.7.5-staging.2 → 0.7.5-staging.21

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.
Files changed (48) hide show
  1. package/README.md +27 -6
  2. package/dist/{cc-session-id-RURNIHHC.js → cc-session-id-5HHQJ7VC.js} +3 -1
  3. package/dist/{chunk-ZSHCHOPL.js → chunk-676WQSWZ.js} +163 -7
  4. package/dist/{chunk-FJUAMJHU.js → chunk-6NPMVZD7.js} +38 -3
  5. package/dist/{chunk-247WFMCJ.js → chunk-AGZ7ZGLY.js} +30 -3
  6. package/dist/chunk-AXBJQJKA.js +65 -0
  7. package/dist/{chunk-TCWIXG5C.js → chunk-CCVRXJJ2.js} +1 -1
  8. package/dist/{chunk-WBXU27BF.js → chunk-FNMKP34Y.js} +1 -1
  9. package/dist/chunk-GEGUWQYT.js +90 -0
  10. package/dist/{chunk-NE2F5CKS.js → chunk-LKGKDZSO.js} +9 -5
  11. package/dist/{chunk-XPIW4N55.js → chunk-N2YAZRAD.js} +178 -43
  12. package/dist/{chunk-LSUB6QMP.js → chunk-NIIBVKLP.js} +3 -0
  13. package/dist/chunk-P64UR3SE.js +86 -0
  14. package/dist/{chunk-A4IOKD4Z.js → chunk-QYZP6QT2.js} +2 -4
  15. package/dist/{chunk-KNEJTD6G.js → chunk-SZLNNMIZ.js} +6 -2
  16. package/dist/{chunk-CUOJHP2S.js → chunk-UGEBGCYU.js} +48 -12
  17. package/dist/{chunk-6XWTUDWW.js → chunk-WDWVBPXA.js} +7 -5
  18. package/dist/{chunk-TNZITJAB.js → chunk-WVQU3QQ7.js} +14 -4
  19. package/dist/cli.js +42 -23
  20. package/dist/{codex-prompt-submit-hook-J5PZEJSK.js → codex-prompt-submit-hook-UQJI6A54.js} +2 -2
  21. package/dist/{codex-stop-hook-32W4BIOM.js → codex-stop-hook-GTGRQNVV.js} +2 -2
  22. package/dist/{connect-handler-NZINEMG3.js → connect-handler-GTFXNZUC.js} +68 -9
  23. package/dist/{doctor-WUU5BVPT.js → doctor-54S7JGOE.js} +64 -5
  24. package/dist/{doctor-codex-PJFWIABF.js → doctor-codex-6H4OOS6O.js} +84 -10
  25. package/dist/doctor-hermes-KMHM27Y3.js +597 -0
  26. package/dist/{doctor-openclaw-LL6NSPLC.js → doctor-openclaw-B5KADVHD.js} +5 -1
  27. package/dist/{event-log-2NBJEIEP.js → event-log-M22X3FAI.js} +1 -1
  28. package/dist/{event-stream-ATKYXDBV.js → event-stream-5ZEL7FXN.js} +5 -1
  29. package/dist/flap-log-D4KG7RK4.js +23 -0
  30. package/dist/{gateway-client-CbM2OC_w.d.ts → gateway-client-CLmQghON.d.ts} +11 -0
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +6 -7
  33. package/dist/{install-JQNDGAAQ.js → install-GJVZEWLI.js} +8 -7
  34. package/dist/lib.d.ts +30 -1
  35. package/dist/lib.js +3 -3
  36. package/dist/plugins/hermes/adapter.py +7 -2
  37. package/dist/{registry-XJ67EO22.js → registry-MCJAVXJW.js} +36 -24
  38. package/dist/{send-cli-45RLGYIC.js → send-cli-WTY7H3BR.js} +2 -2
  39. package/dist/{server-DU3LFS32.js → server-VM3ZIGSZ.js} +2 -3
  40. package/dist/session-start-hook-VL3KYDTT.js +25 -0
  41. package/dist/{setup-handler-44ASXYMS.js → setup-handler-GNAIWAYU.js} +7 -7
  42. package/dist/{stop-hook-N6TX4YQT.js → stop-hook-BLPYRE7T.js} +5 -5
  43. package/dist/stream-watchdog-K2AWNCQW.js +64 -0
  44. package/dist/{tail-stream-G4WGTXDS.js → tail-stream-PQXEY3TI.js} +120 -9
  45. package/dist/{user-prompt-submit-hook-DTXXFDSD.js → user-prompt-submit-hook-YQXGE3JU.js} +3 -3
  46. package/package.json +3 -2
  47. package/dist/chunk-5DHIUN73.js +0 -25
  48. package/dist/chunk-TMCNB4JH.js +0 -33
@@ -3,19 +3,20 @@ import {
3
3
  STATUS_LINE_PREFIX,
4
4
  monitorHeartbeatPath,
5
5
  statusLogPath
6
- } from "./chunk-TNZITJAB.js";
6
+ } from "./chunk-WVQU3QQ7.js";
7
7
  import "./chunk-67F67AQ6.js";
8
8
  import {
9
9
  LOG_HEARTBEAT_INTERVAL_MS,
10
10
  UNARMED_FALLBACK_MS,
11
11
  createAdaptiveWatchdog
12
- } from "./chunk-CUOJHP2S.js";
12
+ } from "./chunk-UGEBGCYU.js";
13
13
  import "./chunk-Z5LPNJQ6.js";
14
14
  import "./chunk-MIEI4PLB.js";
15
15
  import "./chunk-U5HHHRXA.js";
16
16
 
17
17
  // src/tail-stream.ts
18
18
  import fs from "fs";
19
+ import { spawn } from "child_process";
19
20
  var STATUS_LINE_RE = new RegExp(`^\\[[^\\]]*\\] ${STATUS_LINE_PREFIX} (.*)$`);
20
21
  var HEARTBEAT_FIELDS_RE = /(^|\s)status=heartbeat(\s|$)/;
21
22
  var ROTATED_FIELDS_RE = /(^|\s)status=rotated(\s|$)/;
@@ -29,6 +30,7 @@ var TAIL_STALE_FLOOR_MS = envInt(
29
30
  );
30
31
  var STALE_CHECK_INTERVAL_MS = envInt("KOJEE_TAIL_CHECK_MS", 5e3);
31
32
  var TAIL_REWARN_AFTER_MS = 30 * 6e4;
33
+ var SUSTAINED_STALE_MS = envInt("KOJEE_TAIL_SUSTAINED_MS", TAIL_REWARN_AFTER_MS);
32
34
  var TAIL_HEALTHY_RESET_MS = 30 * 6e4;
33
35
  var TAIL_BACKOFF_CAP_CYCLES = 3;
34
36
  function envInt(name, fallback) {
@@ -99,9 +101,14 @@ function createStallDetector(startNow, options = {}) {
99
101
  }
100
102
  };
101
103
  }
102
- async function runTail(messagesPath) {
104
+ async function runTail(messagesPath, opts = {}) {
105
+ const wakeOnly = opts.wakeOnly === true;
106
+ const replay = opts.replay === true;
103
107
  const statusPath = statusLogPath(messagesPath);
104
- const detector = createStallDetector(Date.now(), { floorMs: TAIL_STALE_FLOOR_MS });
108
+ const detector = createStallDetector(Date.now(), {
109
+ floorMs: TAIL_STALE_FLOOR_MS,
110
+ rewarnAfterMs: SUSTAINED_STALE_MS
111
+ });
105
112
  const heartbeatPath = monitorHeartbeatPath(messagesPath);
106
113
  const touchHeartbeat = () => {
107
114
  const now = /* @__PURE__ */ new Date();
@@ -116,7 +123,7 @@ async function runTail(messagesPath) {
116
123
  };
117
124
  let lastCursor = null;
118
125
  function onMessageLine(line) {
119
- if (detector.onLife(Date.now())?.kind === "recovered") {
126
+ if (detector.onLife(Date.now())?.kind === "recovered" && !wakeOnly) {
120
127
  process.stdout.write(
121
128
  "[kojee] stream recovered \u2014 events flowing again (recovery is automatic; no action needed).\n"
122
129
  );
@@ -133,7 +140,7 @@ async function runTail(messagesPath) {
133
140
  if (HEARTBEAT_FIELDS_RE.test(fields)) {
134
141
  detector.onHeartbeat(now);
135
142
  }
136
- if (detector.onLife(now)?.kind === "recovered") {
143
+ if (detector.onLife(now)?.kind === "recovered" && !wakeOnly) {
137
144
  process.stdout.write(
138
145
  "[kojee] stream recovered \u2014 heartbeats resumed (the stall was transient, likely idle-period timing or brief host load; no action needed).\n"
139
146
  );
@@ -149,8 +156,16 @@ async function runTail(messagesPath) {
149
156
  }
150
157
  }
151
158
  const followers = [
152
- makeFollower(messagesPath, onMessageLine, touchHeartbeat),
153
- makeFollower(statusPath, onStatusLine, touchHeartbeat)
159
+ // MESSAGES (wake-critical) — prefer the OS `tail -F` follower where the
160
+ // platform has one; it delegates file-following to the battle-tested system
161
+ // binary instead of the Node fs.watch/poll tailer. STATUS (telemetry) stays
162
+ // on the Node follower: its startup-backlog seeding boundary (statusSeeded)
163
+ // is clean to detect only when we control the drain. See makeMessagesFollower.
164
+ makeMessagesFollower(messagesPath, onMessageLine, touchHeartbeat, replay),
165
+ // STATUS stays replay=true: its single current-state line is seeded on
166
+ // attach (statusSeeded boundary) — that's cheap, not a flood, and the
167
+ // connected/rotated seed is what primes the watchdog + backfill logic.
168
+ makeFollower(statusPath, onStatusLine, touchHeartbeat, true)
154
169
  ];
155
170
  void Promise.all([
156
171
  followers[0].start(),
@@ -171,6 +186,7 @@ async function runTail(messagesPath) {
171
186
  );
172
187
  return;
173
188
  }
189
+ if (wakeOnly) return;
174
190
  const thresholdS = Math.round((signal.thresholdMs ?? 0) / 1e3);
175
191
  process.stdout.write(
176
192
  `[kojee] WARNING: no events or heartbeat for ${silentS}s (threshold ${thresholdS}s) \u2014 stream may be dead, but this is often benign (idle stream, or brief host load delaying heartbeats) and recovery is automatic; if it persists, run \`npx kojee-mcp doctor\`.
@@ -191,7 +207,7 @@ async function runTail(messagesPath) {
191
207
  process.on("SIGINT", cleanup);
192
208
  });
193
209
  }
194
- function makeFollower(filePath, onLine, onActivity) {
210
+ function makeFollower(filePath, onLine, onActivity, replay = true) {
195
211
  let buffer = "";
196
212
  let offset = 0;
197
213
  let watcher = null;
@@ -248,6 +264,12 @@ function makeFollower(filePath, onLine, onActivity) {
248
264
  await sleep(250);
249
265
  }
250
266
  if (stopped) return;
267
+ if (!replay) {
268
+ try {
269
+ offset = (await fs.promises.stat(filePath)).size;
270
+ } catch {
271
+ }
272
+ }
251
273
  onActivity();
252
274
  await scheduleDrain();
253
275
  pollTimer = setInterval(() => {
@@ -273,11 +295,100 @@ function makeFollower(filePath, onLine, onActivity) {
273
295
  }
274
296
  };
275
297
  }
298
+ function osTailAvailable() {
299
+ const override = (process.env.KOJEE_TAIL_IMPL ?? "").trim().toLowerCase();
300
+ if (override === "os") return true;
301
+ if (override === "node") return false;
302
+ return process.platform !== "win32";
303
+ }
304
+ function makeMessagesFollower(filePath, onLine, onActivity, replay = true) {
305
+ if (!osTailAvailable()) return makeFollower(filePath, onLine, onActivity, replay);
306
+ return makeTailFollower(
307
+ filePath,
308
+ onLine,
309
+ onActivity,
310
+ () => makeFollower(filePath, onLine, onActivity, replay),
311
+ replay
312
+ );
313
+ }
314
+ function makeTailFollower(filePath, onLine, onActivity, fallback, replay = true) {
315
+ let child = null;
316
+ let heir = null;
317
+ let hbTimer = null;
318
+ let buffer = "";
319
+ let stopped = false;
320
+ let handedOff = false;
321
+ function emit(chunk) {
322
+ onActivity();
323
+ buffer += chunk;
324
+ let nl;
325
+ while ((nl = buffer.indexOf("\n")) !== -1) {
326
+ onLine(buffer.slice(0, nl));
327
+ buffer = buffer.slice(nl + 1);
328
+ }
329
+ }
330
+ function handOff() {
331
+ if (stopped || handedOff) return;
332
+ handedOff = true;
333
+ if (hbTimer) {
334
+ clearInterval(hbTimer);
335
+ hbTimer = null;
336
+ }
337
+ if (child) {
338
+ try {
339
+ child.kill("SIGTERM");
340
+ } catch {
341
+ }
342
+ child = null;
343
+ }
344
+ heir = fallback();
345
+ void heir.start().catch(() => {
346
+ });
347
+ }
348
+ return {
349
+ async start() {
350
+ try {
351
+ child = spawn("tail", ["-n", replay ? "+1" : "0", "-F", filePath], {
352
+ stdio: ["ignore", "pipe", "ignore"]
353
+ });
354
+ } catch {
355
+ handOff();
356
+ return;
357
+ }
358
+ child.on("error", () => handOff());
359
+ child.on("exit", () => {
360
+ if (!stopped) handOff();
361
+ });
362
+ child.stdout?.setEncoding("utf8");
363
+ child.stdout?.on("data", (d) => emit(d));
364
+ onActivity();
365
+ hbTimer = setInterval(onActivity, 1e3);
366
+ },
367
+ stop() {
368
+ stopped = true;
369
+ if (hbTimer) {
370
+ clearInterval(hbTimer);
371
+ hbTimer = null;
372
+ }
373
+ if (child) {
374
+ try {
375
+ child.kill("SIGTERM");
376
+ } catch {
377
+ }
378
+ child = null;
379
+ }
380
+ if (heir) heir.stop();
381
+ }
382
+ };
383
+ }
276
384
  function sleep(ms) {
277
385
  return new Promise((r) => setTimeout(r, ms));
278
386
  }
279
387
  export {
280
388
  createStallDetector,
281
389
  makeFollower,
390
+ makeMessagesFollower,
391
+ makeTailFollower,
392
+ osTailAvailable,
282
393
  runTail
283
394
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  resolveHookDiscovery
3
- } from "./chunk-WBXU27BF.js";
3
+ } from "./chunk-FNMKP34Y.js";
4
4
  import {
5
5
  readHookStdin
6
- } from "./chunk-LSUB6QMP.js";
6
+ } from "./chunk-NIIBVKLP.js";
7
7
  import {
8
8
  controlTokenAuthHeaders
9
9
  } from "./chunk-GKXHKR3B.js";
@@ -13,7 +13,7 @@ import {
13
13
  import "./chunk-67F67AQ6.js";
14
14
  import "./chunk-U5HHHRXA.js";
15
15
  import "./chunk-XJEBJIQE.js";
16
- import "./chunk-KNEJTD6G.js";
16
+ import "./chunk-SZLNNMIZ.js";
17
17
 
18
18
  // src/hooks/user-prompt-submit-hook.ts
19
19
  async function runUserPromptSubmitHook() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kojee-mcp",
3
- "version": "0.7.5-staging.2",
3
+ "version": "0.7.5-staging.21",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -34,7 +34,8 @@
34
34
  "jose": "^5.0.0",
35
35
  "ps-list": "^8.1.1",
36
36
  "ulidx": "^2.3.0",
37
- "undici": "^8.5.0",
37
+ "undici": "8.5.0",
38
+ "yaml": "^2.9.0",
38
39
  "zod": "^3.22.0"
39
40
  },
40
41
  "devDependencies": {
@@ -1,25 +0,0 @@
1
- // src/version.ts
2
- import fs from "fs";
3
- import path from "path";
4
- import { fileURLToPath } from "url";
5
- var FALLBACK_VERSION = "0.0.0-unknown";
6
- function resolveVersion() {
7
- try {
8
- const here = path.dirname(fileURLToPath(import.meta.url));
9
- const parsed = JSON.parse(
10
- fs.readFileSync(path.join(here, "..", "package.json"), "utf8")
11
- );
12
- return typeof parsed?.version === "string" && parsed.version ? parsed.version : FALLBACK_VERSION;
13
- } catch (err) {
14
- process.stderr.write(
15
- `kojee-mcp: could not resolve version from package.json, falling back to ${FALLBACK_VERSION}: ${String(err)}
16
- `
17
- );
18
- return FALLBACK_VERSION;
19
- }
20
- }
21
- var VERSION = resolveVersion();
22
-
23
- export {
24
- VERSION
25
- };
@@ -1,33 +0,0 @@
1
- // src/hooks/hook-command.ts
2
- import fs from "fs";
3
- import path from "path";
4
- import { fileURLToPath } from "url";
5
- function npxHookCommand(type) {
6
- return `npx -y kojee-mcp hook --type=${type}`;
7
- }
8
- function resolveCliEntry(moduleUrl = import.meta.url) {
9
- try {
10
- const here = fileURLToPath(moduleUrl);
11
- const candidate = path.join(path.dirname(here), "cli.js");
12
- return fs.existsSync(candidate) ? candidate : null;
13
- } catch {
14
- return null;
15
- }
16
- }
17
- function buildHookCommand(type, opts = {}) {
18
- const cliEntry = opts.cliEntry !== void 0 ? opts.cliEntry : resolveCliEntry();
19
- if (!cliEntry) return npxHookCommand(type);
20
- const execPath = opts.execPath ?? process.execPath;
21
- return `"${execPath}" "${cliEntry}" hook --type=${type}`;
22
- }
23
- var PINNED_HOOK_RE = /^"[^"]+" "[^"]+" hook --type=(stop|user-prompt-submit|codex-stop|codex-prompt-submit)$/;
24
- function isKojeeHookCommand(command) {
25
- if (command.startsWith("npx -y kojee-mcp hook --type=")) return true;
26
- return PINNED_HOOK_RE.test(command);
27
- }
28
-
29
- export {
30
- npxHookCommand,
31
- buildHookCommand,
32
- isKojeeHookCommand
33
- };