@dexto/server 1.6.16 → 1.6.17

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 (37) hide show
  1. package/dist/events/a2a-sse-subscriber.cjs +9 -2
  2. package/dist/events/a2a-sse-subscriber.d.ts.map +1 -1
  3. package/dist/events/a2a-sse-subscriber.js +9 -2
  4. package/dist/events/usage-event-subscriber.cjs +263 -0
  5. package/dist/events/usage-event-subscriber.d.ts +35 -0
  6. package/dist/events/usage-event-subscriber.d.ts.map +1 -0
  7. package/dist/events/usage-event-subscriber.js +244 -0
  8. package/dist/events/usage-event-types.cjs +16 -0
  9. package/dist/events/usage-event-types.d.ts +33 -0
  10. package/dist/events/usage-event-types.d.ts.map +1 -0
  11. package/dist/events/usage-event-types.js +0 -0
  12. package/dist/hono/index.d.ts +157 -32
  13. package/dist/hono/index.d.ts.map +1 -1
  14. package/dist/hono/routes/a2a-tasks.d.ts +9 -9
  15. package/dist/hono/routes/approvals.cjs +94 -6
  16. package/dist/hono/routes/approvals.d.ts +22 -6
  17. package/dist/hono/routes/approvals.d.ts.map +1 -1
  18. package/dist/hono/routes/approvals.js +94 -6
  19. package/dist/hono/routes/messages.cjs +16 -5
  20. package/dist/hono/routes/messages.d.ts +6 -0
  21. package/dist/hono/routes/messages.d.ts.map +1 -1
  22. package/dist/hono/routes/messages.js +17 -6
  23. package/dist/hono/routes/search.d.ts +10 -0
  24. package/dist/hono/routes/search.d.ts.map +1 -1
  25. package/dist/hono/routes/sessions.cjs +54 -1
  26. package/dist/hono/routes/sessions.d.ts +111 -18
  27. package/dist/hono/routes/sessions.d.ts.map +1 -1
  28. package/dist/hono/routes/sessions.js +59 -2
  29. package/dist/hono/schemas/responses.cjs +48 -8
  30. package/dist/hono/schemas/responses.d.ts +489 -22
  31. package/dist/hono/schemas/responses.d.ts.map +1 -1
  32. package/dist/hono/schemas/responses.js +49 -9
  33. package/dist/index.cjs +4 -0
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -0
  37. package/package.json +9 -9
@@ -38,6 +38,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
38
38
  json: {
39
39
  message: {
40
40
  role: "user" | "agent";
41
+ messageId: string;
41
42
  kind: "message";
42
43
  parts: ({
43
44
  text: string;
@@ -60,7 +61,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
60
61
  kind: "data";
61
62
  metadata?: Record<string, any> | undefined;
62
63
  })[];
63
- messageId: string;
64
64
  metadata?: Record<string, any> | undefined;
65
65
  taskId?: string | undefined;
66
66
  contextId?: string | undefined;
@@ -84,6 +84,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
84
84
  state: "unknown" | "failed" | "auth-required" | "submitted" | "working" | "input-required" | "completed" | "canceled" | "rejected";
85
85
  message?: {
86
86
  role: "user" | "agent";
87
+ messageId: string;
87
88
  kind: "message";
88
89
  parts: ({
89
90
  text: string;
@@ -114,7 +115,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
114
115
  [x: string]: any;
115
116
  } | undefined;
116
117
  })[];
117
- messageId: string;
118
118
  metadata?: {
119
119
  [x: string]: any;
120
120
  } | undefined;
@@ -133,6 +133,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
133
133
  } | undefined;
134
134
  history?: {
135
135
  role: "user" | "agent";
136
+ messageId: string;
136
137
  kind: "message";
137
138
  parts: ({
138
139
  text: string;
@@ -163,7 +164,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
163
164
  [x: string]: any;
164
165
  } | undefined;
165
166
  })[];
166
- messageId: string;
167
167
  metadata?: {
168
168
  [x: string]: any;
169
169
  } | undefined;
@@ -198,6 +198,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
198
198
  state: "unknown" | "failed" | "auth-required" | "submitted" | "working" | "input-required" | "completed" | "canceled" | "rejected";
199
199
  message?: {
200
200
  role: "user" | "agent";
201
+ messageId: string;
201
202
  kind: "message";
202
203
  parts: ({
203
204
  text: string;
@@ -228,7 +229,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
228
229
  [x: string]: any;
229
230
  } | undefined;
230
231
  })[];
231
- messageId: string;
232
232
  metadata?: {
233
233
  [x: string]: any;
234
234
  } | undefined;
@@ -247,6 +247,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
247
247
  } | undefined;
248
248
  history?: {
249
249
  role: "user" | "agent";
250
+ messageId: string;
250
251
  kind: "message";
251
252
  parts: ({
252
253
  text: string;
@@ -277,7 +278,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
277
278
  [x: string]: any;
278
279
  } | undefined;
279
280
  })[];
280
- messageId: string;
281
281
  metadata?: {
282
282
  [x: string]: any;
283
283
  } | undefined;
@@ -318,6 +318,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
318
318
  state: "unknown" | "failed" | "auth-required" | "submitted" | "working" | "input-required" | "completed" | "canceled" | "rejected";
319
319
  message?: {
320
320
  role: "user" | "agent";
321
+ messageId: string;
321
322
  kind: "message";
322
323
  parts: ({
323
324
  text: string;
@@ -348,7 +349,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
348
349
  [x: string]: any;
349
350
  } | undefined;
350
351
  })[];
351
- messageId: string;
352
352
  metadata?: {
353
353
  [x: string]: any;
354
354
  } | undefined;
@@ -367,6 +367,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
367
367
  } | undefined;
368
368
  history?: {
369
369
  role: "user" | "agent";
370
+ messageId: string;
370
371
  kind: "message";
371
372
  parts: ({
372
373
  text: string;
@@ -397,7 +398,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
397
398
  [x: string]: any;
398
399
  } | undefined;
399
400
  })[];
400
- messageId: string;
401
401
  metadata?: {
402
402
  [x: string]: any;
403
403
  } | undefined;
@@ -434,6 +434,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
434
434
  state: "unknown" | "failed" | "auth-required" | "submitted" | "working" | "input-required" | "completed" | "canceled" | "rejected";
435
435
  message?: {
436
436
  role: "user" | "agent";
437
+ messageId: string;
437
438
  kind: "message";
438
439
  parts: ({
439
440
  text: string;
@@ -464,7 +465,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
464
465
  [x: string]: any;
465
466
  } | undefined;
466
467
  })[];
467
- messageId: string;
468
468
  metadata?: {
469
469
  [x: string]: any;
470
470
  } | undefined;
@@ -483,6 +483,7 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
483
483
  } | undefined;
484
484
  history?: {
485
485
  role: "user" | "agent";
486
+ messageId: string;
486
487
  kind: "message";
487
488
  parts: ({
488
489
  text: string;
@@ -513,7 +514,6 @@ export declare function createA2ATasksRouter(getAgent: GetAgentFn, sseSubscriber
513
514
  [x: string]: any;
514
515
  } | undefined;
515
516
  })[];
516
- messageId: string;
517
517
  metadata?: {
518
518
  [x: string]: any;
519
519
  } | undefined;
@@ -24,14 +24,85 @@ module.exports = __toCommonJS(approvals_exports);
24
24
  var import_zod_openapi = require("@hono/zod-openapi");
25
25
  var import_core = require("@dexto/core");
26
26
  const ApprovalBodySchema = import_zod_openapi.z.object({
27
- status: import_zod_openapi.z.enum([import_core.ApprovalStatus.APPROVED, import_core.ApprovalStatus.DENIED]).describe("The user decision"),
27
+ status: import_zod_openapi.z.enum([import_core.ApprovalStatus.APPROVED, import_core.ApprovalStatus.DENIED, import_core.ApprovalStatus.CANCELLED]).describe("The user decision"),
28
28
  formData: import_zod_openapi.z.record(import_zod_openapi.z.unknown()).optional().describe("Optional form data provided by the user (for elicitation)"),
29
- rememberChoice: import_zod_openapi.z.boolean().optional().describe("Whether to remember this choice for future requests")
29
+ rememberChoice: import_zod_openapi.z.boolean().optional().describe("Whether to remember this choice for future requests"),
30
+ rememberPattern: import_zod_openapi.z.string().optional().describe("Optional approval pattern to remember for future requests"),
31
+ rememberDirectory: import_zod_openapi.z.boolean().optional().describe("Whether to remember the approved directory for future requests"),
32
+ reason: import_zod_openapi.z.nativeEnum(import_core.DenialReason).optional().describe("Optional structured denial or cancellation reason"),
33
+ message: import_zod_openapi.z.string().optional().describe("Optional freeform denial or cancellation message")
34
+ }).strict().superRefine((value, refinementCtx) => {
35
+ const addFieldIssue = (path, message) => {
36
+ refinementCtx.addIssue({
37
+ code: import_zod_openapi.z.ZodIssueCode.custom,
38
+ path: [path],
39
+ message
40
+ });
41
+ };
42
+ if (value.status === import_core.ApprovalStatus.APPROVED) {
43
+ if (value.reason !== void 0) {
44
+ addFieldIssue(
45
+ "reason",
46
+ "reason is only allowed when status is denied or cancelled"
47
+ );
48
+ }
49
+ if (value.message !== void 0) {
50
+ addFieldIssue(
51
+ "message",
52
+ "message is only allowed when status is denied or cancelled"
53
+ );
54
+ }
55
+ return;
56
+ }
57
+ if (value.formData !== void 0) {
58
+ addFieldIssue("formData", "formData is only allowed when status is approved");
59
+ }
60
+ if (value.rememberChoice !== void 0) {
61
+ addFieldIssue(
62
+ "rememberChoice",
63
+ "rememberChoice is only allowed when status is approved"
64
+ );
65
+ }
66
+ if (value.rememberPattern !== void 0) {
67
+ addFieldIssue(
68
+ "rememberPattern",
69
+ "rememberPattern is only allowed when status is approved"
70
+ );
71
+ }
72
+ if (value.rememberDirectory !== void 0) {
73
+ addFieldIssue(
74
+ "rememberDirectory",
75
+ "rememberDirectory is only allowed when status is approved"
76
+ );
77
+ }
78
+ if (value.reason === void 0) {
79
+ return;
80
+ }
81
+ if (value.status === import_core.ApprovalStatus.DENIED) {
82
+ const invalidReasons2 = /* @__PURE__ */ new Set([
83
+ import_core.DenialReason.USER_CANCELLED,
84
+ import_core.DenialReason.SYSTEM_CANCELLED,
85
+ import_core.DenialReason.TIMEOUT
86
+ ]);
87
+ if (invalidReasons2.has(value.reason)) {
88
+ addFieldIssue("reason", "reason must describe a denial when status is denied");
89
+ }
90
+ return;
91
+ }
92
+ const invalidReasons = /* @__PURE__ */ new Set([
93
+ import_core.DenialReason.USER_DENIED,
94
+ import_core.DenialReason.SYSTEM_DENIED,
95
+ import_core.DenialReason.VALIDATION_FAILED,
96
+ import_core.DenialReason.ELICITATION_DISABLED
97
+ ]);
98
+ if (invalidReasons.has(value.reason)) {
99
+ addFieldIssue("reason", "reason must describe a cancellation when status is cancelled");
100
+ }
30
101
  }).describe("Request body for submitting an approval decision");
31
102
  const ApprovalResponseSchema = import_zod_openapi.z.object({
32
103
  ok: import_zod_openapi.z.boolean().describe("Whether the approval was successfully processed"),
33
104
  approvalId: import_zod_openapi.z.string().describe("The ID of the processed approval"),
34
- status: import_zod_openapi.z.enum([import_core.ApprovalStatus.APPROVED, import_core.ApprovalStatus.DENIED]).describe("The final status")
105
+ status: import_zod_openapi.z.enum([import_core.ApprovalStatus.APPROVED, import_core.ApprovalStatus.DENIED, import_core.ApprovalStatus.CANCELLED]).describe("The final status")
35
106
  }).describe("Response after processing approval");
36
107
  const PendingApprovalSchema = import_zod_openapi.z.object({
37
108
  approvalId: import_zod_openapi.z.string().describe("The unique ID of the approval request"),
@@ -126,7 +197,15 @@ function createApprovalsRouter(getAgent, approvalCoordinator) {
126
197
  }).openapi(submitApprovalRoute, async (ctx) => {
127
198
  const agent = await getAgent(ctx);
128
199
  const { approvalId } = ctx.req.valid("param");
129
- const { status, formData, rememberChoice } = ctx.req.valid("json");
200
+ const {
201
+ status,
202
+ formData,
203
+ rememberChoice,
204
+ rememberPattern,
205
+ rememberDirectory,
206
+ reason,
207
+ message
208
+ } = ctx.req.valid("json");
130
209
  agent.logger.info(`Received approval decision for ${approvalId}: ${status}`);
131
210
  if (!approvalCoordinator) {
132
211
  agent.logger.error("ApprovalCoordinator not available");
@@ -145,6 +224,12 @@ function createApprovalsRouter(getAgent, approvalCoordinator) {
145
224
  if (rememberChoice !== void 0) {
146
225
  data.rememberChoice = rememberChoice;
147
226
  }
227
+ if (rememberPattern !== void 0) {
228
+ data.rememberPattern = rememberPattern;
229
+ }
230
+ if (rememberDirectory !== void 0) {
231
+ data.rememberDirectory = rememberDirectory;
232
+ }
148
233
  }
149
234
  const sessionId = approvalCoordinator.getSessionId(approvalId);
150
235
  const responsePayload = {
@@ -153,8 +238,11 @@ function createApprovalsRouter(getAgent, approvalCoordinator) {
153
238
  sessionId,
154
239
  // Attach sessionId for SSE routing to correct client streams
155
240
  ...status === import_core.ApprovalStatus.DENIED ? {
156
- reason: import_core.DenialReason.USER_DENIED,
157
- message: "User denied the request via API"
241
+ reason: reason ?? import_core.DenialReason.USER_DENIED,
242
+ message: message ?? "User denied the request via API"
243
+ } : status === import_core.ApprovalStatus.CANCELLED ? {
244
+ reason: reason ?? import_core.DenialReason.USER_CANCELLED,
245
+ message: message ?? "User cancelled the request via API"
158
246
  } : {},
159
247
  ...Object.keys(data).length > 0 ? { data } : {}
160
248
  };
@@ -1,5 +1,5 @@
1
1
  import { OpenAPIHono } from '@hono/zod-openapi';
2
- import { type DextoAgent, ApprovalStatus } from '@dexto/core';
2
+ import { type DextoAgent, DenialReason, ApprovalStatus } from '@dexto/core';
3
3
  import type { ApprovalCoordinator } from '../../approval/approval-coordinator.js';
4
4
  import type { Context } from 'hono';
5
5
  type GetAgentFn = (ctx: Context) => DextoAgent | Promise<DextoAgent>;
@@ -41,9 +41,13 @@ export declare function createApprovalsRouter(getAgent: GetAgentFn, approvalCoor
41
41
  };
42
42
  } & {
43
43
  json: {
44
- status: ApprovalStatus.APPROVED | ApprovalStatus.DENIED;
44
+ status: ApprovalStatus;
45
+ message?: string | undefined;
45
46
  formData?: Record<string, unknown> | undefined;
46
47
  rememberChoice?: boolean | undefined;
48
+ rememberPattern?: string | undefined;
49
+ rememberDirectory?: boolean | undefined;
50
+ reason?: DenialReason | undefined;
47
51
  };
48
52
  };
49
53
  output: {};
@@ -60,9 +64,13 @@ export declare function createApprovalsRouter(getAgent: GetAgentFn, approvalCoor
60
64
  };
61
65
  } & {
62
66
  json: {
63
- status: ApprovalStatus.APPROVED | ApprovalStatus.DENIED;
67
+ status: ApprovalStatus;
68
+ message?: string | undefined;
64
69
  formData?: Record<string, unknown> | undefined;
65
70
  rememberChoice?: boolean | undefined;
71
+ rememberPattern?: string | undefined;
72
+ rememberDirectory?: boolean | undefined;
73
+ reason?: DenialReason | undefined;
66
74
  };
67
75
  };
68
76
  output: {};
@@ -79,9 +87,13 @@ export declare function createApprovalsRouter(getAgent: GetAgentFn, approvalCoor
79
87
  };
80
88
  } & {
81
89
  json: {
82
- status: ApprovalStatus.APPROVED | ApprovalStatus.DENIED;
90
+ status: ApprovalStatus;
91
+ message?: string | undefined;
83
92
  formData?: Record<string, unknown> | undefined;
84
93
  rememberChoice?: boolean | undefined;
94
+ rememberPattern?: string | undefined;
95
+ rememberDirectory?: boolean | undefined;
96
+ reason?: DenialReason | undefined;
85
97
  };
86
98
  };
87
99
  output: {};
@@ -98,13 +110,17 @@ export declare function createApprovalsRouter(getAgent: GetAgentFn, approvalCoor
98
110
  };
99
111
  } & {
100
112
  json: {
101
- status: ApprovalStatus.APPROVED | ApprovalStatus.DENIED;
113
+ status: ApprovalStatus;
114
+ message?: string | undefined;
102
115
  formData?: Record<string, unknown> | undefined;
103
116
  rememberChoice?: boolean | undefined;
117
+ rememberPattern?: string | undefined;
118
+ rememberDirectory?: boolean | undefined;
119
+ reason?: DenialReason | undefined;
104
120
  };
105
121
  };
106
122
  output: {
107
- status: ApprovalStatus.APPROVED | ApprovalStatus.DENIED;
123
+ status: ApprovalStatus;
108
124
  ok: boolean;
109
125
  approvalId: string;
110
126
  };
@@ -1 +1 @@
1
- {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,KAAK,UAAU,EAAgB,cAAc,EAAiB,MAAM,aAAa,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AA8CrE,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,UAAU,EACpB,mBAAmB,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgK5C"}
1
+ {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../../src/hono/routes/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,KAAK,UAAU,EAAE,YAAY,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAqIrE,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,UAAU,EACpB,mBAAmB,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAmL5C"}
@@ -1,14 +1,85 @@
1
1
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
2
  import { DenialReason, ApprovalStatus, ApprovalError } from "@dexto/core";
3
3
  const ApprovalBodySchema = z.object({
4
- status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.DENIED]).describe("The user decision"),
4
+ status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.DENIED, ApprovalStatus.CANCELLED]).describe("The user decision"),
5
5
  formData: z.record(z.unknown()).optional().describe("Optional form data provided by the user (for elicitation)"),
6
- rememberChoice: z.boolean().optional().describe("Whether to remember this choice for future requests")
6
+ rememberChoice: z.boolean().optional().describe("Whether to remember this choice for future requests"),
7
+ rememberPattern: z.string().optional().describe("Optional approval pattern to remember for future requests"),
8
+ rememberDirectory: z.boolean().optional().describe("Whether to remember the approved directory for future requests"),
9
+ reason: z.nativeEnum(DenialReason).optional().describe("Optional structured denial or cancellation reason"),
10
+ message: z.string().optional().describe("Optional freeform denial or cancellation message")
11
+ }).strict().superRefine((value, refinementCtx) => {
12
+ const addFieldIssue = (path, message) => {
13
+ refinementCtx.addIssue({
14
+ code: z.ZodIssueCode.custom,
15
+ path: [path],
16
+ message
17
+ });
18
+ };
19
+ if (value.status === ApprovalStatus.APPROVED) {
20
+ if (value.reason !== void 0) {
21
+ addFieldIssue(
22
+ "reason",
23
+ "reason is only allowed when status is denied or cancelled"
24
+ );
25
+ }
26
+ if (value.message !== void 0) {
27
+ addFieldIssue(
28
+ "message",
29
+ "message is only allowed when status is denied or cancelled"
30
+ );
31
+ }
32
+ return;
33
+ }
34
+ if (value.formData !== void 0) {
35
+ addFieldIssue("formData", "formData is only allowed when status is approved");
36
+ }
37
+ if (value.rememberChoice !== void 0) {
38
+ addFieldIssue(
39
+ "rememberChoice",
40
+ "rememberChoice is only allowed when status is approved"
41
+ );
42
+ }
43
+ if (value.rememberPattern !== void 0) {
44
+ addFieldIssue(
45
+ "rememberPattern",
46
+ "rememberPattern is only allowed when status is approved"
47
+ );
48
+ }
49
+ if (value.rememberDirectory !== void 0) {
50
+ addFieldIssue(
51
+ "rememberDirectory",
52
+ "rememberDirectory is only allowed when status is approved"
53
+ );
54
+ }
55
+ if (value.reason === void 0) {
56
+ return;
57
+ }
58
+ if (value.status === ApprovalStatus.DENIED) {
59
+ const invalidReasons2 = /* @__PURE__ */ new Set([
60
+ DenialReason.USER_CANCELLED,
61
+ DenialReason.SYSTEM_CANCELLED,
62
+ DenialReason.TIMEOUT
63
+ ]);
64
+ if (invalidReasons2.has(value.reason)) {
65
+ addFieldIssue("reason", "reason must describe a denial when status is denied");
66
+ }
67
+ return;
68
+ }
69
+ const invalidReasons = /* @__PURE__ */ new Set([
70
+ DenialReason.USER_DENIED,
71
+ DenialReason.SYSTEM_DENIED,
72
+ DenialReason.VALIDATION_FAILED,
73
+ DenialReason.ELICITATION_DISABLED
74
+ ]);
75
+ if (invalidReasons.has(value.reason)) {
76
+ addFieldIssue("reason", "reason must describe a cancellation when status is cancelled");
77
+ }
7
78
  }).describe("Request body for submitting an approval decision");
8
79
  const ApprovalResponseSchema = z.object({
9
80
  ok: z.boolean().describe("Whether the approval was successfully processed"),
10
81
  approvalId: z.string().describe("The ID of the processed approval"),
11
- status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.DENIED]).describe("The final status")
82
+ status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.DENIED, ApprovalStatus.CANCELLED]).describe("The final status")
12
83
  }).describe("Response after processing approval");
13
84
  const PendingApprovalSchema = z.object({
14
85
  approvalId: z.string().describe("The unique ID of the approval request"),
@@ -103,7 +174,15 @@ function createApprovalsRouter(getAgent, approvalCoordinator) {
103
174
  }).openapi(submitApprovalRoute, async (ctx) => {
104
175
  const agent = await getAgent(ctx);
105
176
  const { approvalId } = ctx.req.valid("param");
106
- const { status, formData, rememberChoice } = ctx.req.valid("json");
177
+ const {
178
+ status,
179
+ formData,
180
+ rememberChoice,
181
+ rememberPattern,
182
+ rememberDirectory,
183
+ reason,
184
+ message
185
+ } = ctx.req.valid("json");
107
186
  agent.logger.info(`Received approval decision for ${approvalId}: ${status}`);
108
187
  if (!approvalCoordinator) {
109
188
  agent.logger.error("ApprovalCoordinator not available");
@@ -122,6 +201,12 @@ function createApprovalsRouter(getAgent, approvalCoordinator) {
122
201
  if (rememberChoice !== void 0) {
123
202
  data.rememberChoice = rememberChoice;
124
203
  }
204
+ if (rememberPattern !== void 0) {
205
+ data.rememberPattern = rememberPattern;
206
+ }
207
+ if (rememberDirectory !== void 0) {
208
+ data.rememberDirectory = rememberDirectory;
209
+ }
125
210
  }
126
211
  const sessionId = approvalCoordinator.getSessionId(approvalId);
127
212
  const responsePayload = {
@@ -130,8 +215,11 @@ function createApprovalsRouter(getAgent, approvalCoordinator) {
130
215
  sessionId,
131
216
  // Attach sessionId for SSE routing to correct client streams
132
217
  ...status === ApprovalStatus.DENIED ? {
133
- reason: DenialReason.USER_DENIED,
134
- message: "User denied the request via API"
218
+ reason: reason ?? DenialReason.USER_DENIED,
219
+ message: message ?? "User denied the request via API"
220
+ } : status === ApprovalStatus.CANCELLED ? {
221
+ reason: reason ?? DenialReason.USER_CANCELLED,
222
+ message: message ?? "User cancelled the request via API"
135
223
  } : {},
136
224
  ...Object.keys(data).length > 0 ? { data } : {}
137
225
  };
@@ -94,6 +94,14 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
94
94
  response: import_zod_openapi.z.string().describe("Agent response text"),
95
95
  sessionId: import_zod_openapi.z.string().describe("Session ID used for this message"),
96
96
  tokenUsage: import_responses.TokenUsageSchema.optional().describe("Token usage statistics"),
97
+ messageId: import_zod_openapi.z.string().uuid().optional().describe("Assistant message ID for this response"),
98
+ usageScopeId: import_zod_openapi.z.string().optional().describe(
99
+ "Optional usage scope identifier for runtime-scoped metering"
100
+ ),
101
+ estimatedCost: import_zod_openapi.z.number().nonnegative().optional().describe("Estimated cost in USD for this response"),
102
+ pricingStatus: import_responses.PricingStatusSchema.optional().describe(
103
+ "Whether pricing was resolved for this response"
104
+ ),
97
105
  reasoning: import_zod_openapi.z.string().optional().describe("Extended thinking content from reasoning models"),
98
106
  model: import_zod_openapi.z.string().optional().describe("Model used for this response"),
99
107
  provider: import_zod_openapi.z.enum(import_core.LLM_PROVIDERS).optional().describe("LLM provider")
@@ -131,7 +139,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
131
139
  method: "post",
132
140
  path: "/message-stream",
133
141
  summary: "Stream message response",
134
- 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. If the session is busy processing another message, returns 202 with queue information.",
142
+ 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. Final llm:response events include token usage, assistant message ID, and pricing metadata when available. If the session is busy processing another message, returns 202 with queue information.",
135
143
  tags: ["messages"],
136
144
  request: {
137
145
  body: {
@@ -162,7 +170,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
162
170
  content: {
163
171
  "text/event-stream": {
164
172
  schema: import_zod_openapi.z.string().describe(
165
- "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)"
173
+ "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). Final llm:response payloads include token usage, assistant message ID, and pricing metadata when available."
166
174
  )
167
175
  }
168
176
  }
@@ -200,14 +208,17 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
200
208
  const { content, sessionId } = ctx.req.valid("json");
201
209
  agent.logger.info(`Message for session: ${sessionId}`);
202
210
  const result = await agent.generate(content, sessionId);
203
- const llmConfig = agent.stateManager.getLLMConfig(sessionId);
204
211
  return ctx.json({
205
212
  response: result.content,
206
213
  sessionId: result.sessionId,
207
214
  tokenUsage: result.usage,
215
+ messageId: result.messageId,
216
+ usageScopeId: result.usageScopeId,
217
+ estimatedCost: result.estimatedCost,
218
+ pricingStatus: result.pricingStatus,
208
219
  reasoning: result.reasoning,
209
- model: llmConfig.model,
210
- provider: llmConfig.provider
220
+ model: result.model,
221
+ provider: result.provider
211
222
  });
212
223
  }).openapi(resetRoute, async (ctx) => {
213
224
  const agent = await getAgent(ctx);
@@ -103,10 +103,16 @@ export declare function createMessagesRouter(getAgent: GetAgentFn, approvalCoord
103
103
  inputTokens?: number | undefined;
104
104
  outputTokens?: number | undefined;
105
105
  reasoningTokens?: number | undefined;
106
+ cacheReadTokens?: number | undefined;
107
+ cacheWriteTokens?: number | undefined;
106
108
  totalTokens?: number | undefined;
107
109
  } | undefined;
110
+ estimatedCost?: number | undefined;
111
+ pricingStatus?: "estimated" | "unpriced" | undefined;
112
+ usageScopeId?: string | undefined;
108
113
  model?: string | undefined;
109
114
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova" | undefined;
115
+ messageId?: string | undefined;
110
116
  };
111
117
  outputFormat: "json";
112
118
  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;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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+V5C"}
@@ -1,7 +1,7 @@
1
1
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
2
  import { streamSSE } from "hono/streaming";
3
3
  import { LLM_PROVIDERS } from "@dexto/core";
4
- import { TokenUsageSchema } from "../schemas/responses.js";
4
+ import { PricingStatusSchema, TokenUsageSchema } from "../schemas/responses.js";
5
5
  const TextPartSchema = z.object({
6
6
  type: z.literal("text").describe("Content type identifier"),
7
7
  text: z.string().describe("Text content")
@@ -71,6 +71,14 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
71
71
  response: z.string().describe("Agent response text"),
72
72
  sessionId: z.string().describe("Session ID used for this message"),
73
73
  tokenUsage: TokenUsageSchema.optional().describe("Token usage statistics"),
74
+ messageId: z.string().uuid().optional().describe("Assistant message ID for this response"),
75
+ usageScopeId: z.string().optional().describe(
76
+ "Optional usage scope identifier for runtime-scoped metering"
77
+ ),
78
+ estimatedCost: z.number().nonnegative().optional().describe("Estimated cost in USD for this response"),
79
+ pricingStatus: PricingStatusSchema.optional().describe(
80
+ "Whether pricing was resolved for this response"
81
+ ),
74
82
  reasoning: z.string().optional().describe("Extended thinking content from reasoning models"),
75
83
  model: z.string().optional().describe("Model used for this response"),
76
84
  provider: z.enum(LLM_PROVIDERS).optional().describe("LLM provider")
@@ -108,7 +116,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
108
116
  method: "post",
109
117
  path: "/message-stream",
110
118
  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. If the session is busy processing another message, returns 202 with queue information.",
119
+ 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. Final llm:response events include token usage, assistant message ID, and pricing metadata when available. If the session is busy processing another message, returns 202 with queue information.",
112
120
  tags: ["messages"],
113
121
  request: {
114
122
  body: {
@@ -139,7 +147,7 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
139
147
  content: {
140
148
  "text/event-stream": {
141
149
  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)"
150
+ "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). Final llm:response payloads include token usage, assistant message ID, and pricing metadata when available."
143
151
  )
144
152
  }
145
153
  }
@@ -177,14 +185,17 @@ function createMessagesRouter(getAgent, approvalCoordinator) {
177
185
  const { content, sessionId } = ctx.req.valid("json");
178
186
  agent.logger.info(`Message for session: ${sessionId}`);
179
187
  const result = await agent.generate(content, sessionId);
180
- const llmConfig = agent.stateManager.getLLMConfig(sessionId);
181
188
  return ctx.json({
182
189
  response: result.content,
183
190
  sessionId: result.sessionId,
184
191
  tokenUsage: result.usage,
192
+ messageId: result.messageId,
193
+ usageScopeId: result.usageScopeId,
194
+ estimatedCost: result.estimatedCost,
195
+ pricingStatus: result.pricingStatus,
185
196
  reasoning: result.reasoning,
186
- model: llmConfig.model,
187
- provider: llmConfig.provider
197
+ model: result.model,
198
+ provider: result.provider
188
199
  });
189
200
  }).openapi(resetRoute, async (ctx) => {
190
201
  const agent = await getAgent(ctx);
@@ -53,8 +53,13 @@ export declare function createSearchRouter(getAgent: GetAgentFn): OpenAPIHono<im
53
53
  inputTokens?: number | undefined;
54
54
  outputTokens?: number | undefined;
55
55
  reasoningTokens?: number | undefined;
56
+ cacheReadTokens?: number | undefined;
57
+ cacheWriteTokens?: number | undefined;
56
58
  totalTokens?: number | undefined;
57
59
  } | undefined;
60
+ estimatedCost?: number | undefined;
61
+ pricingStatus?: "estimated" | "unpriced" | undefined;
62
+ usageScopeId?: string | undefined;
58
63
  model?: string | undefined;
59
64
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova" | undefined;
60
65
  toolCalls?: {
@@ -135,8 +140,13 @@ export declare function createSearchRouter(getAgent: GetAgentFn): OpenAPIHono<im
135
140
  inputTokens?: number | undefined;
136
141
  outputTokens?: number | undefined;
137
142
  reasoningTokens?: number | undefined;
143
+ cacheReadTokens?: number | undefined;
144
+ cacheWriteTokens?: number | undefined;
138
145
  totalTokens?: number | undefined;
139
146
  } | undefined;
147
+ estimatedCost?: number | undefined;
148
+ pricingStatus?: "estimated" | "unpriced" | undefined;
149
+ usageScopeId?: string | undefined;
140
150
  model?: string | undefined;
141
151
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | "minimax" | "glm" | "openrouter" | "litellm" | "glama" | "vertex" | "bedrock" | "local" | "ollama" | "dexto-nova" | undefined;
142
152
  toolCalls?: {
@@ -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;AAE9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AA0BrE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwDtD"}
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;AAE9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AA0BrE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwDtD"}