Skip to content

feat(task-input): show prompt in chat thread immediately on submit#2310

Open
fercgomes wants to merge 2 commits into
mainfrom
posthog-code/snappier-task-submit
Open

feat(task-input): show prompt in chat thread immediately on submit#2310
fercgomes wants to merge 2 commits into
mainfrom
posthog-code/snappier-task-submit

Conversation

@fercgomes
Copy link
Copy Markdown
Contributor

@fercgomes fercgomes commented May 22, 2026

Summary

Submitting a new task used to leave the user on TaskInput (with a spinning submit button) until the saga finished creating the task, folder, and workspace. Only then did onTaskReady fire and navigate to TaskDetail, where SessionView showed a full-screen spinner until the agent session connected and applyOptimisticPrompt wrote the user message into the optimistic store. The flow felt sluggish because each step blocked the UI from showing the prompt.

This change navigates to a thread-style view synchronously on submit:

  • New task-pending view in navigationStore (transient — excluded from persistence; replaced in history on transition so back doesn't land on a stale placeholder).
  • pendingTaskPromptStore holds the prompt text keyed first by a client-generated UUID, then re-keyed to the real task id once the saga returns.
  • PendingChatView renders the user-message bubble + "Connecting to agent..." footer with the same layout as SessionView's connected state. TaskPendingView wraps it for the view-router; SessionView's initializing branch also renders it when a pending entry exists, bridging the gap until applyOptimisticPrompt fires.
  • useTaskCreation.handleSubmit stashes the prompt, navigates to the pending view, then runs the saga. On failure it clears the pending entry and navigates back to task-input with initialPrompt preserved.
  • MainLayout, useSidebarData, and TaskListView treat task-pending like task-input for sidebar/SpaceSwitcher state. CommandCenterPanel's onTaskCreated override skips the pending view so its existing flow is untouched.
Screen.Recording.2026-05-22.at.16.23.08.mov

Test plan

  • pnpm --filter code typecheck clean
  • 2 new navigation-store tests cover navigateToPendingTask and the history-replace behavior
  • All 914 renderer tests pass
  • Manual: submit a local task — confirm thread + prompt appear immediately, then spinner, then agent response streams in
  • Manual: submit a worktree task — pending view stays during provisioning, transitions seamlessly to TaskDetail
  • Manual: submit a cloud task — pending view shows during saga's cloud setup, then CloudInitializingView takes over
  • Manual: simulate a saga failure — pending view goes back to task-input with the prompt restored
  • Manual: submit from CommandCenterPanel — no pending view; existing flow unchanged
  • Manual: press back from TaskDetail after submit — lands on task-input, not the empty pending placeholder

@fercgomes fercgomes marked this pull request as ready for review May 22, 2026 19:23
@fercgomes fercgomes requested review from a team and jonathanlab May 22, 2026 19:23
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 22, 2026

Comments Outside Diff (1)

  1. apps/code/src/renderer/features/task-detail/hooks/useTaskCreation.ts, line 239-244 (link)

    P1 After editor.clear() is called inside the if (pendingTaskKey) block, editor.getText() returns "". The nullish-coalescing operator ?? only falls back for null/undefined, not empty strings, so "" ?? plainPromptText evaluates to "". The if (plainText) guard then fails, and addPrompt is never called — meaning the task input history is silently skipped on every normal submission that shows the pending view.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/code/src/renderer/features/task-detail/hooks/useTaskCreation.ts
    Line: 239-244
    
    Comment:
    After `editor.clear()` is called inside the `if (pendingTaskKey)` block, `editor.getText()` returns `""`. The nullish-coalescing operator `??` only falls back for `null`/`undefined`, not empty strings, so `"" ?? plainPromptText` evaluates to `""`. The `if (plainText)` guard then fails, and `addPrompt` is never called — meaning the task input history is silently skipped on every normal submission that shows the pending view.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
apps/code/src/renderer/features/task-detail/hooks/useTaskCreation.ts:239-244
After `editor.clear()` is called inside the `if (pendingTaskKey)` block, `editor.getText()` returns `""`. The nullish-coalescing operator `??` only falls back for `null`/`undefined`, not empty strings, so `"" ?? plainPromptText` evaluates to `""`. The `if (plainText)` guard then fails, and `addPrompt` is never called — meaning the task input history is silently skipped on every normal submission that shows the pending view.

```suggestion
        if (!contentOverride) {
          const plainText = (pendingTaskKey ? plainPromptText : editor.getText()?.trim()) ?? plainPromptText;
          if (plainText) {
            useTaskInputHistoryStore.getState().addPrompt(plainText);
          }
        }
```

### Issue 2 of 3
apps/code/src/renderer/features/sessions/components/PendingChatView.tsx:8-9
The JSDoc says "skip the absolute fill wrapper" when `embedded` is true, but the code does the opposite — it *adds* an `absolute inset-0` wrapper. The comment should describe that the absolute wrapper is added so the component fills an existing `relative` container.

```suggestion
  /** Render inside an existing `relative` positioned container — wraps content in `absolute inset-0` to fill it. */
  embedded?: boolean;
```

### Issue 3 of 3
apps/code/src/renderer/stores/pendingTaskPromptStore.ts:3-7
**Stored fields never consumed**

`attachmentLabels` is populated in `useTaskCreation` but `PendingChatView` only uses `promptText` — the labels are never rendered. `createdAt` is similarly stored but not read anywhere. Per the simplicity rule of having no superfluous parts, both fields can be removed until there is a consumer for them.

Reviews (1): Last reviewed commit: "feat(task-input): show prompt in chat th..." | Re-trigger Greptile

Comment on lines +8 to +9
/** Render inside an existing positioned container — skip the absolute fill wrapper. */
embedded?: boolean;
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.

P2 The JSDoc says "skip the absolute fill wrapper" when embedded is true, but the code does the opposite — it adds an absolute inset-0 wrapper. The comment should describe that the absolute wrapper is added so the component fills an existing relative container.

Suggested change
/** Render inside an existing positioned container — skip the absolute fill wrapper. */
embedded?: boolean;
/** Render inside an existing `relative` positioned container — wraps content in `absolute inset-0` to fill it. */
embedded?: boolean;
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/sessions/components/PendingChatView.tsx
Line: 8-9

Comment:
The JSDoc says "skip the absolute fill wrapper" when `embedded` is true, but the code does the opposite — it *adds* an `absolute inset-0` wrapper. The comment should describe that the absolute wrapper is added so the component fills an existing `relative` container.

```suggestion
  /** Render inside an existing `relative` positioned container — wraps content in `absolute inset-0` to fill it. */
  embedded?: boolean;
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread apps/code/src/renderer/stores/pendingTaskPromptStore.ts
@adboio
Copy link
Copy Markdown
Contributor

adboio commented May 22, 2026

this is FIRE, thank you, one of my biggest pet peeves

[mostly typing before i forget, and maybe so i can use this comment as a prompt later 😂] as a followup i might try to make the loading state a bit more obvious too - maybe putting the input box at the bottom immediately as a shimmer loader or disabled, and putting a "starting task..." loader below the initial msg that looks like a normal agent loading state

@adboio adboio self-assigned this May 22, 2026
Previously, submitting a new task left the user staring at the `TaskInput` form (with its submit button spinning) until the saga finished creating the task, registering the folder, and creating the workspace. Only then would `onTaskReady` fire and navigate to `TaskDetail`, where `SessionView` would show a full-screen spinner until the agent session connected and `applyOptimisticPrompt` wrote the user message into the optimistic store. The flow felt sluggish because each of those steps blocked the UI from showing the user's prompt.

This change navigates to a thread-style view synchronously on submit:

- New `task-pending` view in `navigationStore` (transient — excluded from persistence; replaced in history on transition so back doesn't land on a stale placeholder).
- `pendingTaskPromptStore` holds the prompt text keyed first by a client-generated UUID, then re-keyed to the real task id once the saga returns.
- `PendingChatView` renders the user-message bubble + "Connecting to agent..." footer using the same layout as `SessionView`'s connected state. `TaskPendingView` wraps it for the view-router; `SessionView`'s initializing branch also renders it when a pending entry exists, bridging the gap until `applyOptimisticPrompt` fires.
- `useTaskCreation.handleSubmit` stashes the prompt, navigates to the pending view, then runs the saga. On failure it clears the pending entry and navigates back to `task-input` with `initialPrompt` preserved.
- `MainLayout`, `useSidebarData`, and `TaskListView` treat `task-pending` like `task-input` for sidebar/SpaceSwitcher state. `CommandCenterPanel`'s `onTaskCreated` override skips the pending view so its existing flow is untouched.

Tests: 2 new navigation-store tests cover `navigateToPendingTask` and the history-replace behavior; all 914 renderer tests pass.

Generated-By: PostHog Code
Task-Id: c34038da-f59d-4a38-8487-e5f3c6a1ef78
@adboio adboio force-pushed the posthog-code/snappier-task-submit branch from a3cf016 to dcf7ea0 Compare May 22, 2026 20:55
Copy link
Copy Markdown
Contributor

adboio commented May 22, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@adboio
Copy link
Copy Markdown
Contributor

adboio commented May 22, 2026

rebased to bring in the merged bulk archive, testing & reviewing now!

Copy link
Copy Markdown
Contributor

adboio commented May 22, 2026

turns out that feedback was quick for code to implement 😛 thoughts?

speedy-task-startup-demo.mp4 (uploaded via Graphite)

…initializes

Replaces the centered "Connecting to agent..." footer in the pending chat
view with a non-interactive `PromptInput` skeleton at the bottom and an
inline "Starting task..." indicator directly below the user message —
the screen now looks identical in layout to the live chat, so there is
no visible jump when init finishes.

Also carries the full attachment list through the pending prompt store
so attachment chips render under the user message in the pending view.

Generated-By: PostHog Code
Task-Id: 51016b35-b815-4839-bfbd-5a24cd9356ff
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.

2 participants