kojee-mcp 0.5.7 → 0.5.9
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 +189 -50
- package/dist/{chunk-64EOLZNI.js → chunk-65KRRDHP.js} +20 -5
- package/dist/chunk-CH32ELFX.js +68 -0
- package/dist/{chunk-2TUAFAIW.js → chunk-DS26OORG.js} +13 -2
- package/dist/{chunk-3XDJOHMZ.js → chunk-HSR3GXCL.js} +2 -67
- package/dist/{chunk-6SK6ITFE.js → chunk-JXMVZEQ7.js} +1 -1
- package/dist/{chunk-UEGQGXPY.js → chunk-MKDMAAMN.js} +13 -3
- package/dist/chunk-OGHDTFAX.js +50 -0
- package/dist/chunk-PHXO5P25.js +20 -0
- package/dist/{chunk-GATXJ6UT.js → chunk-SCDWPGH3.js} +6 -5
- package/dist/cli.js +87 -73
- package/dist/{doctor-QCQDFLEH.js → doctor-XK335W7B.js} +6 -6
- package/dist/{doctor-codex-NZ53ROQA.js → doctor-codex-SMROUYGV.js} +1 -1
- package/dist/{event-log-RSTM4PLL.js → event-log-B27VVEMK.js} +1 -1
- package/dist/index.js +6 -5
- package/dist/{install-WBIUVBZW.js → install-LJY2CHKG.js} +14 -3
- package/dist/keystore-XLEV3FL5.js +15 -0
- package/dist/lib.d.ts +2 -0
- package/dist/lib.js +12 -10
- package/dist/pair-P4ILCMT7.js +10 -0
- package/dist/{send-cli-C2F4WTBN.js → send-cli-CN5EX7PO.js} +6 -4
- package/dist/{stop-hook-46BJD55B.js → stop-hook-GEJF47SN.js} +8 -17
- package/dist/{tail-stream-VUZBYKXS.js → tail-stream-JNR4WFW3.js} +3 -3
- package/dist/{user-prompt-submit-hook-ZD2XKN7U.js → user-prompt-submit-hook-DGRRFHOB.js} +7 -16
- package/dist/{wizard-UOXQYJLP.js → wizard-PLGHYCT3.js} +94 -14
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/hooks/format-channel.ts
|
|
2
|
+
function sanitizeChannelAttr(value) {
|
|
3
|
+
return String(value ?? "").replace(/["<>\u0000-\u001f\u007f]/g, "");
|
|
4
|
+
}
|
|
5
|
+
function formatChannelEvents(events) {
|
|
6
|
+
const header = `[${events.length} unread Tandem ${events.length === 1 ? "event" : "events"}]
|
|
7
|
+
|
|
8
|
+
`;
|
|
9
|
+
const bodies = events.map((evt) => {
|
|
10
|
+
const attrs = Object.entries(evt.meta).map(([k, v]) => `${k}="${sanitizeChannelAttr(v)}"`).join(" ");
|
|
11
|
+
return `<channel source="kojee-mcp" ${attrs}>
|
|
12
|
+
${evt.content}
|
|
13
|
+
</channel>`;
|
|
14
|
+
});
|
|
15
|
+
return header + bodies.join("\n\n");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
formatChannelEvents
|
|
20
|
+
};
|
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
} from "./chunk-BJMASMKX.js";
|
|
10
10
|
import {
|
|
11
11
|
AuthModule
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JXMVZEQ7.js";
|
|
13
13
|
import {
|
|
14
14
|
GatewayClient
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-HSR3GXCL.js";
|
|
16
16
|
import {
|
|
17
17
|
startEventStream
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-MKDMAAMN.js";
|
|
19
19
|
import {
|
|
20
20
|
translateToolCallResult
|
|
21
21
|
} from "./chunk-LDZXU3DW.js";
|
|
@@ -245,6 +245,7 @@ var claudeCodeAdapter = {
|
|
|
245
245
|
from_display: event.from.displayname,
|
|
246
246
|
severity: computeSeverity(event)
|
|
247
247
|
};
|
|
248
|
+
if (event.wake_reason) meta.wake_reason = event.wake_reason;
|
|
248
249
|
return { content: formatBody(event), meta };
|
|
249
250
|
}
|
|
250
251
|
};
|
|
@@ -377,7 +378,7 @@ async function startProxy(config) {
|
|
|
377
378
|
cleanupDiscoveryByKey,
|
|
378
379
|
sweepStaleDiscovery
|
|
379
380
|
} = await import("./session-discovery-FNMJGFPM.js");
|
|
380
|
-
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-
|
|
381
|
+
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-B27VVEMK.js");
|
|
381
382
|
const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
|
|
382
383
|
const { resolveWebhookConfig } = await import("./webhook-config-O4WMQ532.js");
|
|
383
384
|
const { createWebhookSink } = await import("./webhook-sink-NWGCUDGY.js");
|
|
@@ -514,7 +515,7 @@ async function startProxy(config) {
|
|
|
514
515
|
activeStreamHandle = streamHandle;
|
|
515
516
|
joinReconnect.notifyReady();
|
|
516
517
|
} else if (needsWebhookEventStream()) {
|
|
517
|
-
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-
|
|
518
|
+
const { startEventLog, sweepStaleEventLogs } = await import("./event-log-B27VVEMK.js");
|
|
518
519
|
const { resolveWebhookConfig } = await import("./webhook-config-O4WMQ532.js");
|
|
519
520
|
const { createWebhookSink } = await import("./webhook-sink-NWGCUDGY.js");
|
|
520
521
|
const { resubscribeMemberships } = await import("./resubscribe-G5OGDZJD.js");
|
package/dist/cli.js
CHANGED
|
@@ -1,71 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPair
|
|
4
|
+
} from "./chunk-OGHDTFAX.js";
|
|
2
5
|
import {
|
|
3
6
|
VERSION,
|
|
4
7
|
startProxy
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SCDWPGH3.js";
|
|
6
9
|
import "./chunk-X672ZN7V.js";
|
|
7
10
|
import "./chunk-BJMASMKX.js";
|
|
8
11
|
import {
|
|
9
|
-
|
|
10
|
-
pairedConfigPath,
|
|
11
|
-
savePairedConfig
|
|
12
|
+
pairedConfigPath
|
|
12
13
|
} from "./chunk-YH27B6SW.js";
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
import "./chunk-JXMVZEQ7.js";
|
|
15
|
+
import "./chunk-HSR3GXCL.js";
|
|
16
|
+
import "./chunk-MKDMAAMN.js";
|
|
17
|
+
import "./chunk-2MIISF2W.js";
|
|
16
18
|
import {
|
|
17
19
|
defaultPairedKeystorePath,
|
|
18
20
|
deriveKeystorePath
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-UEGQGXPY.js";
|
|
21
|
-
import "./chunk-2MIISF2W.js";
|
|
22
|
-
import "./chunk-LDZXU3DW.js";
|
|
21
|
+
} from "./chunk-CH32ELFX.js";
|
|
23
22
|
import "./chunk-BLEGIR35.js";
|
|
23
|
+
import "./chunk-LDZXU3DW.js";
|
|
24
24
|
|
|
25
25
|
// src/cli.ts
|
|
26
26
|
import { Command } from "commander";
|
|
27
27
|
import path from "path";
|
|
28
|
-
|
|
29
|
-
// src/tandem/pair.ts
|
|
30
|
-
import fs from "fs";
|
|
31
|
-
async function runPair(opts) {
|
|
32
|
-
if (loadPairedConfig(opts.configPath) !== null) {
|
|
33
|
-
throw new Error(
|
|
34
|
-
`Already paired (config exists at ${opts.configPath}). To re-pair this slot, delete the config file first. For a second account, use --keystore-path /custom/keypair.json.`
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
fs.unlinkSync(opts.keystorePath);
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
41
|
-
const auth = new AuthModule(opts.code, opts.url, opts.keystorePath);
|
|
42
|
-
await auth.ensureEnrolled();
|
|
43
|
-
let principal_id;
|
|
44
|
-
let agent_id;
|
|
45
|
-
try {
|
|
46
|
-
const me = await fetch(`${opts.url}/api/v1/users/me/`, {
|
|
47
|
-
headers: { Authorization: `DPoP ${opts.code}` }
|
|
48
|
-
});
|
|
49
|
-
if (me.ok) {
|
|
50
|
-
const body = await me.json();
|
|
51
|
-
principal_id = body.principal_id;
|
|
52
|
-
agent_id = body.agent_id;
|
|
53
|
-
}
|
|
54
|
-
} catch {
|
|
55
|
-
}
|
|
56
|
-
const config = {
|
|
57
|
-
token: opts.code,
|
|
58
|
-
broker_url: opts.url,
|
|
59
|
-
paired_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
60
|
-
...principal_id ? { principal_id } : {},
|
|
61
|
-
...agent_id ? { agent_id } : {}
|
|
62
|
-
};
|
|
63
|
-
savePairedConfig(opts.configPath, config);
|
|
64
|
-
const who = principal_id && agent_id ? `${principal_id} (${agent_id})` : "(use kojee-mcp without args to start the proxy)";
|
|
65
|
-
return { message: `Paired as ${who}. Keypair: ${opts.keystorePath}. Config: ${opts.configPath}.` };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/cli.ts
|
|
69
28
|
var program = new Command().name("kojee-mcp").description(
|
|
70
29
|
"Local MCP proxy for Kojee \u2014 handles DPoP auth, tool discovery, and governance transparently"
|
|
71
30
|
).version(VERSION).enablePositionalOptions();
|
|
@@ -83,11 +42,11 @@ program.command("pair <code>").description("Pair this machine against Kojee usin
|
|
|
83
42
|
});
|
|
84
43
|
program.command("hook").description("Run a kojee MCP hook script (called by Claude Code via ~/.claude/settings.json)").requiredOption("--type <type>", "Hook type: stop, user-prompt-submit, or codex-stop").action(async (opts) => {
|
|
85
44
|
if (opts.type === "stop") {
|
|
86
|
-
const { runStopHook } = await import("./stop-hook-
|
|
45
|
+
const { runStopHook } = await import("./stop-hook-GEJF47SN.js");
|
|
87
46
|
await runStopHook();
|
|
88
47
|
process.exit(0);
|
|
89
48
|
} else if (opts.type === "user-prompt-submit") {
|
|
90
|
-
const { runUserPromptSubmitHook } = await import("./user-prompt-submit-hook-
|
|
49
|
+
const { runUserPromptSubmitHook } = await import("./user-prompt-submit-hook-DGRRFHOB.js");
|
|
91
50
|
await runUserPromptSubmitHook();
|
|
92
51
|
process.exit(0);
|
|
93
52
|
} else if (opts.type === "codex-stop") {
|
|
@@ -100,7 +59,7 @@ program.command("hook").description("Run a kojee MCP hook script (called by Clau
|
|
|
100
59
|
}
|
|
101
60
|
});
|
|
102
61
|
program.command("install-hooks").description("Install kojee Stop + UserPromptSubmit hooks in ~/.claude/settings.json (idempotent)").option("--hooks-path <path>", "Override default ~/.claude/settings.json").option("--uninstall", "Remove kojee hook entries instead of installing them").action(async (opts) => {
|
|
103
|
-
const { installHooks, uninstallHooks } = await import("./install-
|
|
62
|
+
const { installHooks, uninstallHooks } = await import("./install-LJY2CHKG.js");
|
|
104
63
|
if (opts.uninstall) {
|
|
105
64
|
const removed = uninstallHooks({ hooksPath: opts.hooksPath });
|
|
106
65
|
console.error(removed ? "Removed kojee hook entries." : "No kojee hook entries found.");
|
|
@@ -117,7 +76,7 @@ Restart Claude Code for hooks to take effect.`
|
|
|
117
76
|
program.command("send <tandem_id>").description(
|
|
118
77
|
"Send a Tandem message using this machine's paired credentials (~/.kojee). Prints one JSON envelope to stdout: {ok, message_id, cursor, text} on success, {ok:false, error:<typed code>, message} on failure (exit 1)."
|
|
119
78
|
).requiredOption("--body <text>", "Message body (required)").option("--reply-to <message_id>", "Message id this send replies to").option("--kind <kind>", "Message kind: message | status (default: backend default)").action(async (tandemId, opts) => {
|
|
120
|
-
const { runSendCli } = await import("./send-cli-
|
|
79
|
+
const { runSendCli } = await import("./send-cli-CN5EX7PO.js");
|
|
121
80
|
const { exitCode, envelope } = await runSendCli({
|
|
122
81
|
tandemId,
|
|
123
82
|
body: opts.body,
|
|
@@ -128,7 +87,7 @@ program.command("send <tandem_id>").description(
|
|
|
128
87
|
process.exit(exitCode);
|
|
129
88
|
});
|
|
130
89
|
program.command("tail <path>").description("Stream a file's contents and follow appends (portable replacement for `tail -F`)").action(async (filePath) => {
|
|
131
|
-
const { runTail } = await import("./tail-stream-
|
|
90
|
+
const { runTail } = await import("./tail-stream-JNR4WFW3.js");
|
|
132
91
|
try {
|
|
133
92
|
await runTail(filePath);
|
|
134
93
|
} catch (err) {
|
|
@@ -137,13 +96,13 @@ program.command("tail <path>").description("Stream a file's contents and follow
|
|
|
137
96
|
}
|
|
138
97
|
});
|
|
139
98
|
program.command("doctor").description("Diagnose the kojee wake path (proxy, hook-server, SSE stream, event log, Monitor) and print the exact wake recipe").action(async () => {
|
|
140
|
-
const { runDoctor } = await import("./doctor-
|
|
99
|
+
const { runDoctor } = await import("./doctor-XK335W7B.js");
|
|
141
100
|
const code = await runDoctor();
|
|
142
101
|
process.exit(code);
|
|
143
102
|
});
|
|
144
103
|
program.command("init").description(
|
|
145
104
|
"Set up kojee for a runtime (claude-code | hermes | openclaw | codex). Interactive when stdin is a TTY; `--runtime <id>` for non-interactive/CI. Run after `kojee-mcp pair`."
|
|
146
|
-
).option("--runtime <id>", "Target runtime: claude-code | hermes | openclaw | codex").option("--config-path <path>", "Override the runtime's MCP-config path").option("--hooks-path <path>", "Override the runtime's hooks-file path").option("--webhook-url <url>", "Webhook receiver URL (codex/hermes/openclaw)").option("--webhook-secret <secret>", "Webhook HMAC secret (generated if omitted)").option(
|
|
105
|
+
).option("--runtime <id>", "Target runtime: claude-code | hermes | openclaw | codex").option("--config-path <path>", "Override the runtime's MCP-config path").option("--hooks-path <path>", "Override the runtime's hooks-file path").option("--token <token>", "Gateway token \u2014 token mode (writes --token/--url into the MCP config)").option("--url <url>", "Broker base URL (token mode / pair URL; default https://rosie-staging.kojee.net)").option("--pair-code <code>", "Pair code \u2014 runs the pair flow (writes ~/.kojee/config.json) before configuring").option("--webhook-url <url>", "Webhook receiver URL (codex/hermes/openclaw)").option("--webhook-secret <secret>", "Webhook HMAC secret (generated if omitted)").option(
|
|
147
106
|
"--webhook-signature-format <preset>",
|
|
148
107
|
'Signature preset: "github" = header X-Hub-Signature-256, value sha256=<hex> (default: bare hex in X-Kojee-Signature)'
|
|
149
108
|
).option(
|
|
@@ -153,43 +112,98 @@ program.command("init").description(
|
|
|
153
112
|
"--webhook-signature-prefix <prefix>",
|
|
154
113
|
"Literal string prepended to the hex digest (default empty; overrides the preset's prefix)"
|
|
155
114
|
).option("--uninstall", "Remove the kojee config for the chosen (or recorded) runtime").action(async (opts) => {
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
158
|
-
|
|
115
|
+
const interactive = process.stdin.isTTY === true && opts.runtime === void 0;
|
|
116
|
+
if (opts.pairCode && !opts.uninstall) {
|
|
117
|
+
const { runPair: runPair2 } = await import("./pair-P4ILCMT7.js");
|
|
118
|
+
const { pairedConfigPath: pairedConfigPath2 } = await import("./paired-config-JTFLHMZ2.js");
|
|
119
|
+
const { defaultPairedKeystorePath: defaultPairedKeystorePath2 } = await import("./keystore-XLEV3FL5.js");
|
|
120
|
+
const url = (opts.url ?? "https://rosie-staging.kojee.net").replace(/\/+$/, "");
|
|
121
|
+
try {
|
|
122
|
+
const r = await runPair2({
|
|
123
|
+
code: opts.pairCode,
|
|
124
|
+
url,
|
|
125
|
+
keystorePath: defaultPairedKeystorePath2(),
|
|
126
|
+
configPath: pairedConfigPath2()
|
|
127
|
+
});
|
|
128
|
+
console.error(r.message);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.error("[kojee-mcp init] Pairing failed:", err.message);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const { loadPairedConfig } = await import("./paired-config-JTFLHMZ2.js");
|
|
135
|
+
const hasCredential = loadPairedConfig() !== null || opts.token !== void 0;
|
|
136
|
+
if (!hasCredential && !interactive && !opts.uninstall) {
|
|
137
|
+
console.error("Not paired. Run `kojee-mcp pair <code> --url <broker>` first, then re-run `init` \u2014 or pass --token/--pair-code, or run `init` in a terminal for the guided wizard.");
|
|
159
138
|
process.exit(1);
|
|
160
139
|
}
|
|
161
|
-
const { runWizard } = await import("./wizard-
|
|
162
|
-
const interactive = process.stdin.isTTY === true && opts.runtime === void 0;
|
|
140
|
+
const { runWizard } = await import("./wizard-PLGHYCT3.js");
|
|
163
141
|
const result = await runWizard({
|
|
164
142
|
...opts.runtime !== void 0 ? { runtime: opts.runtime } : {},
|
|
165
143
|
...opts.uninstall ? { uninstall: true } : {},
|
|
166
144
|
...opts.configPath ? { configPath: opts.configPath } : {},
|
|
167
145
|
...opts.hooksPath ? { hooksPath: opts.hooksPath } : {},
|
|
146
|
+
// Token-mode threading (token + url ⇒ --token/--url in the written config).
|
|
147
|
+
// Normalize the URL exactly like the proxy action does (strip trailing /).
|
|
148
|
+
...opts.token ? { token: opts.token } : {},
|
|
149
|
+
...opts.url ? { url: opts.url.replace(/\/+$/, "") } : {},
|
|
168
150
|
...opts.webhookUrl ? { webhookUrl: opts.webhookUrl } : {},
|
|
169
151
|
...opts.webhookSecret ? { webhookSecret: opts.webhookSecret } : {},
|
|
170
152
|
...opts.webhookSignatureFormat ? { webhookSignatureFormat: opts.webhookSignatureFormat } : {},
|
|
171
153
|
...opts.webhookSignatureHeader ? { webhookSignatureHeader: opts.webhookSignatureHeader } : {},
|
|
172
154
|
...opts.webhookSignaturePrefix !== void 0 ? { webhookSignaturePrefix: opts.webhookSignaturePrefix } : {},
|
|
173
155
|
interactive,
|
|
174
|
-
...interactive ? {
|
|
156
|
+
...interactive ? {
|
|
157
|
+
promptRuntime: promptRuntimeFromTty,
|
|
158
|
+
promptUrl: promptUrlFromTty,
|
|
159
|
+
promptAuth: promptAuthFromTty,
|
|
160
|
+
promptToken: promptTokenFromTty,
|
|
161
|
+
promptPairCode: promptPairCodeFromTty,
|
|
162
|
+
promptWebhookUrl: promptWebhookUrlFromTty
|
|
163
|
+
} : {}
|
|
175
164
|
});
|
|
176
165
|
console.error(result.output);
|
|
177
166
|
process.exit(result.exitCode);
|
|
178
167
|
});
|
|
179
|
-
async function
|
|
180
|
-
const { RUNTIME_MENU } = await import("./runtimes-CO43XUUK.js");
|
|
168
|
+
async function withReadline(fn) {
|
|
181
169
|
const readline = await import("readline/promises");
|
|
182
170
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
183
171
|
try {
|
|
172
|
+
return await fn((q) => rl.question(q));
|
|
173
|
+
} finally {
|
|
174
|
+
rl.close();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async function promptRuntimeFromTty() {
|
|
178
|
+
const { RUNTIME_MENU } = await import("./runtimes-CO43XUUK.js");
|
|
179
|
+
return withReadline(async (ask) => {
|
|
184
180
|
const menu = RUNTIME_MENU.map((m) => `[${m.index}] ${m.runtime}`).join(" ");
|
|
185
|
-
const answer = (await
|
|
181
|
+
const answer = (await ask(`Which runtime is this proxy for? ${menu}
|
|
186
182
|
> `)).trim();
|
|
187
183
|
const byIndex = RUNTIME_MENU.find((m) => String(m.index) === answer);
|
|
188
184
|
if (byIndex) return byIndex.runtime;
|
|
189
185
|
return answer;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
async function promptUrlFromTty(defaultUrl) {
|
|
189
|
+
return withReadline((ask) => ask(`Broker URL [${defaultUrl}]
|
|
190
|
+
> `));
|
|
191
|
+
}
|
|
192
|
+
async function promptAuthFromTty() {
|
|
193
|
+
return withReadline(async (ask) => {
|
|
194
|
+
const answer = (await ask("Auth: [1] paste a token [2] enter a pair code\n> ")).trim().toLowerCase();
|
|
195
|
+
if (answer === "2" || answer.startsWith("p")) return "pair";
|
|
196
|
+
return "token";
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
async function promptTokenFromTty() {
|
|
200
|
+
return withReadline((ask) => ask("Paste your gateway token:\n> "));
|
|
201
|
+
}
|
|
202
|
+
async function promptPairCodeFromTty() {
|
|
203
|
+
return withReadline((ask) => ask("Enter your pair code (from the dashboard):\n> "));
|
|
204
|
+
}
|
|
205
|
+
async function promptWebhookUrlFromTty() {
|
|
206
|
+
return withReadline((ask) => ask("Webhook receiver URL (press Enter to skip and set it up later):\n> "));
|
|
193
207
|
}
|
|
194
208
|
program.option("--token <token>", "Gateway token (for token-mode)").option("--url <url>", "Broker base URL (for token-mode; required if --token is passed)").option(
|
|
195
209
|
"--keystore-path <path>",
|
|
@@ -207,8 +221,8 @@ program.option("--token <token>", "Gateway token (for token-mode)").option("--ur
|
|
|
207
221
|
url = url.replace(/\/+$/, "");
|
|
208
222
|
keystorePath ??= deriveKeystorePath(token);
|
|
209
223
|
} else {
|
|
210
|
-
const { loadPairedConfig
|
|
211
|
-
const cfg =
|
|
224
|
+
const { loadPairedConfig } = await import("./paired-config-JTFLHMZ2.js");
|
|
225
|
+
const cfg = loadPairedConfig();
|
|
212
226
|
if (!cfg) {
|
|
213
227
|
console.error(
|
|
214
228
|
"No --token provided and no ~/.kojee/config.json found. Run `kojee-mcp pair <code> --url <broker>` first."
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
monitorHeartbeatPath,
|
|
3
3
|
statusLogPath
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DS26OORG.js";
|
|
5
|
+
import {
|
|
6
|
+
discoveryPathForKey,
|
|
7
|
+
readSessionDiscoveryByKey
|
|
8
|
+
} from "./chunk-DO42NPNR.js";
|
|
5
9
|
import {
|
|
6
10
|
loadControlToken
|
|
7
11
|
} from "./chunk-GI2CKKBL.js";
|
|
@@ -16,10 +20,6 @@ import {
|
|
|
16
20
|
import {
|
|
17
21
|
loadPairedConfig
|
|
18
22
|
} from "./chunk-YH27B6SW.js";
|
|
19
|
-
import {
|
|
20
|
-
discoveryPathForKey,
|
|
21
|
-
readSessionDiscoveryByKey
|
|
22
|
-
} from "./chunk-DO42NPNR.js";
|
|
23
23
|
import "./chunk-BLEGIR35.js";
|
|
24
24
|
|
|
25
25
|
// src/doctor.ts
|
|
@@ -233,7 +233,7 @@ function formatDoctorReport(report) {
|
|
|
233
233
|
async function runDoctor() {
|
|
234
234
|
const { readRecordedRuntime } = await import("./runtime-record-WO4IECM6.js");
|
|
235
235
|
if (readRecordedRuntime() === "codex") {
|
|
236
|
-
const { collectCodexDoctorReport, formatCodexDoctorReport } = await import("./doctor-codex-
|
|
236
|
+
const { collectCodexDoctorReport, formatCodexDoctorReport } = await import("./doctor-codex-SMROUYGV.js");
|
|
237
237
|
const report2 = collectCodexDoctorReport();
|
|
238
238
|
console.error(formatCodexDoctorReport(report2));
|
|
239
239
|
return report2.verdict === "broken" ? 1 : 0;
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
listTandemIds,
|
|
3
3
|
startProxy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SCDWPGH3.js";
|
|
5
5
|
import "./chunk-X672ZN7V.js";
|
|
6
6
|
import "./chunk-BJMASMKX.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-JXMVZEQ7.js";
|
|
8
|
+
import "./chunk-HSR3GXCL.js";
|
|
9
|
+
import "./chunk-MKDMAAMN.js";
|
|
10
10
|
import "./chunk-2MIISF2W.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-CH32ELFX.js";
|
|
12
12
|
import "./chunk-BLEGIR35.js";
|
|
13
|
+
import "./chunk-LDZXU3DW.js";
|
|
13
14
|
export {
|
|
14
15
|
listTandemIds,
|
|
15
16
|
startProxy
|
|
@@ -94,21 +94,28 @@ function uninstallHooks(opts = {}) {
|
|
|
94
94
|
writeConfig(p, cfg);
|
|
95
95
|
return removed;
|
|
96
96
|
}
|
|
97
|
+
function mcpServerArgs(opts) {
|
|
98
|
+
if (opts.token && opts.url) {
|
|
99
|
+
return [...MCP_SERVER_ARGS, "--token", opts.token, "--url", opts.url];
|
|
100
|
+
}
|
|
101
|
+
return [...MCP_SERVER_ARGS];
|
|
102
|
+
}
|
|
97
103
|
function installMcpServer(opts = {}) {
|
|
98
104
|
const p = opts.configPath ?? defaultConfigPath();
|
|
99
105
|
const cfg = readConfig(p);
|
|
100
106
|
cfg.mcpServers ??= {};
|
|
107
|
+
const args = mcpServerArgs(opts);
|
|
101
108
|
const existing = cfg.mcpServers["kojee"];
|
|
102
109
|
if (existing) {
|
|
103
110
|
const sameCommand = existing.command === MCP_SERVER_CMD;
|
|
104
|
-
const sameArgs = JSON.stringify(existing.args ?? []) === JSON.stringify(
|
|
111
|
+
const sameArgs = JSON.stringify(existing.args ?? []) === JSON.stringify(args);
|
|
105
112
|
const sameEnv = JSON.stringify(existing.env ?? {}) === JSON.stringify(MCP_SERVER_ENV);
|
|
106
113
|
if (sameCommand && sameArgs && sameEnv) return "already-installed";
|
|
107
114
|
return "preserved-different";
|
|
108
115
|
}
|
|
109
116
|
cfg.mcpServers["kojee"] = {
|
|
110
117
|
command: MCP_SERVER_CMD,
|
|
111
|
-
args
|
|
118
|
+
args,
|
|
112
119
|
env: { ...MCP_SERVER_ENV }
|
|
113
120
|
};
|
|
114
121
|
writeConfig(p, cfg);
|
|
@@ -135,7 +142,11 @@ function runInit(opts = {}) {
|
|
|
135
142
|
reports.push({ kind: t.kind, path: t.path, ...t.hooksPath ? { hooksPath: t.hooksPath } : {}, mcpServer: "not-found" });
|
|
136
143
|
continue;
|
|
137
144
|
}
|
|
138
|
-
const mcpServer = installMcpServer({
|
|
145
|
+
const mcpServer = installMcpServer({
|
|
146
|
+
configPath: t.path,
|
|
147
|
+
...opts.token ? { token: opts.token } : {},
|
|
148
|
+
...opts.url ? { url: opts.url } : {}
|
|
149
|
+
});
|
|
139
150
|
let stopHook;
|
|
140
151
|
let upsHook;
|
|
141
152
|
if (t.kind === "cli") {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultPairedKeystorePath,
|
|
3
|
+
deriveKeystorePath,
|
|
4
|
+
generateES256KeyPair,
|
|
5
|
+
loadKeystore,
|
|
6
|
+
saveKeystore
|
|
7
|
+
} from "./chunk-CH32ELFX.js";
|
|
8
|
+
import "./chunk-BLEGIR35.js";
|
|
9
|
+
export {
|
|
10
|
+
defaultPairedKeystorePath,
|
|
11
|
+
deriveKeystorePath,
|
|
12
|
+
generateES256KeyPair,
|
|
13
|
+
loadKeystore,
|
|
14
|
+
saveKeystore
|
|
15
|
+
};
|
package/dist/lib.d.ts
CHANGED
package/dist/lib.js
CHANGED
|
@@ -7,25 +7,27 @@ import {
|
|
|
7
7
|
} from "./chunk-YH27B6SW.js";
|
|
8
8
|
import {
|
|
9
9
|
AuthModule
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JXMVZEQ7.js";
|
|
11
11
|
import {
|
|
12
|
-
GatewayClient
|
|
13
|
-
|
|
14
|
-
deriveKeystorePath,
|
|
15
|
-
generateES256KeyPair,
|
|
16
|
-
loadKeystore,
|
|
17
|
-
saveKeystore
|
|
18
|
-
} from "./chunk-3XDJOHMZ.js";
|
|
12
|
+
GatewayClient
|
|
13
|
+
} from "./chunk-HSR3GXCL.js";
|
|
19
14
|
import {
|
|
20
15
|
normalizeBackendEvent,
|
|
21
16
|
sanitizeDisplayname,
|
|
22
17
|
startEventStream
|
|
23
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-MKDMAAMN.js";
|
|
24
19
|
import {
|
|
25
20
|
createDPoPProof
|
|
26
21
|
} from "./chunk-2MIISF2W.js";
|
|
27
|
-
import
|
|
22
|
+
import {
|
|
23
|
+
defaultPairedKeystorePath,
|
|
24
|
+
deriveKeystorePath,
|
|
25
|
+
generateES256KeyPair,
|
|
26
|
+
loadKeystore,
|
|
27
|
+
saveKeystore
|
|
28
|
+
} from "./chunk-CH32ELFX.js";
|
|
28
29
|
import "./chunk-BLEGIR35.js";
|
|
30
|
+
import "./chunk-LDZXU3DW.js";
|
|
29
31
|
export {
|
|
30
32
|
AuthModule,
|
|
31
33
|
GatewayClient,
|
|
@@ -2,17 +2,19 @@ import {
|
|
|
2
2
|
loadPairedConfig
|
|
3
3
|
} from "./chunk-YH27B6SW.js";
|
|
4
4
|
import {
|
|
5
|
-
GatewayClient
|
|
6
|
-
|
|
7
|
-
} from "./chunk-3XDJOHMZ.js";
|
|
5
|
+
GatewayClient
|
|
6
|
+
} from "./chunk-HSR3GXCL.js";
|
|
8
7
|
import "./chunk-2MIISF2W.js";
|
|
8
|
+
import {
|
|
9
|
+
loadKeystore
|
|
10
|
+
} from "./chunk-CH32ELFX.js";
|
|
11
|
+
import "./chunk-BLEGIR35.js";
|
|
9
12
|
import {
|
|
10
13
|
executeSend,
|
|
11
14
|
parseSendRequest,
|
|
12
15
|
sendFailure
|
|
13
16
|
} from "./chunk-HIZ4NDWN.js";
|
|
14
17
|
import "./chunk-LDZXU3DW.js";
|
|
15
|
-
import "./chunk-BLEGIR35.js";
|
|
16
18
|
|
|
17
19
|
// src/tandem/send-cli.ts
|
|
18
20
|
import os from "os";
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatChannelEvents
|
|
3
|
+
} from "./chunk-PHXO5P25.js";
|
|
1
4
|
import {
|
|
2
5
|
readHookStdin
|
|
3
6
|
} from "./chunk-LSUB6QMP.js";
|
|
4
7
|
import {
|
|
5
8
|
monitorHeartbeatPath,
|
|
6
9
|
nudgeSentinelPath
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DS26OORG.js";
|
|
11
|
+
import {
|
|
12
|
+
readSessionDiscoveryByKey
|
|
13
|
+
} from "./chunk-DO42NPNR.js";
|
|
8
14
|
import {
|
|
9
15
|
controlTokenAuthHeaders
|
|
10
16
|
} from "./chunk-GI2CKKBL.js";
|
|
@@ -15,9 +21,6 @@ import {
|
|
|
15
21
|
deriveDiscoveryKey,
|
|
16
22
|
findClaudeAncestorPid
|
|
17
23
|
} from "./chunk-BJMASMKX.js";
|
|
18
|
-
import {
|
|
19
|
-
readSessionDiscoveryByKey
|
|
20
|
-
} from "./chunk-DO42NPNR.js";
|
|
21
24
|
import "./chunk-BLEGIR35.js";
|
|
22
25
|
|
|
23
26
|
// src/hooks/stop-hook.ts
|
|
@@ -37,7 +40,7 @@ async function decideStopHook(deps) {
|
|
|
37
40
|
if (!deps.discovery) return "{}";
|
|
38
41
|
const body = await deps.pollEvents().catch(() => null);
|
|
39
42
|
if (body && body.count > 0) {
|
|
40
|
-
return JSON.stringify({ decision: "block", reason:
|
|
43
|
+
return JSON.stringify({ decision: "block", reason: formatChannelEvents(body.events) });
|
|
41
44
|
}
|
|
42
45
|
const logPath = deps.discovery.eventLogPath;
|
|
43
46
|
if (logPath && deps.logHasContent(logPath) && !deps.monitorIsLive(logPath)) {
|
|
@@ -109,18 +112,6 @@ function monitorIsLive(logPath) {
|
|
|
109
112
|
return false;
|
|
110
113
|
}
|
|
111
114
|
}
|
|
112
|
-
function formatEvents(events) {
|
|
113
|
-
const header = `[${events.length} unread Tandem ${events.length === 1 ? "event" : "events"}]
|
|
114
|
-
|
|
115
|
-
`;
|
|
116
|
-
const bodies = events.map((evt) => {
|
|
117
|
-
const attrs = Object.entries(evt.meta).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
118
|
-
return `<channel source="kojee-mcp" ${attrs}>
|
|
119
|
-
${evt.content}
|
|
120
|
-
</channel>`;
|
|
121
|
-
});
|
|
122
|
-
return header + bodies.join("\n\n");
|
|
123
|
-
}
|
|
124
115
|
export {
|
|
125
116
|
decideStopHook,
|
|
126
117
|
runStopHook
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
STATUS_LINE_PREFIX,
|
|
3
3
|
monitorHeartbeatPath,
|
|
4
4
|
statusLogPath
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DS26OORG.js";
|
|
6
|
+
import "./chunk-DO42NPNR.js";
|
|
6
7
|
import {
|
|
7
8
|
createAdaptiveWatchdog
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MKDMAAMN.js";
|
|
9
10
|
import "./chunk-2MIISF2W.js";
|
|
10
|
-
import "./chunk-DO42NPNR.js";
|
|
11
11
|
import "./chunk-BLEGIR35.js";
|
|
12
12
|
|
|
13
13
|
// src/tail-stream.ts
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatChannelEvents
|
|
3
|
+
} from "./chunk-PHXO5P25.js";
|
|
1
4
|
import {
|
|
2
5
|
readHookStdin
|
|
3
6
|
} from "./chunk-LSUB6QMP.js";
|
|
7
|
+
import {
|
|
8
|
+
readSessionDiscoveryByKey
|
|
9
|
+
} from "./chunk-DO42NPNR.js";
|
|
4
10
|
import {
|
|
5
11
|
controlTokenAuthHeaders
|
|
6
12
|
} from "./chunk-GI2CKKBL.js";
|
|
@@ -8,9 +14,6 @@ import {
|
|
|
8
14
|
deriveDiscoveryKey,
|
|
9
15
|
findClaudeAncestorPid
|
|
10
16
|
} from "./chunk-BJMASMKX.js";
|
|
11
|
-
import {
|
|
12
|
-
readSessionDiscoveryByKey
|
|
13
|
-
} from "./chunk-DO42NPNR.js";
|
|
14
17
|
import "./chunk-BLEGIR35.js";
|
|
15
18
|
|
|
16
19
|
// src/hooks/user-prompt-submit-hook.ts
|
|
@@ -42,19 +45,7 @@ async function runUserPromptSubmitHook() {
|
|
|
42
45
|
process.stdout.write("{}");
|
|
43
46
|
return;
|
|
44
47
|
}
|
|
45
|
-
process.stdout.write(JSON.stringify({ additionalContext:
|
|
46
|
-
}
|
|
47
|
-
function formatEvents(events) {
|
|
48
|
-
const header = `[${events.length} unread Tandem ${events.length === 1 ? "event" : "events"}]
|
|
49
|
-
|
|
50
|
-
`;
|
|
51
|
-
const bodies = events.map((evt) => {
|
|
52
|
-
const attrs = Object.entries(evt.meta).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
53
|
-
return `<channel source="kojee-mcp" ${attrs}>
|
|
54
|
-
${evt.content}
|
|
55
|
-
</channel>`;
|
|
56
|
-
});
|
|
57
|
-
return header + bodies.join("\n\n");
|
|
48
|
+
process.stdout.write(JSON.stringify({ additionalContext: formatChannelEvents(body.events) }));
|
|
58
49
|
}
|
|
59
50
|
export {
|
|
60
51
|
runUserPromptSubmitHook
|