@dexto/server 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/approval/manual-approval-handler.cjs +23 -15
  2. package/dist/approval/manual-approval-handler.d.ts.map +1 -1
  3. package/dist/approval/manual-approval-handler.js +23 -15
  4. package/dist/events/webhook-subscriber.cjs +1 -1
  5. package/dist/events/webhook-subscriber.d.ts.map +1 -1
  6. package/dist/events/webhook-subscriber.js +1 -1
  7. package/dist/hono/__tests__/test-fixtures.cjs +2 -2
  8. package/dist/hono/__tests__/test-fixtures.d.ts.map +1 -1
  9. package/dist/hono/__tests__/test-fixtures.js +2 -2
  10. package/dist/hono/index.cjs +6 -1
  11. package/dist/hono/index.d.ts +433 -88
  12. package/dist/hono/index.d.ts.map +1 -1
  13. package/dist/hono/index.js +6 -1
  14. package/dist/hono/middleware/error.d.ts.map +1 -1
  15. package/dist/hono/routes/agents.cjs +8 -10
  16. package/dist/hono/routes/agents.d.ts +15 -8
  17. package/dist/hono/routes/agents.d.ts.map +1 -1
  18. package/dist/hono/routes/agents.js +10 -10
  19. package/dist/hono/routes/approvals.cjs +52 -1
  20. package/dist/hono/routes/approvals.d.ts +25 -0
  21. package/dist/hono/routes/approvals.d.ts.map +1 -1
  22. package/dist/hono/routes/approvals.js +52 -1
  23. package/dist/hono/routes/llm.cjs +110 -31
  24. package/dist/hono/routes/llm.d.ts +72 -20
  25. package/dist/hono/routes/llm.d.ts.map +1 -1
  26. package/dist/hono/routes/llm.js +108 -25
  27. package/dist/hono/routes/mcp.cjs +8 -4
  28. package/dist/hono/routes/mcp.d.ts +4 -1
  29. package/dist/hono/routes/mcp.d.ts.map +1 -1
  30. package/dist/hono/routes/mcp.js +9 -5
  31. package/dist/hono/routes/memory.d.ts +1 -1
  32. package/dist/hono/routes/messages.cjs +54 -62
  33. package/dist/hono/routes/messages.d.ts +87 -43
  34. package/dist/hono/routes/messages.d.ts.map +1 -1
  35. package/dist/hono/routes/messages.js +55 -63
  36. package/dist/hono/routes/prompts.d.ts +6 -6
  37. package/dist/hono/routes/queue.cjs +202 -0
  38. package/dist/hono/routes/queue.d.ts +171 -0
  39. package/dist/hono/routes/queue.d.ts.map +1 -0
  40. package/dist/hono/routes/queue.js +178 -0
  41. package/dist/hono/routes/resources.d.ts +1 -1
  42. package/dist/hono/routes/search.d.ts +33 -7
  43. package/dist/hono/routes/search.d.ts.map +1 -1
  44. package/dist/hono/routes/sessions.cjs +65 -11
  45. package/dist/hono/routes/sessions.d.ts +22 -1
  46. package/dist/hono/routes/sessions.d.ts.map +1 -1
  47. package/dist/hono/routes/sessions.js +65 -11
  48. package/dist/hono/schemas/responses.cjs +24 -5
  49. package/dist/hono/schemas/responses.d.ts +799 -81
  50. package/dist/hono/schemas/responses.d.ts.map +1 -1
  51. package/dist/hono/schemas/responses.js +24 -10
  52. package/package.json +3 -3
@@ -0,0 +1,178 @@
1
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
+ import { ContentPartSchema } from "../schemas/responses.js";
3
+ const QueuedMessageSchema = z.object({
4
+ id: z.string().describe("Unique identifier for the queued message"),
5
+ content: z.array(ContentPartSchema).describe("Message content parts"),
6
+ queuedAt: z.number().describe("Unix timestamp when message was queued"),
7
+ metadata: z.record(z.unknown()).optional().describe("Optional metadata")
8
+ }).strict().describe("A message waiting in the queue");
9
+ const TextPartSchema = z.object({
10
+ type: z.literal("text").describe("Content type identifier"),
11
+ text: z.string().describe("Text content")
12
+ }).describe("Text content part");
13
+ const ImagePartSchema = z.object({
14
+ type: z.literal("image").describe("Content type identifier"),
15
+ image: z.string().describe("Base64-encoded image data or URL"),
16
+ mimeType: z.string().optional().describe("MIME type (e.g., image/png)")
17
+ }).describe("Image content part");
18
+ const FilePartSchema = z.object({
19
+ type: z.literal("file").describe("Content type identifier"),
20
+ data: z.string().describe("Base64-encoded file data or URL"),
21
+ mimeType: z.string().describe("MIME type (e.g., application/pdf)"),
22
+ filename: z.string().optional().describe("Optional filename")
23
+ }).describe("File content part");
24
+ const QueueContentPartSchema = z.discriminatedUnion("type", [TextPartSchema, ImagePartSchema, FilePartSchema]).describe("Content part - text, image, or file");
25
+ const QueueMessageBodySchema = z.object({
26
+ content: z.union([z.string(), z.array(QueueContentPartSchema)]).describe("Message content - string for text, or ContentPart[] for multimodal")
27
+ }).describe("Request body for queueing a message");
28
+ function createQueueRouter(getAgent) {
29
+ const app = new OpenAPIHono();
30
+ const getQueueRoute = createRoute({
31
+ method: "get",
32
+ path: "/queue/{sessionId}",
33
+ summary: "Get queued messages",
34
+ description: "Returns all messages waiting in the queue for a session",
35
+ tags: ["queue"],
36
+ request: {
37
+ params: z.object({
38
+ sessionId: z.string().min(1).describe("Session ID")
39
+ })
40
+ },
41
+ responses: {
42
+ 200: {
43
+ description: "List of queued messages",
44
+ content: {
45
+ "application/json": {
46
+ schema: z.object({
47
+ messages: z.array(QueuedMessageSchema).describe("Queued messages"),
48
+ count: z.number().describe("Number of messages in queue")
49
+ }).strict()
50
+ }
51
+ }
52
+ },
53
+ 404: { description: "Session not found" }
54
+ }
55
+ });
56
+ const queueMessageRoute = createRoute({
57
+ method: "post",
58
+ path: "/queue/{sessionId}",
59
+ summary: "Queue a message",
60
+ description: "Adds a message to the queue for processing when the session is no longer busy",
61
+ tags: ["queue"],
62
+ request: {
63
+ params: z.object({
64
+ sessionId: z.string().min(1).describe("Session ID")
65
+ }),
66
+ body: {
67
+ content: { "application/json": { schema: QueueMessageBodySchema } }
68
+ }
69
+ },
70
+ responses: {
71
+ 201: {
72
+ description: "Message queued successfully",
73
+ content: {
74
+ "application/json": {
75
+ schema: z.object({
76
+ queued: z.literal(true).describe("Indicates message was queued"),
77
+ id: z.string().describe("ID of the queued message"),
78
+ position: z.number().describe("Position in the queue (1-based)")
79
+ }).strict()
80
+ }
81
+ }
82
+ },
83
+ 404: { description: "Session not found" }
84
+ }
85
+ });
86
+ const removeQueuedMessageRoute = createRoute({
87
+ method: "delete",
88
+ path: "/queue/{sessionId}/{messageId}",
89
+ summary: "Remove queued message",
90
+ description: "Removes a specific message from the queue",
91
+ tags: ["queue"],
92
+ request: {
93
+ params: z.object({
94
+ sessionId: z.string().min(1).describe("Session ID"),
95
+ messageId: z.string().min(1).describe("ID of the queued message to remove")
96
+ })
97
+ },
98
+ responses: {
99
+ 200: {
100
+ description: "Message removed successfully",
101
+ content: {
102
+ "application/json": {
103
+ schema: z.object({
104
+ removed: z.literal(true).describe("Indicates message was removed"),
105
+ id: z.string().describe("ID of the removed message")
106
+ }).strict()
107
+ }
108
+ }
109
+ },
110
+ 404: { description: "Session or message not found" }
111
+ }
112
+ });
113
+ const clearQueueRoute = createRoute({
114
+ method: "delete",
115
+ path: "/queue/{sessionId}",
116
+ summary: "Clear message queue",
117
+ description: "Removes all messages from the queue for a session",
118
+ tags: ["queue"],
119
+ request: {
120
+ params: z.object({
121
+ sessionId: z.string().min(1).describe("Session ID")
122
+ })
123
+ },
124
+ responses: {
125
+ 200: {
126
+ description: "Queue cleared successfully",
127
+ content: {
128
+ "application/json": {
129
+ schema: z.object({
130
+ cleared: z.literal(true).describe("Indicates queue was cleared"),
131
+ count: z.number().describe("Number of messages that were removed")
132
+ }).strict()
133
+ }
134
+ }
135
+ },
136
+ 404: { description: "Session not found" }
137
+ }
138
+ });
139
+ return app.openapi(getQueueRoute, async (ctx) => {
140
+ const agent = getAgent();
141
+ const { sessionId } = ctx.req.valid("param");
142
+ const messages = await agent.getQueuedMessages(sessionId);
143
+ return ctx.json({
144
+ messages,
145
+ count: messages.length
146
+ });
147
+ }).openapi(queueMessageRoute, async (ctx) => {
148
+ const agent = getAgent();
149
+ const { sessionId } = ctx.req.valid("param");
150
+ const { content: rawContent } = ctx.req.valid("json");
151
+ const content = typeof rawContent === "string" ? [{ type: "text", text: rawContent }] : rawContent;
152
+ const result = await agent.queueMessage(sessionId, { content });
153
+ return ctx.json(
154
+ {
155
+ queued: result.queued,
156
+ id: result.id,
157
+ position: result.position
158
+ },
159
+ 201
160
+ );
161
+ }).openapi(removeQueuedMessageRoute, async (ctx) => {
162
+ const agent = getAgent();
163
+ const { sessionId, messageId } = ctx.req.valid("param");
164
+ const removed = await agent.removeQueuedMessage(sessionId, messageId);
165
+ if (!removed) {
166
+ return ctx.json({ error: "Message not found in queue" }, 404);
167
+ }
168
+ return ctx.json({ removed: true, id: messageId });
169
+ }).openapi(clearQueueRoute, async (ctx) => {
170
+ const agent = getAgent();
171
+ const { sessionId } = ctx.req.valid("param");
172
+ const count = await agent.clearMessageQueue(sessionId);
173
+ return ctx.json({ cleared: true, count });
174
+ });
175
+ }
176
+ export {
177
+ createQueueRouter
178
+ };
@@ -11,10 +11,10 @@ export declare function createResourcesRouter(getAgent: () => DextoAgent): OpenA
11
11
  source: "mcp" | "internal";
12
12
  description?: string | undefined;
13
13
  mimeType?: string | undefined;
14
- name?: string | undefined;
15
14
  metadata?: {
16
15
  [x: string]: import("hono/utils/types").JSONValue;
17
16
  } | undefined;
17
+ name?: string | undefined;
18
18
  serverName?: string | undefined;
19
19
  size?: number | undefined;
20
20
  lastModified?: string | undefined;
@@ -28,6 +28,19 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
28
28
  mimeType: string;
29
29
  data: string;
30
30
  filename?: string | undefined;
31
+ } | {
32
+ type: "ui-resource";
33
+ mimeType: string;
34
+ uri: string;
35
+ content?: string | undefined;
36
+ blob?: string | undefined;
37
+ metadata?: {
38
+ title?: string | undefined;
39
+ preferredSize?: {
40
+ width: number;
41
+ height: number;
42
+ } | undefined;
43
+ } | undefined;
31
44
  })[] | null;
32
45
  role: "system" | "user" | "assistant" | "tool";
33
46
  id?: string | undefined;
@@ -42,7 +55,6 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
42
55
  } | undefined;
43
56
  model?: string | undefined;
44
57
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
45
- router?: "vercel" | "in-built" | undefined;
46
58
  toolCalls?: {
47
59
  function: {
48
60
  name: string;
@@ -52,6 +64,7 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
52
64
  id: string;
53
65
  }[] | undefined;
54
66
  toolCallId?: string | undefined;
67
+ success?: boolean | undefined;
55
68
  };
56
69
  sessionId: string;
57
70
  matchedText: string;
@@ -77,6 +90,11 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
77
90
  query: string;
78
91
  results: {
79
92
  sessionId: string;
93
+ metadata: {
94
+ createdAt: number;
95
+ lastActivity: number;
96
+ messageCount: number;
97
+ };
80
98
  matchCount: number;
81
99
  firstMatch: {
82
100
  message: {
@@ -92,6 +110,19 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
92
110
  mimeType: string;
93
111
  data: string;
94
112
  filename?: string | undefined;
113
+ } | {
114
+ type: "ui-resource";
115
+ mimeType: string;
116
+ uri: string;
117
+ content?: string | undefined;
118
+ blob?: string | undefined;
119
+ metadata?: {
120
+ title?: string | undefined;
121
+ preferredSize?: {
122
+ width: number;
123
+ height: number;
124
+ } | undefined;
125
+ } | undefined;
95
126
  })[] | null;
96
127
  role: "system" | "user" | "assistant" | "tool";
97
128
  id?: string | undefined;
@@ -106,7 +137,6 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
106
137
  } | undefined;
107
138
  model?: string | undefined;
108
139
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
109
- router?: "vercel" | "in-built" | undefined;
110
140
  toolCalls?: {
111
141
  function: {
112
142
  name: string;
@@ -116,17 +146,13 @@ export declare function createSearchRouter(getAgent: () => DextoAgent): OpenAPIH
116
146
  id: string;
117
147
  }[] | undefined;
118
148
  toolCallId?: string | undefined;
149
+ success?: boolean | undefined;
119
150
  };
120
151
  sessionId: string;
121
152
  matchedText: string;
122
153
  context: string;
123
154
  messageIndex: number;
124
155
  };
125
- metadata: {
126
- createdAt: number;
127
- lastActivity: number;
128
- messageCount: number;
129
- };
130
156
  }[];
131
157
  total: number;
132
158
  hasMore: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA2B9C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwD5D"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA2B9C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwD5D"}
@@ -95,7 +95,7 @@ function createSessionsRouter(getAgent) {
95
95
  method: "get",
96
96
  path: "/sessions/{sessionId}/history",
97
97
  summary: "Get Session History",
98
- description: "Retrieves the conversation history for a session",
98
+ description: "Retrieves the conversation history for a session along with processing status",
99
99
  tags: ["sessions"],
100
100
  request: { params: import_zod_openapi.z.object({ sessionId: import_zod_openapi.z.string().describe("Session identifier") }) },
101
101
  responses: {
@@ -104,7 +104,10 @@ function createSessionsRouter(getAgent) {
104
104
  content: {
105
105
  "application/json": {
106
106
  schema: import_zod_openapi.z.object({
107
- history: import_zod_openapi.z.array(import_responses.InternalMessageSchema).describe("Array of messages in conversation history")
107
+ history: import_zod_openapi.z.array(import_responses.InternalMessageSchema).describe("Array of messages in conversation history"),
108
+ isBusy: import_zod_openapi.z.boolean().describe(
109
+ "Whether the session is currently processing a message"
110
+ )
108
111
  }).strict()
109
112
  }
110
113
  }
@@ -136,9 +139,23 @@ function createSessionsRouter(getAgent) {
136
139
  method: "post",
137
140
  path: "/sessions/{sessionId}/cancel",
138
141
  summary: "Cancel Session Run",
139
- description: "Cancels an in-flight agent run for the specified session",
142
+ description: "Cancels an in-flight agent run for the specified session. By default (soft cancel), only the current LLM call is cancelled and queued messages continue processing. Set clearQueue=true for hard cancel to also clear any queued messages.",
140
143
  tags: ["sessions"],
141
- request: { params: import_zod_openapi.z.object({ sessionId: import_zod_openapi.z.string().describe("Session identifier") }) },
144
+ request: {
145
+ params: import_zod_openapi.z.object({ sessionId: import_zod_openapi.z.string().describe("Session identifier") }),
146
+ body: {
147
+ content: {
148
+ "application/json": {
149
+ schema: import_zod_openapi.z.object({
150
+ clearQueue: import_zod_openapi.z.boolean().optional().default(false).describe(
151
+ "If true (hard cancel), clears queued messages. If false (soft cancel, default), queued messages continue processing."
152
+ )
153
+ }).strict()
154
+ }
155
+ },
156
+ required: false
157
+ }
158
+ },
142
159
  responses: {
143
160
  200: {
144
161
  description: "Cancel operation result",
@@ -146,7 +163,11 @@ function createSessionsRouter(getAgent) {
146
163
  "application/json": {
147
164
  schema: import_zod_openapi.z.object({
148
165
  cancelled: import_zod_openapi.z.boolean().describe("Whether a run was cancelled"),
149
- sessionId: import_zod_openapi.z.string().describe("Session ID")
166
+ sessionId: import_zod_openapi.z.string().describe("Session ID"),
167
+ queueCleared: import_zod_openapi.z.boolean().describe("Whether queued messages were cleared"),
168
+ clearedCount: import_zod_openapi.z.number().describe(
169
+ "Number of queued messages cleared (0 if soft cancel)"
170
+ )
150
171
  }).strict()
151
172
  }
152
173
  }
@@ -157,7 +178,7 @@ function createSessionsRouter(getAgent) {
157
178
  method: "get",
158
179
  path: "/sessions/{sessionId}/load",
159
180
  summary: "Load Session",
160
- description: "Validates and retrieves session information. The client should track the active session.",
181
+ description: "Validates and retrieves session information including processing status. The client should track the active session.",
161
182
  tags: ["sessions"],
162
183
  request: {
163
184
  params: import_zod_openapi.z.object({ sessionId: import_zod_openapi.z.string().describe("Session identifier") })
@@ -168,7 +189,11 @@ function createSessionsRouter(getAgent) {
168
189
  content: {
169
190
  "application/json": {
170
191
  schema: import_zod_openapi.z.object({
171
- session: import_responses.SessionMetadataSchema.describe("Session metadata")
192
+ session: import_responses.SessionMetadataSchema.extend({
193
+ isBusy: import_zod_openapi.z.boolean().describe(
194
+ "Whether the session is currently processing a message"
195
+ )
196
+ }).describe("Session metadata with processing status")
172
197
  }).strict()
173
198
  }
174
199
  }
@@ -303,8 +328,14 @@ function createSessionsRouter(getAgent) {
303
328
  }).openapi(historyRoute, async (ctx) => {
304
329
  const agent = getAgent();
305
330
  const { sessionId } = ctx.req.param();
306
- const history = await agent.getSessionHistory(sessionId);
307
- return ctx.json({ history });
331
+ const [history, isBusy] = await Promise.all([
332
+ agent.getSessionHistory(sessionId),
333
+ agent.isSessionBusy(sessionId)
334
+ ]);
335
+ return ctx.json({
336
+ history,
337
+ isBusy
338
+ });
308
339
  }).openapi(deleteRoute, async (ctx) => {
309
340
  const agent = getAgent();
310
341
  const { sessionId } = ctx.req.param();
@@ -313,11 +344,32 @@ function createSessionsRouter(getAgent) {
313
344
  }).openapi(cancelRoute, async (ctx) => {
314
345
  const agent = getAgent();
315
346
  const { sessionId } = ctx.req.valid("param");
347
+ let clearQueue = false;
348
+ try {
349
+ const body = ctx.req.valid("json");
350
+ clearQueue = body?.clearQueue ?? false;
351
+ } catch {
352
+ }
353
+ let clearedCount = 0;
354
+ if (clearQueue) {
355
+ try {
356
+ clearedCount = await agent.clearMessageQueue(sessionId);
357
+ agent.logger.debug(
358
+ `Hard cancel: cleared ${clearedCount} queued message(s) for session: ${sessionId}`
359
+ );
360
+ } catch {
361
+ }
362
+ }
316
363
  const cancelled = await agent.cancel(sessionId);
317
364
  if (!cancelled) {
318
365
  agent.logger.debug(`No in-flight run to cancel for session: ${sessionId}`);
319
366
  }
320
- return ctx.json({ cancelled, sessionId });
367
+ return ctx.json({
368
+ cancelled,
369
+ sessionId,
370
+ queueCleared: clearQueue,
371
+ clearedCount
372
+ });
321
373
  }).openapi(loadRoute, async (ctx) => {
322
374
  const agent = getAgent();
323
375
  const { sessionId } = ctx.req.valid("param");
@@ -326,6 +378,7 @@ function createSessionsRouter(getAgent) {
326
378
  return ctx.json({ error: `Session not found: ${sessionId}` }, 404);
327
379
  }
328
380
  const metadata = await agent.getSessionMetadata(sessionId);
381
+ const isBusy = await agent.isSessionBusy(sessionId);
329
382
  return ctx.json(
330
383
  {
331
384
  session: {
@@ -333,7 +386,8 @@ function createSessionsRouter(getAgent) {
333
386
  createdAt: metadata?.createdAt || null,
334
387
  lastActivity: metadata?.lastActivity || null,
335
388
  messageCount: metadata?.messageCount || 0,
336
- title: metadata?.title || null
389
+ title: metadata?.title || null,
390
+ isBusy
337
391
  }
338
392
  },
339
393
  200
@@ -82,6 +82,19 @@ export declare function createSessionsRouter(getAgent: () => DextoAgent): OpenAP
82
82
  mimeType: string;
83
83
  data: string;
84
84
  filename?: string | undefined;
85
+ } | {
86
+ type: "ui-resource";
87
+ mimeType: string;
88
+ uri: string;
89
+ content?: string | undefined;
90
+ blob?: string | undefined;
91
+ metadata?: {
92
+ title?: string | undefined;
93
+ preferredSize?: {
94
+ width: number;
95
+ height: number;
96
+ } | undefined;
97
+ } | undefined;
85
98
  })[] | null;
86
99
  role: "system" | "user" | "assistant" | "tool";
87
100
  id?: string | undefined;
@@ -96,7 +109,6 @@ export declare function createSessionsRouter(getAgent: () => DextoAgent): OpenAP
96
109
  } | undefined;
97
110
  model?: string | undefined;
98
111
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
99
- router?: "vercel" | "in-built" | undefined;
100
112
  toolCalls?: {
101
113
  function: {
102
114
  name: string;
@@ -106,7 +118,9 @@ export declare function createSessionsRouter(getAgent: () => DextoAgent): OpenAP
106
118
  id: string;
107
119
  }[] | undefined;
108
120
  toolCallId?: string | undefined;
121
+ success?: boolean | undefined;
109
122
  }[];
123
+ isBusy: boolean;
110
124
  };
111
125
  outputFormat: "json";
112
126
  status: 200;
@@ -135,10 +149,16 @@ export declare function createSessionsRouter(getAgent: () => DextoAgent): OpenAP
135
149
  param: {
136
150
  sessionId: string;
137
151
  };
152
+ } & {
153
+ json: {
154
+ clearQueue?: boolean | undefined;
155
+ };
138
156
  };
139
157
  output: {
140
158
  sessionId: string;
141
159
  cancelled: boolean;
160
+ queueCleared: boolean;
161
+ clearedCount: number;
142
162
  };
143
163
  outputFormat: "json";
144
164
  status: 200;
@@ -158,6 +178,7 @@ export declare function createSessionsRouter(getAgent: () => DextoAgent): OpenAP
158
178
  createdAt: number | null;
159
179
  lastActivity: number | null;
160
180
  messageCount: number;
181
+ isBusy: boolean;
161
182
  title?: string | null | undefined;
162
183
  };
163
184
  };
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgZ9D"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAS9C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAie9D"}
@@ -72,7 +72,7 @@ function createSessionsRouter(getAgent) {
72
72
  method: "get",
73
73
  path: "/sessions/{sessionId}/history",
74
74
  summary: "Get Session History",
75
- description: "Retrieves the conversation history for a session",
75
+ description: "Retrieves the conversation history for a session along with processing status",
76
76
  tags: ["sessions"],
77
77
  request: { params: z.object({ sessionId: z.string().describe("Session identifier") }) },
78
78
  responses: {
@@ -81,7 +81,10 @@ function createSessionsRouter(getAgent) {
81
81
  content: {
82
82
  "application/json": {
83
83
  schema: z.object({
84
- history: z.array(InternalMessageSchema).describe("Array of messages in conversation history")
84
+ history: z.array(InternalMessageSchema).describe("Array of messages in conversation history"),
85
+ isBusy: z.boolean().describe(
86
+ "Whether the session is currently processing a message"
87
+ )
85
88
  }).strict()
86
89
  }
87
90
  }
@@ -113,9 +116,23 @@ function createSessionsRouter(getAgent) {
113
116
  method: "post",
114
117
  path: "/sessions/{sessionId}/cancel",
115
118
  summary: "Cancel Session Run",
116
- description: "Cancels an in-flight agent run for the specified session",
119
+ description: "Cancels an in-flight agent run for the specified session. By default (soft cancel), only the current LLM call is cancelled and queued messages continue processing. Set clearQueue=true for hard cancel to also clear any queued messages.",
117
120
  tags: ["sessions"],
118
- request: { params: z.object({ sessionId: z.string().describe("Session identifier") }) },
121
+ request: {
122
+ params: z.object({ sessionId: z.string().describe("Session identifier") }),
123
+ body: {
124
+ content: {
125
+ "application/json": {
126
+ schema: z.object({
127
+ clearQueue: z.boolean().optional().default(false).describe(
128
+ "If true (hard cancel), clears queued messages. If false (soft cancel, default), queued messages continue processing."
129
+ )
130
+ }).strict()
131
+ }
132
+ },
133
+ required: false
134
+ }
135
+ },
119
136
  responses: {
120
137
  200: {
121
138
  description: "Cancel operation result",
@@ -123,7 +140,11 @@ function createSessionsRouter(getAgent) {
123
140
  "application/json": {
124
141
  schema: z.object({
125
142
  cancelled: z.boolean().describe("Whether a run was cancelled"),
126
- sessionId: z.string().describe("Session ID")
143
+ sessionId: z.string().describe("Session ID"),
144
+ queueCleared: z.boolean().describe("Whether queued messages were cleared"),
145
+ clearedCount: z.number().describe(
146
+ "Number of queued messages cleared (0 if soft cancel)"
147
+ )
127
148
  }).strict()
128
149
  }
129
150
  }
@@ -134,7 +155,7 @@ function createSessionsRouter(getAgent) {
134
155
  method: "get",
135
156
  path: "/sessions/{sessionId}/load",
136
157
  summary: "Load Session",
137
- description: "Validates and retrieves session information. The client should track the active session.",
158
+ description: "Validates and retrieves session information including processing status. The client should track the active session.",
138
159
  tags: ["sessions"],
139
160
  request: {
140
161
  params: z.object({ sessionId: z.string().describe("Session identifier") })
@@ -145,7 +166,11 @@ function createSessionsRouter(getAgent) {
145
166
  content: {
146
167
  "application/json": {
147
168
  schema: z.object({
148
- session: SessionMetadataSchema.describe("Session metadata")
169
+ session: SessionMetadataSchema.extend({
170
+ isBusy: z.boolean().describe(
171
+ "Whether the session is currently processing a message"
172
+ )
173
+ }).describe("Session metadata with processing status")
149
174
  }).strict()
150
175
  }
151
176
  }
@@ -280,8 +305,14 @@ function createSessionsRouter(getAgent) {
280
305
  }).openapi(historyRoute, async (ctx) => {
281
306
  const agent = getAgent();
282
307
  const { sessionId } = ctx.req.param();
283
- const history = await agent.getSessionHistory(sessionId);
284
- return ctx.json({ history });
308
+ const [history, isBusy] = await Promise.all([
309
+ agent.getSessionHistory(sessionId),
310
+ agent.isSessionBusy(sessionId)
311
+ ]);
312
+ return ctx.json({
313
+ history,
314
+ isBusy
315
+ });
285
316
  }).openapi(deleteRoute, async (ctx) => {
286
317
  const agent = getAgent();
287
318
  const { sessionId } = ctx.req.param();
@@ -290,11 +321,32 @@ function createSessionsRouter(getAgent) {
290
321
  }).openapi(cancelRoute, async (ctx) => {
291
322
  const agent = getAgent();
292
323
  const { sessionId } = ctx.req.valid("param");
324
+ let clearQueue = false;
325
+ try {
326
+ const body = ctx.req.valid("json");
327
+ clearQueue = body?.clearQueue ?? false;
328
+ } catch {
329
+ }
330
+ let clearedCount = 0;
331
+ if (clearQueue) {
332
+ try {
333
+ clearedCount = await agent.clearMessageQueue(sessionId);
334
+ agent.logger.debug(
335
+ `Hard cancel: cleared ${clearedCount} queued message(s) for session: ${sessionId}`
336
+ );
337
+ } catch {
338
+ }
339
+ }
293
340
  const cancelled = await agent.cancel(sessionId);
294
341
  if (!cancelled) {
295
342
  agent.logger.debug(`No in-flight run to cancel for session: ${sessionId}`);
296
343
  }
297
- return ctx.json({ cancelled, sessionId });
344
+ return ctx.json({
345
+ cancelled,
346
+ sessionId,
347
+ queueCleared: clearQueue,
348
+ clearedCount
349
+ });
298
350
  }).openapi(loadRoute, async (ctx) => {
299
351
  const agent = getAgent();
300
352
  const { sessionId } = ctx.req.valid("param");
@@ -303,6 +355,7 @@ function createSessionsRouter(getAgent) {
303
355
  return ctx.json({ error: `Session not found: ${sessionId}` }, 404);
304
356
  }
305
357
  const metadata = await agent.getSessionMetadata(sessionId);
358
+ const isBusy = await agent.isSessionBusy(sessionId);
306
359
  return ctx.json(
307
360
  {
308
361
  session: {
@@ -310,7 +363,8 @@ function createSessionsRouter(getAgent) {
310
363
  createdAt: metadata?.createdAt || null,
311
364
  lastActivity: metadata?.lastActivity || null,
312
365
  messageCount: metadata?.messageCount || 0,
313
- title: metadata?.title || null
366
+ title: metadata?.title || null,
367
+ isBusy
314
368
  }
315
369
  },
316
370
  200