char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Aleksander Grygierui: Refactor Built-In Tools naming (Server/Browser) (#27271)0021a77de

char/aliceai-t5-moe
3.8 KiB124 linesraw
1/**
2 * Shared `file_glob_search` runners with a short-lived result cache, so a
3 * repeated query for the same (type, path, glob, depth) reuses the last
4 * result instead of re-walking the tree.
5 */
6
7import { lastPathSegment } from './path-display';
8import { buildGlobSearchArgs, joinPath, rankEntries } from './working-directory';
9import { GLOB, PATH_SEPARATOR, SEARCH } from '$lib/constants';
10import { BuiltInTool, GlobSearchType } from '$lib/enums';
11import { ToolsService } from '$lib/services/tools.service';
12import type {
13	GlobEntry,
14	GlobEntryResult,
15	GlobSearchArgs,
16	GlobSearchChildOptions,
17	GlobSearchChildResult,
18	GlobSearchResult
19} from '$lib/types/glob';
20
21const SEARCH_CACHE_TTL_MS = 2000;
22
23interface CacheEntry {
24	results: GlobEntry[];
25	base: string;
26	at: number;
27}
28
29const searchCache = new Map<string, CacheEntry>();
30
31export async function runGlobSearch(
32	args: GlobSearchArgs,
33	type: GlobSearchType,
34	limit: number,
35	signal: AbortSignal
36): Promise<GlobSearchResult> {
37	const key = `${type}\u0000${args.path}\u0000${args.include}\u0000${args.maxDepth}\u0000${limit}`;
38	const cached = searchCache.get(key);
39
40	if (cached && Date.now() - cached.at < SEARCH_CACHE_TTL_MS) {
41		return { base: cached.base, entries: cached.results };
42	}
43
44	const res = await ToolsService.executeToolRaw(
45		BuiltInTool.SERVER_FILE_GLOB_SEARCH,
46		{ include: args.include, limit, max_depth: args.maxDepth, path: args.path, type },
47		signal
48	);
49
50	if (typeof res.error === 'string') return { base: '', entries: [], error: res.error };
51
52	const base = typeof res.base === 'string' ? res.base : '';
53	const entries = Array.isArray(res.entries) ? (res.entries as GlobEntry[]) : [];
54	const now = Date.now();
55
56	// prune stale entries so the short-lived cache cannot grow unbounded
57	for (const [k, v] of searchCache) {
58		if (now - v.at >= SEARCH_CACHE_TTL_MS) searchCache.delete(k);
59	}
60	searchCache.set(key, { at: now, base, results: entries });
61
62	return { base, entries };
63}
64
65function toEntryResult(e: GlobEntry, base: string): GlobEntryResult {
66	return { name: lastPathSegment(e.path), path: joinPath(base, e.path), type: e.type };
67}
68
69/**
70 * One ranked glob search that may also list the matched directory's
71 * children, shared by the WD picker (descend on exact match) and the
72 * mention picker (descend on a trailing `/` or `\`).
73 */
74export async function runGlobSearchWithChildren(
75	query: string,
76	scopePath: string,
77	searchDepth: number,
78	limit: number,
79	signal: AbortSignal,
80	options: GlobSearchChildOptions = {}
81): Promise<GlobSearchChildResult> {
82	const {
83		childMaxDepth = SEARCH.PATH_NAV_MAX_DEPTH,
84		descendOnTrailingSeparator = false,
85		type = GlobSearchType.ALL
86	} = options;
87	const args = buildGlobSearchArgs(query, scopePath, searchDepth);
88	const res = await runGlobSearch(args, type, limit, signal);
89
90	if (res.error) return { args, base: res.base, entries: [], error: res.error };
91
92	const ranked = rankEntries(res.entries, args.rankQuery);
93	const entries = ranked.map((e) => toEntryResult(e, res.base));
94	const last = args.last;
95
96	if (last) {
97		const wantsDescend = descendOnTrailingSeparator
98			? query.endsWith(PATH_SEPARATOR) || query.endsWith(GLOB.WINDOWS_SEPARATOR)
99			: true;
100		const exact = ranked.find(
101			(e) => e.type === 'dir' && lastPathSegment(e.path).toLowerCase() === last.toLowerCase()
102		);
103
104		if (wantsDescend && exact) {
105			const exactDir = joinPath(res.base, exact.path);
106			const childRes = await runGlobSearch(
107				{ include: GLOB.WILDCARD, maxDepth: childMaxDepth, path: exactDir, rankQuery: '' },
108				type,
109				limit,
110				signal
111			);
112
113			if (!childRes.error) {
114				const children = childRes.entries
115					.map((e) => toEntryResult(e, childRes.base))
116					.sort((a, b) => a.path.localeCompare(b.path));
117
118				return { args, base: res.base, entries: [...entries, ...children], exactDir };
119			}
120		}
121	}
122
123	return { args, base: res.base, entries };
124}