Skip to content

Unify shell-session paste submission on scheduleSubmitEnters, and fold the wrap-up prod into pasteToSession #3216

Description

@atomantic

Context

pasteToSession in server/services/shell.js was extracted from sendBtwToAgent
(server/services/cosAgentLifecycle.js) and is now also used by the Shell photo
drop (server/services/shellImageDrop.js). It bracket-pastes text and submits it
with a single delayed \r (400ms) — the behavior sendBtwToAgent has always
had.

Two things are unfinished:

1. There are two submit strategies for the same resource. Every other place
that pastes into a shell-service session submits via scheduleSubmitEnters
(server/lib/tuiHandshake.js) — three Enters, 700ms apart:

  • server/services/agentTuiSpawning.js (initial prompt paste)
  • server/lib/tuiPromptRunner.js

That helper exists because a single \r can be swallowed while the TUI is still
reflowing a paste, stranding the prompt unsent. pasteToSession now carries the
weaker strategy under the most generic available name, so the next author who
reaches for the obvious primitive inherits it. Its docblock currently marks the
boundary in prose; the code should just be right.

2. One caller was left hand-rolled. The max-runtime wrap-up prod in
server/services/agentTuiSpawning.js (search buildWrapUpProdMessage) writes
\x1b[200~…\x1b[201~ to a shell-service session by sessionId with no
verification and no retry — structurally identical to pasteToSession, and it
should call it.

Correctly OUT of scope (verified, do not change):

  • server/lib/tuiPromptRunner.js and server/lib/tuiUsageScrape.js write to a
    PTY they own directly that was never registered in shellSessions, so a
    (sessionId, …)-shaped primitive has no handle to offer them.
  • agentTuiSpawning.js's attemptPaste is a paste-marker-verified retry loop;
    its paste write is one step of a handshake, not the whole operation.

Task

  1. Have pasteToSession submit via scheduleSubmitEnters(write, isFinalized)
    instead of one setTimeout(…, 400), returning whatever handle is needed to
    cancel pending Enters. tuiHandshake.js imports nothing from shell.js, so
    there is no cycle.
  2. Replace the hand-rolled paste in agentTuiSpawning.js's wrap-up prod with a
    pasteToSession(...) call.
  3. Update server/services/shell.test.js's pasteToSession suite (it currently
    pins the single-Enter contract) and trim the now-stale "scope" paragraph in the
    docblock.

Why this is safe

Extra Enters land on an empty prompt, which Claude Code ignores — that is why
scheduleSubmitEnters is already the strategy for the two larger paste sites.
The change affects sendBtwToAgent (BTW messages) and the Shell photo drop, both
of which paste short payloads today; the win is that they stop being a second
strategy the next caller can inherit by accident.

Provenance

Raised by an altitude review during the Shell photo-drop change; skipped there
because it alters sendBtwToAgent's production submit behavior and touches
agentTuiSpawning.js, both outside that diff.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions