import { startTransition, type ReactNode } from "react";
import type {
Source,
} from "@executor/react";
import {
useSource,
useSources,
} from "@executor/react";
import {
Alert,
Button,
SourceToolExplorer,
parseSourceToolExplorerSearch,
useSourcePluginNavigation,
useSourcePluginRouteParams,
useSourcePluginSearch,
type SourceToolExplorerSearch,
} from "@executor/react/plugins";
const LOCAL_TOOLS_SOURCE_KIND = "local-tools";
const localToolsSummary = (
File-backed tools loaded from .executor/tools.
Restart the executor session after adding the first local tool so the source is provisioned.
);
function LocalToolsSourceRoute(props: {
children: (source: Source) => ReactNode;
}) {
const params = useSourcePluginRouteParams<{ sourceId?: string }>();
const sourceId = typeof params.sourceId === "string" ? params.sourceId : null;
const source = useSource(sourceId ?? "");
if (sourceId === null || source.status === "error") {
return (
This local tools source is unavailable.
);
}
if (source.status === "loading") {
return (
Loading source...
);
}
if (source.data.kind !== LOCAL_TOOLS_SOURCE_KIND) {
return (
Expected a local-tools source,
but received {source.data.kind}.
);
}
return props.children(source.data);
}
function LocalToolsSourceDetailPage(props: {
source: Source;
}) {
const navigation = useSourcePluginNavigation();
const search = parseSourceToolExplorerSearch(
useSourcePluginSearch(),
) satisfies SourceToolExplorerSearch;
const tab = search.tab === "discover" ? "discover" : "model";
const query = search.query ?? "";
return (
navigation.updateSearch({
tab: next.tab ?? tab,
...(next.tool !== undefined
? { tool: next.tool || undefined }
: { tool: search.tool }),
...(next.query !== undefined
? { query: next.query || undefined }
: { query }),
})}
summary={localToolsSummary}
/>
);
}
export function LocalToolsAddPage() {
const sources = useSources();
const navigation = useSourcePluginNavigation();
if (sources.status === "loading") {
return (
Loading sources...
);
}
if (sources.status === "error") {
return (
Failed loading sources.
);
}
const localToolsSource = sources.data.find(
(source) => source.kind === LOCAL_TOOLS_SOURCE_KIND,
) ?? null;
return (
Local Tools
File-backed tools from .executor/tools promoted into a first-class source.
The source is provisioned automatically when the executor session starts and finds
local tool files in .executor/tools.
Existing tool path behavior is preserved, so a file like
{" "}.executor/tools/demo.ts
{" "}still appears as tools.demo(...).
{localToolsSource ? (
) : (
No local tools source is active yet. Create a tool in
{" "}.executor/tools
{" "}and restart the executor session.
)}
);
}
export function LocalToolsDetailRoute() {
return (
{(source) => }
);
}