opencode-bedrock-1m 1.0.0

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 ADDED
@@ -0,0 +1,70 @@
1
+ # opencode-bedrock-1m
2
+
3
+ OpenCode plugin that unlocks the **1M token context window** for Claude models on AWS Bedrock, with quota error reporting.
4
+
5
+ ## Problem
6
+
7
+ Claude Opus 4.6 and Sonnet 4.6/4.5 support a 1M token context window, but AWS Bedrock requires the beta header `context-1m-2025-08-07` to unlock it. Without this header, the API enforces a hard **200K input token limit**.
8
+
9
+ OpenCode currently sends this header only for `claude-sonnet-*` models. This plugin fixes the issue for all supported models and also surfaces Bedrock quota errors directly in the UI.
10
+
11
+ Tracked in: [#12338](https://github.com/anomalyco/opencode/issues/12338), [#12452](https://github.com/anomalyco/opencode/issues/12452), [#12507](https://github.com/anomalyco/opencode/issues/12507)
12
+
13
+ ## Features
14
+
15
+ - Injects `anthropic-beta: context-1m-2025-08-07` for all supported Claude models on Bedrock
16
+ - Works across all inference profiles: `eu.*`, `us.*`, `global.*`
17
+ - Shows a toast notification when Bedrock quota errors occur (`Too many tokens per day`, `Too many requests`)
18
+
19
+ ## Supported models
20
+
21
+ - `claude-opus-4-6` (all variants)
22
+ - `claude-sonnet-4-6` (all variants)
23
+ - `claude-sonnet-4-5` (all variants)
24
+ - `claude-sonnet-4` / `claude-sonnet-4-20250514`
25
+
26
+ ## Installation
27
+
28
+ Add to your `opencode.json`:
29
+
30
+ ```json
31
+ {
32
+ "plugin": ["opencode-bedrock-1m"]
33
+ }
34
+ ```
35
+
36
+ ## Context limits override (recommended)
37
+
38
+ Since OpenCode may still display the wrong context limit in the UI, add these overrides to your `opencode.json`:
39
+
40
+ ```json
41
+ {
42
+ "provider": {
43
+ "amazon-bedrock": {
44
+ "models": {
45
+ "eu.anthropic.claude-sonnet-4-6": { "limit": { "context": 1000000, "output": 64000 } },
46
+ "global.anthropic.claude-sonnet-4-6": { "limit": { "context": 1000000, "output": 64000 } },
47
+ "us.anthropic.claude-sonnet-4-6": { "limit": { "context": 1000000, "output": 64000 } },
48
+ "eu.anthropic.claude-sonnet-4-5-20250929-v1:0": { "limit": { "context": 1000000, "output": 64000 } },
49
+ "global.anthropic.claude-sonnet-4-5-20250929-v1:0": { "limit": { "context": 1000000, "output": 64000 } },
50
+ "us.anthropic.claude-sonnet-4-5-20250929-v1:0": { "limit": { "context": 1000000, "output": 64000 } }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## AWS Bedrock quota notes
58
+
59
+ Enabling the 1M context header moves your requests to the **1M Context Length** quota bucket:
60
+
61
+ | Model | Standard RPM | 1M Context RPM | Standard tokens/day | 1M Context tokens/day |
62
+ |-------|-------------|----------------|--------------------|-----------------------|
63
+ | Opus 4.6 | 25 | 1 | 1,296,000 | 27,000,000 |
64
+ | Sonnet 4.6 | 50 | 1 | 5,400,000 | 6,480,000 |
65
+
66
+ The 1M context profile has a lower RPM (1 req/min) but a much higher daily token quota for Opus. For Sonnet, the daily advantage is marginal — consider only enabling 1M context for sessions that actually need it.
67
+
68
+ ## License
69
+
70
+ MIT
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "opencode-bedrock-1m",
3
+ "version": "1.0.0",
4
+ "description": "OpenCode plugin that enables 1M context window for Claude models on AWS Bedrock via the context-1m-2025-08-07 beta header, with quota error reporting.",
5
+ "main": "src/index.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "lint": "tsc --noEmit"
9
+ },
10
+ "keywords": [
11
+ "opencode",
12
+ "opencode-plugin",
13
+ "aws",
14
+ "bedrock",
15
+ "claude",
16
+ "anthropic",
17
+ "1m-context"
18
+ ],
19
+ "author": "JAM-Development",
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/JAM-Development/opencode-bedrock-1m"
24
+ },
25
+ "peerDependencies": {
26
+ "@opencode-ai/plugin": ">=1.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "@opencode-ai/plugin": "^1.2.10",
30
+ "typescript": "^5.0.0"
31
+ }
32
+ }
package/src/index.ts ADDED
@@ -0,0 +1,89 @@
1
+ import type { Plugin } from "@opencode-ai/plugin"
2
+
3
+ const CONTEXT_1M_BETA = "context-1m-2025-08-07"
4
+
5
+ /**
6
+ * Models that support the 1M context window beta header.
7
+ * Matched against the model ID using substring search.
8
+ */
9
+ const DEFAULT_SUPPORTED_MODELS = [
10
+ "opus-4-6",
11
+ "opus-4.6",
12
+ "sonnet-4-6",
13
+ "sonnet-4.6",
14
+ "sonnet-4-5",
15
+ "sonnet-4.5",
16
+ "sonnet-4-20250514",
17
+ ]
18
+
19
+ /**
20
+ * User-facing messages for quota errors.
21
+ */
22
+ const QUOTA_MESSAGES: Record<string, string> = {
23
+ "Too many tokens per day":
24
+ "Bedrock daily token quota exhausted for this model. Switch to another region (EU/Global/US) or wait for the reset at midnight UTC.",
25
+ "Too many requests":
26
+ "Bedrock RPM quota exceeded. You are on the 1M context profile (1 RPM). Wait a moment before retrying.",
27
+ }
28
+
29
+ export const BedrockContextPlugin: Plugin = async ({ client }) => {
30
+ return {
31
+ /**
32
+ * Inject the 1M context beta header for supported Claude models on Bedrock.
33
+ */
34
+ "chat.params": async (input, output) => {
35
+ if (input.model.providerID !== "amazon-bedrock") return
36
+ if (!input.model.id.includes("claude")) return
37
+ if (!DEFAULT_SUPPORTED_MODELS.some(m => input.model.id.includes(m))) return
38
+
39
+ const existing = output.options.anthropicBeta ?? []
40
+ if (existing.includes(CONTEXT_1M_BETA)) return
41
+
42
+ output.options.anthropicBeta = [...existing, CONTEXT_1M_BETA]
43
+
44
+ await client.app.log({
45
+ body: {
46
+ service: "opencode-bedrock-1m",
47
+ level: "info",
48
+ message: `1M context beta header injected for model: ${input.model.id}`,
49
+ },
50
+ })
51
+ },
52
+
53
+ /**
54
+ * Intercept session errors and surface Bedrock quota errors as toasts.
55
+ */
56
+ "session.error": async ({ error, sessionID }) => {
57
+ if (!error) return
58
+
59
+ const message = typeof error === "string" ? error : (error as Error).message ?? ""
60
+
61
+ for (const [pattern, userMessage] of Object.entries(QUOTA_MESSAGES)) {
62
+ if (message.includes(pattern)) {
63
+ await client.app.log({
64
+ body: {
65
+ service: "opencode-bedrock-1m",
66
+ level: "warn",
67
+ message: `Bedrock quota error on session ${sessionID}: ${message}`,
68
+ },
69
+ })
70
+
71
+ // Surface to the user via toast
72
+ await client.event.publish({
73
+ body: {
74
+ type: "tui.toast.show",
75
+ properties: {
76
+ message: `Bedrock quota: ${userMessage}`,
77
+ level: "error",
78
+ },
79
+ },
80
+ })
81
+
82
+ break
83
+ }
84
+ }
85
+ },
86
+ }
87
+ }
88
+
89
+ export const plugin = BedrockContextPlugin
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "skipLibCheck": true
9
+ },
10
+ "include": ["src"]
11
+ }