@sideboard-ai/core 0.1.153 → 0.1.156

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.
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-S42XV45P.js";
12
12
  import {
13
13
  isOrchestratorThread
14
- } from "./chunk-RNC3GR6L.js";
14
+ } from "./chunk-TI6UMRWK.js";
15
15
  import {
16
16
  codexUnattendedGitConfigArgs,
17
17
  mergeAgentGitAuthEnv,
@@ -1709,7 +1709,7 @@ function toCodexMcpConfigArgs(servers) {
1709
1709
  }
1710
1710
  return args;
1711
1711
  }
1712
- function toOpencodeMcpConfigContent(servers) {
1712
+ function toOpencodeMcpConfigContent(servers, opts) {
1713
1713
  const mcp = {};
1714
1714
  for (const s of servers) {
1715
1715
  const env = mcpSpawnEnv(s.env);
@@ -1720,6 +1720,11 @@ function toOpencodeMcpConfigContent(servers) {
1720
1720
  ...env ? { environment: env } : {}
1721
1721
  };
1722
1722
  }
1723
+ for (const name of opts?.disableNames ?? []) {
1724
+ const key = name.trim();
1725
+ if (!key || mcp[key]?.enabled === true) continue;
1726
+ mcp[key] = { ...mcp[key], enabled: false };
1727
+ }
1723
1728
  return JSON.stringify({ mcp });
1724
1729
  }
1725
1730
  function writeMcpServersConfig(servers) {
@@ -1935,13 +1940,50 @@ function claudeString(obj, key) {
1935
1940
  const v = obj[key];
1936
1941
  return typeof v === "string" && v.trim() ? v.trim() : void 0;
1937
1942
  }
1943
+ function mcpStatusThinkingFromClaudeInit(obj) {
1944
+ const raw = obj.mcp_servers ?? obj.mcpServers;
1945
+ const servers = [];
1946
+ if (Array.isArray(raw)) {
1947
+ for (const item of raw) {
1948
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
1949
+ const rec = item;
1950
+ const name = typeof rec.name === "string" && rec.name.trim() || typeof rec.server === "string" && rec.server.trim() || "";
1951
+ const status = typeof rec.status === "string" && rec.status.trim() || typeof rec.state === "string" && rec.state.trim() || "";
1952
+ if (name) servers.push({ name, status: status || "unknown" });
1953
+ }
1954
+ } else if (raw && typeof raw === "object") {
1955
+ for (const [name, value] of Object.entries(raw)) {
1956
+ if (!name.trim()) continue;
1957
+ if (typeof value === "string" && value.trim()) {
1958
+ servers.push({ name, status: value.trim() });
1959
+ continue;
1960
+ }
1961
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1962
+ const rec = value;
1963
+ const status = typeof rec.status === "string" && rec.status.trim() || typeof rec.state === "string" && rec.state.trim() || "unknown";
1964
+ servers.push({ name, status });
1965
+ }
1966
+ }
1967
+ }
1968
+ const notable = servers.filter((s) => !isCleanMcpConnect(s.status));
1969
+ if (notable.length === 0) return null;
1970
+ return `MCP: ${notable.map((s) => `${s.name} ${s.status}`).join(", ")}`;
1971
+ }
1972
+ function isCleanMcpConnect(status) {
1973
+ return /^(connected|ok|ready|success)$/i.test(status.trim());
1974
+ }
1938
1975
  function eventsFromClaudeSystem(obj) {
1939
1976
  const subtype = claudeString(obj, "subtype") ?? "";
1940
1977
  const parentId = claudeParentToolUseId(obj);
1941
1978
  if (subtype === "init") {
1942
1979
  if (parentId) return null;
1943
1980
  const sid = claudeString(obj, "session_id");
1944
- return sid ? { type: "session_id", data: sid } : null;
1981
+ const mcpNote = mcpStatusThinkingFromClaudeInit(obj);
1982
+ const events = [];
1983
+ if (sid) events.push({ type: "session_id", data: sid });
1984
+ if (mcpNote) events.push({ type: "thinking", data: mcpNote, replace: true });
1985
+ if (events.length === 0) return null;
1986
+ return events.length === 1 ? events[0] : events;
1945
1987
  }
1946
1988
  if (subtype === "task_started") {
1947
1989
  const id = claudeString(obj, "tool_use_id") ?? claudeString(obj, "task_id");
@@ -2098,7 +2140,7 @@ var claudeAdapter = {
2098
2140
  );
2099
2141
  }
2100
2142
  const mode = permissionMode(thread);
2101
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-4LHCZ2DC.js");
2143
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-MR75BDBY.js");
2102
2144
  const isOrchestrator = isOrchestratorThread2(thread);
2103
2145
  const injectedServers = await buildInjectedMcpServers({
2104
2146
  includeSideboard: true,
@@ -2141,6 +2183,9 @@ var claudeAdapter = {
2141
2183
  const mcpConfigPath = writeMcpServersConfig(injectedServers);
2142
2184
  if (mcpConfigPath) {
2143
2185
  args.push("--mcp-config", mcpConfigPath);
2186
+ if (isOrchestrator) {
2187
+ args.push("--strict-mcp-config");
2188
+ }
2144
2189
  }
2145
2190
  if (chromeOn) {
2146
2191
  args.push("--chrome");
@@ -2170,7 +2215,10 @@ var claudeAdapter = {
2170
2215
  // abandoned at Claude Code’s 10-minute default.
2171
2216
  env: {
2172
2217
  CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1",
2173
- CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: process.env.CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS ?? String(CLAUDE_PRINT_BG_WAIT_CEILING_MS)
2218
+ CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: process.env.CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS ?? String(CLAUDE_PRINT_BG_WAIT_CEILING_MS),
2219
+ // `--strict-mcp-config` still fetches claude.ai connectors on some CLI
2220
+ // builds (anthropics/claude-code#60252). Coordinators do not need them.
2221
+ ...isOrchestrator ? { ENABLE_CLAUDEAI_MCP_SERVERS: "false" } : {}
2174
2222
  }
2175
2223
  };
2176
2224
  },
@@ -2318,9 +2366,106 @@ function parseIssuesJson(raw) {
2318
2366
  }
2319
2367
 
2320
2368
  // src/agents/codex.ts
2321
- import { existsSync as existsSync6, readFileSync, statSync } from "fs";
2369
+ import { existsSync as existsSync8, readFileSync as readFileSync3, statSync } from "fs";
2370
+ import { homedir as homedir4 } from "os";
2371
+ import { join as join6 } from "path";
2372
+
2373
+ // src/agents/orch-mcp-isolation.ts
2374
+ import { existsSync as existsSync7, readFileSync as readFileSync2 } from "fs";
2375
+ import { homedir as homedir3 } from "os";
2376
+ import { join as join5 } from "path";
2377
+ import { parse as parseToml } from "smol-toml";
2378
+
2379
+ // src/agents/user-mcp-config.ts
2380
+ import { existsSync as existsSync6, mkdirSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
2322
2381
  import { homedir as homedir2 } from "os";
2323
- import { join as join4 } from "path";
2382
+ import { dirname as dirname2, join as join4 } from "path";
2383
+
2384
+ // src/agents/orch-mcp-isolation.ts
2385
+ function isInjectedOrchMcpName(name) {
2386
+ const n = name.trim().toLowerCase();
2387
+ return n === "sideboard" || n === "brightsy" || n.startsWith("brightsy_");
2388
+ }
2389
+ function asObject(value) {
2390
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
2391
+ return value;
2392
+ }
2393
+ function listMcpNamesFromJsonMap(raw, key) {
2394
+ return Object.keys(asObject(asObject(raw)[key])).filter((n) => n.trim());
2395
+ }
2396
+ function listMcpNamesFromCodexToml(text) {
2397
+ try {
2398
+ const parsed = parseToml(text);
2399
+ return Object.keys(asObject(parsed.mcp_servers)).filter((n) => n.trim());
2400
+ } catch {
2401
+ return [];
2402
+ }
2403
+ }
2404
+ function readJsonObject(path) {
2405
+ try {
2406
+ return JSON.parse(readFileSync2(path, "utf8"));
2407
+ } catch {
2408
+ return {};
2409
+ }
2410
+ }
2411
+ function readText(path) {
2412
+ try {
2413
+ return readFileSync2(path, "utf8");
2414
+ } catch {
2415
+ return "";
2416
+ }
2417
+ }
2418
+ function userCodexConfigPaths(home = homedir3()) {
2419
+ return [join5(home, ".codex", "config.toml"), join5(home, ".config", "codex", "config.toml")];
2420
+ }
2421
+ function userOpencodeConfigPaths(home = homedir3()) {
2422
+ return [
2423
+ join5(home, ".config", "opencode", "opencode.json"),
2424
+ join5(home, ".config", "opencode", "opencode.jsonc")
2425
+ ];
2426
+ }
2427
+ function userMcpNamesToDisable(opts) {
2428
+ const keep = new Set(
2429
+ [...opts.injectedNames ?? []].map((n) => n.trim().toLowerCase()).filter(Boolean)
2430
+ );
2431
+ const out = [];
2432
+ const seen = /* @__PURE__ */ new Set();
2433
+ for (const raw of opts.names) {
2434
+ const name = raw.trim();
2435
+ if (!name) continue;
2436
+ const key = name.toLowerCase();
2437
+ if (seen.has(key) || keep.has(key) || isInjectedOrchMcpName(name)) continue;
2438
+ seen.add(key);
2439
+ out.push(name);
2440
+ }
2441
+ return out;
2442
+ }
2443
+ function listUserCodexMcpNames(home = homedir3()) {
2444
+ const names = [];
2445
+ for (const path of userCodexConfigPaths(home)) {
2446
+ if (!existsSync7(path)) continue;
2447
+ names.push(...listMcpNamesFromCodexToml(readText(path)));
2448
+ }
2449
+ return names;
2450
+ }
2451
+ function listUserOpencodeMcpNames(home = homedir3()) {
2452
+ const names = [];
2453
+ for (const path of userOpencodeConfigPaths(home)) {
2454
+ if (!existsSync7(path)) continue;
2455
+ names.push(...listMcpNamesFromJsonMap(readJsonObject(path), "mcp"));
2456
+ }
2457
+ return names;
2458
+ }
2459
+ function toCodexDisableUserMcpArgs(names) {
2460
+ const args = [];
2461
+ for (const name of names) {
2462
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) continue;
2463
+ args.push("-c", `mcp_servers.${name}.enabled=false`);
2464
+ }
2465
+ return args;
2466
+ }
2467
+
2468
+ // src/agents/codex.ts
2324
2469
  var CODEX_PROMPT_ARG_MAX = 2e5;
2325
2470
  var FALLBACK_CODEX_MODELS = [
2326
2471
  { id: "gpt-5.6-sol", displayName: "GPT-5.6 Sol" },
@@ -2340,7 +2485,7 @@ async function listCodexModels() {
2340
2485
  if (codex === "codex") {
2341
2486
  const which = await run("which", ["codex"], { reject: false });
2342
2487
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
2343
- } else if (!existsSync6(codex)) {
2488
+ } else if (!existsSync8(codex)) {
2344
2489
  return FALLBACK_CODEX_MODELS;
2345
2490
  }
2346
2491
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -2375,12 +2520,12 @@ function usageFromCodex(usage) {
2375
2520
  }
2376
2521
  function codexConfigHasNetworkAccess() {
2377
2522
  const candidates = [
2378
- join4(homedir2(), ".codex", "config.toml"),
2379
- join4(homedir2(), ".config", "codex", "config.toml")
2523
+ join6(homedir4(), ".codex", "config.toml"),
2524
+ join6(homedir4(), ".config", "codex", "config.toml")
2380
2525
  ];
2381
2526
  for (const path of candidates) {
2382
- if (!existsSync6(path)) continue;
2383
- const text = readFileSync(path, "utf8");
2527
+ if (!existsSync8(path)) continue;
2528
+ const text = readFileSync3(path, "utf8");
2384
2529
  if (/network_access\s*=\s*true/.test(text)) return true;
2385
2530
  }
2386
2531
  return false;
@@ -2412,8 +2557,8 @@ function asRecord2(value) {
2412
2557
  return void 0;
2413
2558
  }
2414
2559
  function codexLooksAuthenticated() {
2415
- const authPath = join4(homedir2(), ".codex", "auth.json");
2416
- if (!existsSync6(authPath)) return false;
2560
+ const authPath = join6(homedir4(), ".codex", "auth.json");
2561
+ if (!existsSync8(authPath)) return false;
2417
2562
  try {
2418
2563
  return statSync(authPath).size > 2;
2419
2564
  } catch {
@@ -2425,7 +2570,7 @@ var codexAdapter = {
2425
2570
  async detect() {
2426
2571
  const codex = resolveAgentExecutable("codex");
2427
2572
  if (codex !== "codex") {
2428
- if (!existsSync6(codex)) {
2573
+ if (!existsSync8(codex)) {
2429
2574
  return {
2430
2575
  agent: "codex",
2431
2576
  installed: false,
@@ -2485,7 +2630,15 @@ var codexAdapter = {
2485
2630
  }),
2486
2631
  orchestratorThreadId: isOrchestrator ? thread.id : null
2487
2632
  });
2488
- const mcpOverrides = toCodexMcpConfigArgs(injected);
2633
+ const mcpOverrides = [
2634
+ ...toCodexMcpConfigArgs(injected),
2635
+ ...isOrchestrator ? toCodexDisableUserMcpArgs(
2636
+ userMcpNamesToDisable({
2637
+ injectedNames: injected.map((s) => s.name),
2638
+ names: listUserCodexMcpNames()
2639
+ })
2640
+ ) : []
2641
+ ];
2489
2642
  const execOpts = [
2490
2643
  // Global orchestration cwd is not a git repo; without this Codex ≥0.147
2491
2644
  // refuses to start ("Not inside a trusted directory").
@@ -2685,9 +2838,9 @@ var codexAdapter = {
2685
2838
  };
2686
2839
 
2687
2840
  // src/agents/cursor.ts
2688
- import { existsSync as existsSync8 } from "fs";
2841
+ import { existsSync as existsSync10 } from "fs";
2689
2842
  import { createRequire as createRequire3 } from "module";
2690
- import { dirname as dirname3, join as join6 } from "path";
2843
+ import { dirname as dirname4, join as join8 } from "path";
2691
2844
  import { fileURLToPath as fileURLToPath2 } from "url";
2692
2845
  import { Cursor } from "@cursor/sdk";
2693
2846
 
@@ -2903,9 +3056,9 @@ function parseCursorRunnerLine(line) {
2903
3056
  }
2904
3057
 
2905
3058
  // src/agents/cursor-ripgrep.ts
2906
- import { existsSync as existsSync7 } from "fs";
3059
+ import { existsSync as existsSync9 } from "fs";
2907
3060
  import { createRequire as createRequire2 } from "module";
2908
- import { dirname as dirname2, isAbsolute, join as join5, parse, resolve as resolvePath } from "path";
3061
+ import { dirname as dirname3, isAbsolute, join as join7, parse, resolve as resolvePath } from "path";
2909
3062
  var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
2910
3063
  function rgBinaryName() {
2911
3064
  return process.platform === "win32" ? "rg.exe" : "rg";
@@ -2917,19 +3070,19 @@ function usableRipgrepPath(candidate) {
2917
3070
  const raw = candidate?.trim();
2918
3071
  if (!raw || !isAbsolute(raw)) return null;
2919
3072
  const readable = nodeReadableScriptPath(raw);
2920
- if (!existsSync7(readable) || isAsarPath(readable)) return null;
3073
+ if (!existsSync9(readable) || isAsarPath(readable)) return null;
2921
3074
  return readable;
2922
3075
  }
2923
3076
  function walkForBundledRipgrep(startFile) {
2924
3077
  if (!startFile) return null;
2925
3078
  const pkg = platformRipgrepPackage();
2926
3079
  const name = rgBinaryName();
2927
- let dir = dirname2(resolvePath(startFile));
3080
+ let dir = dirname3(resolvePath(startFile));
2928
3081
  const root = parse(dir).root;
2929
3082
  while (dir !== root) {
2930
- const hit = usableRipgrepPath(join5(dir, "node_modules", pkg, "bin", name));
3083
+ const hit = usableRipgrepPath(join7(dir, "node_modules", pkg, "bin", name));
2931
3084
  if (hit) return hit;
2932
- const next = dirname2(dir);
3085
+ const next = dirname3(dir);
2933
3086
  if (next === dir) break;
2934
3087
  dir = next;
2935
3088
  }
@@ -2939,7 +3092,7 @@ function requireResolveBundledRipgrep(fromFile) {
2939
3092
  try {
2940
3093
  const req = createRequire2(fromFile);
2941
3094
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
2942
- return usableRipgrepPath(join5(dirname2(pkgJson), "bin", rgBinaryName()));
3095
+ return usableRipgrepPath(join7(dirname3(pkgJson), "bin", rgBinaryName()));
2943
3096
  } catch {
2944
3097
  return null;
2945
3098
  }
@@ -3008,11 +3161,11 @@ function entryDir() {
3008
3161
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
3009
3162
  if (cjsDir) return cjsDir;
3010
3163
  try {
3011
- return dirname3(fileURLToPath2(import.meta.url));
3164
+ return dirname4(fileURLToPath2(import.meta.url));
3012
3165
  } catch {
3013
3166
  try {
3014
3167
  const req = createRequire3(process.cwd() + "/");
3015
- return dirname3(req.resolve("@sideboard-ai/core"));
3168
+ return dirname4(req.resolve("@sideboard-ai/core"));
3016
3169
  } catch {
3017
3170
  return process.cwd();
3018
3171
  }
@@ -3023,17 +3176,17 @@ function cursorRunnerPath() {
3023
3176
  if (packaged) return packaged;
3024
3177
  const root = entryDir();
3025
3178
  const candidates = [
3026
- join6(root, "agents", "cursor-runner.js"),
3027
- join6(root, "agents", "cursor-runner.cjs"),
3179
+ join8(root, "agents", "cursor-runner.js"),
3180
+ join8(root, "agents", "cursor-runner.cjs"),
3028
3181
  // If somehow resolved from package root instead of dist/
3029
- join6(root, "dist", "agents", "cursor-runner.js"),
3030
- join6(root, "dist", "agents", "cursor-runner.cjs"),
3182
+ join8(root, "dist", "agents", "cursor-runner.js"),
3183
+ join8(root, "dist", "agents", "cursor-runner.cjs"),
3031
3184
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
3032
- join6(root, "cursor-runner.ts"),
3033
- join6(root, "src", "agents", "cursor-runner.ts")
3185
+ join8(root, "cursor-runner.ts"),
3186
+ join8(root, "src", "agents", "cursor-runner.ts")
3034
3187
  ];
3035
3188
  for (const candidate of candidates) {
3036
- if (existsSync8(candidate)) return candidate;
3189
+ if (existsSync10(candidate)) return candidate;
3037
3190
  }
3038
3191
  return candidates[0];
3039
3192
  }
@@ -3082,6 +3235,7 @@ var cursorAdapter = {
3082
3235
  fast: thread.fast,
3083
3236
  planMode: thread.planMode,
3084
3237
  apiKey,
3238
+ ...isOrchestrator ? { isolateAmbientMcp: true } : {},
3085
3239
  ...Object.keys(mcpServers).length > 0 ? { mcpServers } : {}
3086
3240
  };
3087
3241
  const runner = cursorRunnerPath();
@@ -3120,7 +3274,7 @@ var cursorAdapter = {
3120
3274
  };
3121
3275
 
3122
3276
  // src/agents/opencode.ts
3123
- import { existsSync as existsSync9 } from "fs";
3277
+ import { existsSync as existsSync11 } from "fs";
3124
3278
  var FALLBACK_OPENCODE_MODELS = [
3125
3279
  { id: "opencode/big-pickle", displayName: "opencode \xB7 big-pickle" },
3126
3280
  {
@@ -3179,7 +3333,7 @@ async function listOpencodeModels() {
3179
3333
  if (opencode === "opencode") {
3180
3334
  const which = await run("which", ["opencode"], { reject: false });
3181
3335
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
3182
- } else if (!existsSync9(opencode)) {
3336
+ } else if (!existsSync11(opencode)) {
3183
3337
  return FALLBACK_OPENCODE_MODELS;
3184
3338
  }
3185
3339
  const listed = await run(opencode, ["models"], { reject: false });
@@ -3214,7 +3368,7 @@ var opencodeAdapter = {
3214
3368
  async detect() {
3215
3369
  const opencode = resolveAgentExecutable("opencode");
3216
3370
  if (opencode !== "opencode") {
3217
- if (!existsSync9(opencode)) {
3371
+ if (!existsSync11(opencode)) {
3218
3372
  return {
3219
3373
  agent: "opencode",
3220
3374
  installed: false,
@@ -3276,7 +3430,11 @@ var opencodeAdapter = {
3276
3430
  }),
3277
3431
  orchestratorThreadId: isOrchestrator ? thread.id : null
3278
3432
  });
3279
- const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
3433
+ const disableNames = isOrchestrator ? userMcpNamesToDisable({
3434
+ injectedNames: injected.map((s) => s.name),
3435
+ names: listUserOpencodeMcpNames()
3436
+ }) : [];
3437
+ const mcpContent = injected.length > 0 || disableNames.length > 0 ? toOpencodeMcpConfigContent(injected, { disableNames }) : null;
3280
3438
  return {
3281
3439
  file: resolveAgentExecutable("opencode"),
3282
3440
  args,
@@ -3949,6 +4107,7 @@ export {
3949
4107
  applyAgentRunnerHeapEnv,
3950
4108
  PLAN_MODE_INSTRUCTION,
3951
4109
  permissionMode,
4110
+ mcpStatusThinkingFromClaudeInit,
3952
4111
  claudeAdapter,
3953
4112
  listCodexModels,
3954
4113
  codexAdapter,