9.9 KiB
Models and Local ACP — Implementation Record
Purpose
This document records all custom model/ACP enhancements on feat/qimingcode-qimingclaw-builtin that differ from origin/dev. Use it to replay work after future dev merges, or to audit what's custom vs upstream.
Branch Baseline
- Base branch:
dev - Feature branch:
feat/qimingcode-qimingclaw-builtin - Merge strategy: manual replay by batch after each
devmerge, not bulk restore
Batch 1 — Model Source, ACP Session, CLI (COMPLETED 2026-04-27)
1.1 Model Source Loading
New file: src/provider/models-source.ts
Unified model source loader. Priority: cache file → macro → bundled asset → network.
Key design:
FetchModelsOptionsinterface withurl?: stringto respectFlag.OPENCODE_MODELS_URL- Falls back to
"https://models.dev/api.json"when url not provided - Logs source and URL at each hit point for observability
- Uses
Installation.USER_AGENTfor network requests
Modified: src/provider/models.ts
Changes from origin/dev baseline:
fetchApi()deleted — replaced byfetchModelsFromSourceimport { Installation }removed — no longer referencedlastResolvedSourcevariable tracks where data was resolved frombundledPathsrestored for compiled binary support:path.join(path.dirname(process.execPath), "assets", "models.json") // compiled binary path.join(__dirname, "../../assets/models.json") // dev modeData()usesfetchModelsFromSourcewithbundledPaths+url, throws on all-sources-failedrefresh()usesfetchModelsFromSourcewithskipCache: true, updateslastResolvedSourcesourceInfo()export exposes{ source, cachePath, modelsURL, fetchDisabled }for observability- Writes cache file only when source is
"network_fetch"(bundled/macro data is read-only)
Replay checklist for this section:
models-source.tsexists withurlin FetchModelsOptionsbundledPathshas both paths (execPath + __dirname)Data()andrefresh()both usefetchModelsFromSource- No
fetchApifunction orInstallationimport sourceInfo()is exported
1.2 ACP Session Model Caching & Logging
Modified: src/acp/agent.ts
MODEL_CACHE_TTL = 30_000(30s) per-directory model resolution cachedefaultModel()has per-branch structured logging withtotalMstiming:config.defaultModel/memory_cache/user_config_validated/user_config_no_providers/opencode_big_pickle/opencode_best/provider_sort_best/user_config_fallback/hard_fallback
loadSessionModelogsloadSessionMode.model_sourcewith full source metadata- Import:
import { ModelsDev, Provider } from "../provider"
Replay checklist:
modelCacheMap exists with 30s TTL- All
defaultModelreturn paths log source + duration loadSessionModeincludesModelsDev.sourceInfo()log
1.3 TUI Model Interaction
No changes needed — dev baseline is sufficient.
src/cli/cmd/tui/context/local.tsx already has:
- null-safe agent handling (
agent.current()can return undefined) parseModel()local function (replaces removedProvider.parseModelimport)variant.selected()/variant.current()separationFilesystem.readJson/writeJsonfor persistence
1.4 CLI Model Source Display
Modified: src/cli/cmd/models.ts
--verboseflag outputsModelsDev.sourceInfo()fields (source, cache path, URL, fetch status)
Modified: src/cli/cmd/run.ts
- Non-JSON mode shows
~ models source: <source> (<url>)on startup - Import:
import { ModelsDev, Provider } from "../../provider"
Replay checklist:
models --verboseprints source inforunshows source hint in non-JSON mode
1.5 Model Adaptation — Compatible Providers
Modified: src/provider/provider.ts
Three additions to the custom() function:
a) anthropic enhanced with token limit overrides:
- Changed from
Effect.succeedtoEffect.fnUntracedto access env - Injects
max_tokensfromOPENCODE_MAX_TOKENSenv /provider.options.max_tokens - Injects
max_context_tokensfromOPENCODE_MAX_CONTEXT_TOKENSenv /provider.options.max_context_tokens
b) anthropic-compatible loader (new):
- Env:
OPENCODE_ANTHROPIC_API_BASE/ANTHROPIC_BASE_URL,OPENCODE_ANTHROPIC_API_KEY/ANTHROPIC_API_KEY /v1suffix auto-normalizationautoloadgate:!!(baseURL || apiKey)getModelfallback chain:sdk.languageModel(modelID)→sdk(modelID)→ recreate@ai-sdk/anthropic- Includes
max_tokens/max_context_tokenssupport
c) openai-compatible loader (new):
- Env priority:
OPENCODE_OPENAI_API_BASE→OPENCODE_API_BASE→OPENAI_BASE_URL - Env priority:
OPENCODE_OPENAI_API_KEY→OPENCODE_API_KEY→OPENAI_API_KEY autoloadgate:!!(baseURL && apiKey)(both required)getModelfallback chain:sdk.chatModel(modelID)→sdk(modelID)→sdk.languageModel(modelID)→ recreate@ai-sdk/openai-compatible- Includes
max_tokens/max_context_tokenssupport
Replay checklist:
anthropicusesEffect.fnUntraced, has max_tokens/max_context_tokens injectionanthropic-compatibleentry in custom() return objectopenai-compatibleentry in custom() return object- Both have
/v1normalization (anthropic-compatible) or proper env priority (openai-compatible)
Batch 2 — Routes, Skills, Logging (NOT NEEDED)
All files match origin/dev baseline. No custom changes required:
src/server/routes/project.tssrc/server/routes/pty.tssrc/skill/skill.tssrc/util/log.ts
Batch 3 — Tests, Prompts (NOT NEEDED)
All files match origin/dev baseline. No custom changes required:
test/acp/system-prompt.test.tstest/mcp/connection-reuse.test.tstest/provider/env_config.test.tssrc/session/prompt/anthropic-20250930.txtsrc/session/prompt/codex_header.txtsrc/session/prompt/anthropic_spoof.txt
Post-Replay Validation
bun run --cwd packages/opencode typecheck
Acceptance criteria:
- typecheck passes with zero errors
- ACP session init returns model metadata correctly
- local model switching works for provider/model pairs
- invalid model rejected with user-visible warning
- fallback model selected when configured model unavailable
- no unresolved merge markers in repo
Execution Notes
- Keep CI/workflow files on
ours. - Keep
packages/opencode/package.jsonworkspace identity asqimingcode. - Never replay full historical deltas. Replay only behavior-relevant slices.
- After each
devmerge: check this doc, replay unmerged batches, update status.
Change Log
- 2026-04-27: Initial retention document created after merge stabilization.
- 2026-04-27: Batch 1.1 —
models-source.tscreated +models.tsrefactored (unified source loading, bundledPaths, sourceInfo, url configurability, refresh unification, fail-fast). - 2026-04-27: Batch 1.2 — ACP
defaultModelcaching + branch logging +loadSessionMode.model_source. - 2026-04-27: Batch 1.4 — CLI verbose output (
models --verbose,runsource hint). - 2026-04-27: Batch 1.5 — Provider model adaptation:
anthropictoken overrides,anthropic-compatible,openai-compatiblerestored in Effect architecture.
Batch 4 — GitHub CI Build & Release (COMPLETED)
4.1 Build-Release Workflow
New file: .github/workflows/build-release.yml (130 lines)
Dedicated build-release workflow for the fork repo (qiming-ai/qimingcode):
- Tag-triggered cross-compile for 11 platform targets
- Cross-compile darwin-x64 on ARM runner with smoke test + archive handling
- Single runner builds all targets (not matrix)
- Links
@opentui/coreand@opentui/solidsymlinks for build script compatibility - Installs opencode workspace deps before build
- Uses standard GitHub runners (replaces blacksmith runners)
- Windows bash syntax fixed
4.2 Publish Workflow Simplification
Modified: .github/workflows/publish.yml
- Drastically simplified (478 lines removed, 559→81)
- Repository check fixed for
qiming-ai/qimingcode - Release version derived from
package.json, upload loop fixed - Allows release to proceed when some build jobs are cancelled
- Allows publish on
feat/qimingcode-qimingclaw-builtinbranch - Uses
macos-13instead of deprecatedmacos-13-large
4.3 Pre-Push Hook
Modified: .husky/pre-push
- Auto-updates
models.jsonbefore push - Aborts push if models content changed (prevents stale model data)
- Typecheck is non-blocking in pre-push
4.4 Offline Models Loading
New: scripts/update-models.ts
- Update script to fetch latest models from source
New: packages/opencode/assets/models.json
- Bundled models snapshot for offline/compiled binary use
Modified: packages/opencode/package.json
- Added models update script
Replay checklist:
.github/workflows/build-release.ymlexists.github/workflows/publish.ymluses simplified structure.husky/pre-pushhas models auto-update logicscripts/update-models.tsexistspackages/opencode/assets/models.jsonexists
Change Log
- 2026-04-27: Initial retention document created after merge stabilization.
- 2026-04-27: Batch 1.1 —
models-source.tscreated +models.tsrefactored (unified source loading, bundledPaths, sourceInfo, url configurability, refresh unification, fail-fast). - 2026-04-27: Batch 1.2 — ACP
defaultModelcaching + branch logging +loadSessionMode.model_source. - 2026-04-27: Batch 1.4 — CLI verbose output (
models --verbose,runsource hint). - 2026-04-27: Batch 1.5 — Provider model adaptation:
anthropictoken overrides,anthropic-compatible,openai-compatiblerestored in Effect architecture. - 2026-04-27: Batch 4 — CI build-release workflow, publish simplification, pre-push hook, offline models loading.
- 2026-04-27: Batch 1 complete. Typecheck passes. Batches 2 & 3 confirmed no-op.