Repository navigation
Conversation
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 28, 2026 14:48
c2306d8 to
97b3d80
Compare
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 28, 2026 15:20
97b3d80 to
43dc386
Compare
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 29, 2026 04:46
43dc386 to
d6c6d8d
Compare
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 29, 2026 08:45
d6c6d8d to
98d1b2c
Compare
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 29, 2026 10:05
98d1b2c to
6d02203
Compare
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 29, 2026 10:27
6d02203 to
3cd4b3d
Compare
allozaur
force-pushed
the
allozaur/ui/model-configuration
branch
from
September 29, 2026 12:02
3cd4b3d to
09bc1cd
Compare
allozaur
marked this pull request as ready for review
September 29, 2026 16:02
Contributor
There was a problem hiding this comment.
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
Open (14)
Preserve backend-qualified model identity · New Make model drawer responsive on narrow screens · New Preserve load and unload operation state · New Hide Load tab for unsupported backends · New Prevent duplicate stop-string keys · New Label sampling controls for accessibility · New Apply inference overrides to chat requests · New Use backend-aware modality lookup · New Fall back when context length is unavailable · New Add accessible names to number inputs · New Explicitly disable Flash Attention when unchecked · New Serialize keep-in-memory setting correctly · New Pass speculative decoding selection to model loading · New Update outdated manage dialog description · New
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. |
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Overview
Additional information
Requirements