@khalilgharbaoui/opencode-claude-code-plugin 0.56.0 → 0.57.0

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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/claude-code-language-model.ts
2
- import { join as join17 } from "path";
2
+ import { join as join18 } from "path";
3
3
 
4
4
  // src/ids.ts
5
5
  import { randomInt } from "crypto";
@@ -717,6 +717,7 @@ var MAX_USAGE_ACCOUNTS = 32;
717
717
  var MAX_USAGE_WINDOWS = 8;
718
718
  var NAME = /^[a-z0-9_-]{1,64}$/;
719
719
  var STATUS = /^[a-z_]{1,32}$/;
720
+ var TIER = /^[A-Za-z0-9][A-Za-z0-9 ]{0,23}$/;
720
721
  var MAX_RESETS_TEXT = 80;
721
722
  var pathOverride = null;
722
723
  var cache = null;
@@ -750,11 +751,28 @@ function validEntry(value) {
750
751
  noted
751
752
  };
752
753
  }
753
- function readStore(file, now) {
754
+ var emptyStore = () => ({ usage: /* @__PURE__ */ new Map(), known: /* @__PURE__ */ new Map() });
755
+ function readKnown(parsed) {
754
756
  const out = /* @__PURE__ */ new Map();
757
+ const known = parsed.known;
758
+ if (!known || typeof known !== "object" || Array.isArray(known)) return out;
759
+ for (const [account, raw] of Object.entries(known)) {
760
+ if (out.size >= MAX_USAGE_ACCOUNTS) break;
761
+ if (!NAME.test(account) || !raw || typeof raw !== "object" || Array.isArray(raw)) continue;
762
+ const record = raw;
763
+ if (!finite(record.at)) continue;
764
+ const tier = typeof record.tier === "string" && TIER.test(record.tier) ? record.tier : void 0;
765
+ out.set(account, { ...tier ? { tier } : {}, at: record.at });
766
+ }
767
+ return out;
768
+ }
769
+ function parseStore(file, now) {
770
+ const out = emptyStore();
755
771
  try {
756
772
  const parsed = JSON.parse(readFileSync(file, "utf8"));
757
- const accounts = parsed && typeof parsed === "object" ? parsed.accounts : null;
773
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return out;
774
+ out.known = readKnown(parsed);
775
+ const accounts = parsed.accounts;
758
776
  if (!accounts || typeof accounts !== "object" || Array.isArray(accounts)) return out;
759
777
  const cutoff = now - USAGE_READING_MAX_AGE_MS;
760
778
  for (const [account, windows] of Object.entries(accounts)) {
@@ -765,12 +783,15 @@ function readStore(file, now) {
765
783
  const entry = validEntry(raw);
766
784
  if (entry && entry.observedAt >= cutoff) kept.set(window, entry);
767
785
  }
768
- if (kept.size > 0) out.set(account, kept);
786
+ if (kept.size > 0) out.usage.set(account, kept);
769
787
  }
770
788
  } catch {
771
789
  }
772
790
  return out;
773
791
  }
792
+ function readStore(file, now) {
793
+ return parseStore(file, now).usage;
794
+ }
774
795
  function newestObserved(windows) {
775
796
  let newest = 0;
776
797
  for (const entry of windows.values()) newest = Math.max(newest, entry.observedAt);
@@ -784,13 +805,14 @@ function bounded(usage, now) {
784
805
  }).filter(([, windows]) => windows.size > 0).sort((a, b) => newestObserved(a[1]) - newestObserved(b[1])).slice(-MAX_USAGE_ACCOUNTS);
785
806
  return new Map(accounts);
786
807
  }
787
- function writeStore(file, usage) {
808
+ function writeStore(file, usage, known) {
788
809
  const accounts = {};
789
810
  for (const [account, windows] of usage) accounts[account] = Object.fromEntries(windows);
811
+ const registered2 = known.size > 0 ? { known: Object.fromEntries(known) } : {};
790
812
  try {
791
813
  mkdirSync2(join2(file, ".."), { recursive: true, mode: 448 });
792
814
  const tmp = `${file}.${process.pid}.tmp`;
793
- writeFileSync(tmp, JSON.stringify({ version: 1, accounts }), { mode: 384 });
815
+ writeFileSync(tmp, JSON.stringify({ version: 1, accounts, ...registered2 }), { mode: 384 });
794
816
  renameSync2(tmp, file);
795
817
  return true;
796
818
  } catch {
@@ -845,7 +867,8 @@ function resolveUsageSwitchAt(value) {
845
867
  function recordUsageReading(account, window, reading, now = Date.now()) {
846
868
  if (!NAME.test(account) || !NAME.test(window)) return null;
847
869
  const file = accountUsageStorePath();
848
- const merged = readStore(file, now);
870
+ const store = parseStore(file, now);
871
+ const merged = store.usage;
849
872
  const previous = merged.get(account)?.get(window) ?? cached(now).get(account)?.get(window);
850
873
  const entry = applyReading(previous, reading, now);
851
874
  const windows = merged.get(account) ?? /* @__PURE__ */ new Map();
@@ -853,12 +876,13 @@ function recordUsageReading(account, window, reading, now = Date.now()) {
853
876
  merged.set(account, windows);
854
877
  const kept = bounded(merged, now);
855
878
  cache = { path: file, usage: kept };
856
- return writeStore(file, kept) ? entry : null;
879
+ return writeStore(file, kept, store.known) ? entry : null;
857
880
  }
858
881
  function markUsageNoted(account, window, thresholds, now = Date.now()) {
859
882
  if (!NAME.test(account) || !NAME.test(window) || thresholds.length === 0) return false;
860
883
  const file = accountUsageStorePath();
861
- const merged = readStore(file, now);
884
+ const store = parseStore(file, now);
885
+ const merged = store.usage;
862
886
  const entry = merged.get(account)?.get(window) ?? cached(now).get(account)?.get(window);
863
887
  if (!entry) return false;
864
888
  const updated = {
@@ -870,7 +894,28 @@ function markUsageNoted(account, window, thresholds, now = Date.now()) {
870
894
  merged.set(account, windows);
871
895
  const kept = bounded(merged, now);
872
896
  cache = { path: file, usage: kept };
873
- return writeStore(file, kept);
897
+ return writeStore(file, kept, store.known);
898
+ }
899
+ function sameKnown(a, b) {
900
+ if (a.size !== b.size) return false;
901
+ for (const [account, record] of a) {
902
+ const other = b.get(account);
903
+ if (!other || other.tier !== record.tier) return false;
904
+ }
905
+ return true;
906
+ }
907
+ function registerKnownAccounts(accounts, now = Date.now()) {
908
+ const file = accountUsageStorePath();
909
+ const store = parseStore(file, now);
910
+ const known = /* @__PURE__ */ new Map();
911
+ for (const entry of accounts) {
912
+ if (known.size >= MAX_USAGE_ACCOUNTS) break;
913
+ if (!NAME.test(entry.account)) continue;
914
+ const tier = entry.tier && TIER.test(entry.tier) ? entry.tier : void 0;
915
+ known.set(entry.account, { ...tier ? { tier } : {}, at: now });
916
+ }
917
+ if (sameKnown(store.known, known)) return true;
918
+ return writeStore(file, bounded(store.usage, now), known);
874
919
  }
875
920
  function usageCrossings(account, thresholds, now = Date.now()) {
876
921
  if (thresholds.length === 0) return [];
@@ -13267,7 +13312,7 @@ function isRecord5(value) {
13267
13312
  if (!record || typeof record !== "object" || Array.isArray(record)) return false;
13268
13313
  if (typeof record.at !== "number" || !Number.isFinite(record.at)) return false;
13269
13314
  const ok = (field) => field === void 0 || typeof field === "string";
13270
- if (!ok(record.model) || !ok(record.effort) || !ok(record.account)) return false;
13315
+ if (!ok(record.model) || !ok(record.effort) || !ok(record.account) || !ok(record.agent)) return false;
13271
13316
  return !!record.model;
13272
13317
  }
13273
13318
  function readEntries(file) {
@@ -13283,6 +13328,7 @@ function readEntries(file) {
13283
13328
  model: record.model,
13284
13329
  ...record.effort ? { effort: record.effort } : {},
13285
13330
  ...record.account ? { account: record.account } : {},
13331
+ ...record.agent ? { agent: record.agent } : {},
13286
13332
  at: record.at
13287
13333
  });
13288
13334
  }
@@ -13296,11 +13342,13 @@ function recordSessionSpawn(sessionID, spawn2, now = Date.now()) {
13296
13342
  model: spawn2.model,
13297
13343
  ...spawn2.effort ? { effort: spawn2.effort } : {},
13298
13344
  ...spawn2.account ? { account: spawn2.account } : {},
13345
+ ...spawn2.agent ? { agent: spawn2.agent } : {},
13299
13346
  at: now
13300
13347
  };
13301
13348
  const fingerprint = `${record.model}
13302
13349
  ${record.effort ?? ""}
13303
- ${record.account ?? ""}`;
13350
+ ${record.account ?? ""}
13351
+ ${record.agent ?? ""}`;
13304
13352
  if (lastWritten.get(sessionID) === fingerprint) return false;
13305
13353
  const file = spawnRecordStorePath();
13306
13354
  const merged = readEntries(file);
@@ -13323,6 +13371,133 @@ ${record.account ?? ""}`;
13323
13371
  return true;
13324
13372
  }
13325
13373
 
13374
+ // src/turn-history.ts
13375
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync10, renameSync as renameSync6, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
13376
+ import { homedir as homedir13 } from "os";
13377
+ import { join as join16 } from "path";
13378
+ var MAX_TURN_SAMPLES = 48;
13379
+ var MAX_TURN_KEYS = 64;
13380
+ var TURN_SAMPLE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
13381
+ var CHARS_BANDWIDTH = Math.log(4);
13382
+ var pathOverride5 = null;
13383
+ function turnHistoryStorePath() {
13384
+ if (pathOverride5) return pathOverride5;
13385
+ const stateRoot = process.env.XDG_STATE_HOME || join16(homedir13(), ".local", "state");
13386
+ return join16(stateRoot, "opencode-claude-code-plugin", "turn-history.json");
13387
+ }
13388
+ function turnHistoryKey(agent, model) {
13389
+ return `${agent || "main"}/${model}`;
13390
+ }
13391
+ var INJECTED_BLOCKS = [
13392
+ /<system-reminder>[\s\S]*?<\/system-reminder>/g,
13393
+ /<dcp-system-reminder>[\s\S]*?<\/dcp-system-reminder>/g,
13394
+ /<dcp-message-id>[\s\S]*?<\/dcp-message-id>/g
13395
+ ];
13396
+ function promptChars(texts) {
13397
+ if (texts.length === 0) return void 0;
13398
+ let total = 0;
13399
+ for (const text of texts) {
13400
+ let stripped = text;
13401
+ for (const block of INJECTED_BLOCKS) stripped = stripped.replace(block, "");
13402
+ total += stripped.trim().length;
13403
+ }
13404
+ return total;
13405
+ }
13406
+ function textsOf(content) {
13407
+ if (typeof content === "string") return [content];
13408
+ if (!Array.isArray(content)) return [];
13409
+ const texts = [];
13410
+ for (const part of content) {
13411
+ if (!part || typeof part !== "object" || part.type !== "text") continue;
13412
+ const text = part.text;
13413
+ if (typeof text === "string") texts.push(text);
13414
+ }
13415
+ return texts;
13416
+ }
13417
+ function newestPromptChars(prompt) {
13418
+ for (let index = prompt.length - 1; index >= 0; index -= 1) {
13419
+ if (prompt[index].role === "user") return promptChars(textsOf(prompt[index].content));
13420
+ }
13421
+ return void 0;
13422
+ }
13423
+ function startsTurn(prompt) {
13424
+ const last = prompt[prompt.length - 1];
13425
+ if (!last || last.role !== "user") return false;
13426
+ const before = prompt[prompt.length - 2];
13427
+ return before === void 0 || before.role !== "tool";
13428
+ }
13429
+ var MAX_TURN_STARTS = 256;
13430
+ var turnStarts = /* @__PURE__ */ new Map();
13431
+ function markTurnStart(key, at, chars) {
13432
+ turnStarts.delete(key);
13433
+ if (turnStarts.size >= MAX_TURN_STARTS) {
13434
+ const oldest = turnStarts.keys().next().value;
13435
+ if (oldest !== void 0) turnStarts.delete(oldest);
13436
+ }
13437
+ turnStarts.set(key, { at, ...chars !== void 0 ? { chars } : {} });
13438
+ }
13439
+ function takeTurnStart(key) {
13440
+ const start = turnStarts.get(key);
13441
+ turnStarts.delete(key);
13442
+ return start;
13443
+ }
13444
+ function isSample(value) {
13445
+ const sample = value;
13446
+ if (!sample || typeof sample !== "object" || Array.isArray(sample)) return false;
13447
+ if (typeof sample.ms !== "number" || !Number.isFinite(sample.ms) || sample.ms < 0) return false;
13448
+ if (typeof sample.at !== "number" || !Number.isFinite(sample.at)) return false;
13449
+ if (sample.chars !== void 0 && (typeof sample.chars !== "number" || !Number.isFinite(sample.chars) || sample.chars < 0)) {
13450
+ return false;
13451
+ }
13452
+ if (sample.effort !== void 0 && typeof sample.effort !== "string") return false;
13453
+ return true;
13454
+ }
13455
+ function cleanSample(sample) {
13456
+ return {
13457
+ ms: Math.round(sample.ms),
13458
+ ...sample.chars !== void 0 ? { chars: Math.round(sample.chars) } : {},
13459
+ ...sample.effort ? { effort: sample.effort } : {},
13460
+ at: sample.at
13461
+ };
13462
+ }
13463
+ function readEntries2(file, now) {
13464
+ const out = /* @__PURE__ */ new Map();
13465
+ try {
13466
+ const parsed = JSON.parse(readFileSync10(file, "utf8"));
13467
+ const entries = parsed && typeof parsed === "object" ? parsed.turns : null;
13468
+ if (!entries || typeof entries !== "object") return out;
13469
+ const cutoff = now - TURN_SAMPLE_MAX_AGE_MS;
13470
+ for (const [key, value] of Object.entries(entries)) {
13471
+ if (!key || !Array.isArray(value)) continue;
13472
+ const samples = value.filter(isSample).filter((sample) => sample.at >= cutoff).sort((a, b) => a.at - b.at).slice(-MAX_TURN_SAMPLES).map(cleanSample);
13473
+ if (samples.length > 0) out.set(key, samples);
13474
+ }
13475
+ } catch {
13476
+ }
13477
+ return out;
13478
+ }
13479
+ function bounded2(history) {
13480
+ const newest = (samples) => samples[samples.length - 1]?.at ?? 0;
13481
+ return new Map([...history.entries()].sort((a, b) => newest(a[1]) - newest(b[1])).slice(-MAX_TURN_KEYS));
13482
+ }
13483
+ function recordTurnSample(key, sample) {
13484
+ if (!key || !isSample(sample)) return false;
13485
+ const file = turnHistoryStorePath();
13486
+ const merged = readEntries2(file, sample.at);
13487
+ const samples = [...merged.get(key) ?? [], cleanSample(sample)].sort((a, b) => a.at - b.at).slice(-MAX_TURN_SAMPLES);
13488
+ merged.set(key, samples);
13489
+ const kept = bounded2(merged);
13490
+ try {
13491
+ mkdirSync8(join16(file, ".."), { recursive: true, mode: 448 });
13492
+ const tmp = `${file}.${process.pid}.tmp`;
13493
+ writeFileSync9(tmp, JSON.stringify({ version: 1, turns: Object.fromEntries(kept) }), { mode: 384 });
13494
+ renameSync6(tmp, file);
13495
+ } catch {
13496
+ return false;
13497
+ }
13498
+ return true;
13499
+ }
13500
+
13326
13501
  // src/account-transcript.ts
13327
13502
  import { randomUUID as randomUUID6 } from "crypto";
13328
13503
  import { constants as fsConstants } from "fs";
@@ -13384,13 +13559,13 @@ function dedupe2(dirs) {
13384
13559
  }
13385
13560
 
13386
13561
  // src/prompts.ts
13387
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
13388
- import { homedir as homedir13 } from "os";
13562
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "fs";
13563
+ import { homedir as homedir14 } from "os";
13389
13564
  import { randomUUID as randomUUID7 } from "crypto";
13390
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join16 } from "path";
13565
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join17 } from "path";
13391
13566
  function readPromptFileIfPresent(path15) {
13392
13567
  try {
13393
- const content = readFileSync10(path15, "utf8").trim();
13568
+ const content = readFileSync11(path15, "utf8").trim();
13394
13569
  return content || void 0;
13395
13570
  } catch {
13396
13571
  return void 0;
@@ -13399,7 +13574,7 @@ function readPromptFileIfPresent(path15) {
13399
13574
  function nearestWorkspaceAgentsPrompt(cwd) {
13400
13575
  let dir = cwd;
13401
13576
  while (true) {
13402
- const content = readPromptFileIfPresent(join16(dir, "AGENTS.md"));
13577
+ const content = readPromptFileIfPresent(join17(dir, "AGENTS.md"));
13403
13578
  if (content) return content;
13404
13579
  const parent = dirname6(dir);
13405
13580
  if (parent === dir) return void 0;
@@ -13510,7 +13685,7 @@ var CLAUDE_NATIVE_INSTRUCTION_FILES = /* @__PURE__ */ new Set(["CLAUDE.md", "CLA
13510
13685
  function userAuthoredInstructions(forwarded, opts = {}) {
13511
13686
  const readFile3 = opts.readFile ?? ((path15) => {
13512
13687
  try {
13513
- return readFileSync10(path15, "utf8");
13688
+ return readFileSync11(path15, "utf8");
13514
13689
  } catch {
13515
13690
  return null;
13516
13691
  }
@@ -13551,8 +13726,8 @@ ${options.compressionSummary.trim()}`
13551
13726
  for (const s of extraSystemContent) {
13552
13727
  if (s.trim()) parts.push(s.trim());
13553
13728
  }
13554
- const configRoot = process.env.XDG_CONFIG_HOME ?? join16(homedir13(), ".config");
13555
- const globalAgents = readPromptFileIfPresent(join16(configRoot, "opencode", "AGENTS.md"));
13729
+ const configRoot = process.env.XDG_CONFIG_HOME ?? join17(homedir14(), ".config");
13730
+ const globalAgents = readPromptFileIfPresent(join17(configRoot, "opencode", "AGENTS.md"));
13556
13731
  const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd);
13557
13732
  const forwarded = extraSystemContent.join("\n\n");
13558
13733
  const pushGlobal = !!globalAgents && !forwarded.includes(globalAgents);
@@ -13568,9 +13743,9 @@ ${options.compressionSummary.trim()}`
13568
13743
  if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT);
13569
13744
  const content = parts.join("\n\n");
13570
13745
  if (!content) return void 0;
13571
- const path15 = join16(pluginTmpDir(), `opencode-cc-sys-${randomUUID7()}.md`);
13746
+ const path15 = join17(pluginTmpDir(), `opencode-cc-sys-${randomUUID7()}.md`);
13572
13747
  try {
13573
- writeFileSync9(path15, content, { encoding: "utf8", mode: 384 });
13748
+ writeFileSync10(path15, content, { encoding: "utf8", mode: 384 });
13574
13749
  return path15;
13575
13750
  } catch (err) {
13576
13751
  log.warn("failed to write system prompt file", { error: String(err) });
@@ -16712,6 +16887,7 @@ var ClaudeCodeLanguageModel = class {
16712
16887
  const autoSwitch = accountRun?.switchTo;
16713
16888
  if (accountRun) accountRun.switchTo = void 0;
16714
16889
  const turnAbort = watchTurnAbort(options.abortSignal);
16890
+ const turnStartedAt = Date.now();
16715
16891
  const abortedBeforeWork = (stage) => {
16716
16892
  log.info("abort before the turn asked claude for work; nothing spawned", {
16717
16893
  stage,
@@ -16971,8 +17147,12 @@ var ClaudeCodeLanguageModel = class {
16971
17147
  recordSessionSpawn(affinity, {
16972
17148
  model: stripAccountSuffix(failover.modelId),
16973
17149
  effort: reasoningEffort,
16974
- account: (this.config.failoverAccounts?.length ?? 0) > 1 ? failover.target ?? sourceAccount : void 0
17150
+ account: (this.config.failoverAccounts?.length ?? 0) > 1 ? failover.target ?? sourceAccount : void 0,
17151
+ agent: this.getOpencodeAgent(options)
16975
17152
  });
17153
+ if (startsTurn(options.prompt)) {
17154
+ markTurnStart(sk, turnStartedAt, newestPromptChars(options.prompt));
17155
+ }
16976
17156
  }
16977
17157
  const hasPriorConversation = options.prompt.filter((m) => m.role === "user" || m.role === "assistant").length > 1;
16978
17158
  if (!hasPriorConversation && !autoSwitch) {
@@ -17262,7 +17442,7 @@ var ClaudeCodeLanguageModel = class {
17262
17442
  let replayReason = "no-session-for-key";
17263
17443
  if (this.config.resumeAfterRestart !== false && includeHistoryContext && !compactionMode && !forkFromClaudeSessionId && failoverAnswer?.kind !== "switch") {
17264
17444
  const configDir = resolveConfigDir(this.config.configDir);
17265
- const transcriptPath2 = (id, dir) => join17(dir ?? configDir, "projects", encodeCwd(cwd), `${id}.jsonl`);
17445
+ const transcriptPath2 = (id, dir) => join18(dir ?? configDir, "projects", encodeCwd(cwd), `${id}.jsonl`);
17266
17446
  const resumePoint = findResumePoint({
17267
17447
  sessionKey: sk,
17268
17448
  prompt: options.prompt,
@@ -18325,6 +18505,18 @@ var ClaudeCodeLanguageModel = class {
18325
18505
  state.resultFailure ??= "usage_limit";
18326
18506
  }
18327
18507
  if (runAutoContinue(state, msg)) return;
18508
+ if (!compactionMode && affinity !== "default" && msg.is_error !== true && state.resultFailure === void 0) {
18509
+ const start = takeTurnStart(sk);
18510
+ if (start) {
18511
+ const endedAt = Date.now();
18512
+ recordTurnSample(turnHistoryKey(self.getOpencodeAgent(options), stripAccountSuffix(failover.modelId)), {
18513
+ ms: endedAt - start.at,
18514
+ chars: start.chars,
18515
+ effort: reasoningEffort,
18516
+ at: endedAt
18517
+ });
18518
+ }
18519
+ }
18328
18520
  for (const [idx, reasoningId] of state.reasoningIds) {
18329
18521
  if (state.reasoningStarted.get(idx)) {
18330
18522
  controller.enqueue({
@@ -18775,7 +18967,7 @@ var ClaudeCodeLanguageModel = class {
18775
18967
  };
18776
18968
 
18777
18969
  // src/account-tier.ts
18778
- import { readFileSync as readFileSync11 } from "fs";
18970
+ import { readFileSync as readFileSync12 } from "fs";
18779
18971
  import path14 from "path";
18780
18972
  var ORGANIZATION_TYPE_LABELS = {
18781
18973
  claude_max: "Max",
@@ -18818,7 +19010,7 @@ function readTierFromConfigDir(configDir, allowLegacyFallback) {
18818
19010
  function readOauthAccount(file) {
18819
19011
  let raw;
18820
19012
  try {
18821
- raw = readFileSync11(file, "utf8");
19013
+ raw = readFileSync12(file, "utf8");
18822
19014
  } catch {
18823
19015
  return void 0;
18824
19016
  }
@@ -18842,18 +19034,27 @@ function tierLabel(oauthAccount) {
18842
19034
  const multiple = typeof rateLimitTier === "string" ? RATE_LIMIT_TIER_LABELS[rateLimitTier] : void 0;
18843
19035
  return multiple ? `${base} ${multiple}` : base;
18844
19036
  }
19037
+ function registerSidebarAccounts(accounts) {
19038
+ const list2 = accounts && accounts.length > 0 ? accounts : [DEFAULT_ACCOUNT];
19039
+ registerKnownAccounts(
19040
+ list2.map((account) => ({
19041
+ account: normalizeAccountName(account) || DEFAULT_ACCOUNT,
19042
+ tier: readAccountTier(account)
19043
+ }))
19044
+ );
19045
+ }
18845
19046
 
18846
19047
  // src/cleanup-stale.ts
18847
19048
  import {
18848
19049
  existsSync as existsSync5,
18849
- mkdirSync as mkdirSync8,
18850
- readFileSync as readFileSync12,
19050
+ mkdirSync as mkdirSync9,
19051
+ readFileSync as readFileSync13,
18851
19052
  realpathSync as realpathSync4,
18852
19053
  rmSync as rmSync3,
18853
- writeFileSync as writeFileSync10
19054
+ writeFileSync as writeFileSync11
18854
19055
  } from "fs";
18855
- import { homedir as homedir14 } from "os";
18856
- import { dirname as dirname7, join as join18, resolve as resolve6 } from "path";
19056
+ import { homedir as homedir15 } from "os";
19057
+ import { dirname as dirname7, join as join19, resolve as resolve6 } from "path";
18857
19058
  import { fileURLToPath as fileURLToPath4 } from "url";
18858
19059
  var STALE_PACKAGE_NAME = "opencode-claude-code-plugin";
18859
19060
  var SUSPECT_DESCRIPTION_TOKEN = "Claude Code";
@@ -18861,20 +19062,20 @@ var alreadyRan = false;
18861
19062
  function candidateCacheRoots() {
18862
19063
  const xdg = process.env.XDG_CACHE_HOME;
18863
19064
  return [
18864
- xdg ? join18(xdg, "opencode") : null,
18865
- join18(homedir14(), ".cache", "opencode"),
18866
- join18(homedir14(), "Library", "Caches", "opencode")
19065
+ xdg ? join19(xdg, "opencode") : null,
19066
+ join19(homedir15(), ".cache", "opencode"),
19067
+ join19(homedir15(), "Library", "Caches", "opencode")
18867
19068
  ].filter((p) => Boolean(p));
18868
19069
  }
18869
19070
  function userOpencodeJsonPath() {
18870
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join18(homedir14(), ".config");
18871
- return join18(xdgConfig, "opencode", "opencode.json");
19071
+ const xdgConfig = process.env.XDG_CONFIG_HOME ?? join19(homedir15(), ".config");
19072
+ return join19(xdgConfig, "opencode", "opencode.json");
18872
19073
  }
18873
19074
  function userIntendsToUseUnscoped() {
18874
19075
  const cfg = userOpencodeJsonPath();
18875
19076
  if (!existsSync5(cfg)) return false;
18876
19077
  try {
18877
- const json = JSON.parse(readFileSync12(cfg, "utf8"));
19078
+ const json = JSON.parse(readFileSync13(cfg, "utf8"));
18878
19079
  const plugins = json.plugin;
18879
19080
  if (!Array.isArray(plugins)) return false;
18880
19081
  return plugins.some(
@@ -18895,19 +19096,19 @@ function ourLoadedDir() {
18895
19096
  function ourVersion(dir) {
18896
19097
  if (!dir) return null;
18897
19098
  try {
18898
- const pkg = JSON.parse(readFileSync12(join18(dir, "package.json"), "utf8"));
19099
+ const pkg = JSON.parse(readFileSync13(join19(dir, "package.json"), "utf8"));
18899
19100
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
18900
19101
  } catch {
18901
19102
  return null;
18902
19103
  }
18903
19104
  }
18904
19105
  function markerPath() {
18905
- const stateRoot = process.env.XDG_STATE_HOME ?? join18(homedir14(), ".local", "state");
18906
- return join18(stateRoot, "opencode-claude-code-plugin", "cleanup-stale.json");
19106
+ const stateRoot = process.env.XDG_STATE_HOME ?? join19(homedir15(), ".local", "state");
19107
+ return join19(stateRoot, "opencode-claude-code-plugin", "cleanup-stale.json");
18907
19108
  }
18908
19109
  function markerVersion() {
18909
19110
  try {
18910
- const marker = JSON.parse(readFileSync12(markerPath(), "utf8"));
19111
+ const marker = JSON.parse(readFileSync13(markerPath(), "utf8"));
18911
19112
  return typeof marker.version === "string" ? marker.version : null;
18912
19113
  } catch {
18913
19114
  return null;
@@ -18916,8 +19117,8 @@ function markerVersion() {
18916
19117
  function writeMarker(version) {
18917
19118
  const file = markerPath();
18918
19119
  try {
18919
- mkdirSync8(dirname7(file), { recursive: true, mode: 448 });
18920
- writeFileSync10(
19120
+ mkdirSync9(dirname7(file), { recursive: true, mode: 448 });
19121
+ writeFileSync11(
18921
19122
  file,
18922
19123
  JSON.stringify({ version, at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2) + "\n",
18923
19124
  "utf8"
@@ -18952,7 +19153,7 @@ function cleanupStaleUnscopedInstall() {
18952
19153
  }
18953
19154
  function cleanupOne(cacheRoot, ourDir) {
18954
19155
  if (!existsSync5(cacheRoot)) return;
18955
- const stalePath = join18(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
19156
+ const stalePath = join19(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
18956
19157
  if (!existsSync5(stalePath)) return;
18957
19158
  let realStalePath = stalePath;
18958
19159
  try {
@@ -18960,11 +19161,11 @@ function cleanupOne(cacheRoot, ourDir) {
18960
19161
  } catch {
18961
19162
  }
18962
19163
  if (ourDir && realStalePath === ourDir) return;
18963
- const pkgJsonPath = join18(stalePath, "package.json");
19164
+ const pkgJsonPath = join19(stalePath, "package.json");
18964
19165
  if (!existsSync5(pkgJsonPath)) return;
18965
19166
  let pkg = {};
18966
19167
  try {
18967
- pkg = JSON.parse(readFileSync12(pkgJsonPath, "utf8"));
19168
+ pkg = JSON.parse(readFileSync13(pkgJsonPath, "utf8"));
18968
19169
  } catch {
18969
19170
  return;
18970
19171
  }
@@ -18980,13 +19181,13 @@ function cleanupOne(cacheRoot, ourDir) {
18980
19181
  });
18981
19182
  return;
18982
19183
  }
18983
- const cachePkgJson = join18(cacheRoot, "package.json");
19184
+ const cachePkgJson = join19(cacheRoot, "package.json");
18984
19185
  if (!existsSync5(cachePkgJson)) return;
18985
19186
  try {
18986
- const cfg = JSON.parse(readFileSync12(cachePkgJson, "utf8"));
19187
+ const cfg = JSON.parse(readFileSync13(cachePkgJson, "utf8"));
18987
19188
  if (cfg?.dependencies?.[STALE_PACKAGE_NAME]) {
18988
19189
  delete cfg.dependencies[STALE_PACKAGE_NAME];
18989
- writeFileSync10(cachePkgJson, JSON.stringify(cfg, null, 2) + "\n");
19190
+ writeFileSync11(cachePkgJson, JSON.stringify(cfg, null, 2) + "\n");
18990
19191
  log.info("cleanup-stale: pruned dep from cache package.json");
18991
19192
  }
18992
19193
  } catch (err) {
@@ -19413,6 +19614,7 @@ function createV2Setup(deps) {
19413
19614
  )
19414
19615
  };
19415
19616
  const plans = planV2Providers(seedSettings, deps.defaultProxyTools);
19617
+ registerSidebarAccounts(resolveAccounts(seedSettings.accounts));
19416
19618
  planned.clear();
19417
19619
  for (const plan of plans) {
19418
19620
  planned.set(plan.info.id, plan.info.settings ?? {});
@@ -19954,6 +20156,7 @@ var server = async (input) => {
19954
20156
  registerBundledSkillPath(config);
19955
20157
  config.provider ??= {};
19956
20158
  await buildAgentRegistry(config);
20159
+ registerSidebarAccounts(resolveAccounts(config.provider[PROVIDER_ID2]?.options?.accounts));
19957
20160
  const expanded = await expandAccountProviders(config);
19958
20161
  if (expanded) {
19959
20162
  logStartupDiagnostics(