fix: migrate coder-tui remote runtime for Pi v0.65#1351
Conversation
|
The latest Agentuity deployment details.
|
📝 WalkthroughWalkthroughThe changes update dependencies to Changes
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
📦 Canary Packages Publishedversion: PackagesInstallAdd to your {
"dependencies": {
"@agentuity/webhook": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-webhook-2.0.9-9f43c59.tgz",
"@agentuity/auth": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-auth-2.0.9-9f43c59.tgz",
"@agentuity/email": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-email-2.0.9-9f43c59.tgz",
"@agentuity/evals": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-evals-2.0.9-9f43c59.tgz",
"@agentuity/migrate": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-migrate-2.0.9-9f43c59.tgz",
"@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-core-2.0.9-9f43c59.tgz",
"@agentuity/sandbox": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-sandbox-2.0.9-9f43c59.tgz",
"@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-server-2.0.9-9f43c59.tgz",
"@agentuity/vector": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-vector-2.0.9-9f43c59.tgz",
"@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-claude-code-2.0.9-9f43c59.tgz",
"@agentuity/keyvalue": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-keyvalue-2.0.9-9f43c59.tgz",
"@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-postgres-2.0.9-9f43c59.tgz",
"@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-opencode-2.0.9-9f43c59.tgz",
"@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-runtime-2.0.9-9f43c59.tgz",
"@agentuity/db": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-db-2.0.9-9f43c59.tgz",
"@agentuity/task": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-task-2.0.9-9f43c59.tgz",
"@agentuity/coder-tui": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-coder-tui-2.0.9-9f43c59.tgz",
"@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-schema-2.0.9-9f43c59.tgz",
"@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-drizzle-2.0.9-9f43c59.tgz",
"@agentuity/coder": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-coder-2.0.9-9f43c59.tgz",
"@agentuity/frontend": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-frontend-2.0.9-9f43c59.tgz",
"@agentuity/react": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-react-2.0.9-9f43c59.tgz",
"@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-cli-2.0.9-9f43c59.tgz",
"@agentuity/schedule": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-schedule-2.0.9-9f43c59.tgz",
"@agentuity/queue": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-queue-2.0.9-9f43c59.tgz",
"@agentuity/workbench": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-workbench-2.0.9-9f43c59.tgz"
}
}Or install directly: bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-webhook-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-auth-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-email-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-evals-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-migrate-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-core-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-sandbox-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-server-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-vector-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-claude-code-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-keyvalue-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-postgres-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-opencode-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-runtime-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-db-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-task-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-coder-tui-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-schema-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-drizzle-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-coder-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-frontend-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-react-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-cli-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-schedule-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-queue-2.0.9-9f43c59.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/2.0.9-9f43c59/agentuity-workbench-2.0.9-9f43c59.tgz |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/coder-tui/src/remote-tui.ts (1)
902-927: Cleanup is comprehensive but has potential double-execution.The signal handler (
cleanup) and thefinallyblock both callremote.close()andsetNativeRemoteExtensionContext(null). When SIGINT fires,interactive.stop()causesrun()to exit, triggering thefinallyblock.This is likely safe since:
- WebSocket
close()is idempotentsetNativeRemoteExtensionContext(null)is idempotentdisposeRuntime()has the idempotent guardHowever, the signal handler doesn't prevent re-registration, so multiple SIGINT signals could race. Consider this optional improvement:
♻️ Optional: Deduplicate cleanup logic
+ let cleanupStarted = false; const cleanup = () => { + if (cleanupStarted) return; + cleanupStarted = true; remote.close(); setNativeRemoteExtensionContext(null); interactive.stop(); void disposeRuntime().catch((err) => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/coder-tui/src/remote-tui.ts` around lines 902 - 927, The signal handler cleanup and the finally block both call remote.close(), setNativeRemoteExtensionContext(null), and disposeRuntime(), which can run twice when SIGINT triggers interactive.stop(); make cleanup idempotent and prevent double-execution by adding a guarded flag (e.g., cleanupCalled) checked/set inside the cleanup function and by removing the process.on listeners (or calling process.off) from within cleanup; update references in remote.close, setNativeRemoteExtensionContext, interactive.stop, and disposeRuntime usages so the cleanup function is the single point of teardown and the finally block only awaits the guarded cleanup (or checks the flag) to avoid duplicate calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/coder-tui/src/remote-tui.ts`:
- Around line 902-927: The signal handler cleanup and the finally block both
call remote.close(), setNativeRemoteExtensionContext(null), and
disposeRuntime(), which can run twice when SIGINT triggers interactive.stop();
make cleanup idempotent and prevent double-execution by adding a guarded flag
(e.g., cleanupCalled) checked/set inside the cleanup function and by removing
the process.on listeners (or calling process.off) from within cleanup; update
references in remote.close, setNativeRemoteExtensionContext, interactive.stop,
and disposeRuntime usages so the cleanup function is the single point of
teardown and the finally block only awaits the guarded cleanup (or checks the
flag) to avoid duplicate calls.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0445b259-b244-47ba-8dab-2721f5293e2a
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (5)
packages/coder-tui/package.jsonpackages/coder-tui/src/index.tspackages/coder-tui/src/remote-runtime.tspackages/coder-tui/src/remote-tui.tspackages/coder-tui/test/remote-runtime.test.ts
💤 Files with no reviewable changes (1)
- packages/coder-tui/src/index.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
- GitHub Check: SDK Integration Test Suite
- GitHub Check: Sandbox CLI Tests
- GitHub Check: Queue CLI Tests
- GitHub Check: Queue SDK Tests
- GitHub Check: Cloud Deployment Tests
- GitHub Check: Standalone Agent Test
- GitHub Check: Postgres SSL Integration Test
- GitHub Check: Template Integration Tests
- GitHub Check: Framework Integration Tests (TanStack & Next.js)
- GitHub Check: Playwright E2E Smoke Test
- GitHub Check: Package Installation & Usage Test
- GitHub Check: Build
- GitHub Check: Pack & Upload
- GitHub Check: Agentuity Deployment
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Biome as code formatter with tabs (width 3), single quotes, semicolons, lineWidth 100, and trailingCommas es5
Files:
packages/coder-tui/test/remote-runtime.test.tspackages/coder-tui/src/remote-runtime.tspackages/coder-tui/src/remote-tui.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript Strict mode with ESNext target and bundler moduleResolution
UseStructuredErrorfrom@agentuity/corefor error handling
Files:
packages/coder-tui/test/remote-runtime.test.tspackages/coder-tui/src/remote-runtime.tspackages/coder-tui/src/remote-tui.ts
**/test/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/test/**/*.{ts,tsx}: Place tests intest/folder, never insrc/or__tests__/directories
Import from../src/in test files
Use@agentuity/test-utilsfor mocks in tests
Files:
packages/coder-tui/test/remote-runtime.test.ts
🧠 Learnings (3)
📚 Learning: 2026-03-27T23:18:58.450Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 1292
File: packages/keyvalue/package.json:3-3
Timestamp: 2026-03-27T23:18:58.450Z
Learning: In the agentuity/sdk monorepo, subpackage `package.json` files under `packages/` (e.g., `packages/keyvalue`) are allowed to depend on other workspace packages (such as `agentuity/server`) and are not limited to only `agentuity/core` and `zod`. Also, if a subpackage uses `bunx tsc --build --force` as its build script, treat it as a valid/intentional build command and do not flag it as a dependency/build-script violation.
Applied to files:
packages/coder-tui/package.json
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.
Applied to files:
packages/coder-tui/test/remote-runtime.test.tspackages/coder-tui/src/remote-runtime.tspackages/coder-tui/src/remote-tui.ts
📚 Learning: 2026-02-21T02:05:57.982Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 1010
File: packages/drizzle/test/proxy.test.ts:594-603
Timestamp: 2026-02-21T02:05:57.982Z
Learning: Do not rely on StructuredError from agentuity/core in test files or simple error handling paths. In tests and straightforward error handling, use plain Error objects to represent failures, reserving StructuredError for more complex error scenarios in application logic.
Applied to files:
packages/coder-tui/test/remote-runtime.test.ts
🔇 Additional comments (9)
packages/coder-tui/src/remote-runtime.ts (1)
1-45: LGTM — Clean utility module for remote runtime guards.The implementation is well-structured:
- The explicit runtime check for
_handleAgentEventwith a descriptive error message provides a clear failure mode if Pi's internal API changes (as noted in PR objectives).- The
blockclosure pattern elegantly creates async guards that return{ cancelled: true }.One minor observation:
switchSessionmaps to/resumein the operation callback, which is intentional per the PR description (blocking controller-side/resumecommands).packages/coder-tui/package.json (1)
28-33: LGTM — Consistent Pi ecosystem version bump to ^0.65.0.All Pi packages (
@mariozechner/pi-coding-agent,@mariozechner/pi-tui,@mariozechner/pi-ai) are bumped in lockstep, which is appropriate for a breaking API migration.packages/coder-tui/test/remote-runtime.test.ts (1)
1-53: LGTM — Comprehensive test coverage for remote runtime helpers.The tests effectively cover:
- Event dispatch routing through
_handleAgentEvent(notagent.emit)- Explicit failure when Pi removes/changes the internal hook
- All four blocked operations with correct callback invocation
The use of
toThrow('_handleAgentEvent')as a substring match is a good regression guard that will fail if Pi changes the hook name.packages/coder-tui/src/remote-tui.ts (6)
100-135: Well-structured migration tocreateAgentSessionRuntime.The factory callback pattern correctly separates service creation from session initialization:
noExtensions: truewith explicitextensionFactoriesensures controlled extension loadingtools: []appropriately delegates tool execution to the sandboxSessionManager.inMemory()is correct since state comes from the remote sessionThe destructuring on line 132 clearly shows the relationship:
runtime.sessionis the backing session.
137-150: Operation guard notification is well-integrated with the UI context.The
notifyBlockedRuntimeOperationfunction:
- Uses the native remote UI context when available for proper user feedback
- Falls back to logging when UI isn't ready
- Sets both notification and status for visibility
The
as anycast on line 148 is acceptable here sinceRemoteRuntimeGuardsis a minimal interface for the specific methods being guarded, and Pi's runtime type may include additional properties.
152-156: Good idempotent dispose pattern.The
runtimeDisposedflag correctly prevents double-disposal, which could cause issues if both the signal handler and thefinallyblock attempt cleanup.
164-166: Clean abstraction for event dispatch.The
emitSessionEventhelper provides a single point of control for routing events throughdispatchRemoteSessionEvent, which:
- Enables centralized error handling if the Pi hook changes
- Makes the code more readable than inline casts at each call site
The
as anycast is necessary since thesessiontype from Pi doesn't expose_handleAgentEventin its public interface.
840-844: Core migration:InteractiveModenow receivesruntimeinstead ofsession.This is the primary change required by Pi v0.65.0's move to
AgentSessionRuntime. The runtime encapsulates the session plus lifecycle management, whichInteractiveModeneeds for proper initialization.
4-11: Documentation accurately reflects the architectural change.The header comments correctly describe:
- Line 4:
AgentSessionRuntime + InteractiveMode(updated from prior session-only model)- Line 11: Events flow through
AgentSession event handlingviadispatchRemoteSessionEventThis provides good context for future maintainers understanding the remote TUI architecture.
|
I merged the Coder app PR related to this fyi. |
related: https://github.com/agentuity/coder/pull/20
Summary
@agentuity/coder-tuiremote mode to Pi'sAgentSessionRuntimemodelInteractiveMode/new,/resume,/fork, and/importwithcancelled: trueplus a user-facing warningsession_switchandsession_forkextension eventspackages/coder-tuito^0.65.0Why
Pi
v0.65.0moved interactive session management ontoAgentSessionRuntime, so the oldnew InteractiveMode(session)path was no longer valid.This PR keeps the remote TUI aligned with the product model we actually want:
Because of that, the migration intentionally blocks controller-side session replacement operations instead of letting them mutate a local in-memory mirror that would diverge from the sandbox source of truth.
Validation
bun run --filter='./packages/coder-tui' typecheckbun run --filter='./packages/coder-tui' buildbun test packages/coder-tui/testagentuity coder startstill booting Piv0.65.0Notes
AgentSession._handleAgentEventhook; the new regression test fails loudly if upstream changes that hook againSummary by CodeRabbit
Release Notes
Dependencies
New Features
Changes
Tests