@khalilgharbaoui/opencode-claude-code-plugin 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -311,7 +311,7 @@ Set `permissionMode: "plan"` to forward `--permission-mode plan` to Claude. The
311
311
 
312
312
  - **Empty text blocks are dropped.** Claude sometimes opens a `content_block_start` for text but never sends a delta. The plugin no longer emits the empty block (which was triggering Anthropic 400s like `cache_control cannot be set for empty text blocks`).
313
313
  - **`AskUserQuestion`** from the CLI is converted into plain text content rather than forwarded as a tool call.
314
- - **Result fallback timer.** If the CLI finishes a text block but never sends a `result` message, the stream closes gracefully after 5 seconds rather than hanging.
314
+ - **Wire-inactivity watchdog.** Once the CLI has produced any content, the stream closes gracefully if stdout goes silent for 60 seconds without a `result` message arriving. Resets on every line received, so long mid-turn pauses (Sonnet between text-end and the next tool_use, for example) are tolerated. On a user-initiated abort, the watchdog shortens to 5 seconds.
315
315
  - **Per-iteration usage.** When the CLI internally retries with tools, the plugin only counts the last iteration's usage so opencode's context accounting stays accurate.
316
316
  - **Lazy `cwd`.** The working directory is re-resolved at every request, so opencode's project-aware behavior works without restarting the plugin.
317
317
  - **Variants survive merge.** opencode recalculates variant lists after the plugin loads; the plugin re-injects defaults into runtime config so your variants don't disappear.
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ var log = {
19
19
  console.error(fmt("NOTICE", msg, data));
20
20
  },
21
21
  warn(msg, data) {
22
- if (DEBUG) console.error(fmt("WARN", msg, data));
22
+ console.error(fmt("WARN", msg, data));
23
23
  },
24
24
  error(msg, data) {
25
25
  console.error(fmt("ERROR", msg, data));
@@ -381,22 +381,49 @@ Now continuing with the current message:
381
381
  }
382
382
 
383
383
  // src/mcp-bridge.ts
384
+ import * as fs2 from "fs";
385
+ import * as path2 from "path";
386
+ import * as os2 from "os";
387
+ import * as crypto from "crypto";
388
+
389
+ // src/tmp.ts
384
390
  import * as fs from "fs";
385
- import * as path from "path";
386
391
  import * as os from "os";
387
- import * as crypto from "crypto";
392
+ import * as path from "path";
393
+ var PLUGIN_TMP_DIR = path.join(
394
+ os.tmpdir(),
395
+ `opencode-claude-code-${process.pid}`
396
+ );
397
+ var registered = false;
398
+ function pluginTmpDir() {
399
+ if (!fs.existsSync(PLUGIN_TMP_DIR)) {
400
+ fs.mkdirSync(PLUGIN_TMP_DIR, { recursive: true });
401
+ }
402
+ if (!registered) {
403
+ registered = true;
404
+ process.on("exit", () => {
405
+ try {
406
+ fs.rmSync(PLUGIN_TMP_DIR, { recursive: true, force: true });
407
+ } catch {
408
+ }
409
+ });
410
+ }
411
+ return PLUGIN_TMP_DIR;
412
+ }
413
+
414
+ // src/mcp-bridge.ts
388
415
  var FILE_NAMES = ["opencode.jsonc", "opencode.json", "config.json"];
389
416
  var PROJECT_FILE_NAMES = ["opencode.json", "opencode.jsonc"];
390
417
  function fileExists(p) {
391
418
  try {
392
- return fs.statSync(p).isFile();
419
+ return fs2.statSync(p).isFile();
393
420
  } catch {
394
421
  return false;
395
422
  }
396
423
  }
397
424
  function dirExists(p) {
398
425
  try {
399
- return fs.statSync(p).isDirectory();
426
+ return fs2.statSync(p).isDirectory();
400
427
  } catch {
401
428
  return false;
402
429
  }
@@ -442,7 +469,7 @@ function stripJsonComments(text) {
442
469
  }
443
470
  function readAndParse(file) {
444
471
  try {
445
- const raw = fs.readFileSync(file, "utf8");
472
+ const raw = fs2.readFileSync(file, "utf8");
446
473
  return JSON.parse(stripJsonComments(raw));
447
474
  } catch (e) {
448
475
  log.warn("failed to parse opencode config", {
@@ -470,14 +497,14 @@ function deepMerge(target, source) {
470
497
  }
471
498
  function walkUp(opts) {
472
499
  const out = [];
473
- let current = path.resolve(opts.start);
500
+ let current = path2.resolve(opts.start);
474
501
  while (true) {
475
502
  for (const target of opts.targets) {
476
- const candidate = path.join(current, target);
503
+ const candidate = path2.join(current, target);
477
504
  if (opts.predicate(candidate)) out.push(candidate);
478
505
  }
479
- if (opts.stop && current === path.resolve(opts.stop)) break;
480
- const parent = path.dirname(current);
506
+ if (opts.stop && current === path2.resolve(opts.stop)) break;
507
+ const parent = path2.dirname(current);
481
508
  if (parent === current) break;
482
509
  current = parent;
483
510
  }
@@ -485,28 +512,28 @@ function walkUp(opts) {
485
512
  }
486
513
  function detectWorktree(cwd) {
487
514
  const override = process.env.OPENCODE_WORKTREE;
488
- if (override) return path.resolve(override);
489
- let current = path.resolve(cwd);
515
+ if (override) return path2.resolve(override);
516
+ let current = path2.resolve(cwd);
490
517
  while (true) {
491
- const gitPath = path.join(current, ".git");
518
+ const gitPath = path2.join(current, ".git");
492
519
  try {
493
- if (fs.existsSync(gitPath)) return current;
520
+ if (fs2.existsSync(gitPath)) return current;
494
521
  } catch {
495
522
  }
496
- const parent = path.dirname(current);
523
+ const parent = path2.dirname(current);
497
524
  if (parent === current) return void 0;
498
525
  current = parent;
499
526
  }
500
527
  }
501
528
  function globalConfigDir() {
502
- const xdg = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config");
503
- return path.join(xdg, "opencode");
529
+ const xdg = process.env.XDG_CONFIG_HOME ?? path2.join(os2.homedir(), ".config");
530
+ return path2.join(xdg, "opencode");
504
531
  }
505
532
  function loadGlobalConfig() {
506
533
  const dir = globalConfigDir();
507
534
  let merged = {};
508
535
  for (const name of FILE_NAMES.slice().reverse()) {
509
- const file = path.join(dir, name);
536
+ const file = path2.join(dir, name);
510
537
  if (!fileExists(file)) continue;
511
538
  const parsed = readAndParse(file);
512
539
  if (parsed) merged = deepMerge(merged, parsed);
@@ -516,7 +543,7 @@ function loadGlobalConfig() {
516
543
  function loadProjectFilesInDir(dir) {
517
544
  let merged = {};
518
545
  for (const name of PROJECT_FILE_NAMES) {
519
- const file = path.join(dir, name);
546
+ const file = path2.join(dir, name);
520
547
  if (!fileExists(file)) continue;
521
548
  const parsed = readAndParse(file);
522
549
  if (parsed) merged = deepMerge(merged, parsed);
@@ -527,7 +554,7 @@ function dotOpencodeDirs(cwd, worktree) {
527
554
  const dirs = [];
528
555
  const seen = /* @__PURE__ */ new Set();
529
556
  const push = (p) => {
530
- const abs = path.resolve(p);
557
+ const abs = path2.resolve(p);
531
558
  if (!seen.has(abs) && dirExists(abs)) {
532
559
  seen.add(abs);
533
560
  dirs.push(abs);
@@ -541,9 +568,9 @@ function dotOpencodeDirs(cwd, worktree) {
541
568
  })) {
542
569
  push(dir);
543
570
  }
544
- const home = os.homedir();
571
+ const home = os2.homedir();
545
572
  if (home) {
546
- const homeDot = path.join(home, ".opencode");
573
+ const homeDot = path2.join(home, ".opencode");
547
574
  if (dirExists(homeDot)) push(homeDot);
548
575
  }
549
576
  const envDir = process.env.OPENCODE_CONFIG_DIR;
@@ -628,7 +655,7 @@ function bridgeOpencodeMcp(cwd, runtimeStatus) {
628
655
  const projectDirs = [];
629
656
  const seenProjectDirs = /* @__PURE__ */ new Set();
630
657
  for (const f of projectFiles) {
631
- const d = path.dirname(f);
658
+ const d = path2.dirname(f);
632
659
  if (!seenProjectDirs.has(d)) {
633
660
  seenProjectDirs.add(d);
634
661
  projectDirs.push(d);
@@ -658,13 +685,13 @@ function bridgeOpencodeMcp(cwd, runtimeStatus) {
658
685
  if (Object.keys(servers).length === 0) return null;
659
686
  const body = JSON.stringify({ mcpServers: servers }, null, 2);
660
687
  const hash = crypto.createHash("sha256").update(body).digest("hex").slice(0, 12);
661
- const outPath = path.join(
662
- os.tmpdir(),
663
- `opencode-claude-code-mcp-${hash}.json`
688
+ const outPath = path2.join(
689
+ pluginTmpDir(),
690
+ `mcp-${hash}.json`
664
691
  );
665
692
  try {
666
693
  if (!fileExists(outPath)) {
667
- fs.writeFileSync(outPath, body, { encoding: "utf8", mode: 384 });
694
+ fs2.writeFileSync(outPath, body, { encoding: "utf8", mode: 384 });
668
695
  }
669
696
  } catch (e) {
670
697
  log.warn("failed to write bridged MCP config", {
@@ -872,14 +899,14 @@ function sessionKey(cwd, modelId) {
872
899
 
873
900
  // src/proxy-mcp.ts
874
901
  import { createServer } from "http";
875
- import * as fs2 from "fs";
876
- import * as path2 from "path";
877
- import * as os2 from "os";
902
+ import * as fs3 from "fs";
903
+ import * as path3 from "path";
878
904
  import * as crypto2 from "crypto";
879
905
  import { EventEmitter as EventEmitter2 } from "events";
880
906
  var PROTOCOL_VERSION = "2024-11-05";
881
907
  var SERVER_NAME = "opencode_proxy";
882
908
  var PROXY_TOOL_PREFIX = `mcp__${SERVER_NAME}__`;
909
+ var PROXY_CALL_TIMEOUT_MS = 10 * 60 * 1e3;
883
910
  var DEFAULT_PROXY_TOOLS = [
884
911
  {
885
912
  name: "bash",
@@ -1050,6 +1077,7 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
1050
1077
  toolName,
1051
1078
  hasInput: input != null
1052
1079
  });
1080
+ let timer = null;
1053
1081
  const result = await new Promise(
1054
1082
  (resolve3, reject) => {
1055
1083
  const entry = {
@@ -1060,9 +1088,24 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
1060
1088
  reject
1061
1089
  };
1062
1090
  pending.set(callId, entry);
1091
+ timer = setTimeout(() => {
1092
+ if (!pending.has(callId)) return;
1093
+ pending.delete(callId);
1094
+ log.warn("proxy-mcp tool call timed out", {
1095
+ callId,
1096
+ toolName,
1097
+ timeoutMs: PROXY_CALL_TIMEOUT_MS
1098
+ });
1099
+ reject(
1100
+ new Error(
1101
+ `Proxy tool '${toolName}' timed out after ${PROXY_CALL_TIMEOUT_MS}ms waiting for opencode to resolve the call`
1102
+ )
1103
+ );
1104
+ }, PROXY_CALL_TIMEOUT_MS);
1063
1105
  calls.emit("call", entry);
1064
1106
  }
1065
1107
  ).finally(() => {
1108
+ if (timer) clearTimeout(timer);
1066
1109
  pending.delete(callId);
1067
1110
  });
1068
1111
  if (result.kind === "error") {
@@ -1151,11 +1194,11 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
1151
1194
  2
1152
1195
  );
1153
1196
  const hash = crypto2.createHash("sha256").update(body).digest("hex").slice(0, 12);
1154
- const outPath = path2.join(
1155
- os2.tmpdir(),
1156
- `opencode-claude-code-proxy-${hash}.json`
1197
+ const outPath = path3.join(
1198
+ pluginTmpDir(),
1199
+ `proxy-${hash}.json`
1157
1200
  );
1158
- fs2.writeFileSync(outPath, body, { encoding: "utf8", mode: 384 });
1201
+ fs3.writeFileSync(outPath, body, { encoding: "utf8", mode: 384 });
1159
1202
  configFilePath = outPath;
1160
1203
  return outPath;
1161
1204
  },
@@ -1167,6 +1210,13 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
1167
1210
  await new Promise((resolve3) => {
1168
1211
  server2.close(() => resolve3());
1169
1212
  });
1213
+ if (configFilePath) {
1214
+ try {
1215
+ fs3.unlinkSync(configFilePath);
1216
+ } catch {
1217
+ }
1218
+ configFilePath = null;
1219
+ }
1170
1220
  }
1171
1221
  };
1172
1222
  return api;
@@ -1266,9 +1316,9 @@ function resolvePendingProxyCall(sessionKey2, result) {
1266
1316
  // src/claude-code-language-model.ts
1267
1317
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
1268
1318
  import { unlink as unlink2 } from "fs/promises";
1269
- import { homedir as homedir2, tmpdir as tmpdir3 } from "os";
1319
+ import { homedir as homedir2, tmpdir as tmpdir2 } from "os";
1270
1320
  import { randomUUID as randomUUID2 } from "crypto";
1271
- import { dirname as dirname2, join as join3 } from "path";
1321
+ import { dirname as dirname2, join as join4 } from "path";
1272
1322
  function hasNewUserContent(prompt) {
1273
1323
  for (let i = prompt.length - 1; i >= 0; i--) {
1274
1324
  const msg = prompt[i];
@@ -1283,14 +1333,15 @@ function hasNewUserContent(prompt) {
1283
1333
  for (const part of content) {
1284
1334
  if (part.type === "text" && part.text && part.text.trim()) return true;
1285
1335
  if (part.type === "tool-result") return true;
1336
+ if (part.type === "image" || part.type === "file") return true;
1286
1337
  }
1287
1338
  }
1288
1339
  }
1289
1340
  return false;
1290
1341
  }
1291
- function readPromptFileIfPresent(path4) {
1342
+ function readPromptFileIfPresent(path5) {
1292
1343
  try {
1293
- const content = readFileSync2(path4, "utf8").trim();
1344
+ const content = readFileSync2(path5, "utf8").trim();
1294
1345
  return content || void 0;
1295
1346
  } catch {
1296
1347
  return void 0;
@@ -1299,7 +1350,7 @@ function readPromptFileIfPresent(path4) {
1299
1350
  function nearestWorkspaceAgentsPrompt(cwd) {
1300
1351
  let dir = cwd;
1301
1352
  while (true) {
1302
- const content = readPromptFileIfPresent(join3(dir, "AGENTS.md"));
1353
+ const content = readPromptFileIfPresent(join4(dir, "AGENTS.md"));
1303
1354
  if (content) return content;
1304
1355
  const parent = dirname2(dir);
1305
1356
  if (parent === dir) return void 0;
@@ -1308,17 +1359,17 @@ function nearestWorkspaceAgentsPrompt(cwd) {
1308
1359
  }
1309
1360
  function buildAppendedSystemPrompt(cwd) {
1310
1361
  const parts = [];
1311
- const configRoot = process.env.XDG_CONFIG_HOME ?? join3(homedir2(), ".config");
1312
- const globalAgents = readPromptFileIfPresent(join3(configRoot, "opencode", "AGENTS.md"));
1362
+ const configRoot = process.env.XDG_CONFIG_HOME ?? join4(homedir2(), ".config");
1363
+ const globalAgents = readPromptFileIfPresent(join4(configRoot, "opencode", "AGENTS.md"));
1313
1364
  const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd);
1314
1365
  if (globalAgents) parts.push(globalAgents);
1315
1366
  if (workspaceAgents && workspaceAgents !== globalAgents) parts.push(workspaceAgents);
1316
1367
  const content = parts.join("\n\n");
1317
1368
  if (!content) return void 0;
1318
- const path4 = join3(tmpdir3(), `opencode-cc-sys-${randomUUID2()}.md`);
1369
+ const path5 = join4(tmpdir2(), `opencode-cc-sys-${randomUUID2()}.md`);
1319
1370
  try {
1320
- writeFileSync3(path4, content, "utf8");
1321
- return path4;
1371
+ writeFileSync3(path5, content, "utf8");
1372
+ return path5;
1322
1373
  } catch (err) {
1323
1374
  log.warn("failed to write system prompt file", { error: String(err) });
1324
1375
  return void 0;
@@ -2889,7 +2940,7 @@ var defaultModels = {
2889
2940
 
2890
2941
  // src/accounts.ts
2891
2942
  import { chmod, lstat, mkdir, readlink, symlink, writeFile } from "fs/promises";
2892
- import path3 from "path";
2943
+ import path4 from "path";
2893
2944
  var BASE_PROVIDER_ID = "claude-code";
2894
2945
  var DEFAULT_ACCOUNT = "default";
2895
2946
  var SHARED_CAPABILITY_ITEMS = [
@@ -2927,7 +2978,7 @@ function expandHome(value) {
2927
2978
  const home = process.env.HOME ?? process.env.USERPROFILE;
2928
2979
  if (value === "~") return home ?? value;
2929
2980
  if (value.startsWith("~/") || value.startsWith("~\\")) {
2930
- return home ? path3.join(home, value.slice(2)) : value;
2981
+ return home ? path4.join(home, value.slice(2)) : value;
2931
2982
  }
2932
2983
  return value;
2933
2984
  }
@@ -2959,8 +3010,8 @@ async function ensureSharedCapabilities(targetRoot) {
2959
3010
  }
2960
3011
  }
2961
3012
  async function ensureSharedCapabilityItem(sourceRoot, targetRoot, item) {
2962
- const source = path3.join(sourceRoot, item);
2963
- const target = path3.join(targetRoot, item);
3013
+ const source = path4.join(sourceRoot, item);
3014
+ const target = path4.join(targetRoot, item);
2964
3015
  let sourceStat;
2965
3016
  try {
2966
3017
  sourceStat = await lstat(source);
@@ -2971,8 +3022,8 @@ async function ensureSharedCapabilityItem(sourceRoot, targetRoot, item) {
2971
3022
  const targetStat = await lstat(target);
2972
3023
  if (targetStat.isSymbolicLink()) {
2973
3024
  const current = await readlink(target);
2974
- const resolvedCurrent = path3.resolve(path3.dirname(target), current);
2975
- const resolvedSource = path3.resolve(source);
3025
+ const resolvedCurrent = path4.resolve(path4.dirname(target), current);
3026
+ const resolvedSource = path4.resolve(source);
2976
3027
  if (resolvedCurrent === resolvedSource) return;
2977
3028
  }
2978
3029
  log.warn("shared Claude capability already exists; leaving untouched", {
@@ -2987,11 +3038,11 @@ async function ensureSharedCapabilityItem(sourceRoot, targetRoot, item) {
2987
3038
  await symlink(source, target, type);
2988
3039
  }
2989
3040
  async function writeAccountWrapper(account, baseCliPath, configDir) {
2990
- const cacheRoot = path3.join(
3041
+ const cacheRoot = path4.join(
2991
3042
  process.env.XDG_CACHE_HOME ?? expandHome("~/.cache"),
2992
3043
  "opencode-claude-code-plugin"
2993
3044
  );
2994
- const wrapperPath = path3.join(cacheRoot, `claude-${account}`);
3045
+ const wrapperPath = path4.join(cacheRoot, `claude-${account}`);
2995
3046
  const suffix = `@${account}`;
2996
3047
  await mkdir(cacheRoot, { recursive: true });
2997
3048
  const script = `#!/usr/bin/env bash
@@ -3031,14 +3082,14 @@ function titleizeAccount(account) {
3031
3082
 
3032
3083
  // src/cleanup-stale.ts
3033
3084
  import {
3034
- existsSync as existsSync2,
3085
+ existsSync as existsSync3,
3035
3086
  readFileSync as readFileSync3,
3036
3087
  realpathSync,
3037
- rmSync,
3088
+ rmSync as rmSync2,
3038
3089
  writeFileSync as writeFileSync4
3039
3090
  } from "fs";
3040
3091
  import { homedir as homedir3 } from "os";
3041
- import { join as join4, resolve as resolve2 } from "path";
3092
+ import { join as join5, resolve as resolve2 } from "path";
3042
3093
  import { fileURLToPath } from "url";
3043
3094
  var STALE_PACKAGE_NAME = "opencode-claude-code-plugin";
3044
3095
  var SUSPECT_DESCRIPTION_TOKEN = "Claude Code";
@@ -3046,18 +3097,18 @@ var alreadyRan = false;
3046
3097
  function candidateCacheRoots() {
3047
3098
  const xdg = process.env.XDG_CACHE_HOME;
3048
3099
  return [
3049
- xdg ? join4(xdg, "opencode") : null,
3050
- join4(homedir3(), ".cache", "opencode"),
3051
- join4(homedir3(), "Library", "Caches", "opencode")
3100
+ xdg ? join5(xdg, "opencode") : null,
3101
+ join5(homedir3(), ".cache", "opencode"),
3102
+ join5(homedir3(), "Library", "Caches", "opencode")
3052
3103
  ].filter((p) => Boolean(p));
3053
3104
  }
3054
3105
  function userOpencodeJsonPath() {
3055
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join4(homedir3(), ".config");
3056
- return join4(xdgConfig, "opencode", "opencode.json");
3106
+ const xdgConfig = process.env.XDG_CONFIG_HOME ?? join5(homedir3(), ".config");
3107
+ return join5(xdgConfig, "opencode", "opencode.json");
3057
3108
  }
3058
3109
  function userIntendsToUseUnscoped() {
3059
3110
  const cfg = userOpencodeJsonPath();
3060
- if (!existsSync2(cfg)) return false;
3111
+ if (!existsSync3(cfg)) return false;
3061
3112
  try {
3062
3113
  const json = JSON.parse(readFileSync3(cfg, "utf8"));
3063
3114
  const plugins = json.plugin;
@@ -3095,17 +3146,17 @@ function cleanupStaleUnscopedInstall() {
3095
3146
  }
3096
3147
  }
3097
3148
  function cleanupOne(cacheRoot, ourDir) {
3098
- if (!existsSync2(cacheRoot)) return;
3099
- const stalePath = join4(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
3100
- if (!existsSync2(stalePath)) return;
3149
+ if (!existsSync3(cacheRoot)) return;
3150
+ const stalePath = join5(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
3151
+ if (!existsSync3(stalePath)) return;
3101
3152
  let realStalePath = stalePath;
3102
3153
  try {
3103
3154
  realStalePath = realpathSync(stalePath);
3104
3155
  } catch {
3105
3156
  }
3106
3157
  if (ourDir && realStalePath === ourDir) return;
3107
- const pkgJsonPath = join4(stalePath, "package.json");
3108
- if (!existsSync2(pkgJsonPath)) return;
3158
+ const pkgJsonPath = join5(stalePath, "package.json");
3159
+ if (!existsSync3(pkgJsonPath)) return;
3109
3160
  let pkg = {};
3110
3161
  try {
3111
3162
  pkg = JSON.parse(readFileSync3(pkgJsonPath, "utf8"));
@@ -3116,7 +3167,7 @@ function cleanupOne(cacheRoot, ourDir) {
3116
3167
  if (!pkg.description?.includes(SUSPECT_DESCRIPTION_TOKEN)) return;
3117
3168
  log.info("cleanup-stale: removing unscoped install", { stalePath });
3118
3169
  try {
3119
- rmSync(stalePath, { recursive: true, force: true });
3170
+ rmSync2(stalePath, { recursive: true, force: true });
3120
3171
  } catch (err) {
3121
3172
  log.warn("cleanup-stale: rmSync failed", {
3122
3173
  stalePath,
@@ -3124,8 +3175,8 @@ function cleanupOne(cacheRoot, ourDir) {
3124
3175
  });
3125
3176
  return;
3126
3177
  }
3127
- const cachePkgJson = join4(cacheRoot, "package.json");
3128
- if (!existsSync2(cachePkgJson)) return;
3178
+ const cachePkgJson = join5(cacheRoot, "package.json");
3179
+ if (!existsSync3(cachePkgJson)) return;
3129
3180
  try {
3130
3181
  const cfg = JSON.parse(readFileSync3(cachePkgJson, "utf8"));
3131
3182
  if (cfg?.dependencies?.[STALE_PACKAGE_NAME]) {
@@ -3342,12 +3393,12 @@ var server = async (input) => {
3342
3393
  config.provider ??= {};
3343
3394
  const expanded = await expandAccountProviders(config);
3344
3395
  if (expanded) {
3345
- const registered = Object.entries(config.provider).filter(([id]) => id === PROVIDER_ID2 || id.startsWith(`${PROVIDER_ID2}-`)).map(([id, p]) => ({
3396
+ const registered2 = Object.entries(config.provider).filter(([id]) => id === PROVIDER_ID2 || id.startsWith(`${PROVIDER_ID2}-`)).map(([id, p]) => ({
3346
3397
  id,
3347
3398
  name: p?.name ?? id,
3348
3399
  cwd: p?.options?.cwd
3349
3400
  }));
3350
- log.notice("registered claude-code providers", { providers: registered });
3401
+ log.notice("registered claude-code providers", { providers: registered2 });
3351
3402
  return;
3352
3403
  }
3353
3404
  const existing = config.provider[PROVIDER_ID2];