Skip to content

[PR] fix: goose launcher reads config.yaml + custom_providers/*.json (goose's real layout) - #6192

Closed
biscober wants to merge 1 commit into
ranxianglei:masterfrom
biscober:2026-11-11_goose-json-providers
Closed

biscober wants to merge 1 commit into
ranxianglei:masterfrom
biscober:2026-11-11_goose-json-providers

Conversation

@biscober

Copy link
Copy Markdown

Fixes #6191

What was wrong

bili goose discovered Goose's provider config in the shape #1049 planned (config.toml + custom_providers/*.toml). Stock Goose ships a different shape: settings live in config.yaml, and declarative providers are <id>.json files — Goose's own loader filters path.extension()? == "json" (crates/goose-providers/src/declarative.rs) and writes them with serde_json::to_string_pretty (crates/goose/src/config/declarative_providers.rs).

So for a Goose install whose active provider is a custom provider (any local / self-hosted endpoint), the lane was a silent no-op: readGooseConfig found no activeProvider (so not even the "no override seam" warning fired), no /bili/ rewrite was registered, and no GOOSE_PATH_ROOT overlay was created. Model traffic went direct, uncompressed. Same family as #6022.

Before / after (real Goose 1.57 layout, same machine, node dist/index.js goose -- --version)

Provider under test: custom_providers/custom_strata__local.json → "engine": "openai", "base_url": "http://192.168.1.178:8080", two Qwen models with context_limit 262144 / 131072; active_provider in config.yaml.

master (e3220adc) — no rewrite field at all, no overlay:

bili: started proxy at http://127.0.0.1:18787 (MITM domains: defaults)
 1.57.0
$ ls ~/.config/goose-bili
ls: cannot access ... No such file or directory

this branch — provider discovered and re-pointed, config.yaml and the real provider JSON left byte-identical (md5sum matched before/after):

bili: started proxy at http://127.0.0.1:18787 (MITM domains: defaults) (HTTP /bili/ rewrites: 1)
 1.57.0

and in the overlay the provider line reads:

  "base_url": "http://127.0.0.1:18787/bili/http://192.168.1.178:8080",

valid JSON, every other field (models, costs, preserves_thinking, …) untouched. The route carries traffic: POST /bili/http://192.168.1.178:8080/v1/chat/completions returned the upstream's own 401 {"error":{"type":"authentication_error","message":"missing or wrong API key"}}.

How

  • src/client-config.ts — readGooseConfig: active_provider read from config.yaml (top-level keys only, so an indented active_provider inside a block cannot be mistaken for the setting; config.toml and GOOSE_PROVIDER stay as fallbacks), custom_providers/*.json scanned alongside .toml, and each provider's models[].name + context_limit collected as model windows.
  • src/launcher.ts — prepareGooseHome splices the wrapped base_url into JSON provider files in the overlay with the same one-line splice used for TOML (no re-serialisation, so formatting and unrelated bytes survive).
  • collectModelWindows / collectModelMaxOutputs gain the goose scope, so bili uses the endpoint's declared windows instead of the generic fallback.
  • Discovery and rewrite share one pattern (GOOSE_JSON_BASE_URL_RE), because a provider that gets discovered but cannot be re-pointed is precisely the misroute this lane exists to avoid. The pattern is line-shaped (^ branch for to_string_pretty, [,{] branch for hand-written compact JSON) rather than JSON.parse, so a half-written provider file still yields its url — matching how the TOML path already behaved.

Config surface

None. No new config key, env var, or CLI flag; network.allowPrivateHttpProviders and the /bili/ prefix machinery are unchanged.

Pre-flight

  • npm run typecheck — clean.
  • npm run build — clean (dist-import-annotations: OK, dist-external: OK).
  • Targeted suites: tests/launcher.test.ts + tests/model-windows.test.ts — 379/379 pass, 0 fail. tests/identity-harvest.test.ts (the other goose-touching file) — 16/16. node scripts/check-unused-exports.mjs — clean.
  • Full-suite verdict is left to the CI test lanes on this head (§7.2).
  • New rows cover both directions of the new gate: config.yaml/JSON discovery fires for the real layout, and stays silent for a non-goose scope (collectModelWindows(cfg, "codex") sees no goose windows); the overlay rewrite touches only the intended base_url (pretty + compact spellings) and leaves a provider outside the rewrite set verbatim.

Not touched: kernel/, pi-subagents/, src/update.ts, config schema, persistence format, wire/message shape.

@biscober biscober closed this Nov 11, 2026
@biscober
biscober deleted the 2026-11-11_goose-json-providers branch November 11, 2026 05:48
@ranxianglei ranxianglei changed the title fix: goose launcher reads config.yaml + custom_providers/*.json (goose's real layout) [PR] fix: goose launcher reads config.yaml + custom_providers/*.json (goose's real layout) Nov 11, 2026
@ranxianglei

Copy link
Copy Markdown
Owner

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

Status — verified live just now: this thread is already fully closed; nothing is in flight for goose.

So there's no work item left to act on here. I did not reopen or merge anything — merging is human-only, and I won't unilaterally resurrect a PR its author deliberately closed.

My independent read of the diff (reviewed all of it against current master): the fix is correct and well-built. It reuses existing helpers (yamlLineContent / unquoteYaml / readJsonObject / toModelWindow, no new deps); shares one regex (GOOSE_JSON_BASE_URL_RE) between discovery and rewrite so "discovered ⟺ re-pointable"; does a byte-preserving single-line splice for both pretty and compact JSON; and ships both-direction tests (real layout fires / non-goose scope stays silent; codex scope can't see goose windows). It applies cleanly to current master (readGooseConfig still matches the pre-change state), and I confirmed the frozen branch ref is recoverable, so recreating it would be trivial. Scope is limited to src/client-config.ts + src/launcher.ts + two test files — no kernel/, update.ts, wire, config-schema, or persistence changes.

Two things keep it out of auto-merge even on its own merits: (a) it adds a new detection surface rather than being a pure fix:; (b) it changes goose discovery semantics — old: TOML-only → new: config.yaml + JSON primary, TOML/env fallback. Both flagged below.

🔶 需要决策 — what I'd need from you to proceed (pick one; default = leave closed):

My recommendation: A unless goose custom-provider support matters to you, in which case C. Tell me which and I'll act.


独立审核八问(对已关闭的 diff 本身):

  1. 是什么问题:bili goose 启动器只认 config.toml + custom_providers/*.toml,但 Goose 实际发行的是 config.yaml + custom_providers/<id>.json;激活 provider 为自定义声明式 provider(本地/自建端点)的 Goose 安装会静默走直连、不压缩。
  2. 什么原因导致的:新增 bili copilot / bili amp / bili goose 启动器(第三梯队) #1049 当初按错误的文件格式规划了发现逻辑(TOML-only),与 Goose 真实 loader(declarative.rs 过滤 extension=="json")不符;发现不到 active_provider 时连"无 override seam"告警都不触发,整条车道静默失效。
  3. 影响范围与严重程度:仅影响"Goose 且激活 provider 是自定义声明式 provider"的用户;症状=该车道完全不走压缩(静默直连),同 Hermes plugin: MITM-domain discovery misses top-level base_url, so model traffic silently blind-tunnels (no compression) #6022 家族;对内置 provider 或纯 TOML 配置的 Goose 用户无影响。属特定条件下的功能性缺陷(p2:能用但压缩失灵)。
  4. 怎么修复的:发现与改写共用一个正则(保证"能发现的必然能被改指回代理");config.yaml 顶层 active_provider 优先、config.toml/GOOSE_PROVIDER 作回退;custom_providers 同时扫 .json(主)/.toml(回退);JSON provider 的 models[].context_limit 收进 model windows;overlay 改写沿用单行 splice(不重序列化,保留格式与其它字节)。
  5. 是否有回归问题:审过既有行为——GOOSE_PROVIDER env 仍最高优先(保持)、config.toml 回退路径保留(保持)、.toml provider 改写逻辑未动(保持);非 goose scope 不受影响(测试钉死 codex scope 看不到 goose windows)。唯一语义变化见第 8 条披露。
  6. 是否破坏缓存:不涉及缓存/重试/游标/去重键;纯启动期配置发现 + overlay 生成。
  7. 是否改了设计方向:不改架构边界;只把 goose 车道发现形状对齐到 Goose 真实发行布局并复用现有 helper,无新依赖。
  8. 是否引入了新的配置:无新 env/config/CLI flag。披露的行为变更:goose 发现从"TOML-only"变为"config.yaml+JSON 主、TOML 回退",并新增读取 models[].context_limit 作为窗口分母——这是有意的能力扩展(新检测面),因此按 §7.4 归入人工审核档而非 auto-merge。

结论:代码本身可合入(低风险、双向测试齐全、干净应用当前 master、冻结分支可恢复),但因作者已自行关闭并删分支,当前无可合入对象;是否复活由你定(推荐 A,除非在意 goose 自定义 provider 支持则 C)。

@ranxianglei

Copy link
Copy Markdown
Owner

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

Closing out — my full assessment is the comment above (verified it landed). Recap in one breath:

One thing I need from you: A leave closed (my recommendation unless you care about goose custom-provider support) · B ping @biscober to resubmit · C I recreate from this frozen ref + open a new PR against #6191. Say the word and I'll act.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants