opencode-resolve 0.1.10 → 0.1.12
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.ko.md +53 -6
- package/README.md +54 -7
- package/dist/agents.d.ts +2 -2
- package/dist/agents.js +16 -3
- package/dist/types.d.ts +1 -1
- package/opencode-resolve.example.json +3 -0
- package/opencode-resolve.reference.jsonc +20 -7
- package/package.json +1 -1
- package/scripts/install-local.mjs +1 -1
- package/scripts/postinstall.mjs +89 -88
package/README.ko.md
CHANGED
|
@@ -156,8 +156,8 @@ npm install -g opencode-resolve
|
|
|
156
156
|
|
|
157
157
|
1. `opencode-resolve`를 `~/.config/opencode/opencode.json`의 `plugin` 배열에 추가 (이미 없는 경우).
|
|
158
158
|
2. 파일이 존재하지 않는 경우, 현재 모델 프로바이더에 맞게 적응된 `~/.config/opencode/resolve.json`을 생성:
|
|
159
|
-
- **인터랙티브 터미널** → 항상 `mix` / `gpt` / `glm`을 묻고, `bronze` / `silver` / `gold` 3티어 모델을 고르게 합니다. `mix`에서는 전용 `
|
|
160
|
-
- **비대화형 설치** →
|
|
159
|
+
- **인터랙티브 터미널** → 항상 `mix` / `gpt` / `glm`을 묻고, `bronze` / `silver` / `gold` 3티어 모델을 고르게 합니다. `mix`에서는 전용 `gpt`, `glm` primary 에이전트를 켤지도 묻습니다.
|
|
160
|
+
- **비대화형 설치** → opencode.json에서 프로바이더를 자동 감지하여 모델 적응 프리셋을 작성합니다. `resolver`, `gpt`, `glm` primary 경로를 활성화합니다.
|
|
161
161
|
- **GLM/ZAI 모델 감지** → 비밀값 없는 로컬 ZAI MCP 부트스트랩은 계속 추가합니다.
|
|
162
162
|
|
|
163
163
|
기존 `resolve.json` 파일은 **동의 없이 덮어쓰지 않습니다**. 재설치 시 인터랙티브 환경이면 기존 파일을 업데이트할지, 백업 후 fresh setup을 다시 돌릴지 묻습니다. 비대화형 자동화에서는 `OPENCODE_RESOLVE_REINSTALL=fresh` 또는 `OPENCODE_RESOLVE_REINSTALL=update`를 설정하세요.
|
|
@@ -176,6 +176,30 @@ OPENCODE_RESOLVE_SKIP_POSTINSTALL=1 npm install -g opencode-resolve
|
|
|
176
176
|
opencode plugin opencode-resolve --global --force
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
+
그래도 OpenCode가 계속 예전 패키지를 로드하면, OpenCode 플러그인 캐시 항목만 지우고 다시 설치하세요. 이 절차는 `~/.config/opencode/resolve.json`을 삭제하지 않습니다.
|
|
180
|
+
|
|
181
|
+
Linux/macOS:
|
|
182
|
+
|
|
183
|
+
```sh
|
|
184
|
+
export OPENCODE_CACHE_ROOT="${XDG_CACHE_HOME:-$HOME/.cache}/opencode"
|
|
185
|
+
rm -rf "$OPENCODE_CACHE_ROOT/packages/opencode-resolve@latest"
|
|
186
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
187
|
+
node -e "console.log(require(process.env.OPENCODE_CACHE_ROOT + '/packages/opencode-resolve@latest/node_modules/opencode-resolve/package.json').version)"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Windows PowerShell:
|
|
191
|
+
|
|
192
|
+
```powershell
|
|
193
|
+
$OpenCodeCacheRoot = if ($env:XDG_CACHE_HOME) { Join-Path $env:XDG_CACHE_HOME "opencode" } else { Join-Path $env:LOCALAPPDATA "opencode" }
|
|
194
|
+
$PluginCache = Join-Path $OpenCodeCacheRoot "packages\opencode-resolve@latest"
|
|
195
|
+
Remove-Item -Recurse -Force $PluginCache -ErrorAction SilentlyContinue
|
|
196
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
197
|
+
$Pkg = Join-Path $PluginCache "node_modules\opencode-resolve\package.json"
|
|
198
|
+
node -e "console.log(require(process.argv[1]).version)" $Pkg
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
캐시 새로고침 후 OpenCode를 재시작하세요.
|
|
202
|
+
|
|
179
203
|
### 수동 대안
|
|
180
204
|
|
|
181
205
|
`postinstall`이 플러그인을 등록하지 않았다면, `~/.config/opencode/opencode.json`에 직접 추가:
|
|
@@ -655,8 +679,8 @@ opencode-resolve는 전체 저장소를 프롬프트에 밀어 넣지 않고도
|
|
|
655
679
|
|
|
656
680
|
| 감지된 프로바이더 | 프리셋 |
|
|
657
681
|
|---|---|
|
|
658
|
-
| 인터랙티브 터미널 | 항상 `mix` / `gpt` / `glm`을 묻고 3티어 모델을 고르게 하며, `mix`에서는 `
|
|
659
|
-
| 비대화형 설치 |
|
|
682
|
+
| 인터랙티브 터미널 | 항상 `mix` / `gpt` / `glm`을 묻고 3티어 모델을 고르게 하며, `mix`에서는 `gpt`와 `glm` primary 에이전트 활성화도 묻습니다 |
|
|
683
|
+
| 비대화형 설치 | opencode.json에서 프로바이더를 자동 감지하여 모델 적응 프리셋 작성. `resolver`, `gpt`, `glm` primary 경로 활성화 |
|
|
660
684
|
| 레거시 opt-in | `OPENCODE_RESOLVE_AUTO_PRESET=1`을 설정하면 비대화형 provider-adapted 프리셋 허용 |
|
|
661
685
|
| GLM/ZAI 감지 | API 키를 복사하지 않고 ZAI MCP 부트스트랩 추가 |
|
|
662
686
|
|
|
@@ -748,7 +772,7 @@ OPENCODE_RESOLVE_SKIP_POSTINSTALL=1 npm install -g opencode-resolve
|
|
|
748
772
|
| `fast` | 빠른/저렴한 모델의 프로바이더 중립적 별칭 |
|
|
749
773
|
| `strong` | 강력한/비싼 모델의 프로바이더 중립적 별칭 |
|
|
750
774
|
| `mini` | 미니/효율적 모델의 프로바이더 중립적 별칭 |
|
|
751
|
-
| `codex` | 코덱스 스타일 코딩 모델의 프로바이더 중립적 별칭 |
|
|
775
|
+
| `codex` | 코덱스 스타일 코딩 모델의 프로바이더 중립적 별칭 (레거시) |
|
|
752
776
|
| `bronze` / `silver` / `gold` | scout / coder / reasoner 3티어 별칭 |
|
|
753
777
|
| `gpt-bronze` / `gpt-silver` / `gpt-gold` | mixed 설정의 GPT/Codex 전용 3티어 별칭 |
|
|
754
778
|
| `glm-bronze` / `glm-silver` / `glm-gold` | mixed 설정의 GLM 전용 3티어 별칭 |
|
|
@@ -766,7 +790,8 @@ OPENCODE_RESOLVE_SKIP_POSTINSTALL=1 npm install -g opencode-resolve
|
|
|
766
790
|
| 에이전트 | 기본 | 모드 | Edit | Bash | WebFetch | 용도 |
|
|
767
791
|
|---|:---:|---|---|---|---|---|
|
|
768
792
|
| `resolver` | 예 (핵심) | `all` | allow | ask (분류기 라우팅) | allow | 컨텍스트 효율적 오케스트레이터. 작업을 검증된 체크포인트로 분해, coder 디스패치, 각각 검증, 반복 회복 실패 시 차단 사항 보고. |
|
|
769
|
-
| `codex` | 아니오 | `all` | allow | ask (분류기 라우팅) | allow | `resolver`와 같은 검증 resolve-loop 스타일의 Codex 최적화 primary.
|
|
793
|
+
| `codex` | 아니오 | `all` | allow | ask (분류기 라우팅) | allow | `resolver`와 같은 검증 resolve-loop 스타일의 Codex 최적화 primary. 레거시 — 새 GPT 설정에서는 `gpt` 권장. |
|
|
794
|
+
| `gpt` | 아니오 | `all` | allow | ask (분류기 라우팅) | allow | `resolver`와 같은 검증 resolve-loop 스타일의 GPT 최적화 primary. 최초 설치 GPT/mix 프리셋 또는 명시 설정으로 활성화. |
|
|
770
795
|
| `glm` | 아니오 | `all` | allow | ask (분류기 라우팅) | allow | `resolver`와 같은 검증 resolve-loop 스타일의 GLM 최적화 primary. 최초 설치 GLM/mix 프리셋 또는 명시 설정으로 활성화. |
|
|
771
796
|
| `coder` | 예 (핵심) | `subagent` | allow | ask (분류기 라우팅) | allow | 집중된 구현자. 가장 작은 올바른 패치. 필요한 파일만 읽음. |
|
|
772
797
|
| `explorer` | 예 (서브에이전트) | `subagent` | **deny** | **deny** | allow | 내부 빠른 코드베이스 스카우트. Resolver가 범위가 불명확할 때만 디스패치; 좁은 범위는 로컬 read/grep/glob 선호. |
|
|
@@ -864,6 +889,28 @@ opencode plugin opencode-resolve --global --force
|
|
|
864
889
|
# OpenCode 재시작
|
|
865
890
|
```
|
|
866
891
|
|
|
892
|
+
그래도 버전이 바뀌지 않으면 OpenCode가 패키지 캐시를 재사용하는 상태입니다. 해당 플러그인 캐시 항목만 hard refresh 하세요:
|
|
893
|
+
|
|
894
|
+
Linux/macOS:
|
|
895
|
+
|
|
896
|
+
```sh
|
|
897
|
+
export OPENCODE_CACHE_ROOT="${XDG_CACHE_HOME:-$HOME/.cache}/opencode"
|
|
898
|
+
rm -rf "$OPENCODE_CACHE_ROOT/packages/opencode-resolve@latest"
|
|
899
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
900
|
+
node -e "console.log(require(process.env.OPENCODE_CACHE_ROOT + '/packages/opencode-resolve@latest/node_modules/opencode-resolve/package.json').version)"
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
Windows PowerShell:
|
|
904
|
+
|
|
905
|
+
```powershell
|
|
906
|
+
$OpenCodeCacheRoot = if ($env:XDG_CACHE_HOME) { Join-Path $env:XDG_CACHE_HOME "opencode" } else { Join-Path $env:LOCALAPPDATA "opencode" }
|
|
907
|
+
$PluginCache = Join-Path $OpenCodeCacheRoot "packages\opencode-resolve@latest"
|
|
908
|
+
Remove-Item -Recurse -Force $PluginCache -ErrorAction SilentlyContinue
|
|
909
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
910
|
+
$Pkg = Join-Path $PluginCache "node_modules\opencode-resolve\package.json"
|
|
911
|
+
node -e "console.log(require(process.argv[1]).version)" $Pkg
|
|
912
|
+
```
|
|
913
|
+
|
|
867
914
|
업그레이드 후 `postinstall`이 `resolve.json`에 추가적 마이그레이션을 실행합니다 — 새 키가 추가되고, 기존 키는 절대 수정되지 않습니다.
|
|
868
915
|
|
|
869
916
|
### 특정 버전 고정
|
package/README.md
CHANGED
|
@@ -156,8 +156,8 @@ The `postinstall` script automatically:
|
|
|
156
156
|
|
|
157
157
|
1. Adds `opencode-resolve` to `~/.config/opencode/opencode.json` `plugin` array (if not already present).
|
|
158
158
|
2. Creates `~/.config/opencode/resolve.json` adapted to your current model provider when the file does not exist:
|
|
159
|
-
- **Interactive terminal** → always asks for `mix` / `gpt` / `glm`, then lets you pick three-tier `bronze` / `silver` / `gold` models. In `mix`, it also asks whether to enable dedicated `
|
|
160
|
-
- **Non-interactive install** →
|
|
159
|
+
- **Interactive terminal** → always asks for `mix` / `gpt` / `glm`, then lets you pick three-tier `bronze` / `silver` / `gold` models. In `mix`, it also asks whether to enable dedicated `gpt` and `glm` primary agents.
|
|
160
|
+
- **Non-interactive install** → auto-detects providers from opencode.json and writes a model-adapted preset. Enables `resolver`, `gpt`, and `glm` as primary routes.
|
|
161
161
|
- **GLM/ZAI model detected** → still adds the non-secret local ZAI MCP bootstrap.
|
|
162
162
|
|
|
163
163
|
Existing `resolve.json` files are **never overwritten without consent**. On reinstall, interactive setup asks whether to update the existing file or back it up and run fresh setup. For non-interactive automation, set `OPENCODE_RESOLVE_REINSTALL=fresh` or `OPENCODE_RESOLVE_REINSTALL=update`.
|
|
@@ -176,6 +176,30 @@ OPENCODE_RESOLVE_SKIP_POSTINSTALL=1 npm install -g opencode-resolve
|
|
|
176
176
|
opencode plugin opencode-resolve --global --force
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
+
If OpenCode keeps loading the old package anyway, clear only the OpenCode plugin cache entry and install again. This does **not** delete `~/.config/opencode/resolve.json`.
|
|
180
|
+
|
|
181
|
+
Linux/macOS:
|
|
182
|
+
|
|
183
|
+
```sh
|
|
184
|
+
export OPENCODE_CACHE_ROOT="${XDG_CACHE_HOME:-$HOME/.cache}/opencode"
|
|
185
|
+
rm -rf "$OPENCODE_CACHE_ROOT/packages/opencode-resolve@latest"
|
|
186
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
187
|
+
node -e "console.log(require(process.env.OPENCODE_CACHE_ROOT + '/packages/opencode-resolve@latest/node_modules/opencode-resolve/package.json').version)"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Windows PowerShell:
|
|
191
|
+
|
|
192
|
+
```powershell
|
|
193
|
+
$OpenCodeCacheRoot = if ($env:XDG_CACHE_HOME) { Join-Path $env:XDG_CACHE_HOME "opencode" } else { Join-Path $env:LOCALAPPDATA "opencode" }
|
|
194
|
+
$PluginCache = Join-Path $OpenCodeCacheRoot "packages\opencode-resolve@latest"
|
|
195
|
+
Remove-Item -Recurse -Force $PluginCache -ErrorAction SilentlyContinue
|
|
196
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
197
|
+
$Pkg = Join-Path $PluginCache "node_modules\opencode-resolve\package.json"
|
|
198
|
+
node -e "console.log(require(process.argv[1]).version)" $Pkg
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Restart OpenCode after the cache refresh.
|
|
202
|
+
|
|
179
203
|
### Manual fallback
|
|
180
204
|
|
|
181
205
|
If `postinstall` didn't register the plugin, add it to `~/.config/opencode/opencode.json` yourself:
|
|
@@ -655,8 +679,8 @@ When `resolve.json` does **not** exist, postinstall inspects your OpenCode model
|
|
|
655
679
|
|
|
656
680
|
| Detected provider | Preset |
|
|
657
681
|
|---|---|
|
|
658
|
-
| Interactive terminal | Always prompts for `mix` / `gpt` / `glm`, asks for three-tier model picks, and in `mix` asks whether to enable `
|
|
659
|
-
| Non-interactive install |
|
|
682
|
+
| Interactive terminal | Always prompts for `mix` / `gpt` / `glm`, asks for three-tier model picks, and in `mix` asks whether to enable `gpt` and `glm` primary agents |
|
|
683
|
+
| Non-interactive install | Auto-detects providers from opencode.json and writes a model-adapted preset with `resolver`, `gpt`, and `glm` enabled |
|
|
660
684
|
| Legacy opt-in | Set `OPENCODE_RESOLVE_AUTO_PRESET=1` to allow non-interactive provider-adapted presets |
|
|
661
685
|
| GLM/ZAI detected | Adds the ZAI MCP bootstrap without copying API keys |
|
|
662
686
|
|
|
@@ -748,9 +772,9 @@ In this setup, `plan` uses `openai/gpt-5.3-codex`; native `build`, resolve `code
|
|
|
748
772
|
| `fast` | Provider-neutral alias for a fast/cheap model |
|
|
749
773
|
| `strong` | Provider-neutral alias for a strong/expensive model |
|
|
750
774
|
| `mini` | Provider-neutral alias for a mini/efficient model |
|
|
751
|
-
| `codex` | Provider-neutral alias for a codex-style coding model |
|
|
775
|
+
| `codex` | Provider-neutral alias for a codex-style coding model (legacy) |
|
|
752
776
|
| `bronze` / `silver` / `gold` | Three-tier scout / coder / reasoner aliases |
|
|
753
|
-
| `gpt-bronze` / `gpt-silver` / `gpt-gold` | GPT
|
|
777
|
+
| `gpt-bronze` / `gpt-silver` / `gpt-gold` | GPT-specific three-tier aliases for mixed setups |
|
|
754
778
|
| `glm-bronze` / `glm-silver` / `glm-gold` | GLM-specific three-tier aliases for mixed setups |
|
|
755
779
|
| `quick` | Legacy alias (equivalent to `fast`) |
|
|
756
780
|
| `deep` | Legacy alias (equivalent to `strong`) |
|
|
@@ -766,7 +790,8 @@ Aliases only resolve when defined in `models`. Agent names (`coder`, `resolver`,
|
|
|
766
790
|
| Agent | Default | Mode | Edit | Bash | WebFetch | Purpose |
|
|
767
791
|
|---|:---:|---|---|---|---|---|
|
|
768
792
|
| `resolver` | Yes (core) | `all` | allow | ask (classifier-routed) | allow | Context-efficient orchestrator. Decomposes work into verified checkpoints, dispatches coder, verifies each, and reports blockers when repeated recovery fails. |
|
|
769
|
-
| `codex` | No | `all` | allow | ask (classifier-routed) | allow | Codex-optimized primary resolver
|
|
793
|
+
| `codex` | No | `all` | allow | ask (classifier-routed) | allow | Codex-optimized primary resolver. Legacy — prefer `gpt` for new GPT setups. |
|
|
794
|
+
| `gpt` | No | `all` | allow | ask (classifier-routed) | allow | GPT-optimized primary resolver with the same verified resolve-loop style as `resolver`. Enabled by first-install GPT/mix presets or explicitly. |
|
|
770
795
|
| `glm` | No | `all` | allow | ask (classifier-routed) | allow | GLM-optimized primary resolver with the same verified resolve-loop style as `resolver`. Enabled by first-install GLM/mix presets or explicitly. |
|
|
771
796
|
| `coder` | Yes (core) | `subagent` | allow | ask (classifier-routed) | allow | Focused implementer. Smallest correct patch. Reads only needed files. |
|
|
772
797
|
| `explorer` | Yes (subagent) | `subagent` | **deny** | **deny** | allow | Internal fast codebase scout. Resolver dispatches when scope is genuinely unknown; prefers local read/grep/glob for narrow scope. |
|
|
@@ -864,6 +889,28 @@ opencode plugin opencode-resolve --global --force
|
|
|
864
889
|
# Restart OpenCode
|
|
865
890
|
```
|
|
866
891
|
|
|
892
|
+
If the version still does not change, OpenCode is reusing its package cache. Hard-refresh that one plugin entry:
|
|
893
|
+
|
|
894
|
+
Linux/macOS:
|
|
895
|
+
|
|
896
|
+
```sh
|
|
897
|
+
export OPENCODE_CACHE_ROOT="${XDG_CACHE_HOME:-$HOME/.cache}/opencode"
|
|
898
|
+
rm -rf "$OPENCODE_CACHE_ROOT/packages/opencode-resolve@latest"
|
|
899
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
900
|
+
node -e "console.log(require(process.env.OPENCODE_CACHE_ROOT + '/packages/opencode-resolve@latest/node_modules/opencode-resolve/package.json').version)"
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
Windows PowerShell:
|
|
904
|
+
|
|
905
|
+
```powershell
|
|
906
|
+
$OpenCodeCacheRoot = if ($env:XDG_CACHE_HOME) { Join-Path $env:XDG_CACHE_HOME "opencode" } else { Join-Path $env:LOCALAPPDATA "opencode" }
|
|
907
|
+
$PluginCache = Join-Path $OpenCodeCacheRoot "packages\opencode-resolve@latest"
|
|
908
|
+
Remove-Item -Recurse -Force $PluginCache -ErrorAction SilentlyContinue
|
|
909
|
+
opencode plugin opencode-resolve@latest --global --force
|
|
910
|
+
$Pkg = Join-Path $PluginCache "node_modules\opencode-resolve\package.json"
|
|
911
|
+
node -e "console.log(require(process.argv[1]).version)" $Pkg
|
|
912
|
+
```
|
|
913
|
+
|
|
867
914
|
After upgrading, `postinstall` runs additive migration on your `resolve.json` — new keys are added, existing keys are never modified.
|
|
868
915
|
|
|
869
916
|
### Pinning a specific version
|
package/dist/agents.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ResolveAgentName, ResolveAgentConfig, ModelAlias, TierName } from "./types.js";
|
|
2
2
|
export declare const DEFAULT_MODELS: Partial<Record<ModelAlias, string>>;
|
|
3
3
|
export declare const DEFAULT_ENABLED: ResolveAgentName[];
|
|
4
|
-
export declare const VALID_AGENT_NAMES: readonly ["coder", "reviewer", "resolver", "codex", "glm", "architect", "gpt-coder", "debugger", "researcher", "explorer", "deep-reviewer", "planner"];
|
|
4
|
+
export declare const VALID_AGENT_NAMES: readonly ["coder", "reviewer", "resolver", "codex", "gpt", "glm", "architect", "gpt-coder", "debugger", "researcher", "explorer", "deep-reviewer", "planner"];
|
|
5
5
|
export declare const VALID_AGENT_NAME_SET: Set<string>;
|
|
6
6
|
export declare const DEFAULT_AGENT_CONFIG: Record<ResolveAgentName, Required<Pick<ResolveAgentConfig, "mode" | "description" | "prompt" | "color">> & ResolveAgentConfig>;
|
|
7
7
|
export declare const GLM_CODER_PROMPT: string;
|
|
@@ -10,7 +10,7 @@ export declare function buildGLMResolverPrompt(maxParallelSubagents: number | un
|
|
|
10
10
|
export declare function buildGPTResolverPrompt(): string;
|
|
11
11
|
export declare function buildCodexResolverPrompt(): string;
|
|
12
12
|
export declare function buildResolverPrompt(maxParallelSubagents: number | undefined): string;
|
|
13
|
-
export declare const VALID_MODEL_ALIASES: readonly ["coder", "reviewer", "resolver", "codex", "glm", "architect", "gpt-coder", "debugger", "researcher", "explorer", "deep-reviewer", "planner", "glm", "gpt", "quick", "deep", "fast", "strong", "mini", "codex", "bronze", "silver", "gold", "gpt-bronze", "gpt-silver", "gpt-gold", "glm-bronze", "glm-silver", "glm-gold"];
|
|
13
|
+
export declare const VALID_MODEL_ALIASES: readonly ["coder", "reviewer", "resolver", "codex", "gpt", "glm", "architect", "gpt-coder", "debugger", "researcher", "explorer", "deep-reviewer", "planner", "glm", "gpt", "quick", "deep", "fast", "strong", "mini", "codex", "bronze", "silver", "gold", "gpt-bronze", "gpt-silver", "gpt-gold", "glm-bronze", "glm-silver", "glm-gold"];
|
|
14
14
|
export declare const VALID_MODEL_ALIAS_SET: Set<string>;
|
|
15
15
|
export declare const VALID_PROFILES: Set<string>;
|
|
16
16
|
export declare const VALID_TIERS: Set<string>;
|
package/dist/agents.js
CHANGED
|
@@ -5,6 +5,7 @@ export const VALID_AGENT_NAMES = [
|
|
|
5
5
|
"reviewer",
|
|
6
6
|
"resolver",
|
|
7
7
|
"codex",
|
|
8
|
+
"gpt",
|
|
8
9
|
"glm",
|
|
9
10
|
"architect",
|
|
10
11
|
"gpt-coder",
|
|
@@ -85,6 +86,18 @@ export const DEFAULT_AGENT_CONFIG = {
|
|
|
85
86
|
webfetch: "allow",
|
|
86
87
|
},
|
|
87
88
|
},
|
|
89
|
+
gpt: {
|
|
90
|
+
mode: "all",
|
|
91
|
+
color: "#FFB347",
|
|
92
|
+
maxSteps: 35,
|
|
93
|
+
description: "GPT-optimized primary resolver for agentic coding work. Use when a GPT/OpenAI coding model is pinned and you want a dedicated user-facing route separate from the neutral resolver.",
|
|
94
|
+
prompt: buildGPTResolverPrompt(),
|
|
95
|
+
permission: {
|
|
96
|
+
edit: "allow",
|
|
97
|
+
bash: "ask",
|
|
98
|
+
webfetch: "allow",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
88
101
|
architect: {
|
|
89
102
|
mode: "subagent",
|
|
90
103
|
color: "#00BFFF",
|
|
@@ -368,11 +381,11 @@ export const VALID_MODEL_ALIAS_SET = new Set(VALID_MODEL_ALIASES);
|
|
|
368
381
|
export const VALID_PROFILES = new Set(["mix", "glm", "gpt"]);
|
|
369
382
|
export const VALID_TIERS = new Set(["bronze", "silver", "gold"]);
|
|
370
383
|
export const GLM_ENABLED = ["coder", "resolver", "glm", "explorer", "reviewer", "planner"];
|
|
371
|
-
export const GPT_ENABLED = ["coder", "resolver", "
|
|
384
|
+
export const GPT_ENABLED = ["coder", "resolver", "gpt", "explorer", "reviewer", "deep-reviewer", "planner"];
|
|
372
385
|
export const TIER_ENABLED = {
|
|
373
386
|
bronze: ["coder", "resolver"],
|
|
374
387
|
silver: ["coder", "resolver", "explorer", "reviewer", "planner"],
|
|
375
|
-
gold: ["coder", "resolver", "codex", "glm", "explorer", "reviewer", "deep-reviewer", "planner", "debugger", "researcher"],
|
|
388
|
+
gold: ["coder", "resolver", "codex", "gpt", "glm", "explorer", "reviewer", "deep-reviewer", "planner", "debugger", "researcher"],
|
|
376
389
|
};
|
|
377
390
|
export const GLM_AGENT_OVERRIDES = {
|
|
378
391
|
coder: { maxSteps: 15 },
|
|
@@ -384,7 +397,7 @@ export const GLM_AGENT_OVERRIDES = {
|
|
|
384
397
|
export const GPT_AGENT_OVERRIDES = {
|
|
385
398
|
coder: { maxSteps: 25 },
|
|
386
399
|
resolver: { maxSteps: 40 },
|
|
387
|
-
|
|
400
|
+
gpt: { maxSteps: 40 },
|
|
388
401
|
explorer: { maxSteps: 8 },
|
|
389
402
|
reviewer: { maxSteps: 10 },
|
|
390
403
|
"deep-reviewer": { maxSteps: 15 },
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type PermissionValue = "ask" | "allow" | "deny";
|
|
2
|
-
export type ResolveAgentName = "coder" | "reviewer" | "resolver" | "codex" | "glm" | "architect" | "gpt-coder" | "debugger" | "researcher" | "explorer" | "deep-reviewer" | "planner";
|
|
2
|
+
export type ResolveAgentName = "coder" | "reviewer" | "resolver" | "codex" | "gpt" | "glm" | "architect" | "gpt-coder" | "debugger" | "researcher" | "explorer" | "deep-reviewer" | "planner";
|
|
3
3
|
export type ModelAlias = ResolveAgentName | "glm" | "gpt" | "quick" | "deep" | "fast" | "strong" | "mini" | "codex" | "bronze" | "silver" | "gold" | "gpt-bronze" | "gpt-silver" | "gpt-gold" | "glm-bronze" | "glm-silver" | "glm-gold";
|
|
4
4
|
export type AgentMode = "subagent" | "primary" | "all";
|
|
5
5
|
export type ResolveAgentConfig = {
|
|
@@ -118,9 +118,9 @@
|
|
|
118
118
|
|
|
119
119
|
// -----------------------------------------------------------------------
|
|
120
120
|
// models (object)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
// Alias map. Keys are either an agent name (coder, reviewer, resolver,
|
|
122
|
+
// codex, gpt, glm, architect, gpt-coder, debugger, researcher, explorer,
|
|
123
|
+
// deep-reviewer, planner)
|
|
124
124
|
// OR one of the well-known aliases (`glm`, `gpt`, `quick`, `deep`,
|
|
125
125
|
// `fast`, `strong`, `mini`, `codex`, `bronze`, `silver`, `gold`,
|
|
126
126
|
// `gpt-bronze`, `gpt-silver`, `gpt-gold`, `glm-bronze`, `glm-silver`,
|
|
@@ -168,12 +168,12 @@
|
|
|
168
168
|
// third-party providers never blocks agent execution.
|
|
169
169
|
// "models": {
|
|
170
170
|
// "glm": "zai-coding-plan/glm-5.1",
|
|
171
|
-
// "bronze": "zai-coding-plan/glm-
|
|
172
|
-
// "silver": "zai-coding-plan/glm-5
|
|
171
|
+
// "bronze": "zai-coding-plan/glm-4.7-flash",
|
|
172
|
+
// "silver": "zai-coding-plan/glm-5",
|
|
173
173
|
// "gold": "zai-coding-plan/glm-5.1",
|
|
174
174
|
// "fast": "bronze",
|
|
175
175
|
// "strong": "gold",
|
|
176
|
-
// "coder": "
|
|
176
|
+
// "coder": "gold",
|
|
177
177
|
// "resolver": "gold",
|
|
178
178
|
// "reviewer": "gold",
|
|
179
179
|
// "deep-reviewer": "gold",
|
|
@@ -223,13 +223,26 @@
|
|
|
223
223
|
|
|
224
224
|
// codex — Codex-optimized primary resolver (selectable in agent picker)
|
|
225
225
|
// Same verified resolve-loop style as resolver, with a Codex-specific
|
|
226
|
-
// system prompt.
|
|
226
|
+
// system prompt. Legacy — kept for backward compatibility. New GPT
|
|
227
|
+
// installs should prefer the "gpt" agent instead.
|
|
227
228
|
"codex": {
|
|
228
229
|
"enabled": false,
|
|
229
230
|
"mode": "all",
|
|
230
231
|
"maxSteps": 35
|
|
231
232
|
},
|
|
232
233
|
|
|
234
|
+
// -----------------------------------------------------------------
|
|
235
|
+
// gpt — GPT-optimized primary resolver (selectable in agent picker)
|
|
236
|
+
// GPT-specific verified resolve-loop with parallel coder dispatch,
|
|
237
|
+
// full agent roster, and higher maxSteps. Enabled automatically when
|
|
238
|
+
// GPT profile is selected during install. Uses buildGPTResolverPrompt().
|
|
239
|
+
// -----------------------------------------------------------------
|
|
240
|
+
"gpt": {
|
|
241
|
+
"enabled": false,
|
|
242
|
+
"mode": "all",
|
|
243
|
+
"maxSteps": 35
|
|
244
|
+
},
|
|
245
|
+
|
|
233
246
|
// Internal specialist subagents — enabled by default as subagents only.
|
|
234
247
|
// Core path is resolver→coder. These are dispatched only when justified.
|
|
235
248
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-resolve",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "OpenCode plugin that adds a lightweight resolver/coder harness for continuous agentic coding.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/jshsakura/opencode-resolve#readme",
|
|
@@ -100,7 +100,7 @@ async function createAdaptiveResolveConfig() {
|
|
|
100
100
|
resolveConfig.models = {}
|
|
101
101
|
resolveConfig.agents = {
|
|
102
102
|
...resolveConfig.agents,
|
|
103
|
-
|
|
103
|
+
gpt: { ...(resolveConfig.agents?.gpt ?? {}), enabled: true },
|
|
104
104
|
glm: { ...(resolveConfig.agents?.glm ?? {}), enabled: true },
|
|
105
105
|
}
|
|
106
106
|
}
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -53,9 +53,13 @@ const OPENAI_MODEL_HINTS = [
|
|
|
53
53
|
|
|
54
54
|
const GLM_MODEL_HINTS = [
|
|
55
55
|
"zai-coding-plan/glm-5.1",
|
|
56
|
+
"zai-coding-plan/glm-5",
|
|
57
|
+
"zai-coding-plan/glm-4.7-flash",
|
|
58
|
+
"zai-coding-plan/glm-4.5-flash",
|
|
56
59
|
"zai/glm-5.1",
|
|
57
60
|
"zai/glm-5",
|
|
58
61
|
"zai/glm-4.7-flash",
|
|
62
|
+
"zai/glm-4.7",
|
|
59
63
|
"zai/glm-4.5-flash",
|
|
60
64
|
"zai/glm-4.5",
|
|
61
65
|
"zai/glm-4.5-air",
|
|
@@ -91,30 +95,55 @@ async function registerPlugin() {
|
|
|
91
95
|
await mkdir(configDir, { recursive: true })
|
|
92
96
|
const scriptedAnswers = await readScriptedAnswersIfNeeded()
|
|
93
97
|
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// Inject ZAI MCP servers when GLM is detected
|
|
98
|
-
const allModels = detectAllModels(config)
|
|
98
|
+
const probe = await readOpenCodeConfig()
|
|
99
|
+
const allModels = detectAllModels(probe)
|
|
99
100
|
const hasGLM = allModels.some((m) => isGLMModel(m))
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
const pluginNeeded = !isPluginRegisteredIn(probe)
|
|
102
|
+
const missingMCPNames = hasGLM
|
|
103
|
+
? Object.keys(ZAI_MCP_SERVERS).filter((name) => probe.mcp?.[name] === undefined)
|
|
104
|
+
: []
|
|
104
105
|
|
|
105
|
-
if (
|
|
106
|
-
|
|
106
|
+
if (pluginNeeded || missingMCPNames.length > 0) {
|
|
107
|
+
const fresh = await readOpenCodeConfig()
|
|
108
|
+
if (pluginNeeded) applyPluginPatch(fresh)
|
|
109
|
+
if (missingMCPNames.length > 0) applyMCPPatches(fresh, missingMCPNames)
|
|
110
|
+
await writeFile(opencodeConfigPath, `${JSON.stringify(fresh, null, 2)}\n`)
|
|
107
111
|
console.log(`[${packageName}] updated ${opencodeConfigPath}`)
|
|
108
112
|
} else {
|
|
109
113
|
console.log(`[${packageName}] already registered in ${opencodeConfigPath}`)
|
|
110
114
|
}
|
|
111
115
|
|
|
112
116
|
if (!(await exists(resolveConfigPath))) {
|
|
113
|
-
await createAdaptiveResolveConfig(
|
|
117
|
+
await createAdaptiveResolveConfig(probe, scriptedAnswers)
|
|
114
118
|
return
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
await handleExistingResolveConfig(
|
|
121
|
+
await handleExistingResolveConfig(probe, scriptedAnswers)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isPluginRegisteredIn(config) {
|
|
125
|
+
return Array.isArray(config.plugin) && config.plugin.some(isRegisteredPluginEntry)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function applyPluginPatch(config) {
|
|
129
|
+
config.plugin ??= []
|
|
130
|
+
if (!Array.isArray(config.plugin)) {
|
|
131
|
+
throw new Error(`${opencodeConfigPath}.plugin must be an array`)
|
|
132
|
+
}
|
|
133
|
+
if (!config.plugin.some(isRegisteredPluginEntry)) {
|
|
134
|
+
config.plugin.push(packageName)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function applyMCPPatches(config, names) {
|
|
139
|
+
config.mcp ??= {}
|
|
140
|
+
for (const name of names) {
|
|
141
|
+
if (config.mcp[name] === undefined) {
|
|
142
|
+
config.mcp[name] = ZAI_MCP_SERVERS[name]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
console.log(`[${packageName}] injected ZAI MCP server config: ${names.join(", ")}`)
|
|
146
|
+
console.log(`[${packageName}] note: API keys are not copied into opencode.json; export Z_AI_API_KEY if the MCP server requires it.`)
|
|
118
147
|
}
|
|
119
148
|
|
|
120
149
|
async function handleExistingResolveConfig(opencodeConfig, scriptedAnswers) {
|
|
@@ -196,29 +225,11 @@ async function createAdaptiveResolveConfig(opencodeConfig, scriptedAnswers) {
|
|
|
196
225
|
return
|
|
197
226
|
}
|
|
198
227
|
|
|
199
|
-
if (process.env.OPENCODE_RESOLVE_AUTO_PRESET !== "1") {
|
|
200
|
-
resolveConfig.profile = "mix"
|
|
201
|
-
delete resolveConfig.tier
|
|
202
|
-
resolveConfig.models = {}
|
|
203
|
-
resolveConfig.agents = {
|
|
204
|
-
...resolveConfig.agents,
|
|
205
|
-
codex: { ...(resolveConfig.agents?.codex ?? {}), enabled: true },
|
|
206
|
-
glm: { ...(resolveConfig.agents?.glm ?? {}), enabled: true },
|
|
207
|
-
}
|
|
208
|
-
await writeFile(resolveConfigPath, `${JSON.stringify(resolveConfig, null, 2)}\n`)
|
|
209
|
-
console.log(`[${packageName}] created ${resolveConfigPath} (preset: prompt-required)`)
|
|
210
|
-
console.log(`[${packageName}] model pinning was not guessed because no interactive prompt was available.`)
|
|
211
|
-
console.log(`[${packageName}] rerun setup in a TTY or edit ${resolveConfigPath} to choose GPT/GLM three-tier models.`)
|
|
212
|
-
return
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Profile selection based on detected providers
|
|
216
228
|
const hasGLM = allModels.some((m) => isGLMModel(m))
|
|
217
229
|
const hasGPT = allModels.some((m) => isGPTModel(m))
|
|
218
230
|
const preset = buildModelPreset(currentModel, allModels)
|
|
219
231
|
|
|
220
232
|
if (hasGLM && !hasGPT) {
|
|
221
|
-
// GLM only → GLM profile, silver tier (token-efficient, no deep-reviewer)
|
|
222
233
|
resolveConfig.profile = "glm"
|
|
223
234
|
resolveConfig.tier = "silver"
|
|
224
235
|
resolveConfig.agents = {
|
|
@@ -226,20 +237,18 @@ async function createAdaptiveResolveConfig(opencodeConfig, scriptedAnswers) {
|
|
|
226
237
|
glm: { ...(resolveConfig.agents?.glm ?? {}), enabled: true },
|
|
227
238
|
}
|
|
228
239
|
} else if (hasGPT && !hasGLM) {
|
|
229
|
-
// GPT only → GPT profile, gold tier (full power)
|
|
230
240
|
resolveConfig.profile = "gpt"
|
|
231
241
|
resolveConfig.tier = "gold"
|
|
232
242
|
resolveConfig.agents = {
|
|
233
243
|
...resolveConfig.agents,
|
|
234
|
-
|
|
244
|
+
gpt: { ...(resolveConfig.agents?.gpt ?? {}), enabled: true },
|
|
235
245
|
}
|
|
236
246
|
} else {
|
|
237
|
-
// Mixed or unknown provider → explicit mix profile. No tier: use DEFAULT_ENABLED.
|
|
238
247
|
resolveConfig.profile = "mix"
|
|
239
248
|
if (hasGLM && hasGPT) {
|
|
240
249
|
resolveConfig.agents = {
|
|
241
250
|
...resolveConfig.agents,
|
|
242
|
-
|
|
251
|
+
gpt: { ...(resolveConfig.agents?.gpt ?? {}), enabled: true },
|
|
243
252
|
glm: { ...(resolveConfig.agents?.glm ?? {}), enabled: true },
|
|
244
253
|
}
|
|
245
254
|
}
|
|
@@ -247,6 +256,9 @@ async function createAdaptiveResolveConfig(opencodeConfig, scriptedAnswers) {
|
|
|
247
256
|
|
|
248
257
|
if (preset && Object.keys(preset).length > 0) {
|
|
249
258
|
resolveConfig.models = preset
|
|
259
|
+
} else {
|
|
260
|
+
console.log(`[${packageName}] no GPT/GLM models detected in opencode.json — agents inherit the top-level model`)
|
|
261
|
+
console.log(`[${packageName}] to configure model pinning, rerun setup in a TTY or edit ${resolveConfigPath}`)
|
|
250
262
|
}
|
|
251
263
|
|
|
252
264
|
await writeFile(resolveConfigPath, `${JSON.stringify(resolveConfig, null, 2)}\n`)
|
|
@@ -327,7 +339,11 @@ function buildModelPreset(currentModel, allModels = []) {
|
|
|
327
339
|
|
|
328
340
|
// GLM / ZAI — GLM-only preset (no GPT dependency, avoids token-exhaustion errors)
|
|
329
341
|
if (lower.includes("glm") || lower.includes("zai")) {
|
|
330
|
-
return buildGLMOnlyPreset(currentModel)
|
|
342
|
+
return buildGLMOnlyPreset(currentModel, glmModels)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (lower.includes("openai/") || lower.includes("gpt")) {
|
|
346
|
+
return buildGPTOnlyPreset(currentModel, gptModels)
|
|
331
347
|
}
|
|
332
348
|
|
|
333
349
|
// OpenAI / GPT single-provider preset
|
|
@@ -339,8 +355,9 @@ function buildModelPreset(currentModel, allModels = []) {
|
|
|
339
355
|
return {}
|
|
340
356
|
}
|
|
341
357
|
|
|
342
|
-
function buildGLMOnlyPreset(model) {
|
|
343
|
-
const
|
|
358
|
+
function buildGLMOnlyPreset(model, glmModels) {
|
|
359
|
+
const models = glmModels && glmModels.length > 0 ? glmModels : [model]
|
|
360
|
+
const tiers = chooseThreeTier(models, "glm", false)
|
|
344
361
|
return {
|
|
345
362
|
glm: tiers.gold,
|
|
346
363
|
bronze: tiers.bronze,
|
|
@@ -349,7 +366,7 @@ function buildGLMOnlyPreset(model) {
|
|
|
349
366
|
fast: "bronze",
|
|
350
367
|
strong: "gold",
|
|
351
368
|
mini: "bronze",
|
|
352
|
-
coder: "
|
|
369
|
+
coder: "gold",
|
|
353
370
|
resolver: "gold",
|
|
354
371
|
reviewer: "gold",
|
|
355
372
|
"deep-reviewer": "gold",
|
|
@@ -358,8 +375,9 @@ function buildGLMOnlyPreset(model) {
|
|
|
358
375
|
}
|
|
359
376
|
}
|
|
360
377
|
|
|
361
|
-
function buildGPTOnlyPreset(model) {
|
|
362
|
-
const
|
|
378
|
+
function buildGPTOnlyPreset(model, gptModels) {
|
|
379
|
+
const models = gptModels && gptModels.length > 0 ? gptModels : [model]
|
|
380
|
+
const tiers = chooseThreeTier(models, "gpt", false)
|
|
363
381
|
return {
|
|
364
382
|
gpt: tiers.gold,
|
|
365
383
|
bronze: tiers.bronze,
|
|
@@ -404,12 +422,17 @@ async function buildInteractivePreset(currentModel, allModels, scriptedAnswers)
|
|
|
404
422
|
profile: "gpt",
|
|
405
423
|
tier: "gold",
|
|
406
424
|
models: buildGPTThreeTierModels(tiers),
|
|
407
|
-
agents: {
|
|
425
|
+
agents: { gpt: { enabled: true } },
|
|
408
426
|
}
|
|
409
427
|
}
|
|
410
428
|
|
|
411
429
|
if (profile === "glm") {
|
|
412
|
-
const
|
|
430
|
+
const useCodingPlan = await askYesNo(rl, "Use coding-plan (zai-coding-plan) instead of standard (zai)? [y/N]: ", false)
|
|
431
|
+
const glmChoices = useCodingPlan
|
|
432
|
+
? choices.glm.map((m) => m.replace(/^zai\//, "zai-coding-plan/"))
|
|
433
|
+
: choices.glm.map((m) => m.replace(/^zai-coding-plan\//, "zai/"))
|
|
434
|
+
const deduped = unique([...glmChoices.filter((m) => isGLMModel(m)), ...GLM_MODEL_HINTS])
|
|
435
|
+
const tiers = await askThreeTier(rl, "GLM", deduped)
|
|
413
436
|
return {
|
|
414
437
|
label: "glm-three-tier",
|
|
415
438
|
profile: "glm",
|
|
@@ -419,16 +442,16 @@ async function buildInteractivePreset(currentModel, allModels, scriptedAnswers)
|
|
|
419
442
|
}
|
|
420
443
|
}
|
|
421
444
|
|
|
422
|
-
const
|
|
445
|
+
const useGPT = await askYesNo(rl, "Enable dedicated GPT primary agent too? [Y/n]: ", true)
|
|
423
446
|
const useGLM = await askYesNo(rl, "Enable dedicated GLM primary agent too? [Y/n]: ", true)
|
|
424
|
-
const gptTiers = await askThreeTier(rl, "
|
|
447
|
+
const gptTiers = await askThreeTier(rl, "GPT", choices.gpt)
|
|
425
448
|
const glmTiers = await askThreeTier(rl, "GLM", choices.glm)
|
|
426
449
|
return {
|
|
427
450
|
label: "mix-three-tier",
|
|
428
451
|
profile: "mix",
|
|
429
452
|
models: buildMixedThreeTierModels(gptTiers, glmTiers),
|
|
430
453
|
agents: {
|
|
431
|
-
|
|
454
|
+
gpt: { enabled: useGPT },
|
|
432
455
|
glm: { enabled: useGLM },
|
|
433
456
|
},
|
|
434
457
|
}
|
|
@@ -539,7 +562,7 @@ function buildGLMThreeTierModels(tiers) {
|
|
|
539
562
|
strong: "gold",
|
|
540
563
|
mini: "bronze",
|
|
541
564
|
explorer: "bronze",
|
|
542
|
-
coder: "
|
|
565
|
+
coder: "gold",
|
|
543
566
|
resolver: "gold",
|
|
544
567
|
reviewer: "gold",
|
|
545
568
|
"deep-reviewer": "gold",
|
|
@@ -561,7 +584,7 @@ function chooseThreeTier(models, family, includeFallbackHints = true) {
|
|
|
561
584
|
const choices = unique(includeFallbackHints ? [...models, ...fallback] : models)
|
|
562
585
|
return {
|
|
563
586
|
bronze: preferModel(choices, family === "glm" ? ["flash", "air", "mini"] : ["spark", "mini", "4o-mini"], choices[0]),
|
|
564
|
-
silver: preferModel(choices, family === "glm" ? ["
|
|
587
|
+
silver: preferModel(choices, family === "glm" ? ["4.7", "4.5", "5"] : ["codex", "5.3", "5.2"], choices[1] ?? choices[0]),
|
|
565
588
|
gold: preferModel(choices, family === "glm" ? ["5.1", "5", "4.5"] : ["5.5", "5.4", "gpt-5.3-codex"], choices[2] ?? choices[1] ?? choices[0]),
|
|
566
589
|
}
|
|
567
590
|
}
|
|
@@ -724,38 +747,7 @@ async function readOpenCodeConfig() {
|
|
|
724
747
|
return parsed
|
|
725
748
|
}
|
|
726
749
|
|
|
727
|
-
function addPlugin(config) {
|
|
728
|
-
config.plugin ??= []
|
|
729
|
-
if (!Array.isArray(config.plugin)) {
|
|
730
|
-
throw new Error(`${opencodeConfigPath}.plugin must be an array`)
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (config.plugin.some(isRegisteredPluginEntry)) return false
|
|
734
|
-
config.plugin.push(packageName)
|
|
735
|
-
return true
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
async function injectZAIMCPs(config) {
|
|
739
|
-
config.mcp ??= {}
|
|
740
|
-
if (!isObject(config.mcp)) return false
|
|
741
|
-
|
|
742
|
-
const added = []
|
|
743
|
-
for (const [name, mcpConfig] of Object.entries(ZAI_MCP_SERVERS)) {
|
|
744
|
-
if (config.mcp[name] === undefined) {
|
|
745
|
-
config.mcp[name] = mcpConfig
|
|
746
|
-
added.push(name)
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
if (added.length > 0) {
|
|
751
|
-
console.log(`[${packageName}] injected ZAI MCP server config: ${added.join(", ")}`)
|
|
752
|
-
console.log(`[${packageName}] note: API keys are not copied into opencode.json; export Z_AI_API_KEY if the MCP server requires it.`)
|
|
753
|
-
return true
|
|
754
|
-
}
|
|
755
750
|
|
|
756
|
-
console.log(`[${packageName}] ZAI MCP server already present — skipping`)
|
|
757
|
-
return false
|
|
758
|
-
}
|
|
759
751
|
|
|
760
752
|
function isRegisteredPluginEntry(entry) {
|
|
761
753
|
if (typeof entry === "string") return isResolvePluginName(entry)
|
|
@@ -879,13 +871,25 @@ async function installCompanion(pkg) {
|
|
|
879
871
|
}
|
|
880
872
|
|
|
881
873
|
async function addCompanionToOpenCodeConfig(pluginEntry) {
|
|
882
|
-
const config = await readOpenCodeConfig()
|
|
883
|
-
config.plugin ??= []
|
|
884
|
-
if (!Array.isArray(config.plugin)) {
|
|
885
|
-
throw new Error(`${opencodeConfigPath}.plugin must be an array`)
|
|
886
|
-
}
|
|
887
874
|
const baseName = stripVersionSuffix(pluginEntry)
|
|
888
|
-
const
|
|
875
|
+
const probe = await readOpenCodeConfig()
|
|
876
|
+
const alreadyPresent = isCompanionPresent(probe, baseName)
|
|
877
|
+
if (alreadyPresent) return
|
|
878
|
+
|
|
879
|
+
const fresh = await readOpenCodeConfig()
|
|
880
|
+
if (!isCompanionPresent(fresh, baseName)) {
|
|
881
|
+
fresh.plugin ??= []
|
|
882
|
+
if (!Array.isArray(fresh.plugin)) {
|
|
883
|
+
throw new Error(`${opencodeConfigPath}.plugin must be an array`)
|
|
884
|
+
}
|
|
885
|
+
fresh.plugin.push(pluginEntry)
|
|
886
|
+
await writeFile(opencodeConfigPath, `${JSON.stringify(fresh, null, 2)}\n`)
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
function isCompanionPresent(config, baseName) {
|
|
891
|
+
if (!Array.isArray(config.plugin)) return false
|
|
892
|
+
return config.plugin.some((entry) => {
|
|
889
893
|
const raw = typeof entry === "string"
|
|
890
894
|
? entry
|
|
891
895
|
: Array.isArray(entry) && typeof entry[0] === "string"
|
|
@@ -893,7 +897,4 @@ async function addCompanionToOpenCodeConfig(pluginEntry) {
|
|
|
893
897
|
: null
|
|
894
898
|
return raw !== null && stripVersionSuffix(raw) === baseName
|
|
895
899
|
})
|
|
896
|
-
if (alreadyPresent) return
|
|
897
|
-
config.plugin.push(pluginEntry)
|
|
898
|
-
await writeFile(opencodeConfigPath, `${JSON.stringify(config, null, 2)}\n`)
|
|
899
900
|
}
|