Skip to content

Commit 184d8ef

Browse files
authored
fix(mobile): steer active turns by default (#6543)
1 parent 038560e commit 184d8ef

7 files changed

Lines changed: 27 additions & 27 deletions

File tree

apps/mobile/src/features/threads/ThreadComposer.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ export interface ThreadComposerProps {
105105
readonly selectedThread: OrchestrationThreadShell;
106106
readonly serverConfig: T3ServerConfig | null;
107107
readonly queueCount: number;
108-
readonly activeThreadBusy: boolean;
109108
readonly environmentId: EnvironmentId;
110109
readonly projectCwd: string | null;
111110
readonly editorRef?: RefObject<ComposerEditorHandle | null>;
@@ -327,9 +326,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer
327326
props.selectedThread.session?.status === "starting";
328327

329328
const sendLabel =
330-
props.connectionState !== "connected" || props.activeThreadBusy || props.queueCount > 0
331-
? "Queue"
332-
: "Send";
329+
props.connectionState !== "connected" || props.queueCount > 0 ? "Queue" : "Send";
333330
const currentModelSelection = props.selectedThread.modelSelection;
334331
const currentRuntimeMode = props.selectedThread.runtimeMode;
335332
const connectionStatus = composerConnectionStatus({

apps/mobile/src/features/threads/ThreadDetailScreen.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ export interface ThreadDetailScreenProps {
101101
readonly threadSyncStatus?: EnvironmentThreadStatus;
102102
/** Non-null when older turns exist beyond the loaded window. */
103103
readonly loadEarlier?: { readonly loading: boolean; readonly onLoadEarlier: () => void } | null;
104-
readonly activeThreadBusy: boolean;
105104
readonly environmentId: EnvironmentId;
106105
readonly projectWorkspaceRoot: string | null;
107106
readonly threadCwd: string | null;
@@ -727,7 +726,6 @@ export const ThreadDetailScreen = memo(function ThreadDetailScreen(props: Thread
727726
selectedThread={props.selectedThread}
728727
serverConfig={props.serverConfig}
729728
queueCount={props.selectedThreadQueueCount}
730-
activeThreadBusy={props.activeThreadBusy}
731729
environmentId={props.environmentId}
732730
projectCwd={props.projectWorkspaceRoot}
733731
bottomInset={composerBottomInset}

apps/mobile/src/features/threads/ThreadRouteScreen.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,6 @@ function ThreadRouteContent(
785785
connectionStateLabel={routeConnectionState}
786786
threadSyncStatus={selectedThreadDetailState.status}
787787
loadEarlier={loadEarlierTurns}
788-
activeThreadBusy={composer.activeThreadBusy}
789788
environmentId={selectedThread.environmentId}
790789
projectWorkspaceRoot={selectedThreadProject?.workspaceRoot ?? null}
791790
threadCwd={selectedThreadCwd}

apps/mobile/src/state/thread-outbox-model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export function resolveThreadOutboxDeliveryAction(input: {
169169
if (!input.threadExists) {
170170
return input.shellStatus === "live" ? "remove" : "wait";
171171
}
172-
return input.environmentConnected && !input.threadBusy ? "send" : "wait";
172+
return input.environmentConnected ? "send" : "wait";
173173
}
174174

175175
/**

apps/mobile/src/state/thread-outbox.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,27 @@ describe("thread outbox", () => {
487487
).toBe("send");
488488
});
489489

490+
it("sends existing-thread messages whenever connected so queued messages can steer", () => {
491+
expect(
492+
resolveThreadOutboxDeliveryAction({
493+
isCreation: false,
494+
threadExists: true,
495+
shellStatus: "live",
496+
environmentConnected: true,
497+
threadBusy: true,
498+
}),
499+
).toBe("send");
500+
expect(
501+
resolveThreadOutboxDeliveryAction({
502+
isCreation: false,
503+
threadExists: true,
504+
shellStatus: "live",
505+
environmentConnected: false,
506+
threadBusy: true,
507+
}),
508+
).toBe("wait");
509+
});
510+
490511
it("sends queued creations once connected and live, removing already-created ones", () => {
491512
expect(
492513
resolveThreadOutboxDeliveryAction({

apps/mobile/src/state/use-thread-composer-state.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,6 @@ export function useThreadComposerState() {
129129
);
130130
}, [selectedThreadDetail, selectedThreadSessionActivity, selectedThreadShell]);
131131

132-
const activeThreadBusy =
133-
!!selectedThread &&
134-
(selectedThread.session?.status === "running" || selectedThread.session?.status === "starting");
135-
136132
const onSendMessage = useCallback(async () => {
137133
if (!selectedThreadShell) {
138134
return null;
@@ -308,7 +304,6 @@ export function useThreadComposerState() {
308304
modelSelection,
309305
runtimeMode,
310306
interactionMode,
311-
activeThreadBusy,
312307
onChangeDraftMessage,
313308
onPickDraftImages,
314309
onPasteIntoDraft,

apps/mobile/src/state/use-thread-outbox-drain.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import {
3737
type QueuedThreadMessage,
3838
type ThreadOutboxCommandStage,
3939
} from "./thread-outbox-model";
40-
import { environmentThreadShells, threadEnvironment } from "./threads";
40+
import { threadEnvironment } from "./threads";
4141
import { useAtomCommand } from "./use-atom-command";
4242
import {
4343
editingQueuedMessageIdsAtom,
@@ -362,22 +362,12 @@ export function useThreadOutboxDrain(): void {
362362
return true;
363363
}
364364
// The guards evaluated before the confirmation await are stale by now:
365-
// the thread may have gone busy, or the user may have opened this
366-
// message in the editor. Re-read both and defer to the next drain pass
367-
// (returning true skips the failure/backoff path) rather than sending
368-
// a payload the user is editing or racing an active turn.
365+
// the user may have opened this message in the editor. Re-read that
366+
// guard and defer to the next drain pass (returning true skips the
367+
// failure/backoff path) rather than sending a payload being edited.
369368
if (appAtomRegistry.get(editingQueuedMessageIdsAtom)[nextQueuedMessage.messageId]) {
370369
return true;
371370
}
372-
const freshThread = findThread(
373-
appAtomRegistry.get(environmentThreadShells.threadShellsAtom),
374-
nextQueuedMessage,
375-
);
376-
const freshThreadBusy =
377-
freshThread?.session?.status === "running" || freshThread?.session?.status === "starting";
378-
if (deliveryAction === "send" && creation === undefined && freshThreadBusy) {
379-
return true;
380-
}
381371
return deliveryAction === "remove"
382372
? removeQueuedMessage("[thread-outbox] failed to remove message for a missing thread")
383373
: creation !== undefined

0 commit comments

Comments
 (0)