th-e7aa17: SEP Phase 6 (smooth) — daemon ui/* relay + smooth-web components#159
Merged
Conversation
…onents
A dispatched operative runs headless, so an extension's ui/* request had
nowhere to render (it got -32001 NoUI). Wire the round-trip:
- smooth-operative: new HttpUiProvider (HostDelegate) relays each ui/* to Big
Smooth over the existing SMOOTH_NARC_URL + SMOOTH_HOST_TOKEN callback channel
(POST /api/ui/request — same channel host_tool uses). Declares the full UI
capability set at handshake when dispatched; falls back to the headless
DefaultHostDelegate on bare local runs. Relay failure degrades to
{cancelled}/{} so a broken daemon never crashes a turn.
- smooth-bigsmooth: /api/ui/{request,answer}. request broadcasts a UiRequest
ServerEvent and, for interactive kinds, parks a oneshot until a frontend
answers (POST /api/ui/answer), times out to {cancelled}, or (no client
connected) cancels immediately. SMOOTH_AUTO_MODE=bypass auto-confirms
policy-covered confirms with an audit entry.
- smooth-web: global UiRelay overlay — modal (select/confirm/input), toast
(notify), chrome (set_status/set_widget/set_title). Render blocks
markdown/keyvalue/progress/table/diff/stack with text fallback.
Also drops the dangling smooth-plugin workspace dep (crate deleted in Phase 5).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 378ad60 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
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.
Problem
SEP Phase 3–5 gave a dispatched operative a live
ExtensionHost, but on the daemon dispatch path it loaded headless with the engine'sDefaultHostDelegate— so any extensionui/*request got-32001 NoUI. Thetodoandpermission-gatedemos couldn't surface a dialog/widget in the browser.What this ships (smooth side of Phase 6)
Round-trip, reusing the
host_toolcallback channel (no new transport, no operative stdin protocol):HttpUiProvider(HostDelegate) relays eachui/*to Big Smooth viaPOST {SMOOTH_NARC_URL}/api/ui/request(bearerSMOOTH_HOST_TOKEN). Wired inload_pretrusted_extension_host: under dispatch it declares the full UI capability set (select/confirm/input/notify/set_status/set_widget/set_title) in modeweb; on a bare local run it falls back to the headlessDefaultHostDelegate. Every other delegate method keeps the engine default (kv → file, exec/session → denied). Relay failure degrades to{cancelled}/{}so a broken daemon never crashes a turn.POST /api/ui/request(operative→daemon, bearer-authed) broadcasts aUiRequestServerEventand, for interactive kinds, parks a oneshot inAppState.ui_pendinguntilPOST /api/ui/answer(frontend→daemon) fires it. Unattended (no client connected) →{cancelled}immediately;SMOOTH_AUTO_MODE=bypass→ auto-confirmconfirm(audited); else waitSMOOTH_UI_TIMEOUT_SECS(default 120s) →{cancelled}. NewUiResolvedevent dismisses the dialog on other clients.UiRelayoverlay (mounted inLayout, own/wssubscription): modal forselect/confirm/input(posts/api/ui/answer), toast fornotify, chrome forset_status/set_title, docked panel forset_widget. Render blocksmarkdown/keyvalue/progress/table/diff/stack, each with the mandatorytextfallback.Also removes the dangling
smooth-pluginworkspace dependency entry (crate deleted in Phase 5).Tests
ui_relay.rs: bearer rejection, one-way returns immediately, no-receivers cancels, live interactive round-trip (park → broadcast → answer → resolve), unknown-request ack. All green (dolt-backed, realAppState).ui_relay_provider.rs: interactive classification, graceful degrade by kind, capability coverage.events.rs: new variants added to the exhaustive serialize test.pnpm build(web) green;cargo fmt --check+cargo clippy --workspace --all-targetsgreen (pre-commit hook).Coordination — smooth-daemon epic (th-c89c2a)
The epic branch
th-c89c2a-smooth-daemonis 121 commits ahead of main and unmerged, and introduces a durable/api/eventsurface + a React control surface (its Phase 4, th-bd0def). This PR builds on current main, not the epic: it rides the event surface main already has (event_txbroadcast →/ws, theaccess/pending pattern) and adds/api/ui/*as additive seams. When the epic lands, theUiRequest/UiResolvedevents can move onto its/api/eventSSE with no protocol change (same JSON frames). No file overlap with the epic's web work beyond mounting one component inLayout.Not in this PR (Phase 6 item 3)
chat-widget
select/confirmbutton-frames on the five smooth-operator servers live in the smooth-operator repo (spec + servers + widget) and ship as a separate PR.🤖 Generated with Claude Code