@dexto/server 1.5.6 → 1.5.8

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-nova";
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-nova";
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-nova";
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-nova";
40
40
  ok: true;
41
41
  envVar: string;
42
42
  };
@@ -28,11 +28,17 @@ var import_agent_management = require("@dexto/agent-management");
28
28
  var import_responses = require("../schemas/responses.js");
29
29
  const CurrentQuerySchema = import_zod_openapi.z.object({
30
30
  sessionId: import_zod_openapi.z.string().optional().describe("Session identifier to retrieve session-specific LLM configuration")
31
- }).describe("Query parameters for getting current LLM configuration");
31
+ }).strict().describe("Query parameters for getting current LLM configuration");
32
32
  const CatalogQuerySchema = import_zod_openapi.z.object({
33
+ scope: import_zod_openapi.z.enum(["curated", "all"]).default("all").describe(
34
+ "Catalog scope: 'curated' returns a small, UI-friendly set of models; 'all' returns the full registry (can be large)"
35
+ ),
33
36
  provider: import_zod_openapi.z.union([import_zod_openapi.z.string(), import_zod_openapi.z.array(import_zod_openapi.z.string())]).optional().transform(
34
37
  (value) => Array.isArray(value) ? value : value ? value.split(",") : void 0
35
38
  ).describe("Comma-separated list of LLM providers to filter by"),
39
+ includeModels: import_zod_openapi.z.union([import_zod_openapi.z.literal("true"), import_zod_openapi.z.literal("false"), import_zod_openapi.z.literal("1"), import_zod_openapi.z.literal("0")]).optional().transform(
40
+ (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
41
+ ).describe("Include models list in the response (true or false)"),
36
42
  hasKey: import_zod_openapi.z.union([import_zod_openapi.z.literal("true"), import_zod_openapi.z.literal("false"), import_zod_openapi.z.literal("1"), import_zod_openapi.z.literal("0")]).optional().transform(
37
43
  (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
38
44
  ).describe("Filter by API key presence (true or false)"),
@@ -41,7 +47,7 @@ const CatalogQuerySchema = import_zod_openapi.z.object({
41
47
  (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
42
48
  ).describe("Include only default models (true or false)"),
43
49
  mode: import_zod_openapi.z.enum(["grouped", "flat"]).default("grouped").describe("Response format mode (grouped by provider or flat list)")
44
- }).describe("Query parameters for filtering and formatting the LLM catalog");
50
+ }).strict().describe("Query parameters for filtering and formatting the LLM catalog");
45
51
  const SwitchLLMBodySchema = import_core2.LLMUpdatesSchema.and(
46
52
  import_zod_openapi.z.object({
47
53
  sessionId: import_zod_openapi.z.string().optional().describe("Session identifier for session-specific LLM configuration")
@@ -66,7 +72,14 @@ function createLlmRouter(getAgent) {
66
72
  maxIterations: true
67
73
  }).extend({
68
74
  displayName: import_zod_openapi.z.string().optional().describe("Human-readable model display name")
69
- })
75
+ }),
76
+ routing: import_zod_openapi.z.object({
77
+ viaDexto: import_zod_openapi.z.boolean().describe(
78
+ "Whether requests route through Dexto gateway"
79
+ )
80
+ }).describe(
81
+ "Routing information for the current LLM configuration"
82
+ )
70
83
  }).describe("Response containing current LLM configuration")
71
84
  }
72
85
  }
@@ -213,6 +226,33 @@ function createLlmRouter(getAgent) {
213
226
  }
214
227
  }
215
228
  });
229
+ const capabilitiesRoute = (0, import_zod_openapi.createRoute)({
230
+ method: "get",
231
+ path: "/llm/capabilities",
232
+ summary: "Get Model Capabilities",
233
+ description: "Returns the capabilities (supported file types) for a specific provider/model combination. Handles gateway providers (dexto-nova, openrouter) by resolving to the underlying model capabilities.",
234
+ tags: ["llm"],
235
+ request: {
236
+ query: import_zod_openapi.z.object({
237
+ provider: import_zod_openapi.z.enum(import_core2.LLM_PROVIDERS).describe("LLM provider name"),
238
+ model: import_zod_openapi.z.string().min(1).describe("Model name (supports both native and OpenRouter format)")
239
+ })
240
+ },
241
+ responses: {
242
+ 200: {
243
+ description: "Model capabilities",
244
+ content: {
245
+ "application/json": {
246
+ schema: import_zod_openapi.z.object({
247
+ provider: import_zod_openapi.z.enum(import_core2.LLM_PROVIDERS).describe("Provider name"),
248
+ model: import_zod_openapi.z.string().describe("Model name as provided"),
249
+ supportedFileTypes: import_zod_openapi.z.array(import_zod_openapi.z.enum(import_core2.SUPPORTED_FILE_TYPES)).describe("File types supported by this model")
250
+ })
251
+ }
252
+ }
253
+ }
254
+ }
255
+ });
216
256
  return app.openapi(currentRoute, async (ctx) => {
217
257
  const agent = await getAgent(ctx);
218
258
  const { sessionId } = ctx.req.valid("query");
@@ -233,26 +273,42 @@ function createLlmRouter(getAgent) {
233
273
  } catch {
234
274
  }
235
275
  const { apiKey, ...configWithoutKey } = currentConfig;
276
+ const viaDexto = (0, import_agent_management.isDextoAuthEnabled)() && currentConfig.provider === "dexto-nova";
236
277
  return ctx.json({
237
278
  config: {
238
279
  ...configWithoutKey,
239
280
  hasApiKey: !!apiKey,
240
281
  ...displayName && { displayName }
282
+ },
283
+ routing: {
284
+ viaDexto
241
285
  }
242
286
  });
243
287
  }).openapi(catalogRoute, (ctx) => {
244
288
  const queryParams = ctx.req.valid("query");
289
+ const includeModels = queryParams.includeModels ?? true;
290
+ const scope = queryParams.scope ?? "all";
245
291
  const providers = {};
246
292
  for (const provider of import_core2.LLM_PROVIDERS) {
293
+ if (provider === "dexto-nova" && !(0, import_agent_management.isDextoAuthEnabled)()) {
294
+ continue;
295
+ }
247
296
  const info = import_core2.LLM_REGISTRY[provider];
248
- const displayName = provider.charAt(0).toUpperCase() + provider.slice(1);
297
+ const displayName = provider === "dexto-nova" ? "Dexto Nova" : provider.charAt(0).toUpperCase() + provider.slice(1);
249
298
  const keyStatus = (0, import_agent_management.getProviderKeyStatus)(provider);
299
+ const models = (() => {
300
+ if (!includeModels) return [];
301
+ if (scope === "all") {
302
+ return (0, import_core2.getAllModelsForProvider)(provider);
303
+ }
304
+ return (0, import_core2.getCuratedModelsForProvider)(provider);
305
+ })();
250
306
  providers[provider] = {
251
307
  name: displayName,
252
308
  hasApiKey: keyStatus.hasApiKey,
253
309
  primaryEnvVar: keyStatus.envVar,
254
310
  supportsBaseURL: (0, import_core2.supportsBaseURL)(provider),
255
- models: info.models,
311
+ models,
256
312
  supportedFileTypes: info.supportedFileTypes
257
313
  };
258
314
  }
@@ -347,6 +403,20 @@ function createLlmRouter(getAgent) {
347
403
  );
348
404
  }
349
405
  return ctx.json({ ok: true, deleted: name }, 200);
406
+ }).openapi(capabilitiesRoute, (ctx) => {
407
+ const { provider, model } = ctx.req.valid("query");
408
+ let supportedFileTypes;
409
+ try {
410
+ supportedFileTypes = (0, import_core2.getSupportedFileTypesForModel)(provider, model);
411
+ } catch {
412
+ const providerInfo = import_core2.LLM_REGISTRY[provider];
413
+ supportedFileTypes = providerInfo?.supportedFileTypes ?? [];
414
+ }
415
+ return ctx.json({
416
+ provider,
417
+ model,
418
+ supportedFileTypes
419
+ });
350
420
  });
351
421
  }
352
422
  // 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-nova";
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;
@@ -35,6 +38,8 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
35
38
  input: {
36
39
  query: {
37
40
  provider?: string | string[] | undefined;
41
+ scope?: "curated" | "all" | undefined;
42
+ includeModels?: "0" | "1" | "true" | "false" | undefined;
38
43
  hasKey?: "0" | "1" | "true" | "false" | undefined;
39
44
  fileType?: "image" | "audio" | "pdf" | undefined;
40
45
  defaultOnly?: "0" | "1" | "true" | "false" | undefined;
@@ -197,6 +202,50 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
197
202
  } | undefined;
198
203
  }[];
199
204
  } | undefined;
205
+ minimax?: {
206
+ name: string;
207
+ hasApiKey: boolean;
208
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
209
+ primaryEnvVar: string;
210
+ supportsBaseURL: boolean;
211
+ models: {
212
+ name: string;
213
+ maxInputTokens: number;
214
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
215
+ default?: boolean | undefined;
216
+ displayName?: string | undefined;
217
+ pricing?: {
218
+ inputPerM: number;
219
+ outputPerM: number;
220
+ cacheReadPerM?: number | undefined;
221
+ cacheWritePerM?: number | undefined;
222
+ currency?: "USD" | undefined;
223
+ unit?: "per_million_tokens" | undefined;
224
+ } | undefined;
225
+ }[];
226
+ } | undefined;
227
+ glm?: {
228
+ name: string;
229
+ hasApiKey: boolean;
230
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
231
+ primaryEnvVar: string;
232
+ supportsBaseURL: boolean;
233
+ models: {
234
+ name: string;
235
+ maxInputTokens: number;
236
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
237
+ default?: boolean | undefined;
238
+ displayName?: string | undefined;
239
+ pricing?: {
240
+ inputPerM: number;
241
+ outputPerM: number;
242
+ cacheReadPerM?: number | undefined;
243
+ cacheWritePerM?: number | undefined;
244
+ currency?: "USD" | undefined;
245
+ unit?: "per_million_tokens" | undefined;
246
+ } | undefined;
247
+ }[];
248
+ } | undefined;
200
249
  openrouter?: {
201
250
  name: string;
202
251
  hasApiKey: boolean;
@@ -351,6 +400,28 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
351
400
  } | undefined;
352
401
  }[];
353
402
  } | undefined;
403
+ "dexto-nova"?: {
404
+ name: string;
405
+ hasApiKey: boolean;
406
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
407
+ primaryEnvVar: string;
408
+ supportsBaseURL: boolean;
409
+ models: {
410
+ name: string;
411
+ maxInputTokens: number;
412
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
413
+ default?: boolean | undefined;
414
+ displayName?: string | undefined;
415
+ pricing?: {
416
+ inputPerM: number;
417
+ outputPerM: number;
418
+ cacheReadPerM?: number | undefined;
419
+ cacheWritePerM?: number | undefined;
420
+ currency?: "USD" | undefined;
421
+ unit?: "per_million_tokens" | undefined;
422
+ } | undefined;
423
+ }[];
424
+ } | undefined;
354
425
  };
355
426
  } | {
356
427
  models: {
@@ -380,15 +451,15 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
380
451
  input: {
381
452
  json: {
382
453
  model?: string | undefined;
383
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
454
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova" | undefined;
384
455
  apiKey?: string | undefined;
456
+ maxInputTokens?: number | undefined;
385
457
  maxIterations?: number | undefined;
386
458
  baseURL?: string | undefined;
387
- maxInputTokens?: number | undefined;
388
459
  maxOutputTokens?: number | undefined;
389
460
  temperature?: number | undefined;
390
461
  allowedMediaTypes?: string[] | undefined;
391
- reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
462
+ reasoningEffort?: "low" | "none" | "minimal" | "medium" | "high" | "xhigh" | undefined;
392
463
  } & {
393
464
  sessionId?: string | undefined;
394
465
  };
@@ -396,7 +467,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
396
467
  output: {
397
468
  config: {
398
469
  model: string;
399
- provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
470
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova";
400
471
  maxIterations?: number | undefined;
401
472
  baseURL?: string | undefined;
402
473
  maxInputTokens?: number | undefined;
@@ -419,7 +490,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
419
490
  output: {
420
491
  models: {
421
492
  name: string;
422
- provider: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
493
+ provider: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova";
423
494
  apiKey?: string | undefined | undefined;
424
495
  baseURL?: string | undefined | undefined;
425
496
  reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined | undefined;
@@ -439,7 +510,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
439
510
  input: {
440
511
  json: {
441
512
  name: string;
442
- provider?: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
513
+ provider?: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova" | undefined;
443
514
  apiKey?: string | undefined;
444
515
  baseURL?: string | undefined;
445
516
  reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined;
@@ -452,7 +523,7 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
452
523
  output: {
453
524
  model: {
454
525
  name: string;
455
- provider: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama";
526
+ provider: "openai-compatible" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova";
456
527
  apiKey?: string | undefined | undefined;
457
528
  baseURL?: string | undefined | undefined;
458
529
  reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined | undefined;
@@ -495,6 +566,24 @@ export declare function createLlmRouter(getAgent: GetAgentFn): OpenAPIHono<impor
495
566
  status: 404;
496
567
  };
497
568
  };
569
+ } & {
570
+ "/llm/capabilities": {
571
+ $get: {
572
+ input: {
573
+ query: {
574
+ model: string;
575
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova";
576
+ };
577
+ };
578
+ output: {
579
+ model: string;
580
+ provider: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova";
581
+ supportedFileTypes: ("image" | "audio" | "pdf")[];
582
+ };
583
+ outputFormat: "json";
584
+ status: 200;
585
+ };
586
+ };
498
587
  }, "/">;
499
588
  export {};
500
589
  //# 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;AAuB9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAOpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAmFrE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwdnD"}
@@ -5,6 +5,9 @@ import {
5
5
  LLM_PROVIDERS,
6
6
  SUPPORTED_FILE_TYPES,
7
7
  supportsBaseURL,
8
+ getAllModelsForProvider,
9
+ getCuratedModelsForProvider,
10
+ getSupportedFileTypesForModel,
8
11
  LLMUpdatesSchema
9
12
  } from "@dexto/core";
10
13
  import {
@@ -12,7 +15,8 @@ import {
12
15
  loadCustomModels,
13
16
  saveCustomModel,
14
17
  deleteCustomModel,
15
- CustomModelSchema
18
+ CustomModelSchema,
19
+ isDextoAuthEnabled
16
20
  } from "@dexto/agent-management";
17
21
  import {
18
22
  ProviderCatalogSchema,
@@ -21,11 +25,17 @@ import {
21
25
  } from "../schemas/responses.js";
22
26
  const CurrentQuerySchema = z.object({
23
27
  sessionId: z.string().optional().describe("Session identifier to retrieve session-specific LLM configuration")
24
- }).describe("Query parameters for getting current LLM configuration");
28
+ }).strict().describe("Query parameters for getting current LLM configuration");
25
29
  const CatalogQuerySchema = z.object({
30
+ scope: z.enum(["curated", "all"]).default("all").describe(
31
+ "Catalog scope: 'curated' returns a small, UI-friendly set of models; 'all' returns the full registry (can be large)"
32
+ ),
26
33
  provider: z.union([z.string(), z.array(z.string())]).optional().transform(
27
34
  (value) => Array.isArray(value) ? value : value ? value.split(",") : void 0
28
35
  ).describe("Comma-separated list of LLM providers to filter by"),
36
+ includeModels: z.union([z.literal("true"), z.literal("false"), z.literal("1"), z.literal("0")]).optional().transform(
37
+ (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
38
+ ).describe("Include models list in the response (true or false)"),
29
39
  hasKey: z.union([z.literal("true"), z.literal("false"), z.literal("1"), z.literal("0")]).optional().transform(
30
40
  (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
31
41
  ).describe("Filter by API key presence (true or false)"),
@@ -34,7 +44,7 @@ const CatalogQuerySchema = z.object({
34
44
  (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
35
45
  ).describe("Include only default models (true or false)"),
36
46
  mode: z.enum(["grouped", "flat"]).default("grouped").describe("Response format mode (grouped by provider or flat list)")
37
- }).describe("Query parameters for filtering and formatting the LLM catalog");
47
+ }).strict().describe("Query parameters for filtering and formatting the LLM catalog");
38
48
  const SwitchLLMBodySchema = LLMUpdatesSchema.and(
39
49
  z.object({
40
50
  sessionId: z.string().optional().describe("Session identifier for session-specific LLM configuration")
@@ -59,7 +69,14 @@ function createLlmRouter(getAgent) {
59
69
  maxIterations: true
60
70
  }).extend({
61
71
  displayName: z.string().optional().describe("Human-readable model display name")
62
- })
72
+ }),
73
+ routing: z.object({
74
+ viaDexto: z.boolean().describe(
75
+ "Whether requests route through Dexto gateway"
76
+ )
77
+ }).describe(
78
+ "Routing information for the current LLM configuration"
79
+ )
63
80
  }).describe("Response containing current LLM configuration")
64
81
  }
65
82
  }
@@ -206,6 +223,33 @@ function createLlmRouter(getAgent) {
206
223
  }
207
224
  }
208
225
  });
226
+ const capabilitiesRoute = createRoute({
227
+ method: "get",
228
+ path: "/llm/capabilities",
229
+ summary: "Get Model Capabilities",
230
+ description: "Returns the capabilities (supported file types) for a specific provider/model combination. Handles gateway providers (dexto-nova, openrouter) by resolving to the underlying model capabilities.",
231
+ tags: ["llm"],
232
+ request: {
233
+ query: z.object({
234
+ provider: z.enum(LLM_PROVIDERS).describe("LLM provider name"),
235
+ model: z.string().min(1).describe("Model name (supports both native and OpenRouter format)")
236
+ })
237
+ },
238
+ responses: {
239
+ 200: {
240
+ description: "Model capabilities",
241
+ content: {
242
+ "application/json": {
243
+ schema: z.object({
244
+ provider: z.enum(LLM_PROVIDERS).describe("Provider name"),
245
+ model: z.string().describe("Model name as provided"),
246
+ supportedFileTypes: z.array(z.enum(SUPPORTED_FILE_TYPES)).describe("File types supported by this model")
247
+ })
248
+ }
249
+ }
250
+ }
251
+ }
252
+ });
209
253
  return app.openapi(currentRoute, async (ctx) => {
210
254
  const agent = await getAgent(ctx);
211
255
  const { sessionId } = ctx.req.valid("query");
@@ -226,26 +270,42 @@ function createLlmRouter(getAgent) {
226
270
  } catch {
227
271
  }
228
272
  const { apiKey, ...configWithoutKey } = currentConfig;
273
+ const viaDexto = isDextoAuthEnabled() && currentConfig.provider === "dexto-nova";
229
274
  return ctx.json({
230
275
  config: {
231
276
  ...configWithoutKey,
232
277
  hasApiKey: !!apiKey,
233
278
  ...displayName && { displayName }
279
+ },
280
+ routing: {
281
+ viaDexto
234
282
  }
235
283
  });
236
284
  }).openapi(catalogRoute, (ctx) => {
237
285
  const queryParams = ctx.req.valid("query");
286
+ const includeModels = queryParams.includeModels ?? true;
287
+ const scope = queryParams.scope ?? "all";
238
288
  const providers = {};
239
289
  for (const provider of LLM_PROVIDERS) {
290
+ if (provider === "dexto-nova" && !isDextoAuthEnabled()) {
291
+ continue;
292
+ }
240
293
  const info = LLM_REGISTRY[provider];
241
- const displayName = provider.charAt(0).toUpperCase() + provider.slice(1);
294
+ const displayName = provider === "dexto-nova" ? "Dexto Nova" : provider.charAt(0).toUpperCase() + provider.slice(1);
242
295
  const keyStatus = getProviderKeyStatus(provider);
296
+ const models = (() => {
297
+ if (!includeModels) return [];
298
+ if (scope === "all") {
299
+ return getAllModelsForProvider(provider);
300
+ }
301
+ return getCuratedModelsForProvider(provider);
302
+ })();
243
303
  providers[provider] = {
244
304
  name: displayName,
245
305
  hasApiKey: keyStatus.hasApiKey,
246
306
  primaryEnvVar: keyStatus.envVar,
247
307
  supportsBaseURL: supportsBaseURL(provider),
248
- models: info.models,
308
+ models,
249
309
  supportedFileTypes: info.supportedFileTypes
250
310
  };
251
311
  }
@@ -340,6 +400,20 @@ function createLlmRouter(getAgent) {
340
400
  );
341
401
  }
342
402
  return ctx.json({ ok: true, deleted: name }, 200);
403
+ }).openapi(capabilitiesRoute, (ctx) => {
404
+ const { provider, model } = ctx.req.valid("query");
405
+ let supportedFileTypes;
406
+ try {
407
+ supportedFileTypes = getSupportedFileTypesForModel(provider, model);
408
+ } catch {
409
+ const providerInfo = LLM_REGISTRY[provider];
410
+ supportedFileTypes = providerInfo?.supportedFileTypes ?? [];
411
+ }
412
+ return ctx.json({
413
+ provider,
414
+ model,
415
+ supportedFileTypes
416
+ });
343
417
  });
344
418
  }
345
419
  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-nova" | undefined;
110
110
  };
111
111
  outputFormat: "json";
112
112
  status: 200;
@@ -27,7 +27,8 @@ const QueuedMessageSchema = import_zod_openapi.z.object({
27
27
  id: import_zod_openapi.z.string().describe("Unique identifier for the queued message"),
28
28
  content: import_zod_openapi.z.array(import_responses.ContentPartSchema).describe("Message content parts"),
29
29
  queuedAt: import_zod_openapi.z.number().describe("Unix timestamp when message was queued"),
30
- metadata: import_zod_openapi.z.record(import_zod_openapi.z.unknown()).optional().describe("Optional metadata")
30
+ metadata: import_zod_openapi.z.record(import_zod_openapi.z.unknown()).optional().describe("Optional metadata"),
31
+ kind: import_zod_openapi.z.enum(["default", "background"]).optional().describe("Optional queued message kind")
31
32
  }).strict().describe("A message waiting in the queue");
32
33
  const TextPartSchema = import_zod_openapi.z.object({
33
34
  type: import_zod_openapi.z.literal("text").describe("Content type identifier"),
@@ -46,7 +47,8 @@ const FilePartSchema = import_zod_openapi.z.object({
46
47
  }).describe("File content part");
47
48
  const QueueContentPartSchema = import_zod_openapi.z.discriminatedUnion("type", [TextPartSchema, ImagePartSchema, FilePartSchema]).describe("Content part - text, image, or file");
48
49
  const QueueMessageBodySchema = import_zod_openapi.z.object({
49
- content: import_zod_openapi.z.union([import_zod_openapi.z.string(), import_zod_openapi.z.array(QueueContentPartSchema)]).describe("Message content - string for text, or ContentPart[] for multimodal")
50
+ content: import_zod_openapi.z.union([import_zod_openapi.z.string(), import_zod_openapi.z.array(QueueContentPartSchema)]).describe("Message content - string for text, or ContentPart[] for multimodal"),
51
+ kind: import_zod_openapi.z.enum(["default", "background"]).optional().describe("Optional queued message kind")
50
52
  }).describe("Request body for queueing a message");
51
53
  function createQueueRouter(getAgent) {
52
54
  const app = new import_zod_openapi.OpenAPIHono();
@@ -172,7 +174,11 @@ function createQueueRouter(getAgent) {
172
174
  const { sessionId } = ctx.req.valid("param");
173
175
  const { content: rawContent } = ctx.req.valid("json");
174
176
  const content = typeof rawContent === "string" ? [{ type: "text", text: rawContent }] : rawContent;
175
- const result = await agent.queueMessage(sessionId, { content });
177
+ const { kind } = ctx.req.valid("json");
178
+ const result = await agent.queueMessage(sessionId, {
179
+ content,
180
+ ...kind !== void 0 && { kind }
181
+ });
176
182
  return ctx.json(
177
183
  {
178
184
  queued: result.queued,