Skip to content

ui : the model configuration panel - #29587

Closed
allozaur wants to merge 42 commits into
allozaur/ui/providers-settingsfrom
allozaur/ui/model-configuration
Closed

allozaur wants to merge 42 commits into
allozaur/ui/providers-settingsfrom
allozaur/ui/model-configuration

Conversation

@allozaur

Copy link
Copy Markdown
Contributor

Overview

Additional information

Requirements

@allozaur allozaur changed the title allozaur/ui/model configuration ui : the model configuration pane Sep 28, 2026
@allozaur
allozaur added this pull request to stack #29589 September 28, 2026 14:47
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from c2306d8 to 97b3d80 Compare September 28, 2026 14:48
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from 97b3d80 to 43dc386 Compare September 28, 2026 15:20
@allozaur
allozaur removed this pull request from stack #29589 September 28, 2026 15:21
@allozaur
allozaur added this pull request to stack #29594 September 28, 2026 15:24
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from 43dc386 to d6c6d8d Compare September 29, 2026 04:46
@allozaur
allozaur removed this pull request from stack #29594 September 29, 2026 04:55
@allozaur
allozaur added this pull request to stack #29630 September 29, 2026 04:56
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from d6c6d8d to 98d1b2c Compare September 29, 2026 08:45
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from 98d1b2c to 6d02203 Compare September 29, 2026 10:05
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from 6d02203 to 3cd4b3d Compare September 29, 2026 10:27
@allozaur
allozaur removed this pull request from stack #29630 September 29, 2026 10:42
@allozaur
allozaur added this pull request to stack #29646 September 29, 2026 10:43
@allozaur
allozaur force-pushed the allozaur/ui/model-configuration branch from 3cd4b3d to 09bc1cd Compare September 29, 2026 12:02
@allozaur
allozaur removed this pull request from stack #29646 September 29, 2026 12:14
@allozaur
allozaur added this pull request to stack #29653 September 29, 2026 12:15
@allozaur
allozaur marked this pull request as ready for review September 29, 2026 16:02
@allozaur
allozaur requested a review from a team as a code owner September 29, 2026 16:02
Copilot AI balanced review requested due to automatic review settings September 29, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Several controls are not applied, backend identity can be lost, and the drawer has correctness and accessibility issues.

Review effort: Balanced
Findings: 1 High severity · 12 Medium severity · 1 Low severity

Open (14)
What changed in this PR

Adds a model configuration drawer to the models manager with model information, loading controls, and inference settings.

Changes:

  • Adds animated model configuration and information views.
  • Adds load/inference forms and a slider component.
  • Replaces the standalone model information dialog.
File Description
slider/​slider.svelte Adds the slider UI primitive.
slider/​index.ts Exports the slider component.
ModelsManagerModelConfigurationLoad.svelte Adds model-loading controls.
ModelsManagerModelConfigurationInformation.svelte Displays model and server metadata.
ModelsManagerModelConfigurationInference.svelte Adds per-model inference settings.
ModelsManagerModelConfigurationHeader.svelte Adds status and model actions.
ModelsManagerModelConfiguration.svelte Coordinates configuration tabs and data.
ModelsManager.svelte Integrates the animated configuration drawer.
dialogs/​index.ts Updates dialog exports and documentation.
DialogModelInformation.svelte Removes the legacy information dialog.
DialogManageModels.svelte Connects manager actions to dialog closing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +342 to +348
if (modelsStore.isModelLoaded(option.model)) {
await modelsStore.status.unload(option.model);

return;
}

await modelsStore.status.load(option.model, loadExtraArgs(overrides[option.id]));
<div class="pane-drawer shrink-0" data-open={paneOpen}>
<!-- the content box keeps the open width, so it never reflows with the drawer -->
<div
class="pane-content flex h-full min-h-0 w-[30rem] max-w-[30rem] flex-col border-l border-border/40"
Comment on lines +41 to +44
let isLoaded = $derived(
(status === ServerModelStatus.LOADED || status === ServerModelStatus.SLEEPING) &&
!isOperationInProgress
);
<Tabs.List class="w-full">
<Tabs.Trigger value="information">Information</Tabs.Trigger>

<Tabs.Trigger value="load">Load</Tabs.Trigger>
Comment on lines +31 to +34
if (!value) return;

onChange({ ...draft, stopStrings: [...stopStrings, value] });
stopDraft = '';
Comment on lines +38 to +45
{#snippet numberInput(value: number, onInput: (value: number) => void)}
<Input
class="h-8 w-24 text-right text-sm"
min="0"
oninput={(event) => onInput(Number(event.currentTarget.value) || 0)}
type="number"
{value}
/>
Comment on lines +134 to +138
<Switch
checked={load.flashAttention}
class="ml-auto"
onCheckedChange={(checked) => patchLoad({ flashAttention: checked === true })}
/>
</div>

<div class={rowClass}>
<span class="text-sm">Keep Model in Memory</span>
Comment on lines +164 to +170
<select
class="ml-auto h-8 cursor-pointer rounded-md border border-input bg-transparent px-2 text-sm capitalize"
onchange={(event) => patchLoad({ speculativeDecoding: event.currentTarget.value })}
value={load.speculativeDecoding}
>
{#each SPECULATIVE_OPTIONS as value (value)}
<option {value}>{value.replace('-', ' ')}</option>
* ```
*/
/**
* **DialogManageModels** - shell for model management, still to be designed.
allozaur and others added 29 commits October 14, 2026 15:36
Tracked downloads group by repo: the main weights lead and the draft
sidecars ride inside their item as compact sub-lines, on the selector,
the discover list and the manager table. The main model's controls
pause, resume and cancel the whole cluster, and the manager's download
rows select into the configuration pane.

Assisted-by: pi
The table passes its clusters' draft sub-lines to the model rows. A
row's actions cascade pause and resume, an in-flight row offers Cancel
download while a paused one keeps Delete from disk, and the confirm
dialog's copy follows the state.

Assisted-by: pi
Selecting a tracked download opens the pane in a download mode: live
progress with pause, resume and cancel, and See in Discover, instead of
metadata and load actions that a model without files cannot offer.

Assisted-by: pi
ModelsDiscoverDetailsContainer owns the details, tree and readme
fetches so hosts outside the discover view can render the pane, and the
details layout adapts to narrow panes with container queries instead of
viewport breakpoints.

Assisted-by: pi
A main quant download now pulls the quant-matched draft of the most
preferred kind the repo ships (DFlash before MTP), fire-and-forget, so
speculative decoding is ready when the main lands. Manual draft chips
stay available; the options row also collapses to one column in narrow
panes.

Assisted-by: pi
Discover Models starts unchecked. Enabling it turns the Hugging Face
Hub setting on and disabling it turns it back off, so the checkbox
never lies; with discover off the hub setting stays available on its
own for the display data. Stored and reset state are corrected the same
way on load.

Assisted-by: pi
The dialog now opens on the manager instead of returning to the last
view, discover entries still land on the discover view while the
setting allows it, and the discover surfaces follow the setting's
state.

Assisted-by: pi
The sticky search bar insets from the panel edges so the focus ring
stays inside the scroll container, and rows scroll behind an opaque bar
instead of through it.

Assisted-by: pi
An infix or trailing sidecar token is ambiguous: draft heads use it
(Model-MTP-BF16.gguf), so do full models with embedded heads
(Model-Q8D-MTP.gguf). Such a name is a sidecar only next to token-free
main weights of the same family, while mmproj or imatrix anywhere in the
name, or a leading token, decides alone (mmproj_f16.gguf).

A quant tag always carries its bit count, so a sidecar named after no
quant (mtp-Model-it.gguf) gets the bare tag: the listing, the plan and
remove all use it. An imatrix tag resolves into a plan slot of its own,
downloaded but never wired into the params.

remove resolves the tag the way a download does and deletes the partial
files of every planned blob, so cancelling a running download or
dropping one left unfinished by an earlier run leaves nothing on disk.
The router passes its token and releases its lock around the call, and
records the unfinished downloads with an atomic write.

llama download succeeds on a sidecar-only plan and prints its paths.
The models dialog's views become the ModelsDialogView enum, the draft
subline's states join ModelRowDownloadState, the view fade and the
copy-feedback reset move to ui constants, and the dialog's compass
marks come from DISCOVER_ICON.

Assisted-by: pi
The dead openDiscoverModels twin, the commented-out command divider,
the details pane's unused onClose and its header's close button, and a
redundant type cast leave; the command's copy feedback joins the shared
reset constant.

Assisted-by: pi
The comment verbosity the options panel and its chips carried shrinks
to the non-obvious why, and the chat template dialog renders through
SyntaxHighlightedCode as jinja instead of a plain pre block.

Assisted-by: pi
…ords

A non-GGUF file named like a sidecar (quantization-mmproj-Q8_0.json) is
picked as the mmproj, and a sidecar word inside a longer word of a model
name (Phi-2-OmniMatrix.i1-Q4_K_M.gguf) drops the model.
A provider is a server entry with a base url, an optional key, a protocol
and the paths its API lives at; the local llama.cpp server is the built-in
one. Backends persist in settings and the active one is restored on load.
Requests resolve against the active backend, model ids become
backend-qualified, and every backend's model list is fetched and cached in
the background. The manager's helpers learn to read a model's drafts,
context and the provider that serves it.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
Chat goes through protocol adapters, so an OpenAI-compatible endpoint
speaks its own wire format: per-backend paths and headers, the model on
the request, tools kept on the local server, and token counts synthesized
for endpoints that do not stream their own timings. The server store keeps
the local server's props while another provider is active, a conversation
resolves the provider its model belongs to before sending, and the chat
screen never blocks on the local probe when the install has none.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
A provider is added from a preset card or by hand: the dialog probes the
endpoint, reads a refusal as a llama.cpp server that wants a key, and
shows the connection test as a status block. Presets carry their official
artwork and a saved backend keeps its branding through the favicon
fallback. The manager dialog gains its third view, and the settings save
stops clobbering keys that other surfaces write.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The table grows a section per enabled provider, each with its own mark,
error and loading state, and a provider filter with live repo counts.
Rows gain their capability gates back, the draft column with its
use-as-draft action, and the quant badge names the provider on its rows.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The key check reads the providers api url and waits for the server
capabilities, and the model status feed survives tab switches instead
of tearing down on every one. Split from the shell polish: the layout
depends on the providers layer.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The models store derives its list from the backends now, so the drawer
test seeds the active models instead of assigning the derived list, and
runs inside the tooltip provider the app shell supplies.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The active backend of an external provider has no /props, so its role
degrades to MODEL while the selector still has a list to show. The
trigger opened the manager instead of the list.

Gate the trigger on the selectable list instead of the router role.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
A compat backend serves the selection itself and reports no load state,
so the selected model sat inside its provider section, possibly cut off
by the display cap. Give it a leading section of its own, in the
selector list and the manager table, the way loaded models lead the
llama-compat ones.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
A remote provider serves its own template and reports no /props, so the
section would never show one.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The pane passed no canToggleLoad, so the load button defaulted to
visible for models of backends that cannot load or unload.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The status cell branched on the active backend's role, so rows collapsed
to the served-by placeholder once a provider was the selected backend,
and the state lookup resolved the backend by raw-name first match, which
a same-named provider catalog entry shadowed: loading a loaded local
model then failed with 'model is already running'.

Branch the cell per row instead, resolve the state from the local feed
first and the backends' own listings after, and start the local feed
while a remote backend is active: the feed reports the local server's
models, so the local server's role decides.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
The pane shows a model's information, load and inference settings side by
side: what its provider reports, the Hub records it falls back to, the
load controls gated by what the serving backend can do, and the
per-model overrides the load form writes. The slider control arrives
with it.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
A row click slides the pane in as a fixed-width drawer: the toolbar's
calls to action leave first, the pane is laid out before its first open,
and a model switch fades one out and the next in. The model information
dialog folds into the pane's information tab, and a chat started from
the pane closes the manager and focuses the composer.

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
Serve the recommended MCP server favicons and the Hugging Face badge from
the app's base path, not the domain root, so they resolve when the app is
mounted under a path. Also normalizes the safe HTML config indentation.

Assisted-by: pi:GLM-5.3-Flash
The tool groups in the add menu expand with a measured height
transition instead of a Collapsible, so the rows animate in every
browser, and collapsed rows leave the tab order.

Assisted-by: pi
It sat pinned just above the pane's edge on a phone, where the actions bar below
it is the only thing that should stay put.

Assisted-by: pi (zai-org/GLM-5.3-Flash)
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.

3 participants