[BUG] tapLookupResources: Resource not found for lookup: {"key":"__LOCALID_47AWGUp"} using local thread runtime with remote thread list
Hello, After updating assistant-ui to the latest version (0.11) from 0.10, I started encountering an error when initializing a new chat, which crashes the app. On version 0.10 everything works correctly.
I have created a repo which allows to reproduce the error. https://github.com/watFiree/assistant-ui-external-store-example
After a bit of research, I found that the initialize method in RemoteThreadListAdapter causes the error when the response takes too long.
Has anyone encountered this error and found the solution?
I have this issue too.
I worked around it by doing:
"use client";
import { useCallback, useEffect, useMemo, useRef } from "react";
import {
useChatRuntime,
AssistantChatTransport,
} from "@assistant-ui/react-ai-sdk";
import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useAskAI } from "@/components/search/llm/ask-ai-provider";
import { AssistantModal } from "@/components/assistant-ui/assistant-modal";
export function AIAssistant({
apiUrl,
}: Readonly<{
apiUrl: string;
}>) {
const { isOpen, setOpen } = useAskAI();
const transport = useMemo(
() =>
new AssistantChatTransport({
api: apiUrl,
}),
[apiUrl],
);
const runtime = useChatRuntime({
transport,
});
const previousIsOpenRef = useRef(isOpen);
const resetThread = useCallback(() => {
runtime.thread.reset();
}, [runtime]);
useEffect(() => {
if (previousIsOpenRef.current && !isOpen) {
// Clearing the thread (instead of switching) avoids the tapLookupResources
// crash triggered when Assistant UI races on local thread IDs.
resetThread();
}
previousIsOpenRef.current = isOpen;
}, [isOpen, resetThread]);
const handleOpenChange = useCallback(
(nextOpen: boolean) => {
setOpen(nextOpen);
},
[setOpen],
);
return (
<AssistantRuntimeProvider runtime={runtime}>
<AssistantModal open={isOpen} onOpenChange={handleOpenChange} />
</AssistantRuntimeProvider>
);
}
I'm not using a modal, so I didn't have that callback. However I was able to catch it like this:
try {
threadListItem = useAssistantState(({ threadListItem: x }) => x);
} catch (error) {
console.error("Error getting composer thread list item", error);
transientError = true;
}
and generally not crash on transientError below.
Somehow everything works out (it must reload the component after the transient issue stops happening)
in another spot, I was doing
const runtime = useRemoteThreadListRuntime({
// Build the model adapter inside runtimeHook so we can capture the per-thread runtime
runtimeHook: () => {
// it actually is in a hook
// eslint-disable-next-line react-hooks/rules-of-hooks
const itemRt = useAssistantApi().threadListItem();
const model: ChatModelAdapter = {
async run({
messages,
abortSignal,
}: ChatModelRunOptions): Promise<ChatModelRunResult> {
// use itemRt
}
I changed that to this and it works - i assume because it's more delayed.
const runtime = useRemoteThreadListRuntime({
// Build the model adapter inside runtimeHook so we can capture the per-thread runtime
runtimeHook: () => {
// it actually is in a hook
// eslint-disable-next-line react-hooks/rules-of-hooks
const assistantApi = useAssistantApi();
const model: ChatModelAdapter = {
async run({
messages,
abortSignal,
}: ChatModelRunOptions): Promise<ChatModelRunResult> {
const itemRt = assistantApi.threadListItem();
// use itemRT
}
According to bleonard, i also find another way to solve it. replace
const remoteId = useAssistantState(({ threadListItem }) => threadListItem.remoteId);
to
const remoteId = useAssistantApi().threadListItem().getState().remoteId;