Add streamer mode to hide custom models from model lists - #2107
Conversation
Streamer mode is a new Settings → General preference. When it is on, the server omits every config.json customModels entry from the execution options catalog, so the web and mobile pickers, plugin pickers, bb provider models, and sdk.providers.models all hide them. Co-Authored-By: Claude <noreply@anthropic.com>
|
🚨 SLOP COP 🚨 · I am the SlopCop. I am reviewing this pull request for security, code quality, performance, architecture, and the user path. I will post one final review after the parallel checks finish. |
| deps.providerRegistry, | ||
| { | ||
| customModels: deps.config.customModels, | ||
| customModels: listVisibleCustomModels(deps), |
There was a problem hiding this comment.
🚨 slopcop/review — Streamer mode changes execution policy, not only model-list presentation.
This catalog also drives thread default resolution and sticky-model recovery. When this filter removes a stored custom model, the web and mobile clients select a catalog default and mark it as explicit. The server can then persist that replacement. A provider whose only usable model comes from customModels can also get an empty internal catalog. Keep the complete catalog for execution policy. Redact only the public presentation result.
| systemConfigQueryKey(), | ||
| allThreadTimelineQueryKeyPrefix(), | ||
| allThreadTimelineTurnSummaryDetailsQueryKeyPrefix(), | ||
| allSystemExecutionOptionsQueryKeyPrefix(), |
There was a problem hiding this comment.
🚨 slopcop/review — Query invalidation does not immediately remove the hidden model data.
The active query and the persistent model-catalog cache keep complete custom model records until a successful refresh replaces them. A slow or failed refresh can still show the private name in the picker. Clear or partition this cache when streamer mode changes. Also mask a raw stored model during the hidden state.
This local invalidation also duplicates the config-changed realtime invalidation. The source window can send two execution-options requests and repeat provider health checks.
There was a problem hiding this comment.
🚨 SLOP COP 🚨 · review
Plain-English summary: This adds a Streamer mode switch. It hides configured custom models from desktop, mobile, CLI, and SDK model lists.
The setting keeps each custom model in config.json. It only removes the model from returned catalogs.
Findings:
-
High: Streamer mode changes execution policy. The filtered catalog also controls thread defaults and sticky-model recovery.
A stored custom model can become the provider default after the next send. A custom-only provider can also lose its only default.
-
Medium: The web cache can keep the private model visible. Query invalidation does not clear active data or the persistent model catalog.
A slow or failed refresh can leave the old name in the picker. The raw stored model can also become the fallback label.
-
Low: The source window can refetch execution options twice. The local invalidation duplicates the server's
config-changedevent.The second request can repeat provider health checks. The model-list memo limits the larger model probe cost.
-
Low: The provider guide still says custom models always appear in the CLI and picker. It does not mention Streamer mode.
Architecture:
- Keep one complete internal catalog for execution and validation.
- Return a separate redacted catalog for public model lists.
- Mask hidden selected models in both clients.
- Clear or partition the browser model cache when Streamer mode changes.
Security: I found no new authentication or authorization issue. The privacy control has the client-state gaps described above.
Verification:
- Three parallel GPT-5.6 agents reviewed security, code quality, architecture, duplication, and performance.
- A final GPT-5.6 review gate confirmed the high and medium findings.
- Doobie changed the real Settings switch in the local app.
- A temporary custom model disappeared from the API when enabled and returned when disabled.
- Turbo type checks passed for the app, server, mobile, domain, and database packages.
- Focused worker tests passed: 36 server tests, 23 app tests, and 8 mobile tests.
git diff --check origin/main...HEADpassed.
Please fix the high and medium issues before merge. I posted this as a comment-only review.
- resolveSystemProviderModels keeps the full custom model list, so a thread created without an explicit model resolves the same default with streamer mode on, and a custom-only provider can still start. - A streamer mode flip clears the localStorage model catalog preload and resets the execution-options queries instead of invalidating them, so no stale list can still name a hidden model while the refetch runs. - Other General settings writes no longer refetch model catalogs; the server's config-changed broadcast already covers that. - Provider guide and skill reference the setting; docs state the composer fallback behavior for a hidden stored selection. Co-Authored-By: Claude <noreply@anthropic.com>
SlopCop follow-up (e2e1a55)
|
Mutation files must not import query keys; the boundary test enforces it. Co-Authored-By: Claude <noreply@anthropic.com>
What was wrong
bb had no way to hide the
customModelsentries from~/.bb/config.json. A user with a private or early-access model id showed it in every model picker during a screen share or stream.What changed
packages/domain/src/app-settings.ts: newstreamerModegeneral setting, defaultfalse. The key/value settings table needs no migration, andbb settings general streamerMode <true|false>works with no CLI change.apps/server/src/services/system/execution-options.ts: newlistVisibleCustomModels(deps)returns[]when streamer mode is on. All threeappendCustomModelscall sites use it, so the web and mobile pickers, plugin pickers,bb provider models, andsdk.providers.modelsall hide the entries. The filter runs after the memoized daemon probe, so a toggle does not re-probe the host. An explicit thread model request bypasses the catalog, so a hidden model still runs when a caller names it.apps/app/src/views/SettingsView.tsx: "Streamer mode" switch in Settings → General, plus story wiring.apps/app/src/hooks/cache-owners/system-cache-effects.ts: a General settings write now also invalidates the execution options queries, so open pickers refetch at once.apps/mobile/src/screens/settings/GeneralSettingsScreen.tsx: the same switch in a Privacy section.docs/configuration.md, thebb guidecustomization template, and the bb-cli skill and its settings reference.No
HOST_DAEMON_PROTOCOL_VERSIONbump. Nothing on the server ↔ daemon wire changed.How you verified
apps/server/test/system/execution-options.test.ts: the catalog shows the custom model, streamer mode on hides it, streamer mode off restores it, and the daemon receives oneprovider.list_modelscall. With the filter removed it fails withexpected [ 'claude-opus-5', …(1) ] to deeply equal [ 'claude-opus-5' ].apps/app/src/hooks/mutations/settings-mutations.test.tsxnow also asserts the execution options query is invalidated.pnpm exec turbo run typecheck --filter=@bb/domain --filter=@bb/db --filter=@bb/server --filter=@bb/app --filter=@bb/mobilepasses.pnpm exec turbo run testfor the settings, migration, CLI, SettingsView, and execution-options test files passes.Fixes #