Skip to content

fix: resolve internal/background roles' model against owner BYO config - #22

Merged
RowitZou merged 1 commit into
mainfrom
feature/byo-internal-models
Jun 26, 2026
Merged

fix: resolve internal/background roles' model against owner BYO config#22
RowitZou merged 1 commit into
mainfrom
feature/byo-internal-models

Conversation

@RowitZou

Copy link
Copy Markdown
Owner

问题

纯 per-user BYO 部署(admin 全局 config 不配任何 model/endpoint,每个用户自带 BYO)下,后台/内部角色一调模型就 No model is configured / Registered: (none)

  • [memory] extraction failed: No model is configured ... Registered: (none).
  • [auto-dream] retry-attempt user=... result=fired(拿空 config 空转重试)

根因:memoryExtractor / memoryCurator、background fire、以及 imageRead / webSearch / compact 这些 sub-LLM 解析模型时读的是全局 admin config,而不是触发它们那个用户的 resolved config(含 BYO)。用户自己的 DM 不受影响,因为 runner 已经把 resolveUserConfig(userId, getConfig())appConfig 传进 query()

改动

把"按 owner 解析模型"这条不变量立全:

  • dispatched-agent.ts(中心 chokepoint,所有 worker / internal / bg fire 都经过):resolveUserConfig(canonicalUser, config)query() 的 config + childCtx.config。后者让 dispatched agent 内的 getSessionConfig()(imageRead / webSearch sub-LLM、用户 lang / permissionMode)也认 owner BYO。
  • run-subagent.ts:在 getProviderFor 预检(真正抛出 extraction / dream 错误的那行)之前先按 owner 解析。
  • api.ts:imageRead / webSearch / describe sub-LLM 的 getConfig() fallback → getSessionConfig()

resolveUserConfig 是幂等的并集 merge,已解析的 config 再过一次是 no-op;没 BYO 的用户 + 空 admin base = 那个用户确实没模型(清晰报错,不偷偷兜底)。

测试

回归测试 dispatched-agent.test.ts:空 admin base + 磁盘上的 user BYO model → query() 收到的 config 和 dispatched session-context 都带 owner BYO model。旧码上 fail(got [],新码通过。全量 pnpm test 2606/2606 通过,pnpm typecheck 干净。

🤖 Generated with Claude Code

…st owner BYO

Internal roles (memoryExtractor / memoryCurator), background fires, and the
imageRead / webSearch / compact sub-LLMs resolved their model against the
global admin config. In a BYO-only deployment (admin base has zero models,
each user brings their own), that yields an empty registry and fails with
"No model is configured / Registered: (none)" — breaking memory extraction,
auto-dream, and any background work, while the user's own DM keeps working
via its per-session resolved config.

Resolve against the OWNER's config everywhere a dispatched agent or sub-LLM
selects a model:
- dispatched-agent.ts: resolveUserConfig(canonicalUser, config) feeds query +
  childCtx.config — the single chokepoint every worker / internal / bg fire
  flows through (also fixes getSessionConfig()-driven imageRead / webSearch).
- run-subagent.ts: resolve owner config before the getProviderFor precheck
  that actually threw the extraction / dream error.
- api.ts: imageRead / webSearch / describe sub-LLM fallbacks getConfig() ->
  getSessionConfig() so they honor the session's resolved BYO.

resolveUserConfig is an idempotent union merge, so passing an already-resolved
config back through it is a no-op.

Regression test (dispatched-agent.test.ts): empty admin base + on-disk user
BYO model -> the config handed to query() and the dispatched session-context
both carry the owner BYO model. Fails on old code with `got []`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 26, 2026 08:44
@RowitZou
RowitZou merged commit 71a6274 into main Jun 26, 2026
1 check passed
@RowitZou
RowitZou deleted the feature/byo-internal-models branch June 26, 2026 08:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes BYO-only deployments where internal/background roles and sub-LLM modules (imageRead/webSearch/compact/etc.) were resolving models against the global admin config (which may have an empty model registry) instead of the owning user’s resolved config (including BYO endpoints/models).

Changes:

  • Route API fallbacks for model-dependent helpers through getSessionConfig() so sub-LLM calls honor the session’s resolved (owner) config.
  • Resolve owner config earlier for subagent execution to prevent provider/model selection from failing on empty admin registries.
  • Ensure dispatched agents pass owner-resolved config into query() and the dispatched session context, plus add a regression test for BYO-only behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/api.ts Uses session-resolved config as the fallback for streamChat/describe/transcribe/web-summarize model resolution.
src/agents/run-subagent.ts Resolves the model registry against the owner before role-model resolution/provider selection.
src/agents/dispatched-agent.ts Resolves dispatched agent execution config against owner BYO and pins dispatched session context to that config.
src/agents/dispatched-agent.test.ts Adds regression coverage for BYO-only deployments (empty admin base + per-user BYO).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +112 to +114
const effectiveConfig = params.canonicalUser
? resolveUserConfig(params.canonicalUser, params.config)
: params.config
Comment on lines +112 to +114
const effectiveConfig = params.canonicalUser
? resolveUserConfig(params.canonicalUser, params.config)
: params.config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants