kojee-mcp 0.5.11 → 0.5.13

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 (37) hide show
  1. package/README.md +24 -0
  2. package/dist/ancestry-ONFBQEP5.js +8 -0
  3. package/dist/{chunk-LDZXU3DW.js → chunk-2OLXXOT3.js} +1 -0
  4. package/dist/{codex-stop-hook-SWA53ECG.js → chunk-35XBRG3V.js} +4 -3
  5. package/dist/chunk-3H3TL34J.js +401 -0
  6. package/dist/{chunk-MKDMAAMN.js → chunk-74XFVX6Z.js} +16 -4
  7. package/dist/chunk-CM3EKMDD.js +116 -0
  8. package/dist/{chunk-DS26OORG.js → chunk-CO73VGWM.js} +41 -23
  9. package/dist/{chunk-HIZ4NDWN.js → chunk-DXJ6QLSJ.js} +22 -2
  10. package/dist/{chunk-HSR3GXCL.js → chunk-IMOEZ4NJ.js} +83 -6
  11. package/dist/{chunk-2MIISF2W.js → chunk-NR4Y54OL.js} +14 -1
  12. package/dist/chunk-XLKGPGZT.js +0 -0
  13. package/dist/chunk-XXFVWP6H.js +44 -0
  14. package/dist/cli.js +17 -15
  15. package/dist/codex-stop-hook-VY7DOMAG.js +16 -0
  16. package/dist/{doctor-XK335W7B.js → doctor-FVTALRQD.js} +110 -15
  17. package/dist/{event-log-B27VVEMK.js → event-log-VZD7NKYX.js} +1 -1
  18. package/dist/event-stream-XX5EZ6HN.js +19 -0
  19. package/dist/{gateway-client-93P1E0CZ.d.ts → gateway-client-C6yx1mfM.d.ts} +6 -1
  20. package/dist/{hook-server-37E2LUKJ.js → hook-server-T2Z444OV.js} +2 -2
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +8 -7
  23. package/dist/lib.d.ts +224 -3
  24. package/dist/lib.js +16 -11
  25. package/dist/{parent-watchdog-RZLHYP7T.js → parent-watchdog-TLU355FB.js} +1 -1
  26. package/dist/registry-TGALQP6M.js +348 -0
  27. package/dist/{send-cli-CN5EX7PO.js → send-cli-RH7D4JDP.js} +18 -10
  28. package/dist/server-LBVEDIXP.js +14 -0
  29. package/dist/{stop-hook-GEJF47SN.js → stop-hook-CUVDKXP7.js} +7 -6
  30. package/dist/{tail-stream-JNR4WFW3.js → tail-stream-5DAVRQYK.js} +4 -3
  31. package/dist/{user-prompt-submit-hook-DGRRFHOB.js → user-prompt-submit-hook-PMBUPKUV.js} +5 -5
  32. package/dist/{webhook-sink-NWGCUDGY.js → webhook-sink-N6AUTFL3.js} +1 -1
  33. package/package.json +1 -1
  34. package/dist/chunk-D42PZX2I.js +0 -784
  35. package/dist/{chunk-BJMASMKX.js → chunk-VHKPWUX7.js} +0 -0
  36. package/dist/{doctor-codex-SMROUYGV.js → doctor-codex-PA3WO6LR.js} +1 -1
  37. package/dist/{wizard-PLGHYCT3.js → wizard-L4MYRLJI.js} +11 -11
@@ -3,8 +3,8 @@ import {
3
3
  httpStatusForEnvelope,
4
4
  parseSendRequest,
5
5
  sendFailure
6
- } from "./chunk-HIZ4NDWN.js";
7
- import "./chunk-LDZXU3DW.js";
6
+ } from "./chunk-DXJ6QLSJ.js";
7
+ import "./chunk-2OLXXOT3.js";
8
8
 
9
9
  // src/tandem/hook-server.ts
10
10
  import crypto from "crypto";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as GatewayClient, P as ProxyConfig } from './gateway-client-93P1E0CZ.js';
1
+ import { G as GatewayClient, P as ProxyConfig } from './gateway-client-C6yx1mfM.js';
2
2
  import 'jose';
3
3
 
4
4
  /**
package/dist/index.js CHANGED
@@ -1,17 +1,18 @@
1
1
  import {
2
2
  listTandemIds,
3
3
  startProxy
4
- } from "./chunk-D42PZX2I.js";
5
- import "./chunk-X672ZN7V.js";
6
- import "./chunk-BJMASMKX.js";
4
+ } from "./chunk-3H3TL34J.js";
5
+ import "./chunk-XXFVWP6H.js";
6
+ import "./chunk-IMOEZ4NJ.js";
7
7
  import "./chunk-JXMVZEQ7.js";
8
- import "./chunk-HSR3GXCL.js";
9
- import "./chunk-MKDMAAMN.js";
10
- import "./chunk-2MIISF2W.js";
8
+ import "./chunk-NR4Y54OL.js";
11
9
  import "./chunk-CH32ELFX.js";
12
10
  import "./chunk-BLEGIR35.js";
11
+ import "./chunk-CM3EKMDD.js";
12
+ import "./chunk-X672ZN7V.js";
13
+ import "./chunk-2OLXXOT3.js";
14
+ import "./chunk-VHKPWUX7.js";
13
15
  import "./chunk-YKW54DKF.js";
14
- import "./chunk-LDZXU3DW.js";
15
16
  export {
16
17
  listTandemIds,
17
18
  startProxy
package/dist/lib.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { KeyLike, JWK } from 'jose';
2
- import { L as LoadedKeyPair, K as KeystoreData, G as GatewayClient } from './gateway-client-93P1E0CZ.js';
3
- export { P as ProxyConfig, T as ToolCallResult } from './gateway-client-93P1E0CZ.js';
2
+ import { L as LoadedKeyPair, K as KeystoreData, G as GatewayClient, M as McpToolDefinition, T as ToolCallResult, P as ProxyConfig } from './gateway-client-C6yx1mfM.js';
4
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
4
 
6
5
  /**
@@ -271,6 +270,19 @@ interface EventStreamOptions {
271
270
  * webhook delivery, zero behavior change.
272
271
  */
273
272
  webhookSink?: WebhookSink;
273
+ /**
274
+ * Pluggable per-runtime WAKE DELIVERY (#32 Phase 1). When wired, consumeSse
275
+ * routes each normalized, wake-filtered TandemEvent through `delivery.deliver`
276
+ * INSTEAD OF the inline queue→event-log→channel→webhook fan-out below. The
277
+ * delivery owns the exact same per-sink isolation + ordering; this is purely
278
+ * WHERE the fan-out lives, not WHAT it does. When UNSET (the kojee-mcp/lib
279
+ * consumers — the OpenClaw plugin — and the event-stream unit/integration
280
+ * tests that pass `queue`/`eventLog`/`webhookSink` directly), the historical
281
+ * inline fan-out runs unchanged. The two paths are behaviorally identical.
282
+ */
283
+ delivery?: {
284
+ deliver(event: TandemEvent): Promise<void>;
285
+ };
274
286
  /**
275
287
  * Resubscribe-on-start hook (P0 audit item #2). Called once after each
276
288
  * successful (re)connect with the live `Response`. Implementations touch
@@ -426,4 +438,213 @@ interface ResubscribeOptions {
426
438
  */
427
439
  declare function resubscribeMemberships(opts: ResubscribeOptions): Promise<number>;
428
440
 
429
- export { AuthModule, type EventLog, type EventStreamOptions, GatewayClient, type HarnessAdapter, type PairedConfig, type Runtime, type StreamHandle, type StreamState, type TandemEvent, type WebhookSink, createDPoPProof, defaultPairedKeystorePath, deriveKeystorePath, generateES256KeyPair, loadKeystore, loadPairedConfig, normalizeBackendEvent, pairedConfigPath, resubscribeMemberships, sanitizeDisplayname, saveKeystore, startEventStream };
441
+ interface StableSessionDeps {
442
+ /**
443
+ * The Claude Code ancestor PID, when the caller already has it (the daemon).
444
+ * Pass `null` to SKIP the ancestry read (non-CC contexts, tests) — resolution
445
+ * then falls to KOJEE_INSTANCE → working-dir hash. Omit to resolve ancestry.
446
+ */
447
+ ccPid?: number | null;
448
+ /**
449
+ * An explicit instanceKey — bypasses ancestry AND resolveInstanceKey entirely.
450
+ * Used where the window identity is known out-of-band (an embedder's account
451
+ * key, tests).
452
+ */
453
+ instanceKey?: string;
454
+ }
455
+ /**
456
+ * §7 — install the STABLE Mcp-Session-Id (D1) for THIS process, the one DRY way
457
+ * every outbound construction site does it: the daemon (index.ts), the `send`
458
+ * sub-command, and embedding plugins (OpenClaw). Same (token, instanceKey) →
459
+ * same id → the backend converges on ONE seat per (credential, window) across
460
+ * restarts (no phantom seats; reaper retired).
461
+ *
462
+ * instanceKey precedence: an explicit `deps.instanceKey` wins; otherwise it's
463
+ * resolved by {@link resolveInstanceKey} from `deps.ccPid` (or a fresh ancestry
464
+ * read when `ccPid` is omitted) → CC session id, else KOJEE_INSTANCE, else a
465
+ * working-dir hash.
466
+ *
467
+ * Returns the resolved instanceKey + the installed sessionId so callers that
468
+ * also need the key (room-memory, discovery) don't resolve it twice.
469
+ */
470
+ declare function applyStableSessionId(token: string, deps?: StableSessionDeps): Promise<{
471
+ instanceKey: string;
472
+ sessionId: string;
473
+ }>;
474
+
475
+ /**
476
+ * D1 — the STABLE Mcp-Session-Id: deterministic per (token, instanceKey),
477
+ * one-way + opaque. Same inputs → same id across proxy restarts, so the backend
478
+ * resolves the SAME Session + seat (no phantom seats, reaper retired). Computed
479
+ * at proxy startup where the gateway token + instanceKey (resolveInstanceKey)
480
+ * are known, in place of the random ulid() above.
481
+ */
482
+ declare function deriveStableSessionId(token: string, instanceKey: string): string;
483
+
484
+ /**
485
+ * Flat tool registry — fetches all Kojee tools with full schemas on startup
486
+ * and registers them directly with the MCP server. No discovery indirection,
487
+ * no meta-tools, no call_tool wrapper.
488
+ *
489
+ * The agent sees each Kojee tool directly (e.g. gmail_send_email, github_list_repos)
490
+ * and calls it like any native MCP tool. Prompt caching handles the token cost
491
+ * of ~15K tokens after the first turn.
492
+ */
493
+ declare class ToolRegistry {
494
+ private readonly gateway;
495
+ /** Flat map: tool name → full tool definition */
496
+ private tools;
497
+ constructor(gateway: GatewayClient);
498
+ /**
499
+ * Fetch all tools with full schemas from the gateway in a single RPC call.
500
+ */
501
+ discoverTools(): Promise<void>;
502
+ /**
503
+ * Return all registered tools for the MCP ListTools response.
504
+ */
505
+ getAllTools(): McpToolDefinition[];
506
+ /**
507
+ * Call a tool through the gateway.
508
+ */
509
+ callTool(name: string, args: Record<string, unknown>): Promise<ToolCallResult>;
510
+ /** Total number of registered tools. */
511
+ get toolCount(): number;
512
+ }
513
+
514
+ /**
515
+ * Side-channel hooks observed by the tool-call path (0.5.4 wake continuity).
516
+ */
517
+ interface ToolCallHooks {
518
+ /**
519
+ * Fired after a SUCCESSFUL tandem_join performed through this proxy by its
520
+ * agent, with the joined tandem id (null if it couldn't be read from args).
521
+ * The proxy wires this to the debounced stream-reconnect scheduler so the
522
+ * event-stream's membership snapshot picks up the just-acquired seat without
523
+ * a daemon restart, AND (#28) records the room in this instance's local
524
+ * room-memory for session-faithful re-seat. A throwing hook never breaks the
525
+ * tool reply.
526
+ */
527
+ onTandemJoin?: (tandemId: string | null) => void;
528
+ /**
529
+ * Fired after a SUCCESSFUL tandem_leave through this proxy, with the left
530
+ * tandem id (#28). The proxy drops the room from this instance's local
531
+ * room-memory so a restart doesn't rejoin a room the agent deliberately
532
+ * left. A throwing hook never breaks the tool reply.
533
+ */
534
+ onTandemLeave?: (tandemId: string | null) => void;
535
+ }
536
+
537
+ /**
538
+ * The pluggable per-runtime WAKE-DELIVERY interface (#32 Phase 1).
539
+ *
540
+ * Historically the dispatch of a normalized TandemEvent to its wake sinks lived
541
+ * in two places: the THREE-WAY branch in `startProxy` (src/index.ts) that wired
542
+ * the event-log / webhook / hook-server / discovery surfaces per runtime, and
543
+ * the inline fan-out in `consumeSse` (src/tandem/event-stream.ts) that, per
544
+ * event, appended to the event log (Monitor wake), emitted a channel
545
+ * notification (claude-code only), and enqueued the webhook POST.
546
+ *
547
+ * Phase 1 extracts that into one interface so each runtime owns its own wake
548
+ * delivery as a composable unit, selected from a registry instead of an
549
+ * if/else-if/else ladder. The extraction is BEHAVIOR-PRESERVING: each runtime's
550
+ * `start`/`deliver`/`stop` replicate exactly what its branch did before.
551
+ *
552
+ * - start(ctx) — build + start this runtime's sinks/surfaces and the SSE
553
+ * stream. Returns the wired MCP `server` (so the proxy can
554
+ * drive the stdio transport) plus a stop handle.
555
+ * - deliver(event) — the per-event fan-out, formerly inlined in consumeSse
556
+ * (event-stream.ts:594-642). MUST preserve per-sink
557
+ * isolation + ordering: event-log append (primary Monitor
558
+ * wake) FIRST, channel notification SECOND (claude-code
559
+ * only), webhook enqueue LAST + fire-and-forget. Each sink
560
+ * is wrapped in its own try/catch so one failing sink can
561
+ * never starve another.
562
+ * - stop() — idempotent teardown (webhook sink stop, discovery
563
+ * cleanup, event-log cleanup, hook-server stop).
564
+ * - health() — optional liveness snapshot for GET /status + doctor.
565
+ */
566
+
567
+ /**
568
+ * Everything a {@link WakeDelivery.start} needs from the proxy to build its
569
+ * sinks/surfaces and wire the SSE stream. Assembled once in `startProxy` after
570
+ * auth + ensure-join, before the stream connects.
571
+ */
572
+ interface WakeDeliveryContext {
573
+ /**
574
+ * This instance's stable key (#28): the CC session_id when readable, else
575
+ * KOJEE_INSTANCE / a working-dir hash. Used to derive the per-runtime
576
+ * event-log filename and other per-session artifacts.
577
+ */
578
+ instanceKey: string;
579
+ /** The detected runtime label (drives capability + which delivery is built). */
580
+ runtime: Runtime;
581
+ /** The selected harness adapter (channel capability + formatTandemEvent). */
582
+ adapter: HarnessAdapter;
583
+ /** Directory the event log lives in (defaults to os.tmpdir()). */
584
+ eventLogDir?: string;
585
+ /** Resolved proxy config (broker url + token + auth mode). */
586
+ config: ProxyConfig;
587
+ /** The discovered tool registry (used to build the MCP server). */
588
+ registry: ToolRegistry;
589
+ /** The authenticated gateway JSON-RPC client. */
590
+ gateway: GatewayClient;
591
+ /** The Claude Code ancestor pid, or null if none was found. */
592
+ ccPid: number | null;
593
+ /** Boot-probed membership count for the handshake instructions (-1 = unknown). */
594
+ tandemMembershipCount: number;
595
+ /** tandem_id lister for the resubscribe-on-connect touch. */
596
+ listTandemIds: () => Promise<string[] | null>;
597
+ /** join/leave side-channel hooks (stream reconnect + room-memory record). */
598
+ toolCallHooks: ToolCallHooks;
599
+ /** Called once the stream handle is armed, to flush a boot-race reconnect. */
600
+ onStreamReady?: (handle: StreamLike) => void;
601
+ /** Best-effort line sink for boot/observability logs (status sibling backed). */
602
+ log: (line: string) => void;
603
+ }
604
+ /** The subset of the SSE stream handle the proxy + scheduler depend on. */
605
+ interface StreamLike {
606
+ (): void;
607
+ reconnect: () => void;
608
+ getState: () => unknown;
609
+ }
610
+ /** Optional liveness snapshot surfaced via GET /status + doctor. */
611
+ interface DeliveryHealth {
612
+ /** Whether the SSE stream is currently connected (null = no stream). */
613
+ connected: boolean | null;
614
+ /** Implementation-specific extra state (stream state, hook-server, etc.). */
615
+ detail?: Record<string, unknown>;
616
+ }
617
+ /** The result of {@link WakeDelivery.start}: the wired server + teardown. */
618
+ interface StartedDelivery {
619
+ /** The MCP server to drive over stdio. */
620
+ server: Server;
621
+ /** Synchronous teardown steps to register with the shutdown coordinator. */
622
+ teardown: Array<() => void | Promise<void>>;
623
+ /** Last-ditch synchronous cleanup for process 'exit' (cannot await). */
624
+ exitCleanup?: () => void;
625
+ }
626
+ /**
627
+ * A per-runtime wake-delivery unit. Built from the registry, started once, and
628
+ * driven per-event by consumeSse via {@link WakeDelivery.deliver}.
629
+ */
630
+ interface WakeDelivery {
631
+ /** Stable identifier (the runtime label + variant, e.g. "claude-code"). */
632
+ readonly name: string;
633
+ /**
634
+ * Build + start this delivery's sinks/surfaces and the SSE stream. The stream
635
+ * is wired so consumeSse calls back into {@link WakeDelivery.deliver}.
636
+ */
637
+ start(ctx: WakeDeliveryContext): Promise<StartedDelivery>;
638
+ /**
639
+ * Per-event fan-out (the seam formerly inlined in consumeSse). Called for
640
+ * every normalized, wake-filtered TandemEvent. MUST preserve per-sink
641
+ * isolation + ordering and never throw.
642
+ */
643
+ deliver(event: TandemEvent): Promise<void>;
644
+ /** Idempotent teardown. */
645
+ stop(): Promise<void>;
646
+ /** Optional liveness snapshot. */
647
+ health?(): DeliveryHealth;
648
+ }
649
+
650
+ export { AuthModule, type DeliveryHealth, type EventLog, type EventStreamOptions, GatewayClient, type HarnessAdapter, type PairedConfig, ProxyConfig, type Runtime, type StableSessionDeps, type StartedDelivery, type StreamHandle, type StreamLike, type StreamState, type TandemEvent, ToolCallResult, type WakeDelivery, type WakeDeliveryContext, type WebhookSink, applyStableSessionId, createDPoPProof, defaultPairedKeystorePath, deriveKeystorePath, deriveStableSessionId, generateES256KeyPair, loadKeystore, loadPairedConfig, normalizeBackendEvent, pairedConfigPath, resubscribeMemberships, sanitizeDisplayname, saveKeystore, startEventStream };
package/dist/lib.js CHANGED
@@ -1,24 +1,26 @@
1
1
  import {
2
2
  resubscribeMemberships
3
3
  } from "./chunk-OT2GILXC.js";
4
+ import {
5
+ normalizeBackendEvent,
6
+ sanitizeDisplayname,
7
+ startEventStream
8
+ } from "./chunk-74XFVX6Z.js";
4
9
  import {
5
10
  loadPairedConfig,
6
11
  pairedConfigPath
7
12
  } from "./chunk-YH27B6SW.js";
13
+ import {
14
+ GatewayClient,
15
+ applyStableSessionId
16
+ } from "./chunk-IMOEZ4NJ.js";
8
17
  import {
9
18
  AuthModule
10
19
  } from "./chunk-JXMVZEQ7.js";
11
20
  import {
12
- GatewayClient
13
- } from "./chunk-HSR3GXCL.js";
14
- import {
15
- normalizeBackendEvent,
16
- sanitizeDisplayname,
17
- startEventStream
18
- } from "./chunk-MKDMAAMN.js";
19
- import {
20
- createDPoPProof
21
- } from "./chunk-2MIISF2W.js";
21
+ createDPoPProof,
22
+ deriveStableSessionId
23
+ } from "./chunk-NR4Y54OL.js";
22
24
  import {
23
25
  defaultPairedKeystorePath,
24
26
  deriveKeystorePath,
@@ -27,13 +29,16 @@ import {
27
29
  saveKeystore
28
30
  } from "./chunk-CH32ELFX.js";
29
31
  import "./chunk-BLEGIR35.js";
30
- import "./chunk-LDZXU3DW.js";
32
+ import "./chunk-2OLXXOT3.js";
33
+ import "./chunk-VHKPWUX7.js";
31
34
  export {
32
35
  AuthModule,
33
36
  GatewayClient,
37
+ applyStableSessionId,
34
38
  createDPoPProof,
35
39
  defaultPairedKeystorePath,
36
40
  deriveKeystorePath,
41
+ deriveStableSessionId,
37
42
  generateES256KeyPair,
38
43
  loadKeystore,
39
44
  loadPairedConfig,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  findClaudeAncestorPid
3
- } from "./chunk-BJMASMKX.js";
3
+ } from "./chunk-VHKPWUX7.js";
4
4
 
5
5
  // src/runtime/parent-watchdog.ts
6
6
  function defaultIsPidAlive(pid) {