feat(desktop): wire pi terminal agent to notification hooks#1
Closed
garritfra wants to merge 1 commit into
Closed
Conversation
Follow-up to superset-sh#2562, which added pi as a built-in agent (preset, command, icon, settings UI, docs). This PR adds the corresponding notification-hook integration in apps/desktop/src/main/lib/agent-setup/, so pi participates in the same Start/Stop/PostToolUse lifecycle that drives Superset's working indicator and completion chime for claude, codex, gemini, cursor, copilot, opencode, mastra, amp, and droid. Mechanism: ship a small TypeScript pi extension to the global pi extensions directory (~/.pi/agent/extensions/superset-hooks.ts). The extension subscribes to pi's lifecycle events and spawns notify.sh with Claude-Code-format hook_event_name JSON payloads, which the existing notify.sh dispatcher already speaks natively — no per-agent translator shim needed. Mapping: pi before_agent_start → UserPromptSubmit → Superset Start pi tool_execution_end → PostToolUse → progress pi agent_end → Stop → completion / chime pi session_shutdown → Stop → cleanup on Ctrl+C, /quit, /reload Subagent flicker is prevented by gating every event on ctx.hasUI === false (strict equality, so older pi versions where hasUI is undefined still fire). Structurally identical to the opencode integration: template file + wrapper module + barrel re-export + capabilities target + runners map entry. Mirrors writeFileIfChanged + signature/version marker convention. No changes required to notify.sh, the v2 host-service tRPC endpoint, the renderer event bus, or the server-side mapEventType.
Owner
Author
|
Re-targeting against upstream superset-sh/superset. |
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.
Follow-up to superset-sh#2562, which added pi as a built-in agent (preset, command, icon, settings UI, docs). This PR adds the corresponding notification-hook integration in
apps/desktop/src/main/lib/agent-setup/, so pi participates in the same Start/Stop/PostToolUse lifecycle that drives Superset's working indicator and completion chime for claude, codex, gemini, cursor, copilot, opencode, mastra, amp, and droid.Mechanism
Ship a small TypeScript pi extension to the global pi extensions directory (
~/.pi/agent/extensions/superset-hooks.ts). The extension subscribes to pi's lifecycle events and spawnsnotify.shwith Claude-Code-formathook_event_nameJSON payloads, which the existingnotify.shdispatcher already speaks natively — no per-agent translator shim needed.Install lifecycle: at desktop app launch, the new wrapper writes the extension using the standard
writeFileIfChanged+ signature-marker + version pattern. Pi's auto-discovery picks it up at the next session start. Install is unconditional on whether pi is installed — if pi is later installed via npm, hooks just start working.Event mapping
before_agent_startUserPromptSubmitStarttool_execution_endPostToolUsePostToolUse(progress)agent_endStopStopsession_shutdownStopStop(cleanup on Ctrl+C, SIGTERM, SIGHUP, /quit, /reload, /new, /resume, /fork)Subagent filtering
Every event is gated on
ctx.hasUI === false. Subagents spawned via the bundledsubagentextension run viapi --mode json -pand havehasUI: false; user-facing interactive and RPC sessions havehasUI: true. The strict-equality check (rather than!ctx.hasUI) is intentional: pi versions older than 0.38.0 (wherehasUIdid not yet exist) still fire hooks correctly becauseundefined !== false. Subagent flicker is possible on those older versions only — documented limitation.Structural symmetry
Identical to the opencode integration:
agent-wrappers-pi.ts— wrapper module exportingcreatePiExtension,getPiExtensionPath,getPiExtensionContent,PI_EXTENSION_MARKERtemplates/pi-extension.template.ts— the extension itself, with// {{MARKER}}placeholder substituted at install timeagent-wrappers.ts— barrel re-exportdesktop-agent-capabilities.ts— adds"pi-extension"action and{ id: "pi", setupActions: ["pi-extension"] }target (nomanagedBinary— pi is user-installed via npm; cursor-agent is precedent)desktop-agent-setup.ts— runners map entryNo changes required to
notify.sh, the v2 host-service tRPC endpoint, the renderer event bus, or the server-sidemapEventType.Failure modes
All silent: notify.sh missing, spawn errors (EACCES/ENOENT), broken pipe, missing curl. Outside Superset (no
SUPERSET_TERMINAL_ID/SUPERSET_TAB_ID/SUPERSET_PANE_IDset) the extension is a complete no-op.Pi version compatibility
Soft minimum (not enforced): pi 0.31.0 introduced
before_agent_startandsession_shutdown; 0.38.0 introducedctx.hasUI; 0.52.10 introducedtool_execution_end; 0.67.3 madesession_shutdownfire on SIGHUP/SIGTERM. Pi'spi.on(eventName, handler)is permissive — unknown event names silently never fire. Extension degrades gracefully on older versions.Tests
Three new
it()blocks underdescribe("agent-wrappers pi", ...)inagent-wrappers.test.ts:getPiExtensionContent()returns a string containingPI_EXTENSION_MARKER(cleanup recognition).getPiExtensionContent()returns a string containingexport default function(valid pi extension shape).createPiExtension()writes to~/.pi/agent/extensions/superset-hooks.tswith marker present.Local validation:
bun test apps/desktop/src/main/lib/agent-setup/agent-wrappers.test.ts→ 29 pass / 0 failbunx biome check apps/desktop/src/main/lib/agent-setup/ biome.jsonc→ cleanbun --filter='./apps/desktop' typecheck→ exit 0bun run lint(whole repo) → cleanEnd-to-end was smoke-tested against
notify.shduring the design conversation:SUPERSET_DEBUG_HOOKS=1 echo '{"hook_event_name":"UserPromptSubmit"}' | ~/.superset/hooks/notify.shreturned HTTP 200 for all three managed event types (UserPromptSubmit,PostToolUse,Stop).Out of scope (flagged for visibility)
SUPERSET_HOST_AGENT_HOOK_URLnot set in v2 hook env) — affects all agents; will mask pi's improvements until fixed independently.Stophook transitions pane toidleinstead ofreview) — affects all agents; same disposition.before_permission_requestlifecycle event; permission UI is in-process viactx.ui.confirm. Reaching parity with Claude requires a new pi feature filed upstream atbadlogic/pi-mono.cleanupGlobalPiExtension) — not needed in v1; no prior install location to migrate from.apps/docs/content/docs/agent-integration.mdxalready promises this works for "agents" generically and lists pi under Supported Agents. This PR makes that promise true; pi-specific copy under Notifications would be off-pattern.