🤖 fix: send queued message with empty Enter#3592
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4af7df4595
ℹ️ 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".
4af7df4 to
7d94b95
Compare
|
@codex review Please take another look after the edit-mode guard fix. |
7d94b95 to
41c2e3f
Compare
|
@codex review Please review the latest pushed commit; the previous edit-mode thread is addressed and resolved. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 41c2e3fb67
ℹ️ 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".
41c2e3f to
d641c90
Compare
|
@codex review Please review the latest pushed commit; the repeated Enter in-flight guard is addressed and the thread is resolved. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d641c9038e
ℹ️ 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".
d641c90 to
d6c5275
Compare
|
@codex review Please review the latest pushed commit; the stale queued-message window is guarded until the queued id changes/clears, and the test now covers a fast second Enter press. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6c527592b
ℹ️ 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".
Move the queued Enter shortcut into ChatInput's existing key/state path and exercise it through the user-visible queued-send flow.\n\n---\n\n_Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `n/a`_\n\n<!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=n/a --> Signed-off-by: Thomas Kosiewski <tk@coder.com>
d6c5275 to
6beed0c
Compare
|
@codex review Please review the latest pushed commit; the guard now resets on |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
## Summary Long-lived auto-cleanup PR maintained by the **Auto-Cleanup Agent**. Each pass lands at most one extremely low-risk, behavior-preserving cleanup drawn from recently merged `main` activity, then advances the checkpoint below. The prior long-lived PR (coder#3559) merged into `main`; this is its successor. Auto-cleanup checkpoint: 2af29df ## This pass Considered the one new `main` commit since the previous checkpoint — coder#3603 (`feat: add built-in loop skill`). That change adds the advertised `loop` built-in skill (`src/node/builtinSkills/loop.md`), regenerates `builtInSkillContent.generated.ts` (generated — off-limits), and extends the agent-skills discovery test expectations. The skill-content/generated surface offers no safe hand-edit, so the cleanup was drawn from the production sibling of that area: the skill-discovery service `agentSkillsService.ts`. Landed one behavior-preserving cleanup in `agentSkillsService.ts`: `readSkillDescriptorFromDir` open-coded the same invalid-skill diagnostic push — `options?.invalidSkills?.push({ directoryName, scope, displayPath: skillFilePath, message, hint })` — at six failure sites (missing/unreadable SKILL.md, SKILL.md-is-a-directory, oversized file, read failure, invalid descriptor, parse failure). Those six sites share identical identity fields (`directoryName` / `scope` / `displayPath`) and differ only in `message` + `hint`. All six now delegate to a single function-local `pushInvalidSkill(message, hint)` closure that captures the function-constant identity fields. Behavior-preserving: the pushed object shape and every per-site `message`/`hint` are unchanged, and the closure short-circuits on `options?.invalidSkills` exactly as the inline calls did. ## Branch contents (net diff against `main`) <details> <summary>Cleanups carried by this PR (not yet merged)</summary> - **`agentSkillsService.ts` — dedupe invalid-skill diagnostics.** coder#3603's new built-in skill lives in the agent-skills discovery area; `readSkillDescriptorFromDir` open-coded the same `options?.invalidSkills?.push({ directoryName, scope, displayPath: skillFilePath, message, hint })` at six failure sites that share identical identity fields and differ only in `message`/`hint`. All six now delegate to a single function-local `pushInvalidSkill(message, hint)` closure. Behavior-preserving (identical pushed shape, messages, hints, and `options?.invalidSkills` short-circuit). - **`workspaceGoalService.ts` — dedupe session file path resolution.** The three private accessors `getFilePath` / `getHistoryFilePath` / `getBoardFilePath` each open-coded the same `assert(...non-empty workspaceId)` guard and `path.join(getSessionDir(...), <FILE_CONST>)`. All three now delegate to a single `resolveSessionFilePath(workspaceId, fileName)` helper. Behavior-preserving (identical guard + join; accessor names and callers unchanged). - **`task.ts` — dedupe plan-agent explore-only error.** The plan-agent restriction error `In the plan agent you may only spawn agentId: "explore" tasks.` was open-coded twice (the workspace-turn guard and the per-launch agent-id guard). Both now reference a single module-level `PLAN_AGENT_EXPLORE_ONLY_ERROR` constant. Behavior-preserving (identical string output). - **`task_await.ts` — dedupe workspace-turn error fallback.** coder#3600's new workspace-turn await paths open-coded the fallback error message `"Workspace turn failed"` three times (`<record>.error ?? "Workspace turn failed"`). All three now reference a single module-level `WORKSPACE_TURN_DEFAULT_ERROR` constant. Behavior-preserving (identical string output). - **`goalToolUtils.tsx` / `SetGoalToolCall.tsx` — dedupe turn-count pluralization.** coder#3595's new goal toolcards open-coded `` `${n} turn${n === 1 ? "" : "s"}` `` in both `formatGoalTurns` and the set_goal toolcard's `formatOptionalTurnCap`. Both now call a shared `pluralizeTurns(count)` helper. Behavior-preserving (identical string output). - **`heartbeat.ts` — dedupe heartbeat tool success result construction.** coder#3596's new `heartbeat` tool open-coded the same `{ success: true, action, configured, settings, summary }` success object three times (`get` / `set` / `unset`), each re-calling `summarize({ action, settings })`. All three now route through a single `buildSuccessResult(action, settings)` helper that derives `configured` from `settings`. Behavior-preserving: the per-branch `configured` values (`settings != null`, `false`, `true`) all equal `settings != null` given the non-null `Ok` payload type for `set`. - **`taskService.ts` — dedupe startup recovery candidate listing.** coder#3594's `TaskService.initialize` open-coded the `awaiting_report` / `running` candidate filters twice (initial computation and post-interrupt refresh). Both call sites now reuse a single `listStartupRecoveryCandidates(sourceConfig)` closure returning `{ awaitingReportTasks, runningTasks }`, matching the existing `listQueuedTasks` pattern. Behavior-preserving. - **`ChatPane.tsx` — dedupe send-queued-immediately in-flight guard clear.** coder#3592 introduced `sendQueuedImmediatelyInFlightRef` to block duplicate send-now attempts; releasing that guard ("clear it only if it still points at this attempt") was open-coded twice — once after a failed interrupt result and once in the `catch` arm. Both call sites now invoke a single callback-local closure `clearInFlightGuardIfCurrent()`. Behavior-preserving: the failed-result site's combined `!interruptResult.success && ref === id` becomes `if (!interruptResult.success) clearInFlightGuardIfCurrent()` (logically identical); the `catch` site is a verbatim substitution. - **`WorkflowRunner.ts` — dedupe `parallelAgents` child-failure abort handling** into a single batch-local closure `applyChildFailureToBatch(error)`, shared by the per-run task closure and the bulk-create path. - **`ChatInput/index.tsx` — dedupe edit-mode attachment toast** string `"Attachments cannot be added while editing a message."` into a single module-level constant `EDIT_MODE_ATTACHMENT_ERROR_MESSAGE`, replacing three inline copies across the add-attachment / paste / drop guards. </details> <details> <summary>Prior passes (landed via coder#3559, merged)</summary> - Replaced an inline terminal-status check in `WorkflowService.interruptRunOnAbort` with the `isTerminalWorkflowRunStatus` helper. - Deduplicated the `workspaceId`-only metadata JSON Schema repeated by three id-targeted host actions in `workspaceHostActions.ts` into `WORKSPACE_ID_ONLY_INPUT_SCHEMA`. - Extracted a shared `BlockedBadge` component in `WorkflowDefinitionToolCall.tsx`. - Deduplicated the repeated `argsSchema.properties must be an object` error string in `workflowArgs.ts`. - Deduplicated mocked-module specifier strings in `useModelsFromSettings.test.ts`. - Removed a redundant `toggleWorkflowExpanded` wrapper in `WorkflowRunToolCall.tsx`. - Deduplicated `SAVE_AUTOMATION_ERROR_MESSAGE` / `REMOVE_AUTOMATION_ERROR_MESSAGE` in `AutomationModal.tsx`. - Replaced a duplicated `"wfr_"` literal in `WorkflowRunner.ts` with `isWorkflowRunTaskId()`. </details> ## Validation - `make static-check` — ESLint, both `tsgo` typecheck configs, and Prettier all pass on the rebased tree. The only failing step is `fmt-shell-check`, which requires `shfmt` (not installed in this environment); no shell scripts were touched, so CI (which has `shfmt`) is unaffected. - `bun test src/node/services/agentSkills/agentSkillsService.test.ts` — 20 pass, 0 fail (covers skill discovery + the invalid-skill diagnostics path this pass deduped); `builtInLoopSkill.test.ts` — 1 pass. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-8` • Thinking: `xhigh`_ <!-- mux-attribution: model=anthropic:claude-opus-4-8 thinking=xhigh --> --------- Co-authored-by: mux-bot[bot] <264182336+mux-bot[bot]@users.noreply.github.com>
Summary
Enable pressing Enter in an empty workspace composer to trigger the queued-message “Send now” action, so queued follow-ups can be dispatched immediately without using the mouse.
Background
When a follow-up is queued to send after the active turn, the UI already exposes a “Send now” button in the queued-message banner. Keyboard-only users could queue the follow-up, but then still needed pointer interaction to send it immediately.
Implementation
ChatPaneinto the workspaceChatInput.ChatInputwhen the workspace composer is empty, a queued message exists, there are no staged attachments or reviews, the user is not editing a prior message, and the layout is not mobile-touch.Validation
bun x jest tests/ui/chat/sendModeDropdown.test.ts -t "pressing Enter on an empty composer sends the queued message now" --runInBandmake static-check./scripts/wait_pr_ready.sh 3592Risks
Low. The shortcut only fires for workspace chat inputs with an existing queued message, an empty text draft, no attachments, no attached reviews, non-editing mode, and non-mobile touch layout; duplicate send-now attempts are ignored while the queued id is being flushed.
Generated with
mux• Model:openai:gpt-5.5• Thinking:xhigh• Cost:$30.42