@dexto/server 1.4.0 → 1.5.1

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 (100) hide show
  1. package/dist/hono/__tests__/test-fixtures.cjs +1 -1
  2. package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -1
  3. package/dist/hono/__tests__/test-fixtures.js +1 -1
  4. package/dist/hono/index.cjs +41 -5
  5. package/dist/hono/index.d.ts +470 -456
  6. package/dist/hono/index.d.ts.map +1 -1
  7. package/dist/hono/index.js +41 -5
  8. package/dist/hono/routes/a2a-jsonrpc.cjs +3 -3
  9. package/dist/hono/routes/a2a-jsonrpc.d.ts +4 -1
  10. package/dist/hono/routes/a2a-jsonrpc.d.ts.map +1 -1
  11. package/dist/hono/routes/a2a-jsonrpc.js +3 -3
  12. package/dist/hono/routes/a2a-tasks.cjs +5 -5
  13. package/dist/hono/routes/a2a-tasks.d.ts +13 -10
  14. package/dist/hono/routes/a2a-tasks.d.ts.map +1 -1
  15. package/dist/hono/routes/a2a-tasks.js +5 -5
  16. package/dist/hono/routes/agents.cjs +25 -35
  17. package/dist/hono/routes/agents.d.ts +6 -407
  18. package/dist/hono/routes/agents.d.ts.map +1 -1
  19. package/dist/hono/routes/agents.js +25 -35
  20. package/dist/hono/routes/approvals.cjs +2 -2
  21. package/dist/hono/routes/approvals.d.ts +4 -1
  22. package/dist/hono/routes/approvals.d.ts.map +1 -1
  23. package/dist/hono/routes/approvals.js +2 -2
  24. package/dist/hono/routes/discovery.cjs +68 -0
  25. package/dist/hono/routes/discovery.d.ts +53 -0
  26. package/dist/hono/routes/discovery.d.ts.map +1 -0
  27. package/dist/hono/routes/discovery.js +44 -0
  28. package/dist/hono/routes/greeting.cjs +2 -2
  29. package/dist/hono/routes/greeting.d.ts +2 -2
  30. package/dist/hono/routes/greeting.d.ts.map +1 -1
  31. package/dist/hono/routes/greeting.js +2 -2
  32. package/dist/hono/routes/health.d.ts +2 -2
  33. package/dist/hono/routes/health.d.ts.map +1 -1
  34. package/dist/hono/routes/key.cjs +110 -0
  35. package/dist/hono/routes/key.d.ts +48 -0
  36. package/dist/hono/routes/key.d.ts.map +1 -0
  37. package/dist/hono/routes/key.js +90 -0
  38. package/dist/hono/routes/llm.cjs +12 -34
  39. package/dist/hono/routes/llm.d.ts +179 -25
  40. package/dist/hono/routes/llm.d.ts.map +1 -1
  41. package/dist/hono/routes/llm.js +12 -35
  42. package/dist/hono/routes/mcp.cjs +8 -8
  43. package/dist/hono/routes/mcp.d.ts +2 -2
  44. package/dist/hono/routes/mcp.d.ts.map +1 -1
  45. package/dist/hono/routes/mcp.js +8 -8
  46. package/dist/hono/routes/memory.cjs +5 -5
  47. package/dist/hono/routes/memory.d.ts +8 -5
  48. package/dist/hono/routes/memory.d.ts.map +1 -1
  49. package/dist/hono/routes/memory.js +5 -5
  50. package/dist/hono/routes/messages.cjs +4 -4
  51. package/dist/hono/routes/messages.d.ts +12 -12
  52. package/dist/hono/routes/messages.d.ts.map +1 -1
  53. package/dist/hono/routes/messages.js +4 -4
  54. package/dist/hono/routes/models.cjs +319 -0
  55. package/dist/hono/routes/models.d.ts +107 -0
  56. package/dist/hono/routes/models.d.ts.map +1 -0
  57. package/dist/hono/routes/models.js +305 -0
  58. package/dist/hono/routes/openrouter.cjs +153 -0
  59. package/dist/hono/routes/openrouter.d.ts +54 -0
  60. package/dist/hono/routes/openrouter.d.ts.map +1 -0
  61. package/dist/hono/routes/openrouter.js +134 -0
  62. package/dist/hono/routes/prompts.cjs +5 -5
  63. package/dist/hono/routes/prompts.d.ts +4 -1
  64. package/dist/hono/routes/prompts.d.ts.map +1 -1
  65. package/dist/hono/routes/prompts.js +5 -5
  66. package/dist/hono/routes/queue.cjs +4 -4
  67. package/dist/hono/routes/queue.d.ts +4 -1
  68. package/dist/hono/routes/queue.d.ts.map +1 -1
  69. package/dist/hono/routes/queue.js +4 -4
  70. package/dist/hono/routes/resources.cjs +3 -3
  71. package/dist/hono/routes/resources.d.ts +2 -2
  72. package/dist/hono/routes/resources.d.ts.map +1 -1
  73. package/dist/hono/routes/resources.js +3 -3
  74. package/dist/hono/routes/search.cjs +2 -2
  75. package/dist/hono/routes/search.d.ts +6 -3
  76. package/dist/hono/routes/search.d.ts.map +1 -1
  77. package/dist/hono/routes/search.js +2 -2
  78. package/dist/hono/routes/sessions.cjs +9 -9
  79. package/dist/hono/routes/sessions.d.ts +3 -3
  80. package/dist/hono/routes/sessions.d.ts.map +1 -1
  81. package/dist/hono/routes/sessions.js +9 -9
  82. package/dist/hono/routes/tools.cjs +126 -0
  83. package/dist/hono/routes/tools.d.ts +42 -0
  84. package/dist/hono/routes/tools.d.ts.map +1 -0
  85. package/dist/hono/routes/tools.js +102 -0
  86. package/dist/hono/routes/webhooks.cjs +4 -4
  87. package/dist/hono/routes/webhooks.d.ts +4 -1
  88. package/dist/hono/routes/webhooks.d.ts.map +1 -1
  89. package/dist/hono/routes/webhooks.js +4 -4
  90. package/dist/hono/schemas/responses.d.ts +47 -41
  91. package/dist/hono/schemas/responses.d.ts.map +1 -1
  92. package/dist/hono/start-server.cjs +102 -0
  93. package/dist/hono/start-server.d.ts +61 -0
  94. package/dist/hono/start-server.d.ts.map +1 -0
  95. package/dist/hono/start-server.js +78 -0
  96. package/dist/index.cjs +2 -0
  97. package/dist/index.d.ts +1 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +1 -0
  100. package/package.json +5 -4
@@ -127,7 +127,7 @@ function createMemoryRouter(getAgent) {
127
127
  if (input.metadata !== void 0) {
128
128
  createInput.metadata = input.metadata;
129
129
  }
130
- const agent = getAgent();
130
+ const agent = await getAgent(ctx);
131
131
  const memory = await agent.memoryManager.create(createInput);
132
132
  return ctx.json({ ok: true, memory }, 201);
133
133
  }).openapi(listRoute, async (ctx) => {
@@ -138,12 +138,12 @@ function createMemoryRouter(getAgent) {
138
138
  if (query.pinned !== void 0) options.pinned = query.pinned;
139
139
  if (query.limit !== void 0) options.limit = query.limit;
140
140
  if (query.offset !== void 0) options.offset = query.offset;
141
- const agent = getAgent();
141
+ const agent = await getAgent(ctx);
142
142
  const memories = await agent.memoryManager.list(options);
143
143
  return ctx.json({ ok: true, memories });
144
144
  }).openapi(getRoute, async (ctx) => {
145
145
  const { id } = ctx.req.valid("param");
146
- const agent = getAgent();
146
+ const agent = await getAgent(ctx);
147
147
  const memory = await agent.memoryManager.get(id);
148
148
  return ctx.json({ ok: true, memory });
149
149
  }).openapi(updateRoute, async (ctx) => {
@@ -153,12 +153,12 @@ function createMemoryRouter(getAgent) {
153
153
  if (updatesRaw.content !== void 0) updates.content = updatesRaw.content;
154
154
  if (updatesRaw.metadata !== void 0) updates.metadata = updatesRaw.metadata;
155
155
  if (updatesRaw.tags !== void 0) updates.tags = updatesRaw.tags;
156
- const agent = getAgent();
156
+ const agent = await getAgent(ctx);
157
157
  const memory = await agent.memoryManager.update(id, updates);
158
158
  return ctx.json({ ok: true, memory });
159
159
  }).openapi(deleteRoute, async (ctx) => {
160
160
  const { id } = ctx.req.valid("param");
161
- const agent = getAgent();
161
+ const agent = await getAgent(ctx);
162
162
  await agent.memoryManager.delete(id);
163
163
  return ctx.json({ ok: true, message: "Memory deleted successfully" });
164
164
  });
@@ -184,7 +184,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
184
184
  }
185
185
  });
186
186
  return app.openapi(messageRoute, async (ctx) => {
187
- const agent = getAgent();
187
+ const agent = await getAgent(ctx);
188
188
  agent.logger.info("Received message via POST /api/message");
189
189
  const { content, sessionId } = ctx.req.valid("json");
190
190
  agent.logger.info(`Message for session: ${sessionId}`);
@@ -195,7 +195,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
195
195
  });
196
196
  return ctx.json({ accepted: true, sessionId }, 202);
197
197
  }).openapi(messageSyncRoute, async (ctx) => {
198
- const agent = getAgent();
198
+ const agent = await getAgent(ctx);
199
199
  agent.logger.info("Received message via POST /api/message-sync");
200
200
  const { content, sessionId } = ctx.req.valid("json");
201
201
  agent.logger.info(`Message for session: ${sessionId}`);
@@ -210,13 +210,13 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
210
210
  provider: llmConfig.provider
211
211
  });
212
212
  }).openapi(resetRoute, async (ctx) => {
213
- const agent = getAgent();
213
+ const agent = await getAgent(ctx);
214
214
  agent.logger.info("Received request via POST /api/reset");
215
215
  const { sessionId } = ctx.req.valid("json");
216
216
  await agent.resetConversation(sessionId);
217
217
  return ctx.json({ status: "reset initiated", sessionId });
218
218
  }).openapi(messageStreamRoute, async (ctx) => {
219
- const agent = getAgent();
219
+ const agent = await getAgent(ctx);
220
220
  const { content, sessionId } = ctx.req.valid("json");
221
221
  const isBusy = await agent.isSessionBusy(sessionId);
222
222
  if (isBusy) {
@@ -1,7 +1,7 @@
1
1
  import { OpenAPIHono } from '@hono/zod-openapi';
2
- import type { DextoAgent } from '@dexto/core';
3
2
  import type { ApprovalCoordinator } from '../../approval/approval-coordinator.js';
4
- export declare function createMessagesRouter(getAgent: () => DextoAgent, approvalCoordinator?: ApprovalCoordinator): OpenAPIHono<import("hono").Env, {
3
+ import type { GetAgentFn } from '../index.js';
4
+ export declare function createMessagesRouter(getAgent: GetAgentFn, approvalCoordinator?: ApprovalCoordinator): OpenAPIHono<import("hono").Env, {
5
5
  "/message": {
6
6
  $post: {
7
7
  input: {
@@ -22,12 +22,9 @@ export declare function createMessagesRouter(getAgent: () => DextoAgent, approva
22
22
  sessionId: string;
23
23
  };
24
24
  };
25
- output: {
26
- sessionId: string;
27
- accepted: true;
28
- };
29
- outputFormat: "json";
30
- status: 202;
25
+ output: {};
26
+ outputFormat: string;
27
+ status: 400;
31
28
  } | {
32
29
  input: {
33
30
  json: {
@@ -47,9 +44,12 @@ export declare function createMessagesRouter(getAgent: () => DextoAgent, approva
47
44
  sessionId: string;
48
45
  };
49
46
  };
50
- output: {};
51
- outputFormat: string;
52
- status: 400;
47
+ output: {
48
+ sessionId: string;
49
+ accepted: true;
50
+ };
51
+ outputFormat: "json";
52
+ status: 202;
53
53
  };
54
54
  };
55
55
  } & {
@@ -106,7 +106,7 @@ export declare function createMessagesRouter(getAgent: () => DextoAgent, approva
106
106
  totalTokens?: number | undefined;
107
107
  } | undefined;
108
108
  model?: string | undefined;
109
- provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
109
+ provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | undefined;
110
110
  };
111
111
  outputFormat: "json";
112
112
  status: 200;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AA2DlF,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,MAAM,UAAU,EAC1B,mBAAmB,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0U5C"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAIhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAElF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA0D9C,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,UAAU,EACpB,mBAAmB,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0U5C"}
@@ -161,7 +161,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
161
161
  }
162
162
  });
163
163
  return app.openapi(messageRoute, async (ctx) => {
164
- const agent = getAgent();
164
+ const agent = await getAgent(ctx);
165
165
  agent.logger.info("Received message via POST /api/message");
166
166
  const { content, sessionId } = ctx.req.valid("json");
167
167
  agent.logger.info(`Message for session: ${sessionId}`);
@@ -172,7 +172,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
172
172
  });
173
173
  return ctx.json({ accepted: true, sessionId }, 202);
174
174
  }).openapi(messageSyncRoute, async (ctx) => {
175
- const agent = getAgent();
175
+ const agent = await getAgent(ctx);
176
176
  agent.logger.info("Received message via POST /api/message-sync");
177
177
  const { content, sessionId } = ctx.req.valid("json");
178
178
  agent.logger.info(`Message for session: ${sessionId}`);
@@ -187,13 +187,13 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
187
187
  provider: llmConfig.provider
188
188
  });
189
189
  }).openapi(resetRoute, async (ctx) => {
190
- const agent = getAgent();
190
+ const agent = await getAgent(ctx);
191
191
  agent.logger.info("Received request via POST /api/reset");
192
192
  const { sessionId } = ctx.req.valid("json");
193
193
  await agent.resetConversation(sessionId);
194
194
  return ctx.json({ status: "reset initiated", sessionId });
195
195
  }).openapi(messageStreamRoute, async (ctx) => {
196
- const agent = getAgent();
196
+ const agent = await getAgent(ctx);
197
197
  const { content, sessionId } = ctx.req.valid("json");
198
198
  const isBusy = await agent.isSessionBusy(sessionId);
199
199
  if (isBusy) {
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var models_exports = {};
20
+ __export(models_exports, {
21
+ createModelsRouter: () => createModelsRouter
22
+ });
23
+ module.exports = __toCommonJS(models_exports);
24
+ var import_zod_openapi = require("@hono/zod-openapi");
25
+ var import_fs = require("fs");
26
+ var import_core = require("@dexto/core");
27
+ var import_agent_management = require("@dexto/agent-management");
28
+ const LocalModelSchema = import_zod_openapi.z.object({
29
+ id: import_zod_openapi.z.string().describe("Model identifier"),
30
+ displayName: import_zod_openapi.z.string().describe("Human-readable model name"),
31
+ filePath: import_zod_openapi.z.string().describe("Absolute path to the GGUF file"),
32
+ sizeBytes: import_zod_openapi.z.number().describe("File size in bytes"),
33
+ contextLength: import_zod_openapi.z.number().optional().describe("Maximum context length in tokens"),
34
+ source: import_zod_openapi.z.enum(["huggingface", "manual"]).optional().describe("Where the model was downloaded from")
35
+ }).describe("An installed local GGUF model");
36
+ const OllamaModelSchema = import_zod_openapi.z.object({
37
+ name: import_zod_openapi.z.string().describe("Ollama model name (e.g., llama3.2:latest)"),
38
+ size: import_zod_openapi.z.number().optional().describe("Model size in bytes"),
39
+ digest: import_zod_openapi.z.string().optional().describe("Model digest/hash"),
40
+ modifiedAt: import_zod_openapi.z.string().optional().describe("Last modified timestamp")
41
+ }).describe("An Ollama model");
42
+ const ValidateFileRequestSchema = import_zod_openapi.z.object({
43
+ filePath: import_zod_openapi.z.string().min(1).describe("Absolute path to the GGUF file to validate")
44
+ }).describe("File validation request");
45
+ const ValidateFileResponseSchema = import_zod_openapi.z.object({
46
+ valid: import_zod_openapi.z.boolean().describe("Whether the file exists and is readable"),
47
+ sizeBytes: import_zod_openapi.z.number().optional().describe("File size in bytes if valid"),
48
+ error: import_zod_openapi.z.string().optional().describe("Error message if invalid")
49
+ }).describe("File validation response");
50
+ const listLocalModelsRoute = (0, import_zod_openapi.createRoute)({
51
+ method: "get",
52
+ path: "/models/local",
53
+ summary: "List Local Models",
54
+ description: "Returns all installed local GGUF models from ~/.dexto/models/state.json. These are models downloaded from HuggingFace or manually registered.",
55
+ tags: ["models"],
56
+ responses: {
57
+ 200: {
58
+ description: "List of installed local models",
59
+ content: {
60
+ "application/json": {
61
+ schema: import_zod_openapi.z.object({
62
+ models: import_zod_openapi.z.array(LocalModelSchema).describe("List of installed local models")
63
+ })
64
+ }
65
+ }
66
+ }
67
+ }
68
+ });
69
+ const listOllamaModelsRoute = (0, import_zod_openapi.createRoute)({
70
+ method: "get",
71
+ path: "/models/ollama",
72
+ summary: "List Ollama Models",
73
+ description: "Returns available models from the local Ollama server. Returns empty list with available=false if Ollama is not running.",
74
+ tags: ["models"],
75
+ request: {
76
+ query: import_zod_openapi.z.object({
77
+ baseURL: import_zod_openapi.z.string().url().optional().describe(`Ollama server URL (default: ${import_core.DEFAULT_OLLAMA_URL})`)
78
+ })
79
+ },
80
+ responses: {
81
+ 200: {
82
+ description: "List of Ollama models",
83
+ content: {
84
+ "application/json": {
85
+ schema: import_zod_openapi.z.object({
86
+ available: import_zod_openapi.z.boolean().describe("Whether Ollama server is running"),
87
+ version: import_zod_openapi.z.string().optional().describe("Ollama server version"),
88
+ models: import_zod_openapi.z.array(OllamaModelSchema).describe("List of available Ollama models"),
89
+ error: import_zod_openapi.z.string().optional().describe("Error message if Ollama not available")
90
+ })
91
+ }
92
+ }
93
+ }
94
+ }
95
+ });
96
+ const validateLocalFileRoute = (0, import_zod_openapi.createRoute)({
97
+ method: "post",
98
+ path: "/models/local/validate",
99
+ summary: "Validate GGUF File",
100
+ description: "Validates that a GGUF file exists and is readable. Used by Web UI to validate custom file paths before saving.",
101
+ tags: ["models"],
102
+ request: {
103
+ body: {
104
+ content: {
105
+ "application/json": {
106
+ schema: ValidateFileRequestSchema
107
+ }
108
+ }
109
+ }
110
+ },
111
+ responses: {
112
+ 200: {
113
+ description: "Validation result",
114
+ content: {
115
+ "application/json": {
116
+ schema: ValidateFileResponseSchema
117
+ }
118
+ }
119
+ }
120
+ }
121
+ });
122
+ const DeleteModelRequestSchema = import_zod_openapi.z.object({
123
+ deleteFile: import_zod_openapi.z.boolean().default(true).describe("Whether to also delete the GGUF file from disk")
124
+ }).describe("Delete model request options");
125
+ const DeleteModelResponseSchema = import_zod_openapi.z.object({
126
+ success: import_zod_openapi.z.boolean().describe("Whether the deletion was successful"),
127
+ modelId: import_zod_openapi.z.string().describe("The deleted model ID"),
128
+ fileDeleted: import_zod_openapi.z.boolean().describe("Whether the GGUF file was deleted"),
129
+ error: import_zod_openapi.z.string().optional().describe("Error message if deletion failed")
130
+ }).describe("Delete model response");
131
+ const deleteLocalModelRoute = (0, import_zod_openapi.createRoute)({
132
+ method: "delete",
133
+ path: "/models/local/{modelId}",
134
+ summary: "Delete Installed Model",
135
+ description: "Removes an installed local model from state.json. Optionally deletes the GGUF file from disk (default: true).",
136
+ tags: ["models"],
137
+ request: {
138
+ params: import_zod_openapi.z.object({
139
+ modelId: import_zod_openapi.z.string().describe("The model ID to delete")
140
+ }),
141
+ body: {
142
+ content: {
143
+ "application/json": {
144
+ schema: DeleteModelRequestSchema
145
+ }
146
+ },
147
+ required: false
148
+ }
149
+ },
150
+ responses: {
151
+ 200: {
152
+ description: "Model deleted successfully",
153
+ content: {
154
+ "application/json": {
155
+ schema: DeleteModelResponseSchema
156
+ }
157
+ }
158
+ },
159
+ 404: {
160
+ description: "Model not found",
161
+ content: {
162
+ "application/json": {
163
+ schema: DeleteModelResponseSchema
164
+ }
165
+ }
166
+ }
167
+ }
168
+ });
169
+ function createModelsRouter() {
170
+ const app = new import_zod_openapi.OpenAPIHono();
171
+ return app.openapi(listLocalModelsRoute, async (ctx) => {
172
+ const installedModels = await (0, import_agent_management.getAllInstalledModels)();
173
+ const models = installedModels.map((model) => {
174
+ const registryInfo = (0, import_core.getLocalModelById)(model.id);
175
+ return {
176
+ id: model.id,
177
+ displayName: registryInfo?.name || model.id,
178
+ filePath: model.filePath,
179
+ sizeBytes: model.sizeBytes,
180
+ contextLength: registryInfo?.contextLength,
181
+ source: model.source
182
+ };
183
+ });
184
+ return ctx.json({ models });
185
+ }).openapi(listOllamaModelsRoute, async (ctx) => {
186
+ const { baseURL } = ctx.req.valid("query");
187
+ const ollamaURL = baseURL || import_core.DEFAULT_OLLAMA_URL;
188
+ try {
189
+ const status = await (0, import_core.checkOllamaStatus)(ollamaURL);
190
+ if (!status.running) {
191
+ return ctx.json({
192
+ available: false,
193
+ models: [],
194
+ error: "Ollama server is not running"
195
+ });
196
+ }
197
+ const ollamaModels = await (0, import_core.listOllamaModels)(ollamaURL);
198
+ return ctx.json({
199
+ available: true,
200
+ version: status.version,
201
+ models: ollamaModels.map((m) => ({
202
+ name: m.name,
203
+ size: m.size,
204
+ digest: m.digest,
205
+ modifiedAt: m.modifiedAt
206
+ }))
207
+ });
208
+ } catch (error) {
209
+ return ctx.json({
210
+ available: false,
211
+ models: [],
212
+ error: error instanceof Error ? error.message : "Failed to connect to Ollama server"
213
+ });
214
+ }
215
+ }).openapi(validateLocalFileRoute, async (ctx) => {
216
+ const { filePath } = ctx.req.valid("json");
217
+ if (!filePath.startsWith("/")) {
218
+ return ctx.json({
219
+ valid: false,
220
+ error: "File path must be absolute (start with /)"
221
+ });
222
+ }
223
+ if (!filePath.endsWith(".gguf")) {
224
+ return ctx.json({
225
+ valid: false,
226
+ error: "File must have .gguf extension"
227
+ });
228
+ }
229
+ try {
230
+ const stats = await import_fs.promises.stat(filePath);
231
+ if (!stats.isFile()) {
232
+ return ctx.json({
233
+ valid: false,
234
+ error: "Path is not a file"
235
+ });
236
+ }
237
+ await import_fs.promises.access(filePath, import_fs.promises.constants.R_OK);
238
+ return ctx.json({
239
+ valid: true,
240
+ sizeBytes: stats.size
241
+ });
242
+ } catch (error) {
243
+ const nodeError = error;
244
+ if (nodeError.code === "ENOENT") {
245
+ return ctx.json({
246
+ valid: false,
247
+ error: "File not found"
248
+ });
249
+ }
250
+ if (nodeError.code === "EACCES") {
251
+ return ctx.json({
252
+ valid: false,
253
+ error: "File is not readable (permission denied)"
254
+ });
255
+ }
256
+ return ctx.json({
257
+ valid: false,
258
+ error: error instanceof Error ? error.message : "Failed to access file"
259
+ });
260
+ }
261
+ }).openapi(deleteLocalModelRoute, async (ctx) => {
262
+ const { modelId } = ctx.req.valid("param");
263
+ let deleteFile = true;
264
+ try {
265
+ const body = await ctx.req.json();
266
+ if (body && typeof body.deleteFile === "boolean") {
267
+ deleteFile = body.deleteFile;
268
+ }
269
+ } catch {
270
+ }
271
+ const model = await (0, import_agent_management.getInstalledModel)(modelId);
272
+ if (!model) {
273
+ return ctx.json(
274
+ {
275
+ success: false,
276
+ modelId,
277
+ fileDeleted: false,
278
+ error: `Model '${modelId}' not found`
279
+ },
280
+ 404
281
+ );
282
+ }
283
+ const filePath = model.filePath;
284
+ let fileDeleted = false;
285
+ if (deleteFile && filePath) {
286
+ try {
287
+ await import_fs.promises.unlink(filePath);
288
+ fileDeleted = true;
289
+ } catch (error) {
290
+ const nodeError = error;
291
+ if (nodeError.code === "ENOENT") {
292
+ fileDeleted = true;
293
+ } else {
294
+ import_core.logger.warn(
295
+ `Failed to delete GGUF file ${filePath}: ${error instanceof Error ? error.message : String(error)}`
296
+ );
297
+ }
298
+ }
299
+ }
300
+ const removed = await (0, import_agent_management.removeInstalledModel)(modelId);
301
+ if (!removed) {
302
+ return ctx.json({
303
+ success: false,
304
+ modelId,
305
+ fileDeleted,
306
+ error: "Failed to remove model from state"
307
+ });
308
+ }
309
+ return ctx.json({
310
+ success: true,
311
+ modelId,
312
+ fileDeleted
313
+ });
314
+ });
315
+ }
316
+ // Annotate the CommonJS export names for ESM import in node:
317
+ 0 && (module.exports = {
318
+ createModelsRouter
319
+ });
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Models Routes
3
+ *
4
+ * API endpoints for listing and managing local/ollama models.
5
+ * These endpoints expose model discovery that CLI does directly via function calls.
6
+ */
7
+ import { OpenAPIHono } from '@hono/zod-openapi';
8
+ export declare function createModelsRouter(): OpenAPIHono<import("hono").Env, {
9
+ "/models/local": {
10
+ $get: {
11
+ input: {};
12
+ output: {
13
+ models: {
14
+ id: string;
15
+ displayName: string;
16
+ filePath: string;
17
+ sizeBytes: number;
18
+ source?: "manual" | "huggingface" | undefined;
19
+ contextLength?: number | undefined;
20
+ }[];
21
+ };
22
+ outputFormat: "json";
23
+ status: 200;
24
+ };
25
+ };
26
+ } & {
27
+ "/models/ollama": {
28
+ $get: {
29
+ input: {
30
+ query: {
31
+ baseURL?: string | undefined;
32
+ };
33
+ };
34
+ output: {
35
+ models: {
36
+ name: string;
37
+ size?: number | undefined;
38
+ digest?: string | undefined;
39
+ modifiedAt?: string | undefined;
40
+ }[];
41
+ available: boolean;
42
+ error?: string | undefined;
43
+ version?: string | undefined;
44
+ };
45
+ outputFormat: "json";
46
+ status: 200;
47
+ };
48
+ };
49
+ } & {
50
+ "/models/local/validate": {
51
+ $post: {
52
+ input: {
53
+ json: {
54
+ filePath: string;
55
+ };
56
+ };
57
+ output: {
58
+ valid: boolean;
59
+ error?: string | undefined;
60
+ sizeBytes?: number | undefined;
61
+ };
62
+ outputFormat: "json";
63
+ status: 200;
64
+ };
65
+ };
66
+ } & {
67
+ "/models/local/:modelId": {
68
+ $delete: {
69
+ input: {
70
+ param: {
71
+ modelId: string;
72
+ };
73
+ } & {
74
+ json: {
75
+ deleteFile?: boolean | undefined;
76
+ };
77
+ };
78
+ output: {
79
+ success: boolean;
80
+ modelId: string;
81
+ fileDeleted: boolean;
82
+ error?: string | undefined;
83
+ };
84
+ outputFormat: "json";
85
+ status: 200;
86
+ } | {
87
+ input: {
88
+ param: {
89
+ modelId: string;
90
+ };
91
+ } & {
92
+ json: {
93
+ deleteFile?: boolean | undefined;
94
+ };
95
+ };
96
+ output: {
97
+ success: boolean;
98
+ modelId: string;
99
+ fileDeleted: boolean;
100
+ error?: string | undefined;
101
+ };
102
+ outputFormat: "json";
103
+ status: 404;
104
+ };
105
+ };
106
+ }, "/">;
107
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/models.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAuNhE,wBAAgB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8LjC"}