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
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as GatewayClient, P as ProxyConfig } from './gateway-client-CbM2OC_w.js';
1
+ import { G as GatewayClient, P as ProxyConfig } from './gateway-client-CLmQghON.js';
2
2
  import 'jose';
3
3
 
4
4
  /**
package/dist/index.js CHANGED
@@ -1,20 +1,19 @@
1
1
  import {
2
2
  listTandemIds,
3
3
  startProxy
4
- } from "./chunk-ZSHCHOPL.js";
5
- import "./chunk-TCWIXG5C.js";
6
- import "./chunk-247WFMCJ.js";
4
+ } from "./chunk-676WQSWZ.js";
5
+ import "./chunk-CCVRXJJ2.js";
6
+ import "./chunk-AGZ7ZGLY.js";
7
7
  import "./chunk-Z5LPNJQ6.js";
8
8
  import "./chunk-I67C2HYA.js";
9
9
  import "./chunk-MIEI4PLB.js";
10
10
  import "./chunk-6G6YYST6.js";
11
11
  import "./chunk-U5HHHRXA.js";
12
- import "./chunk-A4IOKD4Z.js";
13
- import "./chunk-5DHIUN73.js";
14
- import "./chunk-FJUAMJHU.js";
12
+ import "./chunk-QYZP6QT2.js";
13
+ import "./chunk-6NPMVZD7.js";
15
14
  import "./chunk-PPTKGWFF.js";
16
15
  import "./chunk-XJEBJIQE.js";
17
- import "./chunk-KNEJTD6G.js";
16
+ import "./chunk-SZLNNMIZ.js";
18
17
  export {
19
18
  listTandemIds,
20
19
  startProxy
@@ -1,10 +1,10 @@
1
- import {
2
- buildHookCommand,
3
- isKojeeHookCommand
4
- } from "./chunk-TMCNB4JH.js";
5
1
  import {
6
2
  wrapNpxLauncher
7
3
  } from "./chunk-D6JKFJ6A.js";
4
+ import {
5
+ buildHookCommand,
6
+ isKojeeHookCommand
7
+ } from "./chunk-AXBJQJKA.js";
8
8
  import {
9
9
  secureFile
10
10
  } from "./chunk-U5HHHRXA.js";
@@ -77,7 +77,7 @@ function installHookEntry(cfg, event, command) {
77
77
  function uninstallHookEntries(cfg) {
78
78
  let removed = false;
79
79
  if (!cfg.hooks) return false;
80
- for (const event of ["Stop", "UserPromptSubmit"]) {
80
+ for (const event of ["Stop", "UserPromptSubmit", "SessionStart"]) {
81
81
  const arr = cfg.hooks[event];
82
82
  if (!arr) continue;
83
83
  const before = arr.length;
@@ -93,7 +93,8 @@ function installHooks(opts = {}) {
93
93
  const cfg = readConfig(p);
94
94
  const stop = installHookEntry(cfg, "Stop", buildHookCommand("stop"));
95
95
  const ups = installHookEntry(cfg, "UserPromptSubmit", buildHookCommand("user-prompt-submit"));
96
- if (stop !== "already-installed" || ups !== "already-installed") {
96
+ const sessionStart = installHookEntry(cfg, "SessionStart", buildHookCommand("session-start"));
97
+ if (stop !== "already-installed" || ups !== "already-installed" || sessionStart !== "already-installed") {
97
98
  writeConfig(p, cfg);
98
99
  } else {
99
100
  const newContent = JSON.stringify(cfg, null, 2);
@@ -106,7 +107,7 @@ function installHooks(opts = {}) {
106
107
  writeConfig(p, cfg);
107
108
  }
108
109
  }
109
- return { stop, ups };
110
+ return { stop, ups, sessionStart };
110
111
  }
111
112
  function uninstallHooks(opts = {}) {
112
113
  const p = opts.hooksPath ?? (opts.configPath ? deriveHooksPath(opts.configPath) : defaultHooksPath());
package/dist/lib.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { KeyLike, JWK } from 'jose';
2
- import { L as LoadedKeyPair, K as KeystoreData, G as GatewayClient, M as McpToolDefinition, T as ToolCallResult, P as ProxyConfig } from './gateway-client-CbM2OC_w.js';
2
+ import { L as LoadedKeyPair, K as KeystoreData, G as GatewayClient, M as McpToolDefinition, T as ToolCallResult, P as ProxyConfig } from './gateway-client-CLmQghON.js';
3
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
4
 
5
5
  /**
@@ -39,6 +39,7 @@ interface TandemEvent {
39
39
  severity?: string;
40
40
  wake?: boolean;
41
41
  wake_reason?: string;
42
+ edited_at?: string | null;
42
43
  }
43
44
 
44
45
  /**
@@ -261,6 +262,17 @@ interface EventStreamOptions {
261
262
  gateway: GatewayClient;
262
263
  adapter: HarnessAdapter;
263
264
  server: Server;
265
+ /**
266
+ * This connection's STABLE per-seat identity (SEAT-INVITE #226 per-seat
267
+ * routing). When set, the stream opens with `?seat_name=<value>` so the
268
+ * backend subscribes this seat's own `seat:{agent}:{seat_name}` channel and
269
+ * scopes the invite catch-up to it — so a per-seat invite wakes ONLY this
270
+ * seat, not every seat of a shared agent_id (the Clauron dev fleet all share
271
+ * one agent). It MUST be the exact `tandem_join` seat_name (e.g. "Backend-Dev",
272
+ * NOT the hyphen-form `KOJEE_INSTANCE`); the backend normalizes both sides
273
+ * identically. Unset ⇒ no `?seat_name=` (legacy agent-wide invite wake).
274
+ */
275
+ seatName?: string;
264
276
  queue?: EventQueue;
265
277
  eventLog?: EventLog;
266
278
  /**
@@ -509,6 +521,23 @@ declare class ToolRegistry {
509
521
  * Fetch all tools with full schemas from the gateway in a single RPC call.
510
522
  */
511
523
  discoverTools(): Promise<void>;
524
+ /**
525
+ * Teach the gateway's `tandem_upload_attachment` tool about a `file_path` arg
526
+ * that THIS proxy resolves in-process (see {@link resolveUploadFilePath}): the
527
+ * model emits a local path, the proxy reads the bytes and forwards them as
528
+ * `data_base64`, so a multi-MB image never has to be generated into the model's
529
+ * tool call. Purely additive — the original `data_base64` shape still works. A
530
+ * no-op if the gateway doesn't expose the tool (older backend).
531
+ */
532
+ private augmentUploadTool;
533
+ /**
534
+ * Resolve a `tandem_upload_attachment` call that used `file_path`: read the file
535
+ * locally, base64-encode the RAW bytes (Buffer→base64 is byte-exact — no text
536
+ * round-trip, so no U+FFFD corruption), and rewrite the args to the `data_base64`
537
+ * shape the gateway expects. Returns the args to forward, or throws with a clear
538
+ * message the caller surfaces as an isError result.
539
+ */
540
+ private resolveUploadFilePath;
512
541
  /**
513
542
  * Return all registered tools for the MCP ListTools response — gateway tools
514
543
  * first (minus any a local tool shadows), then local tools.
package/dist/lib.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  normalizeBackendEvent,
3
3
  sanitizeDisplayname,
4
4
  startEventStream
5
- } from "./chunk-CUOJHP2S.js";
5
+ } from "./chunk-UGEBGCYU.js";
6
6
  import {
7
7
  resubscribeMemberships
8
8
  } from "./chunk-OT2GILXC.js";
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  GatewayClient,
15
15
  applyStableSessionId
16
- } from "./chunk-247WFMCJ.js";
16
+ } from "./chunk-AGZ7ZGLY.js";
17
17
  import {
18
18
  deriveStableSessionId
19
19
  } from "./chunk-Z5LPNJQ6.js";
@@ -32,7 +32,7 @@ import {
32
32
  } from "./chunk-6G6YYST6.js";
33
33
  import "./chunk-U5HHHRXA.js";
34
34
  import "./chunk-PPTKGWFF.js";
35
- import "./chunk-KNEJTD6G.js";
35
+ import "./chunk-SZLNNMIZ.js";
36
36
  export {
37
37
  AuthModule,
38
38
  GatewayClient,
@@ -154,8 +154,13 @@ class KojeeTandemAdapter(BasePlatformAdapter):
154
154
 
155
155
  # ── Connection lifecycle ────────────────────────────────────────────
156
156
 
157
- async def connect(self) -> bool:
158
- """Start the loopback webhook listener the kojee-mcp daemon POSTs to."""
157
+ async def connect(self, *, is_reconnect: bool = False) -> bool:
158
+ """Start the loopback webhook listener the kojee-mcp daemon POSTs to.
159
+
160
+ ``is_reconnect`` is part of the BasePlatformAdapter.connect contract
161
+ (the gateway's reconnection watcher calls ``connect(is_reconnect=True)``);
162
+ this listener is stateless per-connect so the flag is accepted and ignored.
163
+ """
159
164
  if not self.webhook_secret:
160
165
  logger.error("kojee-tandem: KOJEE_WEBHOOK_SECRET must be set (signed-only inbound)")
161
166
  self._set_fatal_error(
@@ -5,20 +5,19 @@ import {
5
5
  } from "./chunk-XLRF5ATG.js";
6
6
  import {
7
7
  createCachedOpenclawWakeResolver,
8
- postOpenclawWake
9
- } from "./chunk-NE2F5CKS.js";
8
+ postOpenclawAgent
9
+ } from "./chunk-LKGKDZSO.js";
10
10
  import "./chunk-PHXO5P25.js";
11
11
  import {
12
12
  recordDelivered
13
13
  } from "./chunk-IZN7IZPW.js";
14
14
  import {
15
15
  claudeCodeAdapter
16
- } from "./chunk-TCWIXG5C.js";
17
- import "./chunk-A4IOKD4Z.js";
16
+ } from "./chunk-CCVRXJJ2.js";
17
+ import "./chunk-QYZP6QT2.js";
18
18
  import {
19
19
  VERSION
20
- } from "./chunk-5DHIUN73.js";
21
- import "./chunk-FJUAMJHU.js";
20
+ } from "./chunk-6NPMVZD7.js";
22
21
  import "./chunk-PPTKGWFF.js";
23
22
 
24
23
  // src/delivery/lib/fanout.ts
@@ -122,14 +121,14 @@ function createClaudeCodeDelivery() {
122
121
  cleanupDiscoveryByKey,
123
122
  sweepStaleDiscovery
124
123
  } = await import("./session-discovery-NHCZ2XWA.js");
125
- const { startEventLog, sweepStaleEventLogs } = await import("./event-log-2NBJEIEP.js");
124
+ const { startEventLog, sweepStaleEventLogs } = await import("./event-log-M22X3FAI.js");
126
125
  const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
127
126
  const { resolveWebhookConfig } = await import("./webhook-config-O4WMQ532.js");
128
127
  const { createWebhookSink } = await import("./webhook-sink-N6AUTFL3.js");
129
- const { startEventStream } = await import("./event-stream-ATKYXDBV.js");
130
- const { createMcpServer } = await import("./server-DU3LFS32.js");
128
+ const { startEventStream } = await import("./event-stream-5ZEL7FXN.js");
129
+ const { createMcpServer } = await import("./server-VM3ZIGSZ.js");
131
130
  const { deriveDiscoveryKey } = await import("./ancestry-A2F5KQ6A.js");
132
- const { resolveSharedSessionId } = await import("./cc-session-id-RURNIHHC.js");
131
+ const { resolveSharedSessionId } = await import("./cc-session-id-5HHQJ7VC.js");
133
132
  sweepStaleDiscovery();
134
133
  sweepStaleEventLogs();
135
134
  const projectDir = process.env["CLAUDE_PROJECT_DIR"];
@@ -255,6 +254,9 @@ function createClaudeCodeDelivery() {
255
254
  gateway: ctx.gateway,
256
255
  adapter: ctx.adapter,
257
256
  server,
257
+ // SEAT-INVITE #226 per-seat routing: this seat's stable seat_name, set
258
+ // per-seat in the fleet systemd env. Unset ⇒ legacy agent-wide wake.
259
+ seatName: process.env["CLAURON_SEAT_NAME"] || void 0,
258
260
  // eventLog is passed so the stream's status/heartbeat lines land in the
259
261
  // status sibling (emitStatus / heartbeat use opts.eventLog.appendStatus).
260
262
  // The PER-EVENT fan-out (queue/eventLog/channel/webhook) is owned by
@@ -319,12 +321,12 @@ function createWebhookDelivery(name, pendingLedger) {
319
321
  return {
320
322
  name,
321
323
  async start(ctx) {
322
- const { startEventLog, sweepStaleEventLogs } = await import("./event-log-2NBJEIEP.js");
324
+ const { startEventLog, sweepStaleEventLogs } = await import("./event-log-M22X3FAI.js");
323
325
  const { resolveWebhookConfig } = await import("./webhook-config-O4WMQ532.js");
324
326
  const { createWebhookSink } = await import("./webhook-sink-N6AUTFL3.js");
325
327
  const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
326
- const { startEventStream } = await import("./event-stream-ATKYXDBV.js");
327
- const { createMcpServer } = await import("./server-DU3LFS32.js");
328
+ const { startEventStream } = await import("./event-stream-5ZEL7FXN.js");
329
+ const { createMcpServer } = await import("./server-VM3ZIGSZ.js");
328
330
  sweepStaleEventLogs();
329
331
  eventLog = startEventLog({
330
332
  key: ctx.instanceKey,
@@ -373,6 +375,9 @@ function createWebhookDelivery(name, pendingLedger) {
373
375
  gateway: ctx.gateway,
374
376
  adapter: ctx.adapter,
375
377
  server,
378
+ // SEAT-INVITE #226 per-seat routing: this seat's stable seat_name, set
379
+ // per-seat in the fleet systemd env. Unset ⇒ legacy agent-wide wake.
380
+ seatName: process.env["CLAURON_SEAT_NAME"] || void 0,
376
381
  eventLog,
377
382
  delivery: this,
378
383
  onConnected: /* @__PURE__ */ (() => {
@@ -501,24 +506,23 @@ function createCodexDelivery(onDelivered) {
501
506
  }
502
507
 
503
508
  // src/delivery/openclaw.ts
504
- function formatOpenclawNudge(event) {
505
- const who = event.from?.member_id ?? "someone";
506
- const body = (event.content?.body ?? "").replace(/\s+/g, " ").slice(0, 160);
507
- return `New Kojee Tandem activity in ${event.tandem_id} from ${who}: "${body}". Catch up with tandem_messages / tandem_listen and reply via tandem_send.`;
509
+ function formatOpenclawAgentPrompt(event) {
510
+ const since = Math.max(0, (event.cursor ?? 1) - 1);
511
+ return `You were mentioned in Kojee Tandem ${event.tandem_id}. Read it to see who and what \u2014 tandem_messages(tandem_id="${event.tandem_id}", since=${since}) \u2014 then REPLY IN THE FORUM now with tandem_send(tandem_id="${event.tandem_id}", body=..., reply_to="${event.id}"). Do this now; don't just read or ack.`;
508
512
  }
509
513
  function createOpenclawDelivery(deps = {}) {
510
514
  const resolveTarget = deps.resolveTarget ?? createCachedOpenclawWakeResolver();
511
- const postWake = deps.postWake ?? postOpenclawWake;
515
+ const postAgent = deps.postAgent ?? postOpenclawAgent;
512
516
  let eventLog = null;
513
517
  let streamHandle = null;
514
518
  let warnedUnconfigured = false;
515
519
  return {
516
520
  name: "openclaw",
517
521
  async start(ctx) {
518
- const { startEventLog, sweepStaleEventLogs } = await import("./event-log-2NBJEIEP.js");
522
+ const { startEventLog, sweepStaleEventLogs } = await import("./event-log-M22X3FAI.js");
519
523
  const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
520
- const { startEventStream } = await import("./event-stream-ATKYXDBV.js");
521
- const { createMcpServer } = await import("./server-DU3LFS32.js");
524
+ const { startEventStream } = await import("./event-stream-5ZEL7FXN.js");
525
+ const { createMcpServer } = await import("./server-VM3ZIGSZ.js");
522
526
  sweepStaleEventLogs();
523
527
  eventLog = startEventLog({
524
528
  key: ctx.instanceKey,
@@ -544,6 +548,9 @@ function createOpenclawDelivery(deps = {}) {
544
548
  gateway: ctx.gateway,
545
549
  adapter: ctx.adapter,
546
550
  server,
551
+ // SEAT-INVITE #226 per-seat routing: this seat's stable seat_name, set
552
+ // per-seat in the fleet systemd env. Unset ⇒ legacy agent-wide wake.
553
+ seatName: process.env["CLAURON_SEAT_NAME"] || void 0,
547
554
  eventLog,
548
555
  delivery: this,
549
556
  onConnected: /* @__PURE__ */ (() => {
@@ -587,8 +594,13 @@ function createOpenclawDelivery(deps = {}) {
587
594
  return;
588
595
  }
589
596
  warnedUnconfigured = false;
590
- const res = await postWake(r.target, { text: formatOpenclawNudge(event), mode: "now" });
591
- if (!res.ok) console.error(`[openclaw] wake POST failed: ${res.error ?? res.status}`);
597
+ const res = await postAgent(r.target, {
598
+ message: formatOpenclawAgentPrompt(event),
599
+ channel: "last",
600
+ name: "Kojee",
601
+ wakeMode: "now"
602
+ });
603
+ if (!res.ok) console.error(`[openclaw] agent wake POST failed: ${res.error ?? res.status}`);
592
604
  })().catch((err) => {
593
605
  console.error("[openclaw] wake delivery failed:", err);
594
606
  });
@@ -615,7 +627,7 @@ function selectDelivery(runtime, opts) {
615
627
  return createCodexDelivery(opts.onDelivered);
616
628
  }
617
629
  if (runtime === "openclaw") {
618
- return createOpenclawDelivery();
630
+ return opts.headless ? createOpenclawDelivery() : null;
619
631
  }
620
632
  if (!needsWebhookEventStream(opts.env)) {
621
633
  return null;
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  GatewayClient,
15
15
  applyStableSessionId
16
- } from "./chunk-247WFMCJ.js";
16
+ } from "./chunk-AGZ7ZGLY.js";
17
17
  import "./chunk-Z5LPNJQ6.js";
18
18
  import "./chunk-MIEI4PLB.js";
19
19
  import {
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-6G6YYST6.js";
23
23
  import "./chunk-U5HHHRXA.js";
24
24
  import "./chunk-PPTKGWFF.js";
25
- import "./chunk-KNEJTD6G.js";
25
+ import "./chunk-SZLNNMIZ.js";
26
26
 
27
27
  // src/tandem/send-cli.ts
28
28
  import os from "os";
@@ -5,9 +5,8 @@ import {
5
5
  executeToolCall,
6
6
  extractDrainCursor,
7
7
  startMcpServer
8
- } from "./chunk-A4IOKD4Z.js";
9
- import "./chunk-5DHIUN73.js";
10
- import "./chunk-FJUAMJHU.js";
8
+ } from "./chunk-QYZP6QT2.js";
9
+ import "./chunk-6NPMVZD7.js";
11
10
  import "./chunk-PPTKGWFF.js";
12
11
  export {
13
12
  buildChannelInstructions,
@@ -0,0 +1,25 @@
1
+ import {
2
+ readHookStdin
3
+ } from "./chunk-NIIBVKLP.js";
4
+ import {
5
+ buildSessionStartReminder
6
+ } from "./chunk-6NPMVZD7.js";
7
+
8
+ // src/hooks/session-start-hook.ts
9
+ async function runSessionStartHook() {
10
+ let source = null;
11
+ try {
12
+ ({ source } = await readHookStdin());
13
+ } catch {
14
+ }
15
+ const out = {
16
+ hookSpecificOutput: {
17
+ hookEventName: "SessionStart",
18
+ additionalContext: buildSessionStartReminder(source)
19
+ }
20
+ };
21
+ process.stdout.write(JSON.stringify(out));
22
+ }
23
+ export {
24
+ runSessionStartHook
25
+ };
@@ -3,16 +3,17 @@ import {
3
3
  pairSlotFor,
4
4
  reconcileConnectPairSlot,
5
5
  runWizard
6
- } from "./chunk-XPIW4N55.js";
7
- import "./chunk-6XWTUDWW.js";
6
+ } from "./chunk-N2YAZRAD.js";
7
+ import "./chunk-WDWVBPXA.js";
8
8
  import "./chunk-E6WMFMM2.js";
9
+ import "./chunk-GEGUWQYT.js";
10
+ import "./chunk-EIH2LNF4.js";
11
+ import "./chunk-RDLF4NQC.js";
9
12
  import {
10
13
  isWizardRuntime
11
14
  } from "./chunk-77HWBSRH.js";
12
- import "./chunk-TMCNB4JH.js";
13
15
  import "./chunk-D6JKFJ6A.js";
14
- import "./chunk-EIH2LNF4.js";
15
- import "./chunk-RDLF4NQC.js";
16
+ import "./chunk-AXBJQJKA.js";
16
17
  import "./chunk-SQL56SEB.js";
17
18
  import "./chunk-V5VZPYMZ.js";
18
19
  import {
@@ -25,8 +26,7 @@ import "./chunk-I67C2HYA.js";
25
26
  import "./chunk-MIEI4PLB.js";
26
27
  import "./chunk-6G6YYST6.js";
27
28
  import "./chunk-U5HHHRXA.js";
28
- import "./chunk-5DHIUN73.js";
29
- import "./chunk-FJUAMJHU.js";
29
+ import "./chunk-6NPMVZD7.js";
30
30
 
31
31
  // src/wizard/setup-handler.ts
32
32
  var SETUP_SUPPORTED_RUNTIMES = ["claude-code", "codex"];
@@ -1,10 +1,10 @@
1
1
  import "./chunk-XLKGPGZT.js";
2
2
  import {
3
3
  resolveHookDiscovery
4
- } from "./chunk-WBXU27BF.js";
4
+ } from "./chunk-FNMKP34Y.js";
5
5
  import {
6
6
  readHookStdin
7
- } from "./chunk-LSUB6QMP.js";
7
+ } from "./chunk-NIIBVKLP.js";
8
8
  import {
9
9
  controlTokenAuthHeaders
10
10
  } from "./chunk-GKXHKR3B.js";
@@ -14,14 +14,14 @@ import {
14
14
  import {
15
15
  monitorHeartbeatPath,
16
16
  nudgeSentinelPath
17
- } from "./chunk-TNZITJAB.js";
17
+ } from "./chunk-WVQU3QQ7.js";
18
18
  import "./chunk-67F67AQ6.js";
19
19
  import "./chunk-U5HHHRXA.js";
20
20
  import {
21
21
  buildMonitorNudge
22
- } from "./chunk-FJUAMJHU.js";
22
+ } from "./chunk-6NPMVZD7.js";
23
23
  import "./chunk-XJEBJIQE.js";
24
- import "./chunk-KNEJTD6G.js";
24
+ import "./chunk-SZLNNMIZ.js";
25
25
 
26
26
  // src/hooks/stop-hook.ts
27
27
  import fs from "fs";
@@ -0,0 +1,64 @@
1
+ // src/runtime/stream-watchdog.ts
2
+ var DEFAULT_STREAM_THRESHOLD_MS = 9e4;
3
+ var DEFAULT_STREAM_INTERVAL_MS = 15e3;
4
+ function createStreamWatchdog(opts) {
5
+ const thresholdMs = opts.thresholdMs ?? DEFAULT_STREAM_THRESHOLD_MS;
6
+ const intervalMs = opts.intervalMs ?? DEFAULT_STREAM_INTERVAL_MS;
7
+ const now = opts.now ?? Date.now;
8
+ const reArm = opts.reArmAfterUnhealthy === true;
9
+ let timer = null;
10
+ let fired = false;
11
+ let lastHealthyAt = now();
12
+ let lastSeenEventAt = null;
13
+ function stop() {
14
+ if (timer !== null) {
15
+ clearInterval(timer);
16
+ timer = null;
17
+ }
18
+ }
19
+ function check() {
20
+ if (fired) return;
21
+ let state;
22
+ try {
23
+ state = opts.getState();
24
+ } catch {
25
+ return;
26
+ }
27
+ const t = now();
28
+ const eventAdvanced = state.lastEventAt !== null && state.lastEventAt !== lastSeenEventAt;
29
+ if (state.lastEventAt !== null) lastSeenEventAt = state.lastEventAt;
30
+ if (state.connected || eventAdvanced) {
31
+ lastHealthyAt = t;
32
+ return;
33
+ }
34
+ const disconnectedForMs = t - lastHealthyAt;
35
+ if (disconnectedForMs > thresholdMs) {
36
+ fired = true;
37
+ if (!reArm) stop();
38
+ try {
39
+ opts.onUnhealthy({
40
+ disconnectedForMs,
41
+ reason: `SSE stream unhealthy for ${Math.round(disconnectedForMs / 1e3)}s (connected=false, no new events) \u2014 reconnect loop presumed wedged`
42
+ });
43
+ } catch {
44
+ }
45
+ if (reArm) {
46
+ fired = false;
47
+ lastHealthyAt = now();
48
+ }
49
+ }
50
+ }
51
+ return {
52
+ start() {
53
+ if (timer !== null || fired) return;
54
+ timer = setInterval(() => check(), intervalMs);
55
+ timer.unref?.();
56
+ },
57
+ stop
58
+ };
59
+ }
60
+ export {
61
+ DEFAULT_STREAM_INTERVAL_MS,
62
+ DEFAULT_STREAM_THRESHOLD_MS,
63
+ createStreamWatchdog
64
+ };