Skip to content

fix(coding-agent): keep custom-editor Enter submissions from being dropped - #908

Open
Tinycute00 wants to merge 1 commit into
code-yeongyu:mainfrom
Tinycute00:fix/custom-editor-submit-dropped
Open

fix(coding-agent): keep custom-editor Enter submissions from being dropped#908
Tinycute00 wants to merge 1 commit into
code-yeongyu:mainfrom
Tinycute00:fix/custom-editor-submit-dropped

Conversation

@Tinycute00

@Tinycute00 Tinycute00 commented Aug 16, 2026

Copy link
Copy Markdown

Symptom

With a custom editor component installed via ctx.ui.setEditorComponent() (e.g. the pi-voice-stt dictation extension), pressing Enter clears the prompt but the message is never sent — no user message, no model activity, no error. With such an extension installed, the TUI cannot submit any user input at all, including normally typed text.

Root cause

setCustomEditorComponent() wires the custom editor's submit through expandEditorSubmission(newEditor, text):

newEditor.onSubmit = (text) => {
	this.defaultEditor.onSubmit?.(expandEditorSubmission(newEditor, text));
};

expandEditorSubmission() prefers editor.getExpandedText() over the passed text. But pi-tui's Editor.submitValue() clears the editor state and paste registry before invoking onSubmit:

const result = this.pasteMarkers.expand(this.state.lines.join("\n")).trim();
this.state = { lines: [""], cursorLine: 0, cursorCol: 0 };
this.pasteMarkers.clear();
// ...
if (this.onSubmit) this.onSubmit(result);

So for any custom editor that implements getExpandedText() — a thin wrapper delegating to a pi-tui Editor, which is exactly what pi-voice-stt does — the bridge re-reads the already-cleared editor, gets "", and defaultEditor.onSubmit("") returns early on the empty-text guard. Because the editor was cleared, to the user it looks like "Enter did nothing".

Fix

Add expandSubmittedText() next to expandEditorSubmission() and use it at the submit call site only. It expands paste markers against the passed (authoritative) text and never re-reads the editor. The live-draft read path (getExpandedEditorText()) keeps the existing getExpandedText() preference, so draft-read behavior is unchanged.

changes.md entry included per the fork contract.

Reproduction (before this patch)

  1. Install a custom-editor extension that wraps the pi-tui Editor and exposes getExpandedText() (pi-voice-stt).
  2. Type anything, press Enter.
  3. Prompt clears; nothing is submitted. After the patch: the message sends normally.

Verified end-to-end on a real TUI (omo, senpi engine 2026.8.12-4, Linux, xterm-256color) with pi-voice-stt installed:

  • Before the fix: typed text + Enter → editor cleared, nothing sent (no session activity). Same for voice transcripts inserted into the prompt.
  • After the fix: typed text + Enter → message sent, model responded. Full voice loop ctrl+r → record → ctrl+r → transcript inserted into prompt → Enter → message sent, model responded.

Tests

  • New packages/coding-agent/test/editor-paste-transfer.test.ts (4 tests, deterministic, offline):
    • submit path keeps the passed text when the editor was already cleared (the regression);
    • submit path expands paste markers via the editor's paste registry;
    • submit path passes text through when no paste registry exists;
    • expandEditorSubmission() (live draft reads) still prefers getExpandedText().

Summary by cubic

Prevents custom-editor Enter submissions from being dropped by expanding paste markers against the submitted text at submit time. Previously, with editors implementing getExpandedText (e.g., pi-voice-stt wrapping @earendil-works/pi-tui), Enter cleared the prompt but sent nothing; now Enter sends the message, and live draft reads remain unchanged.

  • Switch the submit bridge in interactive-mode.ts to use expandSubmittedText(...); keep expandEditorSubmission(...) for live draft reads.
  • Add tests in packages/coding-agent/test/editor-paste-transfer.test.ts for submit-time behavior and paste expansion.
  • Review focus: one call site and one import changed in interactive-mode.ts; new export added in editor-paste-transfer.ts (low risk).

Written for commit b4bf8bb. Summary will update on new commits.

Review in cubic

…opped

The custom-editor submit bridge in setCustomEditorComponent() expanded the
submission via expandEditorSubmission(), which prefers the editor's live
getExpandedText() over the passed text. pi-tui's Editor.submitValue()
clears the editor state and paste registry BEFORE invoking onSubmit, so
any custom editor implementing getExpandedText() (e.g. pi-voice-stt's
wrapper around the pi-tui Editor) was re-read as "" and the submission
was silently discarded: Enter cleared the prompt and nothing was sent.

Add expandSubmittedText() — paste-marker expansion against the passed,
authoritative text with no live editor re-read — and use it at the submit
call site. The live-draft read path (getExpandedEditorText) keeps the
existing getExpandedText() preference.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4bf8bbd3d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -0,0 +1,48 @@
import type { EditorComponent, EditorPasteState } from "@earendil-works/pi-tui";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Move the regression into the designated regression suite

This file specifically covers the dropped custom-editor submission regression, but it is added at the test root rather than under test/suite/regressions/, splitting related coverage from the existing editor-paste regression tests and violating the repository's required placement. Move these cases into a suitably named regression file in that directory, preferably alongside 0000-editor-paste-submit.test.ts.

AGENTS.md reference: packages/coding-agent/test/AGENTS.md:L40-L40

Useful? React with 👍 / 👎.

Comment on lines +27 to +29
export function expandSubmittedText(editor: EditorComponent, text: string): string {
const pasteState = editor.getPasteState?.();
return pasteState ? expandPasteMarkers(text, pasteState) : text;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve submit-time expansion for uncleared custom editors

When a custom EditorComponent invokes onSubmit before clearing its draft and relies on the optional getExpandedText() method to turn its own markers into submitted content, this helper now ignores that valid expanded value and forwards the raw callback text unless the component also exposes pi-tui paste state. The previous bridge supported this extension pattern, so such editors will silently submit marker placeholders after this change; use the passed text only when the live expanded read shows that the editor has already been cleared rather than unconditionally bypassing getExpandedText().

Useful? React with 👍 / 👎.

@@ -1,5 +1,25 @@
# changes

## Custom-editor Enter submissions are no longer dropped (2026-08-16)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Mirror the behavior change in the root change record

This new fork-visible behavior is recorded only in the nested interactive changes.md; packages/coding-agent/src/changes.md has no corresponding custom-editor submission entry. The package requires the root and nested change records to remain aligned, so upstream-sync and fork-behavior audits using the root record will miss this fix unless a matching entry is added in the same increment.

AGENTS.md reference: packages/coding-agent/AGENTS.md:L81-L81

Useful? React with 👍 / 👎.

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