@vedmalex/ai-connect 0.2.0 → 0.4.0

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/bun/local.js CHANGED
@@ -220,11 +220,7 @@ function normalizeTransport(providerId, input) {
220
220
  ...selector.whereEquals !== void 0 ? { whereEquals: selector.whereEquals } : {}
221
221
  };
222
222
  };
223
- const parser = (() => {
224
- if (!descriptor.cli?.parser) {
225
- return void 0;
226
- }
227
- const cliParser = descriptor.cli.parser;
223
+ const normalizeCliParser = (cliParser) => {
228
224
  if (cliParser.kind === "json") {
229
225
  assert(
230
226
  cliParser.textPath.trim().length > 0,
@@ -237,13 +233,22 @@ function normalizeTransport(providerId, input) {
237
233
  ...cliParser.usagePath?.trim() ? { usagePath: cliParser.usagePath.trim() } : {}
238
234
  };
239
235
  }
236
+ if (cliParser.kind === "text") {
237
+ return {
238
+ kind: "text",
239
+ // Default trim=true, stripAnsi=false; only persist explicit overrides.
240
+ ...cliParser.trim === false ? { trim: false } : {},
241
+ ...cliParser.stripAnsi === true ? { stripAnsi: true } : {}
242
+ };
243
+ }
240
244
  return {
241
245
  kind: "jsonl",
242
246
  text: normalizeSelector(cliParser.text, "text"),
243
247
  ...cliParser.error ? { error: normalizeSelector(cliParser.error, "error") } : {},
244
248
  ...cliParser.usage ? { usage: normalizeSelector(cliParser.usage, "usage") } : {}
245
249
  };
246
- })();
250
+ };
251
+ const parser = descriptor.cli?.parser ? normalizeCliParser(descriptor.cli.parser) : void 0;
247
252
  const normalized = {
248
253
  ...descriptor.cli.preset ? { preset: descriptor.cli.preset } : {},
249
254
  ...descriptor.cli.argsTemplate ? {
@@ -255,11 +260,13 @@ function normalizeTransport(providerId, input) {
255
260
  if (!descriptor.cli?.discovery) {
256
261
  return void 0;
257
262
  }
258
- const via = descriptor.cli.discovery.via ?? "none";
259
- assert(
260
- via === "none" || via === "acp",
261
- `Unsupported CLI discovery mode "${String(via)}" for provider "${providerId}".`
262
- );
263
+ const explicitVia = descriptor.cli.discovery.via;
264
+ if (explicitVia !== void 0) {
265
+ assert(
266
+ explicitVia === "none" || explicitVia === "acp" || explicitVia === "command" || explicitVia === "static",
267
+ `Unsupported CLI discovery mode "${String(explicitVia)}" for provider "${providerId}".`
268
+ );
269
+ }
263
270
  const launch = descriptor.cli.discovery.acp?.launch ? (() => {
264
271
  const contextMode = descriptor.cli.discovery?.acp?.launch?.contextMode ?? "workspace";
265
272
  const skillsMode = descriptor.cli.discovery?.acp?.launch?.skillsMode ?? "default";
@@ -280,7 +287,7 @@ function normalizeTransport(providerId, input) {
280
287
  methodId: descriptor.cli.discovery.acp.auth.methodId.trim(),
281
288
  params: descriptor.cli.discovery.acp.auth.params ?? {}
282
289
  } : void 0;
283
- const acp = via === "acp" ? {
290
+ const acp = descriptor.cli.discovery.acp ? {
284
291
  ...descriptor.cli.discovery.acp?.providerId?.trim() ? { providerId: descriptor.cli.discovery.acp.providerId.trim() } : {},
285
292
  ...descriptor.cli.discovery.acp?.transportId?.trim() ? {
286
293
  transportId: descriptor.cli.discovery.acp.transportId.trim()
@@ -288,9 +295,55 @@ function normalizeTransport(providerId, input) {
288
295
  ...auth ? { auth } : {},
289
296
  ...launch ? { launch } : {}
290
297
  } : void 0;
298
+ const commandInput = descriptor.cli.discovery.command;
299
+ const command = commandInput ? (() => {
300
+ assert(
301
+ Array.isArray(commandInput.argsTemplate) && commandInput.argsTemplate.length > 0,
302
+ `CLI discovery command.argsTemplate must be a non-empty array for provider "${providerId}".`
303
+ );
304
+ const cmdParserInput = commandInput.parser ?? { kind: "text" };
305
+ const cmdParser = cmdParserInput.kind === "text" ? {
306
+ kind: "text",
307
+ ...cmdParserInput.trim === false ? { trim: false } : {},
308
+ ...cmdParserInput.stripAnsi === true ? { stripAnsi: true } : {}
309
+ } : { kind: cmdParserInput.kind };
310
+ if (cmdParser.kind !== "text") {
311
+ assert(
312
+ Boolean(commandInput.models?.idPath?.trim()),
313
+ `CLI discovery command.models.idPath is required for a ${cmdParser.kind} parser for provider "${providerId}".`
314
+ );
315
+ }
316
+ const m = commandInput.models;
317
+ const models = m?.idPath?.trim() ? {
318
+ ...m.path?.trim() ? { path: m.path.trim() } : {},
319
+ idPath: m.idPath.trim(),
320
+ ...m.namePath?.trim() ? { namePath: m.namePath.trim() } : {},
321
+ ...m.descriptionPath?.trim() ? { descriptionPath: m.descriptionPath.trim() } : {},
322
+ ...m.contextLengthPath?.trim() ? { contextLengthPath: m.contextLengthPath.trim() } : {}
323
+ } : void 0;
324
+ return {
325
+ ...commandInput.command?.trim() ? { command: commandInput.command.trim() } : {},
326
+ argsTemplate: commandInput.argsTemplate.map((part) => String(part)),
327
+ parser: cmdParser,
328
+ ...models ? { models } : {}
329
+ };
330
+ })() : void 0;
331
+ assert(
332
+ explicitVia !== "command" || command !== void 0,
333
+ `CLI discovery via:"command" requires a discovery.command block for provider "${providerId}".`
334
+ );
335
+ const fallback = descriptor.cli.discovery.fallback;
336
+ if (fallback !== void 0) {
337
+ assert(
338
+ fallback === "static" || fallback === "none",
339
+ `Unsupported CLI discovery fallback "${String(fallback)}" for provider "${providerId}".`
340
+ );
341
+ }
291
342
  return {
292
- via,
293
- ...acp ? { acp } : {}
343
+ ...explicitVia !== void 0 ? { via: explicitVia } : {},
344
+ ...acp ? { acp } : {},
345
+ ...command ? { command } : {},
346
+ ...fallback !== void 0 ? { fallback } : {}
294
347
  };
295
348
  })();
296
349
  return {
@@ -1721,6 +1774,25 @@ function resolveModelContextWindow(input) {
1721
1774
  const fallback = isUsableContextLength(input.defaultContextWindow) ? input.defaultContextWindow : DEFAULT_CONTEXT_WINDOW;
1722
1775
  return { contextWindow: fallback, source: "default" };
1723
1776
  }
1777
+ function fillConfiguredContextLength(route, models) {
1778
+ if (!isUsableContextLength(route.contextWindow)) {
1779
+ return models;
1780
+ }
1781
+ const configured = route.contextWindow;
1782
+ return models.map((entry) => {
1783
+ if (isUsableContextLength(entry.contextLength)) {
1784
+ return entry;
1785
+ }
1786
+ if (route.model !== void 0 && entry.modelId !== route.model) {
1787
+ return entry;
1788
+ }
1789
+ return {
1790
+ ...entry,
1791
+ contextLength: configured,
1792
+ metadata: { ...entry.metadata ?? {}, contextWindowSource: "configured" }
1793
+ };
1794
+ });
1795
+ }
1724
1796
  function modelContextCacheKey(input) {
1725
1797
  if (typeof input === "string") {
1726
1798
  return { key: `::${input}`, model: input };
@@ -2163,6 +2235,7 @@ function normalizeResult(route, output, attempts) {
2163
2235
  attempts,
2164
2236
  ...output.toolCalls ? { toolCalls: output.toolCalls } : {},
2165
2237
  ...output.text !== void 0 ? { text: output.text } : {},
2238
+ ...output.reasoning !== void 0 ? { reasoning: output.reasoning } : {},
2166
2239
  ...output.data !== void 0 ? { data: output.data } : {},
2167
2240
  ...output.usage !== void 0 ? { usage: output.usage } : {}
2168
2241
  };
@@ -4695,18 +4768,19 @@ function canonicalGeminiImageModelId(modelId) {
4695
4768
  }
4696
4769
  function buildModelCatalog(route, availableModels, currentModelId) {
4697
4770
  const requestedModelId = route.model;
4698
- const requestedModelAdvertised = availableModels.some(
4771
+ const filledModels = fillConfiguredContextLength(route, availableModels);
4772
+ const requestedModelAdvertised = filledModels.some(
4699
4773
  (model) => model.modelId === requestedModelId
4700
4774
  );
4701
4775
  const canonicalModelId = route.provider === "gemini" ? canonicalGeminiImageModelId(requestedModelId) : void 0;
4702
- const resolvedModelId = requestedModelAdvertised ? requestedModelId : canonicalModelId && availableModels.some((model) => model.modelId === canonicalModelId) ? canonicalModelId : void 0;
4776
+ const resolvedModelId = requestedModelAdvertised ? requestedModelId : canonicalModelId && filledModels.some((model) => model.modelId === canonicalModelId) ? canonicalModelId : void 0;
4703
4777
  return {
4704
4778
  requestedModelId,
4705
4779
  requestedModelAdvertised,
4706
4780
  ...canonicalModelId ? { canonicalModelId } : {},
4707
4781
  ...resolvedModelId ? { resolvedModelId } : {},
4708
4782
  ...currentModelId ? { currentModelId } : {},
4709
- availableModels
4783
+ availableModels: filledModels
4710
4784
  };
4711
4785
  }
4712
4786
  function parseOpenAiModelCatalog(route, payload) {
@@ -5521,6 +5595,9 @@ function extractText(value) {
5521
5595
  return [part];
5522
5596
  }
5523
5597
  if (part && typeof part === "object") {
5598
+ if (part.thought === true) {
5599
+ return [];
5600
+ }
5524
5601
  const candidate = part.text;
5525
5602
  if (typeof candidate === "string") {
5526
5603
  return [candidate];
@@ -5531,6 +5608,22 @@ function extractText(value) {
5531
5608
  }
5532
5609
  return "";
5533
5610
  }
5611
+ function extractThoughts(value) {
5612
+ if (!Array.isArray(value)) {
5613
+ return void 0;
5614
+ }
5615
+ const thoughts = value.flatMap((part) => {
5616
+ if (part && typeof part === "object" && part.thought === true) {
5617
+ const candidate = part.text;
5618
+ if (typeof candidate === "string") {
5619
+ return [candidate];
5620
+ }
5621
+ }
5622
+ return [];
5623
+ });
5624
+ const joined = thoughts.join("\n").trim();
5625
+ return joined.length > 0 ? joined : void 0;
5626
+ }
5534
5627
  function imageAttachmentsFromPayload(payload, ...sources) {
5535
5628
  return extractImagePayloads(payload, ...sources).map(
5536
5629
  (item) => preparePortableFile(item)
@@ -6073,8 +6166,11 @@ async function runGemini(fetchImpl, context) {
6073
6166
  throw classifyApiError(provider, response, payload);
6074
6167
  }
6075
6168
  const data = payload;
6169
+ const geminiThoughts = extractThoughts(data.candidates?.[0]?.content?.parts);
6076
6170
  return {
6077
6171
  text: extractText(data.candidates?.[0]?.content?.parts),
6172
+ // The model's `{ thought: true }` parts, separated from the answer (consumers route this to a thinking UI).
6173
+ ...geminiThoughts ? { reasoning: geminiThoughts } : {},
6078
6174
  data,
6079
6175
  ...geminiToolCallsFromPayload(data).length > 0 ? { toolCalls: geminiToolCallsFromPayload(data) } : {},
6080
6176
  ...(() => {
@@ -7530,6 +7626,10 @@ var AcpConnection = class {
7530
7626
  `ACP route "${context.route.id}" did not return an ACP model catalog in session/new.`
7531
7627
  );
7532
7628
  }
7629
+ catalog.availableModels = fillConfiguredContextLength(
7630
+ context.route,
7631
+ catalog.availableModels
7632
+ );
7533
7633
  return catalog;
7534
7634
  } finally {
7535
7635
  this.bumpIdleTimer();
@@ -8606,14 +8706,26 @@ function normalizeCliDiscoveryAcpSource(route, discovery) {
8606
8706
  };
8607
8707
  }
8608
8708
  function resolveCliDiscoverySource(route) {
8609
- const via = route.transport.cli?.discovery?.via ?? (defaultCliDiscoveryTransportIdForRoute(route) ? "acp" : "none");
8610
- if (via === "none") {
8611
- return { via: "none" };
8709
+ const discovery = route.transport.cli?.discovery;
8710
+ const hasModels = (route.advertisedModels?.length ?? 0) > 0;
8711
+ const hasAcpDefault = Boolean(defaultCliDiscoveryTransportIdForRoute(route));
8712
+ const via = discovery?.via ?? (discovery?.command ? "command" : hasAcpDefault ? "acp" : hasModels ? "static" : "none");
8713
+ switch (via) {
8714
+ case "none":
8715
+ return { via: "none" };
8716
+ case "static":
8717
+ return { via: "static" };
8718
+ case "command": {
8719
+ const command = discovery?.command;
8720
+ if (!command) {
8721
+ return { via: "none" };
8722
+ }
8723
+ const fallback = discovery?.fallback ?? (hasModels ? "static" : "none");
8724
+ return { via: "command", command, fallback };
8725
+ }
8726
+ default:
8727
+ return normalizeCliDiscoveryAcpSource(route, discovery?.acp);
8612
8728
  }
8613
- return normalizeCliDiscoveryAcpSource(
8614
- route,
8615
- route.transport.cli?.discovery?.acp
8616
- );
8617
8729
  }
8618
8730
  function createCliDiscoveryAcpRoute(route) {
8619
8731
  const discovery = resolveCliDiscoverySource(route);
@@ -8722,6 +8834,42 @@ async function buildCliInvocation(context, options) {
8722
8834
  parameterKeys
8723
8835
  };
8724
8836
  }
8837
+ function buildCliDiscoveryInvocation(route, command, options) {
8838
+ const commandLine = command.command?.trim() ? command.command : resolveCliCommand(route, options);
8839
+ const resolved = splitCommandLine2(commandLine);
8840
+ const parameterKeys = [];
8841
+ const args = [
8842
+ ...resolved.args,
8843
+ ...command.argsTemplate.map((part) => {
8844
+ if (part === "{model}") {
8845
+ parameterKeys.push("model");
8846
+ return route.model;
8847
+ }
8848
+ if (part.startsWith("--")) {
8849
+ parameterKeys.push(part);
8850
+ }
8851
+ return part;
8852
+ })
8853
+ ];
8854
+ return {
8855
+ command: resolved.command,
8856
+ args,
8857
+ cwd: path2.resolve(options?.cwd ?? process.cwd()),
8858
+ env: buildCliEnvironment(options),
8859
+ parameterKeys
8860
+ };
8861
+ }
8862
+ function buildStaticCliCatalog(route) {
8863
+ const models = route.advertisedModels.map((id) => ({
8864
+ modelId: id,
8865
+ name: id
8866
+ }));
8867
+ return buildModelCatalog(
8868
+ route,
8869
+ models,
8870
+ currentModelIdForRoute(route, route.advertisedModels)
8871
+ );
8872
+ }
8725
8873
  function statsToUsage(stats) {
8726
8874
  if (!stats || typeof stats !== "object") {
8727
8875
  return void 0;
@@ -8759,6 +8907,9 @@ function getValueByPath(value, dotPath) {
8759
8907
  }
8760
8908
  return current;
8761
8909
  }
8910
+ function splitJsonlLines(stdout) {
8911
+ return stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
8912
+ }
8762
8913
  function normalizeErrorMessage(value) {
8763
8914
  if (typeof value === "string" && value.trim()) {
8764
8915
  return value.trim();
@@ -8806,7 +8957,7 @@ function parseGenericJsonCli(stdout, parser) {
8806
8957
  };
8807
8958
  }
8808
8959
  function parseGenericJsonlCli(stdout, parser) {
8809
- const entries = stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
8960
+ const entries = splitJsonlLines(stdout);
8810
8961
  const errorValue = parser.error ? findJsonlSelection(entries, parser.error) : void 0;
8811
8962
  const errorMessage = normalizeErrorMessage(errorValue);
8812
8963
  if (errorMessage) {
@@ -8827,6 +8978,70 @@ function parseGenericJsonlCli(stdout, parser) {
8827
8978
  data: entries
8828
8979
  };
8829
8980
  }
8981
+ var ANSI_ESCAPE_PATTERN = /\[[0-?]*[ -/]*[@-~]/g;
8982
+ function parseTextCli(stdout, parser) {
8983
+ let text = stdout;
8984
+ if (parser.stripAnsi) {
8985
+ text = text.replace(ANSI_ESCAPE_PATTERN, "");
8986
+ }
8987
+ if (parser.trim !== false) {
8988
+ text = text.trim();
8989
+ }
8990
+ if (!text) {
8991
+ throw new AiConnectError(
8992
+ "temporary_unavailable",
8993
+ "CLI text parser produced no output."
8994
+ );
8995
+ }
8996
+ return { text, data: stdout };
8997
+ }
8998
+ function modelInfoFromRecord(record, selector) {
8999
+ const rawId = getValueByPath(record, selector.idPath);
9000
+ const modelId = typeof rawId === "string" ? rawId.trim() : "";
9001
+ if (!modelId) {
9002
+ return void 0;
9003
+ }
9004
+ const rawName = selector.namePath ? getValueByPath(record, selector.namePath) : void 0;
9005
+ const name = typeof rawName === "string" && rawName.trim().length > 0 ? rawName : modelId;
9006
+ const rawDescription = selector.descriptionPath ? getValueByPath(record, selector.descriptionPath) : void 0;
9007
+ const description = typeof rawDescription === "string" && rawDescription.trim().length > 0 ? rawDescription : void 0;
9008
+ const rawContext = selector.contextLengthPath ? getValueByPath(record, selector.contextLengthPath) : void 0;
9009
+ const contextLength = typeof rawContext === "number" && Number.isFinite(rawContext) && rawContext > 0 ? Math.floor(rawContext) : void 0;
9010
+ return {
9011
+ modelId,
9012
+ name,
9013
+ ...description ? { description } : {},
9014
+ ...contextLength !== void 0 ? { contextLength } : {}
9015
+ };
9016
+ }
9017
+ function parseCliModelList(stdout, parser, selector) {
9018
+ if (parser.kind === "text") {
9019
+ let text = stdout;
9020
+ if (parser.stripAnsi) {
9021
+ text = text.replace(ANSI_ESCAPE_PATTERN, "");
9022
+ }
9023
+ return text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => ({ modelId: line, name: line }));
9024
+ }
9025
+ if (!selector) {
9026
+ throw new AiConnectError(
9027
+ "validation_error",
9028
+ `CLI ${parser.kind} discovery parser requires a models selector with idPath.`
9029
+ );
9030
+ }
9031
+ const records = parser.kind === "jsonl" ? splitJsonlLines(stdout) : (() => {
9032
+ const payload = JSON.parse(stdout);
9033
+ const arr = selector.path ? getValueByPath(payload, selector.path) : payload;
9034
+ return Array.isArray(arr) ? arr : [];
9035
+ })();
9036
+ const models = [];
9037
+ for (const record of records) {
9038
+ const info = modelInfoFromRecord(record, selector);
9039
+ if (info) {
9040
+ models.push(info);
9041
+ }
9042
+ }
9043
+ return models;
9044
+ }
8830
9045
  function parseGeminiCli(stdout) {
8831
9046
  const payload = JSON.parse(stdout);
8832
9047
  if (typeof payload.error === "string") {
@@ -8898,8 +9113,7 @@ function parseClaudeCli(stdout) {
8898
9113
  };
8899
9114
  }
8900
9115
  function parseCodexCli(stdout, outputFileContent) {
8901
- const lines = stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
8902
- const events = lines.map((line) => JSON.parse(line));
9116
+ const events = splitJsonlLines(stdout);
8903
9117
  let text = outputFileContent?.trim() || void 0;
8904
9118
  let usage;
8905
9119
  for (const event of events) {
@@ -8957,7 +9171,14 @@ function parseCliResult(route, result, outputFileContent) {
8957
9171
  `CLI route "${route.id}" declared a parser override but normalization did not preserve it.`
8958
9172
  );
8959
9173
  }
8960
- return parser.kind === "json" ? parseGenericJsonCli(stdout, parser) : parseGenericJsonlCli(stdout, parser);
9174
+ switch (parser.kind) {
9175
+ case "text":
9176
+ return parseTextCli(result.stdout, parser);
9177
+ case "json":
9178
+ return parseGenericJsonCli(stdout, parser);
9179
+ default:
9180
+ return parseGenericJsonlCli(stdout, parser);
9181
+ }
8961
9182
  }
8962
9183
  switch (cliOptions.preset) {
8963
9184
  case "gemini":
@@ -9060,6 +9281,88 @@ async function cleanupCliInvocation(invocation) {
9060
9281
  }
9061
9282
  function createCliTransportManager(options) {
9062
9283
  return {
9284
+ async discoverModels(context) {
9285
+ const source = resolveCliDiscoverySource(context.route);
9286
+ if (source.via === "none") {
9287
+ throw new AiConnectError(
9288
+ "not_supported",
9289
+ `CLI transport "${context.route.transport.id}" does not support model discovery (no list command, no ACP sidecar, and no configured models[]).`
9290
+ );
9291
+ }
9292
+ if (source.via === "acp") {
9293
+ throw new AiConnectError(
9294
+ "not_supported",
9295
+ `CLI route "${context.route.id}" resolves discovery via acp; dispatch to the acp discovery route instead.`
9296
+ );
9297
+ }
9298
+ if (source.via === "static") {
9299
+ return buildStaticCliCatalog(context.route);
9300
+ }
9301
+ const phases = [];
9302
+ const invocation = buildCliDiscoveryInvocation(
9303
+ context.route,
9304
+ source.command,
9305
+ options
9306
+ );
9307
+ context.telemetry?.captureTransport({
9308
+ protocol: "cli",
9309
+ endpoint: invocation.command,
9310
+ method: "process",
9311
+ bodyKeys: ["argv"],
9312
+ parameterKeys: invocation.parameterKeys,
9313
+ phases,
9314
+ stream: false
9315
+ });
9316
+ try {
9317
+ let models;
9318
+ try {
9319
+ const execution = await executeCliInvocation(
9320
+ invocation,
9321
+ options?.timeoutMs ?? 6e4,
9322
+ phases,
9323
+ context.abort.signal
9324
+ );
9325
+ if (execution.exitCode !== 0 || !execution.stdout.trim()) {
9326
+ throw new AiConnectError(
9327
+ "temporary_unavailable",
9328
+ execution.stderr.trim() || `CLI discovery command for "${context.route.transport.id}" exited with code ${execution.exitCode ?? "null"}.`
9329
+ );
9330
+ }
9331
+ models = parseCliModelList(
9332
+ execution.stdout,
9333
+ source.command.parser,
9334
+ source.command.models
9335
+ );
9336
+ } catch (error) {
9337
+ if (error instanceof AiConnectError && error.code === "aborted") {
9338
+ throw error;
9339
+ }
9340
+ if (source.fallback === "static") {
9341
+ return buildStaticCliCatalog(context.route);
9342
+ }
9343
+ throw error;
9344
+ }
9345
+ if (models.length === 0) {
9346
+ if (source.fallback === "static") {
9347
+ return buildStaticCliCatalog(context.route);
9348
+ }
9349
+ throw new AiConnectError(
9350
+ "temporary_unavailable",
9351
+ `CLI discovery command for "${context.route.transport.id}" returned no models.`
9352
+ );
9353
+ }
9354
+ return buildModelCatalog(
9355
+ context.route,
9356
+ models,
9357
+ currentModelIdForRoute(
9358
+ context.route,
9359
+ models.map((model) => model.modelId)
9360
+ )
9361
+ );
9362
+ } finally {
9363
+ await cleanupCliInvocation(invocation);
9364
+ }
9365
+ },
9063
9366
  async runPrompt(context) {
9064
9367
  const invocation = await buildCliInvocation(context, options);
9065
9368
  const phases = [];
@@ -9594,17 +9897,21 @@ function createLocalRouteHandlers(options = {}) {
9594
9897
  return cliTransport.runPrompt(context);
9595
9898
  },
9596
9899
  async discoverModels(context) {
9597
- const discoveryRoute = createCliDiscoveryAcpRoute(context.route);
9598
- if (!discoveryRoute) {
9599
- throw new AiConnectError(
9600
- "not_supported",
9601
- `CLI route "${context.route.id}" does not define a model discovery backend.`
9602
- );
9900
+ const source = resolveCliDiscoverySource(context.route);
9901
+ if (source.via === "acp") {
9902
+ const discoveryRoute = createCliDiscoveryAcpRoute(context.route);
9903
+ if (!discoveryRoute) {
9904
+ throw new AiConnectError(
9905
+ "not_supported",
9906
+ `CLI route "${context.route.id}" does not define a model discovery backend.`
9907
+ );
9908
+ }
9909
+ return acpTransport.discoverModels({
9910
+ ...context,
9911
+ route: discoveryRoute
9912
+ });
9603
9913
  }
9604
- return acpTransport.discoverModels({
9605
- ...context,
9606
- route: discoveryRoute
9607
- });
9914
+ return cliTransport.discoverModels(context);
9608
9915
  },
9609
9916
  async verify({ route, runtime }) {
9610
9917
  try {