@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.
- package/dist/hono/__tests__/test-fixtures.cjs +1 -1
- package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -1
- package/dist/hono/__tests__/test-fixtures.js +1 -1
- package/dist/hono/index.cjs +41 -5
- package/dist/hono/index.d.ts +470 -456
- package/dist/hono/index.d.ts.map +1 -1
- package/dist/hono/index.js +41 -5
- package/dist/hono/routes/a2a-jsonrpc.cjs +3 -3
- package/dist/hono/routes/a2a-jsonrpc.d.ts +4 -1
- package/dist/hono/routes/a2a-jsonrpc.d.ts.map +1 -1
- package/dist/hono/routes/a2a-jsonrpc.js +3 -3
- package/dist/hono/routes/a2a-tasks.cjs +5 -5
- package/dist/hono/routes/a2a-tasks.d.ts +13 -10
- package/dist/hono/routes/a2a-tasks.d.ts.map +1 -1
- package/dist/hono/routes/a2a-tasks.js +5 -5
- package/dist/hono/routes/agents.cjs +25 -35
- package/dist/hono/routes/agents.d.ts +6 -407
- package/dist/hono/routes/agents.d.ts.map +1 -1
- package/dist/hono/routes/agents.js +25 -35
- package/dist/hono/routes/approvals.cjs +2 -2
- package/dist/hono/routes/approvals.d.ts +4 -1
- package/dist/hono/routes/approvals.d.ts.map +1 -1
- package/dist/hono/routes/approvals.js +2 -2
- package/dist/hono/routes/discovery.cjs +68 -0
- package/dist/hono/routes/discovery.d.ts +53 -0
- package/dist/hono/routes/discovery.d.ts.map +1 -0
- package/dist/hono/routes/discovery.js +44 -0
- package/dist/hono/routes/greeting.cjs +2 -2
- package/dist/hono/routes/greeting.d.ts +2 -2
- package/dist/hono/routes/greeting.d.ts.map +1 -1
- package/dist/hono/routes/greeting.js +2 -2
- package/dist/hono/routes/health.d.ts +2 -2
- package/dist/hono/routes/health.d.ts.map +1 -1
- package/dist/hono/routes/key.cjs +110 -0
- package/dist/hono/routes/key.d.ts +48 -0
- package/dist/hono/routes/key.d.ts.map +1 -0
- package/dist/hono/routes/key.js +90 -0
- package/dist/hono/routes/llm.cjs +12 -34
- package/dist/hono/routes/llm.d.ts +179 -25
- package/dist/hono/routes/llm.d.ts.map +1 -1
- package/dist/hono/routes/llm.js +12 -35
- package/dist/hono/routes/mcp.cjs +8 -8
- package/dist/hono/routes/mcp.d.ts +2 -2
- package/dist/hono/routes/mcp.d.ts.map +1 -1
- package/dist/hono/routes/mcp.js +8 -8
- package/dist/hono/routes/memory.cjs +5 -5
- package/dist/hono/routes/memory.d.ts +8 -5
- package/dist/hono/routes/memory.d.ts.map +1 -1
- package/dist/hono/routes/memory.js +5 -5
- package/dist/hono/routes/messages.cjs +4 -4
- package/dist/hono/routes/messages.d.ts +12 -12
- package/dist/hono/routes/messages.d.ts.map +1 -1
- package/dist/hono/routes/messages.js +4 -4
- package/dist/hono/routes/models.cjs +319 -0
- package/dist/hono/routes/models.d.ts +107 -0
- package/dist/hono/routes/models.d.ts.map +1 -0
- package/dist/hono/routes/models.js +305 -0
- package/dist/hono/routes/openrouter.cjs +153 -0
- package/dist/hono/routes/openrouter.d.ts +54 -0
- package/dist/hono/routes/openrouter.d.ts.map +1 -0
- package/dist/hono/routes/openrouter.js +134 -0
- package/dist/hono/routes/prompts.cjs +5 -5
- package/dist/hono/routes/prompts.d.ts +4 -1
- package/dist/hono/routes/prompts.d.ts.map +1 -1
- package/dist/hono/routes/prompts.js +5 -5
- package/dist/hono/routes/queue.cjs +4 -4
- package/dist/hono/routes/queue.d.ts +4 -1
- package/dist/hono/routes/queue.d.ts.map +1 -1
- package/dist/hono/routes/queue.js +4 -4
- package/dist/hono/routes/resources.cjs +3 -3
- package/dist/hono/routes/resources.d.ts +2 -2
- package/dist/hono/routes/resources.d.ts.map +1 -1
- package/dist/hono/routes/resources.js +3 -3
- package/dist/hono/routes/search.cjs +2 -2
- package/dist/hono/routes/search.d.ts +6 -3
- package/dist/hono/routes/search.d.ts.map +1 -1
- package/dist/hono/routes/search.js +2 -2
- package/dist/hono/routes/sessions.cjs +9 -9
- package/dist/hono/routes/sessions.d.ts +3 -3
- package/dist/hono/routes/sessions.d.ts.map +1 -1
- package/dist/hono/routes/sessions.js +9 -9
- package/dist/hono/routes/tools.cjs +126 -0
- package/dist/hono/routes/tools.d.ts +42 -0
- package/dist/hono/routes/tools.d.ts.map +1 -0
- package/dist/hono/routes/tools.js +102 -0
- package/dist/hono/routes/webhooks.cjs +4 -4
- package/dist/hono/routes/webhooks.d.ts +4 -1
- package/dist/hono/routes/webhooks.d.ts.map +1 -1
- package/dist/hono/routes/webhooks.js +4 -4
- package/dist/hono/schemas/responses.d.ts +47 -41
- package/dist/hono/schemas/responses.d.ts.map +1 -1
- package/dist/hono/start-server.cjs +102 -0
- package/dist/hono/start-server.d.ts +61 -0
- package/dist/hono/start-server.d.ts.map +1 -0
- package/dist/hono/start-server.js +78 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- 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
|
-
|
|
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
|
-
|
|
27
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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;
|
|
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"}
|