Skip to content

fix(input): reject writes to inactive sessions - #71

Open
dhaern wants to merge 1 commit into
shekohex:mainfrom
dhaern:omos/fix-pty-write-live-only
Open

dhaern wants to merge 1 commit into
shekohex:mainfrom
dhaern:omos/fix-pty-write-live-only

Conversation

@dhaern

@dhaern dhaern commented Oct 5, 2026

Copy link
Copy Markdown

Summary

OutputManager.write() returns true even when nothing was written. An exited PTY answers POST /api/sessions/:id/input with a success, and pty_write can report "Sent N bytes" for input that never reached a process. This PR makes write() report the real outcome.

In plain terms: if the agent or the web page tried to type into a terminal that had already finished, the plugin said the input was sent when nothing could receive it. Now it says the write failed.

Cause

write() swallowed every error and returned true, with the comment "allow write to exited process for tests". It also never checked the session state:

  • The input endpoint answered 200 for sessions that had exited or been killed.
  • pty_write checks that the session is running and then awaits the command permission check. If the PTY exits during that wait, the write still returned true and the tool reported success.

Changes

write() returns false unless the session is running and has a process, and it returns false when the native write throws. The only test that depended on the old behavior is updated.

Behavior changes

  • POST /api/sessions/:id/input on a session that is not running now answers 400 with { "error": "Failed to write to session" } instead of 200.
  • pty_write throws Failed to write to PTY '<id>'. when the session exits before the write, instead of reporting "Sent N bytes".
  • pty_write with an empty data string now fails instead of replying "Sent 0 bytes". The native write throws on an empty string (bun:ffi cannot convert argument to 'ptr'), and the old code hid that error.
  • WebSocket input ignores the result of write(), as before.

Validation

The integration test that wrote to an exited PTY now expects 400 and the error body. On main it fails with 200. Replacing the body of write() with return true makes it fail again.

bun test over test/*.test.ts, without the live and npm-pack suites, gives 184 passing. bun run typecheck, bun run lint and bunx biome format . are clean. I did not run the Playwright e2e suite locally. I found no e2e test or tool test that depends on writing to a finished PTY.

Diff

Production: +1 line (+3/-2) in src/plugin/pty/output-manager.ts.
Tests: +1 line (+2/-1) in test/integration.test.ts.

Reject writes unless the session is running and has a process; return false when process.write throws instead of reporting success.

Intentionally change POST /api/sessions/:id/input for inactive PTYs from HTTP 200 to 400. The shared manager also rejects pty_write when a session exits during permission checks in v1 and v2.
@dhaern dhaern changed the title fix(pty): reject writes to inactive sessions fix(input): reject writes to inactive sessions Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant