@dexto/server 1.3.0 → 1.5.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.
Files changed (109) hide show
  1. package/dist/approval/manual-approval-handler.cjs +23 -15
  2. package/dist/approval/manual-approval-handler.d.ts.map +1 -1
  3. package/dist/approval/manual-approval-handler.js +23 -15
  4. package/dist/events/webhook-subscriber.cjs +1 -1
  5. package/dist/events/webhook-subscriber.d.ts.map +1 -1
  6. package/dist/events/webhook-subscriber.js +1 -1
  7. package/dist/hono/__tests__/test-fixtures.cjs +3 -3
  8. package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -1
  9. package/dist/hono/__tests__/test-fixtures.js +3 -3
  10. package/dist/hono/index.cjs +46 -5
  11. package/dist/hono/index.d.ts +928 -584
  12. package/dist/hono/index.d.ts.map +1 -1
  13. package/dist/hono/index.js +46 -5
  14. package/dist/hono/middleware/error.d.ts.map +1 -1
  15. package/dist/hono/routes/a2a-jsonrpc.cjs +3 -3
  16. package/dist/hono/routes/a2a-jsonrpc.d.ts +4 -1
  17. package/dist/hono/routes/a2a-jsonrpc.d.ts.map +1 -1
  18. package/dist/hono/routes/a2a-jsonrpc.js +3 -3
  19. package/dist/hono/routes/a2a-tasks.cjs +5 -5
  20. package/dist/hono/routes/a2a-tasks.d.ts +13 -10
  21. package/dist/hono/routes/a2a-tasks.d.ts.map +1 -1
  22. package/dist/hono/routes/a2a-tasks.js +5 -5
  23. package/dist/hono/routes/agents.cjs +30 -42
  24. package/dist/hono/routes/agents.d.ts +7 -401
  25. package/dist/hono/routes/agents.d.ts.map +1 -1
  26. package/dist/hono/routes/agents.js +32 -42
  27. package/dist/hono/routes/approvals.cjs +53 -2
  28. package/dist/hono/routes/approvals.d.ts +29 -1
  29. package/dist/hono/routes/approvals.d.ts.map +1 -1
  30. package/dist/hono/routes/approvals.js +53 -2
  31. package/dist/hono/routes/discovery.cjs +67 -0
  32. package/dist/hono/routes/discovery.d.ts +44 -0
  33. package/dist/hono/routes/discovery.d.ts.map +1 -0
  34. package/dist/hono/routes/discovery.js +43 -0
  35. package/dist/hono/routes/greeting.cjs +2 -2
  36. package/dist/hono/routes/greeting.d.ts +2 -2
  37. package/dist/hono/routes/greeting.d.ts.map +1 -1
  38. package/dist/hono/routes/greeting.js +2 -2
  39. package/dist/hono/routes/health.d.ts +2 -2
  40. package/dist/hono/routes/health.d.ts.map +1 -1
  41. package/dist/hono/routes/key.cjs +110 -0
  42. package/dist/hono/routes/key.d.ts +48 -0
  43. package/dist/hono/routes/key.d.ts.map +1 -0
  44. package/dist/hono/routes/key.js +90 -0
  45. package/dist/hono/routes/llm.cjs +119 -62
  46. package/dist/hono/routes/llm.d.ts +242 -42
  47. package/dist/hono/routes/llm.d.ts.map +1 -1
  48. package/dist/hono/routes/llm.js +118 -58
  49. package/dist/hono/routes/mcp.cjs +16 -12
  50. package/dist/hono/routes/mcp.d.ts +6 -3
  51. package/dist/hono/routes/mcp.d.ts.map +1 -1
  52. package/dist/hono/routes/mcp.js +17 -13
  53. package/dist/hono/routes/memory.cjs +5 -5
  54. package/dist/hono/routes/memory.d.ts +5 -2
  55. package/dist/hono/routes/memory.d.ts.map +1 -1
  56. package/dist/hono/routes/memory.js +5 -5
  57. package/dist/hono/routes/messages.cjs +58 -66
  58. package/dist/hono/routes/messages.d.ts +99 -55
  59. package/dist/hono/routes/messages.d.ts.map +1 -1
  60. package/dist/hono/routes/messages.js +59 -67
  61. package/dist/hono/routes/models.cjs +319 -0
  62. package/dist/hono/routes/models.d.ts +107 -0
  63. package/dist/hono/routes/models.d.ts.map +1 -0
  64. package/dist/hono/routes/models.js +305 -0
  65. package/dist/hono/routes/openrouter.cjs +153 -0
  66. package/dist/hono/routes/openrouter.d.ts +54 -0
  67. package/dist/hono/routes/openrouter.d.ts.map +1 -0
  68. package/dist/hono/routes/openrouter.js +134 -0
  69. package/dist/hono/routes/prompts.cjs +5 -5
  70. package/dist/hono/routes/prompts.d.ts +10 -7
  71. package/dist/hono/routes/prompts.d.ts.map +1 -1
  72. package/dist/hono/routes/prompts.js +5 -5
  73. package/dist/hono/routes/queue.cjs +202 -0
  74. package/dist/hono/routes/queue.d.ts +174 -0
  75. package/dist/hono/routes/queue.d.ts.map +1 -0
  76. package/dist/hono/routes/queue.js +178 -0
  77. package/dist/hono/routes/resources.cjs +3 -3
  78. package/dist/hono/routes/resources.d.ts +3 -3
  79. package/dist/hono/routes/resources.d.ts.map +1 -1
  80. package/dist/hono/routes/resources.js +3 -3
  81. package/dist/hono/routes/search.cjs +2 -2
  82. package/dist/hono/routes/search.d.ts +39 -10
  83. package/dist/hono/routes/search.d.ts.map +1 -1
  84. package/dist/hono/routes/search.js +2 -2
  85. package/dist/hono/routes/sessions.cjs +74 -20
  86. package/dist/hono/routes/sessions.d.ts +25 -4
  87. package/dist/hono/routes/sessions.d.ts.map +1 -1
  88. package/dist/hono/routes/sessions.js +74 -20
  89. package/dist/hono/routes/tools.cjs +126 -0
  90. package/dist/hono/routes/tools.d.ts +42 -0
  91. package/dist/hono/routes/tools.d.ts.map +1 -0
  92. package/dist/hono/routes/tools.js +102 -0
  93. package/dist/hono/routes/webhooks.cjs +4 -4
  94. package/dist/hono/routes/webhooks.d.ts +4 -1
  95. package/dist/hono/routes/webhooks.d.ts.map +1 -1
  96. package/dist/hono/routes/webhooks.js +4 -4
  97. package/dist/hono/schemas/responses.cjs +24 -5
  98. package/dist/hono/schemas/responses.d.ts +838 -120
  99. package/dist/hono/schemas/responses.d.ts.map +1 -1
  100. package/dist/hono/schemas/responses.js +24 -10
  101. package/dist/hono/start-server.cjs +102 -0
  102. package/dist/hono/start-server.d.ts +61 -0
  103. package/dist/hono/start-server.d.ts.map +1 -0
  104. package/dist/hono/start-server.js +78 -0
  105. package/dist/index.cjs +2 -0
  106. package/dist/index.d.ts +1 -0
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +1 -0
  109. package/package.json +5 -4
@@ -0,0 +1,90 @@
1
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
+ import { LLM_PROVIDERS } from "@dexto/core";
3
+ import {
4
+ getProviderKeyStatus,
5
+ saveProviderApiKey,
6
+ resolveApiKeyForProvider
7
+ } from "@dexto/agent-management";
8
+ function maskApiKey(key) {
9
+ if (!key) return "";
10
+ if (key.length < 12) {
11
+ return key.slice(0, 4) + "..." + key.slice(-4);
12
+ }
13
+ return key.slice(0, 7) + "..." + key.slice(-4);
14
+ }
15
+ const GetKeyParamsSchema = z.object({
16
+ provider: z.enum(LLM_PROVIDERS).describe("LLM provider identifier")
17
+ }).describe("Path parameters for API key operations");
18
+ const SaveKeySchema = z.object({
19
+ provider: z.enum(LLM_PROVIDERS).describe("LLM provider identifier (e.g., openai, anthropic)"),
20
+ apiKey: z.string().min(1, "API key is required").describe("API key for the provider (writeOnly - never returned in responses)").openapi({ writeOnly: true })
21
+ }).describe("Request body for saving a provider API key");
22
+ function createKeyRouter() {
23
+ const app = new OpenAPIHono();
24
+ const getKeyRoute = createRoute({
25
+ method: "get",
26
+ path: "/llm/key/{provider}",
27
+ summary: "Get Provider API Key Status",
28
+ description: "Retrieves the API key status for a provider. Returns a masked key value (e.g., sk-proj...xyz4) for UI display purposes.",
29
+ tags: ["llm"],
30
+ request: { params: GetKeyParamsSchema },
31
+ responses: {
32
+ 200: {
33
+ description: "API key status and value",
34
+ content: {
35
+ "application/json": {
36
+ schema: z.object({
37
+ provider: z.enum(LLM_PROVIDERS).describe("Provider identifier"),
38
+ envVar: z.string().describe("Environment variable name"),
39
+ hasKey: z.boolean().describe("Whether API key is configured"),
40
+ keyValue: z.string().optional().describe(
41
+ "Masked API key value if configured (e.g., sk-proj...xyz4)"
42
+ )
43
+ }).strict().describe("API key status response")
44
+ }
45
+ }
46
+ }
47
+ }
48
+ });
49
+ const saveKeyRoute = createRoute({
50
+ method: "post",
51
+ path: "/llm/key",
52
+ summary: "Save Provider API Key",
53
+ description: "Stores an API key for a provider in .env and makes it available immediately",
54
+ tags: ["llm"],
55
+ request: { body: { content: { "application/json": { schema: SaveKeySchema } } } },
56
+ responses: {
57
+ 200: {
58
+ description: "API key saved",
59
+ content: {
60
+ "application/json": {
61
+ schema: z.object({
62
+ ok: z.literal(true).describe("Operation success indicator"),
63
+ provider: z.enum(LLM_PROVIDERS).describe("Provider for which the key was saved"),
64
+ envVar: z.string().describe("Environment variable name where key was stored")
65
+ }).strict().describe("API key save response")
66
+ }
67
+ }
68
+ }
69
+ }
70
+ });
71
+ return app.openapi(getKeyRoute, (ctx) => {
72
+ const { provider } = ctx.req.valid("param");
73
+ const keyStatus = getProviderKeyStatus(provider);
74
+ const apiKey = resolveApiKeyForProvider(provider);
75
+ const maskedKey = apiKey ? maskApiKey(apiKey) : void 0;
76
+ return ctx.json({
77
+ provider,
78
+ envVar: keyStatus.envVar,
79
+ hasKey: keyStatus.hasApiKey,
80
+ ...maskedKey && { keyValue: maskedKey }
81
+ });
82
+ }).openapi(saveKeyRoute, async (ctx) => {
83
+ const { provider, apiKey } = ctx.req.valid("json");
84
+ const meta = await saveProviderApiKey(provider, apiKey);
85
+ return ctx.json({ ok: true, provider, envVar: meta.envVar });
86
+ });
87
+ }
88
+ export {
89
+ createKeyRouter
90
+ };
@@ -23,6 +23,7 @@ __export(llm_exports, {
23
23
  module.exports = __toCommonJS(llm_exports);
24
24
  var import_zod_openapi = require("@hono/zod-openapi");
25
25
  var import_core = require("@dexto/core");
26
+ var import_core2 = require("@dexto/core");
26
27
  var import_agent_management = require("@dexto/agent-management");
27
28
  var import_responses = require("../schemas/responses.js");
28
29
  const CurrentQuerySchema = import_zod_openapi.z.object({
@@ -35,18 +36,13 @@ const CatalogQuerySchema = import_zod_openapi.z.object({
35
36
  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(
36
37
  (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
37
38
  ).describe("Filter by API key presence (true or false)"),
38
- router: import_zod_openapi.z.enum(import_core.LLM_ROUTERS).optional().describe("Filter by router type (vercel or in-built)"),
39
- fileType: import_zod_openapi.z.enum(import_core.SUPPORTED_FILE_TYPES).optional().describe("Filter by supported file type (audio, pdf, or image)"),
39
+ fileType: import_zod_openapi.z.enum(import_core2.SUPPORTED_FILE_TYPES).optional().describe("Filter by supported file type (audio, pdf, or image)"),
40
40
  defaultOnly: 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(
41
41
  (raw) => raw === "true" || raw === "1" ? true : raw === "false" || raw === "0" ? false : void 0
42
42
  ).describe("Include only default models (true or false)"),
43
43
  mode: import_zod_openapi.z.enum(["grouped", "flat"]).default("grouped").describe("Response format mode (grouped by provider or flat list)")
44
44
  }).describe("Query parameters for filtering and formatting the LLM catalog");
45
- const SaveKeySchema = import_zod_openapi.z.object({
46
- provider: import_zod_openapi.z.enum(import_core.LLM_PROVIDERS).describe("LLM provider identifier (e.g., openai, anthropic)"),
47
- apiKey: import_zod_openapi.z.string().min(1, "API key is required").describe("API key for the provider (writeOnly - never returned in responses)").openapi({ writeOnly: true })
48
- }).describe("Request body for saving a provider API key");
49
- const SwitchLLMBodySchema = import_core.LLMUpdatesSchema.and(
45
+ const SwitchLLMBodySchema = import_core2.LLMUpdatesSchema.and(
50
46
  import_zod_openapi.z.object({
51
47
  sessionId: import_zod_openapi.z.string().optional().describe("Session identifier for session-specific LLM configuration")
52
48
  })
@@ -67,8 +63,7 @@ function createLlmRouter(getAgent) {
67
63
  "application/json": {
68
64
  schema: import_zod_openapi.z.object({
69
65
  config: import_responses.LLMConfigResponseSchema.partial({
70
- maxIterations: true,
71
- router: true
66
+ maxIterations: true
72
67
  }).extend({
73
68
  displayName: import_zod_openapi.z.string().optional().describe("Human-readable model display name")
74
69
  })
@@ -92,7 +87,7 @@ function createLlmRouter(getAgent) {
92
87
  "application/json": {
93
88
  schema: import_zod_openapi.z.union([
94
89
  import_zod_openapi.z.object({
95
- providers: import_zod_openapi.z.record(import_zod_openapi.z.enum(import_core.LLM_PROVIDERS), import_responses.ProviderCatalogSchema).describe(
90
+ providers: import_zod_openapi.z.record(import_zod_openapi.z.enum(import_core2.LLM_PROVIDERS), import_responses.ProviderCatalogSchema).describe(
96
91
  "Providers grouped by ID with their models and capabilities"
97
92
  )
98
93
  }).strict().describe("Grouped catalog response (mode=grouped)"),
@@ -109,28 +104,6 @@ function createLlmRouter(getAgent) {
109
104
  }
110
105
  }
111
106
  });
112
- const saveKeyRoute = (0, import_zod_openapi.createRoute)({
113
- method: "post",
114
- path: "/llm/key",
115
- summary: "Save Provider API Key",
116
- description: "Stores an API key for a provider in .env and makes it available immediately",
117
- tags: ["llm"],
118
- request: { body: { content: { "application/json": { schema: SaveKeySchema } } } },
119
- responses: {
120
- 200: {
121
- description: "API key saved",
122
- content: {
123
- "application/json": {
124
- schema: import_zod_openapi.z.object({
125
- ok: import_zod_openapi.z.literal(true).describe("Operation success indicator"),
126
- provider: import_zod_openapi.z.enum(import_core.LLM_PROVIDERS).describe("Provider for which the key was saved"),
127
- envVar: import_zod_openapi.z.string().describe("Environment variable name where key was stored")
128
- }).strict().describe("API key save response")
129
- }
130
- }
131
- }
132
- }
133
- });
134
107
  const switchRoute = (0, import_zod_openapi.createRoute)({
135
108
  method: "post",
136
109
  path: "/llm/switch",
@@ -162,16 +135,101 @@ function createLlmRouter(getAgent) {
162
135
  }
163
136
  }
164
137
  });
165
- return app.openapi(currentRoute, (ctx) => {
166
- const agent = getAgent();
138
+ const listCustomModelsRoute = (0, import_zod_openapi.createRoute)({
139
+ method: "get",
140
+ path: "/llm/custom-models",
141
+ summary: "List Custom Models",
142
+ description: "Returns all saved custom openai-compatible model configurations",
143
+ tags: ["llm"],
144
+ responses: {
145
+ 200: {
146
+ description: "List of custom models",
147
+ content: {
148
+ "application/json": {
149
+ schema: import_zod_openapi.z.object({
150
+ models: import_zod_openapi.z.array(import_agent_management.CustomModelSchema).describe("List of custom models")
151
+ })
152
+ }
153
+ }
154
+ }
155
+ }
156
+ });
157
+ const createCustomModelRoute = (0, import_zod_openapi.createRoute)({
158
+ method: "post",
159
+ path: "/llm/custom-models",
160
+ summary: "Create Custom Model",
161
+ description: "Saves a new custom openai-compatible model configuration",
162
+ tags: ["llm"],
163
+ request: {
164
+ body: { content: { "application/json": { schema: import_agent_management.CustomModelSchema } } }
165
+ },
166
+ responses: {
167
+ 200: {
168
+ description: "Custom model saved",
169
+ content: {
170
+ "application/json": {
171
+ schema: import_zod_openapi.z.object({
172
+ ok: import_zod_openapi.z.literal(true).describe("Success indicator"),
173
+ model: import_agent_management.CustomModelSchema
174
+ })
175
+ }
176
+ }
177
+ }
178
+ }
179
+ });
180
+ const deleteCustomModelRoute = (0, import_zod_openapi.createRoute)({
181
+ method: "delete",
182
+ path: "/llm/custom-models/{name}",
183
+ summary: "Delete Custom Model",
184
+ description: "Deletes a custom model by name",
185
+ tags: ["llm"],
186
+ request: {
187
+ params: import_zod_openapi.z.object({
188
+ name: import_zod_openapi.z.string().min(1).describe("Model name to delete")
189
+ })
190
+ },
191
+ responses: {
192
+ 200: {
193
+ description: "Custom model deleted",
194
+ content: {
195
+ "application/json": {
196
+ schema: import_zod_openapi.z.object({
197
+ ok: import_zod_openapi.z.literal(true).describe("Success indicator"),
198
+ deleted: import_zod_openapi.z.string().describe("Name of the deleted model")
199
+ })
200
+ }
201
+ }
202
+ },
203
+ 404: {
204
+ description: "Custom model not found",
205
+ content: {
206
+ "application/json": {
207
+ schema: import_zod_openapi.z.object({
208
+ ok: import_zod_openapi.z.literal(false).describe("Failure indicator"),
209
+ error: import_zod_openapi.z.string().describe("Error message")
210
+ })
211
+ }
212
+ }
213
+ }
214
+ }
215
+ });
216
+ return app.openapi(currentRoute, async (ctx) => {
217
+ const agent = await getAgent(ctx);
167
218
  const { sessionId } = ctx.req.valid("query");
168
219
  const currentConfig = sessionId ? agent.getEffectiveConfig(sessionId).llm : agent.getCurrentLLMConfig();
169
220
  let displayName;
170
221
  try {
171
- const model = import_core.LLM_REGISTRY[currentConfig.provider]?.models.find(
222
+ const model = import_core2.LLM_REGISTRY[currentConfig.provider]?.models.find(
172
223
  (m) => m.name.toLowerCase() === String(currentConfig.model).toLowerCase()
173
224
  );
174
225
  displayName = model?.displayName || void 0;
226
+ if (!displayName) {
227
+ const customModels = await (0, import_agent_management.loadCustomModels)();
228
+ const customModel = customModels.find(
229
+ (cm) => cm.name.toLowerCase() === String(currentConfig.model).toLowerCase()
230
+ );
231
+ displayName = customModel?.displayName || void 0;
232
+ }
175
233
  } catch {
176
234
  }
177
235
  const { apiKey, ...configWithoutKey } = currentConfig;
@@ -185,16 +243,15 @@ function createLlmRouter(getAgent) {
185
243
  }).openapi(catalogRoute, (ctx) => {
186
244
  const queryParams = ctx.req.valid("query");
187
245
  const providers = {};
188
- for (const provider of import_core.LLM_PROVIDERS) {
189
- const info = import_core.LLM_REGISTRY[provider];
246
+ for (const provider of import_core2.LLM_PROVIDERS) {
247
+ const info = import_core2.LLM_REGISTRY[provider];
190
248
  const displayName = provider.charAt(0).toUpperCase() + provider.slice(1);
191
249
  const keyStatus = (0, import_agent_management.getProviderKeyStatus)(provider);
192
250
  providers[provider] = {
193
251
  name: displayName,
194
252
  hasApiKey: keyStatus.hasApiKey,
195
253
  primaryEnvVar: keyStatus.envVar,
196
- supportedRouters: (0, import_core.getSupportedRoutersForProvider)(provider),
197
- supportsBaseURL: (0, import_core.supportsBaseURL)(provider),
254
+ supportsBaseURL: (0, import_core2.supportsBaseURL)(provider),
198
255
  models: info.models,
199
256
  supportedFileTypes: info.supportedFileTypes
200
257
  };
@@ -203,7 +260,7 @@ function createLlmRouter(getAgent) {
203
260
  if (queryParams.provider && queryParams.provider.length > 0) {
204
261
  const allowed = new Set(
205
262
  queryParams.provider.filter(
206
- (p) => import_core.LLM_PROVIDERS.includes(p)
263
+ (p) => import_core2.LLM_PROVIDERS.includes(p)
207
264
  )
208
265
  );
209
266
  const filteredByProvider = {};
@@ -223,23 +280,6 @@ function createLlmRouter(getAgent) {
223
280
  }
224
281
  filtered = byKey;
225
282
  }
226
- if (queryParams.router) {
227
- const byRouter = {};
228
- for (const [id, catalog] of Object.entries(filtered)) {
229
- if (!catalog.supportedRouters.includes(queryParams.router)) continue;
230
- const models = catalog.models.filter(
231
- (model) => (0, import_core.isRouterSupportedForModel)(
232
- id,
233
- model.name,
234
- queryParams.router
235
- )
236
- );
237
- if (models.length > 0) {
238
- byRouter[id] = { ...catalog, models };
239
- }
240
- }
241
- filtered = byRouter;
242
- }
243
283
  if (queryParams.fileType) {
244
284
  const byFileType = {};
245
285
  for (const [id, catalog] of Object.entries(filtered)) {
@@ -273,12 +313,8 @@ function createLlmRouter(getAgent) {
273
313
  return ctx.json({ models: flat });
274
314
  }
275
315
  return ctx.json({ providers: filtered });
276
- }).openapi(saveKeyRoute, async (ctx) => {
277
- const { provider, apiKey } = ctx.req.valid("json");
278
- const meta = await (0, import_agent_management.saveProviderApiKey)(provider, apiKey, process.cwd());
279
- return ctx.json({ ok: true, provider, envVar: meta.envVar });
280
316
  }).openapi(switchRoute, async (ctx) => {
281
- const agent = getAgent();
317
+ const agent = await getAgent(ctx);
282
318
  const raw = ctx.req.valid("json");
283
319
  const { sessionId, ...llmUpdates } = raw;
284
320
  const config = await agent.switchLLM(llmUpdates, sessionId);
@@ -290,6 +326,27 @@ function createLlmRouter(getAgent) {
290
326
  },
291
327
  sessionId
292
328
  });
329
+ }).openapi(listCustomModelsRoute, async (ctx) => {
330
+ const models = await (0, import_agent_management.loadCustomModels)();
331
+ return ctx.json({ models });
332
+ }).openapi(createCustomModelRoute, async (ctx) => {
333
+ const model = ctx.req.valid("json");
334
+ await (0, import_agent_management.saveCustomModel)(model);
335
+ return ctx.json({ ok: true, model });
336
+ }).openapi(deleteCustomModelRoute, async (ctx) => {
337
+ const { name: encodedName } = ctx.req.valid("param");
338
+ const name = decodeURIComponent(encodedName);
339
+ const deleted = await (0, import_agent_management.deleteCustomModel)(name);
340
+ if (!deleted) {
341
+ throw new import_core.DextoRuntimeError(
342
+ "custom_model_not_found",
343
+ import_core.ErrorScope.LLM,
344
+ import_core.ErrorType.NOT_FOUND,
345
+ `Custom model '${name}' not found`,
346
+ { modelName: name }
347
+ );
348
+ }
349
+ return ctx.json({ ok: true, deleted: name }, 200);
293
350
  });
294
351
  }
295
352
  // Annotate the CommonJS export names for ESM import in node: