@dexto/server 1.2.5
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/LICENSE +44 -0
- package/dist/a2a/adapters/index.cjs +42 -0
- package/dist/a2a/adapters/index.d.ts +10 -0
- package/dist/a2a/adapters/index.d.ts.map +1 -0
- package/dist/a2a/adapters/index.js +12 -0
- package/dist/a2a/adapters/message.cjs +193 -0
- package/dist/a2a/adapters/message.d.ts +50 -0
- package/dist/a2a/adapters/message.d.ts.map +1 -0
- package/dist/a2a/adapters/message.js +167 -0
- package/dist/a2a/adapters/state.cjs +57 -0
- package/dist/a2a/adapters/state.d.ts +36 -0
- package/dist/a2a/adapters/state.d.ts.map +1 -0
- package/dist/a2a/adapters/state.js +32 -0
- package/dist/a2a/adapters/task-view.cjs +85 -0
- package/dist/a2a/adapters/task-view.d.ts +58 -0
- package/dist/a2a/adapters/task-view.d.ts.map +1 -0
- package/dist/a2a/adapters/task-view.js +60 -0
- package/dist/a2a/index.cjs +51 -0
- package/dist/a2a/index.d.ts +15 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +30 -0
- package/dist/a2a/jsonrpc/index.cjs +38 -0
- package/dist/a2a/jsonrpc/index.d.ts +11 -0
- package/dist/a2a/jsonrpc/index.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/index.js +10 -0
- package/dist/a2a/jsonrpc/methods.cjs +183 -0
- package/dist/a2a/jsonrpc/methods.d.ts +110 -0
- package/dist/a2a/jsonrpc/methods.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/methods.js +159 -0
- package/dist/a2a/jsonrpc/server.cjs +199 -0
- package/dist/a2a/jsonrpc/server.d.ts +100 -0
- package/dist/a2a/jsonrpc/server.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/server.js +175 -0
- package/dist/a2a/jsonrpc/types.cjs +47 -0
- package/dist/a2a/jsonrpc/types.d.ts +91 -0
- package/dist/a2a/jsonrpc/types.d.ts.map +1 -0
- package/dist/a2a/jsonrpc/types.js +21 -0
- package/dist/a2a/types.cjs +16 -0
- package/dist/a2a/types.d.ts +250 -0
- package/dist/a2a/types.d.ts.map +1 -0
- package/dist/a2a/types.js +0 -0
- package/dist/approval/approval-coordinator.cjs +87 -0
- package/dist/approval/approval-coordinator.d.ts +52 -0
- package/dist/approval/approval-coordinator.d.ts.map +1 -0
- package/dist/approval/approval-coordinator.js +63 -0
- package/dist/approval/manual-approval-handler.cjs +100 -0
- package/dist/approval/manual-approval-handler.d.ts +32 -0
- package/dist/approval/manual-approval-handler.d.ts.map +1 -0
- package/dist/approval/manual-approval-handler.js +76 -0
- package/dist/events/a2a-sse-subscriber.cjs +271 -0
- package/dist/events/a2a-sse-subscriber.d.ts +94 -0
- package/dist/events/a2a-sse-subscriber.d.ts.map +1 -0
- package/dist/events/a2a-sse-subscriber.js +247 -0
- package/dist/events/types.cjs +16 -0
- package/dist/events/types.d.ts +15 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +0 -0
- package/dist/events/webhook-subscriber.cjs +301 -0
- package/dist/events/webhook-subscriber.d.ts +64 -0
- package/dist/events/webhook-subscriber.d.ts.map +1 -0
- package/dist/events/webhook-subscriber.js +269 -0
- package/dist/events/webhook-types.cjs +16 -0
- package/dist/events/webhook-types.d.ts +91 -0
- package/dist/events/webhook-types.d.ts.map +1 -0
- package/dist/events/webhook-types.js +0 -0
- package/dist/hono/__tests__/test-fixtures.cjs +236 -0
- package/dist/hono/__tests__/test-fixtures.d.ts +65 -0
- package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -0
- package/dist/hono/__tests__/test-fixtures.js +197 -0
- package/dist/hono/index.cjs +166 -0
- package/dist/hono/index.d.ts +2783 -0
- package/dist/hono/index.d.ts.map +1 -0
- package/dist/hono/index.js +141 -0
- package/dist/hono/middleware/auth.cjs +75 -0
- package/dist/hono/middleware/auth.d.ts +3 -0
- package/dist/hono/middleware/auth.d.ts.map +1 -0
- package/dist/hono/middleware/auth.js +51 -0
- package/dist/hono/middleware/cors.cjs +57 -0
- package/dist/hono/middleware/cors.d.ts +9 -0
- package/dist/hono/middleware/cors.d.ts.map +1 -0
- package/dist/hono/middleware/cors.js +33 -0
- package/dist/hono/middleware/error.cjs +131 -0
- package/dist/hono/middleware/error.d.ts +5 -0
- package/dist/hono/middleware/error.d.ts.map +1 -0
- package/dist/hono/middleware/error.js +105 -0
- package/dist/hono/middleware/redaction.cjs +45 -0
- package/dist/hono/middleware/redaction.d.ts +4 -0
- package/dist/hono/middleware/redaction.d.ts.map +1 -0
- package/dist/hono/middleware/redaction.js +20 -0
- package/dist/hono/node/index.cjs +139 -0
- package/dist/hono/node/index.d.ts +19 -0
- package/dist/hono/node/index.d.ts.map +1 -0
- package/dist/hono/node/index.js +115 -0
- package/dist/hono/routes/a2a-jsonrpc.cjs +119 -0
- package/dist/hono/routes/a2a-jsonrpc.d.ts +46 -0
- package/dist/hono/routes/a2a-jsonrpc.d.ts.map +1 -0
- package/dist/hono/routes/a2a-jsonrpc.js +95 -0
- package/dist/hono/routes/a2a-tasks.cjs +315 -0
- package/dist/hono/routes/a2a-tasks.d.ts +530 -0
- package/dist/hono/routes/a2a-tasks.d.ts.map +1 -0
- package/dist/hono/routes/a2a-tasks.js +291 -0
- package/dist/hono/routes/a2a.cjs +36 -0
- package/dist/hono/routes/a2a.d.ts +4 -0
- package/dist/hono/routes/a2a.d.ts.map +1 -0
- package/dist/hono/routes/a2a.js +12 -0
- package/dist/hono/routes/agents.cjs +735 -0
- package/dist/hono/routes/agents.d.ts +650 -0
- package/dist/hono/routes/agents.d.ts.map +1 -0
- package/dist/hono/routes/agents.js +711 -0
- package/dist/hono/routes/approvals.cjs +125 -0
- package/dist/hono/routes/approvals.d.ts +89 -0
- package/dist/hono/routes/approvals.d.ts.map +1 -0
- package/dist/hono/routes/approvals.js +101 -0
- package/dist/hono/routes/greeting.cjs +60 -0
- package/dist/hono/routes/greeting.d.ts +19 -0
- package/dist/hono/routes/greeting.d.ts.map +1 -0
- package/dist/hono/routes/greeting.js +36 -0
- package/dist/hono/routes/health.cjs +45 -0
- package/dist/hono/routes/health.d.ts +17 -0
- package/dist/hono/routes/health.d.ts.map +1 -0
- package/dist/hono/routes/health.js +21 -0
- package/dist/hono/routes/llm.cjs +298 -0
- package/dist/hono/routes/llm.d.ts +294 -0
- package/dist/hono/routes/llm.d.ts.map +1 -0
- package/dist/hono/routes/llm.js +287 -0
- package/dist/hono/routes/mcp.cjs +356 -0
- package/dist/hono/routes/mcp.d.ts +246 -0
- package/dist/hono/routes/mcp.d.ts.map +1 -0
- package/dist/hono/routes/mcp.js +332 -0
- package/dist/hono/routes/memory.cjs +192 -0
- package/dist/hono/routes/memory.d.ts +146 -0
- package/dist/hono/routes/memory.d.ts.map +1 -0
- package/dist/hono/routes/memory.js +168 -0
- package/dist/hono/routes/messages.cjs +320 -0
- package/dist/hono/routes/messages.d.ts +163 -0
- package/dist/hono/routes/messages.d.ts.map +1 -0
- package/dist/hono/routes/messages.js +296 -0
- package/dist/hono/routes/prompts.cjs +228 -0
- package/dist/hono/routes/prompts.d.ts +150 -0
- package/dist/hono/routes/prompts.d.ts.map +1 -0
- package/dist/hono/routes/prompts.js +204 -0
- package/dist/hono/routes/resources.cjs +110 -0
- package/dist/hono/routes/resources.d.ts +76 -0
- package/dist/hono/routes/resources.d.ts.map +1 -0
- package/dist/hono/routes/resources.js +86 -0
- package/dist/hono/routes/search.cjs +109 -0
- package/dist/hono/routes/search.d.ts +137 -0
- package/dist/hono/routes/search.d.ts.map +1 -0
- package/dist/hono/routes/search.js +85 -0
- package/dist/hono/routes/sessions.cjs +366 -0
- package/dist/hono/routes/sessions.d.ts +229 -0
- package/dist/hono/routes/sessions.d.ts.map +1 -0
- package/dist/hono/routes/sessions.js +342 -0
- package/dist/hono/routes/webhooks.cjs +228 -0
- package/dist/hono/routes/webhooks.d.ts +127 -0
- package/dist/hono/routes/webhooks.d.ts.map +1 -0
- package/dist/hono/routes/webhooks.js +204 -0
- package/dist/hono/schemas/responses.cjs +276 -0
- package/dist/hono/schemas/responses.d.ts +1418 -0
- package/dist/hono/schemas/responses.d.ts.map +1 -0
- package/dist/hono/schemas/responses.js +227 -0
- package/dist/hono/types.cjs +16 -0
- package/dist/hono/types.d.ts +6 -0
- package/dist/hono/types.d.ts.map +1 -0
- package/dist/hono/types.js +0 -0
- package/dist/index.cjs +38 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/mcp/mcp-handler.cjs +145 -0
- package/dist/mcp/mcp-handler.d.ts +14 -0
- package/dist/mcp/mcp-handler.d.ts.map +1 -0
- package/dist/mcp/mcp-handler.js +118 -0
- package/package.json +59 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
2
|
+
import { streamSSE } from "hono/streaming";
|
|
3
|
+
import { LLM_PROVIDERS, LLM_ROUTERS } from "@dexto/core";
|
|
4
|
+
import { TokenUsageSchema } from "../schemas/responses.js";
|
|
5
|
+
const MessageBodySchema = z.object({
|
|
6
|
+
message: z.string().optional().describe("The user message text"),
|
|
7
|
+
sessionId: z.string().min(1, "Session ID is required").describe("The session to use for this message"),
|
|
8
|
+
imageData: z.object({
|
|
9
|
+
base64: z.string().describe("Base64-encoded image data"),
|
|
10
|
+
mimeType: z.string().describe("The MIME type of the image (e.g., image/png)")
|
|
11
|
+
}).optional().describe("Optional image data to include with the message"),
|
|
12
|
+
fileData: z.object({
|
|
13
|
+
base64: z.string().describe("Base64-encoded file data"),
|
|
14
|
+
mimeType: z.string().describe("The MIME type of the file (e.g., application/pdf)"),
|
|
15
|
+
filename: z.string().optional().describe("The filename")
|
|
16
|
+
}).optional().describe("Optional file data to include with the message")
|
|
17
|
+
}).refine(
|
|
18
|
+
(data) => {
|
|
19
|
+
const msg = (data.message ?? "").trim();
|
|
20
|
+
return msg.length > 0 || !!data.imageData || !!data.fileData;
|
|
21
|
+
},
|
|
22
|
+
{ message: "Must provide either message text, image data, or file data" }
|
|
23
|
+
).describe("Request body for sending a message to the agent");
|
|
24
|
+
const ResetBodySchema = z.object({
|
|
25
|
+
sessionId: z.string().min(1, "Session ID is required").describe("The ID of the session to reset")
|
|
26
|
+
}).describe("Request body for resetting a conversation");
|
|
27
|
+
function createMessagesRouter(getAgent, approvalCoordinator) {
|
|
28
|
+
const app = new OpenAPIHono();
|
|
29
|
+
const messageRoute = createRoute({
|
|
30
|
+
method: "post",
|
|
31
|
+
path: "/message",
|
|
32
|
+
summary: "Send Message (async)",
|
|
33
|
+
description: "Sends a message and returns immediately. The full response will be sent over SSE",
|
|
34
|
+
tags: ["messages"],
|
|
35
|
+
request: {
|
|
36
|
+
body: {
|
|
37
|
+
content: { "application/json": { schema: MessageBodySchema } }
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
responses: {
|
|
41
|
+
202: {
|
|
42
|
+
description: "Message accepted for async processing; subscribe to SSE for results",
|
|
43
|
+
content: {
|
|
44
|
+
"application/json": {
|
|
45
|
+
schema: z.object({
|
|
46
|
+
accepted: z.literal(true).describe("Indicates request was accepted"),
|
|
47
|
+
sessionId: z.string().describe("Session ID used for this message")
|
|
48
|
+
}).strict()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
400: { description: "Validation error" }
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const messageSyncRoute = createRoute({
|
|
56
|
+
method: "post",
|
|
57
|
+
path: "/message-sync",
|
|
58
|
+
summary: "Send Message (sync)",
|
|
59
|
+
description: "Sends a message and waits for the full response",
|
|
60
|
+
tags: ["messages"],
|
|
61
|
+
request: {
|
|
62
|
+
body: { content: { "application/json": { schema: MessageBodySchema } } }
|
|
63
|
+
},
|
|
64
|
+
responses: {
|
|
65
|
+
200: {
|
|
66
|
+
description: "Synchronous response",
|
|
67
|
+
content: {
|
|
68
|
+
"application/json": {
|
|
69
|
+
schema: z.object({
|
|
70
|
+
response: z.string().describe("Agent response text"),
|
|
71
|
+
sessionId: z.string().describe("Session ID used for this message"),
|
|
72
|
+
tokenUsage: TokenUsageSchema.optional().describe("Token usage statistics"),
|
|
73
|
+
reasoning: z.string().optional().describe("Extended thinking content from reasoning models"),
|
|
74
|
+
model: z.string().optional().describe("Model used for this response"),
|
|
75
|
+
provider: z.enum(LLM_PROVIDERS).optional().describe("LLM provider"),
|
|
76
|
+
router: z.enum(LLM_ROUTERS).optional().describe("Router used (e.g., vercel)")
|
|
77
|
+
}).strict()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
400: { description: "Validation error" }
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const resetRoute = createRoute({
|
|
85
|
+
method: "post",
|
|
86
|
+
path: "/reset",
|
|
87
|
+
summary: "Reset Conversation",
|
|
88
|
+
description: "Resets the conversation history for a given session",
|
|
89
|
+
tags: ["messages"],
|
|
90
|
+
request: {
|
|
91
|
+
body: { content: { "application/json": { schema: ResetBodySchema } } }
|
|
92
|
+
},
|
|
93
|
+
responses: {
|
|
94
|
+
200: {
|
|
95
|
+
description: "Reset initiated",
|
|
96
|
+
content: {
|
|
97
|
+
"application/json": {
|
|
98
|
+
schema: z.object({
|
|
99
|
+
status: z.string().describe("Status message indicating reset was initiated"),
|
|
100
|
+
sessionId: z.string().describe("Session ID that was reset")
|
|
101
|
+
}).strict()
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const messageStreamRoute = createRoute({
|
|
108
|
+
method: "post",
|
|
109
|
+
path: "/message-stream",
|
|
110
|
+
summary: "Stream message response",
|
|
111
|
+
description: "Sends a message and streams the response via Server-Sent Events (SSE). Returns SSE stream directly in response. Events include llm:thinking, llm:chunk, llm:tool-call, llm:tool-result, llm:response, and llm:error.",
|
|
112
|
+
tags: ["messages"],
|
|
113
|
+
request: {
|
|
114
|
+
body: {
|
|
115
|
+
content: { "application/json": { schema: MessageBodySchema } }
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
responses: {
|
|
119
|
+
200: {
|
|
120
|
+
description: "SSE stream of agent events. Standard SSE format with event type and JSON data.",
|
|
121
|
+
headers: {
|
|
122
|
+
"Content-Type": {
|
|
123
|
+
description: "SSE content type",
|
|
124
|
+
schema: { type: "string", example: "text/event-stream" }
|
|
125
|
+
},
|
|
126
|
+
"Cache-Control": {
|
|
127
|
+
description: "Disable caching for stream",
|
|
128
|
+
schema: { type: "string", example: "no-cache" }
|
|
129
|
+
},
|
|
130
|
+
Connection: {
|
|
131
|
+
description: "Keep connection alive for streaming",
|
|
132
|
+
schema: { type: "string", example: "keep-alive" }
|
|
133
|
+
},
|
|
134
|
+
"X-Accel-Buffering": {
|
|
135
|
+
description: "Disable nginx buffering",
|
|
136
|
+
schema: { type: "string", example: "no" }
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
content: {
|
|
140
|
+
"text/event-stream": {
|
|
141
|
+
schema: z.string().describe(
|
|
142
|
+
"Server-Sent Events stream. Events: llm:thinking (start), llm:chunk (text fragments), llm:tool-call (tool execution), llm:tool-result (tool output), llm:response (final), llm:error (errors)"
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
400: { description: "Validation error" }
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return app.openapi(messageRoute, async (ctx) => {
|
|
151
|
+
const agent = getAgent();
|
|
152
|
+
agent.logger.info("Received message via POST /api/message");
|
|
153
|
+
const { message, sessionId, imageData, fileData } = ctx.req.valid("json");
|
|
154
|
+
const imageDataInput = imageData ? { image: imageData.base64, mimeType: imageData.mimeType } : void 0;
|
|
155
|
+
const fileDataInput = fileData ? {
|
|
156
|
+
data: fileData.base64,
|
|
157
|
+
mimeType: fileData.mimeType,
|
|
158
|
+
...fileData.filename && { filename: fileData.filename }
|
|
159
|
+
} : void 0;
|
|
160
|
+
if (imageDataInput) agent.logger.info("Image data included in message.");
|
|
161
|
+
if (fileDataInput) agent.logger.info("File data included in message.");
|
|
162
|
+
agent.logger.info(`Message for session: ${sessionId}`);
|
|
163
|
+
agent.run(message || "", imageDataInput, fileDataInput, sessionId, false).catch((error) => {
|
|
164
|
+
agent.logger.error(
|
|
165
|
+
`Error in async message processing: ${error instanceof Error ? error.message : String(error)}`
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
return ctx.json({ accepted: true, sessionId }, 202);
|
|
169
|
+
}).openapi(messageSyncRoute, async (ctx) => {
|
|
170
|
+
const agent = getAgent();
|
|
171
|
+
agent.logger.info("Received message via POST /api/message-sync");
|
|
172
|
+
const { message, sessionId, imageData, fileData } = ctx.req.valid("json");
|
|
173
|
+
const imageDataInput = imageData ? { image: imageData.base64, mimeType: imageData.mimeType } : void 0;
|
|
174
|
+
const fileDataInput = fileData ? {
|
|
175
|
+
data: fileData.base64,
|
|
176
|
+
mimeType: fileData.mimeType,
|
|
177
|
+
...fileData.filename && { filename: fileData.filename }
|
|
178
|
+
} : void 0;
|
|
179
|
+
if (imageDataInput) agent.logger.info("Image data included in message.");
|
|
180
|
+
if (fileDataInput) agent.logger.info("File data included in message.");
|
|
181
|
+
agent.logger.info(`Message for session: ${sessionId}`);
|
|
182
|
+
const result = await agent.generate(message || "", {
|
|
183
|
+
sessionId,
|
|
184
|
+
imageData: imageDataInput,
|
|
185
|
+
fileData: fileDataInput
|
|
186
|
+
});
|
|
187
|
+
const llmConfig = agent.stateManager.getLLMConfig(sessionId);
|
|
188
|
+
return ctx.json({
|
|
189
|
+
response: result.content,
|
|
190
|
+
sessionId: result.sessionId,
|
|
191
|
+
tokenUsage: result.usage,
|
|
192
|
+
reasoning: result.reasoning,
|
|
193
|
+
model: llmConfig.model,
|
|
194
|
+
provider: llmConfig.provider,
|
|
195
|
+
router: "vercel"
|
|
196
|
+
// Hardcoded for now since we only use Vercel AI SDK
|
|
197
|
+
});
|
|
198
|
+
}).openapi(resetRoute, async (ctx) => {
|
|
199
|
+
const agent = getAgent();
|
|
200
|
+
agent.logger.info("Received request via POST /api/reset");
|
|
201
|
+
const { sessionId } = ctx.req.valid("json");
|
|
202
|
+
await agent.resetConversation(sessionId);
|
|
203
|
+
return ctx.json({ status: "reset initiated", sessionId });
|
|
204
|
+
}).openapi(messageStreamRoute, async (ctx) => {
|
|
205
|
+
const agent = getAgent();
|
|
206
|
+
const body = ctx.req.valid("json");
|
|
207
|
+
const { message = "", sessionId, imageData, fileData } = body;
|
|
208
|
+
const imageDataInput = imageData ? { image: imageData.base64, mimeType: imageData.mimeType } : void 0;
|
|
209
|
+
const fileDataInput = fileData ? {
|
|
210
|
+
data: fileData.base64,
|
|
211
|
+
mimeType: fileData.mimeType,
|
|
212
|
+
...fileData.filename && { filename: fileData.filename }
|
|
213
|
+
} : void 0;
|
|
214
|
+
const abortController = new AbortController();
|
|
215
|
+
const { signal } = abortController;
|
|
216
|
+
const iterator = await agent.stream(message, {
|
|
217
|
+
sessionId,
|
|
218
|
+
imageData: imageDataInput,
|
|
219
|
+
fileData: fileDataInput,
|
|
220
|
+
signal
|
|
221
|
+
});
|
|
222
|
+
return streamSSE(ctx, async (stream) => {
|
|
223
|
+
const pendingApprovalEvents = [];
|
|
224
|
+
if (approvalCoordinator) {
|
|
225
|
+
approvalCoordinator.onRequest(
|
|
226
|
+
(request) => {
|
|
227
|
+
if (request.sessionId === sessionId) {
|
|
228
|
+
pendingApprovalEvents.push({
|
|
229
|
+
event: "approval:request",
|
|
230
|
+
data: request
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{ signal }
|
|
235
|
+
);
|
|
236
|
+
approvalCoordinator.onResponse(
|
|
237
|
+
(response) => {
|
|
238
|
+
if (response.sessionId === sessionId) {
|
|
239
|
+
pendingApprovalEvents.push({
|
|
240
|
+
event: "approval:response",
|
|
241
|
+
data: response
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
{ signal }
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
for await (const event of iterator) {
|
|
250
|
+
while (pendingApprovalEvents.length > 0) {
|
|
251
|
+
const approvalEvent = pendingApprovalEvents.shift();
|
|
252
|
+
await stream.writeSSE({
|
|
253
|
+
event: approvalEvent.event,
|
|
254
|
+
data: JSON.stringify(approvalEvent.data)
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
const eventData = event.type === "llm:error" && event.error instanceof Error ? {
|
|
258
|
+
...event,
|
|
259
|
+
error: {
|
|
260
|
+
message: event.error.message,
|
|
261
|
+
name: event.error.name,
|
|
262
|
+
stack: event.error.stack
|
|
263
|
+
}
|
|
264
|
+
} : event;
|
|
265
|
+
await stream.writeSSE({
|
|
266
|
+
event: event.type,
|
|
267
|
+
data: JSON.stringify(eventData)
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
while (pendingApprovalEvents.length > 0) {
|
|
271
|
+
const approvalEvent = pendingApprovalEvents.shift();
|
|
272
|
+
await stream.writeSSE({
|
|
273
|
+
event: approvalEvent.event,
|
|
274
|
+
data: JSON.stringify(approvalEvent.data)
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
} catch (error) {
|
|
278
|
+
await stream.writeSSE({
|
|
279
|
+
event: "llm:error",
|
|
280
|
+
data: JSON.stringify({
|
|
281
|
+
error: {
|
|
282
|
+
message: error instanceof Error ? error.message : String(error)
|
|
283
|
+
},
|
|
284
|
+
recoverable: false,
|
|
285
|
+
sessionId
|
|
286
|
+
})
|
|
287
|
+
});
|
|
288
|
+
} finally {
|
|
289
|
+
abortController.abort();
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
export {
|
|
295
|
+
createMessagesRouter
|
|
296
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
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 prompts_exports = {};
|
|
20
|
+
__export(prompts_exports, {
|
|
21
|
+
createPromptsRouter: () => createPromptsRouter
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(prompts_exports);
|
|
24
|
+
var import_zod_openapi = require("@hono/zod-openapi");
|
|
25
|
+
var import_core = require("@dexto/core");
|
|
26
|
+
var import_responses = require("../schemas/responses.js");
|
|
27
|
+
const CustomPromptRequestSchema = import_zod_openapi.z.object({
|
|
28
|
+
name: import_zod_openapi.z.string().min(1, "Prompt name is required").describe("Unique name for the custom prompt"),
|
|
29
|
+
title: import_zod_openapi.z.string().optional().describe("Display title for the prompt"),
|
|
30
|
+
description: import_zod_openapi.z.string().optional().describe("Description of what the prompt does"),
|
|
31
|
+
content: import_zod_openapi.z.string().min(1, "Prompt content is required").describe("The prompt content text (can include {{argumentName}} placeholders)"),
|
|
32
|
+
arguments: import_zod_openapi.z.array(
|
|
33
|
+
import_zod_openapi.z.object({
|
|
34
|
+
name: import_zod_openapi.z.string().min(1, "Argument name is required").describe("Argument name"),
|
|
35
|
+
description: import_zod_openapi.z.string().optional().describe("Argument description"),
|
|
36
|
+
required: import_zod_openapi.z.boolean().optional().describe("Whether the argument is required")
|
|
37
|
+
}).strict()
|
|
38
|
+
).optional().describe("Array of argument definitions"),
|
|
39
|
+
resource: import_zod_openapi.z.object({
|
|
40
|
+
base64: import_zod_openapi.z.string().min(1, "Resource data is required").describe("Base64-encoded resource data"),
|
|
41
|
+
mimeType: import_zod_openapi.z.string().min(1, "Resource MIME type is required").describe("MIME type of the resource (e.g., text/plain, application/pdf)"),
|
|
42
|
+
filename: import_zod_openapi.z.string().optional().describe("Resource filename")
|
|
43
|
+
}).strict().optional().describe("Attach a resource to this prompt")
|
|
44
|
+
}).strict().describe("Request body for creating a custom prompt with optional resource attachment");
|
|
45
|
+
const PromptNameParamSchema = import_zod_openapi.z.object({
|
|
46
|
+
name: import_zod_openapi.z.string().min(1, "Prompt name is required").describe("The prompt name")
|
|
47
|
+
}).describe("Path parameters for prompt endpoints");
|
|
48
|
+
const ResolvePromptQuerySchema = import_zod_openapi.z.object({
|
|
49
|
+
context: import_zod_openapi.z.string().optional().describe("Additional context for prompt resolution"),
|
|
50
|
+
args: import_zod_openapi.z.string().optional().describe("Arguments to substitute in the prompt template (pass as a JSON string)")
|
|
51
|
+
}).describe("Query parameters for resolving prompt templates");
|
|
52
|
+
function createPromptsRouter(getAgent) {
|
|
53
|
+
const app = new import_zod_openapi.OpenAPIHono();
|
|
54
|
+
const listRoute = (0, import_zod_openapi.createRoute)({
|
|
55
|
+
method: "get",
|
|
56
|
+
path: "/prompts",
|
|
57
|
+
summary: "List Prompts",
|
|
58
|
+
description: "Retrieves all available prompts, including both built-in and custom prompts",
|
|
59
|
+
tags: ["prompts"],
|
|
60
|
+
responses: {
|
|
61
|
+
200: {
|
|
62
|
+
description: "List all prompts",
|
|
63
|
+
content: {
|
|
64
|
+
"application/json": {
|
|
65
|
+
schema: import_zod_openapi.z.object({
|
|
66
|
+
prompts: import_zod_openapi.z.array(import_responses.PromptInfoSchema).describe("Array of available prompts")
|
|
67
|
+
}).strict().describe("Prompts list response")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const createCustomRoute = (0, import_zod_openapi.createRoute)({
|
|
74
|
+
method: "post",
|
|
75
|
+
path: "/prompts/custom",
|
|
76
|
+
summary: "Create Custom Prompt",
|
|
77
|
+
description: "Creates a new custom prompt with optional resource attachment. Maximum request size: 10MB",
|
|
78
|
+
tags: ["prompts"],
|
|
79
|
+
request: {
|
|
80
|
+
body: {
|
|
81
|
+
content: {
|
|
82
|
+
"application/json": {
|
|
83
|
+
schema: CustomPromptRequestSchema
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
responses: {
|
|
89
|
+
201: {
|
|
90
|
+
description: "Custom prompt created",
|
|
91
|
+
content: {
|
|
92
|
+
"application/json": {
|
|
93
|
+
schema: import_zod_openapi.z.object({
|
|
94
|
+
prompt: import_responses.PromptInfoSchema.describe("Created prompt information")
|
|
95
|
+
}).strict().describe("Create prompt response")
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const deleteCustomRoute = (0, import_zod_openapi.createRoute)({
|
|
102
|
+
method: "delete",
|
|
103
|
+
path: "/prompts/custom/{name}",
|
|
104
|
+
summary: "Delete Custom Prompt",
|
|
105
|
+
description: "Permanently deletes a custom prompt. Built-in prompts cannot be deleted",
|
|
106
|
+
tags: ["prompts"],
|
|
107
|
+
request: {
|
|
108
|
+
params: import_zod_openapi.z.object({
|
|
109
|
+
name: import_zod_openapi.z.string().min(1, "Prompt name is required").describe("The prompt name")
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
responses: {
|
|
113
|
+
204: { description: "Prompt deleted" }
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
const getPromptRoute = (0, import_zod_openapi.createRoute)({
|
|
117
|
+
method: "get",
|
|
118
|
+
path: "/prompts/{name}",
|
|
119
|
+
summary: "Get Prompt Definition",
|
|
120
|
+
description: "Fetches the definition for a specific prompt",
|
|
121
|
+
tags: ["prompts"],
|
|
122
|
+
request: {
|
|
123
|
+
params: PromptNameParamSchema
|
|
124
|
+
},
|
|
125
|
+
responses: {
|
|
126
|
+
200: {
|
|
127
|
+
description: "Prompt definition",
|
|
128
|
+
content: {
|
|
129
|
+
"application/json": {
|
|
130
|
+
schema: import_zod_openapi.z.object({
|
|
131
|
+
definition: import_responses.PromptDefinitionSchema.describe("Prompt definition")
|
|
132
|
+
}).strict().describe("Get prompt definition response")
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
404: { description: "Prompt not found" }
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
const resolvePromptRoute = (0, import_zod_openapi.createRoute)({
|
|
140
|
+
method: "get",
|
|
141
|
+
path: "/prompts/{name}/resolve",
|
|
142
|
+
summary: "Resolve Prompt",
|
|
143
|
+
description: "Resolves a prompt template with provided arguments and returns the final text with resources",
|
|
144
|
+
tags: ["prompts"],
|
|
145
|
+
request: {
|
|
146
|
+
params: PromptNameParamSchema,
|
|
147
|
+
query: ResolvePromptQuerySchema
|
|
148
|
+
},
|
|
149
|
+
responses: {
|
|
150
|
+
200: {
|
|
151
|
+
description: "Resolved prompt content",
|
|
152
|
+
content: {
|
|
153
|
+
"application/json": {
|
|
154
|
+
schema: import_zod_openapi.z.object({
|
|
155
|
+
text: import_zod_openapi.z.string().describe("Resolved prompt text"),
|
|
156
|
+
resources: import_zod_openapi.z.array(import_zod_openapi.z.string()).describe("Array of resource identifiers")
|
|
157
|
+
}).strict().describe("Resolve prompt response")
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
404: { description: "Prompt not found" }
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return app.openapi(listRoute, async (ctx) => {
|
|
165
|
+
const agent = getAgent();
|
|
166
|
+
const prompts = await agent.listPrompts();
|
|
167
|
+
const list = Object.values(prompts);
|
|
168
|
+
return ctx.json({ prompts: list });
|
|
169
|
+
}).openapi(createCustomRoute, async (ctx) => {
|
|
170
|
+
const agent = getAgent();
|
|
171
|
+
const payload = ctx.req.valid("json");
|
|
172
|
+
const promptArguments = payload.arguments?.map((arg) => ({
|
|
173
|
+
name: arg.name,
|
|
174
|
+
...arg.description ? { description: arg.description } : {},
|
|
175
|
+
...typeof arg.required === "boolean" ? { required: arg.required } : {}
|
|
176
|
+
})).filter(Boolean);
|
|
177
|
+
const createPayload = {
|
|
178
|
+
name: payload.name,
|
|
179
|
+
content: payload.content,
|
|
180
|
+
...payload.title ? { title: payload.title } : {},
|
|
181
|
+
...payload.description ? { description: payload.description } : {},
|
|
182
|
+
...promptArguments && promptArguments.length > 0 ? { arguments: promptArguments } : {},
|
|
183
|
+
...payload.resource ? {
|
|
184
|
+
resource: {
|
|
185
|
+
base64: payload.resource.base64,
|
|
186
|
+
mimeType: payload.resource.mimeType,
|
|
187
|
+
...payload.resource.filename ? { filename: payload.resource.filename } : {}
|
|
188
|
+
}
|
|
189
|
+
} : {}
|
|
190
|
+
};
|
|
191
|
+
const prompt = await agent.createCustomPrompt(createPayload);
|
|
192
|
+
return ctx.json({ prompt }, 201);
|
|
193
|
+
}).openapi(deleteCustomRoute, async (ctx) => {
|
|
194
|
+
const agent = getAgent();
|
|
195
|
+
const { name } = ctx.req.valid("param");
|
|
196
|
+
await agent.deleteCustomPrompt(name);
|
|
197
|
+
return ctx.body(null, 204);
|
|
198
|
+
}).openapi(getPromptRoute, async (ctx) => {
|
|
199
|
+
const agent = getAgent();
|
|
200
|
+
const { name } = ctx.req.valid("param");
|
|
201
|
+
const definition = await agent.getPromptDefinition(name);
|
|
202
|
+
if (!definition) throw import_core.PromptError.notFound(name);
|
|
203
|
+
return ctx.json({ definition });
|
|
204
|
+
}).openapi(resolvePromptRoute, async (ctx) => {
|
|
205
|
+
const agent = getAgent();
|
|
206
|
+
const { name } = ctx.req.valid("param");
|
|
207
|
+
const { context, args: argsString } = ctx.req.valid("query");
|
|
208
|
+
let parsedArgs;
|
|
209
|
+
if (argsString) {
|
|
210
|
+
try {
|
|
211
|
+
const parsed = JSON.parse(argsString);
|
|
212
|
+
if (parsed && typeof parsed === "object") {
|
|
213
|
+
parsedArgs = parsed;
|
|
214
|
+
}
|
|
215
|
+
} catch {
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const options = {};
|
|
219
|
+
if (context !== void 0) options.context = context;
|
|
220
|
+
if (parsedArgs !== void 0) options.args = parsedArgs;
|
|
221
|
+
const result = await agent.resolvePrompt(name, options);
|
|
222
|
+
return ctx.json({ text: result.text, resources: result.resources });
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
226
|
+
0 && (module.exports = {
|
|
227
|
+
createPromptsRouter
|
|
228
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
2
|
+
import type { DextoAgent } from '@dexto/core';
|
|
3
|
+
export declare function createPromptsRouter(getAgent: () => DextoAgent): OpenAPIHono<import("hono").Env, {
|
|
4
|
+
"/prompts": {
|
|
5
|
+
$get: {
|
|
6
|
+
input: {};
|
|
7
|
+
output: {
|
|
8
|
+
prompts: {
|
|
9
|
+
name: string;
|
|
10
|
+
source: "file" | "custom" | "mcp" | "starter";
|
|
11
|
+
description?: string | undefined;
|
|
12
|
+
title?: string | undefined;
|
|
13
|
+
arguments?: {
|
|
14
|
+
name: string;
|
|
15
|
+
description?: string | undefined;
|
|
16
|
+
required?: boolean | undefined;
|
|
17
|
+
}[] | undefined;
|
|
18
|
+
metadata?: {
|
|
19
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
20
|
+
} | undefined;
|
|
21
|
+
}[];
|
|
22
|
+
};
|
|
23
|
+
outputFormat: "json";
|
|
24
|
+
status: 200;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
} & {
|
|
28
|
+
"/prompts/custom": {
|
|
29
|
+
$post: {
|
|
30
|
+
input: {
|
|
31
|
+
json: {
|
|
32
|
+
content: string;
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string | undefined;
|
|
35
|
+
title?: string | undefined;
|
|
36
|
+
arguments?: {
|
|
37
|
+
name: string;
|
|
38
|
+
description?: string | undefined;
|
|
39
|
+
required?: boolean | undefined;
|
|
40
|
+
}[] | undefined;
|
|
41
|
+
resource?: {
|
|
42
|
+
mimeType: string;
|
|
43
|
+
base64: string;
|
|
44
|
+
filename?: string | undefined;
|
|
45
|
+
} | undefined;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
output: {
|
|
49
|
+
prompt: {
|
|
50
|
+
name: string;
|
|
51
|
+
source: "file" | "custom" | "mcp" | "starter";
|
|
52
|
+
description?: string | undefined;
|
|
53
|
+
title?: string | undefined;
|
|
54
|
+
arguments?: {
|
|
55
|
+
name: string;
|
|
56
|
+
description?: string | undefined;
|
|
57
|
+
required?: boolean | undefined;
|
|
58
|
+
}[] | undefined;
|
|
59
|
+
metadata?: {
|
|
60
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
61
|
+
} | undefined;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
outputFormat: "json";
|
|
65
|
+
status: 201;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
} & {
|
|
69
|
+
"/prompts/custom/:name": {
|
|
70
|
+
$delete: {
|
|
71
|
+
input: {
|
|
72
|
+
param: {
|
|
73
|
+
name: string;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
output: {};
|
|
77
|
+
outputFormat: string;
|
|
78
|
+
status: 204;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
} & {
|
|
82
|
+
"/prompts/:name": {
|
|
83
|
+
$get: {
|
|
84
|
+
input: {
|
|
85
|
+
param: {
|
|
86
|
+
name: string;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
output: {};
|
|
90
|
+
outputFormat: string;
|
|
91
|
+
status: 404;
|
|
92
|
+
} | {
|
|
93
|
+
input: {
|
|
94
|
+
param: {
|
|
95
|
+
name: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
output: {
|
|
99
|
+
definition: {
|
|
100
|
+
name: string;
|
|
101
|
+
description?: string | undefined;
|
|
102
|
+
title?: string | undefined;
|
|
103
|
+
arguments?: {
|
|
104
|
+
name: string;
|
|
105
|
+
description?: string | undefined;
|
|
106
|
+
required?: boolean | undefined;
|
|
107
|
+
}[] | undefined;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
outputFormat: "json";
|
|
111
|
+
status: 200;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
} & {
|
|
115
|
+
"/prompts/:name/resolve": {
|
|
116
|
+
$get: {
|
|
117
|
+
input: {
|
|
118
|
+
param: {
|
|
119
|
+
name: string;
|
|
120
|
+
};
|
|
121
|
+
} & {
|
|
122
|
+
query: {
|
|
123
|
+
context?: string | undefined;
|
|
124
|
+
args?: string | undefined;
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
output: {};
|
|
128
|
+
outputFormat: string;
|
|
129
|
+
status: 404;
|
|
130
|
+
} | {
|
|
131
|
+
input: {
|
|
132
|
+
param: {
|
|
133
|
+
name: string;
|
|
134
|
+
};
|
|
135
|
+
} & {
|
|
136
|
+
query: {
|
|
137
|
+
context?: string | undefined;
|
|
138
|
+
args?: string | undefined;
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
output: {
|
|
142
|
+
text: string;
|
|
143
|
+
resources: string[];
|
|
144
|
+
};
|
|
145
|
+
outputFormat: "json";
|
|
146
|
+
status: 200;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
}, "/">;
|
|
150
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAqE9C,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6N7D"}
|