Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9127999
docs(ui): workspace-centric web UI design spec
dkackman Sep 21, 2026
0dca935
docs(ui): workspace-centric UI implementation plan
dkackman Sep 21, 2026
64ba375
feat(ui): route table for workspace-centric hashes with legacy redirects
dkackman Sep 21, 2026
16e9dba
feat(ui): the route is the source of truth for the selected workspace
dkackman Sep 21, 2026
14fbddc
refactor(ui): workspace create/delete and gallery proofs as shared he…
dkackman Sep 21, 2026
469cfb5
feat(ui): sidebar of workspaces, shared and server groups replaces th…
dkackman Sep 21, 2026
44af1de
feat(ui): breadcrumb survives an overview route, drawer is inert off …
dkackman Sep 21, 2026
f2d0ae2
feat(ui): pages link under their workspace; jobs, assets and workflow…
dkackman Sep 21, 2026
a4462fd
fix(ui): examples view population, stale comment, test hash leak
dkackman Sep 21, 2026
f1e59a0
feat(ui): workspace overview page
dkackman Sep 21, 2026
72d1eee
fix(ui): overview panels surface their own load errors
dkackman Sep 21, 2026
a362e6e
feat(ui): server status page carries the all-workspaces queue
dkackman Sep 21, 2026
2cc0925
test(ui): e2e coverage for workspace routes and the sidebar
dkackman Sep 21, 2026
9a3129e
docs(ui): workspace-centric UI - pages by sidebar group; scoping foll…
dkackman Sep 21, 2026
d94be0b
docs(ui): workspaces guide follows the sidebar
dkackman Sep 21, 2026
c8fc91b
fix(ui): deleting a workspace no longer raises the unknown-workspace …
dkackman Sep 21, 2026
34c0ca9
fix(ui): overview jobs panel asks for the running job and the finishe…
dkackman Sep 21, 2026
3bd8c01
fix(ui): unknown-workspace check follows the route, and only speaks w…
dkackman Sep 21, 2026
1c7a84a
fix(ui): docs caption, shared-assets hint copy, and the running link'…
dkackman Sep 21, 2026
a994eb6
Merge branch 'feat/workspace-centric-ui' into develop
dkackman Sep 21, 2026
5cc0415
feat(ui): a workspace switch is shown - sections slide, the name sett…
dkackman Sep 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ own library (so a workspace name shadows a shared one), is tagged `origin:
common` by `GET /api/assets`, and is written to only when a call says so
(`?shared=true` on uploads, `"shared": true` on keep, `shared=True` over MCP).
Reserved names: `workflows`, `prompts`, `assets`, `outputs`, `exports`,
`common`.
`common`. The web UI is organised by workspace, with a sidebar listing every
workspace on the server (`ui/src/lib/Sidebar.svelte`) and the selected one
named in the hash (`#/ws/<name>/...`).

The web UI has a page for it: `ui/src/lib/pages/AssetsPage.svelte` (#165)
reads `GET /api/assets` and shows the library the way the gallery shows
Expand Down
58 changes: 38 additions & 20 deletions docs/SERVER.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,31 @@ load entirely.

## The pages

- **Workflows** — every workflow on the search path (the workspace's own
`--workflow-dir` first, then any `--examples-dir`, read-only), as cards
with descriptions, output kinds, and variable counts. Folders one level
deep become sections. Click through to a run form generated from the
workflow's variables, with the raw JSON alongside. When the server holds
more than one workspace, a picker here chooses which one's workflows are
listed and where a save lands.
- **Prompts** — the prompt library under `--prompt-dir` (default: discovered
The UI is organised by workspace. A sidebar lists every workspace on the
server; the selected one opens into **Overview, Workflows, Jobs, Gallery,
Assets, Editor**, and the hash carries the workspace (`#/ws/studio/gallery`),
so a link names where it points and an old `#/gallery` bookmark redirects to
the last workspace you were in. Below the workspaces, **Shared** holds what
every workspace sees — the prompt library, the `common` asset library and
the read-only example workflows — and **Server** holds Models, Schema and
Status.

- **Overview** — a glance at the workspace: its recent outputs, its recent
jobs, its workflows (ones with a proof first, plus a filled **New
workflow** button), its asset count, and disk usage. Each panel loads and
fails independently, so a slow gallery does not hold the jobs list back
and a panel's own error shows in place of its content rather than reading
as an empty workspace. **Manage** on this page is where a workspace is
deleted (disabled for `default`); a workspace is created from the sidebar.
- **Workflows** — every workflow on the workspace's own search path
(`--workflow-dir`), as cards with descriptions, output kinds, and variable
counts; the read-only ones from an `--examples-dir` are under Shared →
Examples instead, and opening one's Editor there saves a copy into the
current workspace. Folders one level deep become sections. Click through
to a run form generated from the workflow's variables, with the raw JSON
alongside.
- **Prompts** — under Shared: the prompt library under `--prompt-dir`
(default: discovered
the way a CLI run discovers it, then pinned for every job, so the page and
`prompt:` resolution always agree), plus the read-only `prompts/` beside
each `--examples-dir`, so an example's `prompt:` references resolve: stored
Expand All @@ -48,9 +65,8 @@ load entirely.
argument written as `prompt:name` loads the stored text at run time,
and deleting a prompt warns which workflows reference it.
- **Jobs** — the queue and full run history (persisted in
`~/.diffusers_helper/jobs.sqlite`), spanning every workspace with a filter
to narrow to one; each job says which workspace it ran in, and keeps it
through a rerun. A running job streams step-by-step
`~/.diffusers_helper/jobs.sqlite`). A workspace's Jobs page lists its own;
Server → Status lists every workspace's with a filter. A running job streams step-by-step
progress, per-step denoising ticks, what each step is doing when it is not
denoising (loading a model, decoding, saving), and its result files as
they land.
Expand Down Expand Up @@ -110,15 +126,16 @@ load entirely.
upgrade it to GitHub HEAD - new model pipelines usually land there
before a PyPI release. The idle worker restarts on success so the next
job imports the new version; the upgrade is refused while a job runs.
- **Server** — what this server is and how to reach it: device, version,
bind address and LAN addresses, whether a token is required, whether
`/mcp` is mounted (with the `claude mcp add` line to connect to it), the
directories in use, and the workspaces on this server — created and
deleted from here.
- **Schema** — the workflow JSON schema the running server validates
against, as a browsable tree: the document root plus every definition,
with types, required markers, defaults, enums, and descriptions.
`$ref` labels jump to their definition; a filter narrows the list.
- **Server → Status** — what this server is and how to reach it: device,
version, bind address and LAN addresses, whether a token is required,
whether `/mcp` is mounted (with the `claude mcp add` line to connect to
it), and the directories in use — and, below, the queue across every
workspace. Workspaces are created from the sidebar and deleted from their
Overview.

## Workspaces

Expand All @@ -136,11 +153,12 @@ unless one is named.
A workspace is a namespace, not a security boundary: the API token is
all-or-nothing. See [Workspaces](WORKSPACES.md#several-workspaces-on-one-server).

The Server page lists them, creates them, and deletes them - beside the
directories it resolved and the `claude mcp add` line for connecting an agent
from another machine:
The sidebar lists every workspace, and `+ new` there creates one; a
workspace's own Overview page is where it is deleted. Server → Status shows
the resolved directories and the `claude mcp add` line for connecting an
agent from another machine, plus the queue across every workspace:

![The Server page: address picker, generated claude mcp add line, resolved directories, and the workspace list](img/ui-server-dark.png)
![The Server page before the sidebar: address picker, generated claude mcp add line, resolved directories — the workspace list it shows now lives in the sidebar](img/ui-server-dark.png)

## Jobs API

Expand Down
4 changes: 2 additions & 2 deletions docs/WORKSPACES.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,10 @@ pre-workspace call still means what it meant.

| Client | How |
| --- | --- |
| Web UI | The workspace picker on the Workflows and Gallery pages. The choice is remembered in `localStorage`, and the Jobs page adds a filter — job history spans every workspace and says which one each job ran in |
| Web UI | The sidebar lists every workspace; the selected one is named in the hash (`#/ws/<name>/...`), so a link and a reload both land where they say. The choice is remembered in `localStorage` as a fallback for a route that names none (Shared, Server), and Server → Status adds a filter over the all-workspaces queue — job history spans every workspace there and says which one each job ran in |
| MCP | `list_workspaces`, then `use_workspace(name)`. It is a session default rather than an argument on each call, so switching is one visible step in the transcript instead of a flag that can be forgotten on the call where it mattered |
| HTTP | `?workspace=` on the route, or `"workspace"` in a `POST /api/jobs` body |
| Server page | The Workspaces section lists them, creates and deletes them |
| Web UI (create/delete) | The sidebar's `+ new` creates one; a workspace's own Overview page deletes it (disabled for `default`) |

A job carries its own workflow, asset and output directories, so it stays in
the workspace it was submitted from however many others the server serves
Expand Down
Loading
Loading