kojee-mcp 0.5.7 → 0.5.8

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.
@@ -15,11 +15,17 @@ function defaultCodexHooksPath() {
15
15
  return path.join(kojeeHomeDir(), ".codex", "hooks.json");
16
16
  }
17
17
  var CODEX_STOP_HOOK_COMMAND = "npx -y kojee-mcp hook --type=codex-stop";
18
+ function codexArgsLiteral(token, url) {
19
+ if (token && url) {
20
+ return `["-y", "kojee-mcp", "--token", "${escapeTomlString(token)}", "--url", "${escapeTomlString(url)}"]`;
21
+ }
22
+ return '["-y", "kojee-mcp"]';
23
+ }
18
24
  function buildCodexMcpServerTable(opts) {
19
25
  return [
20
26
  "[mcp_servers.kojee]",
21
27
  'command = "npx"',
22
- 'args = ["-y", "kojee-mcp"]',
28
+ `args = ${codexArgsLiteral(opts.token, opts.url)}`,
23
29
  "",
24
30
  "[mcp_servers.kojee.env]",
25
31
  'KOJEE_RUNTIME = "codex"',
@@ -50,7 +56,14 @@ function writeCodexConfig(inputs) {
50
56
  toml = fs.readFileSync(configPath, "utf8");
51
57
  } catch {
52
58
  }
53
- toml = upsertKojeeTomlTables(toml, inputs.webhookUrl, inputs.webhookSecret, inputs.signatureEnv ?? []);
59
+ toml = upsertKojeeTomlTables(
60
+ toml,
61
+ inputs.webhookUrl,
62
+ inputs.webhookSecret,
63
+ inputs.signatureEnv ?? [],
64
+ inputs.token,
65
+ inputs.url
66
+ );
54
67
  writeFile600(configPath, toml);
55
68
  const hooks = readJson(hooksPath);
56
69
  hooks.hooks ??= {};
@@ -95,20 +108,22 @@ function removeCodexConfig(opts = {}) {
95
108
  }
96
109
  return result;
97
110
  }
98
- function upsertKojeeTomlTables(existing, webhookUrl, webhookSecret, signatureEnv = []) {
111
+ function upsertKojeeTomlTables(existing, webhookUrl, webhookSecret, signatureEnv = [], token, url) {
99
112
  const parsed = extractKojeeBlock(existing);
100
113
  if (!parsed) {
101
114
  const block = buildCodexMcpServerTable({
102
115
  webhookUrl,
103
116
  webhookSecret,
104
- ...signatureEnv.length > 0 ? { signatureEnv } : {}
117
+ ...signatureEnv.length > 0 ? { signatureEnv } : {},
118
+ ...token ? { token } : {},
119
+ ...url ? { url } : {}
105
120
  });
106
121
  const base2 = existing.replace(/\s*$/, "");
107
122
  return base2.length === 0 ? block + "\n" : base2 + "\n\n" + block + "\n";
108
123
  }
109
124
  const tableKeys = upsertKeyLines(parsed.tableKeys, [
110
125
  ["command", '"npx"'],
111
- ["args", '["-y", "kojee-mcp"]']
126
+ ["args", codexArgsLiteral(token, url)]
112
127
  ]);
113
128
  const envKeys = upsertKeyLines(parsed.envKeys, [
114
129
  ["KOJEE_RUNTIME", '"codex"'],
@@ -0,0 +1,68 @@
1
+ import {
2
+ secureDir,
3
+ secureFile
4
+ } from "./chunk-BLEGIR35.js";
5
+
6
+ // src/auth/keystore.ts
7
+ import { importJWK, exportJWK, generateKeyPair } from "jose";
8
+ import crypto from "crypto";
9
+ import fs from "fs";
10
+ import os from "os";
11
+ import path from "path";
12
+ var DEFAULT_PATH = path.join(os.homedir(), ".kojee", "keypair.json");
13
+ function defaultPairedKeystorePath() {
14
+ return path.join(os.homedir(), ".kojee", "keypair.json");
15
+ }
16
+ function deriveKeystorePath(token) {
17
+ const hash = crypto.createHash("sha256").update(token).digest("hex").slice(0, 12);
18
+ return path.join(os.homedir(), ".kojee", `keypair-${hash}.json`);
19
+ }
20
+ async function loadKeystore(keystorePath = DEFAULT_PATH, expectedBrokerUrl) {
21
+ if (!fs.existsSync(keystorePath)) {
22
+ return null;
23
+ }
24
+ const raw = fs.readFileSync(keystorePath, "utf-8");
25
+ const data = JSON.parse(raw);
26
+ if (expectedBrokerUrl && data.broker_url !== expectedBrokerUrl) {
27
+ return null;
28
+ }
29
+ const privateKey = await importJWK(data.private_key_jwk, "ES256");
30
+ return {
31
+ privateKey,
32
+ publicJwk: data.public_jwk,
33
+ kid: data.kid,
34
+ data
35
+ };
36
+ }
37
+ async function saveKeystore(privateKey, publicJwk, kid, brokerUrl, keystorePath = DEFAULT_PATH) {
38
+ const dir = path.dirname(keystorePath);
39
+ fs.mkdirSync(dir, { recursive: true, mode: 448 });
40
+ secureDir(dir);
41
+ const privateJwk = await exportJWK(privateKey);
42
+ const data = {
43
+ private_key_jwk: privateJwk,
44
+ kid,
45
+ broker_url: brokerUrl,
46
+ public_jwk: publicJwk,
47
+ enrolled_at: (/* @__PURE__ */ new Date()).toISOString()
48
+ };
49
+ fs.writeFileSync(keystorePath, JSON.stringify(data, null, 2), {
50
+ mode: 384
51
+ });
52
+ secureFile(keystorePath);
53
+ }
54
+ async function generateES256KeyPair() {
55
+ const { privateKey, publicKey } = await generateKeyPair("ES256");
56
+ const publicJwk = await exportJWK(publicKey);
57
+ publicJwk.kty = "EC";
58
+ publicJwk.crv = "P-256";
59
+ return { privateKey, publicJwk };
60
+ }
61
+
62
+ export {
63
+ defaultPairedKeystorePath,
64
+ deriveKeystorePath,
65
+ loadKeystore,
66
+ saveKeystore,
67
+ generateES256KeyPair
68
+ };
@@ -7,69 +7,9 @@ import {
7
7
  translateJsonRpcError,
8
8
  translateNetworkError
9
9
  } from "./chunk-LDZXU3DW.js";
10
- import {
11
- secureDir,
12
- secureFile
13
- } from "./chunk-BLEGIR35.js";
14
-
15
- // src/auth/keystore.ts
16
- import { importJWK, exportJWK, generateKeyPair } from "jose";
17
- import crypto from "crypto";
18
- import fs from "fs";
19
- import os from "os";
20
- import path from "path";
21
- var DEFAULT_PATH = path.join(os.homedir(), ".kojee", "keypair.json");
22
- function defaultPairedKeystorePath() {
23
- return path.join(os.homedir(), ".kojee", "keypair.json");
24
- }
25
- function deriveKeystorePath(token) {
26
- const hash = crypto.createHash("sha256").update(token).digest("hex").slice(0, 12);
27
- return path.join(os.homedir(), ".kojee", `keypair-${hash}.json`);
28
- }
29
- async function loadKeystore(keystorePath = DEFAULT_PATH, expectedBrokerUrl) {
30
- if (!fs.existsSync(keystorePath)) {
31
- return null;
32
- }
33
- const raw = fs.readFileSync(keystorePath, "utf-8");
34
- const data = JSON.parse(raw);
35
- if (expectedBrokerUrl && data.broker_url !== expectedBrokerUrl) {
36
- return null;
37
- }
38
- const privateKey = await importJWK(data.private_key_jwk, "ES256");
39
- return {
40
- privateKey,
41
- publicJwk: data.public_jwk,
42
- kid: data.kid,
43
- data
44
- };
45
- }
46
- async function saveKeystore(privateKey, publicJwk, kid, brokerUrl, keystorePath = DEFAULT_PATH) {
47
- const dir = path.dirname(keystorePath);
48
- fs.mkdirSync(dir, { recursive: true, mode: 448 });
49
- secureDir(dir);
50
- const privateJwk = await exportJWK(privateKey);
51
- const data = {
52
- private_key_jwk: privateJwk,
53
- kid,
54
- broker_url: brokerUrl,
55
- public_jwk: publicJwk,
56
- enrolled_at: (/* @__PURE__ */ new Date()).toISOString()
57
- };
58
- fs.writeFileSync(keystorePath, JSON.stringify(data, null, 2), {
59
- mode: 384
60
- });
61
- secureFile(keystorePath);
62
- }
63
- async function generateES256KeyPair() {
64
- const { privateKey, publicKey } = await generateKeyPair("ES256");
65
- const publicJwk = await exportJWK(publicKey);
66
- publicJwk.kty = "EC";
67
- publicJwk.crv = "P-256";
68
- return { privateKey, publicJwk };
69
- }
70
10
 
71
11
  // src/gateway-client.ts
72
- import crypto2 from "crypto";
12
+ import crypto from "crypto";
73
13
  var GatewayClient = class {
74
14
  constructor(brokerUrl, token, privateKey, kid, sessionId) {
75
15
  this.brokerUrl = brokerUrl;
@@ -105,7 +45,7 @@ var GatewayClient = class {
105
45
  * session_id = sha256(token + "proxy").slice(0, 16)
106
46
  */
107
47
  static deriveSessionId(token) {
108
- const hash = crypto2.createHash("sha256").update(token + "proxy").digest("hex");
48
+ const hash = crypto.createHash("sha256").update(token + "proxy").digest("hex");
109
49
  return hash.slice(0, 16);
110
50
  }
111
51
  /**
@@ -214,10 +154,5 @@ var GatewayClient = class {
214
154
  };
215
155
 
216
156
  export {
217
- defaultPairedKeystorePath,
218
- deriveKeystorePath,
219
- loadKeystore,
220
- saveKeystore,
221
- generateES256KeyPair,
222
157
  GatewayClient
223
158
  };
@@ -9,10 +9,10 @@ import {
9
9
  } from "./chunk-BJMASMKX.js";
10
10
  import {
11
11
  AuthModule
12
- } from "./chunk-6SK6ITFE.js";
12
+ } from "./chunk-JXMVZEQ7.js";
13
13
  import {
14
14
  GatewayClient
15
- } from "./chunk-3XDJOHMZ.js";
15
+ } from "./chunk-HSR3GXCL.js";
16
16
  import {
17
17
  startEventStream
18
18
  } from "./chunk-UEGQGXPY.js";
@@ -2,7 +2,7 @@ import {
2
2
  generateES256KeyPair,
3
3
  loadKeystore,
4
4
  saveKeystore
5
- } from "./chunk-3XDJOHMZ.js";
5
+ } from "./chunk-CH32ELFX.js";
6
6
 
7
7
  // src/auth/auth-module.ts
8
8
  import { calculateJwkThumbprint } from "jose";
@@ -0,0 +1,50 @@
1
+ import {
2
+ loadPairedConfig,
3
+ savePairedConfig
4
+ } from "./chunk-YH27B6SW.js";
5
+ import {
6
+ AuthModule
7
+ } from "./chunk-JXMVZEQ7.js";
8
+
9
+ // src/tandem/pair.ts
10
+ import fs from "fs";
11
+ async function runPair(opts) {
12
+ if (loadPairedConfig(opts.configPath) !== null) {
13
+ throw new Error(
14
+ `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.`
15
+ );
16
+ }
17
+ try {
18
+ fs.unlinkSync(opts.keystorePath);
19
+ } catch {
20
+ }
21
+ const auth = new AuthModule(opts.code, opts.url, opts.keystorePath);
22
+ await auth.ensureEnrolled();
23
+ let principal_id;
24
+ let agent_id;
25
+ try {
26
+ const me = await fetch(`${opts.url}/api/v1/users/me/`, {
27
+ headers: { Authorization: `DPoP ${opts.code}` }
28
+ });
29
+ if (me.ok) {
30
+ const body = await me.json();
31
+ principal_id = body.principal_id;
32
+ agent_id = body.agent_id;
33
+ }
34
+ } catch {
35
+ }
36
+ const config = {
37
+ token: opts.code,
38
+ broker_url: opts.url,
39
+ paired_at: (/* @__PURE__ */ new Date()).toISOString(),
40
+ ...principal_id ? { principal_id } : {},
41
+ ...agent_id ? { agent_id } : {}
42
+ };
43
+ savePairedConfig(opts.configPath, config);
44
+ const who = principal_id && agent_id ? `${principal_id} (${agent_id})` : "(use kojee-mcp without args to start the proxy)";
45
+ return { message: `Paired as ${who}. Keypair: ${opts.keystorePath}. Config: ${opts.configPath}.` };
46
+ }
47
+
48
+ export {
49
+ runPair
50
+ };
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-GATXJ6UT.js";
8
+ } from "./chunk-JWSIR6KV.js";
6
9
  import "./chunk-X672ZN7V.js";
7
10
  import "./chunk-BJMASMKX.js";
8
11
  import {
9
- loadPairedConfig,
10
- pairedConfigPath,
11
- savePairedConfig
12
+ pairedConfigPath
12
13
  } from "./chunk-YH27B6SW.js";
13
- import {
14
- AuthModule
15
- } from "./chunk-6SK6ITFE.js";
14
+ import "./chunk-JXMVZEQ7.js";
15
+ import "./chunk-HSR3GXCL.js";
16
+ import "./chunk-UEGQGXPY.js";
17
+ import "./chunk-2MIISF2W.js";
16
18
  import {
17
19
  defaultPairedKeystorePath,
18
20
  deriveKeystorePath
19
- } from "./chunk-3XDJOHMZ.js";
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-46BJD55B.js");
45
+ const { runStopHook } = await import("./stop-hook-SNPOFG4Q.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-ZD2XKN7U.js");
49
+ const { runUserPromptSubmitHook } = await import("./user-prompt-submit-hook-J7XZSDST.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-WBIUVBZW.js");
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-C2F4WTBN.js");
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-VUZBYKXS.js");
90
+ const { runTail } = await import("./tail-stream-HDM7BZDZ.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-QCQDFLEH.js");
99
+ const { runDoctor } = await import("./doctor-QRATEOFD.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 { loadPairedConfig: loadPairedConfig2 } = await import("./paired-config-JTFLHMZ2.js");
157
- if (loadPairedConfig2() === null && !opts.uninstall) {
158
- console.error("Not paired. Run `kojee-mcp pair <code> --url <broker>` first, then re-run `init`.");
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-UOXQYJLP.js");
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 ? { promptRuntime: promptRuntimeFromTty } : {}
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 promptRuntimeFromTty() {
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 rl.question(`Which runtime is this proxy for? ${menu}
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
- } finally {
191
- rl.close();
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: loadPairedConfig2 } = await import("./paired-config-JTFLHMZ2.js");
211
- const cfg = loadPairedConfig2();
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."
@@ -2,6 +2,10 @@ import {
2
2
  monitorHeartbeatPath,
3
3
  statusLogPath
4
4
  } from "./chunk-2TUAFAIW.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-NZ53ROQA.js");
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;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  defaultCodexConfigPath,
3
3
  defaultCodexHooksPath
4
- } from "./chunk-64EOLZNI.js";
4
+ } from "./chunk-65KRRDHP.js";
5
5
  import "./chunk-SQL56SEB.js";
6
6
  import {
7
7
  resolveWebhookConfig
package/dist/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  import {
2
2
  listTandemIds,
3
3
  startProxy
4
- } from "./chunk-GATXJ6UT.js";
4
+ } from "./chunk-JWSIR6KV.js";
5
5
  import "./chunk-X672ZN7V.js";
6
6
  import "./chunk-BJMASMKX.js";
7
- import "./chunk-6SK6ITFE.js";
8
- import "./chunk-3XDJOHMZ.js";
7
+ import "./chunk-JXMVZEQ7.js";
8
+ import "./chunk-HSR3GXCL.js";
9
9
  import "./chunk-UEGQGXPY.js";
10
10
  import "./chunk-2MIISF2W.js";
11
- import "./chunk-LDZXU3DW.js";
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(MCP_SERVER_ARGS);
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: [...MCP_SERVER_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({ configPath: t.path });
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.js CHANGED
@@ -7,15 +7,10 @@ import {
7
7
  } from "./chunk-YH27B6SW.js";
8
8
  import {
9
9
  AuthModule
10
- } from "./chunk-6SK6ITFE.js";
10
+ } from "./chunk-JXMVZEQ7.js";
11
11
  import {
12
- GatewayClient,
13
- defaultPairedKeystorePath,
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,
@@ -24,8 +19,15 @@ import {
24
19
  import {
25
20
  createDPoPProof
26
21
  } from "./chunk-2MIISF2W.js";
27
- import "./chunk-LDZXU3DW.js";
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,
@@ -0,0 +1,10 @@
1
+ import {
2
+ runPair
3
+ } from "./chunk-OGHDTFAX.js";
4
+ import "./chunk-YH27B6SW.js";
5
+ import "./chunk-JXMVZEQ7.js";
6
+ import "./chunk-CH32ELFX.js";
7
+ import "./chunk-BLEGIR35.js";
8
+ export {
9
+ runPair
10
+ };
@@ -2,17 +2,19 @@ import {
2
2
  loadPairedConfig
3
3
  } from "./chunk-YH27B6SW.js";
4
4
  import {
5
- GatewayClient,
6
- loadKeystore
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,3 +1,9 @@
1
+ import {
2
+ buildCodexMcpServerTable,
3
+ buildCodexStopHookBlock,
4
+ removeCodexConfig,
5
+ writeCodexConfig
6
+ } from "./chunk-65KRRDHP.js";
1
7
  import {
2
8
  WIZARD_RUNTIMES,
3
9
  isWizardRuntime
@@ -7,12 +13,6 @@ import {
7
13
  readRecordedRuntime,
8
14
  recordRuntime
9
15
  } from "./chunk-EW72ZNQL.js";
10
- import {
11
- buildCodexMcpServerTable,
12
- buildCodexStopHookBlock,
13
- removeCodexConfig,
14
- writeCodexConfig
15
- } from "./chunk-64EOLZNI.js";
16
16
  import {
17
17
  kojeeHomeDir
18
18
  } from "./chunk-SQL56SEB.js";
@@ -32,6 +32,7 @@ import {
32
32
  import crypto from "crypto";
33
33
  import fs from "fs";
34
34
  import path from "path";
35
+ var DEFAULT_BROKER_URL = "https://rosie-staging.kojee.net";
35
36
  function generateWebhookSecret() {
36
37
  return crypto.randomBytes(32).toString("hex");
37
38
  }
@@ -115,6 +116,49 @@ function writeRuntimeEnvFile(runtime, url, secret, signatureEnv = []) {
115
116
  return envPath;
116
117
  }
117
118
  var CODEX_UNVERIFIED_NOTE = "NOTE: live Codex verification (hook fires, MCP server connects, bounded listen works) has not been run on this build \u2014 confirm in a real Codex session. This is the owner morning step.";
119
+ function runtimeUsesWebhook(runtime) {
120
+ return runtime === "codex" || runtime === "hermes" || runtime === "openclaw";
121
+ }
122
+ async function gatherGuidedInputs(runtime, opts) {
123
+ const preamble = [];
124
+ const next = { ...opts };
125
+ if (opts.promptUrl) {
126
+ const answered = (await opts.promptUrl(opts.url ?? DEFAULT_BROKER_URL)).trim();
127
+ next.url = (answered.length > 0 ? answered : opts.url ?? DEFAULT_BROKER_URL).replace(/\/+$/, "");
128
+ }
129
+ const brokerUrl = (next.url ?? DEFAULT_BROKER_URL).replace(/\/+$/, "");
130
+ if (opts.promptAuth) {
131
+ const mode = await opts.promptAuth();
132
+ if (mode === "token") {
133
+ const token = opts.promptToken ? (await opts.promptToken()).trim() : "";
134
+ if (!token) return { error: "No token entered. Re-run `kojee-mcp init` and paste a token, or choose pair mode." };
135
+ next.token = token;
136
+ next.url = brokerUrl;
137
+ preamble.push("Auth: token mode \u2014 the written MCP config will launch the proxy with --token/--url");
138
+ preamble.push(" (it enrolls its own per-token keystore on first boot).");
139
+ } else {
140
+ const code = opts.promptPairCode ? (await opts.promptPairCode()).trim() : "";
141
+ if (!code) return { error: "No pair code entered. Re-run `kojee-mcp init` and enter a pair code, or choose token mode." };
142
+ const pair = opts.runPair ?? (async (a) => {
143
+ const { runPair } = await import("./pair-P4ILCMT7.js");
144
+ const { pairedConfigPath } = await import("./paired-config-JTFLHMZ2.js");
145
+ const { defaultPairedKeystorePath } = await import("./keystore-XLEV3FL5.js");
146
+ return runPair({ code: a.code, url: a.url, keystorePath: defaultPairedKeystorePath(), configPath: pairedConfigPath() });
147
+ });
148
+ try {
149
+ const { message } = await pair({ code, url: brokerUrl });
150
+ preamble.push(`Auth: pair mode \u2014 ${message}`);
151
+ } catch (err) {
152
+ return { error: `Pairing failed: ${err.message}` };
153
+ }
154
+ }
155
+ }
156
+ if (runtimeUsesWebhook(runtime) && opts.promptWebhookUrl && opts.webhookUrl === void 0) {
157
+ const wh = (await opts.promptWebhookUrl()).trim();
158
+ if (wh.length > 0) next.webhookUrl = wh;
159
+ }
160
+ return { opts: next, preamble };
161
+ }
118
162
  async function runWizard(opts) {
119
163
  const resolved = await resolveRuntime(opts);
120
164
  if ("error" in resolved) {
@@ -124,15 +168,44 @@ async function runWizard(opts) {
124
168
  if (opts.uninstall) {
125
169
  return runWizardUninstall(runtime, opts);
126
170
  }
127
- if (runtime === "claude-code") return configureClaudeCode(opts);
128
- if (runtime === "codex") return configureCodex(opts);
129
- return configureWebhookDaemon(runtime, opts);
171
+ let effective = opts;
172
+ let preamble = [];
173
+ if (opts.interactive && (opts.promptUrl || opts.promptAuth || opts.promptWebhookUrl)) {
174
+ const gathered = await gatherGuidedInputs(runtime, opts);
175
+ if ("error" in gathered) {
176
+ return { runtime, output: gathered.error, exitCode: 2 };
177
+ }
178
+ effective = gathered.opts;
179
+ preamble = gathered.preamble;
180
+ }
181
+ const result = runtime === "claude-code" ? await configureClaudeCode(effective) : runtime === "codex" ? configureCodex(effective) : configureWebhookDaemon(runtime, effective);
182
+ if (preamble.length > 0 && result.exitCode === 0) {
183
+ return {
184
+ ...result,
185
+ output: [...preamble, "", result.output, "", whatHappensNext(runtime, effective)].join("\n")
186
+ };
187
+ }
188
+ return result;
189
+ }
190
+ function whatHappensNext(runtime, opts) {
191
+ const lines = ["What happens next:"];
192
+ lines.push(" - Restart your runtime so it picks up the new kojee config.");
193
+ if (opts.token) {
194
+ lines.push(" - First boot enrolls this token's own keystore (~/.kojee/keypair-<hash>.json).");
195
+ } else {
196
+ lines.push(" - The proxy uses your paired credentials (~/.kojee/config.json + keypair.json).");
197
+ }
198
+ lines.push(" - Verify with: kojee-mcp doctor");
199
+ return lines.join("\n");
130
200
  }
131
201
  async function configureClaudeCode(opts) {
132
- const { runInit } = await import("./install-WBIUVBZW.js");
202
+ const { runInit } = await import("./install-LJY2CHKG.js");
133
203
  const report = runInit({
134
204
  ...opts.configPath ? { configPath: opts.configPath } : {},
135
- ...opts.hooksPath ? { hooksPath: opts.hooksPath } : {}
205
+ ...opts.hooksPath ? { hooksPath: opts.hooksPath } : {},
206
+ // Token mode threads --token/--url into the written args (per-token
207
+ // keystore). Paired mode leaves both unset ⇒ args stay `["kojee-mcp"]`.
208
+ ...opts.token && opts.url ? { token: opts.token, url: opts.url } : {}
136
209
  });
137
210
  recordRuntime("claude-code");
138
211
  return { runtime: "claude-code", output: formatClaudeInit(report), exitCode: 0 };
@@ -180,12 +253,14 @@ function configureCodex(opts) {
180
253
  }
181
254
  const url = wh.url || "https://YOUR-CODEX-WEBHOOK-RECEIVER.local/kojee";
182
255
  const secret = wh.secret || generateWebhookSecret();
256
+ const tokenArgs = opts.token && opts.url ? { token: opts.token, url: opts.url } : {};
183
257
  writeCodexConfig({
184
258
  ...opts.configPath ? { configPath: opts.configPath } : {},
185
259
  ...opts.hooksPath ? { hooksPath: opts.hooksPath } : {},
186
260
  webhookUrl: url,
187
261
  webhookSecret: secret,
188
- ...wh.signatureEnv.length > 0 ? { signatureEnv: wh.signatureEnv } : {}
262
+ ...wh.signatureEnv.length > 0 ? { signatureEnv: wh.signatureEnv } : {},
263
+ ...tokenArgs
189
264
  });
190
265
  recordRuntime("codex");
191
266
  const lines = [];
@@ -196,7 +271,11 @@ function configureCodex(opts) {
196
271
  lines.push(indent(buildCodexMcpServerTable({
197
272
  webhookUrl: url,
198
273
  webhookSecret: "<redacted>",
199
- ...wh.signatureEnv.length > 0 ? { signatureEnv: wh.signatureEnv } : {}
274
+ ...wh.signatureEnv.length > 0 ? { signatureEnv: wh.signatureEnv } : {},
275
+ // Redact the gateway token in the human-readable printed copy (it ends up
276
+ // in result.output → cli.ts console.error). The WRITTEN config above keeps
277
+ // the real token; only this printed report is redacted, like webhookSecret.
278
+ ...tokenArgs.token ? { token: "<redacted>", url: tokenArgs.url } : {}
200
279
  })));
201
280
  if (wh.warning) lines.push(`webhook WARNING: ${wh.warning}`);
202
281
  lines.push("");
@@ -254,7 +333,7 @@ async function runWizardUninstall(runtime, opts) {
254
333
  const effective = opts.runtime !== void 0 ? runtime : readRecordedRuntime() ?? runtime;
255
334
  const lines = [`Uninstalling runtime: ${effective}`];
256
335
  if (effective === "claude-code") {
257
- const { runUninstall } = await import("./install-WBIUVBZW.js");
336
+ const { runUninstall } = await import("./install-LJY2CHKG.js");
258
337
  const report = runUninstall({
259
338
  ...opts.configPath ? { configPath: opts.configPath } : {},
260
339
  ...opts.hooksPath ? { hooksPath: opts.hooksPath } : {}
@@ -295,6 +374,7 @@ function indent(s) {
295
374
  }
296
375
  export {
297
376
  CODEX_UNVERIFIED_NOTE,
377
+ DEFAULT_BROKER_URL,
298
378
  generateWebhookSecret,
299
379
  resolveRuntime,
300
380
  resolveWizardWebhook,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kojee-mcp",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -5,6 +5,9 @@ import {
5
5
  monitorHeartbeatPath,
6
6
  nudgeSentinelPath
7
7
  } from "./chunk-2TUAFAIW.js";
8
+ import {
9
+ readSessionDiscoveryByKey
10
+ } from "./chunk-DO42NPNR.js";
8
11
  import {
9
12
  controlTokenAuthHeaders
10
13
  } from "./chunk-GI2CKKBL.js";
@@ -15,9 +18,6 @@ import {
15
18
  deriveDiscoveryKey,
16
19
  findClaudeAncestorPid
17
20
  } from "./chunk-BJMASMKX.js";
18
- import {
19
- readSessionDiscoveryByKey
20
- } from "./chunk-DO42NPNR.js";
21
21
  import "./chunk-BLEGIR35.js";
22
22
 
23
23
  // src/hooks/stop-hook.ts
@@ -3,11 +3,11 @@ import {
3
3
  monitorHeartbeatPath,
4
4
  statusLogPath
5
5
  } from "./chunk-2TUAFAIW.js";
6
+ import "./chunk-DO42NPNR.js";
6
7
  import {
7
8
  createAdaptiveWatchdog
8
9
  } from "./chunk-UEGQGXPY.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,9 @@
1
1
  import {
2
2
  readHookStdin
3
3
  } from "./chunk-LSUB6QMP.js";
4
+ import {
5
+ readSessionDiscoveryByKey
6
+ } from "./chunk-DO42NPNR.js";
4
7
  import {
5
8
  controlTokenAuthHeaders
6
9
  } from "./chunk-GI2CKKBL.js";
@@ -8,9 +11,6 @@ import {
8
11
  deriveDiscoveryKey,
9
12
  findClaudeAncestorPid
10
13
  } from "./chunk-BJMASMKX.js";
11
- import {
12
- readSessionDiscoveryByKey
13
- } from "./chunk-DO42NPNR.js";
14
14
  import "./chunk-BLEGIR35.js";
15
15
 
16
16
  // src/hooks/user-prompt-submit-hook.ts