| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
inception | 4 个月前 | |
feat(models): ship a model without shipping a build, and add Fable 5.1 / GPT-6 Astra / Gemini 3.7 Flash Adding a model meant editing renderer source, type-checking it and cutting a release. It is now one line in docs/model-catalog.json on main: the pickers fetch that file at runtime and every installed copy picks it up within the TTL. The mechanism is the one the Settings hero card already uses, not a new one. src/main/fetchText.ts does the https hop, a total parser validates the SHAPE separately from the JSON, and the result is cached under userData behind a six hour TTL. Applied here: - src/shared/modelCatalogPayload.ts — the catalog types (lifted out of the renderer so main can validate against the same shape) and parseModelCatalog, which never throws and returns null for "keep what you have". - src/main/modelCatalog.ts — fetch, cache, and RE-VALIDATE the cache on read. The cache is a file a previous build wrote; a schema bump or a hand edit must not reach a picker unchecked just because it once passed. - IPC models:catalog, a prewarm in app.whenReady() so the cache is fresh before any modal opens, and the preload bridge. The catalog compiled into the build stays the floor. It is what renders offline, on first launch, and whenever the remote copy is missing, unreadable, or announces a schema version this build does not know. The merge is per PROVIDER: a provider the remote copy names replaces that list, one it omits keeps the built-in list. A bad edit therefore costs a list, never a picker. The payload is data and never markup. Every field lands in an <option> as an escaped text node, and a model id is length-capped and stripped of control characters before it can reach a --model flag on a spawn command line, which is the one genuinely sharp edge on this path. AGENT_MODELS becomes agentModels(). A const array is captured at module load and would still be showing the baked list after a refresh landed. The three new models, with every id read off the CLI that will be invoked with it rather than inferred from a name: - claude-fable-5-1, present in the installed claude binary. No [1m] variant. - gpt-6-astra, from codex-rs/models-manager/models.json at rust-v0.153.2. Note it landed in codex 0.153.1, so an older codex will reject the slug; the catalog's bounds constrain the APP version, not the CLI version, so that cannot be expressed here and the command field stays editable. - Gemini 3.7 Flash High/Medium/Low for antigravity, using agy's display label as the id per the existing verified convention, plus the two Cursor carries. Tests: model-catalog-remote.test.cjs covers junk payloads, prototype pollution, the command-line splice, the caps, and every fallback. The SHIPPED literals in model-catalog.test.cjs and the codex ids in provider-config.test.cjs are updated on purpose — they pin the exact --model values the CLIs are invoked with, so a typo there is a model that silently fails to spawn. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKx1g6LQ6Mmzto5BRY8zLT | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 4 个月前 | ||
| 1 个月前 |