@khalilgharbaoui/opencode-claude-code-plugin 0.63.2 → 0.63.3
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 +185 -119
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/claude-code-language-model.ts
|
|
2
|
-
import { join as
|
|
2
|
+
import { join as join21 } from "path";
|
|
3
3
|
|
|
4
4
|
// src/ids.ts
|
|
5
5
|
import { randomInt } from "crypto";
|
|
@@ -152,7 +152,7 @@ function translateStreamForHost(stream, dialect = "v1") {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
// src/account-failover.ts
|
|
155
|
-
import { homedir as
|
|
155
|
+
import { homedir as homedir4 } from "os";
|
|
156
156
|
|
|
157
157
|
// src/accounts.ts
|
|
158
158
|
import {
|
|
@@ -1008,6 +1008,11 @@ function snapshotAccountUsage(now = Date.now()) {
|
|
|
1008
1008
|
return refreshed(now);
|
|
1009
1009
|
}
|
|
1010
1010
|
|
|
1011
|
+
// src/cli-events.ts
|
|
1012
|
+
import { readFileSync as readFileSync2, statSync as statSync3 } from "fs";
|
|
1013
|
+
import { homedir as homedir3 } from "os";
|
|
1014
|
+
import { join as join3, resolve } from "path";
|
|
1015
|
+
|
|
1011
1016
|
// src/types.ts
|
|
1012
1017
|
var READ_ONLY_PERMISSION_MODE = "read-only";
|
|
1013
1018
|
var DEFAULT_PROXY_TOOL_NAMES = [
|
|
@@ -1274,6 +1279,35 @@ var warnedMcpSkips = /* @__PURE__ */ new Set();
|
|
|
1274
1279
|
var lastMcpServerErrors = /* @__PURE__ */ new Map();
|
|
1275
1280
|
var warnedPluginDiagnostics = /* @__PURE__ */ new Set();
|
|
1276
1281
|
var lastPluginLoadFailures = /* @__PURE__ */ new Map();
|
|
1282
|
+
var lastUnconnectedConnectors = /* @__PURE__ */ new Map();
|
|
1283
|
+
var CLAUDE_AI_CONNECTOR_PREFIX = "claude.ai ";
|
|
1284
|
+
function cliGlobalConfigPath(configDir) {
|
|
1285
|
+
const dir = configDir ?? process.env.CLAUDE_CONFIG_DIR;
|
|
1286
|
+
if (!dir) return join3(homedir3(), ".claude.json");
|
|
1287
|
+
const expanded = dir === "~" ? homedir3() : dir.startsWith("~/") ? join3(homedir3(), dir.slice(2)) : dir;
|
|
1288
|
+
return join3(resolve(expanded), ".claude.json");
|
|
1289
|
+
}
|
|
1290
|
+
var everConnectedCache = /* @__PURE__ */ new Map();
|
|
1291
|
+
function claudeAiConnectorsEverConnected(configDir) {
|
|
1292
|
+
const file = cliGlobalConfigPath(configDir);
|
|
1293
|
+
try {
|
|
1294
|
+
const { mtimeMs } = statSync3(file);
|
|
1295
|
+
const cached2 = everConnectedCache.get(file);
|
|
1296
|
+
if (cached2 && cached2.mtimeMs === mtimeMs) return cached2.names;
|
|
1297
|
+
const list2 = JSON.parse(readFileSync2(file, "utf8")).claudeAiMcpEverConnected;
|
|
1298
|
+
const names = Array.isArray(list2) ? new Set(list2.filter((name) => typeof name === "string")) : void 0;
|
|
1299
|
+
everConnectedCache.set(file, { mtimeMs, names });
|
|
1300
|
+
return names;
|
|
1301
|
+
} catch {
|
|
1302
|
+
return void 0;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
function isUnconnectedConnector(server2, everConnected) {
|
|
1306
|
+
return everConnected !== void 0 && server2.status === "needs-auth" && server2.name.startsWith(CLAUDE_AI_CONNECTOR_PREFIX) && !everConnected.has(server2.name);
|
|
1307
|
+
}
|
|
1308
|
+
function snapshotUnconnectedConnectors() {
|
|
1309
|
+
return [...lastUnconnectedConnectors].map(([name, status]) => ({ name, status }));
|
|
1310
|
+
}
|
|
1277
1311
|
function snapshotMcpServerErrors() {
|
|
1278
1312
|
return [...lastMcpServerErrors.values()];
|
|
1279
1313
|
}
|
|
@@ -1324,16 +1358,30 @@ function reportSystemInit(msg, options = {}) {
|
|
|
1324
1358
|
warnedMcpSkips.add(key2);
|
|
1325
1359
|
log.warn(message, { server: error.name, type: error.type });
|
|
1326
1360
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1361
|
+
const unusable = info.mcpServers.filter((server2) => server2.status !== "connected");
|
|
1362
|
+
const everConnected = unusable.some((server2) => server2.name.startsWith(CLAUDE_AI_CONNECTOR_PREFIX)) ? claudeAiConnectorsEverConnected(options.configDir) : void 0;
|
|
1363
|
+
const newlyUnusable = /* @__PURE__ */ new Map();
|
|
1364
|
+
const newlyUnconnected = [];
|
|
1365
|
+
for (const server2 of unusable) {
|
|
1366
|
+
const unconnected = isUnconnectedConnector(server2, everConnected);
|
|
1367
|
+
if (unconnected) lastUnconnectedConnectors.set(server2.name, server2.status);
|
|
1329
1368
|
const key2 = `${server2.name}:${server2.status}`;
|
|
1330
|
-
const message = `MCP server "${server2.name}" is ${server2.status} in Claude Code; its tools are not available to the model this session.`;
|
|
1331
1369
|
if (warnedMcpFailures.has(key2)) {
|
|
1332
|
-
log.debug(
|
|
1370
|
+
log.debug("MCP server still unavailable in Claude Code", { server: server2.name, status: server2.status });
|
|
1333
1371
|
continue;
|
|
1334
1372
|
}
|
|
1335
1373
|
warnedMcpFailures.add(key2);
|
|
1336
|
-
|
|
1374
|
+
if (unconnected) newlyUnconnected.push(server2.name);
|
|
1375
|
+
else newlyUnusable.set(server2.status, [...newlyUnusable.get(server2.status) ?? [], server2.name]);
|
|
1376
|
+
}
|
|
1377
|
+
if (newlyUnconnected.length > 0) {
|
|
1378
|
+
log.info("claude.ai connectors this account never connected need authentication; not warning about them", {
|
|
1379
|
+
servers: newlyUnconnected
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
for (const [status, names] of newlyUnusable) {
|
|
1383
|
+
const message = names.length === 1 ? `MCP server "${names[0]}" is ${status} in Claude Code; its tools are not available to the model this session.` : `${names.length} MCP servers are ${status} in Claude Code; their tools are not available to the model this session: ${names.join(", ")}.`;
|
|
1384
|
+
log.warn(message, names.length === 1 ? { server: names[0], status } : { servers: names, status });
|
|
1337
1385
|
}
|
|
1338
1386
|
const apiKeyMessage = apiKeySourceWarning(info.apiKeySource, options.ignoreAnthropicApiKey);
|
|
1339
1387
|
if (!apiKeyMessage) return;
|
|
@@ -1846,7 +1894,7 @@ function accountBlockKind(msg) {
|
|
|
1846
1894
|
function describeAccountBlock(kind) {
|
|
1847
1895
|
return ACCOUNT_BLOCKS[kind].what;
|
|
1848
1896
|
}
|
|
1849
|
-
function loginCommandFor(configDir, home =
|
|
1897
|
+
function loginCommandFor(configDir, home = homedir4()) {
|
|
1850
1898
|
if (!configDir) return "claude auth login";
|
|
1851
1899
|
const shown = configDir === home || configDir.startsWith(`${home}/`) ? `~${configDir.slice(home.length)}` : configDir;
|
|
1852
1900
|
return `CLAUDE_CONFIG_DIR=${shown} claude auth login`;
|
|
@@ -2228,7 +2276,7 @@ function failoverUntil(resetsAt) {
|
|
|
2228
2276
|
}
|
|
2229
2277
|
|
|
2230
2278
|
// src/subagent-dispatch.ts
|
|
2231
|
-
import { join as
|
|
2279
|
+
import { join as join6 } from "path";
|
|
2232
2280
|
|
|
2233
2281
|
// src/agent-models.ts
|
|
2234
2282
|
import { readFile, readdir } from "fs/promises";
|
|
@@ -2882,9 +2930,9 @@ function agentDirectories(home, projectDirectory) {
|
|
|
2882
2930
|
}
|
|
2883
2931
|
|
|
2884
2932
|
// src/dispatch-choice-store.ts
|
|
2885
|
-
import { mkdirSync as mkdirSync3, readFileSync as
|
|
2886
|
-
import { homedir as
|
|
2887
|
-
import { join as
|
|
2933
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
2934
|
+
import { homedir as homedir5 } from "os";
|
|
2935
|
+
import { join as join4 } from "path";
|
|
2888
2936
|
var MAX_DISPATCH_CHOICE_SESSIONS = 128;
|
|
2889
2937
|
var MAX_DISPATCH_CHOICES_PER_SESSION = 32;
|
|
2890
2938
|
var DISPATCH_CHOICE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -2892,8 +2940,8 @@ var sessions = null;
|
|
|
2892
2940
|
var pathOverride2 = null;
|
|
2893
2941
|
function dispatchChoiceStorePath() {
|
|
2894
2942
|
if (pathOverride2) return pathOverride2;
|
|
2895
|
-
const stateRoot = process.env.XDG_STATE_HOME ||
|
|
2896
|
-
return
|
|
2943
|
+
const stateRoot = process.env.XDG_STATE_HOME || join4(homedir5(), ".local", "state");
|
|
2944
|
+
return join4(stateRoot, "opencode-claude-code-plugin", "subagent-dispatch.json");
|
|
2897
2945
|
}
|
|
2898
2946
|
function isChoice(value) {
|
|
2899
2947
|
const choice = value;
|
|
@@ -2919,7 +2967,7 @@ function trimChoices(choices) {
|
|
|
2919
2967
|
function readFile2(file) {
|
|
2920
2968
|
const out = /* @__PURE__ */ new Map();
|
|
2921
2969
|
try {
|
|
2922
|
-
const parsed = JSON.parse(
|
|
2970
|
+
const parsed = JSON.parse(readFileSync3(file, "utf8"));
|
|
2923
2971
|
const entries = parsed && typeof parsed === "object" ? parsed.sessions : null;
|
|
2924
2972
|
if (!entries || typeof entries !== "object") return out;
|
|
2925
2973
|
const cutoff = Date.now() - DISPATCH_CHOICE_MAX_AGE_MS;
|
|
@@ -2941,7 +2989,7 @@ function save(update) {
|
|
|
2941
2989
|
const kept = [...merged.entries()].filter(([, record]) => record.updatedAt >= cutoff).filter(([, record]) => Object.keys(record.choices).length > 0).sort((a, b) => a[1].updatedAt - b[1].updatedAt).slice(-MAX_DISPATCH_CHOICE_SESSIONS);
|
|
2942
2990
|
sessions = new Map(kept);
|
|
2943
2991
|
try {
|
|
2944
|
-
mkdirSync3(
|
|
2992
|
+
mkdirSync3(join4(file, ".."), { recursive: true, mode: 448 });
|
|
2945
2993
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
2946
2994
|
writeFileSync2(tmp, JSON.stringify({ version: 1, sessions: Object.fromEntries(kept) }), {
|
|
2947
2995
|
mode: 384
|
|
@@ -5291,12 +5339,12 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS, timeoutOverride
|
|
|
5291
5339
|
});
|
|
5292
5340
|
let timer = null;
|
|
5293
5341
|
const result = await new Promise(
|
|
5294
|
-
(
|
|
5342
|
+
(resolve8, reject2) => {
|
|
5295
5343
|
const entry = {
|
|
5296
5344
|
id: callId,
|
|
5297
5345
|
toolName,
|
|
5298
5346
|
input,
|
|
5299
|
-
resolve:
|
|
5347
|
+
resolve: resolve8,
|
|
5300
5348
|
reject: reject2,
|
|
5301
5349
|
channel
|
|
5302
5350
|
};
|
|
@@ -5385,11 +5433,11 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS, timeoutOverride
|
|
|
5385
5433
|
}
|
|
5386
5434
|
}
|
|
5387
5435
|
});
|
|
5388
|
-
await new Promise((
|
|
5436
|
+
await new Promise((resolve8, reject2) => {
|
|
5389
5437
|
server2.once("error", reject2);
|
|
5390
5438
|
server2.listen(0, "127.0.0.1", () => {
|
|
5391
5439
|
server2.off("error", reject2);
|
|
5392
|
-
|
|
5440
|
+
resolve8();
|
|
5393
5441
|
});
|
|
5394
5442
|
});
|
|
5395
5443
|
const addr = server2.address();
|
|
@@ -5446,8 +5494,8 @@ async function createProxyMcpServer(tools = DEFAULT_PROXY_TOOLS, timeoutOverride
|
|
|
5446
5494
|
entry.reject(new Error(SERVER_CLOSED_MESSAGE));
|
|
5447
5495
|
}
|
|
5448
5496
|
pending2.clear();
|
|
5449
|
-
await new Promise((
|
|
5450
|
-
server2.close(() =>
|
|
5497
|
+
await new Promise((resolve8) => {
|
|
5498
|
+
server2.close(() => resolve8());
|
|
5451
5499
|
});
|
|
5452
5500
|
if (configFilePath) {
|
|
5453
5501
|
try {
|
|
@@ -5620,10 +5668,10 @@ function resolveMcpProxyToolDefs(options) {
|
|
|
5620
5668
|
return { defs, coveredServers, matchedServers };
|
|
5621
5669
|
}
|
|
5622
5670
|
function readBody(req) {
|
|
5623
|
-
return new Promise((
|
|
5671
|
+
return new Promise((resolve8, reject) => {
|
|
5624
5672
|
const chunks = [];
|
|
5625
5673
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
5626
|
-
req.on("end", () =>
|
|
5674
|
+
req.on("end", () => resolve8(Buffer.concat(chunks).toString("utf8")));
|
|
5627
5675
|
req.on("error", reject);
|
|
5628
5676
|
});
|
|
5629
5677
|
}
|
|
@@ -6819,7 +6867,7 @@ async function settleSessionRunState(sessionID, options = {}) {
|
|
|
6819
6867
|
if (state === "busy") return "busy";
|
|
6820
6868
|
if (state !== "unknown") last = state;
|
|
6821
6869
|
if (Date.now() - started2 >= windowMs) return last;
|
|
6822
|
-
await new Promise((
|
|
6870
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollMs));
|
|
6823
6871
|
}
|
|
6824
6872
|
}
|
|
6825
6873
|
var DEFAULT_MCP_CONNECT_WAIT_MS = 3e3;
|
|
@@ -6872,7 +6920,7 @@ async function waitForPendingMcpServers(first, budgetMs, signal) {
|
|
|
6872
6920
|
for (; ; ) {
|
|
6873
6921
|
if (Date.now() - started2 >= budgetMs) break;
|
|
6874
6922
|
if (signal?.aborted) break;
|
|
6875
|
-
await new Promise((
|
|
6923
|
+
await new Promise((resolve8) => setTimeout(resolve8, MCP_CONNECT_POLL_MS));
|
|
6876
6924
|
if (signal?.aborted) break;
|
|
6877
6925
|
const next = await fetchRuntimeMcpStatus();
|
|
6878
6926
|
if (!next) break;
|
|
@@ -7101,8 +7149,8 @@ async function countOtherRunningWithin(exclude, budgetMs) {
|
|
|
7101
7149
|
worker
|
|
7102
7150
|
);
|
|
7103
7151
|
let timer;
|
|
7104
|
-
const deadline = new Promise((
|
|
7105
|
-
timer = setTimeout(() =>
|
|
7152
|
+
const deadline = new Promise((resolve8) => {
|
|
7153
|
+
timer = setTimeout(() => resolve8("over"), budgetMs);
|
|
7106
7154
|
timer.unref?.();
|
|
7107
7155
|
});
|
|
7108
7156
|
try {
|
|
@@ -7312,17 +7360,17 @@ async function cancelBackgroundTask(input, options) {
|
|
|
7312
7360
|
}
|
|
7313
7361
|
|
|
7314
7362
|
// src/session-resume-store.ts
|
|
7315
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync5, readFileSync as
|
|
7316
|
-
import { homedir as
|
|
7317
|
-
import { join as
|
|
7363
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
7364
|
+
import { homedir as homedir8 } from "os";
|
|
7365
|
+
import { join as join10 } from "path";
|
|
7318
7366
|
var MAX_RESUME_RECORDS = 256;
|
|
7319
7367
|
var RESUME_RECORD_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
7320
7368
|
var records = null;
|
|
7321
7369
|
var pathOverride3 = null;
|
|
7322
7370
|
function resumeStorePath() {
|
|
7323
7371
|
if (pathOverride3) return pathOverride3;
|
|
7324
|
-
const stateRoot = process.env.XDG_STATE_HOME ||
|
|
7325
|
-
return
|
|
7372
|
+
const stateRoot = process.env.XDG_STATE_HOME || join10(homedir8(), ".local", "state");
|
|
7373
|
+
return join10(stateRoot, "opencode-claude-code-plugin", "claude-sessions.json");
|
|
7326
7374
|
}
|
|
7327
7375
|
function isDigest(value) {
|
|
7328
7376
|
const entry = value;
|
|
@@ -7336,7 +7384,7 @@ function load2() {
|
|
|
7336
7384
|
if (records) return records;
|
|
7337
7385
|
records = /* @__PURE__ */ new Map();
|
|
7338
7386
|
try {
|
|
7339
|
-
const parsed = JSON.parse(
|
|
7387
|
+
const parsed = JSON.parse(readFileSync6(resumeStorePath(), "utf8"));
|
|
7340
7388
|
const entries = parsed && typeof parsed === "object" ? parsed.sessions : null;
|
|
7341
7389
|
if (entries && typeof entries === "object") {
|
|
7342
7390
|
const cutoff = Date.now() - RESUME_RECORD_MAX_AGE_MS;
|
|
@@ -7351,7 +7399,7 @@ function save2(update) {
|
|
|
7351
7399
|
const file = resumeStorePath();
|
|
7352
7400
|
const merged = /* @__PURE__ */ new Map();
|
|
7353
7401
|
try {
|
|
7354
|
-
const onDisk = JSON.parse(
|
|
7402
|
+
const onDisk = JSON.parse(readFileSync6(file, "utf8"))?.sessions;
|
|
7355
7403
|
if (onDisk && typeof onDisk === "object") {
|
|
7356
7404
|
for (const [key, record] of Object.entries(onDisk)) {
|
|
7357
7405
|
if (isRecord2(record)) merged.set(key, record);
|
|
@@ -7364,7 +7412,7 @@ function save2(update) {
|
|
|
7364
7412
|
const kept = [...merged.entries()].filter(([, record]) => record.updatedAt >= cutoff).sort((a, b) => a[1].updatedAt - b[1].updatedAt).slice(-MAX_RESUME_RECORDS);
|
|
7365
7413
|
records = new Map(kept);
|
|
7366
7414
|
try {
|
|
7367
|
-
mkdirSync5(
|
|
7415
|
+
mkdirSync5(join10(file, ".."), { recursive: true, mode: 448 });
|
|
7368
7416
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
7369
7417
|
writeFileSync5(tmp, JSON.stringify({ version: 1, sessions: Object.fromEntries(kept) }), {
|
|
7370
7418
|
mode: 384
|
|
@@ -7790,7 +7838,7 @@ async function requestSideQuestion(activeProcess, question, options) {
|
|
|
7790
7838
|
}
|
|
7791
7839
|
});
|
|
7792
7840
|
pendingProcesses.add(proc);
|
|
7793
|
-
return new Promise((
|
|
7841
|
+
return new Promise((resolve8, reject) => {
|
|
7794
7842
|
const event = `side-question:${requestId}`;
|
|
7795
7843
|
let settled = false;
|
|
7796
7844
|
let sent = false;
|
|
@@ -7845,7 +7893,7 @@ async function requestSideQuestion(activeProcess, question, options) {
|
|
|
7845
7893
|
}
|
|
7846
7894
|
settled = true;
|
|
7847
7895
|
cleanup();
|
|
7848
|
-
|
|
7896
|
+
resolve8({ response: result.response, synthetic: result.synthetic });
|
|
7849
7897
|
};
|
|
7850
7898
|
const timer = setTimeout(() => {
|
|
7851
7899
|
fail(new Error(`/btw timed out after ${timeoutMs}ms.`), true);
|
|
@@ -7891,7 +7939,7 @@ function safely(action) {
|
|
|
7891
7939
|
var ownMember;
|
|
7892
7940
|
var ownFollowers = 0;
|
|
7893
7941
|
var ownServed = false;
|
|
7894
|
-
function
|
|
7942
|
+
function join11() {
|
|
7895
7943
|
if (!ownMember) return;
|
|
7896
7944
|
const state = relayState();
|
|
7897
7945
|
if (state.members.has(ownMember)) return;
|
|
@@ -7904,11 +7952,11 @@ function leave() {
|
|
|
7904
7952
|
}
|
|
7905
7953
|
function defineOwnRelayMember(member) {
|
|
7906
7954
|
ownMember = member;
|
|
7907
|
-
if (ownServed)
|
|
7955
|
+
if (ownServed) join11();
|
|
7908
7956
|
}
|
|
7909
7957
|
function noteRelayMemberServing() {
|
|
7910
7958
|
ownServed = true;
|
|
7911
|
-
|
|
7959
|
+
join11();
|
|
7912
7960
|
}
|
|
7913
7961
|
function relayMemberHasServed() {
|
|
7914
7962
|
return ownServed;
|
|
@@ -7918,7 +7966,7 @@ function leaveSessionEventRelay() {
|
|
|
7918
7966
|
}
|
|
7919
7967
|
function openRelayFollower() {
|
|
7920
7968
|
const state = relayState();
|
|
7921
|
-
|
|
7969
|
+
join11();
|
|
7922
7970
|
ownFollowers += 1;
|
|
7923
7971
|
state.followers += 1;
|
|
7924
7972
|
if (state.followers === 1) {
|
|
@@ -8108,16 +8156,16 @@ function isTurnInFlight(ap) {
|
|
|
8108
8156
|
}
|
|
8109
8157
|
function awaitTurnIdle(ap, timeoutMs) {
|
|
8110
8158
|
if (!ap.turnInFlight) return Promise.resolve(true);
|
|
8111
|
-
return new Promise((
|
|
8159
|
+
return new Promise((resolve8) => {
|
|
8112
8160
|
const wake = () => {
|
|
8113
8161
|
clearTimeout(timer);
|
|
8114
|
-
|
|
8162
|
+
resolve8(true);
|
|
8115
8163
|
};
|
|
8116
8164
|
const timer = setTimeout(() => {
|
|
8117
8165
|
const waiters = ap.turnIdleWaiters ?? [];
|
|
8118
8166
|
const at = waiters.indexOf(wake);
|
|
8119
8167
|
if (at >= 0) waiters.splice(at, 1);
|
|
8120
|
-
|
|
8168
|
+
resolve8(false);
|
|
8121
8169
|
}, timeoutMs);
|
|
8122
8170
|
(ap.turnIdleWaiters ??= []).push(wake);
|
|
8123
8171
|
});
|
|
@@ -8281,14 +8329,14 @@ function hasProcessExited(proc) {
|
|
|
8281
8329
|
}
|
|
8282
8330
|
function waitForProcessExit(proc, timeoutMs) {
|
|
8283
8331
|
if (hasProcessExited(proc)) return Promise.resolve(true);
|
|
8284
|
-
return new Promise((
|
|
8332
|
+
return new Promise((resolve8) => {
|
|
8285
8333
|
const onExit = () => {
|
|
8286
8334
|
clearTimeout(timer);
|
|
8287
|
-
|
|
8335
|
+
resolve8(true);
|
|
8288
8336
|
};
|
|
8289
8337
|
const timer = setTimeout(() => {
|
|
8290
8338
|
proc.off("exit", onExit);
|
|
8291
|
-
|
|
8339
|
+
resolve8(hasProcessExited(proc));
|
|
8292
8340
|
}, timeoutMs);
|
|
8293
8341
|
proc.once("exit", onExit);
|
|
8294
8342
|
});
|
|
@@ -8912,7 +8960,7 @@ async function waitForSessionIdle(client, sessionID, options = {}) {
|
|
|
8912
8960
|
if (options.stop?.()) return true;
|
|
8913
8961
|
if (await sessionStatus(client, sessionID) !== "busy") return true;
|
|
8914
8962
|
if (Date.now() - started2 >= timeoutMs) return false;
|
|
8915
|
-
await new Promise((
|
|
8963
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollMs));
|
|
8916
8964
|
}
|
|
8917
8965
|
}
|
|
8918
8966
|
async function deliverAsideInline(client, sessionID, text, options = {}) {
|
|
@@ -8923,7 +8971,7 @@ async function deliverAsideInline(client, sessionID, text, options = {}) {
|
|
|
8923
8971
|
if (emitAsideInline(sessionID, text)) return true;
|
|
8924
8972
|
if (Date.now() - started2 >= timeoutMs) return false;
|
|
8925
8973
|
if (await sessionStatus(client, sessionID) !== "busy") return false;
|
|
8926
|
-
await new Promise((
|
|
8974
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollMs));
|
|
8927
8975
|
}
|
|
8928
8976
|
}
|
|
8929
8977
|
async function waitForAsideProcess(client, sessionID, options = {}) {
|
|
@@ -8944,7 +8992,7 @@ async function waitForAsideProcess(client, sessionID, options = {}) {
|
|
|
8944
8992
|
log.warn("btw: a turn is running but no claude process appeared for it", { sessionID, waitedMs });
|
|
8945
8993
|
return void 0;
|
|
8946
8994
|
}
|
|
8947
|
-
await new Promise((
|
|
8995
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollMs));
|
|
8948
8996
|
}
|
|
8949
8997
|
}
|
|
8950
8998
|
async function settleSessionBusy(client, sessionID, active, options = {}) {
|
|
@@ -8956,7 +9004,7 @@ async function settleSessionBusy(client, sessionID, active, options = {}) {
|
|
|
8956
9004
|
if (status === "busy") return true;
|
|
8957
9005
|
if (status === "unknown") return isProcessBusy(active);
|
|
8958
9006
|
if (Date.now() - started2 >= settleMs) return false;
|
|
8959
|
-
await new Promise((
|
|
9007
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollMs));
|
|
8960
9008
|
}
|
|
8961
9009
|
}
|
|
8962
9010
|
function errorText(error) {
|
|
@@ -9000,10 +9048,10 @@ async function runBtwCommand(client, input, options = {}) {
|
|
|
9000
9048
|
let inlineDone = false;
|
|
9001
9049
|
let markInlineDelivered = () => {
|
|
9002
9050
|
};
|
|
9003
|
-
const inlineDelivered = new Promise((
|
|
9051
|
+
const inlineDelivered = new Promise((resolve8) => {
|
|
9004
9052
|
markInlineDelivered = () => {
|
|
9005
9053
|
inlineDone = true;
|
|
9006
|
-
|
|
9054
|
+
resolve8("inline");
|
|
9007
9055
|
};
|
|
9008
9056
|
});
|
|
9009
9057
|
if (isSideQuestionPending(active)) {
|
|
@@ -9253,7 +9301,7 @@ function snapshotBudgets() {
|
|
|
9253
9301
|
// src/diagnostic-bundle.ts
|
|
9254
9302
|
import { createHash as createHash4, randomBytes as randomBytes2 } from "crypto";
|
|
9255
9303
|
import { openSync, readSync, closeSync, fstatSync, realpathSync } from "fs";
|
|
9256
|
-
import { homedir as
|
|
9304
|
+
import { homedir as homedir9 } from "os";
|
|
9257
9305
|
|
|
9258
9306
|
// src/log-messages.ts
|
|
9259
9307
|
var PLUGIN_LOG_MESSAGES = /* @__PURE__ */ new Set([
|
|
@@ -9703,7 +9751,7 @@ function createIdHasher(salt = randomBytes2(16).toString("hex")) {
|
|
|
9703
9751
|
return (raw) => createHash4("sha256").update(salt).update("\0").update(raw).digest("hex").slice(0, 8);
|
|
9704
9752
|
}
|
|
9705
9753
|
function createRedactionContext(options = {}) {
|
|
9706
|
-
const home = options.home ??
|
|
9754
|
+
const home = options.home ?? homedir9();
|
|
9707
9755
|
const homes = /* @__PURE__ */ new Set();
|
|
9708
9756
|
if (home) homes.add(home);
|
|
9709
9757
|
if (home) {
|
|
@@ -10236,7 +10284,7 @@ function parsePlanUsage(stdout) {
|
|
|
10236
10284
|
}
|
|
10237
10285
|
function runCli(cliPath, args, timeoutMs, env) {
|
|
10238
10286
|
const plan = planClaudeSpawn(cliPath, args);
|
|
10239
|
-
return new Promise((
|
|
10287
|
+
return new Promise((resolve8, reject) => {
|
|
10240
10288
|
execFile2(
|
|
10241
10289
|
plan.file,
|
|
10242
10290
|
plan.args,
|
|
@@ -10250,9 +10298,9 @@ function runCli(cliPath, args, timeoutMs, env) {
|
|
|
10250
10298
|
windowsVerbatimArguments: plan.windowsVerbatimArguments
|
|
10251
10299
|
},
|
|
10252
10300
|
(error, stdout) => {
|
|
10253
|
-
if (stdout && stdout.trim()) return
|
|
10301
|
+
if (stdout && stdout.trim()) return resolve8(stdout);
|
|
10254
10302
|
if (error) return reject(error);
|
|
10255
|
-
|
|
10303
|
+
resolve8(stdout ?? "");
|
|
10256
10304
|
}
|
|
10257
10305
|
);
|
|
10258
10306
|
});
|
|
@@ -10290,22 +10338,22 @@ async function fetchPlanUsage(cliPath, options = {}) {
|
|
|
10290
10338
|
}
|
|
10291
10339
|
|
|
10292
10340
|
// src/turn-history.ts
|
|
10293
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
10294
|
-
import { homedir as
|
|
10295
|
-
import { join as
|
|
10341
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync6, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
10342
|
+
import { homedir as homedir12 } from "os";
|
|
10343
|
+
import { join as join13 } from "path";
|
|
10296
10344
|
|
|
10297
10345
|
// src/turn-progress-store.ts
|
|
10298
|
-
import { mkdirSync as mkdirSync6, readFileSync as
|
|
10299
|
-
import { homedir as
|
|
10300
|
-
import { join as
|
|
10346
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync5, statSync as statSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
10347
|
+
import { homedir as homedir11 } from "os";
|
|
10348
|
+
import { join as join12 } from "path";
|
|
10301
10349
|
var MAX_TURN_PROGRESS = 64;
|
|
10302
10350
|
var TURN_PROGRESS_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
10303
10351
|
var TAG = /^[0-9a-f]{8}$/;
|
|
10304
10352
|
var pathOverride4 = null;
|
|
10305
10353
|
function turnProgressStorePath() {
|
|
10306
10354
|
if (pathOverride4) return pathOverride4;
|
|
10307
|
-
const stateRoot = process.env.XDG_STATE_HOME ||
|
|
10308
|
-
return
|
|
10355
|
+
const stateRoot = process.env.XDG_STATE_HOME || join12(homedir11(), ".local", "state");
|
|
10356
|
+
return join12(stateRoot, "opencode-claude-code-plugin", "turn-progress.json");
|
|
10309
10357
|
}
|
|
10310
10358
|
function isProgress(value) {
|
|
10311
10359
|
const record = value;
|
|
@@ -10316,7 +10364,7 @@ function isProgress(value) {
|
|
|
10316
10364
|
function readEntries(file, now) {
|
|
10317
10365
|
const out = /* @__PURE__ */ new Map();
|
|
10318
10366
|
try {
|
|
10319
|
-
const parsed = JSON.parse(
|
|
10367
|
+
const parsed = JSON.parse(readFileSync7(file, "utf8"));
|
|
10320
10368
|
const entries = parsed && typeof parsed === "object" ? parsed.turns : null;
|
|
10321
10369
|
if (!entries || typeof entries !== "object") return out;
|
|
10322
10370
|
const cutoff = now - TURN_PROGRESS_MAX_AGE_MS;
|
|
@@ -10335,7 +10383,7 @@ function recordTurnProgress(tag, progress, now = Date.now()) {
|
|
|
10335
10383
|
merged.set(tag, { ...record, out: Math.round(record.out) });
|
|
10336
10384
|
const kept = [...merged.entries()].slice(-MAX_TURN_PROGRESS);
|
|
10337
10385
|
try {
|
|
10338
|
-
mkdirSync6(
|
|
10386
|
+
mkdirSync6(join12(file, ".."), { recursive: true, mode: 448 });
|
|
10339
10387
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
10340
10388
|
writeFileSync6(tmp, JSON.stringify({ version: 1, turns: Object.fromEntries(kept) }), { mode: 384 });
|
|
10341
10389
|
renameSync5(tmp, file);
|
|
@@ -10353,8 +10401,8 @@ var SESSION_TAG = /^[0-9a-f]{8}$/;
|
|
|
10353
10401
|
var pathOverride5 = null;
|
|
10354
10402
|
function turnHistoryStorePath() {
|
|
10355
10403
|
if (pathOverride5) return pathOverride5;
|
|
10356
|
-
const stateRoot = process.env.XDG_STATE_HOME ||
|
|
10357
|
-
return
|
|
10404
|
+
const stateRoot = process.env.XDG_STATE_HOME || join13(homedir12(), ".local", "state");
|
|
10405
|
+
return join13(stateRoot, "opencode-claude-code-plugin", "turn-history.json");
|
|
10358
10406
|
}
|
|
10359
10407
|
function turnHistoryKey(agent, model) {
|
|
10360
10408
|
return `${agent || "main"}/${model}`;
|
|
@@ -10513,7 +10561,7 @@ function cleanSample(sample) {
|
|
|
10513
10561
|
function readEntries2(file, now) {
|
|
10514
10562
|
const out = /* @__PURE__ */ new Map();
|
|
10515
10563
|
try {
|
|
10516
|
-
const parsed = JSON.parse(
|
|
10564
|
+
const parsed = JSON.parse(readFileSync8(file, "utf8"));
|
|
10517
10565
|
const entries = parsed && typeof parsed === "object" ? parsed.turns : null;
|
|
10518
10566
|
if (!entries || typeof entries !== "object") return out;
|
|
10519
10567
|
const cutoff = now - TURN_SAMPLE_MAX_AGE_MS;
|
|
@@ -10538,7 +10586,7 @@ function recordTurnSample(key, sample) {
|
|
|
10538
10586
|
merged.set(key, samples);
|
|
10539
10587
|
const kept = bounded2(merged);
|
|
10540
10588
|
try {
|
|
10541
|
-
mkdirSync7(
|
|
10589
|
+
mkdirSync7(join13(file, ".."), { recursive: true, mode: 448 });
|
|
10542
10590
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
10543
10591
|
writeFileSync7(tmp, JSON.stringify({ version: 1, turns: Object.fromEntries(kept) }), { mode: 384 });
|
|
10544
10592
|
renameSync6(tmp, file);
|
|
@@ -10555,7 +10603,7 @@ function createTurnHistoryReader(file = turnHistoryStorePath) {
|
|
|
10555
10603
|
const path15 = file();
|
|
10556
10604
|
let next = "";
|
|
10557
10605
|
try {
|
|
10558
|
-
const stats =
|
|
10606
|
+
const stats = statSync7(path15);
|
|
10559
10607
|
next = `${stats.mtimeMs}:${stats.size}:${stats.ino}`;
|
|
10560
10608
|
} catch {
|
|
10561
10609
|
next = "missing";
|
|
@@ -11595,6 +11643,21 @@ function formatDoctorReport(report) {
|
|
|
11595
11643
|
lines.push("");
|
|
11596
11644
|
lines.push("A skipped server is missing from the model's tools with no other sign of it.");
|
|
11597
11645
|
}
|
|
11646
|
+
const unconnected = report.unconnectedConnectors ?? [];
|
|
11647
|
+
if (unconnected.length > 0) {
|
|
11648
|
+
lines.push("");
|
|
11649
|
+
lines.push("**claude.ai connectors this account never connected**");
|
|
11650
|
+
lines.push("");
|
|
11651
|
+
lines.push("| connector | status |");
|
|
11652
|
+
lines.push("|---|---|");
|
|
11653
|
+
for (const connector of unconnected) {
|
|
11654
|
+
lines.push(`| ${tableCell(connector.name)} | \`${connector.status}\` |`);
|
|
11655
|
+
}
|
|
11656
|
+
lines.push("");
|
|
11657
|
+
lines.push(
|
|
11658
|
+
"They come with the claude.ai organisation, not from your config, and load no tools. Connect one at claude.ai to give the model its tools; until then the plugin does not warn about it."
|
|
11659
|
+
);
|
|
11660
|
+
}
|
|
11598
11661
|
if (report.pluginLoadFailures.length > 0) {
|
|
11599
11662
|
lines.push("");
|
|
11600
11663
|
lines.push("**Plugins Claude Code did not load**");
|
|
@@ -11971,6 +12034,7 @@ async function gatherDoctorReport(options) {
|
|
|
11971
12034
|
proxyServers,
|
|
11972
12035
|
readRules: snapshotReadRuleMapping(),
|
|
11973
12036
|
mcpServerErrors: snapshotMcpServerErrors(),
|
|
12037
|
+
unconnectedConnectors: snapshotUnconnectedConnectors(),
|
|
11974
12038
|
pluginLoadFailures: snapshotPluginLoadFailures(),
|
|
11975
12039
|
hookFailures: snapshotHookFailures(),
|
|
11976
12040
|
planUsage,
|
|
@@ -12063,6 +12127,7 @@ async function buildDoctorReport(options) {
|
|
|
12063
12127
|
pendingCalls: report.pendingCalls.length,
|
|
12064
12128
|
proxyServers: report.proxyServers.map((server2) => server2.auth.status),
|
|
12065
12129
|
mcpServerErrors: report.mcpServerErrors.length,
|
|
12130
|
+
unconnectedConnectors: report.unconnectedConnectors?.length ?? 0,
|
|
12066
12131
|
pluginLoadFailures: report.pluginLoadFailures.length,
|
|
12067
12132
|
hookFailures: report.hookFailures.length,
|
|
12068
12133
|
planUsage: report.planUsage.status,
|
|
@@ -13121,7 +13186,7 @@ import { EventEmitter as EventEmitter4 } from "events";
|
|
|
13121
13186
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
13122
13187
|
import { existsSync as existsSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
13123
13188
|
import { unlink as unlink2 } from "fs/promises";
|
|
13124
|
-
import { join as
|
|
13189
|
+
import { join as join18 } from "path";
|
|
13125
13190
|
|
|
13126
13191
|
// src/claude-session-bun.ts
|
|
13127
13192
|
import * as os6 from "os";
|
|
@@ -13888,7 +13953,7 @@ var ClaudeSession = class {
|
|
|
13888
13953
|
throw new Error("session not started or already exited");
|
|
13889
13954
|
if (this.turn) throw new Error("a turn is already running in this session");
|
|
13890
13955
|
let settle;
|
|
13891
|
-
this.turn = new Promise((
|
|
13956
|
+
this.turn = new Promise((resolve8) => settle = resolve8);
|
|
13892
13957
|
this.turnDenied = [];
|
|
13893
13958
|
this.abandonTurn = false;
|
|
13894
13959
|
this.transcript.skipToEnd();
|
|
@@ -14303,7 +14368,7 @@ ${text2}`
|
|
|
14303
14368
|
}
|
|
14304
14369
|
function stageImage(data, extension) {
|
|
14305
14370
|
try {
|
|
14306
|
-
const file =
|
|
14371
|
+
const file = join18(pluginTmpDir(), `attachment-${randomUUID5()}.${extension}`);
|
|
14307
14372
|
writeFileSync9(file, data, { mode: 384, flag: "wx" });
|
|
14308
14373
|
return file;
|
|
14309
14374
|
} catch (err) {
|
|
@@ -14785,17 +14850,17 @@ function spawnInteractiveProcess(opts) {
|
|
|
14785
14850
|
}
|
|
14786
14851
|
|
|
14787
14852
|
// src/spawn-record-store.ts
|
|
14788
|
-
import { mkdirSync as mkdirSync9, readFileSync as
|
|
14789
|
-
import { homedir as
|
|
14790
|
-
import { join as
|
|
14853
|
+
import { mkdirSync as mkdirSync9, readFileSync as readFileSync12, renameSync as renameSync7, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
14854
|
+
import { homedir as homedir15 } from "os";
|
|
14855
|
+
import { join as join19 } from "path";
|
|
14791
14856
|
var MAX_SPAWN_RECORDS = 256;
|
|
14792
14857
|
var SPAWN_RECORD_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
14793
14858
|
var pathOverride6 = null;
|
|
14794
14859
|
var lastWritten = /* @__PURE__ */ new Map();
|
|
14795
14860
|
function spawnRecordStorePath() {
|
|
14796
14861
|
if (pathOverride6) return pathOverride6;
|
|
14797
|
-
const stateRoot = process.env.XDG_STATE_HOME ||
|
|
14798
|
-
return
|
|
14862
|
+
const stateRoot = process.env.XDG_STATE_HOME || join19(homedir15(), ".local", "state");
|
|
14863
|
+
return join19(stateRoot, "opencode-claude-code-plugin", "session-spawns.json");
|
|
14799
14864
|
}
|
|
14800
14865
|
function isRecord5(value) {
|
|
14801
14866
|
const record = value;
|
|
@@ -14808,7 +14873,7 @@ function isRecord5(value) {
|
|
|
14808
14873
|
function readEntries3(file) {
|
|
14809
14874
|
const out = /* @__PURE__ */ new Map();
|
|
14810
14875
|
try {
|
|
14811
|
-
const parsed = JSON.parse(
|
|
14876
|
+
const parsed = JSON.parse(readFileSync12(file, "utf8"));
|
|
14812
14877
|
const entries = parsed && typeof parsed === "object" ? parsed.sessions : null;
|
|
14813
14878
|
if (!entries || typeof entries !== "object") return out;
|
|
14814
14879
|
const cutoff = Date.now() - SPAWN_RECORD_MAX_AGE_MS;
|
|
@@ -14847,7 +14912,7 @@ ${record.agent ?? ""}`;
|
|
|
14847
14912
|
const cutoff = now - SPAWN_RECORD_MAX_AGE_MS;
|
|
14848
14913
|
const kept = [...merged.entries()].filter(([, entry]) => entry.at >= cutoff).sort((a, b) => a[1].at - b[1].at).slice(-MAX_SPAWN_RECORDS);
|
|
14849
14914
|
try {
|
|
14850
|
-
mkdirSync9(
|
|
14915
|
+
mkdirSync9(join19(file, ".."), { recursive: true, mode: 448 });
|
|
14851
14916
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
14852
14917
|
writeFileSync10(tmp, JSON.stringify({ version: 1, sessions: Object.fromEntries(kept) }), {
|
|
14853
14918
|
mode: 384
|
|
@@ -14922,13 +14987,13 @@ function dedupe2(dirs) {
|
|
|
14922
14987
|
}
|
|
14923
14988
|
|
|
14924
14989
|
// src/prompts.ts
|
|
14925
|
-
import { readFileSync as
|
|
14926
|
-
import { homedir as
|
|
14990
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "fs";
|
|
14991
|
+
import { homedir as homedir16 } from "os";
|
|
14927
14992
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
14928
|
-
import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as
|
|
14993
|
+
import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join20 } from "path";
|
|
14929
14994
|
function readPromptFileIfPresent(path15) {
|
|
14930
14995
|
try {
|
|
14931
|
-
const content =
|
|
14996
|
+
const content = readFileSync13(path15, "utf8").trim();
|
|
14932
14997
|
return content || void 0;
|
|
14933
14998
|
} catch {
|
|
14934
14999
|
return void 0;
|
|
@@ -14937,7 +15002,7 @@ function readPromptFileIfPresent(path15) {
|
|
|
14937
15002
|
function nearestWorkspaceAgentsPrompt(cwd) {
|
|
14938
15003
|
let dir = cwd;
|
|
14939
15004
|
while (true) {
|
|
14940
|
-
const content = readPromptFileIfPresent(
|
|
15005
|
+
const content = readPromptFileIfPresent(join20(dir, "AGENTS.md"));
|
|
14941
15006
|
if (content) return content;
|
|
14942
15007
|
const parent = dirname6(dir);
|
|
14943
15008
|
if (parent === dir) return void 0;
|
|
@@ -15048,7 +15113,7 @@ var CLAUDE_NATIVE_INSTRUCTION_FILES = /* @__PURE__ */ new Set(["CLAUDE.md", "CLA
|
|
|
15048
15113
|
function userAuthoredInstructions(forwarded, opts = {}) {
|
|
15049
15114
|
const readFile3 = opts.readFile ?? ((path15) => {
|
|
15050
15115
|
try {
|
|
15051
|
-
return
|
|
15116
|
+
return readFileSync13(path15, "utf8");
|
|
15052
15117
|
} catch {
|
|
15053
15118
|
return null;
|
|
15054
15119
|
}
|
|
@@ -15089,8 +15154,8 @@ ${options.compressionSummary.trim()}`
|
|
|
15089
15154
|
for (const s of extraSystemContent) {
|
|
15090
15155
|
if (s.trim()) parts.push(s.trim());
|
|
15091
15156
|
}
|
|
15092
|
-
const configRoot = process.env.XDG_CONFIG_HOME ??
|
|
15093
|
-
const globalAgents = readPromptFileIfPresent(
|
|
15157
|
+
const configRoot = process.env.XDG_CONFIG_HOME ?? join20(homedir16(), ".config");
|
|
15158
|
+
const globalAgents = readPromptFileIfPresent(join20(configRoot, "opencode", "AGENTS.md"));
|
|
15094
15159
|
const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd);
|
|
15095
15160
|
const forwarded = extraSystemContent.join("\n\n");
|
|
15096
15161
|
const pushGlobal = !!globalAgents && !forwarded.includes(globalAgents);
|
|
@@ -15106,7 +15171,7 @@ ${options.compressionSummary.trim()}`
|
|
|
15106
15171
|
if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT);
|
|
15107
15172
|
const content = parts.join("\n\n");
|
|
15108
15173
|
if (!content) return void 0;
|
|
15109
|
-
const path15 =
|
|
15174
|
+
const path15 = join20(pluginTmpDir(), `opencode-cc-sys-${randomUUID7()}.md`);
|
|
15110
15175
|
try {
|
|
15111
15176
|
writeFileSync11(path15, content, { encoding: "utf8", mode: 384 });
|
|
15112
15177
|
return path15;
|
|
@@ -16118,8 +16183,8 @@ function watchTurnAbort(signal) {
|
|
|
16118
16183
|
let aborted = signal?.aborted === true;
|
|
16119
16184
|
let listeners = [];
|
|
16120
16185
|
let settle;
|
|
16121
|
-
const whenAborted = new Promise((
|
|
16122
|
-
settle =
|
|
16186
|
+
const whenAborted = new Promise((resolve8) => {
|
|
16187
|
+
settle = resolve8;
|
|
16123
16188
|
});
|
|
16124
16189
|
const fire = () => {
|
|
16125
16190
|
if (aborted && listeners === null) return;
|
|
@@ -16892,7 +16957,8 @@ function createLineHandler(state, ctx) {
|
|
|
16892
16957
|
}
|
|
16893
16958
|
reportFastModeState(msg, ctx.fastMode, "init");
|
|
16894
16959
|
reportSystemInit(msg, {
|
|
16895
|
-
ignoreAnthropicApiKey: ctx.config.ignoreAnthropicApiKey
|
|
16960
|
+
ignoreAnthropicApiKey: ctx.config.ignoreAnthropicApiKey,
|
|
16961
|
+
configDir: ctx.accountConfigDir
|
|
16896
16962
|
});
|
|
16897
16963
|
}
|
|
16898
16964
|
if (msg.type === "system" && msg.subtype === "compact_boundary") {
|
|
@@ -18964,7 +19030,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
18964
19030
|
let replayReason = "no-session-for-key";
|
|
18965
19031
|
if (this.config.resumeAfterRestart !== false && includeHistoryContext && !compactionMode && !forkFromClaudeSessionId && failoverAnswer?.kind !== "switch") {
|
|
18966
19032
|
const configDir = resolveConfigDir(this.config.configDir);
|
|
18967
|
-
const transcriptPath2 = (id, dir) =>
|
|
19033
|
+
const transcriptPath2 = (id, dir) => join21(dir ?? configDir, "projects", encodeCwd(cwd), `${id}.jsonl`);
|
|
18968
19034
|
const resumePoint = findResumePoint({
|
|
18969
19035
|
sessionKey: sk,
|
|
18970
19036
|
prompt: options.prompt,
|
|
@@ -20448,7 +20514,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
20448
20514
|
return fresh.length;
|
|
20449
20515
|
};
|
|
20450
20516
|
if (!state.unattendedTurnEnded && await forwardTrailingUserMessages() > 0) {
|
|
20451
|
-
await new Promise((
|
|
20517
|
+
await new Promise((resolve8) => setTimeout(resolve8, FORWARD_SETTLE_MS));
|
|
20452
20518
|
if (state.controllerClosed) return;
|
|
20453
20519
|
}
|
|
20454
20520
|
for (const { call, result: opencodeResult } of previousPendingProxyMatches) {
|
|
@@ -20552,7 +20618,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
20552
20618
|
};
|
|
20553
20619
|
|
|
20554
20620
|
// src/account-tier.ts
|
|
20555
|
-
import { readFileSync as
|
|
20621
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
20556
20622
|
import path14 from "path";
|
|
20557
20623
|
var ORGANIZATION_TYPE_LABELS = {
|
|
20558
20624
|
claude_max: "Max",
|
|
@@ -20595,7 +20661,7 @@ function readTierFromConfigDir(configDir, allowLegacyFallback) {
|
|
|
20595
20661
|
function readOauthAccount(file) {
|
|
20596
20662
|
let raw;
|
|
20597
20663
|
try {
|
|
20598
|
-
raw =
|
|
20664
|
+
raw = readFileSync14(file, "utf8");
|
|
20599
20665
|
} catch {
|
|
20600
20666
|
return void 0;
|
|
20601
20667
|
}
|
|
@@ -20633,13 +20699,13 @@ function registerSidebarAccounts(accounts) {
|
|
|
20633
20699
|
import {
|
|
20634
20700
|
existsSync as existsSync5,
|
|
20635
20701
|
mkdirSync as mkdirSync10,
|
|
20636
|
-
readFileSync as
|
|
20702
|
+
readFileSync as readFileSync15,
|
|
20637
20703
|
realpathSync as realpathSync4,
|
|
20638
20704
|
rmSync as rmSync3,
|
|
20639
20705
|
writeFileSync as writeFileSync12
|
|
20640
20706
|
} from "fs";
|
|
20641
|
-
import { homedir as
|
|
20642
|
-
import { dirname as dirname7, join as
|
|
20707
|
+
import { homedir as homedir17 } from "os";
|
|
20708
|
+
import { dirname as dirname7, join as join22, resolve as resolve7 } from "path";
|
|
20643
20709
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
20644
20710
|
var STALE_PACKAGE_NAME = "opencode-claude-code-plugin";
|
|
20645
20711
|
var SUSPECT_DESCRIPTION_TOKEN = "Claude Code";
|
|
@@ -20647,20 +20713,20 @@ var alreadyRan = false;
|
|
|
20647
20713
|
function candidateCacheRoots() {
|
|
20648
20714
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
20649
20715
|
return [
|
|
20650
|
-
xdg ?
|
|
20651
|
-
|
|
20652
|
-
|
|
20716
|
+
xdg ? join22(xdg, "opencode") : null,
|
|
20717
|
+
join22(homedir17(), ".cache", "opencode"),
|
|
20718
|
+
join22(homedir17(), "Library", "Caches", "opencode")
|
|
20653
20719
|
].filter((p) => Boolean(p));
|
|
20654
20720
|
}
|
|
20655
20721
|
function userOpencodeJsonPath() {
|
|
20656
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ??
|
|
20657
|
-
return
|
|
20722
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? join22(homedir17(), ".config");
|
|
20723
|
+
return join22(xdgConfig, "opencode", "opencode.json");
|
|
20658
20724
|
}
|
|
20659
20725
|
function userIntendsToUseUnscoped() {
|
|
20660
20726
|
const cfg = userOpencodeJsonPath();
|
|
20661
20727
|
if (!existsSync5(cfg)) return false;
|
|
20662
20728
|
try {
|
|
20663
|
-
const json = JSON.parse(
|
|
20729
|
+
const json = JSON.parse(readFileSync15(cfg, "utf8"));
|
|
20664
20730
|
const plugins = json.plugin;
|
|
20665
20731
|
if (!Array.isArray(plugins)) return false;
|
|
20666
20732
|
return plugins.some(
|
|
@@ -20673,7 +20739,7 @@ function userIntendsToUseUnscoped() {
|
|
|
20673
20739
|
function ourLoadedDir() {
|
|
20674
20740
|
try {
|
|
20675
20741
|
const filePath = fileURLToPath4(import.meta.url);
|
|
20676
|
-
return realpathSync4(
|
|
20742
|
+
return realpathSync4(resolve7(filePath, "..", ".."));
|
|
20677
20743
|
} catch {
|
|
20678
20744
|
return null;
|
|
20679
20745
|
}
|
|
@@ -20681,19 +20747,19 @@ function ourLoadedDir() {
|
|
|
20681
20747
|
function ourVersion(dir) {
|
|
20682
20748
|
if (!dir) return null;
|
|
20683
20749
|
try {
|
|
20684
|
-
const pkg = JSON.parse(
|
|
20750
|
+
const pkg = JSON.parse(readFileSync15(join22(dir, "package.json"), "utf8"));
|
|
20685
20751
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
20686
20752
|
} catch {
|
|
20687
20753
|
return null;
|
|
20688
20754
|
}
|
|
20689
20755
|
}
|
|
20690
20756
|
function markerPath() {
|
|
20691
|
-
const stateRoot = process.env.XDG_STATE_HOME ??
|
|
20692
|
-
return
|
|
20757
|
+
const stateRoot = process.env.XDG_STATE_HOME ?? join22(homedir17(), ".local", "state");
|
|
20758
|
+
return join22(stateRoot, "opencode-claude-code-plugin", "cleanup-stale.json");
|
|
20693
20759
|
}
|
|
20694
20760
|
function markerVersion() {
|
|
20695
20761
|
try {
|
|
20696
|
-
const marker = JSON.parse(
|
|
20762
|
+
const marker = JSON.parse(readFileSync15(markerPath(), "utf8"));
|
|
20697
20763
|
return typeof marker.version === "string" ? marker.version : null;
|
|
20698
20764
|
} catch {
|
|
20699
20765
|
return null;
|
|
@@ -20738,7 +20804,7 @@ function cleanupStaleUnscopedInstall() {
|
|
|
20738
20804
|
}
|
|
20739
20805
|
function cleanupOne(cacheRoot, ourDir) {
|
|
20740
20806
|
if (!existsSync5(cacheRoot)) return;
|
|
20741
|
-
const stalePath =
|
|
20807
|
+
const stalePath = join22(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
|
|
20742
20808
|
if (!existsSync5(stalePath)) return;
|
|
20743
20809
|
let realStalePath = stalePath;
|
|
20744
20810
|
try {
|
|
@@ -20746,11 +20812,11 @@ function cleanupOne(cacheRoot, ourDir) {
|
|
|
20746
20812
|
} catch {
|
|
20747
20813
|
}
|
|
20748
20814
|
if (ourDir && realStalePath === ourDir) return;
|
|
20749
|
-
const pkgJsonPath =
|
|
20815
|
+
const pkgJsonPath = join22(stalePath, "package.json");
|
|
20750
20816
|
if (!existsSync5(pkgJsonPath)) return;
|
|
20751
20817
|
let pkg = {};
|
|
20752
20818
|
try {
|
|
20753
|
-
pkg = JSON.parse(
|
|
20819
|
+
pkg = JSON.parse(readFileSync15(pkgJsonPath, "utf8"));
|
|
20754
20820
|
} catch {
|
|
20755
20821
|
return;
|
|
20756
20822
|
}
|
|
@@ -20766,10 +20832,10 @@ function cleanupOne(cacheRoot, ourDir) {
|
|
|
20766
20832
|
});
|
|
20767
20833
|
return;
|
|
20768
20834
|
}
|
|
20769
|
-
const cachePkgJson =
|
|
20835
|
+
const cachePkgJson = join22(cacheRoot, "package.json");
|
|
20770
20836
|
if (!existsSync5(cachePkgJson)) return;
|
|
20771
20837
|
try {
|
|
20772
|
-
const cfg = JSON.parse(
|
|
20838
|
+
const cfg = JSON.parse(readFileSync15(cachePkgJson, "utf8"));
|
|
20773
20839
|
if (cfg?.dependencies?.[STALE_PACKAGE_NAME]) {
|
|
20774
20840
|
delete cfg.dependencies[STALE_PACKAGE_NAME];
|
|
20775
20841
|
writeFileSync12(cachePkgJson, JSON.stringify(cfg, null, 2) + "\n");
|