@khalilgharbaoui/opencode-claude-code-plugin 0.2.0 → 0.2.2
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.d.ts +0 -6
- package/dist/index.js +207 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -90,12 +90,6 @@ type OpenCodeHooks = {
|
|
|
90
90
|
id: string;
|
|
91
91
|
models?: (provider: OpenCodeProvider) => Promise<Record<string, OpenCodeModel>>;
|
|
92
92
|
};
|
|
93
|
-
/**
|
|
94
|
-
* Called for every bus event opencode publishes. We use this to react to
|
|
95
|
-
* `global.disposed` (fired when opencode invalidates its config — e.g.
|
|
96
|
-
* after a UI MCP toggle or `updateGlobal`) and evict cached claude
|
|
97
|
-
* subprocesses so the next turn picks up the fresh config.
|
|
98
|
-
*/
|
|
99
93
|
event?: (input: {
|
|
100
94
|
event: OpenCodeEvent;
|
|
101
95
|
}) => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,9 @@ var log = {
|
|
|
15
15
|
info(msg, data) {
|
|
16
16
|
if (DEBUG) console.error(fmt("INFO", msg, data));
|
|
17
17
|
},
|
|
18
|
+
notice(msg, data) {
|
|
19
|
+
console.error(fmt("NOTICE", msg, data));
|
|
20
|
+
},
|
|
18
21
|
warn(msg, data) {
|
|
19
22
|
if (DEBUG) console.error(fmt("WARN", msg, data));
|
|
20
23
|
},
|
|
@@ -711,6 +714,7 @@ async function getRuntimeMcpStatus() {
|
|
|
711
714
|
import { spawn } from "child_process";
|
|
712
715
|
import { createInterface } from "readline";
|
|
713
716
|
import { EventEmitter } from "events";
|
|
717
|
+
import { unlink } from "fs/promises";
|
|
714
718
|
var activeProcesses = /* @__PURE__ */ new Map();
|
|
715
719
|
var claudeSessions = /* @__PURE__ */ new Map();
|
|
716
720
|
var MAX_ACTIVE_PROCESSES = 16;
|
|
@@ -742,15 +746,6 @@ function deleteActiveProcess(key) {
|
|
|
742
746
|
activeProcesses.delete(key);
|
|
743
747
|
}
|
|
744
748
|
}
|
|
745
|
-
function evictAllSessions(reason) {
|
|
746
|
-
const count = activeProcesses.size;
|
|
747
|
-
if (count === 0) return 0;
|
|
748
|
-
log.info("evicting all claude processes", { reason, count });
|
|
749
|
-
for (const key of Array.from(activeProcesses.keys())) {
|
|
750
|
-
deleteActiveProcess(key);
|
|
751
|
-
}
|
|
752
|
-
return count;
|
|
753
|
-
}
|
|
754
749
|
function getClaudeSessionId(key) {
|
|
755
750
|
return claudeSessions.get(key);
|
|
756
751
|
}
|
|
@@ -760,7 +755,7 @@ function setClaudeSessionId(key, sessionId) {
|
|
|
760
755
|
function deleteClaudeSessionId(key) {
|
|
761
756
|
claudeSessions.delete(key);
|
|
762
757
|
}
|
|
763
|
-
function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcpHash) {
|
|
758
|
+
function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcpHash, systemPromptFile) {
|
|
764
759
|
evictIfNeeded();
|
|
765
760
|
log.info("spawning new claude process", { cliPath, cliArgs, cwd, sessionKey: sessionKey2 });
|
|
766
761
|
const proc = spawn(cliPath, cliArgs, {
|
|
@@ -781,7 +776,8 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
|
|
|
781
776
|
proc,
|
|
782
777
|
lineEmitter,
|
|
783
778
|
proxyServer: proxyServer ?? null,
|
|
784
|
-
mcpHash
|
|
779
|
+
mcpHash,
|
|
780
|
+
systemPromptFile
|
|
785
781
|
};
|
|
786
782
|
activeProcesses.set(sessionKey2, ap);
|
|
787
783
|
proc.on("error", (err) => {
|
|
@@ -790,6 +786,10 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
|
|
|
790
786
|
proc.on("exit", (code, signal) => {
|
|
791
787
|
log.info("claude process exited", { code, signal, sessionKey: sessionKey2 });
|
|
792
788
|
void proxyServer?.close();
|
|
789
|
+
if (systemPromptFile) {
|
|
790
|
+
void unlink(systemPromptFile).catch(() => {
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
793
|
activeProcesses.delete(sessionKey2);
|
|
794
794
|
if (code !== 0 && code !== null) {
|
|
795
795
|
log.info("process exited with error, clearing session", {
|
|
@@ -821,7 +821,8 @@ function buildCliArgs(opts) {
|
|
|
821
821
|
permissionMode,
|
|
822
822
|
mcpConfig,
|
|
823
823
|
strictMcpConfig,
|
|
824
|
-
disallowedTools
|
|
824
|
+
disallowedTools,
|
|
825
|
+
appendSystemPromptFile
|
|
825
826
|
} = opts;
|
|
826
827
|
const args = [
|
|
827
828
|
"--output-format",
|
|
@@ -855,6 +856,9 @@ function buildCliArgs(opts) {
|
|
|
855
856
|
if (disallowedTools && disallowedTools.length > 0) {
|
|
856
857
|
args.push("--disallowedTools", ...disallowedTools);
|
|
857
858
|
}
|
|
859
|
+
if (appendSystemPromptFile) {
|
|
860
|
+
args.push("--append-system-prompt-file", appendSystemPromptFile);
|
|
861
|
+
}
|
|
858
862
|
if (skipPermissions) {
|
|
859
863
|
args.push("--dangerously-skip-permissions");
|
|
860
864
|
}
|
|
@@ -1045,12 +1049,12 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
|
|
|
1045
1049
|
hasInput: input != null
|
|
1046
1050
|
});
|
|
1047
1051
|
const result = await new Promise(
|
|
1048
|
-
(
|
|
1052
|
+
(resolve3, reject) => {
|
|
1049
1053
|
const entry = {
|
|
1050
1054
|
id: callId,
|
|
1051
1055
|
toolName,
|
|
1052
1056
|
input,
|
|
1053
|
-
resolve:
|
|
1057
|
+
resolve: resolve3,
|
|
1054
1058
|
reject
|
|
1055
1059
|
};
|
|
1056
1060
|
pending.set(callId, entry);
|
|
@@ -1107,11 +1111,11 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
|
|
|
1107
1111
|
}
|
|
1108
1112
|
}
|
|
1109
1113
|
});
|
|
1110
|
-
await new Promise((
|
|
1114
|
+
await new Promise((resolve3, reject) => {
|
|
1111
1115
|
server2.once("error", reject);
|
|
1112
1116
|
server2.listen(0, "127.0.0.1", () => {
|
|
1113
1117
|
server2.off("error", reject);
|
|
1114
|
-
|
|
1118
|
+
resolve3();
|
|
1115
1119
|
});
|
|
1116
1120
|
});
|
|
1117
1121
|
const addr = server2.address();
|
|
@@ -1158,8 +1162,8 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS) {
|
|
|
1158
1162
|
entry.reject(new Error("proxy MCP server closed"));
|
|
1159
1163
|
}
|
|
1160
1164
|
pending.clear();
|
|
1161
|
-
await new Promise((
|
|
1162
|
-
server2.close(() =>
|
|
1165
|
+
await new Promise((resolve3) => {
|
|
1166
|
+
server2.close(() => resolve3());
|
|
1163
1167
|
});
|
|
1164
1168
|
}
|
|
1165
1169
|
};
|
|
@@ -1183,10 +1187,10 @@ function disallowedToolFlags(tools) {
|
|
|
1183
1187
|
return out;
|
|
1184
1188
|
}
|
|
1185
1189
|
function readBody(req) {
|
|
1186
|
-
return new Promise((
|
|
1190
|
+
return new Promise((resolve3, reject) => {
|
|
1187
1191
|
const chunks = [];
|
|
1188
1192
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
1189
|
-
req.on("end", () =>
|
|
1193
|
+
req.on("end", () => resolve3(Buffer.concat(chunks).toString("utf8")));
|
|
1190
1194
|
req.on("error", reject);
|
|
1191
1195
|
});
|
|
1192
1196
|
}
|
|
@@ -1252,6 +1256,47 @@ function resolvePendingProxyCall(sessionKey2, result) {
|
|
|
1252
1256
|
}
|
|
1253
1257
|
|
|
1254
1258
|
// src/claude-code-language-model.ts
|
|
1259
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
1260
|
+
import { unlink as unlink2 } from "fs/promises";
|
|
1261
|
+
import { homedir as homedir2, tmpdir as tmpdir3 } from "os";
|
|
1262
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1263
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
1264
|
+
function readPromptFileIfPresent(path4) {
|
|
1265
|
+
try {
|
|
1266
|
+
const content = readFileSync2(path4, "utf8").trim();
|
|
1267
|
+
return content || void 0;
|
|
1268
|
+
} catch {
|
|
1269
|
+
return void 0;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
function nearestWorkspaceAgentsPrompt(cwd) {
|
|
1273
|
+
let dir = cwd;
|
|
1274
|
+
while (true) {
|
|
1275
|
+
const content = readPromptFileIfPresent(join3(dir, "AGENTS.md"));
|
|
1276
|
+
if (content) return content;
|
|
1277
|
+
const parent = dirname2(dir);
|
|
1278
|
+
if (parent === dir) return void 0;
|
|
1279
|
+
dir = parent;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
function buildAppendedSystemPrompt(cwd) {
|
|
1283
|
+
const parts = [];
|
|
1284
|
+
const configRoot = process.env.XDG_CONFIG_HOME ?? join3(homedir2(), ".config");
|
|
1285
|
+
const globalAgents = readPromptFileIfPresent(join3(configRoot, "opencode", "AGENTS.md"));
|
|
1286
|
+
const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd);
|
|
1287
|
+
if (globalAgents) parts.push(globalAgents);
|
|
1288
|
+
if (workspaceAgents && workspaceAgents !== globalAgents) parts.push(workspaceAgents);
|
|
1289
|
+
const content = parts.join("\n\n");
|
|
1290
|
+
if (!content) return void 0;
|
|
1291
|
+
const path4 = join3(tmpdir3(), `opencode-cc-sys-${randomUUID2()}.md`);
|
|
1292
|
+
try {
|
|
1293
|
+
writeFileSync3(path4, content, "utf8");
|
|
1294
|
+
return path4;
|
|
1295
|
+
} catch (err) {
|
|
1296
|
+
log.warn("failed to write system prompt file", { error: String(err) });
|
|
1297
|
+
return void 0;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1255
1300
|
var ClaudeCodeLanguageModel = class {
|
|
1256
1301
|
specificationVersion = "v3";
|
|
1257
1302
|
modelId;
|
|
@@ -1655,6 +1700,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1655
1700
|
reasoningEffort
|
|
1656
1701
|
);
|
|
1657
1702
|
const runtimeStatus = await getRuntimeMcpStatus();
|
|
1703
|
+
const systemPromptFile = buildAppendedSystemPrompt(cwd);
|
|
1658
1704
|
const cliArgs = buildCliArgs({
|
|
1659
1705
|
sessionKey: sk,
|
|
1660
1706
|
skipPermissions: this.config.skipPermissions !== false,
|
|
@@ -1663,7 +1709,8 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1663
1709
|
permissionMode: this.config.permissionMode,
|
|
1664
1710
|
mcpConfig: this.effectiveMcpConfig(cwd, void 0, runtimeStatus).paths,
|
|
1665
1711
|
strictMcpConfig: this.config.strictMcpConfig,
|
|
1666
|
-
disallowedTools: this.config.webSearch === "disabled" ? ["WebSearch"] : void 0
|
|
1712
|
+
disallowedTools: this.config.webSearch === "disabled" ? ["WebSearch"] : void 0,
|
|
1713
|
+
appendSystemPromptFile: systemPromptFile
|
|
1667
1714
|
});
|
|
1668
1715
|
log.info("doGenerate starting", {
|
|
1669
1716
|
cwd,
|
|
@@ -1679,12 +1726,18 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1679
1726
|
env: { ...process.env, TERM: "xterm-256color" },
|
|
1680
1727
|
shell: process.platform === "win32"
|
|
1681
1728
|
});
|
|
1729
|
+
if (systemPromptFile) {
|
|
1730
|
+
proc.on("exit", () => {
|
|
1731
|
+
void unlink2(systemPromptFile).catch(() => {
|
|
1732
|
+
});
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1682
1735
|
const rl = createInterface2({ input: proc.stdout });
|
|
1683
1736
|
let responseText = "";
|
|
1684
1737
|
let thinkingText = "";
|
|
1685
1738
|
let resultMeta = {};
|
|
1686
1739
|
const toolCalls = [];
|
|
1687
|
-
const result = await new Promise((
|
|
1740
|
+
const result = await new Promise((resolve3, reject) => {
|
|
1688
1741
|
rl.on("line", (line) => {
|
|
1689
1742
|
if (!line.trim()) return;
|
|
1690
1743
|
try {
|
|
@@ -1775,7 +1828,7 @@ ${plan}
|
|
|
1775
1828
|
durationMs: msg.duration_ms,
|
|
1776
1829
|
usage: msg.usage
|
|
1777
1830
|
};
|
|
1778
|
-
|
|
1831
|
+
resolve3({
|
|
1779
1832
|
...resultMeta,
|
|
1780
1833
|
text: responseText,
|
|
1781
1834
|
thinking: thinkingText,
|
|
@@ -1786,7 +1839,7 @@ ${plan}
|
|
|
1786
1839
|
}
|
|
1787
1840
|
});
|
|
1788
1841
|
rl.on("close", () => {
|
|
1789
|
-
|
|
1842
|
+
resolve3({
|
|
1790
1843
|
...resultMeta,
|
|
1791
1844
|
text: responseText,
|
|
1792
1845
|
thinking: thinkingText,
|
|
@@ -1977,6 +2030,7 @@ ${plan}
|
|
|
1977
2030
|
proxyServer?.configPath(),
|
|
1978
2031
|
runtimeStatus
|
|
1979
2032
|
);
|
|
2033
|
+
const systemPromptFile = activeProcess ? void 0 : buildAppendedSystemPrompt(cwd);
|
|
1980
2034
|
const cliArgs = buildCliArgs({
|
|
1981
2035
|
sessionKey: sk,
|
|
1982
2036
|
skipPermissions,
|
|
@@ -1984,7 +2038,8 @@ ${plan}
|
|
|
1984
2038
|
permissionMode: self.config.permissionMode,
|
|
1985
2039
|
mcpConfig: mcp.paths,
|
|
1986
2040
|
strictMcpConfig: self.config.strictMcpConfig,
|
|
1987
|
-
disallowedTools: allDisallowed.length > 0 ? allDisallowed : void 0
|
|
2041
|
+
disallowedTools: allDisallowed.length > 0 ? allDisallowed : void 0,
|
|
2042
|
+
appendSystemPromptFile: systemPromptFile
|
|
1988
2043
|
});
|
|
1989
2044
|
if (activeProcess) {
|
|
1990
2045
|
proc = activeProcess.proc;
|
|
@@ -1997,7 +2052,8 @@ ${plan}
|
|
|
1997
2052
|
cwd,
|
|
1998
2053
|
sk,
|
|
1999
2054
|
proxyServer,
|
|
2000
|
-
mcp.bridgedHash
|
|
2055
|
+
mcp.bridgedHash,
|
|
2056
|
+
systemPromptFile
|
|
2001
2057
|
);
|
|
2002
2058
|
proc = ap.proc;
|
|
2003
2059
|
lineEmitter = ap.lineEmitter;
|
|
@@ -2901,6 +2957,117 @@ function titleizeAccount(account) {
|
|
|
2901
2957
|
return normalizeAccountName(account).split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
2902
2958
|
}
|
|
2903
2959
|
|
|
2960
|
+
// src/cleanup-stale.ts
|
|
2961
|
+
import {
|
|
2962
|
+
existsSync as existsSync2,
|
|
2963
|
+
readFileSync as readFileSync3,
|
|
2964
|
+
realpathSync,
|
|
2965
|
+
rmSync,
|
|
2966
|
+
writeFileSync as writeFileSync4
|
|
2967
|
+
} from "fs";
|
|
2968
|
+
import { homedir as homedir3 } from "os";
|
|
2969
|
+
import { join as join4, resolve as resolve2 } from "path";
|
|
2970
|
+
import { fileURLToPath } from "url";
|
|
2971
|
+
var STALE_PACKAGE_NAME = "opencode-claude-code-plugin";
|
|
2972
|
+
var SUSPECT_DESCRIPTION_TOKEN = "Claude Code";
|
|
2973
|
+
var alreadyRan = false;
|
|
2974
|
+
function candidateCacheRoots() {
|
|
2975
|
+
const xdg = process.env.XDG_CACHE_HOME;
|
|
2976
|
+
return [
|
|
2977
|
+
xdg ? join4(xdg, "opencode") : null,
|
|
2978
|
+
join4(homedir3(), ".cache", "opencode"),
|
|
2979
|
+
join4(homedir3(), "Library", "Caches", "opencode")
|
|
2980
|
+
].filter((p) => Boolean(p));
|
|
2981
|
+
}
|
|
2982
|
+
function userOpencodeJsonPath() {
|
|
2983
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? join4(homedir3(), ".config");
|
|
2984
|
+
return join4(xdgConfig, "opencode", "opencode.json");
|
|
2985
|
+
}
|
|
2986
|
+
function userIntendsToUseUnscoped() {
|
|
2987
|
+
const cfg = userOpencodeJsonPath();
|
|
2988
|
+
if (!existsSync2(cfg)) return false;
|
|
2989
|
+
try {
|
|
2990
|
+
const json = JSON.parse(readFileSync3(cfg, "utf8"));
|
|
2991
|
+
const plugins = json.plugin;
|
|
2992
|
+
if (!Array.isArray(plugins)) return false;
|
|
2993
|
+
return plugins.some(
|
|
2994
|
+
(entry) => typeof entry === "string" && /^opencode-claude-code-plugin(@[^/]+)?$/.test(entry)
|
|
2995
|
+
);
|
|
2996
|
+
} catch {
|
|
2997
|
+
return false;
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
function ourLoadedDir() {
|
|
3001
|
+
try {
|
|
3002
|
+
const filePath = fileURLToPath(import.meta.url);
|
|
3003
|
+
return realpathSync(resolve2(filePath, "..", ".."));
|
|
3004
|
+
} catch {
|
|
3005
|
+
return null;
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
function cleanupStaleUnscopedInstall() {
|
|
3009
|
+
if (alreadyRan) return;
|
|
3010
|
+
alreadyRan = true;
|
|
3011
|
+
if (process.env.OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP === "1") return;
|
|
3012
|
+
if (userIntendsToUseUnscoped()) return;
|
|
3013
|
+
const ourDir = ourLoadedDir();
|
|
3014
|
+
for (const cacheRoot of candidateCacheRoots()) {
|
|
3015
|
+
try {
|
|
3016
|
+
cleanupOne(cacheRoot, ourDir);
|
|
3017
|
+
} catch (err) {
|
|
3018
|
+
log.warn("cleanup-stale: error processing cache root", {
|
|
3019
|
+
cacheRoot,
|
|
3020
|
+
error: String(err)
|
|
3021
|
+
});
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
function cleanupOne(cacheRoot, ourDir) {
|
|
3026
|
+
if (!existsSync2(cacheRoot)) return;
|
|
3027
|
+
const stalePath = join4(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
|
|
3028
|
+
if (!existsSync2(stalePath)) return;
|
|
3029
|
+
let realStalePath = stalePath;
|
|
3030
|
+
try {
|
|
3031
|
+
realStalePath = realpathSync(stalePath);
|
|
3032
|
+
} catch {
|
|
3033
|
+
}
|
|
3034
|
+
if (ourDir && realStalePath === ourDir) return;
|
|
3035
|
+
const pkgJsonPath = join4(stalePath, "package.json");
|
|
3036
|
+
if (!existsSync2(pkgJsonPath)) return;
|
|
3037
|
+
let pkg = {};
|
|
3038
|
+
try {
|
|
3039
|
+
pkg = JSON.parse(readFileSync3(pkgJsonPath, "utf8"));
|
|
3040
|
+
} catch {
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
if (pkg.name !== STALE_PACKAGE_NAME) return;
|
|
3044
|
+
if (!pkg.description?.includes(SUSPECT_DESCRIPTION_TOKEN)) return;
|
|
3045
|
+
log.info("cleanup-stale: removing unscoped install", { stalePath });
|
|
3046
|
+
try {
|
|
3047
|
+
rmSync(stalePath, { recursive: true, force: true });
|
|
3048
|
+
} catch (err) {
|
|
3049
|
+
log.warn("cleanup-stale: rmSync failed", {
|
|
3050
|
+
stalePath,
|
|
3051
|
+
error: String(err)
|
|
3052
|
+
});
|
|
3053
|
+
return;
|
|
3054
|
+
}
|
|
3055
|
+
const cachePkgJson = join4(cacheRoot, "package.json");
|
|
3056
|
+
if (!existsSync2(cachePkgJson)) return;
|
|
3057
|
+
try {
|
|
3058
|
+
const cfg = JSON.parse(readFileSync3(cachePkgJson, "utf8"));
|
|
3059
|
+
if (cfg?.dependencies?.[STALE_PACKAGE_NAME]) {
|
|
3060
|
+
delete cfg.dependencies[STALE_PACKAGE_NAME];
|
|
3061
|
+
writeFileSync4(cachePkgJson, JSON.stringify(cfg, null, 2) + "\n");
|
|
3062
|
+
log.info("cleanup-stale: pruned dep from cache package.json");
|
|
3063
|
+
}
|
|
3064
|
+
} catch (err) {
|
|
3065
|
+
log.warn("cleanup-stale: cache package.json update failed", {
|
|
3066
|
+
error: String(err)
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
|
|
2904
3071
|
// src/index.ts
|
|
2905
3072
|
function createClaudeCode(settings = {}) {
|
|
2906
3073
|
const cliPath = settings.cliPath ?? process.env.CLAUDE_CLI_PATH ?? "claude";
|
|
@@ -3080,18 +3247,8 @@ async function expandAccountProviders(config) {
|
|
|
3080
3247
|
}
|
|
3081
3248
|
return expandedCount > 0;
|
|
3082
3249
|
}
|
|
3083
|
-
function readEventType(ev) {
|
|
3084
|
-
if (!ev || typeof ev !== "object") return void 0;
|
|
3085
|
-
const e = ev;
|
|
3086
|
-
if (typeof e.type === "string") return e.type;
|
|
3087
|
-
const payload = e.payload;
|
|
3088
|
-
if (payload && typeof payload === "object") {
|
|
3089
|
-
const t = payload.type;
|
|
3090
|
-
if (typeof t === "string") return t;
|
|
3091
|
-
}
|
|
3092
|
-
return void 0;
|
|
3093
|
-
}
|
|
3094
3250
|
var server = async (input) => {
|
|
3251
|
+
cleanupStaleUnscopedInstall();
|
|
3095
3252
|
if (input && typeof input === "object" && "client" in input) {
|
|
3096
3253
|
setOpencodeClient(input.client);
|
|
3097
3254
|
}
|
|
@@ -3099,18 +3256,25 @@ var server = async (input) => {
|
|
|
3099
3256
|
config: async (config) => {
|
|
3100
3257
|
config.provider ??= {};
|
|
3101
3258
|
const expanded = await expandAccountProviders(config);
|
|
3102
|
-
if (expanded)
|
|
3259
|
+
if (expanded) {
|
|
3260
|
+
const registered = Object.entries(config.provider).filter(([id]) => id === PROVIDER_ID2 || id.startsWith(`${PROVIDER_ID2}-`)).map(([id, p]) => ({ id, name: p?.name ?? id }));
|
|
3261
|
+
log.notice("registered claude-code providers", { providers: registered });
|
|
3262
|
+
return;
|
|
3263
|
+
}
|
|
3103
3264
|
const existing = config.provider[PROVIDER_ID2];
|
|
3104
3265
|
config.provider[PROVIDER_ID2] = {
|
|
3105
3266
|
...existing,
|
|
3106
3267
|
...await providerConfig(existing)
|
|
3107
3268
|
};
|
|
3269
|
+
log.notice("registered claude-code provider", {
|
|
3270
|
+
id: PROVIDER_ID2,
|
|
3271
|
+
name: config.provider[PROVIDER_ID2]?.name ?? PROVIDER_ID2
|
|
3272
|
+
});
|
|
3108
3273
|
},
|
|
3109
|
-
event:
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
},
|
|
3274
|
+
// No `event` hook: MCP config drift is detected at turn start by the
|
|
3275
|
+
// hot-reload check in `claude-code-language-model.ts`, which respawns
|
|
3276
|
+
// claude safely between turns. Eviction on `global.disposed` would kill
|
|
3277
|
+
// an in-flight stream and abort the user's current turn.
|
|
3114
3278
|
provider: {
|
|
3115
3279
|
id: PROVIDER_ID2,
|
|
3116
3280
|
models: async (provider) => defaultModelsForProvider(provider.models)
|