@khalilgharbaoui/opencode-claude-code-plugin 0.4.2 → 0.4.4
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 +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +64 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,6 +171,7 @@ The account model IDs are internally suffixed, for example `claude-sonnet-4-6@wo
|
|
|
171
171
|
| `mcpConfig` | string \| string[] | – | Extra `--mcp-config` paths/JSON passed alongside the bridged config. |
|
|
172
172
|
| `strictMcpConfig` | boolean | `false` | Pass `--strict-mcp-config` so Claude loads **only** the configured servers and ignores `~/.claude/settings.json`. |
|
|
173
173
|
| `webSearch` | `"claude"` \| `"disabled"` \| `<tool>` | `"claude"` | Routing for Claude's built-in `WebSearch`. See [WebSearch routing](#websearch-routing). |
|
|
174
|
+
| `multiStepContinuation` | boolean | `true` | Append a system-prompt hint nudging Claude to chain tool calls within one turn instead of pausing between subtasks. Each opencode turn boundary requires the user to manually press "continue", so for multi-step tasks this reduces friction. Set `false` to disable. |
|
|
174
175
|
|
|
175
176
|
### Overriding model metadata
|
|
176
177
|
|
package/dist/index.d.ts
CHANGED
|
@@ -115,6 +115,7 @@ interface ClaudeCodeConfig {
|
|
|
115
115
|
webSearch?: WebSearchRouting;
|
|
116
116
|
hotReloadMcp?: boolean;
|
|
117
117
|
proxyOpencodeMcpTools?: boolean;
|
|
118
|
+
multiStepContinuation?: boolean;
|
|
118
119
|
}
|
|
119
120
|
type WebSearchRouting = "claude" | "disabled" | (string & {});
|
|
120
121
|
interface ClaudeCodeProviderSettings {
|
|
@@ -207,6 +208,17 @@ interface ClaudeCodeProviderSettings {
|
|
|
207
208
|
* an opencode round-trip).
|
|
208
209
|
*/
|
|
209
210
|
proxyOpencodeMcpTools?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Append a short system-prompt hint that nudges Claude to chain
|
|
213
|
+
* multiple tool calls within a single turn instead of pausing for user
|
|
214
|
+
* confirmation between subtasks. Each turn boundary in opencode
|
|
215
|
+
* requires the user to manually press "continue" to resume, so for
|
|
216
|
+
* multi-step tasks this option reduces friction. Defaults to `true`.
|
|
217
|
+
*
|
|
218
|
+
* Set to `false` if you prefer the un-nudged model behavior (Claude
|
|
219
|
+
* decides when to end the turn entirely on its own).
|
|
220
|
+
*/
|
|
221
|
+
multiStepContinuation?: boolean;
|
|
210
222
|
}
|
|
211
223
|
type PermissionMode = "acceptEdits" | "auto" | "bypassPermissions" | "default" | "dontAsk" | "plan";
|
|
212
224
|
type ControlRequestBehavior = "allow" | "deny";
|
package/dist/index.js
CHANGED
|
@@ -577,6 +577,17 @@ function dotOpencodeDirs(cwd, worktree) {
|
|
|
577
577
|
if (envDir && dirExists(envDir)) push(envDir);
|
|
578
578
|
return dirs;
|
|
579
579
|
}
|
|
580
|
+
function substituteEnvPlaceholders(source) {
|
|
581
|
+
const out = {};
|
|
582
|
+
for (const [k, v] of Object.entries(source)) {
|
|
583
|
+
if (typeof v !== "string") continue;
|
|
584
|
+
out[k] = v.replace(/\{env:([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => {
|
|
585
|
+
const resolved = process.env[name];
|
|
586
|
+
return typeof resolved === "string" ? resolved : "";
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
return out;
|
|
590
|
+
}
|
|
580
591
|
function translateServer(name, spec) {
|
|
581
592
|
if (spec.enabled === false) return null;
|
|
582
593
|
const type = spec.type;
|
|
@@ -592,7 +603,9 @@ function translateServer(name, spec) {
|
|
|
592
603
|
};
|
|
593
604
|
if (cmd.length > 1) out.args = cmd.slice(1).map((s) => String(s));
|
|
594
605
|
if (spec.environment && typeof spec.environment === "object") {
|
|
595
|
-
out.env =
|
|
606
|
+
out.env = substituteEnvPlaceholders(
|
|
607
|
+
spec.environment
|
|
608
|
+
);
|
|
596
609
|
}
|
|
597
610
|
return out;
|
|
598
611
|
}
|
|
@@ -606,7 +619,9 @@ function translateServer(name, spec) {
|
|
|
606
619
|
url: spec.url
|
|
607
620
|
};
|
|
608
621
|
if (spec.headers && typeof spec.headers === "object") {
|
|
609
|
-
out.headers =
|
|
622
|
+
out.headers = substituteEnvPlaceholders(
|
|
623
|
+
spec.headers
|
|
624
|
+
);
|
|
610
625
|
}
|
|
611
626
|
return out;
|
|
612
627
|
}
|
|
@@ -1486,13 +1501,22 @@ function nearestWorkspaceAgentsPrompt(cwd) {
|
|
|
1486
1501
|
dir = parent;
|
|
1487
1502
|
}
|
|
1488
1503
|
}
|
|
1489
|
-
|
|
1504
|
+
var MULTI_STEP_TASK_HINT = `## Continuing through multi-step tasks
|
|
1505
|
+
|
|
1506
|
+
opencode requires the user to press "continue" after each turn ends. When a
|
|
1507
|
+
task has multiple steps, do them all in one turn \u2014 chain tool calls rather
|
|
1508
|
+
than pausing for user confirmation between subtasks. End the turn only
|
|
1509
|
+
when the task is done, you need clarification on intent, or you hit a real
|
|
1510
|
+
blocker. The user can interrupt or abort at any time; turn endings should
|
|
1511
|
+
mark meaningful checkpoints, not every completed substep.`;
|
|
1512
|
+
function buildAppendedSystemPrompt(cwd, includeMultiStepHint = true) {
|
|
1490
1513
|
const parts = [];
|
|
1491
1514
|
const configRoot = process.env.XDG_CONFIG_HOME ?? join4(homedir2(), ".config");
|
|
1492
1515
|
const globalAgents = readPromptFileIfPresent(join4(configRoot, "opencode", "AGENTS.md"));
|
|
1493
1516
|
const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd);
|
|
1494
1517
|
if (globalAgents) parts.push(globalAgents);
|
|
1495
1518
|
if (workspaceAgents && workspaceAgents !== globalAgents) parts.push(workspaceAgents);
|
|
1519
|
+
if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT);
|
|
1496
1520
|
const content = parts.join("\n\n");
|
|
1497
1521
|
if (!content) return void 0;
|
|
1498
1522
|
const path5 = join4(tmpdir2(), `opencode-cc-sys-${randomUUID2()}.md`);
|
|
@@ -1966,7 +1990,10 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1966
1990
|
reasoningEffort
|
|
1967
1991
|
);
|
|
1968
1992
|
const runtimeStatus = await getRuntimeMcpStatus();
|
|
1969
|
-
const systemPromptFile = buildAppendedSystemPrompt(
|
|
1993
|
+
const systemPromptFile = buildAppendedSystemPrompt(
|
|
1994
|
+
cwd,
|
|
1995
|
+
this.config.multiStepContinuation !== false
|
|
1996
|
+
);
|
|
1970
1997
|
const cliArgs = buildCliArgs({
|
|
1971
1998
|
sessionKey: sk,
|
|
1972
1999
|
skipPermissions: this.config.skipPermissions !== false,
|
|
@@ -2336,7 +2363,10 @@ ${plan}
|
|
|
2336
2363
|
runtimeStatus,
|
|
2337
2364
|
excludeServers
|
|
2338
2365
|
);
|
|
2339
|
-
const systemPromptFile = activeProcess ? void 0 : buildAppendedSystemPrompt(
|
|
2366
|
+
const systemPromptFile = activeProcess ? void 0 : buildAppendedSystemPrompt(
|
|
2367
|
+
cwd,
|
|
2368
|
+
self.config.multiStepContinuation !== false
|
|
2369
|
+
);
|
|
2340
2370
|
const cliArgs = buildCliArgs({
|
|
2341
2371
|
sessionKey: sk,
|
|
2342
2372
|
skipPermissions,
|
|
@@ -2857,6 +2887,33 @@ ${plan}
|
|
|
2857
2887
|
});
|
|
2858
2888
|
turnCompleted = true;
|
|
2859
2889
|
endTextBlock();
|
|
2890
|
+
if (drainBuffer.length > 0) {
|
|
2891
|
+
log.info(
|
|
2892
|
+
"draining pending proxy calls at turn-result boundary",
|
|
2893
|
+
{
|
|
2894
|
+
sessionKey: sk,
|
|
2895
|
+
count: drainBuffer.length
|
|
2896
|
+
}
|
|
2897
|
+
);
|
|
2898
|
+
drainNow();
|
|
2899
|
+
return;
|
|
2900
|
+
}
|
|
2901
|
+
const orphanPending = getPendingProxyCalls(sk);
|
|
2902
|
+
if (orphanPending.length > 0) {
|
|
2903
|
+
log.warn(
|
|
2904
|
+
"rejecting orphan pending proxy calls at turn-result boundary",
|
|
2905
|
+
{
|
|
2906
|
+
sessionKey: sk,
|
|
2907
|
+
count: orphanPending.length
|
|
2908
|
+
}
|
|
2909
|
+
);
|
|
2910
|
+
rejectAllPendingProxyCallsForSession(
|
|
2911
|
+
sk,
|
|
2912
|
+
new Error(
|
|
2913
|
+
"Claude CLI emitted result with pending proxy calls not in drain buffer"
|
|
2914
|
+
)
|
|
2915
|
+
);
|
|
2916
|
+
}
|
|
2860
2917
|
for (const [idx, reasoningId] of reasoningIds) {
|
|
2861
2918
|
if (reasoningStarted.get(idx)) {
|
|
2862
2919
|
controller.enqueue({
|
|
@@ -3498,7 +3555,8 @@ function createClaudeCode(settings = {}) {
|
|
|
3498
3555
|
proxyTools,
|
|
3499
3556
|
webSearch: settings.webSearch,
|
|
3500
3557
|
hotReloadMcp: settings.hotReloadMcp ?? true,
|
|
3501
|
-
proxyOpencodeMcpTools: settings.proxyOpencodeMcpTools ?? true
|
|
3558
|
+
proxyOpencodeMcpTools: settings.proxyOpencodeMcpTools ?? true,
|
|
3559
|
+
multiStepContinuation: settings.multiStepContinuation ?? true
|
|
3502
3560
|
});
|
|
3503
3561
|
};
|
|
3504
3562
|
const provider = function(modelId) {
|