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