Skip to content

fix(remote): deliver initial prompt to interpreter-wrapped agents (aider/vibe) + surface drops#8099

Closed
Jinwoo-H wants to merge 2 commits into
mainfrom
fix/interpreter-wrapped-agent-prompt-delivery
Closed

fix(remote): deliver initial prompt to interpreter-wrapped agents (aider/vibe) + surface drops#8099
Jinwoo-H wants to merge 2 commits into
mainfrom
fix/interpreter-wrapped-agent-prompt-delivery

Conversation

@Jinwoo-H

@Jinwoo-H Jinwoo-H commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Interpreter-wrapped agents (aider, mistral-vibe — both pip console-scripts) silently dropped their initial prompt when launched via the stdin-after-start delivery path, and a dropped delivery had no user-visible surface. Two commits:

  1. HIGH — prompt delivery (fix(remote): deliver stdin-after-start prompt to interpreter-wrapped agents…). sendFollowupPromptWhenAgentReadywaitForAgentForeground gated solely on isExpectedAgentProcess(foreground, expectedProcess) (exact/prefix name match). aider/mistral-vibe run as python3 …/bin/aider, so the PTY foreground comm is python3 (or python) — never aider/vibe. The wait polled 30×150ms (~4.5s), returned false, and the prompt was dropped with no error. This bit both locally (when the ps-table resolver can't pin the wrapped child to a single candidate) and over SSH (when the relay's getForegroundProcessName falls back to the bare interpreter name). Fix: after a few polls, also accept the foreground when it's a known agent wrapper process (node/python*, via the existing isAgentForegroundWrapperProcess), is not a shell, and the PTY has a non-shell child — the same readiness signal waitForAgentReady (the Use-button flow) already uses. Client-side only; uses just foregroundProcess + hasChildProcesses, both already in RuntimeTerminalProcessInspection, so no relay/RPC protocol change and it works identically on local and SSH.

  2. MEDIUM — failure surface (fix(remote): surface a toast when agent startup prompt/draft delivery is dropped). deliverAgentStartupToTerminal ignored sendFollowupPromptWhenAgentReady's boolean and passed no onTimeout to pasteDraftToAgentPtyWhenReady, so a genuine drop was silent. Wired both to the existing showAutomationPromptNotSentToast(agent) (already a standalone, generically-named module — reused directly, not moved).

Screenshots

No visual change.

Testing

  • pnpm typecheck (green)
  • pnpm oxlint on all touched files (clean)
  • agent-followup-delivery.test.ts — NEW. Pins the real config entries (aider, mistral-vibe) rather than synthetic agents. The python3-wrapper-with-live-child cases fail on pre-fix code (prompt dropped after full ~4.5s poll, no write) and pass post-fix; the bare-shell cases still correctly refuse to type; the already-resolved (foreground === 'aider') case keeps working.
  • new-workspace.test.ts — added toast-on-drop tests for both the follow-up and draft branches (drop → toast; success → no toast; draft onTimeout invokes the toast), and updated the existing exact-match pasteDraft assertions for the new onTimeout arg.
  • Ran agent-ready-wait, agent-process-recognition, pty-shell-utils suites alongside — 65 passed / 5 files.

AI Review Report

Reviewed for: correctness of the readiness relaxation (the new branch is gated behind attempt >= 4, requires a non-shell wrapper foreground AND a live non-shell child — identical to the existing accepted waitForAgentReady heuristic, so it doesn't newly type into an arbitrary shell); SSH parity (traced the relay path: getForegroundProcessName resolves the wrapped descendant when it can, and falls back to python3 otherwise; hasChildProcesses over SSH is pgrep on the shell pid, which is true when the agent child is live — so the new signal fires on both transports); no protocol change; file-boundary compliance (did NOT touch agent-paste-draft.ts, draft-paste-ready-scanner.ts, or tui-agent-config.ts — PR #7862's territory). Cross-platform: isAgentForegroundWrapperProcess already covers node/python/python3; Windows foreground resolution has its own path and is unaffected; no shell/path/shortcut assumptions added.

Security Audit

The follow-up path still refuses to write into a bare shell — the relaxation only accepts a recognized non-shell agent-wrapper foreground with a live child, so user/task text is not typed into an arbitrary prompt. No new input handling, command execution, path handling, auth, secrets, dependency, or IPC surface. The toast wiring only surfaces an existing best-effort UI message.

Notes

  • SSH story: no relay protocol addition needed — the fix relies only on fields the inspection RPC already returns (foregroundProcess, hasChildProcesses), so it works over SSH where the relay reports remote python3.
  • Two separate commits (delivery fix, then failure-surface wiring). Do not merge — flagging for review.

Made with Orca 🐋

Jinwoo-H and others added 2 commits July 10, 2026 05:48
…agents (aider/vibe)

Co-authored-by: Orca <help@stably.ai>
… is dropped

Co-authored-by: Orca <help@stably.ai>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Interpreter-wrapped agent processes are now treated as ready when they are non-shell foreground processes with child processes after repeated polling. Startup terminal setup now displays a notification when follow-up prompt delivery fails or draft prompt pasting times out. Tests cover wrapper detection, shell refusal, exact process matches, delivery outcomes, timeout callbacks, and updated mock expectations.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: prompt delivery fixes and surfacing dropped deliveries for wrapped agents.
Description check ✅ Passed The description includes all required sections and covers summary, screenshots, testing, review, security, and notes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/renderer/src/lib/agent-followup-delivery.test.ts (1)

35-73: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test case for wrapper foreground without child processes.

The parameterized loop tests python3 + hasChildProcesses: true (delivers) and zsh + hasChildProcesses: false (refuses), but no case verifies that python3 + hasChildProcesses: false is refused. Without this, someone could remove the process.hasChildProcesses guard and all tests would still pass.

✅ Suggested additional test case
     it(`still refuses to type into a bare ${agent} shell foreground`, async () => {
       vi.mocked(inspectRuntimeTerminalProcess).mockResolvedValue({
         foregroundProcess: 'zsh',
         hasChildProcesses: false
       })

       const delivered = await sendFollowupPromptWhenAgentReady({
         ptyId: 'pty-1',
         expectedProcess,
         prompt: 'ship it',
         settings: null
       })

       expect(delivered).toBe(false)
       expect(sendRuntimePtyInputVerified).not.toHaveBeenCalled()
     })
+
+    it(`refuses to type into a ${agent} wrapper with no live child`, async () => {
+      // Foreground is python3 (a recognized wrapper) but no child process is
+      // running — the agent hasn't taken over the PTY yet, so don't write.
+      vi.mocked(inspectRuntimeTerminalProcess).mockResolvedValue({
+        foregroundProcess: 'python3',
+        hasChildProcesses: false
+      })
+
+      const delivered = await sendFollowupPromptWhenAgentReady({
+        ptyId: 'pty-1',
+        expectedProcess,
+        prompt: 'ship it',
+        settings: null
+      })
+
+      expect(delivered).toBe(false)
+      expect(sendRuntimePtyInputVerified).not.toHaveBeenCalled()
+    })
   }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 057b3c66-3ab9-4753-a863-30b8ca9d2803

📥 Commits

Reviewing files that changed from the base of the PR and between c17d7cd and 167deb9.

📒 Files selected for processing (4)
  • src/renderer/src/lib/agent-followup-delivery.test.ts
  • src/renderer/src/lib/agent-followup-delivery.ts
  • src/renderer/src/lib/new-workspace.test.ts
  • src/renderer/src/lib/new-workspace.ts

@Jinwoo-H

Copy link
Copy Markdown
Contributor Author

Superseded by #8141, which combines all ten remote-reliability audit fixes, incorporates the valid CodeRabbit follow-ups, and has full CI plus live Electron/SSH validation. Closing this standalone PR so #8141 is the single review target; this fix remains included there.

@Jinwoo-H Jinwoo-H closed this Jul 10, 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