Skip to content

feat(mobile): steer and discard queued messages (port #2768)#2774

Open
Gilbert09 wants to merge 3 commits into
mainfrom
posthog-code/mobile-queued-message-actions
Open

feat(mobile): steer and discard queued messages (port #2768)#2774
Gilbert09 wants to merge 3 commits into
mainfrom
posthog-code/mobile-queued-message-actions

Conversation

@Gilbert09

Copy link
Copy Markdown
Member

Problem

Mobile already lets you queue follow-up messages while a cloud task is running (#2752), but a queued message could only be counted — there was no way to act on one. This ports the desktop queued-message management from #2768 to the mobile app, using native mobile interaction instead of the desktop dock layout.

Changes

  • Queued messages dock — queued messages now render as compact rows pinned above the composer. Tapping a row opens a bottom-sheet (SheetContainer) with the available actions.
  • Steer now — drops the message from the queue and resends it as a steer (cloud interrupt + resend via sendInterrupting). Rolls the message back onto the head of the queue if the resend fails so it is never silently lost, and no-ops while the task is compacting (steering would abort the in-flight compaction). Only offered while a turn is live.
  • Edit in composer — pulls the message (text + attachments) back into TaskChatComposer to revise before re-sending.
  • Discard — removes a single queued message by id.
  • Queued messages now carry a stable id, and the session tracks isCompacting from the cloud _posthog/status / _posthog/compact_boundary stream so steer can be gated.

No desktop/shared code was changed.

Tests

  • messageQueueStore.test.ts — discard removes exactly the targeted message, clears the entry when empty, and ignores unknown ids.
  • taskSessionStore.test.ts — steer removes + resends, rolls back onto the head on failure, and no-ops during compaction / for unknown ids.

Full mobile suite (pnpm test), pnpm lint, and typecheck pass.

How did you test this?

Unit tests for the queue-mutation and steer logic; lint + typecheck clean.

Mobile already supports queuing follow-up messages while a cloud task runs
(#2752), but queued messages could only be counted, not acted on. This adds
per-message management, mirroring the desktop dock from #2768 with native
mobile interaction.

- Queued messages now render in a dock above the composer; tapping one opens
  a bottom-sheet with Steer now / Edit in composer / Discard.
- Steer now: drop the message from the queue and resend it as a steer
  (interrupt + resend), rolling it back onto the head if the resend fails so
  it is never silently lost. No-ops while the task is compacting.
- Edit in composer: pull the message (text + attachments) back into the
  composer to revise before resending.
- Discard: remove a single queued message by id.
- Track compaction state on the session from the cloud status stream so steer
  can be gated.

Adds tests for queue removal and steer rollback-on-failure / compaction
no-op.

Generated-By: PostHog Code
Task-Id: 899edfb9-ddb5-4e11-b640-917d167266bc
@Gilbert09 Gilbert09 requested a review from a team June 19, 2026 10:53
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

React Doctor found 2 issues in 1 file · 2 warnings.

2 warnings

src/features/tasks/composer/TaskChatComposer.tsx

Reviewed by React Doctor for commit d9c4c7d.

@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
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/mobile/src/features/tasks/stores/messageQueueStore.test.ts:69-93
**Prefer parameterised tests for `remove` cases**

The three new `remove` tests differ only in initial queue contents, the target to remove, and expected output — a classic `it.each` candidate. The same pattern applies to the four `steerQueuedMessage` cases in `taskSessionStore.test.ts` (success, rollback-on-failure, no-op during compaction, no-op for unknown id). The team rule is to always prefer parameterised tests; consolidating these would remove the repeated setup boilerplate and make it easier to add edge cases later.

### Issue 2 of 3
apps/mobile/src/features/tasks/stores/taskSessionStore.ts:819-823
**`steerQueuedMessage` only guards on `isCompacting`, not `isPromptPending`**

The dock UI gates the "Steer now" action with `canSteer = isPromptPending && !isCompacting && !terminalStatus`, but the store action itself only returns early when `isCompacting` is set. If `sendInterrupting` is called from the store when no turn is live (e.g. `isPromptPending` is false due to a race between the UI check and this function executing), it could trigger an interrupt on an idle session. Adding a matching `session.isPromptPending` guard in `steerQueuedMessage` would enforce the same invariant at the store level and make the function safe to call directly in tests without relying on UI pre-conditions.

### Issue 3 of 3
apps/mobile/src/features/tasks/stores/taskSessionStore.ts:195-208
**`isCompacting` stream-event parsing has no unit tests**

The new `_posthog/status` / `_posthog/compact_boundary` handling in `analyzeEntries` determines whether steering is offered at all, but there are no tests that exercise this code path through the event stream. The `taskSessionStore.test.ts` tests verify `steerQueuedMessage` behaviour by directly seeding `isCompacting: true`, which bypasses the parsing logic entirely. A scenario where a `_posthog/status { status: "compacting" }` event sets the flag and a subsequent `_posthog/compact_boundary` clears it would give confidence that the guard is actually derived correctly from the stream.

Reviews (1): Last reviewed commit: "feat(mobile): steer and discard queued m..." | Re-trigger Greptile

Comment thread apps/mobile/src/features/tasks/stores/messageQueueStore.test.ts Outdated
Comment thread apps/mobile/src/features/tasks/stores/taskSessionStore.ts Outdated
Comment thread apps/mobile/src/features/tasks/stores/taskSessionStore.ts
- Guard steerQueuedMessage on isPromptPending so the store enforces the same
  precondition as the dock's canSteer, rather than relying on the UI gate.
- Parameterise the queue remove tests with it.each.
- Add a test that drives _handleCloudUpdate with _posthog/status and
  _posthog/compact_boundary entries to verify isCompacting is derived from the
  log stream, plus a no-turn-running steer no-op case.

Generated-By: PostHog Code
Task-Id: 899edfb9-ddb5-4e11-b640-917d167266bc
Generated-By: PostHog Code
Task-Id: 53e96da3-2e75-4009-99fd-cb663cf1800b
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