@khalilgharbaoui/opencode-claude-code-plugin 0.31.0 → 0.31.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 +2 -0
- package/dist/index.js +78 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +6 -0
package/README.md
CHANGED
|
@@ -890,6 +890,8 @@ It carries the startup-diagnostics fields (plugin version, opencode version, `cl
|
|
|
890
890
|
|
|
891
891
|
When Claude Code refused an entry in an `--mcp-config` it was handed, an **MCP config entries Claude Code skipped** section names each one with the CLI's own category and sentence. That section only appears when there is something in it. It matters because a skipped server is absent from the CLI's server list entirely rather than listed as broken, so the model silently does not have those tools; if the skipped name is `opencode_proxy` the report says so plainly, because then it is the plugin's own server and every proxied tool call in the session fails. The same thing is a warning in your terminal when it happens.
|
|
892
892
|
|
|
893
|
+
A **Plugins Claude Code did not load** section works the same way for Claude plugins: one the CLI demoted at load time (for example, a dependency that is not installed) is absent from its plugin list, so its skills, commands and MCP servers are silently missing. The skill bridge is such a plugin (`opencode-skills`), and a failure there is reported as the plugin's own bug rather than your config. A plugin warning only counts when its content did not load; advisory feedback about a plugin that did load stays in the log at INFO.
|
|
894
|
+
|
|
893
895
|
```text
|
|
894
896
|
/claude-code-doctor usage
|
|
895
897
|
```
|
package/dist/index.js
CHANGED
|
@@ -415,6 +415,7 @@ var DEFAULT_PROXY_TOOL_NAMES = [
|
|
|
415
415
|
"Task"
|
|
416
416
|
];
|
|
417
417
|
var PROXY_MCP_SERVER_NAME = "opencode_proxy";
|
|
418
|
+
var SKILL_PLUGIN_NAME = "opencode-skills";
|
|
418
419
|
|
|
419
420
|
// src/cli-events.ts
|
|
420
421
|
function isRecord(value) {
|
|
@@ -595,9 +596,44 @@ function parseSystemInit(msg) {
|
|
|
595
596
|
cliVersion: str(raw.claude_code_version),
|
|
596
597
|
toolCount: Array.isArray(raw.tools) ? raw.tools.length : 0,
|
|
597
598
|
mcpServers: servers,
|
|
598
|
-
mcpServerErrors: parseMcpServerErrors(msg)
|
|
599
|
+
mcpServerErrors: parseMcpServerErrors(msg),
|
|
600
|
+
pluginErrors: parsePluginDiagnostics(raw.plugin_errors),
|
|
601
|
+
pluginWarnings: parsePluginDiagnostics(raw.plugin_warnings),
|
|
602
|
+
loadedPlugins: parseLoadedPlugins(raw.plugins)
|
|
599
603
|
};
|
|
600
604
|
}
|
|
605
|
+
function parsePluginDiagnostics(raw) {
|
|
606
|
+
if (!Array.isArray(raw)) return [];
|
|
607
|
+
const diagnostics = [];
|
|
608
|
+
for (const entry of raw) {
|
|
609
|
+
if (!isRecord(entry)) continue;
|
|
610
|
+
diagnostics.push({
|
|
611
|
+
plugin: str(entry.plugin) ?? "unknown",
|
|
612
|
+
type: str(entry.type) ?? "unknown",
|
|
613
|
+
message: str(entry.message) ?? ""
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
return diagnostics;
|
|
617
|
+
}
|
|
618
|
+
function parseLoadedPlugins(raw) {
|
|
619
|
+
if (!Array.isArray(raw)) return [];
|
|
620
|
+
const loaded = [];
|
|
621
|
+
for (const entry of raw) {
|
|
622
|
+
if (!isRecord(entry)) continue;
|
|
623
|
+
for (const id of [str(entry.source), str(entry.name)]) {
|
|
624
|
+
if (id && !loaded.includes(id)) loaded.push(id);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return loaded;
|
|
628
|
+
}
|
|
629
|
+
function describePluginLoadFailure(diagnostic) {
|
|
630
|
+
const detail = diagnostic.message ? ` Claude Code said: ${diagnostic.message}` : "";
|
|
631
|
+
const name = diagnostic.plugin.split("@", 1)[0];
|
|
632
|
+
if (name === SKILL_PLUGIN_NAME) {
|
|
633
|
+
return `Claude Code did not load the plugin's own skill bridge "${diagnostic.plugin}" (${diagnostic.type}), so the opencode skills it bridges are missing this session. This is a plugin bug or a corrupted scratch directory rather than your config: report it with this line.${detail}`;
|
|
634
|
+
}
|
|
635
|
+
return `Claude Code did not load plugin "${diagnostic.plugin}" (${diagnostic.type}), so its skills, commands and MCP servers are missing this session.${detail}`;
|
|
636
|
+
}
|
|
601
637
|
function apiKeySourceWarning(apiKeySource, ignoreAnthropicApiKey) {
|
|
602
638
|
if (!apiKeySource || !API_KEY_SOURCES.has(apiKeySource)) return null;
|
|
603
639
|
const base = `Claude Code authenticated with an API key (apiKeySource: ${apiKeySource}), so these turns bill as pay-as-you-go API usage instead of your subscription.`;
|
|
@@ -607,9 +643,32 @@ var warnedApiKeySources = /* @__PURE__ */ new Set();
|
|
|
607
643
|
var warnedMcpFailures = /* @__PURE__ */ new Set();
|
|
608
644
|
var warnedMcpSkips = /* @__PURE__ */ new Set();
|
|
609
645
|
var lastMcpServerErrors = /* @__PURE__ */ new Map();
|
|
646
|
+
var warnedPluginDiagnostics = /* @__PURE__ */ new Set();
|
|
647
|
+
var lastPluginLoadFailures = /* @__PURE__ */ new Map();
|
|
610
648
|
function snapshotMcpServerErrors() {
|
|
611
649
|
return [...lastMcpServerErrors.values()];
|
|
612
650
|
}
|
|
651
|
+
function snapshotPluginLoadFailures() {
|
|
652
|
+
return [...lastPluginLoadFailures.values()];
|
|
653
|
+
}
|
|
654
|
+
function reportPluginDiagnostics(info) {
|
|
655
|
+
const report = (kind, diagnostic) => {
|
|
656
|
+
const loaded = kind === "warning" && info.loadedPlugins.includes(diagnostic.plugin);
|
|
657
|
+
const message = loaded ? `Claude Code has advisory feedback for plugin "${diagnostic.plugin}" (${diagnostic.type}): ${diagnostic.message}` : describePluginLoadFailure(diagnostic);
|
|
658
|
+
if (!loaded) lastPluginLoadFailures.set(diagnostic.plugin, { kind, ...diagnostic });
|
|
659
|
+
const key = `${kind}:${diagnostic.plugin}:${diagnostic.type}`;
|
|
660
|
+
const data = { plugin: diagnostic.plugin, type: diagnostic.type, kind };
|
|
661
|
+
if (warnedPluginDiagnostics.has(key)) {
|
|
662
|
+
log.debug(message, data);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
warnedPluginDiagnostics.add(key);
|
|
666
|
+
if (loaded) log.info(message, data);
|
|
667
|
+
else log.warn(message, data);
|
|
668
|
+
};
|
|
669
|
+
for (const diagnostic of info.pluginErrors) report("error", diagnostic);
|
|
670
|
+
for (const diagnostic of info.pluginWarnings) report("warning", diagnostic);
|
|
671
|
+
}
|
|
613
672
|
function reportSystemInit(msg, options = {}) {
|
|
614
673
|
const info = parseSystemInit(msg);
|
|
615
674
|
if (!info) return;
|
|
@@ -620,8 +679,11 @@ function reportSystemInit(msg, options = {}) {
|
|
|
620
679
|
cliVersion: info.cliVersion ?? null,
|
|
621
680
|
tools: info.toolCount,
|
|
622
681
|
mcpServers: info.mcpServers,
|
|
623
|
-
mcpServerErrors: info.mcpServerErrors
|
|
682
|
+
mcpServerErrors: info.mcpServerErrors,
|
|
683
|
+
pluginErrors: info.pluginErrors,
|
|
684
|
+
pluginWarnings: info.pluginWarnings
|
|
624
685
|
});
|
|
686
|
+
reportPluginDiagnostics(info);
|
|
625
687
|
for (const error of info.mcpServerErrors) {
|
|
626
688
|
lastMcpServerErrors.set(error.name, error);
|
|
627
689
|
const key2 = `${error.name}:${error.type}`;
|
|
@@ -4869,6 +4931,18 @@ function formatDoctorReport(report) {
|
|
|
4869
4931
|
lines.push("");
|
|
4870
4932
|
lines.push("A skipped server is missing from the model's tools with no other sign of it.");
|
|
4871
4933
|
}
|
|
4934
|
+
if (report.pluginLoadFailures.length > 0) {
|
|
4935
|
+
lines.push("");
|
|
4936
|
+
lines.push("**Plugins Claude Code did not load**");
|
|
4937
|
+
lines.push("");
|
|
4938
|
+
lines.push("| plugin | kind | category | Claude Code said |");
|
|
4939
|
+
lines.push("|---|---|---|---|");
|
|
4940
|
+
for (const failure of report.pluginLoadFailures) {
|
|
4941
|
+
lines.push(
|
|
4942
|
+
`| ${failure.plugin} | ${failure.kind} | \`${failure.type}\` | ${failure.message || "no detail"} |`
|
|
4943
|
+
);
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4872
4946
|
lines.push("");
|
|
4873
4947
|
lines.push("**Plan usage**");
|
|
4874
4948
|
lines.push("");
|
|
@@ -4967,6 +5041,7 @@ async function gatherDoctorReport(options) {
|
|
|
4967
5041
|
pendingCalls: snapshotPendingProxyCalls(),
|
|
4968
5042
|
proxyServers,
|
|
4969
5043
|
mcpServerErrors: snapshotMcpServerErrors(),
|
|
5044
|
+
pluginLoadFailures: snapshotPluginLoadFailures(),
|
|
4970
5045
|
planUsage
|
|
4971
5046
|
};
|
|
4972
5047
|
}
|
|
@@ -4981,6 +5056,7 @@ async function buildDoctorReport(options) {
|
|
|
4981
5056
|
pendingCalls: report.pendingCalls.length,
|
|
4982
5057
|
proxyServers: report.proxyServers.map((server2) => server2.auth.status),
|
|
4983
5058
|
mcpServerErrors: report.mcpServerErrors.length,
|
|
5059
|
+
pluginLoadFailures: report.pluginLoadFailures.length,
|
|
4984
5060
|
planUsage: report.planUsage.status
|
|
4985
5061
|
});
|
|
4986
5062
|
return formatDoctorReport(report);
|
|
@@ -6078,7 +6154,6 @@ import * as fs5 from "fs";
|
|
|
6078
6154
|
import * as os3 from "os";
|
|
6079
6155
|
import * as path7 from "path";
|
|
6080
6156
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6081
|
-
var SKILL_PLUGIN_NAME = "opencode-skills";
|
|
6082
6157
|
function bundledSkillsDir() {
|
|
6083
6158
|
try {
|
|
6084
6159
|
const here = fileURLToPath2(import.meta.url);
|