Skip to content

feat(web): simplify message delivery controls - #1314

Draft
mindfn wants to merge 5 commits into
mainfrom
feat/1306-message-delivery-ux
Draft

feat(web): simplify message delivery controls#1314
mindfn wants to merge 5 commits into
mainfrom
feat/1306-message-delivery-ux

Conversation

@mindfn

@mindfn mindfn commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

What

Closes #1307.

  • makes global Queue / Append the only everyday delivery choice; one-shot Append is explicit and never interrupts a reply
  • maps the conversation Stop control to the existing whole-thread force-reset behavior, with visible request failure feedback
  • makes Steer confirmation explicit that it stops the target reply before sending

Verification

  • cross-family review: Fable approved the final two commits
  • targeted API + web tests: 65 passing
  • isolated UI preview: frontend and API health checks returned 200

Known non-blocking

  • Review noted a P3, non-runtime ChatInput comment wording cleanup; behavior and tests are unaffected.

mindfn added 2 commits August 7, 2026 15:00
Why: users need one understandable delivery choice, a truthful whole-conversation Stop, and an explicit destructive Steer confirmation instead of overlapping cancellation semantics.
Why: a failed durable stop request must not leave the conversation appearing stopped without feedback.
@mindfn
mindfn requested a review from zts212653 as a code owner August 7, 2026 08:36

@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: f81b884278

ℹ️ 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".

? dispositionCarrierSupport === 'exact'
? (messageDisposition.oneShot ?? undefined)
: 'next_work'
? (messageDisposition.oneShot ?? messageDisposition.effective)

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 Let the server resolve an unhydrated global disposition

When active work first appears and the preference GET is still pending or has failed, messageDisposition.effective remains the local next_work default. Sending that value explicitly gives it precedence in resolveMessageDispositionForAdmission, so a persisted global continue_current preference is silently ignored and the message is queued. Send only the one-shot override explicitly, or wait until preference hydration succeeds before sending the effective value.

Useful? React with 👍 / 👎.

// #1307: a conversation-level Stop is always a full-thread stop. Per-cat
// cancellation remains an internal control-plane primitive and Steer uses
// its dedicated, explicitly destructive path.
cancelFn(threadId, undefined);

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 Defer local Stop cleanup until force-reset succeeds

When the new force-reset POST rejects or returns a non-2xx response, cancelInvocation only displays an error toast, but handleStop immediately proceeds to clear callbacks, active invocation slots, and streaming state. The server invocation therefore continues while the UI removes its liveness indicators and Stop control, potentially also dropping subsequent output until a refresh or rehydration. Return and await the request result, clearing local state only after success or restoring it on failure.

Useful? React with 👍 / 👎.

mindfn added 2 commits August 7, 2026 16:51
Why: delivery preference belongs with append custody; this PR now contains only the destructive Stop and Steer interaction.
Why: a rejected whole-thread Stop must leave the visible invocation state intact so users can retry or inspect the failure.
@mindfn

mindfn commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review the latest head; prior inline findings were addressed in subsequent commits.

@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: de0db64c4b

ℹ️ 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".

// its dedicated, explicitly destructive path.
const clearStoppedThread = () => {
clearPendingCallbacksForThread(threadId);
const isActiveThreadStop = threadId === store.currentThreadId;

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 Re-read the active thread after the Stop request

When a user stops foreground thread A and navigates to an already-running thread B before the force-reset request resolves, store is the Zustand snapshot captured before the request, so this comparison still treats A as active. The success callback then calls active-thread helpers such as clearAllActiveInvocations(), which operate on the store's current thread and clear B's running/streaming UI instead of only A. Read the current state after the await (or always perform thread-scoped cleanup) before selecting the cleanup branch.

Useful? React with 👍 / 👎.

Why: a force-reset can finish after navigation; re-reading the store prevents the prior thread's Stop from clearing the newly active thread's running state.
@mindfn

mindfn commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review the latest head; this addresses the newly reported cross-thread async Stop P1.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: fb5f51ba09

ℹ️ 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".

@mindfn
mindfn marked this pull request as draft August 7, 2026 09:34
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.

UX:收敛消息投递策略,并统一停止与 Steer 语义

1 participant