@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 +75 -8
- package/dist/index.js.map +1 -1
- package/dist/tui.js +75 -34
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +11 -7
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
|
|
16540
|
-
|
|
16541
|
-
|
|
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
|
-
|
|
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);
|