Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/src/components/BranchToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export const BranchToolbar = memo(function BranchToolbar({
() => scopeThreadRef(environmentId, threadId),
[environmentId, threadId],
);
const serverThread = useThread(threadRef);
const serverThread = useThread(threadRef, { waitForShell: draftId !== undefined });
const draftThread = useComposerDraftStore((store) =>
draftId ? store.getDraftSession(draftId) : store.getDraftThreadByRef(threadRef),
);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/BranchToolbarBranchSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export function BranchToolbarBranchSelector({
() => scopeThreadRef(environmentId, threadId),
[environmentId, threadId],
);
const serverThread = useThread(threadRef);
const serverThread = useThread(threadRef, { waitForShell: draftId !== undefined });
const serverSession = serverThread?.session ?? null;
const draftThread = useComposerDraftStore((store) =>
draftId ? store.getDraftSession(draftId) : store.getDraftThreadByRef(threadRef),
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,8 @@ const PersistentThreadTerminalDrawer = memo(function PersistentThreadTerminalDra
const openTerminal = useAtomCommand(terminalEnvironment.open, "terminal open");
const writeTerminal = useAtomCommand(terminalEnvironment.write, "terminal write");
const closeTerminalMutation = useAtomCommand(terminalEnvironment.close, "terminal close");
const serverThread = useThread(threadRef);
const draftThread = useComposerDraftStore((store) => store.getDraftThreadByRef(threadRef));
const serverThread = useThread(threadRef, { waitForShell: draftThread !== null });
const projectRef = serverThread
? scopeProjectRef(serverThread.environmentId, serverThread.projectId)
: draftThread
Expand Down Expand Up @@ -976,8 +976,8 @@ const PersistentThreadTerminalPanel = memo(function PersistentThreadTerminalPane
newShortcutLabel,
closeShortcutLabel,
}: PersistentThreadTerminalPanelProps) {
const serverThread = useThread(threadRef);
const draftThread = useComposerDraftStore((store) => store.getDraftThreadByRef(threadRef));
const serverThread = useThread(threadRef, { waitForShell: draftThread !== null });
const projectRef = serverThread
? scopeProjectRef(serverThread.environmentId, serverThread.projectId)
: draftThread
Expand Down Expand Up @@ -1181,7 +1181,7 @@ function ChatViewContent(props: ChatViewProps) {
);
const composerDraftTarget: ScopedThreadRef | DraftId =
routeKind === "server" ? routeThreadRef : props.draftId;
const serverThread = useThread(routeThreadRef);
const serverThread = useThread(routeThreadRef, { waitForShell: routeKind === "draft" });
Comment thread
cursor[bot] marked this conversation as resolved.
Resolved
const markThreadVisited = useUiStateStore((store) => store.markThreadVisited);
const activeThreadLastVisitedAt = useUiStateStore(
(store) => store.threadLastVisitedAtById[routeThreadKey],
Expand Down
4 changes: 3 additions & 1 deletion apps/web/src/components/GitActionsControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,9 @@ export default function GitActionsControl({
() => (activeThreadRef ? { threadRef: activeThreadRef } : undefined),
[activeThreadRef],
);
const activeServerThread = useThread(activeThreadRef);
const activeServerThread = useThread(activeThreadRef, {
waitForShell: draftId !== undefined,
});
const activeDraftThread = useComposerDraftStore((store) =>
draftId
? store.getDraftSession(draftId)
Expand Down
36 changes: 36 additions & 0 deletions apps/web/src/state/entities.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { scopeThreadRef } from "@t3tools/client-runtime/environment";
import { EnvironmentId, ThreadId } from "@t3tools/contracts";
import { describe, expect, it } from "vite-plus/test";

import { resolveThreadDetailRef } from "./entities";

const threadRef = scopeThreadRef(EnvironmentId.make("environment-1"), ThreadId.make("thread-1"));

describe("resolveThreadDetailRef", () => {
it("does not subscribe to a reserved draft thread before it enters the shell index", () => {
expect(
resolveThreadDetailRef(threadRef, {
shellExists: false,
waitForShell: true,
}),
).toBeNull();
});

it("subscribes once the reserved draft thread enters the shell index", () => {
expect(
resolveThreadDetailRef(threadRef, {
shellExists: true,
waitForShell: true,
}),
).toBe(threadRef);
});

it("keeps direct server-thread lookups enabled when the shell has not loaded it", () => {
expect(
resolveThreadDetailRef(threadRef, {
shellExists: false,
waitForShell: false,
}),
).toBe(threadRef);
});
});
29 changes: 27 additions & 2 deletions apps/web/src/state/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,35 @@ export function useThreadStatus(ref: ScopedThreadRef | null): EnvironmentThreadS
);
}

export function resolveThreadDetailRef(
ref: ScopedThreadRef | null,
options: {
shellExists: boolean;
waitForShell: boolean;
},
): ScopedThreadRef | null {
return ref !== null && (!options.waitForShell || options.shellExists) ? ref : null;
}

/** Detail collections composed with shell-authoritative thread/workspace metadata. */
export function useThread(ref: ScopedThreadRef | null): EnvironmentThread | null {
export function useThread(
ref: ScopedThreadRef | null,
options?: {
/**
* Client-reserved draft thread ids do not exist on the server until the
* first send. Waiting for the shell index avoids polling the detail
* endpoint for an intentionally missing thread during that window.
*/
waitForShell?: boolean;
},
): EnvironmentThread | null {
const shell = useThreadShell(ref);
const detail = useThreadDetail(ref);
const detail = useThreadDetail(
resolveThreadDetailRef(ref, {
shellExists: shell !== null,
waitForShell: options?.waitForShell === true,
}),
);
return useMemo(() => mergeEnvironmentThread(detail, shell), [detail, shell]);
}

Expand Down
Loading