@poolzin/pool-bot 2026.2.4 → 2026.2.6
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/dist/agents/auth-profiles/profiles.js +9 -0
- package/dist/agents/auth-profiles.js +1 -1
- package/dist/agents/huggingface-models.js +166 -0
- package/dist/agents/model-auth.js +6 -0
- package/dist/agents/model-forward-compat.js +187 -0
- package/dist/agents/pi-embedded-runner/model.js +10 -56
- package/dist/browser/constants.js +1 -1
- package/dist/browser/profiles.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/cli/config-cli.js +17 -3
- package/dist/cli/program/register.onboard.js +38 -5
- package/dist/commands/auth-choice-options.js +71 -7
- package/dist/commands/auth-choice.apply.api-providers.js +202 -97
- package/dist/commands/auth-choice.apply.huggingface.js +130 -0
- package/dist/commands/auth-choice.apply.openrouter.js +77 -0
- package/dist/commands/auth-choice.apply.plugin-provider.js +1 -56
- package/dist/commands/auth-choice.apply.vllm.js +92 -0
- package/dist/commands/auth-choice.preferred-provider.js +10 -0
- package/dist/commands/models/auth.js +1 -58
- package/dist/commands/models/list.errors.js +14 -0
- package/dist/commands/models/list.list-command.js +32 -21
- package/dist/commands/models/list.registry.js +120 -28
- package/dist/commands/models/list.status-command.js +1 -0
- package/dist/commands/models/shared.js +14 -0
- package/dist/commands/onboard-auth.config-core.js +265 -8
- package/dist/commands/onboard-auth.credentials.js +47 -6
- package/dist/commands/onboard-auth.js +3 -3
- package/dist/commands/onboard-auth.models.js +67 -0
- package/dist/commands/onboard-custom.js +181 -70
- package/dist/commands/onboard-non-interactive/api-keys.js +10 -1
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +15 -7
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +322 -124
- package/dist/commands/provider-auth-helpers.js +61 -0
- package/dist/commands/zai-endpoint-detect.js +97 -0
- package/dist/config/legacy.migrations.part-3.js +57 -0
- package/dist/terminal/theme.js +1 -1
- package/package.json +1 -1
|
@@ -7,18 +7,24 @@ const DEFAULT_OLLAMA_BASE_URL = "http://127.0.0.1:11434/v1";
|
|
|
7
7
|
const DEFAULT_CONTEXT_WINDOW = 4096;
|
|
8
8
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
9
9
|
const VERIFY_TIMEOUT_MS = 10000;
|
|
10
|
+
export class CustomApiError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
constructor(code, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "CustomApiError";
|
|
15
|
+
this.code = code;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
10
18
|
const COMPATIBILITY_OPTIONS = [
|
|
11
19
|
{
|
|
12
20
|
value: "openai",
|
|
13
21
|
label: "OpenAI-compatible",
|
|
14
22
|
hint: "Uses /chat/completions",
|
|
15
|
-
api: "openai-completions",
|
|
16
23
|
},
|
|
17
24
|
{
|
|
18
25
|
value: "anthropic",
|
|
19
26
|
label: "Anthropic-compatible",
|
|
20
27
|
hint: "Uses /messages",
|
|
21
|
-
api: "anthropic-messages",
|
|
22
28
|
},
|
|
23
29
|
{
|
|
24
30
|
value: "unknown",
|
|
@@ -183,6 +189,155 @@ async function promptBaseUrlAndKey(params) {
|
|
|
183
189
|
});
|
|
184
190
|
return { baseUrl: baseUrlInput.trim(), apiKey: apiKeyInput.trim() };
|
|
185
191
|
}
|
|
192
|
+
function resolveProviderApi(compatibility) {
|
|
193
|
+
return compatibility === "anthropic" ? "anthropic-messages" : "openai-completions";
|
|
194
|
+
}
|
|
195
|
+
function parseCustomApiCompatibility(raw) {
|
|
196
|
+
const compatibilityRaw = raw?.trim().toLowerCase();
|
|
197
|
+
if (!compatibilityRaw) {
|
|
198
|
+
return "openai";
|
|
199
|
+
}
|
|
200
|
+
if (compatibilityRaw !== "openai" && compatibilityRaw !== "anthropic") {
|
|
201
|
+
throw new CustomApiError("invalid_compatibility", 'Invalid --custom-compatibility (use "openai" or "anthropic").');
|
|
202
|
+
}
|
|
203
|
+
return compatibilityRaw;
|
|
204
|
+
}
|
|
205
|
+
export function resolveCustomProviderId(params) {
|
|
206
|
+
const providers = params.config.models?.providers ?? {};
|
|
207
|
+
const baseUrl = params.baseUrl.trim();
|
|
208
|
+
const explicitProviderId = params.providerId?.trim();
|
|
209
|
+
if (explicitProviderId && !normalizeEndpointId(explicitProviderId)) {
|
|
210
|
+
throw new CustomApiError("invalid_provider_id", "Custom provider ID must include letters, numbers, or hyphens.");
|
|
211
|
+
}
|
|
212
|
+
const requestedProviderId = explicitProviderId || buildEndpointIdFromUrl(baseUrl);
|
|
213
|
+
const providerIdResult = resolveUniqueEndpointId({
|
|
214
|
+
requestedId: requestedProviderId,
|
|
215
|
+
baseUrl,
|
|
216
|
+
providers,
|
|
217
|
+
});
|
|
218
|
+
return {
|
|
219
|
+
providerId: providerIdResult.providerId,
|
|
220
|
+
...(providerIdResult.renamed
|
|
221
|
+
? {
|
|
222
|
+
providerIdRenamedFrom: normalizeEndpointId(requestedProviderId) || "custom",
|
|
223
|
+
}
|
|
224
|
+
: {}),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
export function parseNonInteractiveCustomApiFlags(params) {
|
|
228
|
+
const baseUrl = params.baseUrl?.trim() ?? "";
|
|
229
|
+
const modelId = params.modelId?.trim() ?? "";
|
|
230
|
+
if (!baseUrl || !modelId) {
|
|
231
|
+
throw new CustomApiError("missing_required", [
|
|
232
|
+
'Auth choice "custom-api-key" requires a base URL and model ID.',
|
|
233
|
+
"Use --custom-base-url and --custom-model-id.",
|
|
234
|
+
].join("\n"));
|
|
235
|
+
}
|
|
236
|
+
const apiKey = params.apiKey?.trim();
|
|
237
|
+
const providerId = params.providerId?.trim();
|
|
238
|
+
if (providerId && !normalizeEndpointId(providerId)) {
|
|
239
|
+
throw new CustomApiError("invalid_provider_id", "Custom provider ID must include letters, numbers, or hyphens.");
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
baseUrl,
|
|
243
|
+
modelId,
|
|
244
|
+
compatibility: parseCustomApiCompatibility(params.compatibility),
|
|
245
|
+
...(apiKey ? { apiKey } : {}),
|
|
246
|
+
...(providerId ? { providerId } : {}),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
export function applyCustomApiConfig(params) {
|
|
250
|
+
const baseUrl = params.baseUrl.trim();
|
|
251
|
+
try {
|
|
252
|
+
new URL(baseUrl);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
throw new CustomApiError("invalid_base_url", "Custom provider base URL must be a valid URL.");
|
|
256
|
+
}
|
|
257
|
+
if (params.compatibility !== "openai" && params.compatibility !== "anthropic") {
|
|
258
|
+
throw new CustomApiError("invalid_compatibility", 'Custom provider compatibility must be "openai" or "anthropic".');
|
|
259
|
+
}
|
|
260
|
+
const modelId = params.modelId.trim();
|
|
261
|
+
if (!modelId) {
|
|
262
|
+
throw new CustomApiError("invalid_model_id", "Custom provider model ID is required.");
|
|
263
|
+
}
|
|
264
|
+
const providerIdResult = resolveCustomProviderId({
|
|
265
|
+
config: params.config,
|
|
266
|
+
baseUrl,
|
|
267
|
+
providerId: params.providerId,
|
|
268
|
+
});
|
|
269
|
+
const providerId = providerIdResult.providerId;
|
|
270
|
+
const providers = params.config.models?.providers ?? {};
|
|
271
|
+
const modelRef = modelKey(providerId, modelId);
|
|
272
|
+
const alias = params.alias?.trim() ?? "";
|
|
273
|
+
const aliasError = resolveAliasError({
|
|
274
|
+
raw: alias,
|
|
275
|
+
cfg: params.config,
|
|
276
|
+
modelRef,
|
|
277
|
+
});
|
|
278
|
+
if (aliasError) {
|
|
279
|
+
throw new CustomApiError("invalid_alias", aliasError);
|
|
280
|
+
}
|
|
281
|
+
const existingProvider = providers[providerId];
|
|
282
|
+
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
|
|
283
|
+
const hasModel = existingModels.some((model) => model.id === modelId);
|
|
284
|
+
const nextModel = {
|
|
285
|
+
id: modelId,
|
|
286
|
+
name: `${modelId} (Custom Provider)`,
|
|
287
|
+
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
288
|
+
maxTokens: DEFAULT_MAX_TOKENS,
|
|
289
|
+
input: ["text"],
|
|
290
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
291
|
+
reasoning: false,
|
|
292
|
+
};
|
|
293
|
+
const mergedModels = hasModel ? existingModels : [...existingModels, nextModel];
|
|
294
|
+
const { apiKey: existingApiKey, ...existingProviderRest } = existingProvider ?? {};
|
|
295
|
+
const normalizedApiKey = params.apiKey?.trim() || (existingApiKey ? existingApiKey.trim() : undefined);
|
|
296
|
+
let config = {
|
|
297
|
+
...params.config,
|
|
298
|
+
models: {
|
|
299
|
+
...params.config.models,
|
|
300
|
+
mode: params.config.models?.mode ?? "merge",
|
|
301
|
+
providers: {
|
|
302
|
+
...providers,
|
|
303
|
+
[providerId]: {
|
|
304
|
+
...existingProviderRest,
|
|
305
|
+
baseUrl,
|
|
306
|
+
api: resolveProviderApi(params.compatibility),
|
|
307
|
+
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
|
|
308
|
+
models: mergedModels.length > 0 ? mergedModels : [nextModel],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
config = applyPrimaryModel(config, modelRef);
|
|
314
|
+
if (alias) {
|
|
315
|
+
config = {
|
|
316
|
+
...config,
|
|
317
|
+
agents: {
|
|
318
|
+
...config.agents,
|
|
319
|
+
defaults: {
|
|
320
|
+
...config.agents?.defaults,
|
|
321
|
+
models: {
|
|
322
|
+
...config.agents?.defaults?.models,
|
|
323
|
+
[modelRef]: {
|
|
324
|
+
...config.agents?.defaults?.models?.[modelRef],
|
|
325
|
+
alias,
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
config,
|
|
334
|
+
providerId,
|
|
335
|
+
modelId,
|
|
336
|
+
...(providerIdResult.providerIdRenamedFrom
|
|
337
|
+
? { providerIdRenamedFrom: providerIdResult.providerIdRenamedFrom }
|
|
338
|
+
: {}),
|
|
339
|
+
};
|
|
340
|
+
}
|
|
186
341
|
export async function promptCustomApiConfig(params) {
|
|
187
342
|
const { prompter, runtime, config } = params;
|
|
188
343
|
const baseInput = await promptBaseUrlAndKey({ prompter });
|
|
@@ -202,8 +357,6 @@ export async function promptCustomApiConfig(params) {
|
|
|
202
357
|
validate: (val) => (val.trim() ? undefined : "Model ID is required"),
|
|
203
358
|
})).trim();
|
|
204
359
|
let compatibility = compatibilityChoice === "unknown" ? null : compatibilityChoice;
|
|
205
|
-
let providerApi = COMPATIBILITY_OPTIONS.find((entry) => entry.value === compatibility)?.api ??
|
|
206
|
-
"openai-completions";
|
|
207
360
|
while (true) {
|
|
208
361
|
let verifiedFromProbe = false;
|
|
209
362
|
if (!compatibility) {
|
|
@@ -212,7 +365,6 @@ export async function promptCustomApiConfig(params) {
|
|
|
212
365
|
if (openaiProbe.ok) {
|
|
213
366
|
probeSpinner.stop("Detected OpenAI-compatible endpoint.");
|
|
214
367
|
compatibility = "openai";
|
|
215
|
-
providerApi = "openai-completions";
|
|
216
368
|
verifiedFromProbe = true;
|
|
217
369
|
}
|
|
218
370
|
else {
|
|
@@ -220,7 +372,6 @@ export async function promptCustomApiConfig(params) {
|
|
|
220
372
|
if (anthropicProbe.ok) {
|
|
221
373
|
probeSpinner.stop("Detected Anthropic-compatible endpoint.");
|
|
222
374
|
compatibility = "anthropic";
|
|
223
|
-
providerApi = "anthropic-messages";
|
|
224
375
|
verifiedFromProbe = true;
|
|
225
376
|
}
|
|
226
377
|
else {
|
|
@@ -311,74 +462,34 @@ export async function promptCustomApiConfig(params) {
|
|
|
311
462
|
return undefined;
|
|
312
463
|
},
|
|
313
464
|
});
|
|
314
|
-
const providerIdResult = resolveUniqueEndpointId({
|
|
315
|
-
requestedId: providerIdInput,
|
|
316
|
-
baseUrl,
|
|
317
|
-
providers,
|
|
318
|
-
});
|
|
319
|
-
if (providerIdResult.renamed) {
|
|
320
|
-
await prompter.note(`Endpoint ID "${providerIdInput}" already exists for a different base URL. Using "${providerIdResult.providerId}".`, "Endpoint ID");
|
|
321
|
-
}
|
|
322
|
-
const providerId = providerIdResult.providerId;
|
|
323
|
-
const modelRef = modelKey(providerId, modelId);
|
|
324
465
|
const aliasInput = await prompter.text({
|
|
325
466
|
message: "Model alias (optional)",
|
|
326
467
|
placeholder: "e.g. local, ollama",
|
|
327
468
|
initialValue: "",
|
|
328
|
-
validate: (value) =>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
338
|
-
maxTokens: DEFAULT_MAX_TOKENS,
|
|
339
|
-
input: ["text"],
|
|
340
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
341
|
-
reasoning: false,
|
|
342
|
-
};
|
|
343
|
-
const mergedModels = hasModel ? existingModels : [...existingModels, nextModel];
|
|
344
|
-
const { apiKey: existingApiKey, ...existingProviderRest } = existingProvider ?? {};
|
|
345
|
-
const normalizedApiKey = apiKey.trim() || (existingApiKey ? existingApiKey.trim() : undefined);
|
|
346
|
-
let newConfig = {
|
|
347
|
-
...config,
|
|
348
|
-
models: {
|
|
349
|
-
...config.models,
|
|
350
|
-
mode: config.models?.mode ?? "merge",
|
|
351
|
-
providers: {
|
|
352
|
-
...providers,
|
|
353
|
-
[providerId]: {
|
|
354
|
-
...existingProviderRest,
|
|
355
|
-
baseUrl,
|
|
356
|
-
api: providerApi,
|
|
357
|
-
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
|
|
358
|
-
models: mergedModels.length > 0 ? mergedModels : [nextModel],
|
|
359
|
-
},
|
|
360
|
-
},
|
|
469
|
+
validate: (value) => {
|
|
470
|
+
const requestedId = normalizeEndpointId(providerIdInput) || "custom";
|
|
471
|
+
const providerIdResult = resolveUniqueEndpointId({
|
|
472
|
+
requestedId,
|
|
473
|
+
baseUrl,
|
|
474
|
+
providers,
|
|
475
|
+
});
|
|
476
|
+
const modelRef = modelKey(providerIdResult.providerId, modelId);
|
|
477
|
+
return resolveAliasError({ raw: value, cfg: config, modelRef });
|
|
361
478
|
},
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
alias,
|
|
376
|
-
},
|
|
377
|
-
},
|
|
378
|
-
},
|
|
379
|
-
},
|
|
380
|
-
};
|
|
479
|
+
});
|
|
480
|
+
const resolvedCompatibility = compatibility ?? "openai";
|
|
481
|
+
const result = applyCustomApiConfig({
|
|
482
|
+
config,
|
|
483
|
+
baseUrl,
|
|
484
|
+
modelId,
|
|
485
|
+
compatibility: resolvedCompatibility,
|
|
486
|
+
apiKey,
|
|
487
|
+
providerId: providerIdInput,
|
|
488
|
+
alias: aliasInput,
|
|
489
|
+
});
|
|
490
|
+
if (result.providerIdRenamedFrom && result.providerId) {
|
|
491
|
+
await prompter.note(`Endpoint ID "${result.providerIdRenamedFrom}" already exists for a different base URL. Using "${result.providerId}".`, "Endpoint ID");
|
|
381
492
|
}
|
|
382
|
-
runtime.log(`Configured custom provider: ${providerId}/${modelId}`);
|
|
383
|
-
return
|
|
493
|
+
runtime.log(`Configured custom provider: ${result.providerId}/${result.modelId}`);
|
|
494
|
+
return result;
|
|
384
495
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ensureAuthProfileStore, resolveApiKeyForProfile, resolveAuthProfileOrder, } from "../../agents/auth-profiles.js";
|
|
2
2
|
import { resolveEnvApiKey } from "../../agents/model-auth.js";
|
|
3
|
+
import { normalizeOptionalSecretInput } from "../../utils/normalize-secret-input.js";
|
|
3
4
|
async function resolveApiKeyFromProfiles(params) {
|
|
4
5
|
const store = ensureAuthProfileStore(params.agentDir);
|
|
5
6
|
const order = resolveAuthProfileOrder({
|
|
@@ -23,12 +24,18 @@ async function resolveApiKeyFromProfiles(params) {
|
|
|
23
24
|
return null;
|
|
24
25
|
}
|
|
25
26
|
export async function resolveNonInteractiveApiKey(params) {
|
|
26
|
-
const flagKey = params.flagValue
|
|
27
|
+
const flagKey = normalizeOptionalSecretInput(params.flagValue);
|
|
27
28
|
if (flagKey)
|
|
28
29
|
return { key: flagKey, source: "flag" };
|
|
29
30
|
const envResolved = resolveEnvApiKey(params.provider);
|
|
30
31
|
if (envResolved?.apiKey)
|
|
31
32
|
return { key: envResolved.apiKey, source: "env" };
|
|
33
|
+
const explicitEnvVar = params.envVarName?.trim();
|
|
34
|
+
if (explicitEnvVar) {
|
|
35
|
+
const explicitEnvKey = normalizeOptionalSecretInput(process.env[explicitEnvVar]);
|
|
36
|
+
if (explicitEnvKey)
|
|
37
|
+
return { key: explicitEnvKey, source: "env" };
|
|
38
|
+
}
|
|
32
39
|
if (params.allowProfile ?? true) {
|
|
33
40
|
const profileKey = await resolveApiKeyFromProfiles({
|
|
34
41
|
provider: params.provider,
|
|
@@ -38,6 +45,8 @@ export async function resolveNonInteractiveApiKey(params) {
|
|
|
38
45
|
if (profileKey)
|
|
39
46
|
return { key: profileKey, source: "profile" };
|
|
40
47
|
}
|
|
48
|
+
if (params.required === false)
|
|
49
|
+
return null;
|
|
41
50
|
const profileHint = params.allowProfile === false ? "" : `, or existing ${params.provider} API-key profile`;
|
|
42
51
|
params.runtime.error(`Missing ${params.flagName} (or ${params.envVar} in env${profileHint}).`);
|
|
43
52
|
params.runtime.exit(1);
|
|
@@ -13,21 +13,29 @@ const AUTH_CHOICE_FLAG_MAP = [
|
|
|
13
13
|
{ flag: "kimiCodeApiKey", authChoice: "kimi-code-api-key", label: "--kimi-code-api-key" },
|
|
14
14
|
{ flag: "syntheticApiKey", authChoice: "synthetic-api-key", label: "--synthetic-api-key" },
|
|
15
15
|
{ flag: "veniceApiKey", authChoice: "venice-api-key", label: "--venice-api-key" },
|
|
16
|
+
{ flag: "togetherApiKey", authChoice: "together-api-key", label: "--together-api-key" },
|
|
16
17
|
{ flag: "zaiApiKey", authChoice: "zai-api-key", label: "--zai-api-key" },
|
|
17
18
|
{ flag: "xiaomiApiKey", authChoice: "xiaomi-api-key", label: "--xiaomi-api-key" },
|
|
18
19
|
{ flag: "xaiApiKey", authChoice: "xai-api-key", label: "--xai-api-key" },
|
|
20
|
+
{ flag: "nvidiaApiKey", authChoice: "nvidia-api-key", label: "--nvidia-api-key" },
|
|
21
|
+
{ flag: "huggingfaceApiKey", authChoice: "huggingface-api-key", label: "--huggingface-api-key" },
|
|
22
|
+
{ flag: "litellmApiKey", authChoice: "litellm-api-key", label: "--litellm-api-key" },
|
|
19
23
|
{ flag: "minimaxApiKey", authChoice: "minimax-api", label: "--minimax-api-key" },
|
|
20
24
|
{ flag: "opencodeZenApiKey", authChoice: "opencode-zen", label: "--opencode-zen-api-key" },
|
|
21
25
|
];
|
|
26
|
+
function hasStringValue(val) {
|
|
27
|
+
return typeof val === "string" && val.trim().length > 0;
|
|
28
|
+
}
|
|
22
29
|
// Infer auth choice from explicit provider API key flags.
|
|
23
30
|
export function inferAuthChoiceFromFlags(opts) {
|
|
24
|
-
const matches = AUTH_CHOICE_FLAG_MAP.filter(({ flag }) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const matches = AUTH_CHOICE_FLAG_MAP.filter(({ flag }) => hasStringValue(opts[flag]));
|
|
32
|
+
// Special case: custom-api-key is inferred from custom flags
|
|
33
|
+
if (!matches.length &&
|
|
34
|
+
(hasStringValue(opts.customBaseUrl) ||
|
|
35
|
+
hasStringValue(opts.customModelId) ||
|
|
36
|
+
hasStringValue(opts.customApiKey))) {
|
|
37
|
+
return { choice: "custom-api-key", matches: [] };
|
|
38
|
+
}
|
|
31
39
|
return {
|
|
32
40
|
choice: matches[0]?.authChoice,
|
|
33
41
|
matches,
|