@novu/framework 2.11.1 → 2.11.2-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -9
- package/ai-sdk/package.json +4 -0
- package/cards/package.json +4 -0
- package/dist/{esm/index-D6L0Yufw.d.ts → cjs/agent.types-Dqm2VBTO.d.cts} +410 -193
- package/dist/cjs/ai-sdk/index.cjs +1 -0
- package/dist/cjs/ai-sdk/index.d.cts +40 -0
- package/dist/cjs/cards.cjs +57 -0
- package/dist/cjs/cards.d.cts +2 -0
- package/dist/cjs/{health-check.types-D4NEyjyC.d.cts → health-check.types-B9FbzRbm.d.cts} +6 -140
- package/dist/cjs/index-1DobCKAF.d.cts +160 -0
- package/dist/cjs/index.cjs +138 -138
- package/dist/cjs/index.d.cts +5 -3
- package/dist/cjs/internal/index.cjs +1 -1
- package/dist/cjs/internal/index.d.cts +98 -4
- package/dist/cjs/jsx-dev-runtime.cjs +1 -1
- package/dist/cjs/jsx-runtime.cjs +1 -1
- package/dist/cjs/langchain/index.cjs +1 -0
- package/dist/cjs/langchain/index.d.cts +106 -0
- package/dist/cjs/servers/express.cjs +138 -138
- package/dist/cjs/servers/express.d.cts +6 -4
- package/dist/cjs/servers/h3.cjs +137 -137
- package/dist/cjs/servers/h3.d.cts +6 -4
- package/dist/cjs/servers/lambda.cjs +137 -137
- package/dist/cjs/servers/lambda.d.cts +6 -5
- package/dist/cjs/servers/nest.cjs +138 -138
- package/dist/cjs/servers/nest.d.cts +21 -7
- package/dist/cjs/servers/next.cjs +137 -137
- package/dist/cjs/servers/next.d.cts +6 -4
- package/dist/cjs/servers/nuxt.cjs +137 -137
- package/dist/cjs/servers/nuxt.d.cts +6 -4
- package/dist/cjs/servers/remix.cjs +137 -137
- package/dist/cjs/servers/remix.d.cts +6 -4
- package/dist/cjs/servers/sveltekit.cjs +137 -137
- package/dist/cjs/servers/sveltekit.d.cts +6 -4
- package/dist/cjs/step-resolver.cjs +1 -1
- package/dist/cjs/step-resolver.d.cts +3 -2
- package/dist/cjs/{subscriber.types-PRaHFLJu.d.cts → subscriber.types-DubxcL8q.d.cts} +18 -78
- package/dist/cjs/util.types-DaFfsxgy.d.cts +78 -0
- package/dist/cjs/validators.cjs +1 -1
- package/dist/{cjs/index-BNiIiOE-.d.cts → esm/agent.types-E3sxq6xr.d.ts} +410 -193
- package/dist/esm/ai-sdk/index.d.ts +40 -0
- package/dist/esm/ai-sdk/index.js +1 -0
- package/dist/esm/cards.d.ts +2 -0
- package/dist/esm/cards.js +1 -0
- package/dist/esm/{chunk-DKQLYSZS.js → chunk-22DBAEUX.js} +1 -1
- package/dist/esm/{chunk-KLCBNFAF.js → chunk-3XT6S7TZ.js} +14 -14
- package/dist/esm/chunk-3ZWME5KT.js +0 -0
- package/dist/esm/chunk-C3P3ZH2I.js +36 -0
- package/dist/esm/{chunk-QTWEINJ4.js → chunk-CANJPWLT.js} +1 -1
- package/dist/esm/chunk-E2MET7IR.js +1 -0
- package/dist/esm/chunk-FHYMHX3T.js +1 -0
- package/dist/esm/chunk-Q6BV36LU.js +98 -0
- package/dist/esm/chunk-W6DIBD4Z.js +1 -0
- package/dist/esm/{health-check.types-C-81VaBO.d.ts → health-check.types-BNocZ4Wk.d.ts} +6 -140
- package/dist/esm/index-aVljLqR4.d.ts +160 -0
- package/dist/esm/index.d.ts +5 -3
- package/dist/esm/index.js +1 -1
- package/dist/esm/internal/index.d.ts +98 -4
- package/dist/esm/internal/index.js +1 -1
- package/dist/esm/jsx-dev-runtime.js +1 -1
- package/dist/esm/jsx-runtime-7EPQR56T.js +1 -0
- package/dist/esm/jsx-runtime.js +1 -1
- package/dist/esm/langchain/index.d.ts +106 -0
- package/dist/esm/langchain/index.js +1 -0
- package/dist/esm/servers/express.d.ts +6 -4
- package/dist/esm/servers/express.js +1 -1
- package/dist/esm/servers/h3.d.ts +6 -4
- package/dist/esm/servers/h3.js +1 -1
- package/dist/esm/servers/lambda.d.ts +6 -5
- package/dist/esm/servers/lambda.js +1 -1
- package/dist/esm/servers/nest.d.ts +21 -7
- package/dist/esm/servers/nest.js +1 -1
- package/dist/esm/servers/next.d.ts +6 -4
- package/dist/esm/servers/next.js +1 -1
- package/dist/esm/servers/nuxt.d.ts +6 -4
- package/dist/esm/servers/nuxt.js +1 -1
- package/dist/esm/servers/remix.d.ts +6 -4
- package/dist/esm/servers/remix.js +1 -1
- package/dist/esm/servers/sveltekit.d.ts +6 -4
- package/dist/esm/servers/sveltekit.js +1 -1
- package/dist/esm/step-resolver.d.ts +3 -2
- package/dist/esm/step-resolver.js +1 -1
- package/dist/esm/{subscriber.types-CC7F0JO_.d.ts → subscriber.types-CmybpXhA.d.ts} +18 -78
- package/dist/esm/util.types-DaFfsxgy.d.ts +78 -0
- package/dist/esm/validators.js +1 -1
- package/package.json +56 -8
- package/dist/esm/chunk-52LSX2V5.js +0 -1
- package/dist/esm/chunk-N4PZBM53.js +0 -1
- package/dist/esm/chunk-ND6IQFTA.js +0 -133
|
@@ -1,8 +1,198 @@
|
|
|
1
1
|
import { ChatElement, Emoji, CardElement } from 'chat';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { A as Awaitable } from './util.types-DaFfsxgy.cjs';
|
|
3
|
+
|
|
4
|
+
type AgentErrorDelivery = {
|
|
5
|
+
statusCode: number;
|
|
6
|
+
responseBody: string;
|
|
7
|
+
};
|
|
8
|
+
type AgentErrorOptions = {
|
|
9
|
+
cause?: unknown;
|
|
10
|
+
delivery?: AgentErrorDelivery;
|
|
11
|
+
};
|
|
12
|
+
/** Turn and handler failures. Delivery failures use {@link AgentDeliveryError}. */
|
|
13
|
+
declare class AgentError extends Error {
|
|
14
|
+
readonly cause?: unknown;
|
|
15
|
+
readonly delivery?: AgentErrorDelivery;
|
|
16
|
+
constructor(message: string, options?: AgentErrorOptions);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Thrown by `ctx.reply()` and `handle.edit()` when the upstream message delivery
|
|
20
|
+
* fails — e.g. the configured email provider returns 401, Slack rejects the token,
|
|
21
|
+
* or Teams rejects the request.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { AgentDeliveryError } from '@novu/framework';
|
|
26
|
+
*
|
|
27
|
+
* try {
|
|
28
|
+
* await ctx.reply('Hello!');
|
|
29
|
+
* } catch (err) {
|
|
30
|
+
* if (err instanceof AgentDeliveryError) {
|
|
31
|
+
* console.error('Delivery failed:', err.message, err.statusCode);
|
|
32
|
+
* return;
|
|
33
|
+
* }
|
|
34
|
+
* throw err;
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare class AgentDeliveryError extends AgentError {
|
|
39
|
+
readonly statusCode: number;
|
|
40
|
+
readonly responseBody: string;
|
|
41
|
+
constructor(statusCode: number, responseBody: string);
|
|
42
|
+
}
|
|
43
|
+
declare function toAgentError(err: unknown): AgentError;
|
|
44
|
+
|
|
45
|
+
declare enum ChannelTypeEnum {
|
|
46
|
+
IN_APP = "in_app",
|
|
47
|
+
EMAIL = "email",
|
|
48
|
+
SMS = "sms",
|
|
49
|
+
CHAT = "chat",
|
|
50
|
+
PUSH = "push"
|
|
51
|
+
}
|
|
52
|
+
interface IAttachmentOptions {
|
|
53
|
+
mime: string;
|
|
54
|
+
file: Buffer;
|
|
55
|
+
name?: string;
|
|
56
|
+
channels?: ChannelTypeEnum[];
|
|
57
|
+
cid?: string;
|
|
58
|
+
disposition?: string;
|
|
59
|
+
}
|
|
60
|
+
interface ITriggerPayload {
|
|
61
|
+
attachments?: IAttachmentOptions[];
|
|
62
|
+
[key: string]: string | string[] | boolean | number | undefined | IAttachmentOptions | IAttachmentOptions[] | Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
interface ISubscriberPayload {
|
|
65
|
+
subscriberId: string;
|
|
66
|
+
firstName?: string;
|
|
67
|
+
lastName?: string;
|
|
68
|
+
email?: string;
|
|
69
|
+
phone?: string;
|
|
70
|
+
avatar?: string;
|
|
71
|
+
locale?: string;
|
|
72
|
+
data?: Record<string, unknown>;
|
|
73
|
+
channels?: ISubscriberChannel[];
|
|
74
|
+
}
|
|
75
|
+
interface ISubscriberChannel {
|
|
76
|
+
providerId: ChatProviderIdEnum | PushProviderIdEnum;
|
|
77
|
+
integrationIdentifier?: string;
|
|
78
|
+
credentials: IChannelCredentials;
|
|
79
|
+
}
|
|
80
|
+
interface IChannelCredentials {
|
|
81
|
+
webhookUrl?: string;
|
|
82
|
+
deviceTokens?: string[];
|
|
83
|
+
}
|
|
84
|
+
interface ITopic {
|
|
85
|
+
type: 'Topic';
|
|
86
|
+
topicKey: string;
|
|
87
|
+
exclude?: string[];
|
|
88
|
+
}
|
|
89
|
+
type TriggerRecipientsPayload = string | ISubscriberPayload | ITopic | ISubscriberPayload[] | ITopic[];
|
|
90
|
+
declare enum TriggerEventStatusEnum {
|
|
91
|
+
ERROR = "error",
|
|
92
|
+
NOT_ACTIVE = "trigger_not_active",
|
|
93
|
+
NO_WORKFLOW_ACTIVE_STEPS = "no_workflow_active_steps_defined",
|
|
94
|
+
NO_WORKFLOW_STEPS = "no_workflow_steps_defined",
|
|
95
|
+
PROCESSED = "processed",
|
|
96
|
+
SUBSCRIBER_MISSING = "subscriber_id_missing",
|
|
97
|
+
TENANT_MISSING = "no_tenant_found"
|
|
98
|
+
}
|
|
99
|
+
declare enum ChatProviderIdEnum {
|
|
100
|
+
Slack = "slack",
|
|
101
|
+
Discord = "discord",
|
|
102
|
+
MsTeams = "msteams",
|
|
103
|
+
Mattermost = "mattermost",
|
|
104
|
+
Ryver = "ryver",
|
|
105
|
+
Zulip = "zulip",
|
|
106
|
+
GrafanaOnCall = "grafana-on-call",
|
|
107
|
+
GetStream = "getstream",
|
|
108
|
+
RocketChat = "rocket-chat",
|
|
109
|
+
WhatsAppBusiness = "whatsapp-business",
|
|
110
|
+
ChatWebhook = "chat-webhook",
|
|
111
|
+
Telegram = "telegram",
|
|
112
|
+
Sendblue = "sendblue"
|
|
113
|
+
}
|
|
114
|
+
declare enum PushProviderIdEnum {
|
|
115
|
+
FCM = "fcm",
|
|
116
|
+
APNS = "apns",
|
|
117
|
+
EXPO = "expo",
|
|
118
|
+
OneSignal = "one-signal",
|
|
119
|
+
Pushpad = "pushpad",
|
|
120
|
+
PushWebhook = "push-webhook",
|
|
121
|
+
PusherBeams = "pusher-beams",
|
|
122
|
+
AppIO = "appio"
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* A preference for a notification delivery workflow.
|
|
126
|
+
*
|
|
127
|
+
* This provides a shortcut to setting all channels to the same preference.
|
|
128
|
+
*/
|
|
129
|
+
type WorkflowPreference = {
|
|
130
|
+
/**
|
|
131
|
+
* A flag specifying if notification delivery is enabled for the workflow.
|
|
132
|
+
*
|
|
133
|
+
* If `true`, notification delivery is enabled by default for all channels.
|
|
134
|
+
*
|
|
135
|
+
* This setting can be overridden by the channel preferences.
|
|
136
|
+
*
|
|
137
|
+
* @default true
|
|
138
|
+
*/
|
|
139
|
+
enabled: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* A flag specifying if the preference is read-only.
|
|
142
|
+
*
|
|
143
|
+
* If `true`, the preference cannot be changed by the Subscriber.
|
|
144
|
+
*
|
|
145
|
+
* @default false
|
|
146
|
+
*/
|
|
147
|
+
readOnly: boolean;
|
|
148
|
+
};
|
|
149
|
+
/** A preference for a notification delivery channel. */
|
|
150
|
+
type ChannelPreference = {
|
|
151
|
+
/**
|
|
152
|
+
* A flag specifying if notification delivery is enabled for the channel.
|
|
153
|
+
*
|
|
154
|
+
* If `true`, notification delivery is enabled.
|
|
155
|
+
*
|
|
156
|
+
* @default true
|
|
157
|
+
*/
|
|
158
|
+
enabled: boolean;
|
|
159
|
+
};
|
|
160
|
+
type WorkflowPreferences = {
|
|
161
|
+
/**
|
|
162
|
+
* A preference for the workflow.
|
|
163
|
+
*
|
|
164
|
+
* The values specified here will be used if no preference is specified for a channel.
|
|
165
|
+
*/
|
|
166
|
+
all: WorkflowPreference;
|
|
167
|
+
/**
|
|
168
|
+
* A preference for each notification delivery channel.
|
|
169
|
+
*
|
|
170
|
+
* If no preference is specified for a channel, the `all` preference will be used.
|
|
171
|
+
*/
|
|
172
|
+
channels: Record<ChannelTypeEnum, ChannelPreference>;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Recursively make all properties of type `T` optional.
|
|
176
|
+
*/
|
|
177
|
+
type DeepPartial<T> = T extends object ? {
|
|
178
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
179
|
+
} : T;
|
|
180
|
+
/** A partial set of workflow preferences. */
|
|
181
|
+
type WorkflowPreferencesPartial = DeepPartial<WorkflowPreferences>;
|
|
182
|
+
|
|
183
|
+
type Verdict = 'approve' | 'deny';
|
|
184
|
+
interface ToolApprovalRequestPayload {
|
|
185
|
+
approvalId: string;
|
|
186
|
+
toolCallId: string;
|
|
187
|
+
name: string;
|
|
188
|
+
input?: Record<string, unknown>;
|
|
189
|
+
}
|
|
190
|
+
interface ParsedApprovalAction {
|
|
191
|
+
approved: boolean;
|
|
192
|
+
approvalId: string;
|
|
193
|
+
}
|
|
194
|
+
declare function buildApprovalActionId(verdict: Verdict, approvalId: string): string;
|
|
195
|
+
declare function parseApprovalActionId(id: string | undefined): ParsedApprovalAction | null;
|
|
6
196
|
|
|
7
197
|
declare enum AgentEventEnum {
|
|
8
198
|
ON_MESSAGE = "onMessage",
|
|
@@ -64,6 +254,24 @@ interface AgentSubscriber {
|
|
|
64
254
|
/** Arbitrary custom data attached to the subscriber in Novu. */
|
|
65
255
|
data?: Record<string, unknown>;
|
|
66
256
|
}
|
|
257
|
+
/**
|
|
258
|
+
* Tool-call details on a tool-related history entry. Which fields are set depends on the
|
|
259
|
+
* entry's `type` (`tool_approval_request`, `tool_approval_decision`, or `tool_result`).
|
|
260
|
+
*/
|
|
261
|
+
interface AgentToolData {
|
|
262
|
+
/** Id of the tool call. */
|
|
263
|
+
toolCallId?: string;
|
|
264
|
+
/** Name of the tool. */
|
|
265
|
+
toolName?: string;
|
|
266
|
+
/** Id linking an approval request to its decision. */
|
|
267
|
+
approvalId?: string;
|
|
268
|
+
/** Arguments the tool was called with. */
|
|
269
|
+
input?: Record<string, unknown>;
|
|
270
|
+
/** Whether the tool call was approved or denied. */
|
|
271
|
+
approved?: boolean;
|
|
272
|
+
/** What the tool returned (or the `execution-denied` marker for a denied call). */
|
|
273
|
+
output?: unknown;
|
|
274
|
+
}
|
|
67
275
|
/**
|
|
68
276
|
* A single entry in the conversation history.
|
|
69
277
|
* `ctx.history` is an ordered array of these entries — map them to your LLM's
|
|
@@ -72,17 +280,22 @@ interface AgentSubscriber {
|
|
|
72
280
|
interface AgentHistoryEntry {
|
|
73
281
|
/** Message role: `'user'`, `'assistant'`, or `'system'`. */
|
|
74
282
|
role: string;
|
|
75
|
-
/**
|
|
283
|
+
/**
|
|
284
|
+
* The kind of entry: `'message'`, `'edit'`, `'signal'`, or a tool-lifecycle event
|
|
285
|
+
* (`'tool_approval_request'`, `'tool_approval_decision'`, `'tool_result'`).
|
|
286
|
+
*/
|
|
76
287
|
type: string;
|
|
77
288
|
/** Plain-text representation of the message content. */
|
|
78
289
|
content: string;
|
|
79
290
|
richContent?: Record<string, unknown>;
|
|
80
291
|
senderName?: string;
|
|
81
|
-
/**
|
|
292
|
+
/** Structured data for `signal` entries (e.g. metadata updates). */
|
|
82
293
|
signalData?: {
|
|
83
294
|
type: string;
|
|
84
295
|
payload?: Record<string, unknown>;
|
|
85
296
|
};
|
|
297
|
+
/** Tool-call details — set on tool-lifecycle entries (`tool_*`). */
|
|
298
|
+
toolData?: AgentToolData;
|
|
86
299
|
createdAt: string;
|
|
87
300
|
}
|
|
88
301
|
/** Resolved inbound email domain metadata (present when `platform === 'email'`). */
|
|
@@ -150,6 +363,7 @@ type MessageContent = string | ChatElement;
|
|
|
150
363
|
interface ReplyContent {
|
|
151
364
|
markdown?: string;
|
|
152
365
|
card?: CardElement;
|
|
366
|
+
toolApprovalCard?: ToolApprovalCard;
|
|
153
367
|
files?: FileRef[];
|
|
154
368
|
}
|
|
155
369
|
/**
|
|
@@ -166,6 +380,89 @@ interface AgentAction {
|
|
|
166
380
|
/** Platform-native message ID of the message containing the clicked button/action. */
|
|
167
381
|
sourceMessageId?: string;
|
|
168
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* A tool call that requires user approval before it runs.
|
|
385
|
+
* Pass this to `ctx.toolApproval.request()` when your agent wants to gate a tool.
|
|
386
|
+
*/
|
|
387
|
+
interface AgentToolCall {
|
|
388
|
+
id: string;
|
|
389
|
+
name: string;
|
|
390
|
+
input?: Record<string, unknown>;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Presentation descriptor for Novu's built-in tool-approval card. Returned by the
|
|
394
|
+
* injected `approvalCard()` helper. Novu renders it natively on Slack and as a
|
|
395
|
+
* portable fallback elsewhere; Approve/Deny action ids are always supplied by Novu.
|
|
396
|
+
*
|
|
397
|
+
* Channel mapping (self-hosted):
|
|
398
|
+
* - **Slack (native card):** `icon`, `title`, `subtitle`, `body`, `approveLabel`, `denyLabel`
|
|
399
|
+
* - **Other channels (portable card):** `title`, `subtitle`, `approveLabel`, `denyLabel`
|
|
400
|
+
*
|
|
401
|
+
* `icon` and `body` are ignored on non-Slack channels — the portable fallback has no
|
|
402
|
+
* card image or body block. Catalog icons are 32×32; custom `https://` URLs should match.
|
|
403
|
+
*/
|
|
404
|
+
interface ToolApprovalCard {
|
|
405
|
+
type: 'tool-approval-card';
|
|
406
|
+
/** Slack only. Catalog id (`'stripe'`), `https://` URL, or omit to auto-match the tool name. Use 32×32 px for custom URLs. */
|
|
407
|
+
icon?: string;
|
|
408
|
+
/** All channels. Card title. Defaults to `Tool approval required`. */
|
|
409
|
+
title?: string;
|
|
410
|
+
/** All channels. Card subtitle; auto-generated from the tool name/input when omitted. */
|
|
411
|
+
subtitle?: string;
|
|
412
|
+
/** Slack only. Optional markdown body (e.g. argument preview). Not shown on portable fallback. */
|
|
413
|
+
body?: string;
|
|
414
|
+
/** All channels. Approve button label. Defaults to `Approve`. */
|
|
415
|
+
approveLabel?: string;
|
|
416
|
+
/** All channels. Deny button label. Defaults to `Deny`. */
|
|
417
|
+
denyLabel?: string;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Returned by `ctx.toolApproval.request()`. Return it from `onMessage` to post
|
|
421
|
+
* an approval card and end the turn until the user approves or denies.
|
|
422
|
+
*/
|
|
423
|
+
declare class PendingApproval {
|
|
424
|
+
readonly __novuPendingApproval: true;
|
|
425
|
+
}
|
|
426
|
+
/** Optional customization for tool approval messages. */
|
|
427
|
+
interface ToolApprovalConfig {
|
|
428
|
+
/**
|
|
429
|
+
* Build the approval message shown while waiting for a decision.
|
|
430
|
+
*
|
|
431
|
+
* Return `approvalCard(...)` for Novu's channel-adaptive card (native on Slack,
|
|
432
|
+
* fallback elsewhere), or return a string/`Card` to take full control (portable
|
|
433
|
+
* on every channel). Use the provided `actionIds` on your own buttons.
|
|
434
|
+
*/
|
|
435
|
+
renderApproval?: (args: {
|
|
436
|
+
toolCall: AgentToolCall;
|
|
437
|
+
actionIds: {
|
|
438
|
+
approve: string;
|
|
439
|
+
deny: string;
|
|
440
|
+
};
|
|
441
|
+
approvalCard: (overrides?: Omit<ToolApprovalCard, 'type'>) => ToolApprovalCard;
|
|
442
|
+
}) => MessageContent | ToolApprovalCard;
|
|
443
|
+
}
|
|
444
|
+
/** Passed to `onToolApproval` when the user clicks Approve or Deny. */
|
|
445
|
+
interface ToolApprovalDecision {
|
|
446
|
+
/** The tool that was awaiting approval. */
|
|
447
|
+
toolCall: AgentToolCall;
|
|
448
|
+
/** `true` if the user approved, `false` if they denied. */
|
|
449
|
+
approved: boolean;
|
|
450
|
+
/**
|
|
451
|
+
* Handle to the approval message. When you register `onToolApproval`, you own
|
|
452
|
+
* card cleanup — call `edit()` or `delete()` as needed. When the framework
|
|
453
|
+
* handles the approval click, the card is deleted for you.
|
|
454
|
+
*/
|
|
455
|
+
approvalMessage: ReplyHandle;
|
|
456
|
+
}
|
|
457
|
+
/** Controls on `ctx.toolApproval` for gating tool calls. */
|
|
458
|
+
interface ToolApprovalControl {
|
|
459
|
+
/**
|
|
460
|
+
* Post an approval message and pause the turn.
|
|
461
|
+
* Return the result (`return ctx.toolApproval.request(...)`) from `onMessage`
|
|
462
|
+
* to end the turn until the user decides.
|
|
463
|
+
*/
|
|
464
|
+
request(toolCall: AgentToolCall): Promise<PendingApproval>;
|
|
465
|
+
}
|
|
169
466
|
/** An emoji reaction added to or removed from a message. */
|
|
170
467
|
interface AgentReaction {
|
|
171
468
|
/** Platform-native ID of the message that was reacted to. */
|
|
@@ -192,8 +489,10 @@ interface ReplyHandle {
|
|
|
192
489
|
edit(content: MessageContent, options?: {
|
|
193
490
|
files?: FileRef[];
|
|
194
491
|
}): Promise<ReplyHandle>;
|
|
492
|
+
/** Delete this message from the platform. Removes the rendered message only — history is preserved. */
|
|
493
|
+
delete(): Promise<void>;
|
|
195
494
|
}
|
|
196
|
-
interface
|
|
495
|
+
interface AgentHandlerContext {
|
|
197
496
|
/** Live state of the current conversation, including persisted metadata. */
|
|
198
497
|
readonly conversation: AgentConversation;
|
|
199
498
|
/**
|
|
@@ -227,6 +526,15 @@ interface AgentContextBase {
|
|
|
227
526
|
reply(content: MessageContent, options?: {
|
|
228
527
|
files?: FileRef[];
|
|
229
528
|
}): Promise<ReplyHandle>;
|
|
529
|
+
/**
|
|
530
|
+
* Gate tool calls that need user approval before they run.
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* if (needsApproval(toolCall)) {
|
|
534
|
+
* return ctx.toolApproval.request(toolCall);
|
|
535
|
+
* }
|
|
536
|
+
*/
|
|
537
|
+
readonly toolApproval: ToolApprovalControl;
|
|
230
538
|
/**
|
|
231
539
|
* Mark the conversation as resolved. Optionally provide a summary for the resolution record.
|
|
232
540
|
* Triggers the `onResolve` handler if one is registered.
|
|
@@ -285,25 +593,49 @@ interface AgentContextBase {
|
|
|
285
593
|
* await ctx.reply('Done!');
|
|
286
594
|
*/
|
|
287
595
|
addReaction(messageId: string, emojiName: Emoji): void;
|
|
596
|
+
/**
|
|
597
|
+
* Delete a platform message by id. Queued and flushed with the next `ctx.reply()`,
|
|
598
|
+
* or automatically when the handler completes (same batching as `ctx.addReaction()`).
|
|
599
|
+
* Deletes the rendered message only — conversation history is preserved.
|
|
600
|
+
*
|
|
601
|
+
* @example
|
|
602
|
+
* ctx.deleteMessage(ctx.action!.sourceMessageId!);
|
|
603
|
+
* await ctx.reply('Processing…');
|
|
604
|
+
*/
|
|
605
|
+
deleteMessage(messageId: string): void;
|
|
606
|
+
/**
|
|
607
|
+
* Control the typing / "Thinking…" status for the current turn.
|
|
608
|
+
* Posts immediately (like `reply()`), updating the indicator Novu already shows on inbound.
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* await ctx.typing('Searching the docs…'); // set / replace the status text
|
|
612
|
+
* await ctx.typing(); // reset to the default "Thinking…"
|
|
613
|
+
* await ctx.typing.stop(); // clear it for this turn
|
|
614
|
+
*
|
|
615
|
+
* Behaviour is best-effort per platform: custom text shows on Slack-like platforms,
|
|
616
|
+
* a generic typing bubble on others, and is a no-op where there is no typing channel
|
|
617
|
+
* (e.g. email). A normal turn that ends with `ctx.reply()` clears the status automatically.
|
|
618
|
+
*/
|
|
619
|
+
typing: TypingControl;
|
|
288
620
|
}
|
|
289
621
|
/** Context passed to the `onMessage` handler. */
|
|
290
|
-
interface AgentMessageContext extends
|
|
622
|
+
interface AgentMessageContext extends AgentHandlerContext {
|
|
291
623
|
readonly event: 'onMessage';
|
|
292
624
|
}
|
|
293
625
|
/** Context passed to the `onAction` handler. */
|
|
294
|
-
interface AgentActionContext extends
|
|
626
|
+
interface AgentActionContext extends AgentHandlerContext {
|
|
295
627
|
readonly event: 'onAction';
|
|
296
628
|
/** The button click or interactive action that triggered this handler. */
|
|
297
629
|
readonly action: AgentAction;
|
|
298
630
|
}
|
|
299
631
|
/** Context passed to the `onReaction` handler. */
|
|
300
|
-
interface AgentReactionContext extends
|
|
632
|
+
interface AgentReactionContext extends AgentHandlerContext {
|
|
301
633
|
readonly event: 'onReaction';
|
|
302
634
|
/** The emoji reaction that triggered this handler. */
|
|
303
635
|
readonly reaction: AgentReaction;
|
|
304
636
|
}
|
|
305
637
|
/** Context passed to the `onResolve` handler. */
|
|
306
|
-
interface AgentResolveContext extends
|
|
638
|
+
interface AgentResolveContext extends AgentHandlerContext {
|
|
307
639
|
readonly event: 'onResolve';
|
|
308
640
|
}
|
|
309
641
|
type AgentContext = AgentMessageContext | AgentActionContext | AgentReactionContext | AgentResolveContext;
|
|
@@ -346,10 +678,41 @@ interface AgentHandlers {
|
|
|
346
678
|
* `ctx.subscriber` and `ctx.conversation`.
|
|
347
679
|
*/
|
|
348
680
|
onResolve?: (ctx: AgentResolveContext) => Awaitable<MessageContent | void>;
|
|
681
|
+
/**
|
|
682
|
+
* Fires when the user approves or denies a tool call you previously gated with
|
|
683
|
+
* `ctx.toolApproval.request()`.
|
|
684
|
+
*
|
|
685
|
+
* @param decision - The tool, the user's verdict, and a handle to the approval message.
|
|
686
|
+
* @param ctx - Conversation context (history, subscriber, metadata, reply/trigger methods).
|
|
687
|
+
*
|
|
688
|
+
* Run the tool (or skip it), then return a reply or call `ctx.reply()` directly.
|
|
689
|
+
* Register this handler whenever you call `ctx.toolApproval.request()` in `onMessage`.
|
|
690
|
+
*/
|
|
691
|
+
onToolApproval?: (decision: ToolApprovalDecision, ctx: AgentActionContext) => Awaitable<MessageContent | void>;
|
|
692
|
+
/**
|
|
693
|
+
* Optional turn failure handler. Return `{ suppress: true }` to skip user notification,
|
|
694
|
+
* return message content for a custom user reply, or return nothing to auto-report
|
|
695
|
+
* `{ error: true }` to Novu (generic end-user copy delivered by the API).
|
|
696
|
+
*/
|
|
697
|
+
onError?: (error: AgentError, ctx: AgentMessageContext | AgentActionContext | AgentReactionContext | AgentResolveContext) => Awaitable<AgentErrorResult>;
|
|
698
|
+
/**
|
|
699
|
+
* Customize how approval messages look. Omit to use the built-in Approve/Deny card.
|
|
700
|
+
*/
|
|
701
|
+
toolApproval?: ToolApprovalConfig;
|
|
349
702
|
}
|
|
703
|
+
type AgentErrorSuppress = {
|
|
704
|
+
suppress: true;
|
|
705
|
+
};
|
|
706
|
+
type AgentErrorResult = MessageContent | void | AgentErrorSuppress;
|
|
350
707
|
interface Agent {
|
|
351
708
|
id: string;
|
|
352
709
|
handlers: AgentHandlers;
|
|
710
|
+
/**
|
|
711
|
+
* @internal Set by `agent()` / ai-sdk registration. True when the application
|
|
712
|
+
* author registered `onToolApproval` (full manual card cleanup). False when
|
|
713
|
+
* only a framework wrapper handles approval clicks (auto-delete after handler).
|
|
714
|
+
*/
|
|
715
|
+
userOnToolApproval?: boolean;
|
|
353
716
|
}
|
|
354
717
|
interface AgentBridgeRequest {
|
|
355
718
|
version: number;
|
|
@@ -398,6 +761,17 @@ type TriggerSignal = {
|
|
|
398
761
|
payload?: Record<string, unknown>;
|
|
399
762
|
};
|
|
400
763
|
type Signal = MetadataSignal | TriggerSignal;
|
|
764
|
+
/** The outcome of a tool call, reported back so it's saved in the conversation history. */
|
|
765
|
+
type ToolResult = {
|
|
766
|
+
/** Id of the tool call this result belongs to. */
|
|
767
|
+
toolCallId: string;
|
|
768
|
+
/** Name of the tool. */
|
|
769
|
+
toolName?: string;
|
|
770
|
+
/** What the tool returned (or the `execution-denied` marker for a denied call). */
|
|
771
|
+
output: unknown;
|
|
772
|
+
/** Optional human-readable summary shown in the conversation timeline. */
|
|
773
|
+
preview?: string;
|
|
774
|
+
};
|
|
401
775
|
/** In-place edit of a previously posted agent message. Identified by platform message id. */
|
|
402
776
|
interface EditPayload {
|
|
403
777
|
messageId: string;
|
|
@@ -408,6 +782,24 @@ interface AddReactionPayload {
|
|
|
408
782
|
messageId: string;
|
|
409
783
|
emojiName: Emoji;
|
|
410
784
|
}
|
|
785
|
+
/** Delete a previously posted platform message. Removes the rendered message only — history is preserved. */
|
|
786
|
+
interface DeleteMessagePayload {
|
|
787
|
+
messageId: string;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Per-turn typing/status control op sent on the reply contract.
|
|
791
|
+
* - `{ status?: string }` — set/replace the status; omit `status` for the default "Thinking…".
|
|
792
|
+
* - `'stop'` — clear the status for this turn.
|
|
793
|
+
*/
|
|
794
|
+
type TypingOp = {
|
|
795
|
+
status?: string;
|
|
796
|
+
} | 'stop';
|
|
797
|
+
/**
|
|
798
|
+
* `ctx.typing` surface: a callable that sets/updates the status, plus `.stop()` to clear it.
|
|
799
|
+
*/
|
|
800
|
+
type TypingControl = ((status?: string) => Promise<void>) & {
|
|
801
|
+
stop: () => Promise<void>;
|
|
802
|
+
};
|
|
411
803
|
interface AgentReplyPayload {
|
|
412
804
|
conversationId: string;
|
|
413
805
|
integrationIdentifier: string;
|
|
@@ -417,7 +809,13 @@ interface AgentReplyPayload {
|
|
|
417
809
|
summary?: string;
|
|
418
810
|
};
|
|
419
811
|
signals?: Signal[];
|
|
812
|
+
toolResults?: ToolResult[];
|
|
813
|
+
toolApprovalRequest?: ToolApprovalRequestPayload;
|
|
420
814
|
addReactions?: AddReactionPayload[];
|
|
815
|
+
deleteMessages?: DeleteMessagePayload[];
|
|
816
|
+
typing?: TypingOp;
|
|
817
|
+
/** Bridge reports a real turn failure; Novu delivers generic user copy. */
|
|
818
|
+
error?: true;
|
|
421
819
|
}
|
|
422
820
|
/** Shape returned by /agents/:id/reply when a reply or edit was delivered. */
|
|
423
821
|
interface SentMessageInfo {
|
|
@@ -425,185 +823,4 @@ interface SentMessageInfo {
|
|
|
425
823
|
platformThreadId: string;
|
|
426
824
|
}
|
|
427
825
|
|
|
428
|
-
|
|
429
|
-
* Thrown by `ctx.reply()` and `handle.edit()` when the upstream message delivery
|
|
430
|
-
* fails — e.g. the configured email provider returns 401, Slack rejects the token,
|
|
431
|
-
* or Teams rejects the request.
|
|
432
|
-
*
|
|
433
|
-
* `message` is always a short, human-readable summary.
|
|
434
|
-
* `responseBody` preserves the raw upstream body for debugging.
|
|
435
|
-
*
|
|
436
|
-
* @example
|
|
437
|
-
* ```ts
|
|
438
|
-
* import { AgentDeliveryError } from '@novu/framework';
|
|
439
|
-
*
|
|
440
|
-
* try {
|
|
441
|
-
* await ctx.reply('Hello!');
|
|
442
|
-
* } catch (err) {
|
|
443
|
-
* if (err instanceof AgentDeliveryError) {
|
|
444
|
-
* console.error('Delivery failed:', err.message);
|
|
445
|
-
* return;
|
|
446
|
-
* }
|
|
447
|
-
* throw err;
|
|
448
|
-
* }
|
|
449
|
-
* ```
|
|
450
|
-
*/
|
|
451
|
-
declare class AgentDeliveryError extends Error {
|
|
452
|
-
readonly statusCode: number;
|
|
453
|
-
readonly responseBody: string;
|
|
454
|
-
constructor(statusCode: number, responseBody: string);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Define a new conversational agent.
|
|
459
|
-
*
|
|
460
|
-
* @param agentId - Unique identifier matching the agent entity created in Novu (e.g. 'wine-bot')
|
|
461
|
-
* @param handlers - Handler functions for agent events
|
|
462
|
-
*/
|
|
463
|
-
declare function agent(agentId: string, handlers: AgentHandlers): Agent;
|
|
464
|
-
|
|
465
|
-
declare class Client {
|
|
466
|
-
private discoveredWorkflows;
|
|
467
|
-
private discoverWorkflowPromises;
|
|
468
|
-
private registeredAgents;
|
|
469
|
-
private templateEngine;
|
|
470
|
-
secretKey: string;
|
|
471
|
-
apiUrl: string;
|
|
472
|
-
version: string;
|
|
473
|
-
strictAuthentication: boolean;
|
|
474
|
-
verbose: boolean;
|
|
475
|
-
logger: Logger;
|
|
476
|
-
constructor(options?: ClientOptions);
|
|
477
|
-
private buildOptions;
|
|
478
|
-
private log;
|
|
479
|
-
/**
|
|
480
|
-
* Adds workflows to the client.
|
|
481
|
-
*
|
|
482
|
-
* A locking mechanism is used to ensure that duplicate workflows are not added.
|
|
483
|
-
*
|
|
484
|
-
* @param workflows - The workflows to add.
|
|
485
|
-
*/
|
|
486
|
-
addWorkflows(workflows: Array<Workflow>): Promise<void>;
|
|
487
|
-
addAgents(agents: Array<Agent>): void;
|
|
488
|
-
getAgent(agentId: string): Agent | undefined;
|
|
489
|
-
private addWorkflow;
|
|
490
|
-
healthCheck(): HealthCheck;
|
|
491
|
-
private getWorkflow;
|
|
492
|
-
private getStep;
|
|
493
|
-
private getRegisteredWorkflows;
|
|
494
|
-
discover(): DiscoverOutput;
|
|
495
|
-
/**
|
|
496
|
-
* Mocks data based on the given schema.
|
|
497
|
-
* The `default` value in the schema is used as the base data.
|
|
498
|
-
* If no `default` value is provided, the data is generated using JSONSchemaFaker.
|
|
499
|
-
*
|
|
500
|
-
* @param schema
|
|
501
|
-
* @returns mocked data
|
|
502
|
-
*/
|
|
503
|
-
private mock;
|
|
504
|
-
private validate;
|
|
505
|
-
private throwInvalidProvider;
|
|
506
|
-
private throwInvalidStep;
|
|
507
|
-
private throwInvalidEvent;
|
|
508
|
-
private executeStepFactory;
|
|
509
|
-
private shouldSanitize;
|
|
510
|
-
private shouldSkip;
|
|
511
|
-
executeWorkflow(event: Event): Promise<ExecuteOutput>;
|
|
512
|
-
private createExecutionPayload;
|
|
513
|
-
private prettyPrintExecute;
|
|
514
|
-
private executeProviders;
|
|
515
|
-
private previewProvider;
|
|
516
|
-
private executeProvider;
|
|
517
|
-
private executeStep;
|
|
518
|
-
private compileControls;
|
|
519
|
-
/**
|
|
520
|
-
* Preprocesses standalone translation patterns.
|
|
521
|
-
* Transforms {{t.key}} to [T:key] placeholder (not Liquid syntax, passes through unchanged).
|
|
522
|
-
*/
|
|
523
|
-
private preprocessTranslationPatterns;
|
|
524
|
-
/**
|
|
525
|
-
* Preprocesses translation keys used as filter arguments.
|
|
526
|
-
* Transforms 't.key' to '[T:key]' placeholder (not Liquid syntax, passes through unchanged).
|
|
527
|
-
* Example: pluralize: 't.apple', 't.apples' → pluralize: '[T:apple]', '[T:apples]'
|
|
528
|
-
*/
|
|
529
|
-
private preprocessFilterTranslationArgs;
|
|
530
|
-
/**
|
|
531
|
-
* Post-processes placeholders back to translation markers after Liquid render.
|
|
532
|
-
* Transforms [T:key] back to {{t.key}} for the translation service.
|
|
533
|
-
*/
|
|
534
|
-
private postprocessTranslationMarkers;
|
|
535
|
-
/**
|
|
536
|
-
* Create the controls for a step, taking both the event controls and the default controls into account
|
|
537
|
-
*
|
|
538
|
-
* @param step The step to create the controls for
|
|
539
|
-
* @param event The event that triggered the step
|
|
540
|
-
* @returns The controls for the step
|
|
541
|
-
*/
|
|
542
|
-
private createStepControls;
|
|
543
|
-
private previewStep;
|
|
544
|
-
private constructStepForPreview;
|
|
545
|
-
private extractMockDataForPreviousSteps;
|
|
546
|
-
private previewRequiredStep;
|
|
547
|
-
private getStepState;
|
|
548
|
-
private getStepCode;
|
|
549
|
-
private getWorkflowCode;
|
|
550
|
-
getCode(workflowId: string, stepId?: string): CodeResult;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
interface ServeHandlerOptions {
|
|
554
|
-
client?: Client;
|
|
555
|
-
workflows?: Array<Workflow>;
|
|
556
|
-
agents?: Array<Agent>;
|
|
557
|
-
}
|
|
558
|
-
type INovuRequestHandlerOptions<Input extends any[] = any[], Output = any> = ServeHandlerOptions & {
|
|
559
|
-
frameworkName: string;
|
|
560
|
-
client?: Client;
|
|
561
|
-
workflows?: Array<Workflow>;
|
|
562
|
-
agents?: Array<Agent>;
|
|
563
|
-
handler: Handler<Input, Output>;
|
|
564
|
-
};
|
|
565
|
-
type Handler<Input extends any[] = any[], Output = any> = (...args: Input) => HandlerResponse<Output>;
|
|
566
|
-
type HandlerResponse<Output = any> = {
|
|
567
|
-
body: () => Awaitable<any>;
|
|
568
|
-
headers: (key: string) => Awaitable<string | null | undefined>;
|
|
569
|
-
method: () => Awaitable<string>;
|
|
570
|
-
queryString?: (key: string, url: URL) => Awaitable<string | null | undefined>;
|
|
571
|
-
url: () => Awaitable<URL>;
|
|
572
|
-
transformResponse: (res: IActionResponse<string>) => Output;
|
|
573
|
-
waitUntil?: (promise: Promise<unknown>) => void;
|
|
574
|
-
};
|
|
575
|
-
type IActionResponse<TBody extends string = string> = {
|
|
576
|
-
status: number;
|
|
577
|
-
headers: Record<string, string>;
|
|
578
|
-
body: TBody;
|
|
579
|
-
};
|
|
580
|
-
declare class NovuRequestHandler<Input extends any[] = any[], Output = any> {
|
|
581
|
-
readonly frameworkName: string;
|
|
582
|
-
readonly handler: Handler<Input, Output>;
|
|
583
|
-
readonly client: Client;
|
|
584
|
-
private readonly hmacEnabled;
|
|
585
|
-
private readonly http;
|
|
586
|
-
private readonly workflows;
|
|
587
|
-
private readonly agents;
|
|
588
|
-
constructor(options: INovuRequestHandlerOptions<Input, Output>);
|
|
589
|
-
createHandler(): (...args: Input) => Promise<Output>;
|
|
590
|
-
private getStaticHeaders;
|
|
591
|
-
private createResponse;
|
|
592
|
-
private createError;
|
|
593
|
-
private handleAction;
|
|
594
|
-
private getPostActionMap;
|
|
595
|
-
triggerAction(triggerEvent: EventTriggerParams): () => Promise<IActionResponse<string>>;
|
|
596
|
-
private getGetActionMap;
|
|
597
|
-
private handlePostAction;
|
|
598
|
-
private handleGetAction;
|
|
599
|
-
private runAgentHandler;
|
|
600
|
-
private handleError;
|
|
601
|
-
private validateHmac;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
* Define a new notification workflow.
|
|
606
|
-
*/
|
|
607
|
-
declare function workflow<T_PayloadSchema extends Schema, T_ControlSchema extends Schema, T_EnvSchema extends Schema, T_PayloadValidated extends Record<string, unknown> = FromSchema<T_PayloadSchema>, T_PayloadUnvalidated extends Record<string, unknown> = FromSchemaUnvalidated<T_PayloadSchema>, T_Controls extends Record<string, unknown> = FromSchema<T_ControlSchema>, T_Env extends Record<string, unknown> = FromSchema<T_EnvSchema>>(workflowId: string, execute: Execute<T_PayloadValidated, T_Controls, T_Env>, workflowOptions?: WorkflowOptions<T_PayloadSchema, T_ControlSchema, T_EnvSchema>): Workflow<T_PayloadUnvalidated>;
|
|
608
|
-
|
|
609
|
-
export { type Agent as A, Client as C, type EditPayload as E, type FileRef as F, type INovuRequestHandlerOptions as I, type MessageContent as M, NovuRequestHandler as N, type ReplyContent as R, type ServeHandlerOptions as S, type TriggerSignal as T, type AgentAction as a, type AgentActionContext as b, type AgentAttachment as c, type AgentBridgeRequest as d, type AgentContext as e, type AgentConversation as f, AgentDeliveryError as g, AgentEventEnum as h, type AgentHandlers as i, type AgentHistoryEntry as j, type AgentMessage as k, type AgentMessageAuthor as l, type AgentMessageContext as m, type AgentPlatformContext as n, type AgentReaction as o, type AgentReactionContext as p, type AgentReplyPayload as q, type AgentResolveContext as r, type AgentSubscriber as s, type MetadataSignal as t, type ReplyHandle as u, type SentMessageInfo as v, type Signal as w, agent as x, workflow as y };
|
|
826
|
+
export { type Agent as A, type ToolApprovalRequestPayload as B, AgentEventEnum as C, type TypingControl as D, type ToolApprovalControl as E, type FileRef as F, type AgentBridgeRequest as G, type AgentReplyPayload as H, type ITriggerPayload as I, type DeleteMessagePayload as J, type EditPayload as K, type MetadataSignal as L, type MessageContent as M, type ReplyContent as N, type Signal as O, type ParsedApprovalAction as P, type TriggerSignal as Q, type ReplyHandle as R, type SentMessageInfo as S, type ToolApprovalCard as T, buildApprovalActionId as U, parseApprovalActionId as V, type WorkflowPreferencesPartial as W, type AgentAction as a, type AgentActionContext as b, type AgentAttachment as c, type AgentContext as d, type AgentConversation as e, AgentDeliveryError as f, AgentError as g, type AgentHandlerContext as h, type AgentHandlers as i, type AgentHistoryEntry as j, type AgentMessage as k, type AgentMessageAuthor as l, type AgentMessageContext as m, type AgentPlatformContext as n, type AgentReaction as o, type AgentReactionContext as p, type AgentResolveContext as q, type AgentSubscriber as r, type AgentToolCall as s, type ToolApprovalConfig as t, type ToolApprovalDecision as u, toAgentError as v, type TriggerRecipientsPayload as w, type ISubscriberPayload as x, TriggerEventStatusEnum as y, type ToolResult as z };
|