Skip to content

Commit 0d57bbd

Browse files
author
T3 Code Test
committed
fix(web): redirect hidden agent thread links
1 parent c382ebc commit 0d57bbd

1 file changed

Lines changed: 25 additions & 12 deletions

File tree

apps/web/src/routes/_chat.$environmentId.$threadId.tsx

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { SidebarInset } from "~/components/ui/sidebar";
1414
import { useEnvironmentThreadRefs, useThreadShell } from "../state/entities";
1515
import { useEnvironmentQuery } from "../state/query";
1616
import { environmentShell } from "../state/shell";
17+
import { orchestrationEnvironment } from "../state/orchestration";
1718

1819
function ChatThreadRouteView() {
1920
const navigate = useNavigate();
@@ -39,17 +40,33 @@ function ChatThreadRouteView() {
3940
}
4041
return store.hasDraftThreadsInEnvironment(threadRef.environmentId);
4142
});
43+
const shouldResolveHiddenThread =
44+
bootstrapComplete && threadRef !== null && serverThreadShell === null && !draftThreadExists;
45+
const hiddenThreadProjection = useEnvironmentQuery(
46+
shouldResolveHiddenThread
47+
? orchestrationEnvironment.v2.threadProjection({
48+
environmentId: threadRef.environmentId,
49+
input: { threadId: threadRef.threadId },
50+
})
51+
: null,
52+
);
53+
const routeThread = serverThreadShell ?? hiddenThreadProjection.data?.thread ?? null;
54+
// Hidden provider child threads are intentionally absent from the compact
55+
// shell snapshot. Let the targeted projection lookup settle before
56+
// treating a deep link as missing, so the route can redirect to its parent.
57+
const routeLookupComplete =
58+
routeThread !== null || hiddenThreadProjection.error !== null || draftThreadExists;
4259
const renderState = resolveThreadRouteRenderState({
43-
bootstrapComplete,
44-
serverThreadExists: serverThreadShell !== null,
45-
serverThreadDeleted: serverThreadShell?.deletedAt != null,
60+
bootstrapComplete: bootstrapComplete && routeLookupComplete,
61+
serverThreadExists: routeThread !== null,
62+
serverThreadDeleted: routeThread?.deletedAt != null,
4663
draftThreadExists,
4764
});
4865
const serverThreadStarted = threadHasStarted(serverThreadShell);
4966
const environmentHasAnyThreads = environmentHasServerThreads || environmentHasDraftThreads;
5067
const subagentParentThreadId =
51-
serverThreadShell && isOrchestrationV2InternalSubagentThread(serverThreadShell)
52-
? serverThreadShell.lineage.parentThreadId
68+
routeThread && isOrchestrationV2InternalSubagentThread(routeThread)
69+
? routeThread.lineage.parentThreadId
5370
: null;
5471

5572
useEffect(() => {
@@ -63,11 +80,7 @@ function ChatThreadRouteView() {
6380
}, [bootstrapComplete, environmentHasAnyThreads, navigate, renderState, threadRef]);
6481

6582
useEffect(() => {
66-
if (
67-
!threadRef ||
68-
!serverThreadShell ||
69-
!isOrchestrationV2InternalSubagentThread(serverThreadShell)
70-
) {
83+
if (!threadRef || !routeThread || !isOrchestrationV2InternalSubagentThread(routeThread)) {
7184
return;
7285
}
7386
if (subagentParentThreadId === null) {
@@ -82,7 +95,7 @@ function ChatThreadRouteView() {
8295
}),
8396
replace: true,
8497
});
85-
}, [navigate, serverThreadShell, subagentParentThreadId, threadRef]);
98+
}, [navigate, routeThread, subagentParentThreadId, threadRef]);
8699

87100
useEffect(() => {
88101
if (!threadRef || !serverThreadStarted || !draftThread) {
@@ -94,7 +107,7 @@ function ChatThreadRouteView() {
94107
if (
95108
!threadRef ||
96109
renderState !== "ready" ||
97-
(serverThreadShell !== null && isOrchestrationV2InternalSubagentThread(serverThreadShell))
110+
(routeThread !== null && isOrchestrationV2InternalSubagentThread(routeThread))
98111
) {
99112
return null;
100113
}

0 commit comments

Comments
 (0)