@khalilgharbaoui/opencode-claude-code-plugin 0.8.0 → 0.8.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/README.md +29 -1
- package/dist/index.js +44 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,34 @@ Variants set the underlying reasoning effort. They're regular opencode model var
|
|
|
92
92
|
|
|
93
93
|
---
|
|
94
94
|
|
|
95
|
+
## Billing change: June 15, 2026 (Agent SDK credit)
|
|
96
|
+
|
|
97
|
+
This plugin drives Claude Code headlessly (`claude --print`), which Anthropic bills as [`claude -p` / Agent SDK usage](https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan). Starting **June 15, 2026**, on subscription plans that usage no longer counts toward your normal plan limits — it draws from a separate monthly **Agent SDK credit**:
|
|
98
|
+
|
|
99
|
+
| Plan | Monthly credit |
|
|
100
|
+
|---|---|
|
|
101
|
+
| Pro | $20 |
|
|
102
|
+
| Max 5x | $100 |
|
|
103
|
+
| Max 20x | $200 |
|
|
104
|
+
| Team Standard | $20/seat |
|
|
105
|
+
| Team Premium | $100/seat |
|
|
106
|
+
| Enterprise (Standard seats) | none |
|
|
107
|
+
|
|
108
|
+
What this means for plugin users:
|
|
109
|
+
|
|
110
|
+
- **Claim the credit once.** It's a one-time opt-in via your Claude account (claim emails started going out June 8, 2026); after that it refreshes every billing cycle. Unused credit does not roll over.
|
|
111
|
+
- **When the credit runs out, plugin requests stop** until the next billing cycle — unless you enable usage credits in your Claude account, in which case overflow is billed at standard API rates.
|
|
112
|
+
- **The credit is denominated in dollars at standard API rates**, so the Price × column above maps directly to how fast each model drains it — Fable 5 / Mythos 5 burn it 10× faster than Haiku, 2× faster than Opus 4.8.
|
|
113
|
+
- **API-key auth is unaffected.** If your `claude` CLI authenticates with an Anthropic API key / Console billing instead of a subscription, nothing changes — pay-as-you-go as before.
|
|
114
|
+
- **Interactive Claude Code in your terminal is unaffected.** The change targets programmatic usage only: the Agent SDK, `claude -p`, Claude Code GitHub Actions, and third-party apps like this plugin.
|
|
115
|
+
|
|
116
|
+
Two related dates:
|
|
117
|
+
|
|
118
|
+
- **June 15, 2026** also retires the original Claude 4 model IDs `claude-sonnet-4-20250514` and `claude-opus-4-20250514` from the API. The plugin doesn't register either, but model IDs pass straight through to `claude --model` — if you've configured one of these as an override, migrate to `claude-sonnet-4-6` / `claude-opus-4-8` before then.
|
|
119
|
+
- **June 22, 2026** is the last day [Fable 5 is included at no extra cost](https://platform.claude.com/docs/en/about-claude/models/introducing-claude-fable-5-and-claude-mythos-5) on Pro, Max, Team, and seat-based Enterprise plans. From June 23, `claude-fable-5` requires usage credits (Anthropic says it aims to fold it back into plans once capacity allows). `claude-mythos-5` is unaffected — it's Glasswing access-gated either way.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
95
123
|
## Configuration
|
|
96
124
|
|
|
97
125
|
The minimum config is just the `plugin` entry above. Everything below is optional override that goes in a `provider.claude-code` block.
|
|
@@ -251,7 +279,7 @@ Claude Code ships a built-in `WebSearch` tool. The `webSearch` option controls w
|
|
|
251
279
|
|
|
252
280
|
| `webSearch` value | Behavior | When to use |
|
|
253
281
|
|---|---|---|
|
|
254
|
-
| `"claude"` (default) | Claude CLI runs WebSearch internally via Anthropic. Zero setup, no extra cost, no API key. | Most users. |
|
|
282
|
+
| `"claude"` (default) | Claude CLI runs WebSearch internally via Anthropic. Zero setup, no extra cost, no API key. The query is shown in the transcript as a `> Web search:` line (opencode has no `WebSearch` tool registry entry, so a raw tool row would render as `⚙ invalid`). | Most users. |
|
|
255
283
|
| `"<opencode-tool-name>"` (e.g. `"websearch_web_search_exa"`) | Forward to that opencode-side tool with `executed:false`. Requires the corresponding MCP server to be configured in opencode (e.g. [exa-mcp-server](https://github.com/exa-labs/exa-mcp-server)). | You want a specific search backend (Exa, Tavily, Brave) and have the MCP wired up in opencode. |
|
|
256
284
|
| `"disabled"` | `WebSearch` is added to `--disallowedTools` so the model can't call it. | Compliance/security scenarios where outbound search isn't allowed. |
|
|
257
285
|
|
package/dist/index.js
CHANGED
|
@@ -210,6 +210,12 @@ function clearLedger(sessionId) {
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
// src/tool-mapping.ts
|
|
213
|
+
function isWebSearchTool(name) {
|
|
214
|
+
return name === "WebSearch" || name === "web_search";
|
|
215
|
+
}
|
|
216
|
+
function isWebSearchHandledByCli(route) {
|
|
217
|
+
return !route || route === "claude" || route === "disabled";
|
|
218
|
+
}
|
|
213
219
|
function mapToolInput(name, input) {
|
|
214
220
|
if (!input) return input;
|
|
215
221
|
switch (name) {
|
|
@@ -326,7 +332,7 @@ function mapTool(name, input, opts) {
|
|
|
326
332
|
const mappedInput = mapToolInput(name, input);
|
|
327
333
|
return { name: "todowrite", input: mappedInput, executed: false };
|
|
328
334
|
}
|
|
329
|
-
if (name
|
|
335
|
+
if (isWebSearchTool(name)) {
|
|
330
336
|
const mappedInput = input?.query ? { query: input.query } : input;
|
|
331
337
|
const route = opts?.webSearch;
|
|
332
338
|
if (route && route !== "claude" && route !== "disabled") {
|
|
@@ -334,7 +340,7 @@ function mapTool(name, input, opts) {
|
|
|
334
340
|
return { name: route, input: mappedInput, executed: false };
|
|
335
341
|
}
|
|
336
342
|
log.debug("WebSearch executed by Claude CLI", { mappedInput });
|
|
337
|
-
return { name: "WebSearch", input: mappedInput, executed: true };
|
|
343
|
+
return { name: "WebSearch", input: mappedInput, executed: true, skip: true };
|
|
338
344
|
}
|
|
339
345
|
if (name === "TaskOutput") {
|
|
340
346
|
if (!input) return { name: "bash", executed: false };
|
|
@@ -3372,11 +3378,13 @@ ${plan}
|
|
|
3372
3378
|
}
|
|
3373
3379
|
if (block.type === "tool_use" && block.id && block.name) {
|
|
3374
3380
|
noteToolActivity();
|
|
3375
|
-
|
|
3381
|
+
const entry = {
|
|
3376
3382
|
id: block.id,
|
|
3377
3383
|
name: block.name,
|
|
3378
|
-
inputJson: ""
|
|
3379
|
-
|
|
3384
|
+
inputJson: "",
|
|
3385
|
+
started: false
|
|
3386
|
+
};
|
|
3387
|
+
toolCallMap.set(idx, entry);
|
|
3380
3388
|
if (block.name !== "AskUserQuestion" && block.name !== "ask_user_question" && block.name !== "ExitPlanMode" && !block.name.startsWith(PROXY_TOOL_PREFIX)) {
|
|
3381
3389
|
const { name: mappedName, skip, executed } = mapTool(
|
|
3382
3390
|
block.name,
|
|
@@ -3388,6 +3396,7 @@ ${plan}
|
|
|
3388
3396
|
}
|
|
3389
3397
|
);
|
|
3390
3398
|
if (!skip) {
|
|
3399
|
+
entry.started = true;
|
|
3391
3400
|
controller.enqueue({
|
|
3392
3401
|
type: "tool-input-start",
|
|
3393
3402
|
id: block.id,
|
|
@@ -3439,11 +3448,13 @@ ${plan}
|
|
|
3439
3448
|
const tc = toolCallMap.get(idx);
|
|
3440
3449
|
if (tc) {
|
|
3441
3450
|
tc.inputJson += delta.partial_json;
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3451
|
+
if (tc.started) {
|
|
3452
|
+
controller.enqueue({
|
|
3453
|
+
type: "tool-input-delta",
|
|
3454
|
+
id: tc.id,
|
|
3455
|
+
delta: delta.partial_json
|
|
3456
|
+
});
|
|
3457
|
+
}
|
|
3447
3458
|
}
|
|
3448
3459
|
}
|
|
3449
3460
|
if (!KNOWN_DELTA_TYPES.has(delta.type)) {
|
|
@@ -3495,6 +3506,17 @@ ${plan}
|
|
|
3495
3506
|
|
|
3496
3507
|
---
|
|
3497
3508
|
**Do you want to proceed with this plan?** (yes/no)
|
|
3509
|
+
`
|
|
3510
|
+
});
|
|
3511
|
+
endTextBlock();
|
|
3512
|
+
} else if (isWebSearchTool(tc.name) && isWebSearchHandledByCli(self.config.webSearch)) {
|
|
3513
|
+
const query = typeof parsedInput?.query === "string" ? parsedInput.query : JSON.stringify(parsedInput);
|
|
3514
|
+
const searchId = startTextBlock();
|
|
3515
|
+
controller.enqueue({
|
|
3516
|
+
type: "text-delta",
|
|
3517
|
+
id: searchId,
|
|
3518
|
+
delta: `
|
|
3519
|
+
> **Web search:** ${query}
|
|
3498
3520
|
`
|
|
3499
3521
|
});
|
|
3500
3522
|
endTextBlock();
|
|
@@ -3654,6 +3676,18 @@ ${plan}
|
|
|
3654
3676
|
|
|
3655
3677
|
---
|
|
3656
3678
|
**Do you want to proceed with this plan?** (yes/no)
|
|
3679
|
+
`
|
|
3680
|
+
});
|
|
3681
|
+
endTextBlock();
|
|
3682
|
+
} else if (isWebSearchTool(block.name) && isWebSearchHandledByCli(self.config.webSearch)) {
|
|
3683
|
+
toolCallsById.delete(block.id);
|
|
3684
|
+
const query = typeof parsedInput?.query === "string" ? parsedInput.query : JSON.stringify(parsedInput);
|
|
3685
|
+
const searchId = startTextBlock();
|
|
3686
|
+
controller.enqueue({
|
|
3687
|
+
type: "text-delta",
|
|
3688
|
+
id: searchId,
|
|
3689
|
+
delta: `
|
|
3690
|
+
> **Web search:** ${query}
|
|
3657
3691
|
`
|
|
3658
3692
|
});
|
|
3659
3693
|
endTextBlock();
|