Finish the mobile performance pass

- Cache the model catalog once per user and each conversation's setting
  separately; clear both on logout and after model saves
- Compress hashed assets asynchronously with a byte budget and set Vary
- Memoize message parsing and throttle selection reads
- Debounce draft writes to localStorage
- Keep the composer editor on the page and focused, as before
- Add a bundle budget check and run it in CI
- Show a loading block while sessions load and a workspace avatar in the
  mobile conversation header
This commit is contained in:
2026-10-20 14:37:11 +01:00
parent c1a94fc9a5
commit 4f7e0a6bf0
38 changed files with 1320 additions and 334 deletions
+49
View File
@@ -340,6 +340,55 @@ export type HarnessOverviewPayload = {
harnesses: HarnessOverview[];
};
/**
* The install-wide part of a harness overview: what it is for and the
* models it can pick. Every bot and workspace shares it, so the models
* modal caches one copy per user.
*/
export type HarnessCatalog = Pick<
HarnessOverview,
| "harness"
| "title"
| "description"
| "required"
| "automatic"
| "providers"
| "models"
>;
export type HarnessCatalogPayload = {
harnesses: HarnessCatalog[];
};
/**
* The per-bot (or per-workspace) part of a harness overview: the setting,
* what it runs on now, and what the default runs on.
*/
export type HarnessSettingOverview = Omit<
HarnessOverview,
| "title"
| "description"
| "required"
| "automatic"
| "providers"
| "models"
> & {
/**
* A picked model the catalog no longer lists (its provider dropped it).
* The merge adds it back so the form can show and keep it.
*/
pinned_model?: HarnessModelOption;
/**
* The provider the setting is limited to when the catalog has no model
* from it, so the form still shows the limit.
*/
unavailable_provider?: HarnessProviderChoice;
};
export type BotHarnessSettingsPayload = {
harnesses: HarnessSettingOverview[];
};
/**
* An env as the Environment settings page sees it. `value` is sent only
* for non-secret envs; secrets are replaced, never read back.