Files
PiAgentUI/docs/superpowers/plans/2026-05-28-pi-agent-extension-migration.md
T
Evandro b3489e1ede
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
🎉 Initial commit: PiAgentUI — AI Agent Desktop & Web UI
A professional workspace for AI coding agents with:
- Real-time streaming chat with SSE
- Session management (fork, clone, tree navigation)
- MCP tools browser & metadata panel
- Skills browser (global, project, package sources)
- Voice input & STT provider configuration
- Integrated terminal & file explorer
- Model selector with capability metadata
- Keyboard-first UI with command palette
- 8 languages (en, pt-BR, es, ja, zh-CN, ar, bn, hi)
- Tauri 2 desktop app
- React 19 + TypeScript + Vite 8 + Tailwind CSS 4
- Pi Agent extension runtime

Originally forked from OpenCodeUI, now an independent project.
License: GPL-3.0-only
2026-06-01 00:50:06 -03:00

28 KiB

Pi Agent Extension Migration Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Migrate PiAgentUi from OpenCode to Pi Agent while preserving the current UI and interaction model.

Architecture: Build a Pi package/extension as the primary integration. Pi loads extensions/piagentui-server.ts, which starts a loopback local server, serves the existing React build, and exposes an owned compatibility API shaped to the current frontend. Tauri/Rust desktop service cleanup is a second track after the Pi package MVP works.

Tech Stack: React 19, Vite 8, TypeScript 5.9, Vitest, Tauri 2/Rust, Pi extension API (@earendil-works/pi-coding-agent), Node HTTP, SSE/WebSocket event streaming.


Decisions Required Before Implementation

Default recommendations are listed; please confirm or override them before code changes.

  1. MVP session model: recommended = active Pi session mirror first. The UI controls the currently running Pi session; full session CRUD/fork/switch is deferred.
  2. Desktop/Tauri scope: recommended = defer process spawning. Tauri can connect to an already-running Pi extension server later, but Track A must not depend on Tauri.
  3. Unsupported features: recommended = disable/stub PTY, MCP, LSP, provider OAuth, worktrees, and multi-session operations until Pi equivalents are verified.
  4. Token/bootstrap: recommended = same-origin injected boot data in HTML served by the extension; bearer token stays in memory, never query strings/localStorage.
  5. Endpoint convention: recommended = keep OpenCode-shaped endpoint paths/envelopes where the current frontend already expects them, then gradually move wrappers to owned names internally.
  6. Product name: needs user decision. Options: PiAgentUi, Pi Agent UI, or another exact name.

Implementation should not begin until these are confirmed.


Non-Negotiable Scope

  • No UI redesign.
  • No /hud command.
  • No Ctrl+Shift+H HUD toggle.
  • Remove OpenCode runtime usage completely by final migration.
  • Remove @opencode-ai/sdk by final migration.
  • Reuse user Pi settings/auth/model setup; do not collect provider credentials in PiAgentUi.
  • Use better-tau/extensions/mirror-server.ts as the main reference for a Pi extension serving HTTP/WebSocket from inside Pi.
  • Current known better-tau unrelated changes must not be touched: .gitignore, extensions/helper-bridge.ts, extensions/helper/.

Core Corrections from Critical Review

  • Do not conflate Pi package and Tauri app. Track A is Pi package/extension; Track B is desktop cleanup.
  • Do not flatten message DTOs. Current UI expects MessageWithParts { info, parts }, and many callsites read message.info.*.
  • Do not emit raw event envelopes unless events.ts is rewritten first. Current frontend accepts { directory, payload: { type, properties } } from /global/event.
  • Use actual Pi lifecycle events. The shutdown event is session_shutdown, not session_end.
  • Typecheck extension files. Existing tsc -b does not include extensions/**/*.ts.
  • Resolve token bootstrap early. The UI cannot call protected APIs unless it receives base URL/token safely.
  • Treat pi.sendUserMessage(...) as asynchronous fire-and-stream. It should return 202 accepted; real message IDs arrive through events.

File/Module Responsibility Map

New files

  • extensions/piagentui-server.ts

    • Pi extension entrypoint.
    • Starts loopback HTTP/SSE/WS server.
    • Serves built dist/ assets.
    • Injects safe runtime boot data into index.html.
    • Bridges Pi session lifecycle and messages to current frontend-compatible events.
  • extensions/piagentui-server-core.ts

    • Pure helpers for testable server behavior: loopback validation, auth validation, body-size guard, path traversal prevention, event envelope helpers.
  • extensions/piagentui-server-core.test.ts

    • Unit tests for server security helpers.
  • tsconfig.extension.json

    • TypeScript project for extension files and extension tests/helpers.
  • src/api/piClient.ts

    • Typed fetch client replacing SDK usage.
    • Sends local bearer auth in headers only.
    • Normalizes typed errors.
  • src/api/piClient.test.ts

    • Request/auth/error behavior tests.
  • src/types/api/compat.ts

    • Owned compatibility DTOs shaped for current UI.
  • src/api/piContract.ts

    • Owned request/response contracts and current event envelope definitions.
  • src/api/piEventTranslator.test.ts

    • Contract tests for frontend event processing.
  • docs/superpowers/specs/2026-05-28-pi-agent-extension-migration-design.md

    • Design spec, endpoint matrix, unsupported features, security, acceptance criteria.

Modified files

  • package.json

    • Add pi.extensions.
    • Add package metadata needed for Pi package usage.
    • Add extension typecheck script.
    • Add/remove dependencies in the correct sequence.
    • Remove @opencode-ai/sdk when no imports remain.
  • tsconfig.json

    • Include tsconfig.extension.json in references.
  • vite.config.ts

    • Remove OpenCode dev proxy when API layer no longer uses OpenCode server.
    • Add Pi extension dev proxy only if chosen.
  • src/constants/api.ts, src/api/http.ts, src/store/serverStore.ts

    • Convert from OpenCode server/basic-auth concepts to PiAgentUi local server boot/connection state.
    • No provider credential storage.
  • src/api/sdk.ts

    • Delete after all imports are removed, or temporarily replace with a non-SDK compatibility facade.
  • src/api/*.ts

    • Replace SDK calls with owned client calls or unsupported-feature stubs.
    • Files likely in scope: agent.ts, client.ts, command.ts, config.ts, file.ts, global.ts, lsp.ts, mcp.ts, message.ts, permission.ts, pty.ts, session.ts, skill.ts, todo.ts, tool.ts, vcs.ts, worktree.ts.
  • src/types/api/*.ts

    • Replace SDK-derived type aliases with owned DTOs or explicit unsupported types.
    • Files likely in scope: agent.ts, common.ts, config.ts, event.ts, file.ts, mcp.ts, message.ts, model.ts, permission.ts, project.ts, pty.ts, session.ts, skill.ts, tool.ts, vcs.ts, worktree.ts.
  • src/main.tsx, src/features/settings/components/ServiceSettings.tsx, src/hooks/useCloseServiceDialog.ts, src/store/serviceStore.ts

    • Track A: ensure OpenCode auto-start does not run while Pi extension mode is active.
    • Track B: rename desktop service integration.
  • src-tauri/src/app/commands/opencode.rs, src-tauri/src/app/commands/mod.rs, src-tauri/src/app/mod.rs

    • Track B only: rename commands and remove OpenCode process management.
  • src-tauri/src/app/bridge/args.rs, src-tauri/src/app/commands/bridge.rs

    • Track B only: enforce loopback URL allowlist in Rust bridge.
  • src-tauri/capabilities/default.json, src-tauri/tauri.conf.json, src-tauri/Cargo.toml

    • Track B only: remove OpenCode branding and tighten security.

Compatibility Contract

DTO shape must match current UI

Current UI expects message shape similar to:

export interface MessageWithParts {
  info: Message
  parts: Part[]
}

Therefore owned DTOs must preserve this shape first, then adapt internally:

export interface CompatMessageInfo {
  id: string
  sessionID: string
  role: 'user' | 'assistant'
  time?: { created?: number; completed?: number }
  summary?: string
  modelID?: string
  providerID?: string
}

export interface CompatMessageWithParts {
  info: CompatMessageInfo
  parts: CompatPart[]
}

export type CompatPart =
  | CompatTextPart
  | CompatReasoningPart
  | CompatToolPart
  | CompatFilePart
  | CompatStepStartPart
  | CompatStepFinishPart
  | CompatUnsupportedPart

export interface CompatTextPart {
  id: string
  sessionID: string
  messageID: string
  type: 'text'
  text: string
}

export interface CompatReasoningPart {
  id: string
  sessionID: string
  messageID: string
  type: 'reasoning'
  text: string
}

export interface CompatToolPart {
  id: string
  sessionID: string
  messageID: string
  type: 'tool'
  tool: string
  state: { status: 'pending' | 'running' | 'completed' | 'error'; input?: unknown; output?: unknown; error?: string }
}

export interface CompatFilePart {
  id: string
  sessionID: string
  messageID: string
  type: 'file'
  mime?: string
  filename?: string
  url?: string
}

export interface CompatStepStartPart {
  id: string
  sessionID: string
  messageID: string
  type: 'step-start'
}

export interface CompatStepFinishPart {
  id: string
  sessionID: string
  messageID: string
  type: 'step-finish'
}

export interface CompatUnsupportedPart {
  id: string
  sessionID: string
  messageID: string
  type: 'unsupported'
  label: string
  data?: unknown
}

Exact fields must be finalized by a field inventory before implementation.

Event envelope must match current frontend first

Current src/api/events.ts expects:

export interface CompatGlobalEvent {
  directory?: string
  payload: {
    type: string
    properties: unknown
  }
}

For MVP, the extension should emit this envelope on the current path or the frontend parser must be rewritten before server events are implemented.

Recommended MVP: keep /global/event and OpenCode-style event names already handled by the UI:

  • server.connected
  • session.updated
  • session.status
  • session.idle
  • session.error
  • message.updated
  • message.part.updated
  • message.part.delta
  • message.part.removed
  • permission.asked only if mapped; otherwise unsupported notification
  • question.asked only if mapped; otherwise unsupported notification

For text deltas, current store expects payload shape compatible with its PartDeltaPayload, including sessionID, messageID, partID, field, and delta.

Send message contract

Current frontend send params include:

interface SendMessageParams {
  sessionId: string
  text: string
  attachments: Attachment[]
  model: { providerID: string; modelID: string }
  agent?: string
  variant?: string
  directory?: string
}

MVP behavior:

  • text: supported.
  • directory: supported only as metadata/active project hint if Pi context allows it.
  • model: support only if Pi allows model switch before send; otherwise ignore with warning event or reject with unsupported error.
  • attachments: defer unless image/file input mapping is verified.
  • agent, variant: defer unless Pi equivalent is verified.
  • response: 202 accepted plus optional synthetic client request ID; real assistant message ID is learned from events.

Endpoint Coverage Matrix

MVP supported

Capability Existing frontend area Compatibility path Backend source
Health serverStore, client.ts /global/health or current health path extension runtime state
Event stream events.ts /global/event Pi extension lifecycle/events
Active models client.ts, model hooks wrapper-owned endpoint, final path decided in Task 1 Pi model registry/settings
Active session snapshot session.ts, stores wrapper-owned endpoint, OpenCode-shaped response active Pi context/session mirror
Send message message.ts, useChatSession.ts wrapper-owned endpoint pi.sendUserMessage(...)
Abort turn message/session controls wrapper-owned endpoint current Pi context abort if available
Static assets browser/webview /, /assets/* extension static server

Explicitly unsupported/deferred for MVP

  • PTY terminal sessions.
  • MCP management.
  • LSP diagnostics endpoints.
  • Provider OAuth/login.
  • Full multi-session create/fork/switch/delete.
  • Worktrees.
  • VCS operations unless trivially provided by current UI independent of OpenCode.
  • Permission/question flows unless Pi extension UI/RPC gives equivalent semantics.
  • Share/export unless Pi exposes safe API from extension context.
  • Config, project, agent, skill, todo, tool, file APIs that currently depend on OpenCode SDK.

Every deferred feature must return a typed unsupported error and must not call an OpenCode endpoint.


Security Contract

Required for Track A:

  • Bind only to 127.0.0.1 and optionally ::1.
  • Use OS-selected random high port by default.
  • Generate per-run bearer token.
  • Bootstrap token via same-origin injected boot data in served HTML, unless user chooses another mechanism.
  • Keep bearer token in memory/session only; do not store it in localStorage or settings backups.
  • Reject API and stream requests without Authorization: Bearer <token>.
  • For browser-native SSE/WS where custom headers are constrained, prefer same-origin cookie/header strategy from extension-served page; do not put token in query strings or userinfo URLs.
  • Validate Host and Origin.
  • No wildcard CORS.
  • Limit request body and WS frame sizes.
  • Reject static path traversal.
  • Never send provider API keys/OAuth tokens to browser.
  • Never log local bearer token, provider secrets, or prompts by default.
  • Close HTTP server and sockets on session_shutdown.

Required for Track B if touched:

  • Rust bridge must validate URLs server-side, not only via Tauri capabilities.
  • Allow only http://127.0.0.1:*, http://localhost:*, ws://127.0.0.1:*, ws://localhost:* as appropriate.
  • Reject userinfo URLs, LAN IPs, non-loopback hosts, and external HTTPS URLs.
  • Narrow src-tauri/capabilities/default.json from broad http://** / https://** to loopback-only.
  • Reintroduce CSP instead of csp: null if compatible with current app.

Validation Contract

Run during implementation milestones:

cd PiAgentUi
npm run typecheck
npm run lint
npm run test:run
npm run build

After extension tsconfig is added:

cd PiAgentUi
npm run typecheck:extensions

If Track B is touched:

cd PiAgentUi/src-tauri
cargo test

OpenCode cleanup check must use an allowlist because docs may mention migration history:

cd PiAgentUi
rg -n "@opencode-ai/sdk|getSDKClient|unwrap\(|opencode serve|OpenCode|opencode" src src-tauri extensions package.json vite.config.ts

Expected final runtime result:

  • no @opencode-ai/sdk imports;
  • no opencode serve launcher;
  • no OpenCode user-facing app title;
  • only temporary deprecated aliases if Track B explicitly keeps them for one release.

Pi package smoke:

cd PiAgentUi
npm run build
npm pack --dry-run

Then install/load the package in Pi using the local package workflow chosen for this repo and verify:

  1. Pi loads the extension.
  2. Extension serves the UI.
  3. UI receives boot data.
  4. UI sends a message to current Pi session.
  5. Assistant response streams into existing chat UI.
  6. Refresh/reconnect recovers current snapshot.
  7. Invalid HTTP/SSE/WS auth is rejected.

Implementation Tasks

Task 1: Confirm Decisions and Write Design Spec

Files:

  • Create: docs/superpowers/specs/2026-05-28-pi-agent-extension-migration-design.md

  • Confirm all decisions in “Decisions Required Before Implementation”.

  • Write the design spec with: MVP, non-goals, endpoint matrix, DTO/event contract, security contract, validation contract, unsupported-feature behavior, Track A/Track B split.

  • Include exact better-tau reference: D:/Documents/Github/PiAgentUI/better-tau/extensions/mirror-server.ts.

  • Run:

cd PiAgentUi
npm run typecheck

Expected: unchanged project still typechecks before migration starts.

Task 2: Inventory Current Frontend API Fields and SDK Coupling

Files:

  • Create: docs/superpowers/specs/2026-05-28-pi-agent-ui-field-inventory.md

  • Run:

cd PiAgentUi
rg -n "@opencode-ai/sdk|getSDKClient|unwrap\(|from './sdk'|from '../api/sdk'|Client\[|SDK[A-Za-z]" src
  • Inventory all files importing SDK-derived types or getSDKClient.
  • Inventory consumed fields for:
    • Session
    • MessageWithParts
    • Message.info
    • every Part variant rendered by components/stores
    • GlobalEvent
    • PartDeltaPayload
    • SendMessageParams
  • Mark each API module as: supported, stubbed, hidden, or deferred.
  • Do not edit runtime code in this task.

Task 3: Add Owned Compatibility Types Without Breaking UI Shape

Files:

  • Create: src/types/api/compat.ts

  • Create: src/api/piContract.ts

  • Modify: src/types/api/message.ts, src/types/api/event.ts, src/types/api/session.ts only after inventory confirms exact fields.

  • Add owned compatibility DTOs preserving current UI shape.

  • Replace SDK aliases gradually with owned DTO aliases that match current field names.

  • Do not flatten MessageWithParts.

  • Keep GlobalEvent envelope compatible with current events.ts unless rewriting events.ts in the same task.

  • Run:

cd PiAgentUi
npm run typecheck
npm run test:run -- src/store/messageStore.test.ts src/api/events.test.ts src/hooks/useChatSession.test.tsx

Expected: failures only from intentional type differences fixed before proceeding.

Task 4: Add Extension Typecheck and Package Metadata

Files:

  • Create: tsconfig.extension.json

  • Modify: tsconfig.json

  • Modify: package.json

  • Add tsconfig.extension.json including extensions/**/*.ts.

  • Add script:

"typecheck:extensions": "tsc -p tsconfig.extension.json --noEmit"
  • Include typecheck:extensions in validate after extension files exist.
  • Add Pi package metadata:
"pi": {
  "extensions": ["./extensions/piagentui-server.ts"]
}
  • Add package contents/prepack strategy so dist/ and extensions/ are included when packed/installed.
  • Decide dependency strategy for @earendil-works/pi-coding-agent:
    • runtime should be supplied by Pi package loader if supported;
    • local typecheck still needs a devDependency or path-compatible type resolution.
  • Run:
cd PiAgentUi
npm run typecheck
npm run typecheck:extensions
npm pack --dry-run

Task 5: Implement Extension Server Core Helpers and Tests

Files:

  • Create: extensions/piagentui-server-core.ts

  • Create: extensions/piagentui-server-core.test.ts

  • Write tests first for:

    • loopback host accepted;
    • LAN/external host rejected;
    • userinfo URL rejected;
    • malformed auth rejected;
    • valid bearer auth accepted;
    • Origin/Host mismatch rejected;
    • static path traversal rejected;
    • body-size guard rejects oversized body;
    • boot data injection does not put token in URL.

Use test token construction that is obviously fake and not a credential:

const sampleToken = ['test', 'token', 'value'].join('-')
  • Implement pure helpers to pass tests.
  • Run:
cd PiAgentUi
npm run test:run -- extensions/piagentui-server-core.test.ts
npm run typecheck:extensions

Task 6: Implement Pi Extension Server Skeleton

Files:

  • Create: extensions/piagentui-server.ts

  • Modify: extension tests/helpers as needed

  • Implement extension entrypoint importing ExtensionAPI from @earendil-works/pi-coding-agent.

  • Start server on session_start or the earliest correct lifecycle event.

  • Cleanup on session_shutdown.

  • Bind loopback on random high port.

  • Serve dist/index.html, injecting boot data same-origin.

  • Serve /assets/* safely.

  • Implement authenticated health endpoint compatible with frontend/serverStore path decision.

  • Run:

cd PiAgentUi
npm run typecheck:extensions
npm run build
npm pack --dry-run

Task 7: Replace Basic Auth Server Store with Pi Local Boot State

Files:

  • Modify: src/store/serverStore.ts

  • Modify: src/store/serverStore.test.ts

  • Modify: src/api/http.ts

  • Modify: src/constants/api.ts

  • Remove provider/server password persistence from active Pi mode.

  • Store only base URL and in-memory/session-scoped local token.

  • Add migration tests proving old Basic auth/password values are not exported in backups after migration.

  • Ensure auth headers use bearer token and never query strings.

  • Run:

cd PiAgentUi
npm run test:run -- src/store/serverStore.test.ts src/api/http.test.ts
npm run typecheck

Task 8: Add piClient and Replace SDK Wrapper Entry Points

Files:

  • Create: src/api/piClient.ts

  • Create: src/api/piClient.test.ts

  • Modify: src/api/client.ts

  • Modify: src/api/session.ts

  • Modify: src/api/message.ts

  • Write piClient tests for bearer headers, no token in URL, JSON errors, base URL normalization.

  • Implement get, post, delete, and stream helper if needed.

  • Replace model/session/message wrappers first because they are MVP-supported.

  • Preserve existing exported function names consumed by hooks/components.

  • For send message, return accepted state if Pi returns no message ID; rely on events for message updates.

  • Run:

cd PiAgentUi
npm run test:run -- src/api/piClient.test.ts src/hooks/useSessions.test.tsx src/hooks/useChatSession.test.tsx src/hooks/useModelSelection.test.tsx
npm run typecheck

Task 9: Implement Pi Event Translation Compatible with Existing events.ts

Files:

  • Modify: extensions/piagentui-server.ts

  • Create: src/api/piEventTranslator.test.ts

  • Modify: src/api/events.ts only if necessary and covered by tests.

  • Add tests for the current envelope { directory, payload: { type, properties } }.

  • Add tests for message.part.delta shape expected by messageStore.

  • Map Pi events to existing frontend events:

    • turn start -> session.status running;
    • turn end -> session.idle or session.status idle;
    • message update -> message.updated;
    • part delta/update -> message.part.delta / message.part.updated;
    • tool events -> tool part updates;
    • errors -> session.error.
  • Add initial snapshot event on connect.

  • Add reconnect behavior using existing generation/snapshot logic.

  • Run:

cd PiAgentUi
npm run test:run -- src/api/events.test.ts src/api/sse.test.ts src/api/piEventTranslator.test.ts src/store/messageStore.test.ts
npm run typecheck

Task 10: Gate or Stub All Unsupported OpenCode-Only Features

Files:

  • Modify: remaining src/api/*.ts

  • Modify: affected hooks/components only when they crash on unsupported errors.

  • Run:

cd PiAgentUi
rg -n "getSDKClient|unwrap\(|@opencode-ai/sdk|opencode|OpenCode" src
  • For every remaining API module, implement one of:
    • supported Pi-backed wrapper;
    • typed unsupported error;
    • hidden/disabled UI action with existing notification style.
  • Cover at least:
    • agent.ts
    • command.ts
    • config.ts
    • file.ts
    • global.ts
    • lsp.ts
    • mcp.ts
    • permission.ts
    • pty.ts
    • skill.ts
    • todo.ts
    • tool.ts
    • vcs.ts
    • worktree.ts
  • Ensure pty.ts never embeds credentials/tokens in URLs.
  • Run:
cd PiAgentUi
npm run test:run
npm run typecheck

Task 11: Prevent OpenCode Auto-Start in Pi Extension Mode

Files:

  • Modify: src/main.tsx

  • Modify: src/store/serviceStore.ts

  • Modify: src/features/settings/components/ServiceSettings.tsx

  • Modify: src/hooks/useCloseServiceDialog.ts

  • Detect Pi extension mode from boot data.

  • In Pi extension mode, do not auto-start opencode serve.

  • Hide/disable OpenCode service settings without changing layout structure more than necessary.

  • Do not rename desktop commands yet unless Track B is approved.

  • Run:

cd PiAgentUi
npm run test:run -- src/store/serviceStore.test.ts src/utils/settingsBackup.test.ts
npm run typecheck

Task 12: Remove @opencode-ai/sdk and SDK Facade

Files:

  • Modify: package.json, lockfile if present

  • Delete or rewrite: src/api/sdk.ts

  • Modify: tests that mock SDK

  • Confirm no imports remain:

cd PiAgentUi
rg -n "@opencode-ai/sdk|getSDKClient|unwrap\(" src
  • Remove dependency using the repo's package manager:
cd PiAgentUi
npm uninstall @opencode-ai/sdk

If package manager/lockfile state is unclear, stop and ask.

  • Delete src/api/sdk.ts if unused.
  • Update tests to mock piClient or API wrappers instead of SDK.
  • Run:
cd PiAgentUi
npm run validate
npm run typecheck:extensions

Task 13: Track B — Tauri Desktop Cleanup and Security Hardening

Only start after Track A smoke passes and user approves desktop scope.

Files:

  • Rename: src-tauri/src/app/commands/opencode.rs -> src-tauri/src/app/commands/pi_agent.rs

  • Modify: src-tauri/src/app/commands/mod.rs

  • Modify: src-tauri/src/app/mod.rs

  • Modify: src-tauri/src/app/bridge/args.rs

  • Modify: src-tauri/src/app/commands/bridge.rs

  • Modify: src/store/serviceStore.ts

  • Modify: src-tauri/capabilities/default.json

  • Modify: src-tauri/tauri.conf.json

  • Modify: src-tauri/Cargo.toml

  • Decide desktop behavior: connect to existing Pi extension server, spawn pi --mode rpc, or defer.

  • Rename service commands to Pi names if desktop remains.

  • Keep old command aliases for one transition release only if required by existing frontend code.

  • Migrate storage keys:

    • opencode-auto-start-service -> pi-agent-auto-start-service
    • opencode-binary-path -> pi-agent-binary-path
    • opencode-service-env-vars -> pi-agent-service-env-vars
  • Add Rust-side URL allowlist tests for bridge connect/send paths.

  • Narrow Tauri HTTP permissions to loopback-only.

  • Reintroduce CSP if compatible.

  • Run:

cd PiAgentUi
npm run typecheck
npm run test:run
cd src-tauri
cargo test

Task 14: Final Product Metadata and OpenCode Cleanup

Files:

  • Modify: package.json

  • Modify: src-tauri/Cargo.toml

  • Modify: src-tauri/tauri.conf.json

  • Modify: README/docs/user-facing strings

  • Apply user-approved final product name.

  • Update package name/description.

  • Update Tauri product name/window title/identifier if Track B is in scope.

  • Remove OpenCode user-facing strings.

  • Run allowlisted grep:

cd PiAgentUi
rg -n "@opencode-ai/sdk|getSDKClient|unwrap\(|opencode serve|OpenCode|opencode" src src-tauri extensions package.json vite.config.ts README.md

Expected: no runtime/user-facing OpenCode references except approved temporary aliases.

  • Run full validation:
cd PiAgentUi
npm run validate
npm run typecheck:extensions
npm run build
npm pack --dry-run

If Track B is in scope:

cd PiAgentUi/src-tauri
cargo test

Review Checklist for Implementation Milestones

After Tasks 6, 9, 12, and 13, run a critical review pass before continuing:

  • Correctness/regression review against this plan.
  • Test coverage and validation review.
  • Security review for local HTTP/SSE/WS, token handling, and Tauri bridge if touched.
  • Simplicity review to catch unnecessary OpenCode compatibility that can be deleted.

The reviewer output should be synthesized before any fixes are applied. Apply fixes with one writer only.


  1. Milestone 1: decisions + design spec + field inventory.
  2. Milestone 2: owned DTOs + extension typecheck/package metadata.
  3. Milestone 3: secure extension server skeleton + boot data.
  4. Milestone 4: model/session/message wrappers + event streaming.
  5. Milestone 5: unsupported feature gating + SDK removal.
  6. Milestone 6: Pi package smoke and final OpenCode cleanup.
  7. Milestone 7: optional Tauri desktop cleanup/hardening.