Skip to content

[multi-team P3a] Parse and store the team catalog into UserWorkspaces - #15463

Merged
IsaiahWitzke merged 4 commits into
masterfrom
factory/multi-team-pr3a-catalog-team-scope
Aug 26, 2026
Merged

[multi-team P3a] Parse and store the team catalog into UserWorkspaces#15463
IsaiahWitzke merged 4 commits into
masterfrom
factory/multi-team-pr3a-catalog-team-scope

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Description

Re-split into three, per review. This is PR 1 of a three-PR stack, built directly on master. PR 2 (stacked on this branch) converts the legacy per-user model-list cache into this new storage. PR 3 (stacked on PR 2) moves LLMPreferences off its flat, non-team-aware catalog onto these fields.

Parses and stores the per-team/workspace model catalog into UserWorkspaces. Nothing reads it. LLMPreferences is untouched: it keeps master's flat models_by_feature and behaves exactly as today. This PR is inert by design — dead data plus a conversion test.

  • Team/Workspace gain a feature_model_choice: ModelsByFeature field.
  • crates/graphql's get_workspaces_metadata_for_user query gains teams[].featureModelChoice (the workspace-level featureModelChoice already existed), with the matching schema mirror line.
  • gql_convert::feature_model_choice_from_gql converts the server payload; a malformed catalog is reported and falls back to ModelsByFeature::default() rather than failing the whole Team/Workspace conversion.
  • New feature_model_choice_json sqlite columns (migration included) persist it through the warm-start cache, so the round trip works before any reader exists.
  • team_feature_model_choices_conversion_keeps_each_teams_choice_distinct proves each team's uid maps to its own catalog payload, never a shared or swapped one.

Testing

  • cargo check --workspace --all-targets — clean.
  • cargo clippy -p warp --lib --tests -- -D warnings — clean.
  • ./script/format — clean (no changes).
  • ./script/bundle --channel oss --nouniversal --check-only — clean.
  • cargo clippy --locked --target wasm32-unknown-unknown --profile release-wasm-debug_assertions -- -D warnings — clean.
  • cargo nextest run -p warp -E 'test(gql_convert) or test(user_workspaces) or test(update_manager) or test(team_feature_model_choices)' — 182 passed.
  • No UI surface changed; this is a data-layer change, so no screenshots.

Linked Issue

  • N/A — multi-team catalog placement work.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

@cla-bot cla-bot Bot added the cla-signed label Aug 23, 2026
@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

This PR was generated with Warp.

Comment @warp-factory on this PR to send it follow-up work.

View run View conversation
View run View conversation

@warp-agent-staging
warp-agent-staging Bot force-pushed the factory/multi-team-pr3a-catalog-team-scope branch 2 times, most recently from fc2b37d to 84f9212 Compare August 23, 2026 04:32
@warp-agent-staging
warp-agent-staging Bot force-pushed the factory/multi-team-pr3a-catalog-team-scope branch from 84f9212 to 49ca77f Compare August 24, 2026 22:29
warp-agent-staging Bot added a commit that referenced this pull request Aug 24, 2026
…metadata

Rebuilds #15463 on top of master (its old base, #15461, was closed and
absorbed into #15446).

Partitions LLMPreferences' model catalog by team scope (models_by_team,
keyed by team UID with None as the resolved-teamless scope) so every
catalog accessor takes a TeamScope instead of reading one ambient,
process-wide catalog.

Replaces the standalone per-team catalog fetch (which called
get_feature_model_choices() with no team and wrote the unscoped result
into every team's bucket) with a fold into the existing polled
workspaces-metadata query: get_workspaces_metadata_for_user now selects
teams[].featureModelChoice for the per-team map, plus the existing
workspace-level featureModelChoice for the resolved-teamless case. Both
halves arrive on one response, replacing the broken standalone fetch.

Trigger disposition:
- UserWorkspacesEvent::TeamsChanged no longer triggers a catalog refetch
  (a workspaces response landing now already carries the catalog); it
  still runs local custom-model-preference sanitization.
- Network-online and AuthComplete no longer trigger a separate catalog
  fetch: TeamUpdateManager already restarts its poll on network online,
  and login already kicks off the poller's first tick before
  AuthComplete fires.
- The two ai/blocklist/controller.rs mid-conversation refresh triggers
  are kept as a narrow, single-scope standalone refresh.

Deletes the TODO in llms.rs that asked for exactly this change.
@warp-agent-staging
warp-agent-staging Bot changed the base branch from factory/multi-team-p1b-llms-migration to master August 24, 2026 22:29
@warp-agent-staging warp-agent-staging Bot changed the title [multi-team P3a] Key the model catalog by team, put a TeamScope on the LLMPreferences singleton boundary [multi-team P3a] Key the model catalog by team, fold into the workspaces-metadata query Aug 24, 2026
@warp-agent-staging
warp-agent-staging Bot marked this pull request as ready for review August 24, 2026 22:32
@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

Converting back to draft — under revision following review (eval-build fix plus four blocking findings). Will mark ready again once addressed and CI is green.

@warp-agent-staging
warp-agent-staging Bot marked this pull request as draft August 24, 2026 22:59
@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

@IsaiahWitzke one question for you while this is under revision: the review wants visual proof of two teams resolving different catalogs before merge. That needs a staging account whose teams have genuinely different featureModelChoice settings, which I can't provision. Do you want that capture, and can you point me at such an account — or are the two-team regression tests being added here enough evidence for you?

Responding as wilson: Open session · View in factory

@warp-agent-staging
warp-agent-staging Bot marked this pull request as ready for review August 24, 2026 23:52
warp-agent-staging Bot added a commit that referenced this pull request Aug 26, 2026
…old changes

Reduces this PR to PR 1 of a two-PR stack: the model catalog keyed by
team (models_by_team, ResolvedTeamScope, the scoped models_by_feature
family and its call sites), the fold into the workspaces-metadata
query (apply_feature_model_choices, pruning, leave_team), the
GraphQL query/schema, the two blocklist refresh triggers rerouted off
the unscoped get_feature_model_choices, and the two-team distinctness/
pruning/conversion-level tests.

PR 2 (stacked on this branch) adds get_llm_info_for_scope/for_team_uid
and threads live TeamScope through the AIExecutionProfileAppExt
context-window helpers and RequestParams's request-limit clamp.
@warp-agent-staging
warp-agent-staging Bot force-pushed the factory/multi-team-pr3a-catalog-team-scope branch from f1246dc to 1d8e82a Compare August 26, 2026 04:56
@warp-agent-staging warp-agent-staging Bot changed the title [multi-team P3a] Key the model catalog by team, fold into the workspaces-metadata query [multi-team P3a] Move the model catalog from LLMPreferences to Team/Workspace Aug 26, 2026
Adds Team.feature_model_choice and Workspace.feature_model_choice,
sourced from the server's per-team/workspace Team.featureModelChoice
(new teams[].featureModelChoice query field, schema mirror line) and
the existing Workspace.featureModelChoice, via gql_convert's new
feature_model_choice_from_gql. Persisted through new
feature_model_choice_json sqlite columns (migration included) so the
warm-start cache round-trips it too.

Nothing reads this yet -- LLMPreferences keeps master's flat
models_by_feature and behaves exactly as today. This PR is inert by
design: dead data plus a conversion test
(team_feature_model_choices_conversion_keeps_each_teams_choice_distinct)
proving each team keeps its own payload through the fold.
@warp-agent-staging
warp-agent-staging Bot force-pushed the factory/multi-team-pr3a-catalog-team-scope branch from 1d8e82a to fc3d9d1 Compare August 26, 2026 06:02
@warp-agent-staging warp-agent-staging Bot changed the title [multi-team P3a] Move the model catalog from LLMPreferences to Team/Workspace [multi-team P3a] Parse and store the team catalog into UserWorkspaces Aug 26, 2026
@IsaiahWitzke
IsaiahWitzke enabled auto-merge (squash) August 26, 2026 15:53
… home (#15565)

## Description
Stacked on #15463 (PR 1 of the three-PR stack — "Parse and store the
team catalog into UserWorkspaces"). PR 1 added
`Team`/`Workspace.feature_model_choice` but nothing populates it for a
user restored from a pre-upgrade SQLite cache. PR 3 (to follow, stacked
on this branch) moves `LLMPreferences` off its flat catalog onto these
fields; this PR makes sure a warm-started, pre-upgrade cache has
something real to read once that happens.

Seeds `Team`/`Workspace.feature_model_choice` from the legacy,
pre-team-keyed `MODELS_BY_FEATURE_CACHE_KEY` cache as a one-release
migration in `UserWorkspaces::new`: a `Workspace` restored from the
SQLite cache predates the `feature_model_choice` column (or the app
hasn't fetched since upgrading), so its catalog is still the bare
default. This seeds it from the last-known model list instead, so an
offline launch right after upgrading isn't stuck on just the `auto`
default for the rest of the offline session.

`migrate_legacy_feature_model_choices_cache` understands both real
shapes an older client could have written: the (more recent) single
`ModelsByFeature`, and (older still) a bare `AvailableLLMs`, which
becomes the `agent_mode` field.

Still nothing reads `Team`/`Workspace.feature_model_choice` for model
selection — `LLMPreferences` keeps master's flat `models_by_feature`.
`legacy_cache_migration_yields_a_usable_teamless_catalog` proves the
older bare-`AvailableLLMs` shape migrates to a catalog whose
`agent_mode` bucket resolves the cached model.

## Testing
- `cargo check --workspace --all-targets` — clean.
- `cargo clippy -p warp --lib --tests -- -D warnings` — clean.
- `./script/format` — clean.
- `./script/bundle --channel oss --nouniversal --check-only` — clean.
- `cargo clippy --locked --target wasm32-unknown-unknown --profile
release-wasm-debug_assertions -- -D warnings` — clean.
- `cargo nextest run -p warp -E 'test(user_workspaces) or
test(legacy_cache) or test(gql_convert)'` — 107 passed.
- No UI surface changed; this is a data-layer change, so no screenshots.
- This branch is stacked on a non-default base, so it does not get a
real CI matrix in this repo; the above was run locally on this exact
branch tip.

## Linked Issue
- [x] N/A — stacked continuation of #15463.

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

---------

Co-authored-by: warp-agent-staging[bot] <240773466+warp-agent-staging[bot]@users.noreply.github.com>
Co-authored-by: Oz <oz-agent@warp.dev>
@IsaiahWitzke
IsaiahWitzke disabled auto-merge August 26, 2026 16:43
@IsaiahWitzke IsaiahWitzke reopened this Aug 26, 2026
@IsaiahWitzke
IsaiahWitzke enabled auto-merge (squash) August 26, 2026 16:43
@IsaiahWitzke
IsaiahWitzke merged commit d6a389d into master Aug 26, 2026
41 of 49 checks passed
@IsaiahWitzke
IsaiahWitzke deleted the factory/multi-team-pr3a-catalog-team-scope branch August 26, 2026 17:17
tylerlam-warp added a commit that referenced this pull request Aug 27, 2026
…orkspace (#15567)

## Description
Stacked on #15565 (PR 2), which is stacked on #15463 (PR 1). This is the
third and final PR of the stack: it deletes `LLMPreferences`'s flat,
non-team-aware `models_by_feature` field and its
`MODELS_BY_FEATURE_CACHE_KEY` read/write, and the old
`WorkspacesMetadataResponse.feature_model_choices` field PR 1
deliberately left alone. Every accessor now reads through
`UserWorkspaces` instead, resolved against a caller-supplied `TeamScope`
(or a raw team uid).

- `UserWorkspaces` gains
`feature_model_choice_for_scope`/`_for_team_uid` (reads, via the same
`scoped_or_workspace_setting` pattern every other team-scoped setting
uses; the absent/no-workspace-at-all case falls back to the
resolved-teamless `pre_login_models_by_feature` seeded by PR 1/PR 2's
migration or a pre-login fetch) and
`set_feature_model_choice_for_team_uid` (the narrow one-off
authed-refresh write path).
- `get_llm_info`/`_for_team_uid`/`_for_scope`, `get_active_base_model`,
and the various choice/default getters gained an app/ctx parameter and a
`TeamScope` parameter accordingly, with the ~85 call sites across the
app updated: `terminal/`, `settings_view/`, `ai/blocklist/`,
`ai/agent_sdk/`, `pane_group/`, `search/`, `workspace/`, and
`crates/warp_tui/`.
- Preserves the earlier review-round behavioral fixes carried since PR
1's first draft: teamless eager fetch for `agent_mode_evals` builds,
refresh-through-workspace-metadata (not the unscoped
`get_feature_model_choices`) for blocklist triggers, cross-team
`get_llm_info` display lookups, and stale-bucket eviction (implied by
the wholesale `Team`/`Workspace` replacement on every response).

This is the bulk of the three-PR stack by line count, but every design
decision here — the storage shape, the legacy-cache conversion — was
already reviewed in PR 1 and PR 2; this should read as fan-out from
those two, not new design.

### Note on ancestry
This branch's only ancestors beyond `master` are PR 1's and PR 2's
commits — verified with `git merge-base --is-ancestor` in both
directions before pushing, since a three-deep stack is easy to get
backwards.

## Testing
Since this branch is stacked on a non-default base, it does not get a
real CI matrix in this repo (only PR 1 does); all of the below was run
locally on this exact branch tip:
- `cargo check --workspace --all-targets` — clean.
- `cargo clippy -p warp --lib --tests -- -D warnings` — clean.
- `./script/format` — clean (2 files needed reformatting, included).
- `./script/bundle --channel oss --nouniversal --check-only` — clean.
- `cargo clippy --locked --target wasm32-unknown-unknown --profile
release-wasm-debug_assertions -- -D warnings` — clean (no
dead-code-on-wasm surprises from the call-site fan-out).
- `cargo nextest run -p warp -E 'test(llms) or test(execution_profile)
or test(update_manager) or test(gql_convert) or test(user_workspaces) or
test(profile_model_selector) or test(agent_profiles_page) or
test(legacy_cache)'` — 262 passed.
- `cargo nextest run --workspace -E 'package(warp_tui) and
(test(terminal_session_view) or test(model_menu))'` — 187 passed.
- No UI surface changed; this is a data-layer change, so no screenshots.

## Linked Issue
- [x] N/A — stacked continuation of #15463 and #15565.

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

---------

Co-authored-by: warp-agent-staging[bot] <240773466+warp-agent-staging[bot]@users.noreply.github.com>
Co-authored-by: Oz <oz-agent@warp.dev>
Co-authored-by: Tyler Lam <tyler.lam@warp.dev>
Co-authored-by: Warp <agent@warp.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants