feat(embedded, ui): support embedding Hunk in host TUIs#309
Conversation
|
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
|
Am I misinterpreting, but does this mean maintaining an internal solidjs fork going forward? Edit (after more than a passing glance): Okay, I guess it's not that bad. Just wondering how we can avoid drift between the React and Solid JS exports. |
9eb8b26 to
cd00647
Compare
Add an embedded session broker availability adapter so embedded sessions start the daemon through the package-provided Hunk CLI. Return snapshots from embedded session open and reload calls so callers can observe reused or refreshed review state directly.
|
@benvinegar I didn't vibe with the internal SolidJS fork either 🤮 and I've since played around with a different approach it now works through
just a bit of clean-up to do here then it should be ready! Screen.Recording.2026-05-22.at.1.14.30.AM-compressed-9.5mb.mp4 |
Move selection, live comments, user notes, and session snapshots into a single review-command state layer shared by the UI and embedded session.
Greptile SummaryThis PR introduces a first-class embedded API (
Confidence Score: 4/5Safe to merge for the embedded-API use case; no data loss on the happy path, and the headless–UI hand-off is well-tested. The ReviewCommandState extraction and the embedded session lifecycle are well-structured. The headless reload path casts a CliInput to EmbeddedHunkSource without conversion, which will silently misbehave if the daemon sends a reload kind that needs special embedded handling. The removeUserNote handler in useReviewController bypasses the updater-based updateCommandState pattern, leaving an inconsistency that could produce a stale state write under React 18 batching. User notes are also silently discarded by persistSessionSnapshot on every UI snapshot flush, meaning they won't survive a panel hide/show cycle. src/embedded/session.ts (headless reload cast and user-note persistence) and src/ui/hooks/useReviewController.ts (removeUserNote state-update pattern) Important Files Changed
Sequence DiagramsequenceDiagram
participant Host as Host TUI
participant Session as EmbeddedHunkSession
participant Mount as mountEmbeddedHunkApp
participant AppHost as AppHost (React)
participant Broker as SessionBrokerClient
participant Daemon as Hunk Daemon
Host->>Session: "createEmbeddedHunkSession({ cwd, source })"
Session->>Broker: start() — register with local daemon
Session-->>Host: EmbeddedHunkSession
Host->>Mount: "mountEmbeddedHunkApp({ session, renderer, container, active })"
Mount->>Mount: createScopedKeyInput + createEmbeddedRendererScope
Mount->>AppHost: render AppHost with bootstrap + initialSessionState
AppHost-->>Mount: "EmbeddedHunkMount { update, unmount }"
Daemon->>Broker: command (comment, navigate, etc.)
Broker->>Session: dispatchCommand(message)
alt UI mounted
Session->>AppHost: mountedBridge.dispatchCommand
AppHost->>Session: hostClient.updateSnapshot
Session->>Session: persistSessionSnapshot
Session->>Broker: brokerClient.updateSnapshot
else headless
Session->>Session: headless state mutation
Session->>Broker: brokerClient.updateSnapshot
end
Host->>Session: session.open(newSource)
Session->>Session: load → setRenderSnapshot
Session-->>AppHost: useSyncExternalStore re-render
AppHost->>AppHost: useEffect → setAppVersion(v+1)
Host->>Mount: mount.unmount()
Mount->>AppHost: root.unmount()
Mount->>Mount: dispose scoped renderer + key input
|
Summary
Playing with Hunk internals for an OpenCode plugin, and turned into a real embedded API instead of a one-off custom route.
hunkdiff/embeddedexport for creating an embedded Hunk session and mounting it inside a host OpenTUI app.show,stash show, file diff, patch, and difftool sources through the same config + loader pipeline as the CLI.hunkdiffbinary.Why
The original goal was to embed
hunkdiffinside OpenCode's TUI. Rather than reaching into renderer internals from the plugin, this gives host TUIs a small supported surface:createEmbeddedHunkSession(...)owns source loading, reloads, snapshots, live comments, notes, and broker registration.mountEmbeddedHunkApp(...)renders the existing Hunk review UI into a host OpenTUI container.LLM use disclosure
I used gpt 5.5 & kimi k2.6 to develop this PR via opencode & pi.
I used gpt 5.5 to draft this PR description and then edited and filtered out some stuff myself.
All diffs were dogfooded with hunk inside opencode via the agent notes feature. Also used plannotator-review for the code tours feature for convenient comprehension.