mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 18:33:15 +00:00
* init gh thread filter * format from main merge and improve filter logic * fix git diff from main merge format * refactor: move GH provider to chat layout * fix cosmetic git diff indentation * suspense and client component * update filter mech w metadata install name * cr * CR: fix single thread view w disableOrgFilter option --------- Co-authored-by: Brace Sproul <braceasproul@gmail.com>
112 lines
3.2 KiB
TypeScript
112 lines
3.2 KiB
TypeScript
import useSWR from "swr";
|
|
import { Thread } from "@langchain/langgraph-sdk";
|
|
import { createClient } from "@/providers/client";
|
|
import { THREAD_SWR_CONFIG } from "@/lib/swr-config";
|
|
import { ManagerGraphState } from "@open-swe/shared/open-swe/manager/types";
|
|
import { PlannerGraphState } from "@open-swe/shared/open-swe/planner/types";
|
|
import { ReviewerGraphState } from "@open-swe/shared/open-swe/reviewer/types";
|
|
import { GraphState } from "@open-swe/shared/open-swe/types";
|
|
import { useMemo } from "react";
|
|
import type { Installation } from "./useGitHubInstallations";
|
|
|
|
/**
|
|
* Union type representing all possible graph states in the Open SWE system
|
|
*/
|
|
export type AnyGraphState =
|
|
| ManagerGraphState
|
|
| PlannerGraphState
|
|
| ReviewerGraphState
|
|
| GraphState;
|
|
|
|
interface UseThreadsSWROptions {
|
|
assistantId?: string;
|
|
refreshInterval?: number;
|
|
revalidateOnFocus?: boolean;
|
|
revalidateOnReconnect?: boolean;
|
|
currentInstallation?: Installation | null;
|
|
disableOrgFiltering?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Hook for fetching threads for any graph type.
|
|
* Works with all graph states (Manager, Planner, Programmer, Reviewer)
|
|
* by passing the appropriate assistantId.
|
|
*
|
|
* For UI display of manager threads, use `threadsToMetadata(threads)` utility to convert
|
|
* raw threads to ThreadMetadata objects.
|
|
*/
|
|
export function useThreadsSWR<
|
|
TGraphState extends AnyGraphState = AnyGraphState,
|
|
>(options: UseThreadsSWROptions = {}) {
|
|
const {
|
|
assistantId,
|
|
refreshInterval = THREAD_SWR_CONFIG.refreshInterval,
|
|
revalidateOnFocus = THREAD_SWR_CONFIG.revalidateOnFocus,
|
|
revalidateOnReconnect = THREAD_SWR_CONFIG.revalidateOnReconnect,
|
|
currentInstallation,
|
|
disableOrgFiltering,
|
|
} = options;
|
|
|
|
const apiUrl: string | undefined = process.env.NEXT_PUBLIC_API_URL ?? "";
|
|
|
|
// Create a unique key for SWR caching based on assistantId
|
|
const swrKey = assistantId ? ["threads", assistantId] : ["threads", "all"];
|
|
|
|
const fetcher = async (): Promise<Thread<TGraphState>[]> => {
|
|
if (!apiUrl) {
|
|
throw new Error("API URL is not configured");
|
|
}
|
|
|
|
const client = createClient(apiUrl);
|
|
const searchArgs = assistantId
|
|
? {
|
|
metadata: {
|
|
graph_id: assistantId,
|
|
},
|
|
}
|
|
: undefined;
|
|
|
|
return await client.threads.search<TGraphState>(searchArgs);
|
|
};
|
|
|
|
const { data, error, isLoading, mutate, isValidating } = useSWR(
|
|
swrKey,
|
|
fetcher,
|
|
{
|
|
refreshInterval,
|
|
revalidateOnFocus,
|
|
revalidateOnReconnect,
|
|
errorRetryCount: THREAD_SWR_CONFIG.errorRetryCount,
|
|
errorRetryInterval: THREAD_SWR_CONFIG.errorRetryInterval,
|
|
dedupingInterval: THREAD_SWR_CONFIG.dedupingInterval,
|
|
},
|
|
);
|
|
|
|
const threads = useMemo(() => {
|
|
const allThreads = data ?? [];
|
|
|
|
if (disableOrgFiltering) {
|
|
return allThreads;
|
|
}
|
|
|
|
if (!currentInstallation) {
|
|
return [];
|
|
}
|
|
|
|
return allThreads.filter((thread) => {
|
|
const threadInstallationName = thread.metadata?.installation_name;
|
|
return (
|
|
typeof threadInstallationName === "string" &&
|
|
threadInstallationName === currentInstallation.accountName
|
|
);
|
|
});
|
|
}, [data, currentInstallation, disableOrgFiltering]);
|
|
|
|
return {
|
|
threads,
|
|
error,
|
|
isLoading,
|
|
isValidating,
|
|
mutate,
|
|
};
|
|
}
|