@runeya/runeya 2.0.64 → 2.0.66

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/agent/index.js CHANGED
@@ -5172,11 +5172,14 @@ import { TRPCError as TRPCError5 } from "@trpc/server";
5172
5172
  import { spawn as spawn4, execFileSync } from "child_process";
5173
5173
  import { EventEmitter as EventEmitter9 } from "events";
5174
5174
  import { randomUUID as randomUUID5 } from "crypto";
5175
- import { fileURLToPath } from "url";
5176
- import { createRequire } from "module";
5177
- import { existsSync as existsSync2, readFileSync } from "fs";
5175
+ import { existsSync as existsSync3, readFileSync } from "fs";
5178
5176
  import { dirname, resolve as resolvePath2 } from "path";
5179
5177
  import * as pty2 from "@lydell/node-pty";
5178
+
5179
+ // ../../packages/mcp-server/src/launch.ts
5180
+ import { fileURLToPath } from "url";
5181
+ import { createRequire } from "module";
5182
+ import { existsSync as existsSync2 } from "fs";
5180
5183
  function resolveMcpServerPath() {
5181
5184
  try {
5182
5185
  const req = createRequire(import.meta.url);
@@ -5184,9 +5187,13 @@ function resolveMcpServerPath() {
5184
5187
  } catch {
5185
5188
  }
5186
5189
  const candidates = [
5190
+ // Build packagé du CLI : dist/agent/index.js et dist/index.js côtoient
5191
+ // dist/mcp-server/, copié là par le post-build.
5192
+ new URL("../mcp-server/index.js", import.meta.url),
5193
+ new URL("./mcp-server/index.js", import.meta.url),
5194
+ // Monorepo, depuis un dist d'app.
5187
5195
  new URL("../../../packages/mcp-server/dist/index.js", import.meta.url),
5188
- new URL("../../../../packages/mcp-server/dist/index.js", import.meta.url),
5189
- new URL("../mcp-server/index.js", import.meta.url)
5196
+ new URL("../../../../packages/mcp-server/dist/index.js", import.meta.url)
5190
5197
  ];
5191
5198
  for (const c of candidates) {
5192
5199
  const p = fileURLToPath(c);
@@ -5194,6 +5201,42 @@ function resolveMcpServerPath() {
5194
5201
  }
5195
5202
  throw new Error("Could not locate @runeya/packages-mcp-server (built dist not found)");
5196
5203
  }
5204
+ function pickEnv(env2) {
5205
+ return {
5206
+ ...env2.RUNEYA_BASE_URL ? { RUNEYA_BASE_URL: env2.RUNEYA_BASE_URL } : {},
5207
+ ...env2.RUNEYA_API_TOKEN ? { RUNEYA_API_TOKEN: env2.RUNEYA_API_TOKEN } : {}
5208
+ };
5209
+ }
5210
+ function claudeMcpArgs(env2) {
5211
+ const config = JSON.stringify({
5212
+ mcpServers: {
5213
+ runeya: {
5214
+ command: "node",
5215
+ args: [resolveMcpServerPath()],
5216
+ env: pickEnv(env2)
5217
+ }
5218
+ }
5219
+ });
5220
+ return ["--mcp-config", config];
5221
+ }
5222
+ function codexMcpArgs(env2) {
5223
+ const fields = [
5224
+ `command=${tomlString("node")}`,
5225
+ `args=[${tomlString(resolveMcpServerPath())}]`
5226
+ ];
5227
+ const entries = Object.entries(pickEnv(env2));
5228
+ if (entries.length > 0) {
5229
+ const inline = entries.map(([k, v]) => `${k}=${tomlString(v)}`).join(",");
5230
+ fields.push(`env={${inline}}`);
5231
+ }
5232
+ return ["-c", `mcp_servers.runeya={${fields.join(",")}}`];
5233
+ }
5234
+ function tomlString(value) {
5235
+ const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\u0000-\u001f\u007f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
5236
+ return `"${escaped}"`;
5237
+ }
5238
+
5239
+ // src/services/ai-spawn-manager.ts
5197
5240
  function resolveCliInvocation(cli, args) {
5198
5241
  if (process.platform !== "win32") return { command: cli, args };
5199
5242
  if (/\.exe$/i.test(cli)) return { command: cli, args };
@@ -5209,13 +5252,13 @@ function resolveCliInvocation(cli, args) {
5209
5252
  shim = found.find((f) => /\.cmd$/i.test(f)) ?? found[0] ?? cli;
5210
5253
  }
5211
5254
  if (/\.exe$/i.test(shim)) return { command: shim, args };
5212
- if (/\.cmd$/i.test(shim) && existsSync2(shim)) {
5255
+ if (/\.cmd$/i.test(shim) && existsSync3(shim)) {
5213
5256
  try {
5214
5257
  const content = readFileSync(shim, "utf-8");
5215
5258
  const m = content.match(/%~?dp0%\\?([^"\s]+\.js)/i);
5216
5259
  if (m?.[1]) {
5217
5260
  const entry = resolvePath2(dirname(shim), m[1].replace(/^\\+/, ""));
5218
- if (existsSync2(entry)) return { command: process.execPath, args: [entry, ...args] };
5261
+ if (existsSync3(entry)) return { command: process.execPath, args: [entry, ...args] };
5219
5262
  }
5220
5263
  } catch {
5221
5264
  }
@@ -5238,20 +5281,10 @@ function resolveSpawnEnvAndArgs(opts) {
5238
5281
  const args = [...opts.args];
5239
5282
  if (opts.enableMcp && opts.cli === "claude") {
5240
5283
  try {
5241
- const mcpServerPath = resolveMcpServerPath();
5242
- const mcpConfig = JSON.stringify({
5243
- mcpServers: {
5244
- runeya: {
5245
- command: "node",
5246
- args: [mcpServerPath],
5247
- env: {
5248
- ...env2.RUNEYA_BASE_URL ? { RUNEYA_BASE_URL: env2.RUNEYA_BASE_URL } : {},
5249
- ...env2.RUNEYA_API_TOKEN ? { RUNEYA_API_TOKEN: env2.RUNEYA_API_TOKEN } : {}
5250
- }
5251
- }
5252
- }
5253
- });
5254
- args.push("--mcp-config", mcpConfig);
5284
+ args.push(...claudeMcpArgs({
5285
+ RUNEYA_BASE_URL: env2.RUNEYA_BASE_URL,
5286
+ RUNEYA_API_TOKEN: env2.RUNEYA_API_TOKEN
5287
+ }));
5255
5288
  } catch (err) {
5256
5289
  console.warn("[ai-spawn-manager] Failed to resolve MCP server path:", err.message);
5257
5290
  }
@@ -5556,6 +5589,18 @@ import { spawn as spawn6 } from "child_process";
5556
5589
  import { createInterface as createInterface2 } from "readline";
5557
5590
  import { EventEmitter as EventEmitter10 } from "events";
5558
5591
  var REQUEST_TIMEOUT_MS = 3e5;
5592
+ function resolveMcpArgs(env2) {
5593
+ if (!env2["RUNEYA_API_TOKEN"]) return [];
5594
+ try {
5595
+ return codexMcpArgs({
5596
+ RUNEYA_BASE_URL: env2["RUNEYA_BASE_URL"],
5597
+ RUNEYA_API_TOKEN: env2["RUNEYA_API_TOKEN"]
5598
+ });
5599
+ } catch (err) {
5600
+ console.warn("[codex-app-server-mgr] Failed to resolve MCP server path:", err.message);
5601
+ return [];
5602
+ }
5603
+ }
5559
5604
  var CodexAppServerManager = class extends EventEmitter10 {
5560
5605
  proc = null;
5561
5606
  rl = null;
@@ -5580,9 +5625,10 @@ var CodexAppServerManager = class extends EventEmitter10 {
5580
5625
  }
5581
5626
  }
5582
5627
  async doConnect() {
5583
- this.proc = spawn6("codex", ["app-server"], {
5628
+ const env2 = { ...process.env, ...this.extraEnv };
5629
+ this.proc = spawn6("codex", [...resolveMcpArgs(env2), "app-server"], {
5584
5630
  stdio: ["pipe", "pipe", "pipe"],
5585
- env: { ...process.env, ...this.extraEnv }
5631
+ env: env2
5586
5632
  });
5587
5633
  this.rl = createInterface2({ input: this.proc.stdout });
5588
5634
  this.rl.on("line", (line) => this.handleLine(line));
@@ -6304,11 +6350,73 @@ function createAgent(opts) {
6304
6350
  // src/config/node-path.ts
6305
6351
  import { dirname as dirname3, delimiter } from "path";
6306
6352
  function ensureNodeBinOnPath(environment = process.env) {
6307
- const nodeBin = dirname3(process.execPath);
6353
+ appendToPath(dirname3(process.execPath), environment);
6354
+ }
6355
+ function appendToPath(dir, environment = process.env) {
6356
+ if (!dir) return;
6308
6357
  const current = environment["PATH"] ?? "";
6309
6358
  const entries = current.split(delimiter).filter(Boolean);
6310
- if (entries.includes(nodeBin)) return;
6311
- environment["PATH"] = entries.length > 0 ? `${current}${delimiter}${nodeBin}` : nodeBin;
6359
+ if (entries.includes(dir)) return;
6360
+ environment["PATH"] = entries.length > 0 ? `${current}${delimiter}${dir}` : dir;
6361
+ }
6362
+
6363
+ // src/config/user-path.ts
6364
+ import { execFile as execFile5 } from "child_process";
6365
+ import { promisify as promisify3 } from "util";
6366
+ import { homedir as homedir5 } from "os";
6367
+ import { existsSync as existsSync4, statSync } from "fs";
6368
+ import { join as join6, delimiter as delimiter2 } from "path";
6369
+ var execFileAsync3 = promisify3(execFile5);
6370
+ var MARKER = "__RUNEYA_PATH__";
6371
+ var SHELL_TIMEOUT_MS = 3e3;
6372
+ function commonUserBins(home) {
6373
+ return [
6374
+ join6(home, ".local", "bin"),
6375
+ join6(home, "bin"),
6376
+ join6(home, ".npm-global", "bin"),
6377
+ join6(home, ".bun", "bin"),
6378
+ join6(home, ".cargo", "bin"),
6379
+ "/opt/homebrew/bin",
6380
+ "/usr/local/bin"
6381
+ ];
6382
+ }
6383
+ async function readLoginShellPath() {
6384
+ if (process.platform === "win32") return null;
6385
+ const shell = process.env["SHELL"];
6386
+ if (!shell || !existsSync4(shell)) return null;
6387
+ try {
6388
+ const { stdout } = await execFileAsync3(shell, ["-l", "-i", "-c", `echo "${MARKER}$PATH"`], {
6389
+ timeout: SHELL_TIMEOUT_MS,
6390
+ shell: false,
6391
+ encoding: "utf8",
6392
+ maxBuffer: 1024 * 1024,
6393
+ env: { ...process.env, TERM: "dumb" }
6394
+ });
6395
+ const line = stdout.split("\n").find((l) => l.includes(MARKER));
6396
+ if (!line) return null;
6397
+ const value = line.slice(line.indexOf(MARKER) + MARKER.length).trim();
6398
+ return value.length > 0 ? value : null;
6399
+ } catch {
6400
+ return null;
6401
+ }
6402
+ }
6403
+ async function ensureUserBinsOnPath(environment = process.env, home = homedir5()) {
6404
+ const shellPath = await readLoginShellPath();
6405
+ if (shellPath) {
6406
+ for (const entry of shellPath.split(delimiter2).filter(Boolean)) {
6407
+ appendToPath(entry, environment);
6408
+ }
6409
+ }
6410
+ for (const dir of commonUserBins(home)) {
6411
+ if (isDirectory(dir)) appendToPath(dir, environment);
6412
+ }
6413
+ }
6414
+ function isDirectory(path3) {
6415
+ try {
6416
+ return statSync(path3).isDirectory();
6417
+ } catch {
6418
+ return false;
6419
+ }
6312
6420
  }
6313
6421
 
6314
6422
  // src/index.ts
@@ -6345,6 +6453,7 @@ process.on("uncaughtException", (err) => {
6345
6453
  });
6346
6454
  async function main() {
6347
6455
  ensureNodeBinOnPath();
6456
+ await ensureUserBinsOnPath();
6348
6457
  const { server, shutdown, passphraseHex } = createAgent({
6349
6458
  passphraseHex: env.PASSPHRASE_OVERRIDE
6350
6459
  });