@khalilgharbaoui/opencode-claude-code-plugin 0.61.1 → 0.62.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
@@ -906,6 +906,44 @@ function recordUsageReading(account, window, reading, now = Date.now()) {
906
906
  cache = { path: file, usage: kept };
907
907
  return writeStore(file, kept, store.known) ? entry : null;
908
908
  }
909
+ function usageReadingsFromObservation(observation, previous, now = Date.now()) {
910
+ const out = [];
911
+ const windows = observation.windows ?? {};
912
+ const limiting = observation.window;
913
+ if (limiting && observation.status) {
914
+ const own = windows[limiting];
915
+ out.push([
916
+ limiting,
917
+ {
918
+ utilization: finite(observation.utilization) ? observation.utilization : own && finite(own.utilization) ? own.utilization : null,
919
+ resetsAt: finite(observation.resetsAt) ? observation.resetsAt : own?.resetsAt,
920
+ status: observation.status
921
+ }
922
+ ]);
923
+ }
924
+ for (const [window, own] of Object.entries(windows)) {
925
+ if (window === limiting || !finite(own.utilization)) continue;
926
+ const before = previous(window);
927
+ const stillRefused = before !== void 0 && before.status === "rejected" && isReadingCurrent(before, now) && own.utilization >= 1;
928
+ out.push([window, { utilization: own.utilization, resetsAt: own.resetsAt, status: stillRefused ? "rejected" : "allowed" }]);
929
+ }
930
+ return out;
931
+ }
932
+ function recordRateLimitObservation(account, observation, now = Date.now()) {
933
+ if (!NAME.test(account)) return false;
934
+ const file = accountUsageStorePath();
935
+ const store = parseStore(file, now);
936
+ const merged = store.usage;
937
+ const windows = merged.get(account) ?? /* @__PURE__ */ new Map();
938
+ const previous = (window) => windows.get(window) ?? cached(now).get(account)?.get(window);
939
+ const readings = usageReadingsFromObservation(observation, previous, now).filter(([window]) => NAME.test(window));
940
+ if (readings.length === 0) return false;
941
+ for (const [window, reading] of readings) windows.set(window, applyReading(previous(window), reading, now));
942
+ merged.set(account, windows);
943
+ const kept = bounded(merged, now);
944
+ cache = { path: file, usage: kept };
945
+ return writeStore(file, kept, store.known);
946
+ }
909
947
  function markUsageNoted(account, window, thresholds, now = Date.now()) {
910
948
  if (!NAME.test(account) || !NAME.test(window) || thresholds.length === 0) return false;
911
949
  const file = accountUsageStorePath();
@@ -992,6 +1030,18 @@ function str(value) {
992
1030
  function num(value) {
993
1031
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
994
1032
  }
1033
+ function parseUnifiedWindows(value) {
1034
+ if (!isRecord(value)) return void 0;
1035
+ const out = {};
1036
+ for (const [window, raw] of Object.entries(value)) {
1037
+ if (!isRecord(raw)) continue;
1038
+ const utilization = num(raw.utilization);
1039
+ if (utilization === void 0 || utilization < 0) continue;
1040
+ const resetsAt = num(raw.resetsAt);
1041
+ out[window] = resetsAt === void 0 ? { utilization } : { utilization, resetsAt };
1042
+ }
1043
+ return Object.keys(out).length > 0 ? out : void 0;
1044
+ }
995
1045
  var RATE_LIMIT_MARKER = "\u258C **rate limit:**";
996
1046
  var RATE_LIMIT_ACTION = "Enable extra usage or add credits on the account, wait for the window to reset, switch account, org or plan, or authenticate with an API key.";
997
1047
  var OVERAGE_DISABLED_REASONS = {
@@ -1020,6 +1070,7 @@ function parseRateLimitEvent(msg) {
1020
1070
  if (msg.type !== "rate_limit_event") return null;
1021
1071
  const info = msg.rate_limit_info;
1022
1072
  if (!isRecord(info)) return null;
1073
+ const windows = parseUnifiedWindows(info.unifiedWindows);
1023
1074
  return {
1024
1075
  status: str(info.status),
1025
1076
  rateLimitType: str(info.rateLimitType),
@@ -1028,7 +1079,8 @@ function parseRateLimitEvent(msg) {
1028
1079
  isUsingOverage: info.isUsingOverage === true,
1029
1080
  overageStatus: str(info.overageStatus),
1030
1081
  overageResetsAt: num(info.overageResetsAt),
1031
- overageDisabledReason: str(info.overageDisabledReason)
1082
+ overageDisabledReason: str(info.overageDisabledReason),
1083
+ ...windows ? { windows } : {}
1032
1084
  };
1033
1085
  }
1034
1086
  function resetsAtToMs(resetsAt) {
@@ -12471,7 +12523,7 @@ function collectSkills(root, claimed, found) {
12471
12523
  if (!skill) continue;
12472
12524
  const winner = claimed.get(skill.name);
12473
12525
  if (winner) {
12474
- if (!sameSkill(winner, skill)) {
12526
+ if (!sameSkill(winner, skill) && firstSkillWarning(`dup:${skill.name}:${winner.dir}:${skill.dir}`)) {
12475
12527
  log.warn("two different skills share a name; bridging the one the nearest root claimed", {
12476
12528
  name: skill.name,
12477
12529
  bridged: winner.dir,
@@ -12484,6 +12536,12 @@ function collectSkills(root, claimed, found) {
12484
12536
  found.push(skill);
12485
12537
  }
12486
12538
  }
12539
+ var warnedSkillClashes = /* @__PURE__ */ new Set();
12540
+ function firstSkillWarning(key) {
12541
+ if (warnedSkillClashes.has(key)) return false;
12542
+ warnedSkillClashes.add(key);
12543
+ return true;
12544
+ }
12487
12545
  var byName = (a, b) => a.name.localeCompare(b.name);
12488
12546
  function discoverOpencodeSkills(cwd) {
12489
12547
  const found = [];
@@ -12584,7 +12642,7 @@ function dropNativelyLoadedSkills(skills, native) {
12584
12642
  }
12585
12643
  const reason = sameCopy ? "same-copy" : sameContent ? "same-content" : "name-taken";
12586
12644
  skipped.push({ skill, native: nameTaken, reason });
12587
- if (reason === "name-taken") {
12645
+ if (reason === "name-taken" && firstSkillWarning(`taken:${skill.name}:${nameTaken.dir}:${skill.dir}`)) {
12588
12646
  log.warn("claude already registers a different skill under this name; not bridging ours", {
12589
12647
  name: skill.name,
12590
12648
  claudeLoads: nameTaken.dir,
@@ -15222,7 +15280,8 @@ function resolvedProxyMcpTools(config, allEnabledServerNames, modelTools, taken,
15222
15280
  if (route === "withhold") withheld.push(server2);
15223
15281
  else if (route === "bridge") bridged.push(server2);
15224
15282
  }
15225
- if (codeMode && resolution.defs.length === 0) {
15283
+ if (codeMode && resolution.defs.length === 0 && !codeModeProxyWarned) {
15284
+ codeModeProxyWarned = true;
15226
15285
  log.warn(
15227
15286
  "proxyOpencodeMcpTools cannot route V2 Code Mode's MCP tools, which reach the model through execute; for Code Mode, explicitly allowlist execute in proxyOpencodeTools and use bridgeOpencodeMcp: false with strictMcpConfig: true",
15228
15287
  { servers: allEnabledServerNames }
@@ -15401,6 +15460,7 @@ function warnCliCapsOnInteractive(caps) {
15401
15460
  "agent maxTurns / maxBudgetUsd not applied: the interactive transport cannot pass print-only flags"
15402
15461
  );
15403
15462
  }
15463
+ var codeModeProxyWarned = false;
15404
15464
 
15405
15465
  // src/mcp-hot-reload.ts
15406
15466
  var DEFAULT_MCP_HOT_RELOAD_COOLDOWN_MS = 6e4;
@@ -16536,11 +16596,18 @@ function createLineHandler(state, ctx) {
16536
16596
  };
16537
16597
  rememberAccountLimit(ctx.sourceAccount, state.accountLimitHit);
16538
16598
  }
16539
- if (info?.rateLimitType && info.status) {
16540
- recordUsageReading(ctx.usageAccount, info.rateLimitType, {
16541
- utilization: info.utilization ?? null,
16599
+ if (info) {
16600
+ recordRateLimitObservation(ctx.usageAccount, {
16601
+ window: info.rateLimitType,
16602
+ status: info.status,
16603
+ utilization: info.utilization,
16542
16604
  resetsAt: resetsAtToMs(info.resetsAt),
16543
- status: info.status
16605
+ windows: info.windows ? Object.fromEntries(
16606
+ Object.entries(info.windows).map(([window, own]) => [
16607
+ window,
16608
+ { utilization: own.utilization, resetsAt: resetsAtToMs(own.resetsAt) }
16609
+ ])
16610
+ ) : void 0
16544
16611
  });
16545
16612
  }
16546
16613
  const note = reportRateLimitEvent(msg);