@khalilgharbaoui/opencode-claude-code-plugin 0.60.2 → 0.61.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/dist/index.d.ts +15 -0
- package/dist/index.js +128 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -473,6 +473,8 @@ interface ClaudeCodeConfig {
|
|
|
473
473
|
bridgeSkipNativeSkills?: boolean;
|
|
474
474
|
/** Append a one-line cost / duration / cache footer to each finished turn. */
|
|
475
475
|
turnStats?: boolean;
|
|
476
|
+
/** Turn Claude Code's todo tools on for every model (`CLAUDE_CODE_ENABLE_TODO_TOOLS=1`). */
|
|
477
|
+
enableTodoTools?: boolean;
|
|
476
478
|
/** Branch a forked opencode session off the parent's Claude conversation. */
|
|
477
479
|
forkSessions?: boolean;
|
|
478
480
|
/** Resume a conversation's Claude session after opencode restarts. Default true. */
|
|
@@ -992,6 +994,19 @@ interface ClaudeCodeProviderSettings {
|
|
|
992
994
|
* `permission_denials` always reach `providerMetadata`.
|
|
993
995
|
*/
|
|
994
996
|
turnStats?: boolean;
|
|
997
|
+
/**
|
|
998
|
+
* Start every `claude` with `CLAUDE_CODE_ENABLE_TODO_TOOLS=1`, so the CLI
|
|
999
|
+
* offers its todo tools (`TaskCreate` and family) whatever the model.
|
|
1000
|
+
* Claude Code offers them on its own only to Claude 3.x, Opus 4.0 to 4.7,
|
|
1001
|
+
* Sonnet 4.0 to 4.6 and Haiku 4.5; on Opus 4.8, the 5.x models and Fable
|
|
1002
|
+
* no todo list reaches opencode without this (h #g259).
|
|
1003
|
+
*
|
|
1004
|
+
* Off by default, because the CLI turned the tools off for those models on
|
|
1005
|
+
* purpose. Fills a gap only: a `CLAUDE_CODE_ENABLE_TODO_TOOLS` already in
|
|
1006
|
+
* opencode's environment, `0` included, is passed through and decides.
|
|
1007
|
+
* Never on a compaction spawn, which runs no tools.
|
|
1008
|
+
*/
|
|
1009
|
+
enableTodoTools?: boolean;
|
|
995
1010
|
/**
|
|
996
1011
|
* When a new opencode session turns out to be a fork of one this provider
|
|
997
1012
|
* already served, branch the parent's Claude conversation with
|
package/dist/index.js
CHANGED
|
@@ -3808,23 +3808,36 @@ import { createHash } from "crypto";
|
|
|
3808
3808
|
var fingerprints = /* @__PURE__ */ new Map();
|
|
3809
3809
|
var fingerprintSeq = 0;
|
|
3810
3810
|
var MAX_FORK_FINGERPRINTS = 64;
|
|
3811
|
-
var DIGEST_VERSION =
|
|
3811
|
+
var DIGEST_VERSION = 3;
|
|
3812
3812
|
var DCP_MESSAGE_ID_TAG = /<dcp-message-id(?:\s[^>]*)?>[^<]*<\/dcp-message-id>/g;
|
|
3813
3813
|
var DCP_COMPACT_REF_LINE = /^@(?:\d+|b\d+|blocked)@(?: \[[^\]\n]*\])?$/;
|
|
3814
|
-
|
|
3815
|
-
|
|
3814
|
+
var DCP_SYSTEM_REMINDER_BLOCK = /<dcp-system-reminder>[\s\S]*?<\/dcp-system-reminder>/g;
|
|
3815
|
+
function withoutDcpRefs(text, version) {
|
|
3816
|
+
let out = text;
|
|
3817
|
+
let removed = false;
|
|
3818
|
+
if (version >= 3 && out.includes("<dcp-system-reminder")) {
|
|
3819
|
+
out = out.replace(DCP_SYSTEM_REMINDER_BLOCK, "");
|
|
3820
|
+
removed = true;
|
|
3821
|
+
}
|
|
3822
|
+
if (out.includes("<dcp-message-id")) {
|
|
3823
|
+
out = out.replace(DCP_MESSAGE_ID_TAG, "");
|
|
3824
|
+
removed = true;
|
|
3825
|
+
}
|
|
3816
3826
|
for (; ; ) {
|
|
3817
3827
|
const trimmed = out.trimEnd();
|
|
3818
|
-
if (!trimmed.endsWith("@") && !trimmed.endsWith("]"))
|
|
3828
|
+
if (!trimmed.endsWith("@") && !trimmed.endsWith("]")) break;
|
|
3819
3829
|
const lineStart = trimmed.lastIndexOf("\n") + 1;
|
|
3820
|
-
if (!DCP_COMPACT_REF_LINE.test(trimmed.slice(lineStart)))
|
|
3830
|
+
if (!DCP_COMPACT_REF_LINE.test(trimmed.slice(lineStart))) break;
|
|
3821
3831
|
out = trimmed.slice(0, lineStart);
|
|
3832
|
+
removed = true;
|
|
3822
3833
|
}
|
|
3834
|
+
if (version < 3 || !removed) return out;
|
|
3835
|
+
return out.replace(/\n{3,}/g, "\n\n").trim();
|
|
3823
3836
|
}
|
|
3824
3837
|
function hashPart(hash, part, version) {
|
|
3825
3838
|
const p = part;
|
|
3826
3839
|
const type = typeof p?.type === "string" ? p.type : "unknown";
|
|
3827
|
-
const content = (text) => version >= 2 ? withoutDcpRefs(text) : text;
|
|
3840
|
+
const content = (text) => version >= 2 ? withoutDcpRefs(text, version) : text;
|
|
3828
3841
|
switch (type) {
|
|
3829
3842
|
case "text":
|
|
3830
3843
|
hash.update("text\0");
|
|
@@ -3840,7 +3853,9 @@ function hashPart(hash, part, version) {
|
|
|
3840
3853
|
hash.update("result\0");
|
|
3841
3854
|
hash.update(String(p?.toolName ?? ""));
|
|
3842
3855
|
hash.update("\0");
|
|
3843
|
-
hash.update(
|
|
3856
|
+
hash.update(
|
|
3857
|
+
stableJson(p?.output, version >= 2 ? (text) => withoutDcpRefs(text, version) : void 0)
|
|
3858
|
+
);
|
|
3844
3859
|
break;
|
|
3845
3860
|
case "file":
|
|
3846
3861
|
case "image": {
|
|
@@ -3888,7 +3903,7 @@ function messageDigest(msg, version) {
|
|
|
3888
3903
|
hash.update("\0");
|
|
3889
3904
|
if (typeof msg.content === "string") {
|
|
3890
3905
|
hash.update("text\0");
|
|
3891
|
-
hash.update(version >= 2 ? withoutDcpRefs(msg.content) : msg.content);
|
|
3906
|
+
hash.update(version >= 2 ? withoutDcpRefs(msg.content, version) : msg.content);
|
|
3892
3907
|
hash.update("");
|
|
3893
3908
|
} else if (Array.isArray(msg.content)) {
|
|
3894
3909
|
for (const part of msg.content) hashPart(hash, part, version);
|
|
@@ -7429,6 +7444,7 @@ function findForeignAccountSibling(opts) {
|
|
|
7429
7444
|
if (modelSiblingSignature(key, providers) !== signature) return void 0;
|
|
7430
7445
|
const account = sessionKeyAccount(key, providers);
|
|
7431
7446
|
if (account === void 0 || account === ownAccount) return void 0;
|
|
7447
|
+
if (opts.only && !opts.only(account)) return void 0;
|
|
7432
7448
|
return { siblingKey: key, account };
|
|
7433
7449
|
};
|
|
7434
7450
|
for (const key of opts.extraKeys ?? []) {
|
|
@@ -7872,6 +7888,7 @@ function claudeSpawnEnv(opts) {
|
|
|
7872
7888
|
if (opts?.configDir) {
|
|
7873
7889
|
env.CLAUDE_CONFIG_DIR = opts.configDir;
|
|
7874
7890
|
}
|
|
7891
|
+
Object.assign(env, todoToolsEnv(opts?.enableTodoTools === true));
|
|
7875
7892
|
if (opts?.ignoreAnthropicApiKey) {
|
|
7876
7893
|
delete env.ANTHROPIC_API_KEY;
|
|
7877
7894
|
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
@@ -7881,6 +7898,10 @@ function claudeSpawnEnv(opts) {
|
|
|
7881
7898
|
}
|
|
7882
7899
|
return env;
|
|
7883
7900
|
}
|
|
7901
|
+
function todoToolsEnv(enabled) {
|
|
7902
|
+
if (!enabled || process.env.CLAUDE_CODE_ENABLE_TODO_TOOLS !== void 0) return {};
|
|
7903
|
+
return { CLAUDE_CODE_ENABLE_TODO_TOOLS: "1" };
|
|
7904
|
+
}
|
|
7884
7905
|
function touch(key) {
|
|
7885
7906
|
const existing = activeProcesses.get(key);
|
|
7886
7907
|
if (existing) {
|
|
@@ -8252,7 +8273,7 @@ function invalidateOtherEffortSessions(baseKey, effort) {
|
|
|
8252
8273
|
clearBackgroundTasks(key);
|
|
8253
8274
|
}
|
|
8254
8275
|
}
|
|
8255
|
-
function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcpHash, systemPromptFile, ignoreAnthropicApiKey, effort, promptCacheTtl, configDir) {
|
|
8276
|
+
function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcpHash, systemPromptFile, ignoreAnthropicApiKey, effort, promptCacheTtl, configDir, enableTodoTools) {
|
|
8256
8277
|
evictIfNeeded();
|
|
8257
8278
|
log.info("spawning new claude process", {
|
|
8258
8279
|
cliPath,
|
|
@@ -8261,13 +8282,14 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
|
|
|
8261
8282
|
sessionKey: sessionKey2,
|
|
8262
8283
|
effort,
|
|
8263
8284
|
promptCacheTtl,
|
|
8264
|
-
configDir
|
|
8285
|
+
configDir,
|
|
8286
|
+
...enableTodoTools ? { enableTodoTools } : {}
|
|
8265
8287
|
});
|
|
8266
8288
|
const plan = planClaudeSpawn(cliPath, cliArgs);
|
|
8267
8289
|
const proc = spawn(plan.file, plan.args, {
|
|
8268
8290
|
cwd,
|
|
8269
8291
|
stdio: ["pipe", "pipe", "pipe"],
|
|
8270
|
-
env: claudeSpawnEnv({ ignoreAnthropicApiKey, effort, promptCacheTtl, configDir }),
|
|
8292
|
+
env: claudeSpawnEnv({ ignoreAnthropicApiKey, effort, promptCacheTtl, configDir, enableTodoTools }),
|
|
8271
8293
|
windowsVerbatimArguments: plan.windowsVerbatimArguments
|
|
8272
8294
|
});
|
|
8273
8295
|
const lineEmitter = new EventEmitter3();
|
|
@@ -8279,6 +8301,7 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
|
|
|
8279
8301
|
systemPromptFile,
|
|
8280
8302
|
effort,
|
|
8281
8303
|
promptCacheTtl,
|
|
8304
|
+
enableTodoTools,
|
|
8282
8305
|
startedAt: Date.now(),
|
|
8283
8306
|
cliPath,
|
|
8284
8307
|
cliArgs: [...cliArgs],
|
|
@@ -8410,7 +8433,8 @@ function respawnActiveProcess(sessionKey2, cliPath, cliArgs, cwd, ignoreAnthropi
|
|
|
8410
8433
|
ignoreAnthropicApiKey,
|
|
8411
8434
|
old.effort,
|
|
8412
8435
|
old.promptCacheTtl,
|
|
8413
|
-
old.configDir
|
|
8436
|
+
old.configDir,
|
|
8437
|
+
old.enableTodoTools
|
|
8414
8438
|
);
|
|
8415
8439
|
replacement.mcpServers = old.mcpServers;
|
|
8416
8440
|
replacement.pendingProxyCompletions = old.pendingProxyCompletions;
|
|
@@ -9122,6 +9146,7 @@ var PLUGIN_LOG_MESSAGES = /* @__PURE__ */ new Set([
|
|
|
9122
9146
|
"no configured account could take this turn; it ends here",
|
|
9123
9147
|
"no proxyTools entry was recognised; nothing will be proxied this turn",
|
|
9124
9148
|
"no stdout after envelope write; respawning claude process to resume conversation",
|
|
9149
|
+
"not replaying what this claude session missed: the conversation continued on an account in another group",
|
|
9125
9150
|
"opencode 2 event subscription ended; deleted sessions keep their claude process until idle eviction, and stopped turns keep their proxy calls until the next message",
|
|
9126
9151
|
"opencode's stored OAuth token for this MCP server has expired, so the bridged server carries no credential; re-authenticate it in opencode",
|
|
9127
9152
|
"pending proxy call arrived after stream close; rejecting",
|
|
@@ -9259,6 +9284,7 @@ var BUNDLE_DATA_ALLOWLIST = {
|
|
|
9259
9284
|
historyLength: "count",
|
|
9260
9285
|
matchedMessages: "count",
|
|
9261
9286
|
messages: "count",
|
|
9287
|
+
userMessages: "count",
|
|
9262
9288
|
inputTokens: "count",
|
|
9263
9289
|
lastTextLength: "count",
|
|
9264
9290
|
lines: "count",
|
|
@@ -11111,6 +11137,11 @@ function formatDoctorReport(report) {
|
|
|
11111
11137
|
`| subagentDispatch | ${report.subagentDispatch}${report.subagentDispatch === "ask" && report.subagentDispatchCrossGroup ? " (cross-group accounts allowed)" : ""} |`
|
|
11112
11138
|
);
|
|
11113
11139
|
lines.push(`| turnStats | ${report.turnStats} |`);
|
|
11140
|
+
if (report.todoTools) {
|
|
11141
|
+
lines.push(
|
|
11142
|
+
`| enableTodoTools | ${report.todoTools.option}${report.todoTools.envSet ? " (CLAUDE_CODE_ENABLE_TODO_TOOLS is set in opencode's environment and decides)" : ""} |`
|
|
11143
|
+
);
|
|
11144
|
+
}
|
|
11114
11145
|
lines.push(`| ANTHROPIC_API_KEY in env | ${report.anthropicApiKeyInEnv ? "yes" : "no"} |`);
|
|
11115
11146
|
const overriding = report.permissionPresets.filter((row) => row.overrides.length > 0);
|
|
11116
11147
|
if (overriding.length > 0) {
|
|
@@ -11542,6 +11573,10 @@ async function gatherDoctorReport(options) {
|
|
|
11542
11573
|
subagentDispatch: base.subagentDispatch,
|
|
11543
11574
|
subagentDispatchCrossGroup: base.subagentDispatchCrossGroup,
|
|
11544
11575
|
turnStats: options.turnStats,
|
|
11576
|
+
todoTools: {
|
|
11577
|
+
option: options.enableTodoTools === true,
|
|
11578
|
+
envSet: process.env.CLAUDE_CODE_ENABLE_TODO_TOOLS !== void 0
|
|
11579
|
+
},
|
|
11545
11580
|
anthropicApiKeyInEnv: base.anthropicApiKeyInEnv,
|
|
11546
11581
|
processes,
|
|
11547
11582
|
pendingCalls: snapshotPendingProxyCalls(),
|
|
@@ -18019,6 +18054,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
18019
18054
|
cliPath,
|
|
18020
18055
|
interactive: !!useInteractive,
|
|
18021
18056
|
turnStats: this.config.turnStats === true,
|
|
18057
|
+
enableTodoTools: this.config.enableTodoTools === true,
|
|
18022
18058
|
ignoreAnthropicApiKey: this.config.ignoreAnthropicApiKey === true,
|
|
18023
18059
|
// Where the plugin applies the account itself rather than through a
|
|
18024
18060
|
// wrapper (`accountInProcess`, Windows), the `/cost` spawn needs the
|
|
@@ -18427,30 +18463,45 @@ var ClaudeCodeLanguageModel = class {
|
|
|
18427
18463
|
carried: conversationOnTarget
|
|
18428
18464
|
});
|
|
18429
18465
|
}
|
|
18430
|
-
let
|
|
18431
|
-
|
|
18432
|
-
|
|
18466
|
+
let crossGroupAccountRead = false;
|
|
18467
|
+
let crossGroupAccountValue;
|
|
18468
|
+
const crossGroupAccount = () => {
|
|
18469
|
+
if (crossGroupAccountRead) return crossGroupAccountValue;
|
|
18470
|
+
crossGroupAccountRead = true;
|
|
18471
|
+
if (compactionMode || !groups || accountProviders.size === 0) return void 0;
|
|
18472
|
+
if (failoverAnswer?.kind === "switch") return void 0;
|
|
18473
|
+
crossGroupAccountValue = findForeignAccountSibling({
|
|
18433
18474
|
sessionKey: sk,
|
|
18434
18475
|
accountProviders,
|
|
18435
18476
|
// The live process's own view, so the guard holds with
|
|
18436
18477
|
// `resumeAfterRestart: false`, where the store is never written.
|
|
18437
|
-
extraKeys: listClaudeSessionKeys()
|
|
18478
|
+
extraKeys: listClaudeSessionKeys(),
|
|
18479
|
+
only: (account) => !accountsShareGroup(sourceAccount, account, groups)
|
|
18480
|
+
})?.account;
|
|
18481
|
+
return crossGroupAccountValue;
|
|
18482
|
+
};
|
|
18483
|
+
const accountGroupNoteFor = (from) => formatAccountGroupNote({
|
|
18484
|
+
sourceAccount: from,
|
|
18485
|
+
sourceGroup: accountGroup(from, groups),
|
|
18486
|
+
targetAccount: sourceAccount,
|
|
18487
|
+
targetGroup: accountGroup(sourceAccount, groups)
|
|
18488
|
+
});
|
|
18489
|
+
const logAnotherAccountGroup = (from) => {
|
|
18490
|
+
log.notice("starting fresh on this account: it is in another account group", {
|
|
18491
|
+
sessionKey: sk,
|
|
18492
|
+
reason: "another-account-group",
|
|
18493
|
+
account: sourceAccount,
|
|
18494
|
+
from,
|
|
18495
|
+
group: accountGroup(sourceAccount, groups)
|
|
18438
18496
|
});
|
|
18439
|
-
|
|
18497
|
+
};
|
|
18498
|
+
let accountGroupNote = null;
|
|
18499
|
+
if (includeHistoryContext) {
|
|
18500
|
+
const from = crossGroupAccount();
|
|
18501
|
+
if (from) {
|
|
18440
18502
|
includeHistoryContext = false;
|
|
18441
|
-
accountGroupNote =
|
|
18442
|
-
|
|
18443
|
-
sourceGroup: accountGroup(foreign.account, groups),
|
|
18444
|
-
targetAccount: sourceAccount,
|
|
18445
|
-
targetGroup: accountGroup(sourceAccount, groups)
|
|
18446
|
-
});
|
|
18447
|
-
log.notice("starting fresh on this account: it is in another account group", {
|
|
18448
|
-
sessionKey: sk,
|
|
18449
|
-
reason: "another-account-group",
|
|
18450
|
-
account: sourceAccount,
|
|
18451
|
-
from: foreign.account,
|
|
18452
|
-
group: accountGroup(sourceAccount, groups)
|
|
18453
|
-
});
|
|
18503
|
+
accountGroupNote = accountGroupNoteFor(from);
|
|
18504
|
+
logAnotherAccountGroup(from);
|
|
18454
18505
|
}
|
|
18455
18506
|
}
|
|
18456
18507
|
let forkFromClaudeSessionId;
|
|
@@ -18600,28 +18651,52 @@ var ClaudeCodeLanguageModel = class {
|
|
|
18600
18651
|
});
|
|
18601
18652
|
}
|
|
18602
18653
|
const conversationChange = !compactionMode && !includeHistoryContext && failoverAnswer?.kind !== "switch" && !accountGroupNote && (!!getClaudeSessionId(sk) || !!getActiveProcess(sk)) ? classifyConversationChange(sk, filterSideQuestionHistory(options.prompt)) : null;
|
|
18603
|
-
|
|
18604
|
-
if (missed) {
|
|
18605
|
-
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18654
|
+
let missed = null;
|
|
18655
|
+
if (conversationChange?.kind === "missed") {
|
|
18656
|
+
const from = crossGroupAccount();
|
|
18657
|
+
if (from) {
|
|
18658
|
+
log.notice(
|
|
18659
|
+
"not replaying what this claude session missed: the conversation continued on an account in another group",
|
|
18660
|
+
{
|
|
18661
|
+
sessionKey: sk,
|
|
18662
|
+
reason: "another-account-group",
|
|
18663
|
+
account: sourceAccount,
|
|
18664
|
+
from,
|
|
18665
|
+
group: accountGroup(sourceAccount, groups),
|
|
18666
|
+
messages: conversationChange.messages.length,
|
|
18667
|
+
userMessages: conversationChange.userMessages
|
|
18668
|
+
}
|
|
18669
|
+
);
|
|
18670
|
+
} else {
|
|
18671
|
+
missed = conversationChange;
|
|
18672
|
+
log.notice("replaying the messages this claude session missed: the conversation continued under another session key", {
|
|
18673
|
+
sessionKey: sk,
|
|
18674
|
+
messages: missed.messages.length,
|
|
18675
|
+
userMessages: missed.userMessages
|
|
18676
|
+
});
|
|
18677
|
+
}
|
|
18610
18678
|
}
|
|
18611
18679
|
let rewoundNote = null;
|
|
18612
18680
|
if (conversationChange?.kind === "rewound") {
|
|
18613
18681
|
await deleteActiveProcessAndWait(sk);
|
|
18614
18682
|
deleteClaudeSessionId(sk);
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18683
|
+
const from = crossGroupAccount();
|
|
18684
|
+
if (from) {
|
|
18685
|
+
includeHistoryContext = false;
|
|
18686
|
+
accountGroupNote = accountGroupNote ?? accountGroupNoteFor(from);
|
|
18687
|
+
logAnotherAccountGroup(from);
|
|
18688
|
+
} else {
|
|
18689
|
+
includeHistoryContext = true;
|
|
18690
|
+
replayReason = "history-rewound";
|
|
18691
|
+
log.notice("replaying the conversation as text: the thread was edited or undone", {
|
|
18692
|
+
sessionKey: sk,
|
|
18693
|
+
reason: "history-rewound",
|
|
18694
|
+
sharedMessages: conversationChange.sharedMessages,
|
|
18695
|
+
removedMessages: conversationChange.removedMessages,
|
|
18696
|
+
removedUserMessages: conversationChange.removedUserMessages
|
|
18697
|
+
});
|
|
18698
|
+
if (mode !== "generate") rewoundNote = formatConversationRewoundNote();
|
|
18699
|
+
}
|
|
18625
18700
|
}
|
|
18626
18701
|
if (this.config.forkSessions === true && !compactionMode) {
|
|
18627
18702
|
recordForkFingerprint(sk, options.prompt, cliPath);
|
|
@@ -19219,7 +19294,8 @@ var ClaudeCodeLanguageModel = class {
|
|
|
19219
19294
|
claudeSpawnEnv({
|
|
19220
19295
|
ignoreAnthropicApiKey: self.config.ignoreAnthropicApiKey,
|
|
19221
19296
|
effort: reasoningEffort,
|
|
19222
|
-
promptCacheTtl
|
|
19297
|
+
promptCacheTtl,
|
|
19298
|
+
enableTodoTools: self.config.enableTodoTools === true
|
|
19223
19299
|
})
|
|
19224
19300
|
)
|
|
19225
19301
|
});
|
|
@@ -19337,7 +19413,9 @@ var ClaudeCodeLanguageModel = class {
|
|
|
19337
19413
|
self.config.ignoreAnthropicApiKey,
|
|
19338
19414
|
reasoningEffort,
|
|
19339
19415
|
promptCacheTtl,
|
|
19340
|
-
spawnConfigDir
|
|
19416
|
+
spawnConfigDir,
|
|
19417
|
+
// A compaction spawn runs no tools, so it never asks for them.
|
|
19418
|
+
self.config.enableTodoTools === true && !compactionMode
|
|
19341
19419
|
);
|
|
19342
19420
|
ap.mcpServers = spawnMcpServers;
|
|
19343
19421
|
state.proc = ap.proc;
|
|
@@ -21070,6 +21148,7 @@ function createClaudeCode(settings = {}) {
|
|
|
21070
21148
|
bridgeOpencodeSkills: settings.bridgeOpencodeSkills === true,
|
|
21071
21149
|
bridgeSkipNativeSkills: settings.bridgeSkipNativeSkills !== false,
|
|
21072
21150
|
turnStats: settings.turnStats === true,
|
|
21151
|
+
enableTodoTools: settings.enableTodoTools === true,
|
|
21073
21152
|
forkSessions: settings.forkSessions === true,
|
|
21074
21153
|
resumeAfterRestart: settings.resumeAfterRestart !== false,
|
|
21075
21154
|
resumeAcrossModelChanges: settings.resumeAcrossModelChanges !== false,
|