import { IWorkspaceService, type Workspace } from '@moonshot-ai/agent-core-v2/app/workspace/workspace'; import { useMutation, useQuery } from '@tanstack/react-query'; import { useEffect, useState } from 'react'; import { useConnection } from '../connection'; import { fetchFsSuggest, type FsSuggestResult } from '../fs/api'; import { Badge, ErrorLine } from '../ui'; import { WorkspaceDirBrowser } from './WorkspaceDirBrowser'; function parseGlobs(value: string): string[] | undefined { const globs = value .split(',') .map((glob) => glob.trim()) .filter((glob) => glob.length > 0); return globs.length === 0 ? undefined : globs; } function parseRoots(value: string): string[] { return value .split(/[\n,]/) .map((root) => root.trim()) .filter((root) => root.length > 0); } export function FsSuggestView() { const { klient, baseUrl } = useConnection(); const [workspace, setWorkspace] = useState(null); const [rootsText, setRootsText] = useState(''); const [query, setQuery] = useState(''); const [limit, setLimit] = useState('50'); const [followGitignore, setFollowGitignore] = useState(true); const [showHidden, setShowHidden] = useState(false); const [includeGlobs, setIncludeGlobs] = useState(''); const [excludeGlobs, setExcludeGlobs] = useState(''); const workspaces = useQuery({ queryKey: ['workspaces', klient.baseUrl], queryFn: () => klient.core(IWorkspaceService).list(), }); const suggest = useMutation({ mutationFn: async () => { const roots = parseRoots(rootsText); const parsedLimit = Number.parseInt(limit, 10); const shared = { baseUrl: klient.baseUrl, token: klient.token, query, limit: Number.isFinite(parsedLimit) && parsedLimit > 0 ? parsedLimit : undefined, followGitignore, showHidden, includeGlobs: parseGlobs(includeGlobs), excludeGlobs: parseGlobs(excludeGlobs), }; if (roots.length > 0) { return fetchFsSuggest({ ...shared, roots }); } if (workspace === null) throw new Error('select a workspace or enter roots first'); return fetchFsSuggest({ ...shared, roots: [workspace.root] }); }, }); useEffect(() => { setWorkspace(null); suggest.reset(); }, [baseUrl]); const selectWorkspace = (next: Workspace) => { setWorkspace(next); suggest.reset(); }; return (

Filesystem Suggest

Query file and directory completion candidates via the workspace-independent fs:suggest API — the selected workspace supplies its root, or enter arbitrary roots to override it.

{ event.preventDefault(); suggest.mutate(); }} >