@navai/voice-frontend 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +65 -24
- package/README.es.md +65 -24
- package/README.md +82 -28
- package/bin/generate-web-module-loaders.mjs +31 -3
- package/dist/index.cjs +437 -68
- package/dist/index.d.cts +45 -22
- package/dist/index.d.ts +45 -22
- package/dist/index.js +437 -68
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -32,22 +32,24 @@ HTTP client for backend routes:
|
|
|
32
32
|
- `GET /navai/functions`
|
|
33
33
|
- `POST /navai/functions/execute`
|
|
34
34
|
|
|
35
|
-
2. `src/runtime.ts`
|
|
36
|
-
Runtime resolver for:
|
|
37
|
-
- route module selection
|
|
38
|
-
- function module filtering by `NAVAI_FUNCTIONS_FOLDERS`
|
|
39
|
-
-
|
|
35
|
+
2. `src/runtime.ts`
|
|
36
|
+
Runtime resolver for:
|
|
37
|
+
- route module selection
|
|
38
|
+
- function module filtering by `NAVAI_FUNCTIONS_FOLDERS`
|
|
39
|
+
- agent discovery by `NAVAI_AGENTS_FOLDERS`
|
|
40
|
+
- optional model override
|
|
40
41
|
|
|
41
42
|
3. `src/functions.ts`
|
|
42
43
|
Local function loader:
|
|
43
44
|
- imports modules from generated loaders
|
|
44
45
|
- converts exports into normalized callable tool definitions
|
|
45
46
|
|
|
46
|
-
4. `src/agent.ts`
|
|
47
|
-
Agent builder:
|
|
48
|
-
- creates `RealtimeAgent`
|
|
49
|
-
- injects built-in tools (`navigate_to`, `execute_app_function`)
|
|
50
|
-
- optionally adds direct alias tools for each allowed function
|
|
47
|
+
4. `src/agent.ts`
|
|
48
|
+
Agent builder:
|
|
49
|
+
- creates the primary `RealtimeAgent`
|
|
50
|
+
- injects built-in tools (`navigate_to`, `execute_app_function`)
|
|
51
|
+
- optionally adds direct alias tools for each allowed function
|
|
52
|
+
- creates specialist agents and wires them with `handoffs`
|
|
51
53
|
|
|
52
54
|
5. `src/useWebVoiceAgent.ts`
|
|
53
55
|
React lifecycle wrapper:
|
|
@@ -161,16 +163,51 @@ For class methods:
|
|
|
161
163
|
2. Env object keys.
|
|
162
164
|
3. Package defaults.
|
|
163
165
|
|
|
164
|
-
Keys used:
|
|
165
|
-
|
|
166
|
-
- `NAVAI_ROUTES_FILE`
|
|
167
|
-
- `NAVAI_FUNCTIONS_FOLDERS`
|
|
168
|
-
- `
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
166
|
+
Keys used:
|
|
167
|
+
|
|
168
|
+
- `NAVAI_ROUTES_FILE`
|
|
169
|
+
- `NAVAI_FUNCTIONS_FOLDERS`
|
|
170
|
+
- `NAVAI_AGENTS_FOLDERS`
|
|
171
|
+
- `NAVAI_REALTIME_MODEL`
|
|
172
|
+
|
|
173
|
+
Defaults:
|
|
174
|
+
|
|
175
|
+
- routes file: `src/ai/routes.ts`
|
|
176
|
+
- functions folder: `src/ai/functions-modules`
|
|
177
|
+
|
|
178
|
+
Multi-agent layout:
|
|
179
|
+
|
|
180
|
+
- agent root: `src/ai`
|
|
181
|
+
- agents env: `NAVAI_AGENTS_FOLDERS=main,support,sales,food`
|
|
182
|
+
- per-agent files live in `src/ai/<agent>/...`
|
|
183
|
+
- optional per-agent config file: `src/ai/<agent>/agent.config.ts`
|
|
184
|
+
- only the first level under `src/ai/` defines the agent key
|
|
185
|
+
- deeper folders are optional organization for that same agent
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
src/ai/
|
|
191
|
+
main/
|
|
192
|
+
agent.config.ts
|
|
193
|
+
session/logout.fn.ts
|
|
194
|
+
support/open-help.fn.ts
|
|
195
|
+
support/
|
|
196
|
+
agent.config.ts
|
|
197
|
+
system/ai-service.ts
|
|
198
|
+
sales/
|
|
199
|
+
agent.config.ts
|
|
200
|
+
utils/math.ts
|
|
201
|
+
food/
|
|
202
|
+
agent.config.ts
|
|
203
|
+
comida_rapida/hamburguesa.ts
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Notes:
|
|
207
|
+
|
|
208
|
+
- `src/ai/main/session/logout.fn.ts` belongs to the `main` agent.
|
|
209
|
+
- `src/ai/main/support/open-help.fn.ts` also belongs to the `main` agent.
|
|
210
|
+
- folders like `session`, `support`, `help`, or `utils` inside an agent are optional.
|
|
174
211
|
|
|
175
212
|
Path matcher formats:
|
|
176
213
|
|
|
@@ -180,10 +217,14 @@ Path matcher formats:
|
|
|
180
217
|
- explicit file: `src/ai/functions-modules/secret.ts`
|
|
181
218
|
- CSV list: `a,b,c`
|
|
182
219
|
|
|
183
|
-
Fallback behavior:
|
|
184
|
-
|
|
185
|
-
- if configured folders match no modules, warning is emitted.
|
|
186
|
-
- resolver falls back to default functions folder.
|
|
220
|
+
Fallback behavior:
|
|
221
|
+
|
|
222
|
+
- if configured folders match no modules, warning is emitted.
|
|
223
|
+
- resolver falls back to default functions folder.
|
|
224
|
+
|
|
225
|
+
When `NAVAI_AGENTS_FOLDERS` is present and `NAVAI_FUNCTIONS_FOLDERS` points to a root such as `src/ai`, the resolver only includes modules inside `src/ai/<agent>/...` for the configured agents.
|
|
226
|
+
|
|
227
|
+
For browser realtime multi-agent orchestration, `buildNavaiAgent` currently wires specialist agents with `handoffs` inside the shared `RealtimeSession`.
|
|
187
228
|
|
|
188
229
|
## Backend Client Behavior
|
|
189
230
|
|
package/README.es.md
CHANGED
|
@@ -32,22 +32,24 @@ Cliente HTTP para rutas backend:
|
|
|
32
32
|
- `GET /navai/functions`
|
|
33
33
|
- `POST /navai/functions/execute`
|
|
34
34
|
|
|
35
|
-
2. `src/runtime.ts`
|
|
36
|
-
Resolver de runtime para:
|
|
37
|
-
- seleccion de modulo de rutas
|
|
38
|
-
- filtrado de modulos de funciones por `NAVAI_FUNCTIONS_FOLDERS`
|
|
39
|
-
-
|
|
35
|
+
2. `src/runtime.ts`
|
|
36
|
+
Resolver de runtime para:
|
|
37
|
+
- seleccion de modulo de rutas
|
|
38
|
+
- filtrado de modulos de funciones por `NAVAI_FUNCTIONS_FOLDERS`
|
|
39
|
+
- descubrimiento de agentes por `NAVAI_AGENTS_FOLDERS`
|
|
40
|
+
- override opcional de modelo
|
|
40
41
|
|
|
41
42
|
3. `src/functions.ts`
|
|
42
43
|
Loader de funciones locales:
|
|
43
44
|
- importa modulos desde loaders generados
|
|
44
45
|
- transforma exports en definiciones de tools normalizadas y ejecutables
|
|
45
46
|
|
|
46
|
-
4. `src/agent.ts`
|
|
47
|
-
Builder del agente:
|
|
48
|
-
- crea `RealtimeAgent`
|
|
49
|
-
- inyecta tools base (`navigate_to`, `execute_app_function`)
|
|
50
|
-
- agrega aliases directos por funcion permitida cuando aplica
|
|
47
|
+
4. `src/agent.ts`
|
|
48
|
+
Builder del agente:
|
|
49
|
+
- crea el `RealtimeAgent` principal
|
|
50
|
+
- inyecta tools base (`navigate_to`, `execute_app_function`)
|
|
51
|
+
- agrega aliases directos por funcion permitida cuando aplica
|
|
52
|
+
- crea agentes especialistas y los conecta con `handoffs`
|
|
51
53
|
|
|
52
54
|
5. `src/useWebVoiceAgent.ts`
|
|
53
55
|
Wrapper de ciclo de vida React:
|
|
@@ -161,16 +163,51 @@ Prioridad de entrada en `resolveNavaiFrontendRuntimeConfig`:
|
|
|
161
163
|
2. Claves del objeto env.
|
|
162
164
|
3. Defaults del paquete.
|
|
163
165
|
|
|
164
|
-
Claves usadas:
|
|
165
|
-
|
|
166
|
-
- `NAVAI_ROUTES_FILE`
|
|
167
|
-
- `NAVAI_FUNCTIONS_FOLDERS`
|
|
168
|
-
- `
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
166
|
+
Claves usadas:
|
|
167
|
+
|
|
168
|
+
- `NAVAI_ROUTES_FILE`
|
|
169
|
+
- `NAVAI_FUNCTIONS_FOLDERS`
|
|
170
|
+
- `NAVAI_AGENTS_FOLDERS`
|
|
171
|
+
- `NAVAI_REALTIME_MODEL`
|
|
172
|
+
|
|
173
|
+
Defaults:
|
|
174
|
+
|
|
175
|
+
- archivo de rutas: `src/ai/routes.ts`
|
|
176
|
+
- carpeta de funciones: `src/ai/functions-modules`
|
|
177
|
+
|
|
178
|
+
Estructura multiagente:
|
|
179
|
+
|
|
180
|
+
- raiz de agentes: `src/ai`
|
|
181
|
+
- env de agentes: `NAVAI_AGENTS_FOLDERS=main,support,sales,food`
|
|
182
|
+
- los archivos por agente viven en `src/ai/<agent>/...`
|
|
183
|
+
- archivo opcional por agente: `src/ai/<agent>/agent.config.ts`
|
|
184
|
+
- solo el primer nivel debajo de `src/ai/` define la clave del agente
|
|
185
|
+
- el resto de carpetas son solo organizacion interna de ese agente
|
|
186
|
+
|
|
187
|
+
Ejemplo:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
src/ai/
|
|
191
|
+
main/
|
|
192
|
+
agent.config.ts
|
|
193
|
+
session/logout.fn.ts
|
|
194
|
+
support/open-help.fn.ts
|
|
195
|
+
support/
|
|
196
|
+
agent.config.ts
|
|
197
|
+
system/ai-service.ts
|
|
198
|
+
sales/
|
|
199
|
+
agent.config.ts
|
|
200
|
+
utils/math.ts
|
|
201
|
+
food/
|
|
202
|
+
agent.config.ts
|
|
203
|
+
comida_rapida/hamburguesa.ts
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Notas:
|
|
207
|
+
|
|
208
|
+
- `src/ai/main/session/logout.fn.ts` pertenece al agente `main`.
|
|
209
|
+
- `src/ai/main/support/open-help.fn.ts` tambien pertenece al agente `main`.
|
|
210
|
+
- carpetas como `session`, `support`, `help` o `utils` dentro de un agente no son obligatorias.
|
|
174
211
|
|
|
175
212
|
Formatos aceptados en matcher de rutas:
|
|
176
213
|
|
|
@@ -180,10 +217,14 @@ Formatos aceptados en matcher de rutas:
|
|
|
180
217
|
- archivo explicito: `src/ai/functions-modules/secret.ts`
|
|
181
218
|
- CSV: `a,b,c`
|
|
182
219
|
|
|
183
|
-
Comportamiento fallback:
|
|
184
|
-
|
|
185
|
-
- si `NAVAI_FUNCTIONS_FOLDERS` no matchea modulos, emite warning.
|
|
186
|
-
- hace fallback a carpeta de funciones por defecto.
|
|
220
|
+
Comportamiento fallback:
|
|
221
|
+
|
|
222
|
+
- si `NAVAI_FUNCTIONS_FOLDERS` no matchea modulos, emite warning.
|
|
223
|
+
- hace fallback a carpeta de funciones por defecto.
|
|
224
|
+
|
|
225
|
+
Cuando `NAVAI_AGENTS_FOLDERS` esta presente y `NAVAI_FUNCTIONS_FOLDERS` apunta a una raiz como `src/ai`, el resolver solo incluye modulos dentro de `src/ai/<agent>/...` para los agentes configurados.
|
|
226
|
+
|
|
227
|
+
En realtime web, `buildNavaiAgent` conecta actualmente los agentes especialistas usando `handoffs` dentro de la misma `RealtimeSession`.
|
|
187
228
|
|
|
188
229
|
## Comportamiento del Backend Client
|
|
189
230
|
|
package/README.md
CHANGED
|
@@ -32,22 +32,24 @@ HTTP client for backend routes:
|
|
|
32
32
|
- `GET /navai/functions`
|
|
33
33
|
- `POST /navai/functions/execute`
|
|
34
34
|
|
|
35
|
-
2. `src/runtime.ts`
|
|
36
|
-
Runtime resolver for:
|
|
37
|
-
- route module selection
|
|
38
|
-
- function module filtering by `NAVAI_FUNCTIONS_FOLDERS`
|
|
39
|
-
-
|
|
35
|
+
2. `src/runtime.ts`
|
|
36
|
+
Runtime resolver for:
|
|
37
|
+
- route module selection
|
|
38
|
+
- function module filtering by `NAVAI_FUNCTIONS_FOLDERS`
|
|
39
|
+
- agent discovery by `NAVAI_AGENTS_FOLDERS`
|
|
40
|
+
- optional model override
|
|
40
41
|
|
|
41
42
|
3. `src/functions.ts`
|
|
42
43
|
Local function loader:
|
|
43
44
|
- imports modules from generated loaders
|
|
44
45
|
- converts exports into normalized callable tool definitions
|
|
45
46
|
|
|
46
|
-
4. `src/agent.ts`
|
|
47
|
-
Agent builder:
|
|
48
|
-
- creates `RealtimeAgent`
|
|
49
|
-
- injects built-in tools (`navigate_to`, `execute_app_function`)
|
|
50
|
-
- optionally adds direct alias tools for each allowed function
|
|
47
|
+
4. `src/agent.ts`
|
|
48
|
+
Agent builder:
|
|
49
|
+
- creates primary `RealtimeAgent`
|
|
50
|
+
- injects built-in tools (`navigate_to`, `execute_app_function`)
|
|
51
|
+
- optionally adds direct alias tools for each allowed function
|
|
52
|
+
- creates specialist realtime agents and wires them as `handoffs`
|
|
51
53
|
|
|
52
54
|
5. `src/useWebVoiceAgent.ts`
|
|
53
55
|
React lifecycle wrapper:
|
|
@@ -110,10 +112,16 @@ Useful types:
|
|
|
110
112
|
|
|
111
113
|
## Tool Model and Behavior
|
|
112
114
|
|
|
113
|
-
`buildNavaiAgent` always registers:
|
|
114
|
-
|
|
115
|
-
- `navigate_to`
|
|
116
|
-
- `execute_app_function`
|
|
115
|
+
`buildNavaiAgent` always registers:
|
|
116
|
+
|
|
117
|
+
- `navigate_to`
|
|
118
|
+
- `execute_app_function`
|
|
119
|
+
|
|
120
|
+
When runtime agents are available:
|
|
121
|
+
|
|
122
|
+
- the first configured or explicit primary agent becomes the main realtime agent.
|
|
123
|
+
- other configured agents become specialist `RealtimeAgent` instances.
|
|
124
|
+
- the main agent delegates with `handoffs`, following the OpenAI Agents SDK multi-agent model.
|
|
117
125
|
|
|
118
126
|
Optional direct alias tools:
|
|
119
127
|
|
|
@@ -161,16 +169,58 @@ For class methods:
|
|
|
161
169
|
2. Env object keys.
|
|
162
170
|
3. Package defaults.
|
|
163
171
|
|
|
164
|
-
Keys used:
|
|
165
|
-
|
|
166
|
-
- `NAVAI_ROUTES_FILE`
|
|
167
|
-
- `NAVAI_FUNCTIONS_FOLDERS`
|
|
168
|
-
- `
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
172
|
+
Keys used:
|
|
173
|
+
|
|
174
|
+
- `NAVAI_ROUTES_FILE`
|
|
175
|
+
- `NAVAI_FUNCTIONS_FOLDERS`
|
|
176
|
+
- `NAVAI_AGENTS_FOLDERS`
|
|
177
|
+
- `NAVAI_REALTIME_MODEL`
|
|
178
|
+
|
|
179
|
+
Defaults:
|
|
180
|
+
|
|
181
|
+
- routes file: `src/ai/routes.ts`
|
|
182
|
+
- functions folder: `src/ai/functions-modules`
|
|
183
|
+
|
|
184
|
+
Multi-agent layout:
|
|
185
|
+
|
|
186
|
+
- agent root: `src/ai`
|
|
187
|
+
- agents env: `NAVAI_AGENTS_FOLDERS=main,support,sales,food`
|
|
188
|
+
- per-agent files live in `src/ai/<agent>/...`
|
|
189
|
+
- optional per-agent config file: `src/ai/<agent>/agent.config.ts`
|
|
190
|
+
- only the first level under `src/ai/` defines the agent key
|
|
191
|
+
- deeper folders are optional organization for that same agent
|
|
192
|
+
|
|
193
|
+
Multi-agent layout:
|
|
194
|
+
|
|
195
|
+
- agent root: `src/ai`
|
|
196
|
+
- agents env: `NAVAI_AGENTS_FOLDERS=main,support,sales`
|
|
197
|
+
- per-agent files live in `src/ai/<agent>/...`
|
|
198
|
+
- optional per-agent config file: `src/ai/<agent>/agent.config.ts`
|
|
199
|
+
|
|
200
|
+
Example:
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
src/ai/
|
|
204
|
+
main/
|
|
205
|
+
agent.config.ts
|
|
206
|
+
session/logout.fn.ts
|
|
207
|
+
support/open-help.fn.ts
|
|
208
|
+
support/
|
|
209
|
+
agent.config.ts
|
|
210
|
+
system/ai-service.ts
|
|
211
|
+
sales/
|
|
212
|
+
agent.config.ts
|
|
213
|
+
utils/math.ts
|
|
214
|
+
food/
|
|
215
|
+
agent.config.ts
|
|
216
|
+
comida_rapida/hamburguesa.ts
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Notes:
|
|
220
|
+
|
|
221
|
+
- `src/ai/main/session/logout.fn.ts` belongs to the `main` agent.
|
|
222
|
+
- `src/ai/main/support/open-help.fn.ts` also belongs to the `main` agent.
|
|
223
|
+
- folders like `session`, `support`, `help`, or `utils` inside an agent are optional.
|
|
174
224
|
|
|
175
225
|
Path matcher formats:
|
|
176
226
|
|
|
@@ -180,10 +230,14 @@ Path matcher formats:
|
|
|
180
230
|
- explicit file: `src/ai/functions-modules/secret.ts`
|
|
181
231
|
- CSV list: `a,b,c`
|
|
182
232
|
|
|
183
|
-
Fallback behavior:
|
|
184
|
-
|
|
185
|
-
- if configured folders match no modules, warning is emitted.
|
|
186
|
-
- resolver falls back to default functions folder.
|
|
233
|
+
Fallback behavior:
|
|
234
|
+
|
|
235
|
+
- if configured folders match no modules, warning is emitted.
|
|
236
|
+
- resolver falls back to default functions folder.
|
|
237
|
+
|
|
238
|
+
When `NAVAI_AGENTS_FOLDERS` is present and `NAVAI_FUNCTIONS_FOLDERS` points to a folder root such as `src/ai`, the resolver only includes modules inside `src/ai/<agent>/...` for the configured agents.
|
|
239
|
+
|
|
240
|
+
For browser realtime multi-agent orchestration, `buildNavaiAgent` currently wires specialist agents with `handoffs` inside the shared `RealtimeSession`.
|
|
187
241
|
|
|
188
242
|
## Backend Client Behavior
|
|
189
243
|
|
|
@@ -39,9 +39,13 @@ async function main() {
|
|
|
39
39
|
const configuredFunctionsFolders =
|
|
40
40
|
readOptional(process.env.NAVAI_FUNCTIONS_FOLDERS) ??
|
|
41
41
|
readOptional(envFileValues.NAVAI_FUNCTIONS_FOLDERS);
|
|
42
|
+
const configuredAgentsFolders =
|
|
43
|
+
readOptional(process.env.NAVAI_AGENTS_FOLDERS) ??
|
|
44
|
+
readOptional(envFileValues.NAVAI_AGENTS_FOLDERS);
|
|
42
45
|
const configuredRoutesFile =
|
|
43
46
|
readOptional(process.env.NAVAI_ROUTES_FILE) ?? readOptional(envFileValues.NAVAI_ROUTES_FILE);
|
|
44
47
|
const functionsFolders = configuredFunctionsFolders ?? defaultFunctionsFolder;
|
|
48
|
+
const agentTokens = parseCsvList(configuredAgentsFolders);
|
|
45
49
|
const routesFile = configuredRoutesFile ?? defaultRoutesFile;
|
|
46
50
|
|
|
47
51
|
const defaultRoutesModuleFile = await resolveModulePathFromFs(defaultRoutesFile, projectRoot);
|
|
@@ -52,7 +56,7 @@ async function main() {
|
|
|
52
56
|
.filter(Boolean);
|
|
53
57
|
const functionTokens =
|
|
54
58
|
configuredFunctionTokens.length > 0 ? configuredFunctionTokens : [defaultFunctionsFolder];
|
|
55
|
-
const functionMatchers = functionTokens.map((token) => createPathMatcher(token));
|
|
59
|
+
const functionMatchers = functionTokens.map((token) => createPathMatcher(token, agentTokens));
|
|
56
60
|
|
|
57
61
|
let selectedFunctionFiles = await collectFilesForTokens({
|
|
58
62
|
tokens: functionTokens,
|
|
@@ -66,7 +70,7 @@ async function main() {
|
|
|
66
70
|
});
|
|
67
71
|
|
|
68
72
|
if (selectedFunctionFiles.length === 0 && configuredFunctionTokens.length > 0) {
|
|
69
|
-
const fallbackMatcher = createPathMatcher(defaultFunctionsFolder);
|
|
73
|
+
const fallbackMatcher = createPathMatcher(defaultFunctionsFolder, agentTokens);
|
|
70
74
|
selectedFunctionFiles = await collectFilesForTokens({
|
|
71
75
|
tokens: [defaultFunctionsFolder],
|
|
72
76
|
projectRoot,
|
|
@@ -423,7 +427,7 @@ function globToRegExp(pattern) {
|
|
|
423
427
|
return new RegExp(`^${output}$`);
|
|
424
428
|
}
|
|
425
429
|
|
|
426
|
-
function createPathMatcher(input) {
|
|
430
|
+
function createPathMatcher(input, agentFolders = []) {
|
|
427
431
|
const normalized = ensureSrcPrefix(input);
|
|
428
432
|
if (!normalized) {
|
|
429
433
|
return () => false;
|
|
@@ -444,9 +448,33 @@ function createPathMatcher(input) {
|
|
|
444
448
|
}
|
|
445
449
|
|
|
446
450
|
const base = normalized.replace(/\/+$/, "");
|
|
451
|
+
const normalizedAgents = agentFolders.map(normalizePathSegment).filter(Boolean);
|
|
452
|
+
if (normalizedAgents.length > 0) {
|
|
453
|
+
return (candidatePath) => {
|
|
454
|
+
if (!candidatePath.startsWith(`${base}/`)) {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const suffix = candidatePath.slice(base.length + 1);
|
|
459
|
+
const firstSegment = suffix.split("/", 1)[0] ?? "";
|
|
460
|
+
return normalizedAgents.includes(firstSegment);
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
447
464
|
return (candidatePath) => candidatePath === base || candidatePath.startsWith(`${base}/`);
|
|
448
465
|
}
|
|
449
466
|
|
|
467
|
+
function normalizePathSegment(input) {
|
|
468
|
+
return normalizeSourcePath(input).replace(/\//g, "");
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function parseCsvList(input) {
|
|
472
|
+
return (input ?? "")
|
|
473
|
+
.split(",")
|
|
474
|
+
.map((value) => normalizePathSegment(value))
|
|
475
|
+
.filter(Boolean);
|
|
476
|
+
}
|
|
477
|
+
|
|
450
478
|
function buildModuleCandidates(inputPath) {
|
|
451
479
|
const normalized = ensureSrcPrefix(inputPath);
|
|
452
480
|
if (!normalized) {
|