Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

75 lines
2.0 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import { useAuiState } from "@assistant-ui/react";
import {
updateXuluxPendingUserMessage,
updateXuluxThreadStatus,
} from "./xulux-local-storage";
export function XuluxThreadStatusObserver() {
const remoteId = useAuiState((state) => state.threadListItem.remoteId);
const isRunning = useAuiState((state) => state.thread.isRunning);
const messages = useAuiState((state) => state.thread.messages);
const previous = useRef<{
remoteId: string | undefined;
isRunning: boolean;
}>({ remoteId: undefined, isRunning: false });
useEffect(() => {
if (!remoteId || !isRunning) return;
const latestUserText = getLatestUserText(messages);
if (latestUserText) {
updateXuluxPendingUserMessage(remoteId, latestUserText);
}
}, [isRunning, messages, remoteId]);
useEffect(() => {
const prior = previous.current;
previous.current = { remoteId, isRunning };
if (!remoteId) return;
if (prior.remoteId !== remoteId) return;
if (isRunning && !prior.isRunning) {
updateXuluxThreadStatus(remoteId, "running");
return;
}
if (!isRunning && prior.isRunning) {
updateXuluxThreadStatus(remoteId, "idle");
updateXuluxPendingUserMessage(remoteId, null);
}
}, [remoteId, isRunning]);
return null;
}
function getLatestUserText(
messages: readonly {
role: string;
content: readonly unknown[];
}[],
): string | null {
for (let index = messages.length - 1; index >= 0; index -= 1) {
const message = messages[index];
if (message?.role !== "user") continue;
const text = message.content
.flatMap((part) => {
if (!part || typeof part !== "object") return [];
const typedPart = part as Record<string, unknown>;
return typedPart.type === "text" && typeof typedPart.text === "string"
? [typedPart.text]
: [];
})
.join("\n")
.trim();
if (text) return text;
}
return null;
}