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,11 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
createCachedOpenclawWakeResolver,
|
|
3
|
+
postOpenclawWake
|
|
4
|
+
} from "./chunk-NE2F5CKS.js";
|
|
2
5
|
import "./chunk-PHXO5P25.js";
|
|
3
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
codexPendingMarkerPath
|
|
8
|
+
} from "./chunk-WIU5WGDF.js";
|
|
4
9
|
import {
|
|
5
10
|
claudeCodeAdapter
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-OB5T6P24.js";
|
|
12
|
+
import "./chunk-SGRVG4HW.js";
|
|
13
|
+
import "./chunk-QEJUNP3X.js";
|
|
9
14
|
import "./chunk-PPTKGWFF.js";
|
|
10
15
|
|
|
11
16
|
// src/delivery/lib/fanout.ts
|
|
@@ -36,6 +41,18 @@ async function deliverEvent(event, sinks) {
|
|
|
36
41
|
} catch (err) {
|
|
37
42
|
console.error("[event-stream] webhook enqueue failed:", err);
|
|
38
43
|
}
|
|
44
|
+
if (sinks.codexPendingMarker) {
|
|
45
|
+
try {
|
|
46
|
+
const pending = sinks.codexPendingMarker(event);
|
|
47
|
+
if (pending && typeof pending.then === "function") {
|
|
48
|
+
pending.catch((err) => {
|
|
49
|
+
console.error("[event-stream] codex pending-marker write failed:", err);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error("[event-stream] codex pending-marker write failed:", err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
39
56
|
}
|
|
40
57
|
|
|
41
58
|
// src/delivery/lib/channel.ts
|
|
@@ -96,20 +113,27 @@ function createClaudeCodeDelivery() {
|
|
|
96
113
|
writeDiscoveryByKey,
|
|
97
114
|
cleanupDiscoveryByKey,
|
|
98
115
|
sweepStaleDiscovery
|
|
99
|
-
} = await import("./session-discovery-
|
|
100
|
-
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-
|
|
116
|
+
} = await import("./session-discovery-NHCZ2XWA.js");
|
|
117
|
+
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-2NBJEIEP.js");
|
|
101
118
|
const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
|
|
102
119
|
const { resolveWebhookConfig } = await import("./webhook-config-O4WMQ532.js");
|
|
103
120
|
const { createWebhookSink } = await import("./webhook-sink-N6AUTFL3.js");
|
|
104
|
-
const { startEventStream } = await import("./event-stream-
|
|
105
|
-
const { createMcpServer } = await import("./server-
|
|
106
|
-
const { deriveDiscoveryKey } = await import("./ancestry-
|
|
121
|
+
const { startEventStream } = await import("./event-stream-KRYWEYWO.js");
|
|
122
|
+
const { createMcpServer } = await import("./server-YTHOMA4H.js");
|
|
123
|
+
const { deriveDiscoveryKey } = await import("./ancestry-A2F5KQ6A.js");
|
|
124
|
+
const { resolveSharedSessionId } = await import("./cc-session-id-RURNIHHC.js");
|
|
107
125
|
sweepStaleDiscovery();
|
|
108
126
|
sweepStaleEventLogs();
|
|
109
127
|
const projectDir = process.env["CLAUDE_PROJECT_DIR"];
|
|
110
|
-
const
|
|
128
|
+
const sessionId = resolveSharedSessionId();
|
|
129
|
+
const discoveryKey = deriveDiscoveryKey(projectDir, ctx.ccPid, sessionId);
|
|
111
130
|
eventLog = startEventLog({
|
|
112
131
|
key: ctx.instanceKey,
|
|
132
|
+
// The proxy's OWN discovery key: lets startEventLog reclaim the STABLE
|
|
133
|
+
// base log path on an in-session reconnect (env-switch / /mcp reconnect;
|
|
134
|
+
// unchanged ccPid → unchanged discovery key) instead of salting and
|
|
135
|
+
// stranding the agent's already-running Monitor on the dead base log.
|
|
136
|
+
selfKey: discoveryKey,
|
|
113
137
|
...ctx.eventLogDir ? { dir: ctx.eventLogDir } : {}
|
|
114
138
|
});
|
|
115
139
|
const log = eventLog;
|
|
@@ -142,7 +166,7 @@ function createClaudeCodeDelivery() {
|
|
|
142
166
|
eventLog.path,
|
|
143
167
|
ctx.toolCallHooks
|
|
144
168
|
);
|
|
145
|
-
const { issueControlToken, controlTokenPath } = await import("./control-token-
|
|
169
|
+
const { issueControlToken, controlTokenPath } = await import("./control-token-KXSZ3GBY.js");
|
|
146
170
|
let controlToken = null;
|
|
147
171
|
try {
|
|
148
172
|
controlToken = issueControlToken();
|
|
@@ -174,7 +198,7 @@ function createClaudeCodeDelivery() {
|
|
|
174
198
|
staleAfterMs: null
|
|
175
199
|
}
|
|
176
200
|
});
|
|
177
|
-
|
|
201
|
+
const discoveryEntry = {
|
|
178
202
|
schema: 2,
|
|
179
203
|
discoveryKey,
|
|
180
204
|
ccPid: ctx.ccPid,
|
|
@@ -187,8 +211,18 @@ function createClaudeCodeDelivery() {
|
|
|
187
211
|
eventLogPath: eventLog.path,
|
|
188
212
|
...controlToken !== null ? { controlTokenPath: controlTokenPath() } : {},
|
|
189
213
|
authMode: ctx.config.authMode ?? "paired"
|
|
190
|
-
}
|
|
191
|
-
|
|
214
|
+
};
|
|
215
|
+
writeDiscoveryByKey(discoveryKey, discoveryEntry);
|
|
216
|
+
const aliasKey = sessionId && ctx.ccPid !== null ? deriveDiscoveryKey(projectDir, ctx.ccPid, null) : null;
|
|
217
|
+
if (aliasKey !== null && aliasKey !== discoveryKey) {
|
|
218
|
+
writeDiscoveryByKey(aliasKey, { ...discoveryEntry, discoveryKey: aliasKey });
|
|
219
|
+
}
|
|
220
|
+
cleanupDiscoveryFile = () => {
|
|
221
|
+
cleanupDiscoveryByKey(discoveryKey);
|
|
222
|
+
if (aliasKey !== null && aliasKey !== discoveryKey) {
|
|
223
|
+
cleanupDiscoveryByKey(aliasKey);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
192
226
|
const localCleanupDiscovery = cleanupDiscoveryFile;
|
|
193
227
|
const localHookServer = hookServer;
|
|
194
228
|
const localLiveliness = liveliness;
|
|
@@ -267,19 +301,19 @@ function createClaudeCodeDelivery() {
|
|
|
267
301
|
}
|
|
268
302
|
|
|
269
303
|
// src/delivery/hermes.ts
|
|
270
|
-
function createWebhookDelivery(name) {
|
|
304
|
+
function createWebhookDelivery(name, codexPendingMarker) {
|
|
271
305
|
let eventLog = null;
|
|
272
306
|
let webhookSink = null;
|
|
273
307
|
let streamHandle = null;
|
|
274
308
|
return {
|
|
275
309
|
name,
|
|
276
310
|
async start(ctx) {
|
|
277
|
-
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-
|
|
311
|
+
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-2NBJEIEP.js");
|
|
278
312
|
const { resolveWebhookConfig } = await import("./webhook-config-O4WMQ532.js");
|
|
279
313
|
const { createWebhookSink } = await import("./webhook-sink-N6AUTFL3.js");
|
|
280
314
|
const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
|
|
281
|
-
const { startEventStream } = await import("./event-stream-
|
|
282
|
-
const { createMcpServer } = await import("./server-
|
|
315
|
+
const { startEventStream } = await import("./event-stream-KRYWEYWO.js");
|
|
316
|
+
const { createMcpServer } = await import("./server-YTHOMA4H.js");
|
|
283
317
|
sweepStaleEventLogs();
|
|
284
318
|
eventLog = startEventLog({
|
|
285
319
|
key: ctx.instanceKey,
|
|
@@ -348,7 +382,9 @@ function createWebhookDelivery(name) {
|
|
|
348
382
|
async deliver(event) {
|
|
349
383
|
await deliverEvent(event, {
|
|
350
384
|
...eventLog ? { eventLog } : {},
|
|
351
|
-
...webhookSink ? { webhookSink } : {}
|
|
385
|
+
...webhookSink ? { webhookSink } : {},
|
|
386
|
+
// OPTIONAL codex-only marker sink (undefined ⇒ byte-identical hermes path).
|
|
387
|
+
...codexPendingMarker ? { codexPendingMarker } : {}
|
|
352
388
|
});
|
|
353
389
|
},
|
|
354
390
|
async stop() {
|
|
@@ -365,9 +401,139 @@ function createWebhookDelivery(name) {
|
|
|
365
401
|
};
|
|
366
402
|
}
|
|
367
403
|
|
|
404
|
+
// src/delivery/codex-pending-marker.ts
|
|
405
|
+
import fsp from "fs/promises";
|
|
406
|
+
import path from "path";
|
|
407
|
+
import crypto from "crypto";
|
|
408
|
+
var MAX_MARKER_BODY_CHARS = 32;
|
|
409
|
+
var ensuredDir = null;
|
|
410
|
+
async function writeCodexPendingMarker(event) {
|
|
411
|
+
const markerPath = codexPendingMarkerPath();
|
|
412
|
+
const dir = path.dirname(markerPath);
|
|
413
|
+
const tmp = `${markerPath}.tmp-${process.pid}-${crypto.randomUUID()}`;
|
|
414
|
+
try {
|
|
415
|
+
if (ensuredDir !== dir) {
|
|
416
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
417
|
+
ensuredDir = dir;
|
|
418
|
+
}
|
|
419
|
+
const body = String(event.cursor ?? 0).slice(0, MAX_MARKER_BODY_CHARS);
|
|
420
|
+
await fsp.writeFile(tmp, body, { mode: 384 });
|
|
421
|
+
await fsp.rename(tmp, markerPath);
|
|
422
|
+
} catch {
|
|
423
|
+
ensuredDir = null;
|
|
424
|
+
try {
|
|
425
|
+
await fsp.unlink(tmp);
|
|
426
|
+
} catch {
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
368
431
|
// src/delivery/codex.ts
|
|
369
432
|
function createCodexDelivery() {
|
|
370
|
-
return createWebhookDelivery("codex");
|
|
433
|
+
return createWebhookDelivery("codex", writeCodexPendingMarker);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/delivery/openclaw.ts
|
|
437
|
+
function formatOpenclawNudge(event) {
|
|
438
|
+
const who = event.from?.member_id ?? "someone";
|
|
439
|
+
const body = (event.content?.body ?? "").replace(/\s+/g, " ").slice(0, 160);
|
|
440
|
+
return `New Kojee Tandem activity in ${event.tandem_id} from ${who}: "${body}". Catch up with tandem_messages / tandem_listen and reply via tandem_send.`;
|
|
441
|
+
}
|
|
442
|
+
function createOpenclawDelivery(deps = {}) {
|
|
443
|
+
const resolveTarget = deps.resolveTarget ?? createCachedOpenclawWakeResolver();
|
|
444
|
+
const postWake = deps.postWake ?? postOpenclawWake;
|
|
445
|
+
let eventLog = null;
|
|
446
|
+
let streamHandle = null;
|
|
447
|
+
let warnedUnconfigured = false;
|
|
448
|
+
return {
|
|
449
|
+
name: "openclaw",
|
|
450
|
+
async start(ctx) {
|
|
451
|
+
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-2NBJEIEP.js");
|
|
452
|
+
const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
|
|
453
|
+
const { startEventStream } = await import("./event-stream-KRYWEYWO.js");
|
|
454
|
+
const { createMcpServer } = await import("./server-YTHOMA4H.js");
|
|
455
|
+
sweepStaleEventLogs();
|
|
456
|
+
eventLog = startEventLog({
|
|
457
|
+
key: ctx.instanceKey,
|
|
458
|
+
...ctx.eventLogDir ? { dir: ctx.eventLogDir } : {}
|
|
459
|
+
});
|
|
460
|
+
const log = eventLog;
|
|
461
|
+
const initial = await resolveTarget();
|
|
462
|
+
void log.appendStatus(
|
|
463
|
+
`status=openclaw-wake ${initial.ok ? `target=${initial.target.url}` : `error="${initial.reason}"`}`
|
|
464
|
+
).catch(() => {
|
|
465
|
+
});
|
|
466
|
+
const server = createMcpServer(
|
|
467
|
+
ctx.registry,
|
|
468
|
+
ctx.adapter,
|
|
469
|
+
ctx.tandemMembershipCount,
|
|
470
|
+
void 0,
|
|
471
|
+
ctx.toolCallHooks
|
|
472
|
+
);
|
|
473
|
+
const teardown = [() => eventLog?.cleanup()];
|
|
474
|
+
streamHandle = await startEventStream({
|
|
475
|
+
brokerUrl: ctx.config.url,
|
|
476
|
+
token: ctx.config.token,
|
|
477
|
+
gateway: ctx.gateway,
|
|
478
|
+
adapter: ctx.adapter,
|
|
479
|
+
server,
|
|
480
|
+
eventLog,
|
|
481
|
+
delivery: this,
|
|
482
|
+
onConnected: /* @__PURE__ */ (() => {
|
|
483
|
+
const debounceState = { lastRunAt: 0 };
|
|
484
|
+
return async () => {
|
|
485
|
+
await resubscribeMemberships({
|
|
486
|
+
gateway: ctx.gateway,
|
|
487
|
+
eventLog,
|
|
488
|
+
listTandems: async () => await ctx.listTandemIds() ?? [],
|
|
489
|
+
debounceState
|
|
490
|
+
});
|
|
491
|
+
};
|
|
492
|
+
})()
|
|
493
|
+
});
|
|
494
|
+
ctx.onStreamReady?.(streamHandle);
|
|
495
|
+
return { server, teardown, exitCleanup: () => eventLog?.cleanup() };
|
|
496
|
+
},
|
|
497
|
+
// Event-log append FIRST (survival/observability parity with hermes; the
|
|
498
|
+
// Monitor's PRIMARY wake path, so it is AWAITED like fanout's eventLog sink).
|
|
499
|
+
// The /wake POST is FIRE-AND-FORGET: it is network I/O with a 4s timeout and
|
|
500
|
+
// must NOT be awaited on the shared consumeSse loop — a gateway that accepts
|
|
501
|
+
// TCP but hangs would otherwise backpressure the single interleaved stream
|
|
502
|
+
// for every room (hermes/codex enqueue their network/disk sinks the same way,
|
|
503
|
+
// fanout.ts). Target RESOLUTION rides the same detached chain (F5): it is
|
|
504
|
+
// disk I/O (openclaw.json read — async + mtime-cached by the default
|
|
505
|
+
// resolver), and a stalled home dir (NFS, AV scan, full disk) must never
|
|
506
|
+
// block the reader loop that multiplexes tool-call proxying for every room.
|
|
507
|
+
async deliver(event) {
|
|
508
|
+
try {
|
|
509
|
+
await eventLog?.append(event);
|
|
510
|
+
} catch (err) {
|
|
511
|
+
console.error("[openclaw] event-log append failed:", err);
|
|
512
|
+
}
|
|
513
|
+
void (async () => {
|
|
514
|
+
const r = await resolveTarget();
|
|
515
|
+
if (!r.ok) {
|
|
516
|
+
if (!warnedUnconfigured) {
|
|
517
|
+
warnedUnconfigured = true;
|
|
518
|
+
console.error(`[openclaw] wake skipped: ${r.reason}`);
|
|
519
|
+
}
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
warnedUnconfigured = false;
|
|
523
|
+
const res = await postWake(r.target, { text: formatOpenclawNudge(event), mode: "now" });
|
|
524
|
+
if (!res.ok) console.error(`[openclaw] wake POST failed: ${res.error ?? res.status}`);
|
|
525
|
+
})().catch((err) => {
|
|
526
|
+
console.error("[openclaw] wake delivery failed:", err);
|
|
527
|
+
});
|
|
528
|
+
},
|
|
529
|
+
async stop() {
|
|
530
|
+
eventLog?.cleanup();
|
|
531
|
+
},
|
|
532
|
+
health() {
|
|
533
|
+
const s = streamHandle?.getState();
|
|
534
|
+
return { connected: s ? s.connected ?? null : null, ...s ? { detail: { stream: s } } : {} };
|
|
535
|
+
}
|
|
536
|
+
};
|
|
371
537
|
}
|
|
372
538
|
|
|
373
539
|
// src/delivery/registry.ts
|
|
@@ -378,12 +544,15 @@ function selectDelivery(runtime, opts) {
|
|
|
378
544
|
if (opts.supportsChannels) {
|
|
379
545
|
return createClaudeCodeDelivery();
|
|
380
546
|
}
|
|
381
|
-
if (!needsWebhookEventStream(opts.env)) {
|
|
382
|
-
return null;
|
|
383
|
-
}
|
|
384
547
|
if (runtime === "codex") {
|
|
385
548
|
return createCodexDelivery();
|
|
386
549
|
}
|
|
550
|
+
if (runtime === "openclaw") {
|
|
551
|
+
return createOpenclawDelivery();
|
|
552
|
+
}
|
|
553
|
+
if (!needsWebhookEventStream(opts.env)) {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
387
556
|
return createWebhookDelivery(runtime);
|
|
388
557
|
}
|
|
389
558
|
export {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CONNECT_RUNTIMES,
|
|
3
|
+
resolveLaunchCreds,
|
|
4
|
+
resolvePairedSlot
|
|
5
|
+
} from "./chunk-EIH2LNF4.js";
|
|
6
|
+
import "./chunk-5SZHXYPK.js";
|
|
7
|
+
import "./chunk-6G6YYST6.js";
|
|
8
|
+
import "./chunk-U5HHHRXA.js";
|
|
9
|
+
export {
|
|
10
|
+
CONNECT_RUNTIMES,
|
|
11
|
+
resolveLaunchCreds,
|
|
12
|
+
resolvePairedSlot
|
|
13
|
+
};
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
readRecordedRuntime,
|
|
4
4
|
recordRuntime,
|
|
5
5
|
runtimeRecordPath
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RDLF4NQC.js";
|
|
7
7
|
import "./chunk-SQL56SEB.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-U5HHHRXA.js";
|
|
9
9
|
export {
|
|
10
10
|
clearRuntimeRecord,
|
|
11
11
|
readRecordedRuntime,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolvePairedSlot
|
|
3
|
+
} from "./chunk-EIH2LNF4.js";
|
|
1
4
|
import {
|
|
2
5
|
executeJoin,
|
|
3
6
|
executeSend,
|
|
@@ -6,38 +9,47 @@ import {
|
|
|
6
9
|
} from "./chunk-PKOBR7ZN.js";
|
|
7
10
|
import {
|
|
8
11
|
loadPairedConfig
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5SZHXYPK.js";
|
|
10
13
|
import {
|
|
11
14
|
GatewayClient,
|
|
12
15
|
applyStableSessionId
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-247WFMCJ.js";
|
|
17
|
+
import "./chunk-Z5LPNJQ6.js";
|
|
18
|
+
import "./chunk-MIEI4PLB.js";
|
|
15
19
|
import {
|
|
20
|
+
deriveKeystorePath,
|
|
16
21
|
loadKeystore
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-6G6YYST6.js";
|
|
23
|
+
import "./chunk-U5HHHRXA.js";
|
|
19
24
|
import "./chunk-PPTKGWFF.js";
|
|
25
|
+
import "./chunk-KNEJTD6G.js";
|
|
20
26
|
|
|
21
27
|
// src/tandem/send-cli.ts
|
|
22
28
|
import os from "os";
|
|
23
29
|
import path from "path";
|
|
24
|
-
async function createPairedGateway(kojeeDir, stableDeps = {}) {
|
|
25
|
-
const
|
|
30
|
+
async function createPairedGateway(kojeeDir, stableDeps = {}, slot = {}) {
|
|
31
|
+
const resolvedRuntime = slot.runtime ?? process.env["KOJEE_RUNTIME"];
|
|
32
|
+
const resolution = resolvePairedSlot({
|
|
33
|
+
...slot.pairedConfig ? { pairedConfig: slot.pairedConfig } : {},
|
|
34
|
+
...resolvedRuntime ? { runtime: resolvedRuntime } : {},
|
|
35
|
+
kojeeDir
|
|
36
|
+
});
|
|
37
|
+
const configPath = resolution.configPath;
|
|
26
38
|
const paired = loadPairedConfig(configPath);
|
|
27
39
|
if (!paired) {
|
|
28
40
|
return sendFailure(
|
|
29
41
|
"not_paired",
|
|
30
|
-
`no paired config at ${configPath} \u2014 run \`kojee-mcp
|
|
42
|
+
`no paired config at ${configPath} \u2014 run \`kojee-mcp connect <code> --runtime <id>\` first`
|
|
31
43
|
);
|
|
32
44
|
}
|
|
33
45
|
await applyStableSessionId(paired.token, stableDeps);
|
|
34
46
|
const brokerUrl = paired.broker_url.replace(/\/+$/, "");
|
|
35
|
-
const keystorePath = path.join(kojeeDir, "keypair.json");
|
|
47
|
+
const keystorePath = resolution.scope === "paired" ? deriveKeystorePath(paired.token) : path.join(kojeeDir, "keypair.json");
|
|
36
48
|
const keystore = await loadKeystore(keystorePath, brokerUrl).catch(() => null);
|
|
37
49
|
if (!keystore) {
|
|
38
50
|
return sendFailure(
|
|
39
51
|
"not_enrolled",
|
|
40
|
-
`no DPoP keystore for ${brokerUrl} at ${keystorePath} \u2014 start the proxy once (or re-run \`kojee-mcp
|
|
52
|
+
`no DPoP keystore for ${brokerUrl} at ${keystorePath} \u2014 start the proxy once (or re-run \`kojee-mcp connect\`) to enroll a keypair`
|
|
41
53
|
);
|
|
42
54
|
}
|
|
43
55
|
const sessionId = GatewayClient.deriveSessionId(paired.token);
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildChannelInstructions,
|
|
3
|
+
buildNonChannelInstructions,
|
|
3
4
|
createMcpServer,
|
|
4
5
|
executeToolCall,
|
|
5
6
|
startMcpServer
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-SGRVG4HW.js";
|
|
8
|
+
import "./chunk-QEJUNP3X.js";
|
|
8
9
|
import "./chunk-PPTKGWFF.js";
|
|
9
10
|
export {
|
|
10
11
|
buildChannelInstructions,
|
|
12
|
+
buildNonChannelInstructions,
|
|
11
13
|
createMcpServer,
|
|
12
14
|
executeToolCall,
|
|
13
15
|
startMcpServer
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
sweepStaleDiscovery,
|
|
11
11
|
writeDiscoveryByKey,
|
|
12
12
|
writeSessionDiscovery
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-67F67AQ6.js";
|
|
14
|
+
import "./chunk-U5HHHRXA.js";
|
|
15
15
|
export {
|
|
16
16
|
cleanupDiscoveryByKey,
|
|
17
17
|
cleanupSessionDiscovery,
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_BROKER_URL,
|
|
3
|
+
pairSlotFor,
|
|
4
|
+
reconcileConnectPairSlot,
|
|
5
|
+
runWizard
|
|
6
|
+
} from "./chunk-GVWYW7MY.js";
|
|
7
|
+
import "./chunk-E6WMFMM2.js";
|
|
8
|
+
import "./chunk-OBIJ6WQP.js";
|
|
9
|
+
import "./chunk-QJFMU4QC.js";
|
|
10
|
+
import "./chunk-D6JKFJ6A.js";
|
|
11
|
+
import "./chunk-EIH2LNF4.js";
|
|
12
|
+
import "./chunk-RDLF4NQC.js";
|
|
13
|
+
import "./chunk-SQL56SEB.js";
|
|
14
|
+
import {
|
|
15
|
+
isWizardRuntime
|
|
16
|
+
} from "./chunk-77HWBSRH.js";
|
|
17
|
+
import "./chunk-V5VZPYMZ.js";
|
|
18
|
+
import {
|
|
19
|
+
runPair
|
|
20
|
+
} from "./chunk-EIAUW6KO.js";
|
|
21
|
+
import {
|
|
22
|
+
loadPairedConfig
|
|
23
|
+
} from "./chunk-5SZHXYPK.js";
|
|
24
|
+
import "./chunk-I67C2HYA.js";
|
|
25
|
+
import "./chunk-MIEI4PLB.js";
|
|
26
|
+
import "./chunk-6G6YYST6.js";
|
|
27
|
+
import "./chunk-U5HHHRXA.js";
|
|
28
|
+
import "./chunk-QEJUNP3X.js";
|
|
29
|
+
|
|
30
|
+
// src/wizard/setup-handler.ts
|
|
31
|
+
var SETUP_SUPPORTED_RUNTIMES = ["claude-code", "codex"];
|
|
32
|
+
function isSetupRuntime(value) {
|
|
33
|
+
return SETUP_SUPPORTED_RUNTIMES.includes(value);
|
|
34
|
+
}
|
|
35
|
+
function resolvePairCode(opts) {
|
|
36
|
+
return opts.pair ?? opts.pairCode;
|
|
37
|
+
}
|
|
38
|
+
async function runSetup(opts) {
|
|
39
|
+
const messages = [];
|
|
40
|
+
const requested = opts.runtime ?? "claude-code";
|
|
41
|
+
if (opts.verb === "setup" && opts.runtime !== void 0 && !isSetupRuntime(opts.runtime)) {
|
|
42
|
+
const supported = SETUP_SUPPORTED_RUNTIMES.join(", ");
|
|
43
|
+
const output = isWizardRuntime(opts.runtime) ? `\`setup\` does not support --runtime ${opts.runtime} yet (coming soon). Supported by \`setup\`: ${supported}. For ${opts.runtime}, use \`kojee-mcp init --runtime ${opts.runtime}\` for now.` : `Unknown --runtime "${opts.runtime}". \`setup\` supports: ${supported}. (For hermes/openclaw use \`kojee-mcp init\`.)`;
|
|
44
|
+
return { runtime: requested, messages, output, exitCode: 2 };
|
|
45
|
+
}
|
|
46
|
+
if (opts.token !== void 0 && (opts.url === void 0 || opts.url.trim() === "") && !opts.uninstall) {
|
|
47
|
+
return {
|
|
48
|
+
runtime: requested,
|
|
49
|
+
messages,
|
|
50
|
+
output: "--token requires --url (the broker URL the Kojee UI gave you). Re-run with --url <broker-url>. Nothing was written.",
|
|
51
|
+
exitCode: 2
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const url = opts.url ? opts.url.replace(/\/+$/, "") : void 0;
|
|
55
|
+
if (opts.pairCode && !opts.uninstall && opts.interactive && opts.runtime === void 0) {
|
|
56
|
+
return {
|
|
57
|
+
runtime: requested,
|
|
58
|
+
messages,
|
|
59
|
+
output: "Pass --runtime (claude-code | codex) together with --pair <code> so the paired credentials are keyed to the runtime you're setting up. Re-run: kojee-mcp setup --pair <code> --runtime <id>.",
|
|
60
|
+
exitCode: 2
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
let justPaired = false;
|
|
64
|
+
let pairedConfigLauncher;
|
|
65
|
+
if (opts.pairCode && !opts.uninstall) {
|
|
66
|
+
const pair = opts.runPair ?? runPair;
|
|
67
|
+
const pairUrl = url ?? DEFAULT_BROKER_URL;
|
|
68
|
+
const reconcile = reconcileConnectPairSlot(requested, opts.pairCode);
|
|
69
|
+
if (!reconcile.ok) {
|
|
70
|
+
return { runtime: requested, messages, output: reconcile.output, exitCode: reconcile.exitCode };
|
|
71
|
+
}
|
|
72
|
+
messages.push(...reconcile.messages);
|
|
73
|
+
const slot = pairSlotFor(requested, opts.pairCode);
|
|
74
|
+
try {
|
|
75
|
+
const r = await pair({
|
|
76
|
+
code: opts.pairCode,
|
|
77
|
+
url: pairUrl,
|
|
78
|
+
keystorePath: slot.keystorePath,
|
|
79
|
+
configPath: slot.configPath,
|
|
80
|
+
...slot.runtime ? { runtime: slot.runtime } : {},
|
|
81
|
+
...slot.allowOverwrite ? { allowOverwrite: true } : {}
|
|
82
|
+
});
|
|
83
|
+
messages.push(r.message);
|
|
84
|
+
justPaired = true;
|
|
85
|
+
pairedConfigLauncher = slot.pairedConfigPath;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
return {
|
|
88
|
+
runtime: requested,
|
|
89
|
+
messages,
|
|
90
|
+
output: `Pairing failed: ${err.message}`,
|
|
91
|
+
exitCode: 1
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const loadCfg = opts.loadPairedConfig ?? loadPairedConfig;
|
|
96
|
+
const hasCredential = justPaired || loadCfg() !== null || opts.token !== void 0;
|
|
97
|
+
if (!hasCredential && !opts.interactive && !opts.uninstall) {
|
|
98
|
+
return {
|
|
99
|
+
runtime: requested,
|
|
100
|
+
messages,
|
|
101
|
+
output: "Not paired. Run `kojee-mcp pair <code> --url <broker>` first, then re-run \u2014 or pass --pair <code> (or --token <T> --url <U>), or run in a terminal for the guided wizard.",
|
|
102
|
+
exitCode: 1
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const result = await runWizard({
|
|
106
|
+
...opts.runtime !== void 0 ? { runtime: opts.runtime } : {},
|
|
107
|
+
...opts.uninstall ? { uninstall: true } : {},
|
|
108
|
+
...opts.configPath ? { configPath: opts.configPath } : {},
|
|
109
|
+
...opts.hooksPath ? { hooksPath: opts.hooksPath } : {},
|
|
110
|
+
// Token mode (token + url) threads --token/--url into the written config.
|
|
111
|
+
...opts.token ? { token: opts.token } : {},
|
|
112
|
+
...url ? { url } : {},
|
|
113
|
+
// connect-runtime pair-mode: point the launcher at the per-runtime slot so
|
|
114
|
+
// the launched proxy reads it (its default branch reads only the global slot).
|
|
115
|
+
...pairedConfigLauncher ? { pairedConfigPath: pairedConfigLauncher } : {},
|
|
116
|
+
...opts.webhookUrl ? { webhookUrl: opts.webhookUrl } : {},
|
|
117
|
+
...opts.webhookSecret ? { webhookSecret: opts.webhookSecret } : {},
|
|
118
|
+
...opts.webhookSignatureFormat ? { webhookSignatureFormat: opts.webhookSignatureFormat } : {},
|
|
119
|
+
...opts.webhookSignatureHeader ? { webhookSignatureHeader: opts.webhookSignatureHeader } : {},
|
|
120
|
+
...opts.webhookSignaturePrefix !== void 0 ? { webhookSignaturePrefix: opts.webhookSignaturePrefix } : {},
|
|
121
|
+
interactive: opts.interactive,
|
|
122
|
+
...opts.interactive && opts.prompts ? opts.prompts : {}
|
|
123
|
+
});
|
|
124
|
+
if (opts.verb === "setup" && result.exitCode === 0 && !opts.uninstall) {
|
|
125
|
+
return {
|
|
126
|
+
runtime: result.runtime,
|
|
127
|
+
messages,
|
|
128
|
+
output: crispSetupSummary(result.runtime, opts, url),
|
|
129
|
+
exitCode: 0
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { runtime: result.runtime, messages, output: result.output, exitCode: result.exitCode };
|
|
133
|
+
}
|
|
134
|
+
function crispSetupSummary(runtime, opts, url) {
|
|
135
|
+
const pairedSlotLabel = isSetupRuntime(runtime) ? `~/.kojee/agents/${runtime}/config.json` : "~/.kojee/config.json";
|
|
136
|
+
const authLine = opts.token ? ` Auth: token mode (--token/--url${url ? `, ${url}` : ""})` : ` Auth: paired credentials (${pairedSlotLabel})`;
|
|
137
|
+
const lines = [];
|
|
138
|
+
if (runtime === "codex") {
|
|
139
|
+
lines.push("\u2713 kojee is set up for Codex.");
|
|
140
|
+
lines.push(` MCP config: ${opts.configPath ?? "~/.codex/config.toml"} ([mcp_servers.kojee])`);
|
|
141
|
+
lines.push(` Stop hook: ${opts.hooksPath ?? "~/.codex/hooks.json"} (codex-stop)`);
|
|
142
|
+
lines.push(authLine);
|
|
143
|
+
lines.push("");
|
|
144
|
+
lines.push("Next: restart Codex to connect.");
|
|
145
|
+
} else {
|
|
146
|
+
lines.push("\u2713 kojee is set up for Claude Code.");
|
|
147
|
+
lines.push(` MCP config: ${opts.configPath ?? "~/.claude.json"} (mcpServers.kojee)`);
|
|
148
|
+
lines.push(` Hooks: ${opts.hooksPath ?? "~/.claude/settings.json"} (Stop + UserPromptSubmit)`);
|
|
149
|
+
lines.push(authLine);
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push("Next: restart Claude Code to connect.");
|
|
152
|
+
}
|
|
153
|
+
return lines.join("\n");
|
|
154
|
+
}
|
|
155
|
+
export {
|
|
156
|
+
SETUP_SUPPORTED_RUNTIMES,
|
|
157
|
+
resolvePairCode,
|
|
158
|
+
runSetup
|
|
159
|
+
};
|
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
import "./chunk-XLKGPGZT.js";
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
2
|
+
resolveHookDiscovery
|
|
3
|
+
} from "./chunk-WBXU27BF.js";
|
|
5
4
|
import {
|
|
6
5
|
readHookStdin
|
|
7
6
|
} from "./chunk-LSUB6QMP.js";
|
|
7
|
+
import "./chunk-XLKGPGZT.js";
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "./chunk-DURRQDYI.js";
|
|
9
|
+
controlTokenAuthHeaders
|
|
10
|
+
} from "./chunk-GKXHKR3B.js";
|
|
12
11
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
formatChannelEvents
|
|
13
|
+
} from "./chunk-PHXO5P25.js";
|
|
15
14
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
monitorHeartbeatPath,
|
|
16
|
+
nudgeSentinelPath
|
|
17
|
+
} from "./chunk-TNZITJAB.js";
|
|
18
|
+
import "./chunk-67F67AQ6.js";
|
|
19
|
+
import "./chunk-U5HHHRXA.js";
|
|
19
20
|
import {
|
|
20
21
|
buildMonitorNudge
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import
|
|
23
|
-
|
|
24
|
-
findClaudeAncestorPid
|
|
25
|
-
} from "./chunk-VHKPWUX7.js";
|
|
22
|
+
} from "./chunk-QEJUNP3X.js";
|
|
23
|
+
import "./chunk-XJEBJIQE.js";
|
|
24
|
+
import "./chunk-KNEJTD6G.js";
|
|
26
25
|
|
|
27
26
|
// src/hooks/stop-hook.ts
|
|
28
27
|
import fs from "fs";
|
|
@@ -72,10 +71,8 @@ function defaultRecordNudge(logPath) {
|
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
async function runStopHook() {
|
|
75
|
-
const { stopHookActive } = await readHookStdin();
|
|
76
|
-
const
|
|
77
|
-
const key = deriveDiscoveryKey(process.env["CLAUDE_PROJECT_DIR"], ccPid);
|
|
78
|
-
const discovery = readSessionDiscoveryByKey(key);
|
|
74
|
+
const { stopHookActive, sessionId: stdinSessionId } = await readHookStdin();
|
|
75
|
+
const { discovery } = await resolveHookDiscovery(stdinSessionId);
|
|
79
76
|
const out = await decideStopHook({
|
|
80
77
|
stopHookActive,
|
|
81
78
|
discovery: discovery ? { port: discovery.port, eventLogPath: discovery.eventLogPath } : null,
|