-
Notifications
You must be signed in to change notification settings - Fork 1
feat(chat): steer a queued follow-up into the running turn #386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -165,6 +165,7 @@ import { | |
| resolveTurnModelForSend, | ||
| } from "@/store/prompt-draft-runtime"; | ||
| import { | ||
| applySteeredPromptDraft, | ||
| buildPreservedQueuedDraft, | ||
| resolvePromptDraftAfterSend, | ||
| resolvePromptDraftSendState, | ||
|
|
@@ -1949,11 +1950,16 @@ export const useAppStore = create<AppState>()( | |
| if (activeTurnId && activeTurnStalled) { | ||
| get().abortTaskTurn({ taskId: resolvedTaskId }); | ||
| } | ||
| if (queuedTurnToSend && activeTurnId && !activeTurnStalled) { | ||
| // Manual dispatch of a queued item only makes sense while no live | ||
| // turn is running — during an active turn the item is already in | ||
| // line to auto-dispatch, and falling through here would re-queue | ||
| // it as a duplicate. | ||
| // A queued item dispatched during a live turn is already in line to | ||
| // auto-dispatch, so sending it here would duplicate it — unless the | ||
| // caller explicitly asked to steer, which promotes it into the | ||
| // running turn instead of waiting (see the steer branch below). | ||
| if ( | ||
| queuedTurnToSend && | ||
| activeTurnId && | ||
| !activeTurnStalled && | ||
| submitIntent !== "steer" | ||
| ) { | ||
| return { status: "blocked" } satisfies SendUserMessageResult; | ||
| } | ||
| if (activeTurnId && !activeTurnStalled && submitIntent === "steer") { | ||
|
|
@@ -2055,21 +2061,15 @@ export const useAppStore = create<AppState>()( | |
| }); | ||
| const promptDraftByTask = | ||
| cachedSession?.promptDraftByTask ?? nextState.promptDraftByTask; | ||
| const currentDraft = promptDraftByTask[resolvedTaskId]; | ||
| const shouldClearSubmittedDraft = | ||
| !preservePromptDraft && currentDraft?.text === promptDraft.text; | ||
| const nextPromptDraftByTask = shouldClearSubmittedDraft | ||
| ? { | ||
| ...promptDraftByTask, | ||
| [resolvedTaskId]: normalizePromptDraftForStorage({ | ||
| ...(currentDraft ?? sourcePromptDraft), | ||
| text: "", | ||
| attachedFilePaths: [], | ||
| attachments: [], | ||
| promptBatch: undefined, | ||
| }), | ||
| } | ||
| : promptDraftByTask; | ||
| const nextPromptDraftByTask = applySteeredPromptDraft({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the steer acknowledgment is delayed until after the active turn completes, the queued item remains visible to Useful? React with 👍 / 👎.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Valid — fixed in 00204c9. Confirmed the window is real and wide: Added
Holds are in-memory and keyed by the item UUID, so a reload drops them with the turn they were ambiguous about and a stale key can never match a different item. Covered by |
||
| promptDraftByTask, | ||
| taskId: resolvedTaskId, | ||
| storedDraft: storedPromptDraftForTask, | ||
| sourceDraft: sourcePromptDraft, | ||
| sentDraft: promptDraft, | ||
| preservePromptDraft, | ||
| steeredQueuedTurn: queuedTurnToSend, | ||
| }); | ||
| const activityByTask = turnStillActive | ||
| ? startProviderTurnActivity({ | ||
| activityByTask: nextState.providerTurnActivityByTask, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the user changes the enabled model/provider selector while a turn is running,
args.activeProviderbecomes the newly selected task provider rather than the provider serving the active turn. Consequently, switching away from a steer-capable running provider hides these new actions, while switching toward one exposes actions thatresolveMidTurnSteeringContextrejects after the click. Derive this capability from the matchingproviderTurnActivity.providerId(with the same history fallback used by the store) instead.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right in principle — fixed in 00204c9, though it is latent today: both descriptors set
supportsMidTurnSteering: true, so no provider switch can currently make the UI andresolveMidTurnSteeringContextdisagree. It would start biting silently the moment a provider turns the capability off, so worth closing now.Extracted the store's own resolution into
resolveActiveTurnProviderId(activity snapshot matchingactiveTurnId, else thegetRespondingProviderIdhistory fallback) and used it in both places, so the chip affordance and the dispatch gate cannot drift.Left
canSteerActiveTurn(composer Enter/Tab) on the selector: that is pre-existing behaviour and this PR deliberately does not touch the Enter/Tab affordances. Happy to follow up separately if you want them unified.