Skip to content

Desktop overhaul: workspace tabs, settings, queued prompts, and resume after restart - #98

Merged
sanchitrk merged 27 commits into
canaryfrom
desktop-overhaul-ui
Oct 24, 2026
Merged

sanchitrk merged 27 commits into
canaryfrom
desktop-overhaul-ui

Conversation

@sanchitrk

@sanchitrk sanchitrk commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Desktop UI overhaul, plus two harness features it surfaces: editable queued prompts (steers and follow-ups), and resuming runs that a crash or shutdown cut off.

Harness and server (@codeworksh/harness, @codeworksh/cli)

  • Queued prompts can be listed, cancelled and changed before the agent takes them in: the session.queue, session.cancel and session.update RPCs. A cancel is a durable session.prompt.cancelled event that marks the row instead of deleting it, so a promotion already in flight loses. An update moves a prompt to the other lane or rewrites it in place; moving it to the steer lane wakes the session.
  • Resume after restart. The session records an unfinished run (execution: running, or closed after a shutdown) and counts crash restarts. A committed turn resets the count. codework serve resumes marked sessions at startup, parks a session after 5 restarts (parked in session info), and answers the cut-off reply before queued follow-ups. A user stop is never resumed; Ctrl+C on a local codework run counts as one.
  • Promotion steps back, instead of failing the drain, when its prompt was changed, cancelled or re-sent after it was selected. A turn started for a prompt cancelled just before promotion makes no provider request.

Desktop (apps/web, apps/widget)

  • Workspace tabs: a close button on hover, a fixed window icon (the stored workspace icon and its picker are removed), one-line titles taken from the focused widget, and titles kept across restarts.
  • Session frame header shows the project badge used in the sidebar.
  • A queue strip above the session composer: steer or send now, move to follow-up, edit in place, back to composer, remove. It stays visible after a stop or failure, shows a count past 3 and scrolls past 4.
  • Settings: integrated with the desktop shell, with internal scrolling for the providers list and detail. Plus a text scale and theme radii instead of arbitrary values, a shared prompt composer, a startup splash, and a New session button.

Tests and docs

  • No test uses the deprecated gpt-5.5; tests use gpt-6-luna.
  • New harness tests for queue races (cancel, update, re-admit against promotion) and resume (crash, shutdown, stop, parking, restart-count reset). Each was checked to fail with its fix removed.
  • CHANGELOG.md Unreleased covers the harness, cli and aikit changes.

Test plan

  • vp check and vp run typecheck
  • Harness and codework suites; the only failures are live Anthropic tests (no credits)
  • Live in the Electron app: queue strip actions, steer/follow-up ordering, cancel, and the strip staying put after Stop
  • Real crash: kill -9 the server mid-turn and start it again. The session resumed by itself and finished (three runs).

Known limits: tool calls may run twice after a crash (at-least-once), and two very narrow stop-timing races remain; neither loses a prompt.

🤖 Generated with Claude Code

sanchitrk and others added 27 commits October 23, 2026 13:12
Show the logo in the saved theme until the first route loads, turn it into
a reload prompt if the app fails to load, and keep the desktop window hidden
until its first paint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Starts on the start page in the current session's project; drops the model line from session rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Workspace tabs show a close button on hover; closing deletes the
  workspace without a confirm and moves to a neighbouring tab.
- Tabs always show the window icon; the workspace icon, its settings
  picker and the stored column are removed.
- Session frames show the project's badge, as in the sessions sidebar;
  frame icons accept an element as well as a Lucide icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Side by side, the providers card keeps a fixed height and each pane
scrolls inside it; stacked, the page scrolls as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gpt-5.5 is out of the live OpenAI model list, its thinking-levels
artifact and every stubbed test. The thinking wire test gives its
gpt-6-luna model the catalog's thinking map, since GPT-6 takes no
minimal effort.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Prompts admitted but not yet promoted can now be read, withdrawn and
changed before the agent takes them in:

- session.queue lists them, both lanes, in admission order.
- session.cancel withdraws one through a durable session.prompt.cancelled
  event. The row is kept and marked cancelled_seq, so a promotion already
  in flight loses rather than appending it; a cancelled id may be sent
  again.
- session.update moves one to the other lane or rewrites it in place
  through session.prompt.updated, carrying only the changed fields.
  Moving to the steer lane wakes the session, so a prompt left by a stop
  runs now.

A promotion that finds its prompt changed, cancelled or re-admitted since
selection steps back instead of failing the drain, and a turn started for
a prompt that was cancelled before promotion makes no provider request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A strip tucked behind the composer lists the prompts waiting to join the
conversation, while the agent works and after a stop or failure leaves
them parked. Past three it shows a count; past four it scrolls. Each row
can steer now (or send now while idle), move to the follow-up lane, be
edited in place, go back to the composer, or be removed.

The transcript stays at its end as the strip grows or shrinks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like Pi, work cut off by a crash or a shutdown resumes when the server
starts again. The session table records a run as unfinished (execution:
running, or closed after a shutdown) and counts the restarts a crash
causes; a committed turn starts the count over.

- Control marks a session running before every wake, so an accepted
  prompt survives a crash before its run starts.
- A run's end clears the mark: a finished run unless prompts are still
  pending, a user stop unless a prompt came after it. A shutdown leaves
  it closed.
- At startup the codework server claims each marked session atomically,
  counting a restart for a crash, and resumes it. At five restarts the
  session is parked instead; session.info reports it, and its next
  prompt runs it again. A recovered run does nothing if a stop cleared
  the mark meanwhile, and answers the reply it was cut off in before a
  queued follow-up goes in.
- Ctrl+C on a local `codework run` is a user stop, so it is not resumed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With @types/json-schema reachable, the provider's JSONSchema7 is no longer
any, and the inferred `type: string` schemas stop matching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shadcn/lint's no-unknown-classes and no-raw-colors gate vp check for
apps/web, outside shadcn's components/ui. `vp run lint:tailwind` adds
no-arbitrary-values, no-restyle, require-static-classes and Tailwind's
canonical class names (eslint-plugin-better-tailwindcss) until each is
clean enough to join them.

Classes rewritten to their canonical names; the generated CSS is the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like t3code, sizes below Tailwind's xs are theme tokens (text-2xs, 3xs,
4xs, with their line heights); 12px and 14px text uses text-xs and
text-sm, 13px moves up to text-sm and 15px headings to text-base. Exact
radii become rounded-sm/md/lg/2xl; the title bar's nested radii move to
xl/lg/md and stay concentric. One-off shadows, gradients, the queue fade
and inline code size are allow-listed in no-arbitrary-values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PromptComposer, ComposerHeader and ComposerSubmit give the start page's
New Session box and a session's Reply box the same surface, header and
submit button, instead of each building its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A widget's setTab now takes one string, such as "Project / Title", and
the tab shortens it at its end to fit; the full text is in its tooltip.
The session sets its project and title, so the tab names both again. A
frame moved to a new workspace still names it for its project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A workspace stores what its tab last read (a new nullable tab column),
saved through workspaces.update when its focused frame sets a new one.
After a restart, a workspace not opened yet shows that title instead of
only its name, until its frame sets a fresh one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
modelgen omits providers with no models, so a snapshot without OpenAI
entries has no openai-codex entry at all rather than an empty one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Queued-prompt list, cancel and update, resume after restart, the
local Ctrl+C stop, and modelgen leaving out empty providers. Also
restores the Unreleased heading the format note had swallowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments say what the code does and why, without naming the projects
it was compared against.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit's comment rewording was meant for the TypeScript
packages only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sanchitrk
sanchitrk merged commit e7df22a into canary Oct 24, 2026
2 checks passed
@sanchitrk
sanchitrk deleted the desktop-overhaul-ui branch October 24, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant