mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-15 17:25:26 -04:00
Cookbook UI: Ollama browser, advanced serve fold, API tokens form, diagnosis toolbar, polish
Surface a lot of accumulated cookbook + UI work as a single non-agent
commit so the agent rework lands cleanly.
Highlights:
- Ollama as a first-class backend in the Cookbook:
* Download input accepts ollama-style names (name:tag) → backend=ollama
* /api/cookbook/ollama/library (cached scrape of ollama.com + curated
fallback so classic models like qwen2.5 stay reachable)
* "Browse Ollama library" toggle below Download with size chips
* Engine=Ollama in hwfit toolbar merges the Ollama library into the
main scan list as per-tag rows with the same Fit/Param/Quant/VRAM
columns; click → fills Download input
- API Tokens form added to Integrations panel (matching wired
loadTokens()/initTokenForm() that had no HTML)
- Serve panel polish: Advanced fold tightening (-8px nudges on vLLM
checks, Extra args, Spec row), n_cpu_moe + Split Mode controls
pulled up 8px to align with the row's checkboxes, GGUF File dropdown
exposed for Ollama backend, GPU re-render on Edit serve restore,
_forceBackend flag so saved serveState wins over backend detection,
cookbook:servers-changed CustomEvent so panels don't need refresh
- Models page redesign: Add Models row (URL + hidden API key reveal +
Type select + Scan/Ollama/Key/Test/Add icon buttons), Probe All +
Clear-offline buttons in Added Models toolbar, offline-pill removed
(opacity already conveys state), Engine dropdown gains Ollama option
- _ping_endpoint probes /v1/models then base, accepts 4xx as
reachable (vLLM returns 404 on bare /v1, fully working endpoints
were showing offline)
- Diagnosis card: × dismiss + Copy bundle buttons restored on the
serve error feedback card
- Orphan tmux sweep re-enabled behind a 60s rate-limit + background
Thread (off the main event loop) so dead serves get discovered
- cookbook_routes auto-register watchdog: drops the endpoint if the
serve session exits non-zero within the first ~3min
- ollama-rocm sidecar awareness in download wrapper (`docker exec
ollama-rocm ollama pull` when host ollama isn't installed)
- Skill extractor sets initial_status="published" when
auto_approve_skills pref is on (audit demotes later)
- Skill list / model list / cookbook scan misc polish
This commit is contained in:
+266
-14
@@ -2048,12 +2048,64 @@ body.bg-pattern-sparkles {
|
||||
.msg-user .body {
|
||||
color: var(--fg);
|
||||
}
|
||||
.msg-ai .body {
|
||||
color: var(--fg);
|
||||
}
|
||||
.rag-sources {
|
||||
margin-top: 12px;
|
||||
border: 1px solid var(--border);
|
||||
.msg-ai .body {
|
||||
color: var(--fg);
|
||||
}
|
||||
.model-endpoint-add-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-left: 7px;
|
||||
padding: 2px 7px;
|
||||
border: 1px solid color-mix(in srgb, var(--red) 34%, var(--border));
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--red) 8%, transparent);
|
||||
color: var(--red);
|
||||
font: inherit;
|
||||
font-size: 0.78em;
|
||||
line-height: 1.45;
|
||||
cursor: pointer;
|
||||
vertical-align: 1px;
|
||||
}
|
||||
.model-endpoint-add-btn:hover {
|
||||
background: color-mix(in srgb, var(--red) 14%, transparent);
|
||||
border-color: color-mix(in srgb, var(--red) 55%, var(--border));
|
||||
}
|
||||
.model-endpoint-add-btn:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.72;
|
||||
}
|
||||
.model-endpoint-add-btn.added {
|
||||
color: var(--color-save-green, #4caf50);
|
||||
border-color: color-mix(in srgb, var(--color-save-green, #4caf50) 45%, var(--border));
|
||||
background: color-mix(in srgb, var(--color-save-green, #4caf50) 9%, transparent);
|
||||
}
|
||||
.task-completed-marker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
margin: 7px 0 2px;
|
||||
padding: 5px 9px;
|
||||
border: 1px solid color-mix(in srgb, var(--color-save-green, #4caf50) 42%, var(--border));
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--color-save-green, #4caf50) 9%, transparent);
|
||||
color: var(--color-save-green, #4caf50);
|
||||
font-size: 0.86em;
|
||||
font-weight: 600;
|
||||
}
|
||||
.task-completed-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
border-radius: 50%;
|
||||
background: color-mix(in srgb, var(--color-save-green, #4caf50) 18%, transparent);
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.rag-sources {
|
||||
margin-top: 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
@@ -2182,7 +2234,7 @@ body.bg-pattern-sparkles {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
z-index: 250;
|
||||
transform-origin: top right;
|
||||
transition: opacity 0.22s ease, transform 0.22s ease;
|
||||
will-change: opacity, transform;
|
||||
@@ -2704,7 +2756,7 @@ body.bg-pattern-sparkles {
|
||||
position: absolute;
|
||||
bottom: calc(100% + 16px);
|
||||
right: 0;
|
||||
z-index: 300;
|
||||
z-index: 250;
|
||||
min-width: 260px;
|
||||
max-width: 360px;
|
||||
background: var(--panel);
|
||||
@@ -8367,6 +8419,14 @@ body.hide-thinking .thinking-section { display: none !important; }
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.thinking-header > .token-new {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thinking-header > div:last-child {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.thinking-header:hover {
|
||||
background: color-mix(in srgb, var(--red) 12%, transparent);
|
||||
}
|
||||
@@ -8382,6 +8442,7 @@ body.hide-thinking .thinking-section { display: none !important; }
|
||||
min-width: 0;
|
||||
}
|
||||
.thinking-header-left span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -8760,6 +8821,22 @@ body.hide-thinking .thinking-section { display: none !important; }
|
||||
.agent-thread-node + .agent-thread-node {
|
||||
margin-top: 2px;
|
||||
}
|
||||
/* Supervisor ladder cards — same chrome as tool cards but tinted so the
|
||||
user can tell at a glance "this is the agent recovering" vs "this is
|
||||
the agent doing work". Stop rung gets the red accent. */
|
||||
.agent-thread-node.supervisor-step .agent-thread-tool {
|
||||
color: color-mix(in srgb, var(--accent, #c08a3e) 80%, var(--fg));
|
||||
font-style: italic;
|
||||
}
|
||||
.agent-thread-node.supervisor-step .agent-thread-dot {
|
||||
background: color-mix(in srgb, var(--accent, #c08a3e) 60%, transparent);
|
||||
}
|
||||
.agent-thread-node.supervisor-step[data-rung="stop"] .agent-thread-tool {
|
||||
color: var(--red, #d65a5a);
|
||||
}
|
||||
.agent-thread-node.supervisor-step[data-rung="stop"] .agent-thread-dot {
|
||||
background: color-mix(in srgb, var(--red, #d65a5a) 60%, transparent);
|
||||
}
|
||||
.agent-thread-dot {
|
||||
position: absolute;
|
||||
left: -20px;
|
||||
@@ -15144,10 +15221,28 @@ body.right-dock-active:not(.email-doc-split-active) .doc-editor-pane {
|
||||
}
|
||||
}
|
||||
|
||||
/* Cookbook's cached-model list should scale with viewport height, not be capped at 400px */
|
||||
/* Cookbook's cached-model list: NO inner-scroll cap. Two nested scroll
|
||||
surfaces (this + the outer .admin-card) trapped the wheel so an expanded
|
||||
serve panel couldn't be reached on tall content. Let the outer
|
||||
.admin-card (overflow-y:auto) be the single scroll surface. */
|
||||
.hwfit-cached-list {
|
||||
max-height: min(75vh, 900px) !important;
|
||||
overflow-y: auto;
|
||||
max-height: none !important;
|
||||
overflow-y: visible !important;
|
||||
}
|
||||
/* Serve panel specifically: the admin-card inline style is
|
||||
`overflow:hidden` (so the toolbar/header don't drift), and the list
|
||||
inside has overflow:visible. On short windows that combination
|
||||
clipped the cards off the bottom with no scrollbar. Make the list
|
||||
itself the scroll surface so the rest of the card stays put. */
|
||||
.cookbook-group[data-backend-group="Serve"] > .admin-card {
|
||||
min-height: 0;
|
||||
}
|
||||
.cookbook-group[data-backend-group="Serve"] > .admin-card > #hwfit-cached-list,
|
||||
.cookbook-group[data-backend-group="Serve"] > .admin-card > .hwfit-cached-list {
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
overflow-y: auto !important;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
/* Drag-and-drop visual hint for the email compose pane. Subtle accent
|
||||
outline + tinted overlay so it's obvious files will attach if dropped. */
|
||||
@@ -17924,8 +18019,11 @@ body.gallery-selecting .gallery-dl-btn,
|
||||
}
|
||||
#cookbook-modal .cookbook-group > .admin-card {
|
||||
min-height: 0;
|
||||
overflow-y: auto !important;
|
||||
overflow-x: hidden !important;
|
||||
/* Let .cookbook-body be the SINGLE scroll surface. Nesting another
|
||||
overflow:auto here trapped the wheel inside the cached-list when a
|
||||
serve panel expanded — the page couldn't scroll past the panel's
|
||||
bottom (Launch button got hidden). */
|
||||
overflow: visible !important;
|
||||
}
|
||||
#cookbook-modal .cookbook-section-body {
|
||||
min-height: 0;
|
||||
@@ -18733,6 +18831,13 @@ body.gallery-selecting .gallery-dl-btn,
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
/* When the Save split sits inside Row 1 (next to GPUs), align it with the
|
||||
input baseline (the row's grid cells stretch top-down; without this the
|
||||
Save buttons sit above the GPU button group). */
|
||||
.hwfit-serve-row .cookbook-serve-slots {
|
||||
align-self: end;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.cookbook-slot-btn {
|
||||
min-width: 22px; height: 22px;
|
||||
padding: 0 6px;
|
||||
@@ -20207,6 +20312,21 @@ body.gallery-selecting .gallery-dl-btn,
|
||||
background: color-mix(in srgb, var(--color-error) 8%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--color-error) 30%, transparent);
|
||||
border-radius: 6px;
|
||||
/* The diagnosis body can carry traceback fragments and long unbroken
|
||||
paths (e.g. /home/.../snapshots/<sha>/<file>.gguf). Without these,
|
||||
a single long token pushes the card wider than the cookbook modal,
|
||||
scrolling the row right and clipping the action buttons. */
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
.cookbook-diagnosis pre,
|
||||
.cookbook-diagnosis code {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
max-width: 100%;
|
||||
}
|
||||
.cookbook-diag-header {
|
||||
display: flex;
|
||||
@@ -20400,6 +20520,14 @@ body.gallery-selecting .gallery-dl-btn,
|
||||
opacity: 0.5;
|
||||
font-family: inherit;
|
||||
}
|
||||
/* Brief border+glow flash when an Ollama row in the hwfit list autofills the
|
||||
Download input — helps the user see what landed when the input is offscreen
|
||||
or above a tall list. */
|
||||
.cookbook-dl-repo.cookbook-dl-flash {
|
||||
border-color: var(--red) !important;
|
||||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--red) 25%, transparent) !important;
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.cookbook-dl-btn {
|
||||
background: var(--accent, var(--red));
|
||||
color: #fff;
|
||||
@@ -22446,6 +22574,88 @@ input.settings-select::placeholder { color: color-mix(in srgb, var(--fg) 35%, tr
|
||||
text-align: right;
|
||||
}
|
||||
.settings-fallback-row .settings-select { flex: 1; min-width: 0; }
|
||||
/* Cookbook Serve Advanced fold — wraps the rarely-touched tuning rows
|
||||
(KV/Attention/Swap/Env for vLLM, llama.cpp batch/cache/split, VRAM
|
||||
monitor, speculative, extra args). Matches the existing .hwfit-panel-
|
||||
advanced look: muted-gray label, no caps, no letter-spacing, no
|
||||
warning-y opacity. Content flows into the parent's existing scroll
|
||||
surface (no inner max-height) and inner rows reset their margin so
|
||||
stacking gaps don't double when the fold opens. */
|
||||
/* Styled to match the Add Models page collapsible sections
|
||||
(.adm-section-toggle) — same border/background/caret pattern, so the
|
||||
two folds across the app read consistently. */
|
||||
details.hwfit-serve-advanced {
|
||||
margin-top: 8px;
|
||||
overflow: visible;
|
||||
}
|
||||
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
color: var(--fg);
|
||||
opacity: 0.8;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 6px 9px;
|
||||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||||
transition: border-color 0.12s, background 0.12s, opacity 0.12s, border-radius 0s;
|
||||
}
|
||||
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary:hover {
|
||||
opacity: 1;
|
||||
border-color: var(--red);
|
||||
background: color-mix(in srgb, var(--red) 8%, transparent);
|
||||
}
|
||||
/* Caret on the right, rotates open/closed. SVG-style rectangles via
|
||||
borders keep this glyph-free + crisp at small sizes. */
|
||||
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary::after {
|
||||
content: '';
|
||||
margin-left: auto;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 4px solid currentColor;
|
||||
border-top: 3px solid transparent;
|
||||
border-bottom: 3px solid transparent;
|
||||
opacity: 0.6;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.18s ease;
|
||||
}
|
||||
details.hwfit-serve-advanced:not([open]) > summary.hwfit-serve-advanced-summary::after {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
/* Body rows below the header — tight rhythm so the fold doesn't
|
||||
feel airy. The cookbook modal's existing .cookbook-body is the
|
||||
scroll surface; nothing inside the fold should add its own scroll. */
|
||||
details.hwfit-serve-advanced[open] > summary.hwfit-serve-advanced-summary {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
details.hwfit-serve-advanced > .hwfit-serve-row,
|
||||
details.hwfit-serve-advanced > .hwfit-serve-checks,
|
||||
details.hwfit-serve-advanced > .hwfit-serve-cmd-wrap,
|
||||
details.hwfit-serve-advanced > .hwfit-serve-extra {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
/* Pull the vLLM/SGLang checks row, Extra args, and the trailing
|
||||
model-specific (Speculative) checks row up tight against the row
|
||||
above — the previous 4px gap plus per-row baseline padding left a
|
||||
~8px gap that read as too airy in the Advanced fold. */
|
||||
details.hwfit-serve-advanced > .hwfit-serve-checks.hwfit-backend-vllm,
|
||||
details.hwfit-serve-advanced > .hwfit-serve-checks.hwfit-backend-sglang,
|
||||
details.hwfit-serve-advanced > .hwfit-serve-extra {
|
||||
margin-top: -8px;
|
||||
}
|
||||
details.hwfit-serve-advanced > .hwfit-serve-row:last-of-type,
|
||||
details.hwfit-serve-advanced > .hwfit-serve-checks:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.settings-fallback-remove {
|
||||
flex-shrink: 0;
|
||||
margin-right: 4px;
|
||||
@@ -22463,6 +22673,9 @@ input.settings-select::placeholder { color: color-mix(in srgb, var(--fg) 35%, tr
|
||||
transition: border-color 0.12s, color 0.12s, background 0.12s;
|
||||
position: relative;
|
||||
top: -6px;
|
||||
/* Glyph baseline trim: nudge × up 1px inside the button without moving the
|
||||
button. line-height < 1 lets the glyph float toward the top of its line box. */
|
||||
line-height: 0.85;
|
||||
}
|
||||
.settings-fallback-remove:hover {
|
||||
border-color: var(--red);
|
||||
@@ -33593,7 +33806,24 @@ button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm:hover .cal-add-label {
|
||||
/* Only the direct-child compose button gets pushed right; nested chips
|
||||
inside #email-lib-accounts pack to the left as normal flex items. */
|
||||
.email-accounts-row > .memory-toolbar-btn { flex-shrink: 0; margin-left: auto; }
|
||||
#email-lib-accounts { justify-content: flex-start; }
|
||||
#email-lib-accounts { justify-content: flex-start; flex-wrap: wrap; }
|
||||
/* Mobile: collapse the account chips to a single horizontally-scrollable
|
||||
strip instead of stacking onto multiple rows. The compose "New" button
|
||||
stays outside the scroller (it's a sibling of #email-lib-accounts inside
|
||||
.email-accounts-row) so it remains pinned on the right. */
|
||||
@media (max-width: 768px) {
|
||||
#email-lib-accounts {
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
scroll-snap-type: x proximity;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
#email-lib-accounts::-webkit-scrollbar { display: none; height: 0; }
|
||||
#email-lib-accounts > * { flex-shrink: 0; scroll-snap-align: start; }
|
||||
}
|
||||
.email-accounts-loading-whirlpool {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
@@ -36198,6 +36428,16 @@ body.theme-frosted .modal {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Mobile: drop the inline icons on Launch + Cancel in the serve panel so
|
||||
the buttons are text-only and don't wrap on narrow screens. Icons stay
|
||||
on desktop where horizontal space isn't tight. */
|
||||
@media (max-width: 600px) {
|
||||
.hwfit-serve-launch > svg,
|
||||
.hwfit-serve-cancel > svg {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule form — mounted inside the cookbook serve panel. Uses the
|
||||
theme tokens (--bg, --panel, --border, --accent, --red) so it
|
||||
matches the rest of the cookbook chrome instead of inline whites. */
|
||||
@@ -36249,6 +36489,18 @@ body.theme-frosted .modal {
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
/* Days field inline with From / Until — push it + the action buttons to
|
||||
the right end of the row so the row reads: From | Until | …gap… | Days | Cancel | Save. */
|
||||
.hwfit-schedule-days-field {
|
||||
margin-left: auto;
|
||||
}
|
||||
.hwfit-schedule-actions-inline {
|
||||
display: inline-flex;
|
||||
align-items: flex-end;
|
||||
gap: 6px;
|
||||
align-self: flex-end;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
.hwfit-sched-day-chip {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
Reference in New Issue
Block a user