opencode-copilot-failover 0.1.0 → 0.1.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/README.md +75 -19
- package/dist/lib/failover-engine.d.ts +1 -0
- package/dist/lib/failover-engine.d.ts.map +1 -1
- package/dist/lib/failover-engine.js +36 -10
- package/dist/lib/failover-engine.js.map +1 -1
- package/dist/lib/model-mapper.d.ts +3 -6
- package/dist/lib/model-mapper.d.ts.map +1 -1
- package/dist/lib/model-mapper.js +24 -15
- package/dist/lib/model-mapper.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
# opencode-copilot-failover
|
|
2
2
|
|
|
3
|
-
Automatic provider failover plugin for opencode
|
|
3
|
+
Automatic provider failover plugin for opencode. It switches a failed request to GitHub Copilot while preserving the original agent, tools, system prompt, and model intent.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What it does
|
|
6
6
|
|
|
7
|
-
1. Listens for `session.error`
|
|
8
|
-
2. Detects retryable
|
|
9
|
-
3.
|
|
10
|
-
4. Re-prompts the session
|
|
11
|
-
5. Shows a toast
|
|
7
|
+
1. Listens for `session.error` after opencode retries are exhausted.
|
|
8
|
+
2. Detects retryable provider failures (for example: `429`, `500`, `502`, `503`, `529`, timeout/capacity style errors).
|
|
9
|
+
3. Resolves the best GitHub Copilot model (direct map first, then fallback chain).
|
|
10
|
+
4. Re-prompts the same session through `github-copilot`.
|
|
11
|
+
5. Shows a TUI toast describing the provider/model switch.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- OpenCode installed and working.
|
|
16
|
+
- `github-copilot` provider authenticated in OpenCode.
|
|
17
|
+
- At least one non-copilot provider configured (for normal primary execution).
|
|
12
18
|
|
|
13
19
|
## Installation
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
No separate `npm install` command is required. OpenCode installs plugins automatically from the `plugin` array in your config.
|
|
22
|
+
|
|
23
|
+
### Recommended (pin version)
|
|
24
|
+
|
|
25
|
+
Use a pinned plugin version for predictable upgrades:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"plugin": ["opencode-copilot-failover@0.1.1"]
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Use latest
|
|
34
|
+
|
|
35
|
+
If you prefer tracking latest:
|
|
16
36
|
|
|
17
37
|
```json
|
|
18
38
|
{
|
|
@@ -20,14 +40,38 @@ Add to your `opencode.json`:
|
|
|
20
40
|
}
|
|
21
41
|
```
|
|
22
42
|
|
|
23
|
-
|
|
43
|
+
### With other plugins
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"plugin": ["oh-my-opencode@latest", "opencode-openai-codex-auth", "opencode-copilot-failover@0.1.1"]
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Config file locations
|
|
52
|
+
|
|
53
|
+
- Global config: `~/.config/opencode/opencode.json`
|
|
54
|
+
- Project config: `<project>/.opencode.json`
|
|
55
|
+
|
|
56
|
+
Restart OpenCode after editing config so it installs/loads the plugin.
|
|
57
|
+
|
|
58
|
+
## Local development install
|
|
59
|
+
|
|
60
|
+
To test local changes without publishing:
|
|
24
61
|
|
|
25
62
|
```json
|
|
26
63
|
{
|
|
27
|
-
"plugin": ["
|
|
64
|
+
"plugin": ["/absolute/path/to/opencode-copilot-failover"]
|
|
28
65
|
}
|
|
29
66
|
```
|
|
30
67
|
|
|
68
|
+
## Verify it is working
|
|
69
|
+
|
|
70
|
+
1. Start a session on a non-copilot model (for example `anthropic/...` or `openai/...`).
|
|
71
|
+
2. Trigger a retryable provider failure (rate-limit/server error scenario).
|
|
72
|
+
3. Confirm a toast appears indicating switch to `github-copilot/<model>`.
|
|
73
|
+
4. Confirm the request continues in the same session.
|
|
74
|
+
|
|
31
75
|
## Supported Models
|
|
32
76
|
|
|
33
77
|
| Source Model | Copilot Model |
|
|
@@ -48,18 +92,30 @@ Or alongside other plugins:
|
|
|
48
92
|
| `gpt-5` | `gpt-5` |
|
|
49
93
|
| `gpt-5-mini` | `gpt-5-mini` |
|
|
50
94
|
| `gemini-2.5-pro` | `gemini-2.5-pro` |
|
|
51
|
-
| `gemini-3-flash` | `gemini-3-flash` |
|
|
52
|
-
| `gemini-3-pro` | `gemini-3-pro` |
|
|
95
|
+
| `gemini-3-flash` | `gemini-3-flash-preview` |
|
|
96
|
+
| `gemini-3-pro` | `gemini-3-pro-preview` |
|
|
53
97
|
|
|
54
98
|
## Behavior
|
|
55
99
|
|
|
56
|
-
- **Zero
|
|
57
|
-
- **Per-request failover
|
|
58
|
-
- **
|
|
59
|
-
- **
|
|
100
|
+
- **Zero config runtime**: no extra setup beyond plugin entry.
|
|
101
|
+
- **Per-request failover**: primary provider always gets first attempt.
|
|
102
|
+
- **No infinite loops**: it does not re-failover if already on copilot.
|
|
103
|
+
- **Deduplicated retries**: same failed parent message is only failovered once.
|
|
104
|
+
- **Ordered fallback**: enforced prefix is `claude-opus-4.6 -> gpt-5.3-codex -> claude-opus-4.5`.
|
|
105
|
+
- **Free model normalization**: source model IDs ending in `-free` are normalized first (for example `kimi-k2.5-free` -> `kimi-k2.5`) before fallback chain resolution.
|
|
106
|
+
|
|
107
|
+
## Strict benchmark-ranked fallback (1 month freshness)
|
|
108
|
+
|
|
109
|
+
This plugin uses a strict fallback list derived from Terminal-Bench 2.0 leaderboard data with freshness window `<= 1 month` (snapshot date: `2026-02-11`, cutoff: `2026-01-11`) and filtered to models that are relevant to current GitHub Copilot routing:
|
|
110
|
+
|
|
111
|
+
1. `claude-opus-4.6` (enforced)
|
|
112
|
+
2. `gpt-5.3-codex` (enforced)
|
|
113
|
+
3. `claude-opus-4.5` (enforced)
|
|
114
|
+
4. `gemini-3-pro-preview` (fresh benchmark-backed tail)
|
|
115
|
+
5. `gpt-5.2` (fresh benchmark-backed tail)
|
|
60
116
|
|
|
61
117
|
## Limitations
|
|
62
118
|
|
|
63
|
-
- GitHub Copilot must be authenticated in
|
|
64
|
-
- Not all models
|
|
65
|
-
- If
|
|
119
|
+
- GitHub Copilot must be authenticated in OpenCode.
|
|
120
|
+
- Not all source models exist on Copilot (fallback chain is used when possible).
|
|
121
|
+
- If Copilot also fails, no further failover provider is attempted.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failover-engine.d.ts","sourceRoot":"","sources":["../../lib/failover-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,
|
|
1
|
+
{"version":3,"file":"failover-engine.d.ts","sourceRoot":"","sources":["../../lib/failover-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EASjB,cAAc,EACd,MAAM,kBAAkB,CAAC;AAmB1B;;;GAGG;AACH,qBAAa,qBAAqB;IAIrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,mBAAmB,CAA4B;gBAE1B,MAAM,EAAE,cAAc;IAEnD;;;OAGG;YACW,qBAAqB;IAuB7B,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;YAYnD,YAAY;YA6FZ,iBAAiB;YAajB,SAAS;IAgCvB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA6C3B,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,WAAW;CAQnB"}
|
|
@@ -99,18 +99,20 @@ export class CopilotFailoverEngine {
|
|
|
99
99
|
if (inputParts.length === 0)
|
|
100
100
|
return;
|
|
101
101
|
const userInfo = userEntry.info;
|
|
102
|
+
const failoverAgent = this.readOptionalStringField(failedAssistant, "agent") || userInfo.agent;
|
|
103
|
+
const promptBody = {
|
|
104
|
+
parts: inputParts,
|
|
105
|
+
model: {
|
|
106
|
+
providerID: COPILOT_PROVIDER_ID,
|
|
107
|
+
modelID: copilotModelID,
|
|
108
|
+
},
|
|
109
|
+
agent: failoverAgent,
|
|
110
|
+
system: userInfo.system,
|
|
111
|
+
tools: userInfo.tools,
|
|
112
|
+
};
|
|
102
113
|
await this.client.session.promptAsync({
|
|
103
114
|
path: { id: sessionID },
|
|
104
|
-
body:
|
|
105
|
-
parts: inputParts,
|
|
106
|
-
model: {
|
|
107
|
-
providerID: COPILOT_PROVIDER_ID,
|
|
108
|
-
modelID: copilotModelID,
|
|
109
|
-
},
|
|
110
|
-
agent: userInfo.agent,
|
|
111
|
-
system: userInfo.system,
|
|
112
|
-
tools: userInfo.tools,
|
|
113
|
-
},
|
|
115
|
+
body: promptBody,
|
|
114
116
|
});
|
|
115
117
|
await this.emitFailoverToast(originalProvider, originalModel, copilotModelID, trigger.reason);
|
|
116
118
|
this.recordDedup(sessionID, parentID);
|
|
@@ -169,6 +171,23 @@ export class CopilotFailoverEngine {
|
|
|
169
171
|
});
|
|
170
172
|
break;
|
|
171
173
|
}
|
|
174
|
+
case "agent": {
|
|
175
|
+
result.push({
|
|
176
|
+
type: "agent",
|
|
177
|
+
name: part.name,
|
|
178
|
+
...(part.source ? { source: part.source } : {}),
|
|
179
|
+
});
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "subtask": {
|
|
183
|
+
result.push({
|
|
184
|
+
type: "subtask",
|
|
185
|
+
prompt: part.prompt,
|
|
186
|
+
description: part.description,
|
|
187
|
+
agent: part.agent,
|
|
188
|
+
});
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
172
191
|
case "file": {
|
|
173
192
|
result.push({
|
|
174
193
|
type: "file",
|
|
@@ -183,6 +202,13 @@ export class CopilotFailoverEngine {
|
|
|
183
202
|
}
|
|
184
203
|
return result;
|
|
185
204
|
}
|
|
205
|
+
readOptionalStringField(data, field) {
|
|
206
|
+
if (!data || typeof data !== "object")
|
|
207
|
+
return undefined;
|
|
208
|
+
const record = data;
|
|
209
|
+
const value = record[field];
|
|
210
|
+
return typeof value === "string" ? value : undefined;
|
|
211
|
+
}
|
|
186
212
|
isDuplicate(sessionID, parentID) {
|
|
187
213
|
const sessionSet = this.dedup.get(sessionID);
|
|
188
214
|
return sessionSet !== undefined && sessionSet.has(parentID);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failover-engine.js","sourceRoot":"","sources":["../../lib/failover-engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"failover-engine.js","sourceRoot":"","sources":["../../lib/failover-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,12 +18,9 @@ export declare const COPILOT_MODEL_MAP: Record<string, string>;
|
|
|
18
18
|
* Fallback chain — ordered list of model IDs to try when the original
|
|
19
19
|
* model isn't available in copilot. Walked top-to-bottom, first match wins.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
* 1.
|
|
23
|
-
* 2.
|
|
24
|
-
* 3. claude-sonnet (latest)
|
|
25
|
-
* 4. kimi-2.5
|
|
26
|
-
* 5. any remaining
|
|
21
|
+
* Tier order for coding fallback:
|
|
22
|
+
* 1. enforced prefix: opus-4.6 -> gpt-5.3-codex -> opus-4.5
|
|
23
|
+
* 2. remaining models ranked by fresh benchmark evidence (<= 1 month)
|
|
27
24
|
*/
|
|
28
25
|
export declare const FALLBACK_CHAIN: readonly string[];
|
|
29
26
|
export declare function parseModelString(fullModelID: string): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-mapper.d.ts","sourceRoot":"","sources":["../../lib/model-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"model-mapper.d.ts","sourceRoot":"","sources":["../../lib/model-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqCpD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAM3C,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CAChB,CASA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAehE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,GAC1C,MAAM,GAAG,IAAI,CAuCf;AAgBD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEhE"}
|
package/dist/lib/model-mapper.js
CHANGED
|
@@ -28,6 +28,7 @@ export const COPILOT_MODEL_MAP = {
|
|
|
28
28
|
"claude-haiku-4-5": "claude-haiku-4.5",
|
|
29
29
|
"claude-haiku-4.5": "claude-haiku-4.5",
|
|
30
30
|
// OpenAI
|
|
31
|
+
"gpt-5.3-codex": "gpt-5.3-codex",
|
|
31
32
|
"gpt-5.2-codex": "gpt-5.2-codex",
|
|
32
33
|
"gpt-5.2": "gpt-5.2",
|
|
33
34
|
"gpt-5.1-codex-max": "gpt-5.1-codex-max",
|
|
@@ -51,26 +52,16 @@ export const COPILOT_MODEL_MAP = {
|
|
|
51
52
|
* Fallback chain — ordered list of model IDs to try when the original
|
|
52
53
|
* model isn't available in copilot. Walked top-to-bottom, first match wins.
|
|
53
54
|
*
|
|
54
|
-
*
|
|
55
|
-
* 1.
|
|
56
|
-
* 2.
|
|
57
|
-
* 3. claude-sonnet (latest)
|
|
58
|
-
* 4. kimi-2.5
|
|
59
|
-
* 5. any remaining
|
|
55
|
+
* Tier order for coding fallback:
|
|
56
|
+
* 1. enforced prefix: opus-4.6 -> gpt-5.3-codex -> opus-4.5
|
|
57
|
+
* 2. remaining models ranked by fresh benchmark evidence (<= 1 month)
|
|
60
58
|
*/
|
|
61
59
|
export const FALLBACK_CHAIN = [
|
|
62
60
|
"claude-opus-4.6",
|
|
63
|
-
"claude-opus-4.5",
|
|
64
61
|
"gpt-5.3-codex",
|
|
65
|
-
"
|
|
66
|
-
"claude-sonnet-4.5",
|
|
67
|
-
"kimi-2.5",
|
|
68
|
-
"gpt-5.2",
|
|
69
|
-
"gpt-5-mini",
|
|
62
|
+
"claude-opus-4.5",
|
|
70
63
|
"gemini-3-pro-preview",
|
|
71
|
-
"
|
|
72
|
-
"grok-code-fast-1",
|
|
73
|
-
"claude-haiku-4.5",
|
|
64
|
+
"gpt-5.2",
|
|
74
65
|
];
|
|
75
66
|
export function parseModelString(fullModelID) {
|
|
76
67
|
const slashIndex = fullModelID.indexOf("/");
|
|
@@ -114,6 +105,18 @@ export function resolveWithFallback(modelID, availableModels) {
|
|
|
114
105
|
if (isAvailable(bare, availableModels)) {
|
|
115
106
|
return bare;
|
|
116
107
|
}
|
|
108
|
+
const freeNormalized = normalizeFreeModelID(bare);
|
|
109
|
+
if (freeNormalized && isAvailable(freeNormalized, availableModels)) {
|
|
110
|
+
return freeNormalized;
|
|
111
|
+
}
|
|
112
|
+
if (freeNormalized) {
|
|
113
|
+
const mappedFreeNormalized = mapModelToCopilot(freeNormalized);
|
|
114
|
+
if (mappedFreeNormalized &&
|
|
115
|
+
mappedFreeNormalized !== freeNormalized &&
|
|
116
|
+
isAvailable(mappedFreeNormalized, availableModels)) {
|
|
117
|
+
return mappedFreeNormalized;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
117
120
|
// 2. Try the mapped name (e.g. claude-opus-4-6 -> claude-opus-4.6)
|
|
118
121
|
const mappedMatch = mapModelToCopilot(modelID);
|
|
119
122
|
if (mappedMatch && mappedMatch !== bare && isAvailable(mappedMatch, availableModels)) {
|
|
@@ -129,6 +132,12 @@ export function resolveWithFallback(modelID, availableModels) {
|
|
|
129
132
|
}
|
|
130
133
|
return null;
|
|
131
134
|
}
|
|
135
|
+
function normalizeFreeModelID(modelID) {
|
|
136
|
+
if (!modelID.endsWith("-free"))
|
|
137
|
+
return null;
|
|
138
|
+
const normalized = modelID.slice(0, -"-free".length);
|
|
139
|
+
return normalized.length > 0 ? normalized : null;
|
|
140
|
+
}
|
|
132
141
|
function isAvailable(modelID, availableModels) {
|
|
133
142
|
if (!availableModels)
|
|
134
143
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-mapper.js","sourceRoot":"","sources":["../../lib/model-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACxD,YAAY;IACZ,iBAAiB,EAAE,iBAAiB;IACpC,iBAAiB,EAAE,iBAAiB;IACpC,iBAAiB,EAAE,iBAAiB;IACpC,iBAAiB,EAAE,iBAAiB;IACpC,iBAAiB,EAAE,gBAAgB;IACnC,iBAAiB,EAAE,gBAAgB;IACnC,gBAAgB,EAAE,gBAAgB;IAClC,mBAAmB,EAAE,mBAAmB;IACxC,mBAAmB,EAAE,mBAAmB;IACxC,iBAAiB,EAAE,iBAAiB;IACpC,kBAAkB,EAAE,kBAAkB;IACtC,kBAAkB,EAAE,kBAAkB;IAEtC,SAAS;IACT,eAAe,EAAE,eAAe;IAChC,SAAS,EAAE,SAAS;IACpB,mBAAmB,EAAE,mBAAmB;IACxC,eAAe,EAAE,eAAe;IAChC,oBAAoB,EAAE,oBAAoB;IAC1C,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE,YAAY;IAC1B,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,QAAQ;IAElB,SAAS;IACT,gBAAgB,EAAE,gBAAgB;IAClC,gBAAgB,EAAE,wBAAwB;IAC1C,wBAAwB,EAAE,wBAAwB;IAClD,cAAc,EAAE,sBAAsB;IACtC,sBAAsB,EAAE,sBAAsB;IAE9C,MAAM;IACN,kBAAkB,EAAE,kBAAkB;CACtC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"model-mapper.js","sourceRoot":"","sources":["../../lib/model-mapper.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-copilot-failover",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Auto-failover from anthropic/openai providers to github-copilot when primary providers return retryable errors",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|