@dexto/server 1.5.6 → 1.5.7

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.
@@ -0,0 +1,52 @@
1
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
+ import {
3
+ isDextoAuthEnabled,
4
+ isDextoAuthenticated,
5
+ canUseDextoProvider
6
+ } from "@dexto/agent-management";
7
+ function createDextoAuthRouter(_getAgent) {
8
+ const app = new OpenAPIHono();
9
+ const statusRoute = createRoute({
10
+ method: "get",
11
+ path: "/dexto-auth/status",
12
+ summary: "Dexto Auth Status",
13
+ description: "Returns dexto authentication status. Used by Web UI to check if user can use dexto features.",
14
+ tags: ["auth"],
15
+ responses: {
16
+ 200: {
17
+ description: "Dexto auth status",
18
+ content: {
19
+ "application/json": {
20
+ schema: z.object({
21
+ enabled: z.boolean().describe("Whether dexto auth feature is enabled"),
22
+ authenticated: z.boolean().describe("Whether user is authenticated with dexto"),
23
+ canUse: z.boolean().describe(
24
+ "Whether user can use dexto (authenticated AND has API key)"
25
+ )
26
+ })
27
+ }
28
+ }
29
+ }
30
+ }
31
+ });
32
+ return app.openapi(statusRoute, async (c) => {
33
+ const enabled = isDextoAuthEnabled();
34
+ if (!enabled) {
35
+ return c.json({
36
+ enabled: false,
37
+ authenticated: false,
38
+ canUse: false
39
+ });
40
+ }
41
+ const authenticated = await isDextoAuthenticated();
42
+ const canUse = await canUseDextoProvider();
43
+ return c.json({
44
+ enabled,
45
+ authenticated,
46
+ canUse
47
+ });
48
+ });
49
+ }
50
+ export {
51
+ createDextoAuthRouter
52
+ };
@@ -13,11 +13,11 @@ export declare function createKeyRouter(): OpenAPIHono<import("hono").Env, {
13
13
  $get: {
14
14
  input: {
15
15
  param: {
16
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
16
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
17
17
  };
18
18
  };
19
19
  output: {
20
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
20
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
21
21
  hasKey: boolean;
22
22
  envVar: string;
23
23
  keyValue?: string | undefined;
@@ -31,12 +31,12 @@ export declare function createKeyRouter(): OpenAPIHono<import("hono").Env, {
31
31
  $post: {
32
32
  input: {
33
33
  json: {
34
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
34
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
35
35
  apiKey: string;
36
36
  };
37
37
  };
38
38
  output: {
39
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
39
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
40
40
  ok: true;
41
41
  envVar: string;
42
42
  };
@@ -66,7 +66,14 @@ function createLlmRouter(getAgent) {
66
66
  maxIterations: true
67
67
  }).extend({
68
68
  displayName: import_zod_openapi.z.string().optional().describe("Human-readable model display name")
69
- })
69
+ }),
70
+ routing: import_zod_openapi.z.object({
71
+ viaDexto: import_zod_openapi.z.boolean().describe(
72
+ "Whether requests route through Dexto gateway"
73
+ )
74
+ }).describe(
75
+ "Routing information for the current LLM configuration"
76
+ )
70
77
  }).describe("Response containing current LLM configuration")
71
78
  }
72
79
  }
@@ -213,6 +220,33 @@ function createLlmRouter(getAgent) {
213
220
  }
214
221
  }
215
222
  });
223
+ const capabilitiesRoute = (0, import_zod_openapi.createRoute)({
224
+ method: "get",
225
+ path: "/llm/capabilities",
226
+ summary: "Get Model Capabilities",
227
+ description: "Returns the capabilities (supported file types) for a specific provider/model combination. Handles gateway providers (dexto, openrouter) by resolving to the underlying model capabilities.",
228
+ tags: ["llm"],
229
+ request: {
230
+ query: import_zod_openapi.z.object({
231
+ provider: import_zod_openapi.z.enum(import_core2.LLM_PROVIDERS).describe("LLM provider name"),
232
+ model: import_zod_openapi.z.string().min(1).describe("Model name (supports both native and OpenRouter format)")
233
+ })
234
+ },
235
+ responses: {
236
+ 200: {
237
+ description: "Model capabilities",
238
+ content: {
239
+ "application/json": {
240
+ schema: import_zod_openapi.z.object({
241
+ provider: import_zod_openapi.z.enum(import_core2.LLM_PROVIDERS).describe("Provider name"),
242
+ model: import_zod_openapi.z.string().describe("Model name as provided"),
243
+ supportedFileTypes: import_zod_openapi.z.array(import_zod_openapi.z.enum(import_core2.SUPPORTED_FILE_TYPES)).describe("File types supported by this model")
244
+ })
245
+ }
246
+ }
247
+ }
248
+ }
249
+ });
216
250
  return app.openapi(currentRoute, async (ctx) => {
217
251
  const agent = await getAgent(ctx);
218
252
  const { sessionId } = ctx.req.valid("query");
@@ -233,26 +267,34 @@ function createLlmRouter(getAgent) {
233
267
  } catch {
234
268
  }
235
269
  const { apiKey, ...configWithoutKey } = currentConfig;
270
+ const viaDexto = (0, import_agent_management.isDextoAuthEnabled)() && currentConfig.provider === "dexto";
236
271
  return ctx.json({
237
272
  config: {
238
273
  ...configWithoutKey,
239
274
  hasApiKey: !!apiKey,
240
275
  ...displayName && { displayName }
276
+ },
277
+ routing: {
278
+ viaDexto
241
279
  }
242
280
  });
243
281
  }).openapi(catalogRoute, (ctx) => {
244
282
  const queryParams = ctx.req.valid("query");
245
283
  const providers = {};
246
284
  for (const provider of import_core2.LLM_PROVIDERS) {
285
+ if (provider === "dexto" && !(0, import_agent_management.isDextoAuthEnabled)()) {
286
+ continue;
287
+ }
247
288
  const info = import_core2.LLM_REGISTRY[provider];
248
289
  const displayName = provider.charAt(0).toUpperCase() + provider.slice(1);
249
290
  const keyStatus = (0, import_agent_management.getProviderKeyStatus)(provider);
291
+ const models = (0, import_core2.getAllModelsForProvider)(provider);
250
292
  providers[provider] = {
251
293
  name: displayName,
252
294
  hasApiKey: keyStatus.hasApiKey,
253
295
  primaryEnvVar: keyStatus.envVar,
254
296
  supportsBaseURL: (0, import_core2.supportsBaseURL)(provider),
255
- models: info.models,
297
+ models,
256
298
  supportedFileTypes: info.supportedFileTypes
257
299
  };
258
300
  }
@@ -347,6 +389,20 @@ function createLlmRouter(getAgent) {
347
389
  );
348
390
  }
349
391
  return ctx.json({ ok: true, deleted: name }, 200);
392
+ }).openapi(capabilitiesRoute, (ctx) => {
393
+ const { provider, model } = ctx.req.valid("query");
394
+ let supportedFileTypes;
395
+ try {
396
+ supportedFileTypes = (0, import_core2.getSupportedFileTypesForModel)(provider, model);
397
+ } catch {
398
+ const providerInfo = import_core2.LLM_REGISTRY[provider];
399
+ supportedFileTypes = providerInfo?.supportedFileTypes ?? [];
400
+ }
401
+ return ctx.json({
402
+ provider,
403
+ model,
404
+ supportedFileTypes
405
+ });
350
406
  });
351
407
  }
352
408
  // Annotate the CommonJS export names for ESM import in node:
@@ -13,7 +13,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
13
13
  output: {
14
14
  config: {
15
15
  model: string;
16
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
16
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
17
17
  maxIterations?: number | undefined;
18
18
  baseURL?: string | undefined;
19
19
  maxInputTokens?: number | undefined;
@@ -24,6 +24,9 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
24
24
  hasApiKey?: boolean | undefined;
25
25
  displayName?: string | undefined;
26
26
  };
27
+ routing: {
28
+ viaDexto: boolean;
29
+ };
27
30
  };
28
31
  outputFormat: "json";
29
32
  status: 200;
@@ -197,6 +200,50 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
197
200
  } | undefined;
198
201
  }[];
199
202
  } | undefined;
203
+ minimax?: {
204
+ name: string;
205
+ hasApiKey: boolean;
206
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
207
+ primaryEnvVar: string;
208
+ supportsBaseURL: boolean;
209
+ models: {
210
+ name: string;
211
+ maxInputTokens: number;
212
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
213
+ default?: boolean | undefined;
214
+ displayName?: string | undefined;
215
+ pricing?: {
216
+ inputPerM: number;
217
+ outputPerM: number;
218
+ cacheReadPerM?: number | undefined;
219
+ cacheWritePerM?: number | undefined;
220
+ currency?: "USD" | undefined;
221
+ unit?: "per_million_tokens" | undefined;
222
+ } | undefined;
223
+ }[];
224
+ } | undefined;
225
+ glm?: {
226
+ name: string;
227
+ hasApiKey: boolean;
228
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
229
+ primaryEnvVar: string;
230
+ supportsBaseURL: boolean;
231
+ models: {
232
+ name: string;
233
+ maxInputTokens: number;
234
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
235
+ default?: boolean | undefined;
236
+ displayName?: string | undefined;
237
+ pricing?: {
238
+ inputPerM: number;
239
+ outputPerM: number;
240
+ cacheReadPerM?: number | undefined;
241
+ cacheWritePerM?: number | undefined;
242
+ currency?: "USD" | undefined;
243
+ unit?: "per_million_tokens" | undefined;
244
+ } | undefined;
245
+ }[];
246
+ } | undefined;
200
247
  openrouter?: {
201
248
  name: string;
202
249
  hasApiKey: boolean;
@@ -351,6 +398,28 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
351
398
  } | undefined;
352
399
  }[];
353
400
  } | undefined;
401
+ dexto?: {
402
+ name: string;
403
+ hasApiKey: boolean;
404
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
405
+ primaryEnvVar: string;
406
+ supportsBaseURL: boolean;
407
+ models: {
408
+ name: string;
409
+ maxInputTokens: number;
410
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
411
+ default?: boolean | undefined;
412
+ displayName?: string | undefined;
413
+ pricing?: {
414
+ inputPerM: number;
415
+ outputPerM: number;
416
+ cacheReadPerM?: number | undefined;
417
+ cacheWritePerM?: number | undefined;
418
+ currency?: "USD" | undefined;
419
+ unit?: "per_million_tokens" | undefined;
420
+ } | undefined;
421
+ }[];
422
+ } | undefined;
354
423
  };
355
424
  } | {
356
425
  models: {
@@ -380,15 +449,15 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
380
449
  input: {
381
450
  json: {
382
451
  model?: string | undefined;
383
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
452
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto" | undefined;
384
453
  apiKey?: string | undefined;
454
+ maxInputTokens?: number | undefined;
385
455
  maxIterations?: number | undefined;
386
456
  baseURL?: string | undefined;
387
- maxInputTokens?: number | undefined;
388
457
  maxOutputTokens?: number | undefined;
389
458
  temperature?: number | undefined;
390
459
  allowedMediaTypes?: string[] | undefined;
391
- reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
460
+ reasoningEffort?: "low" | "none" | "minimal" | "medium" | "high" | "xhigh" | undefined;
392
461
  } & {
393
462
  sessionId?: string | undefined;
394
463
  };
@@ -396,7 +465,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
396
465
  output: {
397
466
  config: {
398
467
  model: string;
399
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
468
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
400
469
  maxIterations?: number | undefined;
401
470
  baseURL?: string | undefined;
402
471
  maxInputTokens?: number | undefined;
@@ -419,7 +488,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
419
488
  output: {
420
489
  models: {
421
490
  name: string;
422
- provider: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
491
+ provider: "dexto" | "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
423
492
  apiKey?: string | undefined | undefined;
424
493
  baseURL?: string | undefined | undefined;
425
494
  reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined | undefined;
@@ -439,7 +508,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
439
508
  input: {
440
509
  json: {
441
510
  name: string;
442
- provider?: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
511
+ provider?: "dexto" | "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
443
512
  apiKey?: string | undefined;
444
513
  baseURL?: string | undefined;
445
514
  reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
@@ -452,7 +521,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
452
521
  output: {
453
522
  model: {
454
523
  name: string;
455
- provider: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
524
+ provider: "dexto" | "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
456
525
  apiKey?: string | undefined | undefined;
457
526
  baseURL?: string | undefined | undefined;
458
527
  reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined | undefined;
@@ -495,6 +564,24 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
495
564
  status: 404;
496
565
  };
497
566
  };
567
+ } & {
568
+ "/llm/capabilities": {
569
+ $get: {
570
+ input: {
571
+ query: {
572
+ model: string;
573
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
574
+ };
575
+ };
576
+ output: {
577
+ model: string;
578
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto";
579
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
580
+ };
581
+ outputFormat: "json";
582
+ status: 200;
583
+ };
584
+ };
498
585
  }, "/">;
499
586
  export {};
500
587
  //# sourceMappingURL=llm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/llm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAkB9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAOpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAgErE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAoXnD"}
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/llm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsB9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAOpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAgErE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4cnD"}
@@ -5,6 +5,8 @@ import {
5
5
  LLM_PROVIDERS,
6
6
  SUPPORTED_FILE_TYPES,
7
7
  supportsBaseURL,
8
+ getAllModelsForProvider,
9
+ getSupportedFileTypesForModel,
8
10
  LLMUpdatesSchema
9
11
  } from "@dexto/core";
10
12
  import {
@@ -12,7 +14,8 @@ import {
12
14
  loadCustomModels,
13
15
  saveCustomModel,
14
16
  deleteCustomModel,
15
- CustomModelSchema
17
+ CustomModelSchema,
18
+ isDextoAuthEnabled
16
19
  } from "@dexto/agent-management";
17
20
  import {
18
21
  ProviderCatalogSchema,
@@ -59,7 +62,14 @@ function createLlmRouter(getAgent) {
59
62
  maxIterations: true
60
63
  }).extend({
61
64
  displayName: z.string().optional().describe("Human-readable model display name")
62
- })
65
+ }),
66
+ routing: z.object({
67
+ viaDexto: z.boolean().describe(
68
+ "Whether requests route through Dexto gateway"
69
+ )
70
+ }).describe(
71
+ "Routing information for the current LLM configuration"
72
+ )
63
73
  }).describe("Response containing current LLM configuration")
64
74
  }
65
75
  }
@@ -206,6 +216,33 @@ function createLlmRouter(getAgent) {
206
216
  }
207
217
  }
208
218
  });
219
+ const capabilitiesRoute = createRoute({
220
+ method: "get",
221
+ path: "/llm/capabilities",
222
+ summary: "Get Model Capabilities",
223
+ description: "Returns the capabilities (supported file types) for a specific provider/model combination. Handles gateway providers (dexto, openrouter) by resolving to the underlying model capabilities.",
224
+ tags: ["llm"],
225
+ request: {
226
+ query: z.object({
227
+ provider: z.enum(LLM_PROVIDERS).describe("LLM provider name"),
228
+ model: z.string().min(1).describe("Model name (supports both native and OpenRouter format)")
229
+ })
230
+ },
231
+ responses: {
232
+ 200: {
233
+ description: "Model capabilities",
234
+ content: {
235
+ "application/json": {
236
+ schema: z.object({
237
+ provider: z.enum(LLM_PROVIDERS).describe("Provider name"),
238
+ model: z.string().describe("Model name as provided"),
239
+ supportedFileTypes: z.array(z.enum(SUPPORTED_FILE_TYPES)).describe("File types supported by this model")
240
+ })
241
+ }
242
+ }
243
+ }
244
+ }
245
+ });
209
246
  return app.openapi(currentRoute, async (ctx) => {
210
247
  const agent = await getAgent(ctx);
211
248
  const { sessionId } = ctx.req.valid("query");
@@ -226,26 +263,34 @@ function createLlmRouter(getAgent) {
226
263
  } catch {
227
264
  }
228
265
  const { apiKey, ...configWithoutKey } = currentConfig;
266
+ const viaDexto = isDextoAuthEnabled() && currentConfig.provider === "dexto";
229
267
  return ctx.json({
230
268
  config: {
231
269
  ...configWithoutKey,
232
270
  hasApiKey: !!apiKey,
233
271
  ...displayName && { displayName }
272
+ },
273
+ routing: {
274
+ viaDexto
234
275
  }
235
276
  });
236
277
  }).openapi(catalogRoute, (ctx) => {
237
278
  const queryParams = ctx.req.valid("query");
238
279
  const providers = {};
239
280
  for (const provider of LLM_PROVIDERS) {
281
+ if (provider === "dexto" && !isDextoAuthEnabled()) {
282
+ continue;
283
+ }
240
284
  const info = LLM_REGISTRY[provider];
241
285
  const displayName = provider.charAt(0).toUpperCase() + provider.slice(1);
242
286
  const keyStatus = getProviderKeyStatus(provider);
287
+ const models = getAllModelsForProvider(provider);
243
288
  providers[provider] = {
244
289
  name: displayName,
245
290
  hasApiKey: keyStatus.hasApiKey,
246
291
  primaryEnvVar: keyStatus.envVar,
247
292
  supportsBaseURL: supportsBaseURL(provider),
248
- models: info.models,
293
+ models,
249
294
  supportedFileTypes: info.supportedFileTypes
250
295
  };
251
296
  }
@@ -340,6 +385,20 @@ function createLlmRouter(getAgent) {
340
385
  );
341
386
  }
342
387
  return ctx.json({ ok: true, deleted: name }, 200);
388
+ }).openapi(capabilitiesRoute, (ctx) => {
389
+ const { provider, model } = ctx.req.valid("query");
390
+ let supportedFileTypes;
391
+ try {
392
+ supportedFileTypes = getSupportedFileTypesForModel(provider, model);
393
+ } catch {
394
+ const providerInfo = LLM_REGISTRY[provider];
395
+ supportedFileTypes = providerInfo?.supportedFileTypes ?? [];
396
+ }
397
+ return ctx.json({
398
+ provider,
399
+ model,
400
+ supportedFileTypes
401
+ });
343
402
  });
344
403
  }
345
404
  export {
@@ -46,7 +46,7 @@ export declare function createMcpRouter(getAgent: GetAgentFn): OpenAPIHono<impor
46
46
  input: {};
47
47
  output: {
48
48
  servers: {
49
- status: "error" | "connected" | "disconnected";
49
+ status: "error" | "connected" | "disconnected" | "auth-required";
50
50
  id: string;
51
51
  name: string;
52
52
  }[];
@@ -106,7 +106,7 @@ export declare function createMessagesRouter(getAgent: GetAgentFn, approvalCoord
106
106
  totalTokens?: number | undefined;
107
107
  } | undefined;
108
108
  model?: string | undefined;
109
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
109
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto" | undefined;
110
110
  };
111
111
  outputFormat: "json";
112
112
  status: 200;
@@ -56,7 +56,7 @@ export declare function createSearchRouter(getAgent: GetAgentFn): OpenAPIHono<im
56
56
  totalTokens?: number | undefined;
57
57
  } | undefined;
58
58
  model?: string | undefined;
59
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
59
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto" | undefined;
60
60
  toolCalls?: {
61
61
  function: {
62
62
  name: string;
@@ -138,7 +138,7 @@ export declare function createSearchRouter(getAgent: GetAgentFn): OpenAPIHono<im
138
138
  totalTokens?: number | undefined;
139
139
  } | undefined;
140
140
  model?: string | undefined;
141
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
141
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto" | undefined;
142
142
  toolCalls?: {
143
143
  function: {
144
144
  name: string;
@@ -108,7 +108,7 @@ export declare function createSessionsRouter(getAgent: GetAgentFn): OpenAPIHono<
108
108
  totalTokens?: number | undefined;
109
109
  } | undefined;
110
110
  model?: string | undefined;
111
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
111
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto" | undefined;
112
112
  toolCalls?: {
113
113
  function: {
114
114
  name: string;