char-fork/llama.cpp

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

Aleksander Grygierui: Constants refactor (#26908)e21152dc9

char/aliceai-t5-moe
5.8 KiB197 linesraw
1import {
2	LEADING_SLASHES_REGEX,
3	TEMPLATE_EXPRESSION_REGEX,
4	URI_SCHEME_SEPARATOR,
5	URI_TEMPLATE_SYMBOLS,
6	VARIABLE_EXPLODE_MODIFIER_REGEX,
7	VARIABLE_PREFIX_MODIFIER_REGEX
8} from '../constants';
9
10/**
11 * Normalize a resource URI for comparison.
12 *
13 * URI template expansion (especially with path operators like {/var})
14 * can produce URIs that differ from listed resource URIs in slash placement.
15 * For example, the template `svelte://{/slug*}.md` with slug="svelte/$effect"
16 * expands to `svelte:///svelte/$effect.md`, while the listed resource URI is
17 * `svelte://svelte/$effect.md`.
18 *
19 * This function strips extra leading slashes after the scheme to normalize
20 * both forms to the same string for comparison purposes.
21 *
22 * @param uri - The URI to normalize
23 * @returns Normalized URI string
24 */
25export function normalizeResourceUri(uri: string): string {
26	const schemeEnd = uri.indexOf(URI_SCHEME_SEPARATOR);
27
28	if (schemeEnd === -1) return uri;
29
30	const scheme = uri.substring(0, schemeEnd);
31	const rest = uri
32		.substring(schemeEnd + URI_SCHEME_SEPARATOR.length)
33		.replace(LEADING_SLASHES_REGEX, '');
34
35	return `${scheme}${URI_SCHEME_SEPARATOR}${rest}`;
36}
37
38/**
39 * A parsed variable from a URI template expression.
40 */
41export interface UriTemplateVariable {
42	/** Variable name */
43	name: string;
44	/** Operator prefix (+, #, /, etc.) or empty string */
45	operator: string;
46}
47
48/**
49 * Extract all variable names from a URI template string.
50 *
51 * @param template - URI template string (RFC 6570)
52 * @returns Array of unique variable descriptors
53 *
54 * @example
55 * ```ts
56 * extractTemplateVariables("file:///{path}")
57 * // => [{ name: "path", operator: "" }]
58 *
59 * extractTemplateVariables("db://{schema}/{table}")
60 * // => [{ name: "schema", operator: "" }, { name: "table", operator: "" }]
61 * ```
62 */
63export function extractTemplateVariables(template: string): UriTemplateVariable[] {
64	const variables: UriTemplateVariable[] = [];
65	const seen = new Set<string>();
66
67	let match;
68
69	TEMPLATE_EXPRESSION_REGEX.lastIndex = 0;
70
71	while ((match = TEMPLATE_EXPRESSION_REGEX.exec(template)) !== null) {
72		const operator = match[1] || '';
73		const varList = match[2];
74
75		// RFC 6570 allows comma-separated variable lists: {x,y,z}
76		for (const varSpec of varList.split(',')) {
77			// Strip explode modifier (*) and prefix modifier (:N)
78			const name = varSpec
79				.replace(VARIABLE_EXPLODE_MODIFIER_REGEX, '')
80				.replace(VARIABLE_PREFIX_MODIFIER_REGEX, '')
81				.trim();
82
83			if (name && !seen.has(name)) {
84				seen.add(name);
85				variables.push({ name, operator });
86			}
87		}
88	}
89
90	return variables;
91}
92
93/**
94 * Expand a URI template with the given variable values.
95 * Implements a simplified RFC 6570 Level 2 expansion.
96 *
97 * @param template - URI template string
98 * @param values - Map of variable name to value
99 * @returns Expanded URI string
100 *
101 * @example
102 * ```ts
103 * expandTemplate("file:///{path}", { path: "src/main.rs" })
104 * // => "file:///src/main.rs"
105 * ```
106 */
107export function expandTemplate(template: string, values: Record<string, string>): string {
108	TEMPLATE_EXPRESSION_REGEX.lastIndex = 0;
109
110	return template.replace(
111		TEMPLATE_EXPRESSION_REGEX,
112		(_match, operator: string, varList: string) => {
113			const varNames = varList
114				.split(',')
115				.map((v: string) =>
116					v
117						.replace(VARIABLE_EXPLODE_MODIFIER_REGEX, '')
118						.replace(VARIABLE_PREFIX_MODIFIER_REGEX, '')
119						.trim()
120				);
121			const expandedParts = varNames
122				.map((name: string) => values[name] ?? '')
123				.filter((v: string) => v !== '');
124
125			if (expandedParts.length === 0) return '';
126
127			switch (operator) {
128				case URI_TEMPLATE_SYMBOLS.RESERVED:
129					// Reserved expansion: no encoding
130					return expandedParts.join(URI_TEMPLATE_SYMBOLS.COMMA);
131				case URI_TEMPLATE_SYMBOLS.FRAGMENT:
132					// Fragment expansion
133					return URI_TEMPLATE_SYMBOLS.FRAGMENT + expandedParts.join(URI_TEMPLATE_SYMBOLS.COMMA);
134				case URI_TEMPLATE_SYMBOLS.PATH_SEGMENT:
135					// Path segments
136					return (
137						URI_TEMPLATE_SYMBOLS.PATH_SEGMENT +
138						expandedParts.join(URI_TEMPLATE_SYMBOLS.PATH_SEGMENT)
139					);
140				case URI_TEMPLATE_SYMBOLS.LABEL:
141					// Label expansion
142					return URI_TEMPLATE_SYMBOLS.LABEL + expandedParts.join(URI_TEMPLATE_SYMBOLS.LABEL);
143				case URI_TEMPLATE_SYMBOLS.PATH_PARAM:
144					// Path-style parameters
145					return varNames
146						.filter((_: string, i: number) => expandedParts[i])
147						.map(
148							(name: string, i: number) =>
149								`${URI_TEMPLATE_SYMBOLS.PATH_PARAM}${name}=${expandedParts[i]}`
150						)
151						.join('');
152				case URI_TEMPLATE_SYMBOLS.FORM_QUERY:
153					// Form-style query
154					return (
155						URI_TEMPLATE_SYMBOLS.FORM_QUERY +
156						varNames
157							.filter((_: string, i: number) => expandedParts[i])
158							.map(
159								(name: string, i: number) =>
160									`${encodeURIComponent(name)}=${encodeURIComponent(expandedParts[i])}`
161							)
162							.join(URI_TEMPLATE_SYMBOLS.FORM_CONTINUATION)
163					);
164				case URI_TEMPLATE_SYMBOLS.FORM_CONTINUATION:
165					// Form-style query continuation
166					return (
167						URI_TEMPLATE_SYMBOLS.FORM_CONTINUATION +
168						varNames
169							.filter((_: string, i: number) => expandedParts[i])
170							.map(
171								(name: string, i: number) =>
172									`${encodeURIComponent(name)}=${encodeURIComponent(expandedParts[i])}`
173							)
174							.join(URI_TEMPLATE_SYMBOLS.COMMA)
175					);
176				default:
177					// Simple string expansion (default operator)
178					return expandedParts
179						.map((v: string) => encodeURIComponent(v))
180						.join(URI_TEMPLATE_SYMBOLS.COMMA);
181			}
182		}
183	);
184}
185
186/**
187 * Check whether all required variables in a template have been provided.
188 *
189 * @param template - URI template string
190 * @param values - Map of variable name to value
191 * @returns true if all variables have non-empty values
192 */
193export function isTemplateComplete(template: string, values: Record<string, string>): boolean {
194	const variables = extractTemplateVariables(template);
195
196	return variables.every((v) => (values[v.name] ?? '').trim() !== '');
197}