@trigger.dev/sdk 4.8.0-webhooks.20261015065339 → 4.8.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.
- package/dist/commonjs/v3/ai.d.ts +69 -2
- package/dist/commonjs/v3/ai.js +120 -30
- package/dist/commonjs/v3/ai.js.map +1 -1
- package/dist/commonjs/v3/query.d.ts +434 -1
- package/dist/commonjs/v3/query.js +115 -0
- package/dist/commonjs/v3/query.js.map +1 -1
- package/dist/commonjs/v3/webhooks.d.ts +19 -5
- package/dist/commonjs/v3/webhooks.js +19 -2
- package/dist/commonjs/v3/webhooks.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/esm/v3/ai.d.ts +69 -2
- package/dist/esm/v3/ai.js +119 -29
- package/dist/esm/v3/ai.js.map +1 -1
- package/dist/esm/v3/query.d.ts +434 -1
- package/dist/esm/v3/query.js +115 -0
- package/dist/esm/v3/query.js.map +1 -1
- package/dist/esm/v3/webhooks.d.ts +19 -5
- package/dist/esm/v3/webhooks.js +19 -2
- package/dist/esm/v3/webhooks.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/ai-chat/backend.mdx +12 -3
- package/docs/ai-chat/client-protocol.mdx +6 -3
- package/docs/ai-chat/patterns/redacting-telemetry.mdx +117 -0
- package/docs/ai-chat/reference.mdx +3 -0
- package/docs/ai-chat/transcript-storage.mdx +1 -1
- package/docs/apikeys.mdx +6 -4
- package/docs/cli-runs-commands.mdx +2 -2
- package/docs/cli-tasks-commands.mdx +95 -0
- package/docs/config/config-file.mdx +58 -0
- package/docs/config/extensions/prismaExtension.mdx +4 -4
- package/docs/deploy-environment-variables.mdx +23 -0
- package/docs/deployment/atomic-deployment.mdx +3 -3
- package/docs/deployment/overview.mdx +1 -1
- package/docs/deployment/preview-branches.mdx +1 -1
- package/docs/github-actions.mdx +3 -3
- package/docs/limits.mdx +6 -0
- package/docs/manual-setup.mdx +1 -1
- package/docs/mcp-tools.mdx +19 -3
- package/docs/observability/dashboards.mdx +62 -0
- package/docs/runs/max-duration.mdx +4 -0
- package/docs/self-hosting/env/supervisor.mdx +1 -0
- package/docs/webhooks/channels.mdx +31 -5
- package/docs/webhooks/connect.mdx +14 -3
- package/docs/webhooks/deliveries.mdx +8 -1
- package/docs/webhooks/filters.mdx +39 -2
- package/docs/webhooks/human-in-the-loop.mdx +11 -2
- package/docs/webhooks/linear.mdx +5 -4
- package/docs/webhooks/overview.mdx +16 -0
- package/docs/webhooks/session-routing.mdx +11 -2
- package/docs/webhooks/slack.mdx +51 -18
- package/docs/webhooks/sources.mdx +36 -3
- package/docs/webhooks/waiters.mdx +22 -2
- package/package.json +3 -2
package/dist/commonjs/v3/ai.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ type ChatTurnContext<TClientData = unknown> = {
|
|
|
34
34
|
turn: number;
|
|
35
35
|
continuation: boolean;
|
|
36
36
|
clientData?: TClientData;
|
|
37
|
+
recordUserMessage?: boolean;
|
|
37
38
|
};
|
|
38
39
|
export { __readChatSnapshotProductionPathForTests, __setReadChatSnapshotImplForTests, __setWriteChatSnapshotImplForTests, __writeChatSnapshotProductionPathForTests, } from "./chatSnapshotIo.js";
|
|
39
40
|
export { defaultStorage, memoryTranscriptStorage, reduceTranscriptChanges, snapshotTranscriptStorage, type LoadContextEvent, type MemoryTranscriptStorage, type TranscriptChange, type TranscriptChangeReason, type TranscriptChangeset, type TranscriptCursors, type TranscriptLoadOptions, type TranscriptLoadResult, type TranscriptScope, type TranscriptState, type TranscriptStorage, type TranscriptStorageContext, } from "./transcriptStorage.js";
|
|
@@ -1862,21 +1863,25 @@ export type ChannelControl = {
|
|
|
1862
1863
|
/**
|
|
1863
1864
|
* What a connector's `progress()` hook observes while a turn streams: each tool call as its input is
|
|
1864
1865
|
* complete, and each result or error as it lands. Text deltas are not reported (use `delivery: "stream"`).
|
|
1866
|
+
* `title` is the tool's display title (`tool({ title })`), when it declares one.
|
|
1865
1867
|
*/
|
|
1866
1868
|
export type ChannelProgressEvent = {
|
|
1867
1869
|
type: "tool-call";
|
|
1868
1870
|
toolCallId: string;
|
|
1869
1871
|
toolName: string;
|
|
1872
|
+
title?: string;
|
|
1870
1873
|
input: unknown;
|
|
1871
1874
|
} | {
|
|
1872
1875
|
type: "tool-result";
|
|
1873
1876
|
toolCallId: string;
|
|
1874
1877
|
toolName: string;
|
|
1878
|
+
title?: string;
|
|
1875
1879
|
output: unknown;
|
|
1876
1880
|
} | {
|
|
1877
1881
|
type: "tool-error";
|
|
1878
1882
|
toolCallId: string;
|
|
1879
1883
|
toolName: string;
|
|
1884
|
+
title?: string;
|
|
1880
1885
|
errorText: string;
|
|
1881
1886
|
};
|
|
1882
1887
|
/**
|
|
@@ -1900,7 +1905,7 @@ export type ChannelReplyStreamEnd = {
|
|
|
1900
1905
|
stopped: boolean;
|
|
1901
1906
|
/** The turn paused on a human decision; the controls follow as their own message. */
|
|
1902
1907
|
pending: boolean;
|
|
1903
|
-
/** The
|
|
1908
|
+
/** The connector's error line (`errorMessage`) when the turn ended on a model or stream error. */
|
|
1904
1909
|
errorText?: string;
|
|
1905
1910
|
};
|
|
1906
1911
|
/**
|
|
@@ -2026,6 +2031,12 @@ export interface ChannelConnector<TEvent = unknown, THandle = unknown> {
|
|
|
2026
2031
|
cancelInteraction?: (cancelled: ChannelCancelledToolCall[], ctx: ChannelTurnCtx<TEvent, THandle>) => Promise<void> | void;
|
|
2027
2032
|
react?: (reaction: ChannelReaction, ctx: ChannelReactCtx<TEvent>) => Promise<void>;
|
|
2028
2033
|
reactions?: ChannelReactions<TEvent>;
|
|
2034
|
+
/**
|
|
2035
|
+
* What the channel shows when a turn fails, in place of the error text: a fixed line, or a
|
|
2036
|
+
* function of the failure that returns one. Defaults to {@link CHANNEL_TURN_ERROR_MESSAGE}. The
|
|
2037
|
+
* error itself is logged on the run, and `outbound()` still receives it as `reply.error`.
|
|
2038
|
+
*/
|
|
2039
|
+
errorMessage?: ChannelErrorMessage<TEvent>;
|
|
2029
2040
|
/**
|
|
2030
2041
|
* Observe tool calls and results as the turn streams, to post progress into the surface (a Linear
|
|
2031
2042
|
* `action` activity, a Slack status). Called in order, awaited one at a time, independent of
|
|
@@ -2045,6 +2056,34 @@ export interface ChannelConnector<TEvent = unknown, THandle = unknown> {
|
|
|
2045
2056
|
readonly [channelEventPhantom]?: TEvent;
|
|
2046
2057
|
}
|
|
2047
2058
|
export type AnyChannelConnector = ChannelConnector<any, any>;
|
|
2059
|
+
/** The line a channel shows when a turn fails, unless the connector sets its own `errorMessage`. */
|
|
2060
|
+
export declare const CHANNEL_TURN_ERROR_MESSAGE = "Something went wrong answering this. Try again.";
|
|
2061
|
+
/** What an `errorMessage` function receives when a channel turn fails. */
|
|
2062
|
+
export type ChannelErrorContext<TEvent = unknown> = {
|
|
2063
|
+
/** The failure: the model or stream error, or what the turn threw. */
|
|
2064
|
+
error: Error;
|
|
2065
|
+
/** The text the turn streamed before it failed; empty when it failed before answering. */
|
|
2066
|
+
partialText: string;
|
|
2067
|
+
/** The event that started the turn; undefined on a turn the channel did not start (an action turn, a browser message). */
|
|
2068
|
+
event: TEvent | undefined;
|
|
2069
|
+
/** The run the turn failed in, for a support reference. */
|
|
2070
|
+
runId: string | undefined;
|
|
2071
|
+
/** The session's chat id. */
|
|
2072
|
+
chatId: string;
|
|
2073
|
+
/** {@link CHANNEL_TURN_ERROR_MESSAGE}, to extend rather than replace. */
|
|
2074
|
+
defaultMessage: string;
|
|
2075
|
+
};
|
|
2076
|
+
/**
|
|
2077
|
+
* A channel's error line: a fixed string, or a function of the failure. A function that returns
|
|
2078
|
+
* nothing, or throws, falls back to {@link CHANNEL_TURN_ERROR_MESSAGE}.
|
|
2079
|
+
*
|
|
2080
|
+
* @example
|
|
2081
|
+
* ```ts
|
|
2082
|
+
* errorMessage: ({ error, runId }) =>
|
|
2083
|
+
* error.name === "RateLimitError" ? "I'm a bit busy, try again in a minute." : `That failed (ref ${runId}).`,
|
|
2084
|
+
* ```
|
|
2085
|
+
*/
|
|
2086
|
+
export type ChannelErrorMessage<TEvent = unknown> = string | ((ctx: ChannelErrorContext<TEvent>) => string | null | undefined | Promise<string | null | undefined>);
|
|
2048
2087
|
/**
|
|
2049
2088
|
* A generic chat-frontend channel over any verified source. Unlike `slack()`, you supply the egress
|
|
2050
2089
|
* `send` yourself (post/edit the reply back to your surface), so the whole round-trip is under your
|
|
@@ -2088,6 +2127,8 @@ export declare function chatChannelCustom<TEndpoint extends AnyWebhookEndpoint,
|
|
|
2088
2127
|
filter?: ValidateWebhookFilter<InferWebhookEndpointEvent<TEndpoint>, TFilter>;
|
|
2089
2128
|
startOn?: ValidateWebhookFilter<InferWebhookEndpointEvent<TEndpoint>, TStartOn>;
|
|
2090
2129
|
delivery?: "final" | "stream";
|
|
2130
|
+
/** What the channel shows when a turn fails: a line, or a function of the failure. Defaults to {@link CHANNEL_TURN_ERROR_MESSAGE}. */
|
|
2131
|
+
errorMessage?: ChannelErrorMessage<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>>;
|
|
2091
2132
|
}): ChannelConnector<NarrowWebhookEvent<InferWebhookEndpointEvent<TEndpoint>, TFilter>, THandle>;
|
|
2092
2133
|
export declare function resolveReactionChoice(choice: ChannelReactionChoice | undefined, event: unknown): Promise<string | undefined>;
|
|
2093
2134
|
/**
|
|
@@ -2184,6 +2225,31 @@ export type ChatAgentOptions<TIdentifier extends string, TClientDataSchema exten
|
|
|
2184
2225
|
* Ignored for sessions with no pin, and for sessions using `lockToVersion`.
|
|
2185
2226
|
*/
|
|
2186
2227
|
versionSkew?: ChatVersionSkewPolicy;
|
|
2228
|
+
/**
|
|
2229
|
+
* Controls which chat content the chat runtime records on its spans in the run trace.
|
|
2230
|
+
*
|
|
2231
|
+
* - `recordUserMessage` (default `true`) records the last user message as `chat.user_message`
|
|
2232
|
+
* and as the turn span's preview text, and messages sent mid-turn as `pending.messages`.
|
|
2233
|
+
* - `recordClientData` (default `true`) records the raw `clientData` sent by the frontend as
|
|
2234
|
+
* `chat.client_data`.
|
|
2235
|
+
*
|
|
2236
|
+
* Set either to `false` to keep that content out of telemetry. Content recorded by the AI SDK's
|
|
2237
|
+
* own spans is controlled separately, through `experimental_telemetry` on the model call.
|
|
2238
|
+
*
|
|
2239
|
+
* @example
|
|
2240
|
+
* ```ts
|
|
2241
|
+
* chat.agent({
|
|
2242
|
+
* id: "my-chat",
|
|
2243
|
+
* telemetry: { recordUserMessage: false, recordClientData: false },
|
|
2244
|
+
* run: async ({ messages, signal, streamText }) =>
|
|
2245
|
+
* streamText({ model, messages, abortSignal: signal }),
|
|
2246
|
+
* });
|
|
2247
|
+
* ```
|
|
2248
|
+
*/
|
|
2249
|
+
telemetry?: {
|
|
2250
|
+
recordUserMessage?: boolean;
|
|
2251
|
+
recordClientData?: boolean;
|
|
2252
|
+
};
|
|
2187
2253
|
/**
|
|
2188
2254
|
* Schema for validating `clientData` from the frontend.
|
|
2189
2255
|
* Accepts Zod, ArkType, Valibot, or any supported schema library.
|
|
@@ -4069,7 +4135,8 @@ export declare const chat: {
|
|
|
4069
4135
|
/**
|
|
4070
4136
|
* Returns an options object ready to spread into `streamText()`.
|
|
4071
4137
|
* Reads the stored prompt and returns `{ system, experimental_telemetry, ...config }`.
|
|
4072
|
-
*
|
|
4138
|
+
* With no stored prompt it still returns `experimental_telemetry` (on), so the model call is
|
|
4139
|
+
* traced.
|
|
4073
4140
|
*/
|
|
4074
4141
|
toStreamTextOptions: typeof toStreamTextOptions;
|
|
4075
4142
|
/**
|
package/dist/commonjs/v3/ai.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.chat = exports.__buildManagedStreamTextOptionsForTests = exports.upsertIncomingMessage = exports.PENDING_MESSAGE_INJECTED_TYPE = exports.ai = exports.snapshotTranscriptStorage = exports.reduceTranscriptChanges = exports.memoryTranscriptStorage = exports.defaultStorage = exports.__writeChatSnapshotProductionPathForTests = exports.__setWriteChatSnapshotImplForTests = exports.__setReadChatSnapshotImplForTests = exports.__readChatSnapshotProductionPathForTests = void 0;
|
|
3
|
+
exports.chat = exports.CHANNEL_TURN_ERROR_MESSAGE = exports.__buildManagedStreamTextOptionsForTests = exports.upsertIncomingMessage = exports.PENDING_MESSAGE_INJECTED_TYPE = exports.ai = exports.snapshotTranscriptStorage = exports.reduceTranscriptChanges = exports.memoryTranscriptStorage = exports.defaultStorage = exports.__writeChatSnapshotProductionPathForTests = exports.__setWriteChatSnapshotImplForTests = exports.__setReadChatSnapshotImplForTests = exports.__readChatSnapshotProductionPathForTests = void 0;
|
|
4
4
|
exports.__setTranscriptStorageForTests = __setTranscriptStorageForTests;
|
|
5
5
|
exports.__mergeByIdReplaceWinsForTests = __mergeByIdReplaceWinsForTests;
|
|
6
6
|
exports.__setReplaySessionOutTailImplForTests = __setReplaySessionOutTailImplForTests;
|
|
@@ -2954,7 +2954,6 @@ async function drainSteeringQueue(config, messages, steps, queueOverride) {
|
|
|
2954
2954
|
// Span attributes describe the offered batch; the chunk and callback below
|
|
2955
2955
|
// describe what was actually claimed and injected.
|
|
2956
2956
|
const messageTexts = uiMessages.map(textOfUIMessage);
|
|
2957
|
-
const _previewText = messageTexts.length === 1 ? messageTexts[0].slice(0, 80) : `${queue.length} messages`;
|
|
2958
2957
|
return tracer_js_1.tracer.startActiveSpan("pending message injected", async () => {
|
|
2959
2958
|
/**
|
|
2960
2959
|
* Claim before transforming, and inject only what was claimed.
|
|
@@ -3093,7 +3092,7 @@ async function drainSteeringQueue(config, messages, steps, queueOverride) {
|
|
|
3093
3092
|
[v3_1.SemanticInternalAttributes.STYLE_ICON]: "tabler-message-forward",
|
|
3094
3093
|
"pending.message_count": uiMessages.length,
|
|
3095
3094
|
"pending.step_number": stepNumber,
|
|
3096
|
-
"pending.messages": messageTexts,
|
|
3095
|
+
...(ctx?.recordUserMessage === false ? {} : { "pending.messages": messageTexts }),
|
|
3097
3096
|
...(ctx?.chatId ? { "pending.chat_id": ctx.chatId } : {}),
|
|
3098
3097
|
...(ctx?.turn != null ? { "pending.turn": ctx.turn } : {}),
|
|
3099
3098
|
...(0, v3_1.accessoryAttributes)({
|
|
@@ -3569,6 +3568,22 @@ function toStreamTextOptions(options, retain = true) {
|
|
|
3569
3568
|
const telemetry = prompt.toAISDKTelemetry(options?.telemetry);
|
|
3570
3569
|
Object.assign(result, telemetry);
|
|
3571
3570
|
}
|
|
3571
|
+
const telemetry = result.experimental_telemetry ?? {
|
|
3572
|
+
isEnabled: true,
|
|
3573
|
+
metadata: { ...(options?.telemetry ?? {}) },
|
|
3574
|
+
};
|
|
3575
|
+
if (locals_js_1.locals.get(chatTurnContextKey)?.recordUserMessage === false) {
|
|
3576
|
+
const { "prompt.input": _input, ...metadata } = (telemetry.metadata ?? {});
|
|
3577
|
+
result.experimental_telemetry = {
|
|
3578
|
+
...telemetry,
|
|
3579
|
+
metadata,
|
|
3580
|
+
recordInputs: false,
|
|
3581
|
+
recordOutputs: false,
|
|
3582
|
+
};
|
|
3583
|
+
}
|
|
3584
|
+
else {
|
|
3585
|
+
result.experimental_telemetry = telemetry;
|
|
3586
|
+
}
|
|
3572
3587
|
// Skills: merge auto-injected tools with any user-provided tools.
|
|
3573
3588
|
// User tools override on name conflict (though we namespace ours).
|
|
3574
3589
|
if (skills && skills.length > 0) {
|
|
@@ -3839,13 +3854,39 @@ async function pipeChat(source, options, capture) {
|
|
|
3839
3854
|
await waitUntilComplete();
|
|
3840
3855
|
}
|
|
3841
3856
|
}
|
|
3857
|
+
/** The AI SDK's default `toUIMessageStream` `onError`: the error's message, as the client sees it. */
|
|
3858
|
+
function uiStreamErrorText(error) {
|
|
3859
|
+
if (error == null)
|
|
3860
|
+
return "unknown error";
|
|
3861
|
+
if (typeof error === "string")
|
|
3862
|
+
return error;
|
|
3863
|
+
if (error instanceof Error)
|
|
3864
|
+
return error.message;
|
|
3865
|
+
return JSON.stringify(error);
|
|
3866
|
+
}
|
|
3867
|
+
/** The line a channel shows when a turn fails, unless the connector sets its own `errorMessage`. */
|
|
3868
|
+
exports.CHANNEL_TURN_ERROR_MESSAGE = "Something went wrong answering this. Try again.";
|
|
3869
|
+
async function channelTurnErrorMessage(connector, ctx) {
|
|
3870
|
+
const option = connector?.errorMessage;
|
|
3871
|
+
if (typeof option !== "function")
|
|
3872
|
+
return option || exports.CHANNEL_TURN_ERROR_MESSAGE;
|
|
3873
|
+
try {
|
|
3874
|
+
const line = await option({ ...ctx, defaultMessage: exports.CHANNEL_TURN_ERROR_MESSAGE });
|
|
3875
|
+
if (line)
|
|
3876
|
+
return line;
|
|
3877
|
+
}
|
|
3878
|
+
catch (error) {
|
|
3879
|
+
v3_1.logger.warn("chat.agent: channel errorMessage threw; posting the default line", { error });
|
|
3880
|
+
}
|
|
3881
|
+
return exports.CHANNEL_TURN_ERROR_MESSAGE;
|
|
3882
|
+
}
|
|
3842
3883
|
/**
|
|
3843
3884
|
* A generic chat-frontend channel over any verified source. Unlike `slack()`, you supply the egress
|
|
3844
3885
|
* `send` yourself (post/edit the reply back to your surface), so the whole round-trip is under your
|
|
3845
3886
|
* control. Use for providers without a preset, or to test the channel round-trip end to end.
|
|
3846
3887
|
*/
|
|
3847
3888
|
function chatChannelCustom(options) {
|
|
3848
|
-
const { id, endpoint, key, inbound, bind, seed, outbound, ack, send, renderInteraction, onInteraction, finalizeInteraction, react, reactions, progress, surface, onControl, stream, endInterruptedStream, download, received, toAction, lifecycle, cancelInteraction, filter, startOn, delivery, } = options;
|
|
3889
|
+
const { id, endpoint, key, inbound, bind, seed, outbound, ack, send, renderInteraction, onInteraction, finalizeInteraction, react, reactions, progress, surface, onControl, stream, endInterruptedStream, download, received, toAction, lifecycle, cancelInteraction, filter, startOn, delivery, errorMessage, } = options;
|
|
3849
3890
|
if (!endpoint?.id) {
|
|
3850
3891
|
throw new Error(`chat.channels.custom("${id}"): an endpoint is required. Declare one with webhooks.endpoint.define() and pass it as { endpoint }.`);
|
|
3851
3892
|
}
|
|
@@ -3879,6 +3920,7 @@ function chatChannelCustom(options) {
|
|
|
3879
3920
|
lifecycle,
|
|
3880
3921
|
cancelInteraction,
|
|
3881
3922
|
delivery: delivery ?? "final",
|
|
3923
|
+
errorMessage,
|
|
3882
3924
|
};
|
|
3883
3925
|
}
|
|
3884
3926
|
const chatChannels = {
|
|
@@ -4376,6 +4418,7 @@ function makeChannelProgressObserver(connector, wireEvent, handle) {
|
|
|
4376
4418
|
const progress = connector.progress;
|
|
4377
4419
|
const turnCtx = channelTurnCtx(wireEvent, handle);
|
|
4378
4420
|
const toolNames = new Map();
|
|
4421
|
+
const toolTitles = new Map();
|
|
4379
4422
|
let chain = Promise.resolve();
|
|
4380
4423
|
let stopped = false;
|
|
4381
4424
|
const emit = (event) => {
|
|
@@ -4398,6 +4441,10 @@ function makeChannelProgressObserver(connector, wireEvent, handle) {
|
|
|
4398
4441
|
const c = chunk;
|
|
4399
4442
|
if (!c?.type || !c.toolCallId)
|
|
4400
4443
|
return;
|
|
4444
|
+
if (c.title)
|
|
4445
|
+
toolTitles.set(c.toolCallId, c.title);
|
|
4446
|
+
const title = toolTitles.get(c.toolCallId);
|
|
4447
|
+
const titled = title ? { title } : {};
|
|
4401
4448
|
if (c.type === "tool-input-start" && c.toolName) {
|
|
4402
4449
|
toolNames.set(c.toolCallId, c.toolName);
|
|
4403
4450
|
return;
|
|
@@ -4405,7 +4452,7 @@ function makeChannelProgressObserver(connector, wireEvent, handle) {
|
|
|
4405
4452
|
if (c.type === "tool-input-available") {
|
|
4406
4453
|
const toolName = c.toolName ?? toolNames.get(c.toolCallId) ?? "tool";
|
|
4407
4454
|
toolNames.set(c.toolCallId, toolName);
|
|
4408
|
-
emit({ type: "tool-call", toolCallId: c.toolCallId, toolName, input: c.input });
|
|
4455
|
+
emit({ type: "tool-call", toolCallId: c.toolCallId, toolName, ...titled, input: c.input });
|
|
4409
4456
|
return;
|
|
4410
4457
|
}
|
|
4411
4458
|
if (c.type === "tool-output-available" && !c.preliminary) {
|
|
@@ -4413,6 +4460,7 @@ function makeChannelProgressObserver(connector, wireEvent, handle) {
|
|
|
4413
4460
|
type: "tool-result",
|
|
4414
4461
|
toolCallId: c.toolCallId,
|
|
4415
4462
|
toolName: toolNames.get(c.toolCallId) ?? "tool",
|
|
4463
|
+
...titled,
|
|
4416
4464
|
output: c.output,
|
|
4417
4465
|
});
|
|
4418
4466
|
return;
|
|
@@ -4422,6 +4470,7 @@ function makeChannelProgressObserver(connector, wireEvent, handle) {
|
|
|
4422
4470
|
type: "tool-error",
|
|
4423
4471
|
toolCallId: c.toolCallId,
|
|
4424
4472
|
toolName: toolNames.get(c.toolCallId) ?? "tool",
|
|
4473
|
+
...titled,
|
|
4425
4474
|
errorText: c.errorText ?? "tool failed",
|
|
4426
4475
|
});
|
|
4427
4476
|
}
|
|
@@ -4513,6 +4562,7 @@ function stopPendingToolCalls(message, toolCallIds, errorText) {
|
|
|
4513
4562
|
*/
|
|
4514
4563
|
function makeChannelReplyStreamObserver(stream) {
|
|
4515
4564
|
const toolNames = new Map();
|
|
4565
|
+
const toolTitles = new Map();
|
|
4516
4566
|
let stopped = false;
|
|
4517
4567
|
const safe = (fn) => {
|
|
4518
4568
|
try {
|
|
@@ -4535,22 +4585,32 @@ function makeChannelReplyStreamObserver(stream) {
|
|
|
4535
4585
|
if (!stream.progress || !c?.type || !c.toolCallId)
|
|
4536
4586
|
return;
|
|
4537
4587
|
const toolCallId = c.toolCallId;
|
|
4588
|
+
if (c.title)
|
|
4589
|
+
toolTitles.set(toolCallId, c.title);
|
|
4590
|
+
const title = toolTitles.get(toolCallId);
|
|
4591
|
+
const titled = title ? { title } : {};
|
|
4538
4592
|
if (c.type === "tool-input-start" && c.toolName) {
|
|
4539
4593
|
toolNames.set(toolCallId, c.toolName);
|
|
4540
4594
|
}
|
|
4541
4595
|
else if (c.type === "tool-input-available") {
|
|
4542
4596
|
const toolName = c.toolName ?? toolNames.get(toolCallId) ?? "tool";
|
|
4543
4597
|
toolNames.set(toolCallId, toolName);
|
|
4544
|
-
safe(() => stream.progress({ type: "tool-call", toolCallId, toolName, input: c.input }));
|
|
4598
|
+
safe(() => stream.progress({ type: "tool-call", toolCallId, toolName, ...titled, input: c.input }));
|
|
4545
4599
|
}
|
|
4546
4600
|
else if (c.type === "tool-output-available" && !c.preliminary) {
|
|
4547
4601
|
const toolName = toolNames.get(toolCallId) ?? "tool";
|
|
4548
|
-
safe(() => stream.progress({
|
|
4602
|
+
safe(() => stream.progress({
|
|
4603
|
+
type: "tool-result",
|
|
4604
|
+
toolCallId,
|
|
4605
|
+
toolName,
|
|
4606
|
+
...titled,
|
|
4607
|
+
output: c.output,
|
|
4608
|
+
}));
|
|
4549
4609
|
}
|
|
4550
4610
|
else if (c.type === "tool-output-error") {
|
|
4551
4611
|
const toolName = toolNames.get(toolCallId) ?? "tool";
|
|
4552
4612
|
const errorText = c.errorText ?? "tool failed";
|
|
4553
|
-
safe(() => stream.progress({ type: "tool-error", toolCallId, toolName, errorText }));
|
|
4613
|
+
safe(() => stream.progress({ type: "tool-error", toolCallId, toolName, ...titled, errorText }));
|
|
4554
4614
|
}
|
|
4555
4615
|
},
|
|
4556
4616
|
stop() {
|
|
@@ -4831,7 +4891,9 @@ function chatCustomAgent(options) {
|
|
|
4831
4891
|
return task;
|
|
4832
4892
|
}
|
|
4833
4893
|
function chatAgent(options) {
|
|
4834
|
-
const { run: userRun, clientDataSchema, onBoot, onRecoveryBoot, onPreload, onChatStart, onValidateMessages, hydrateMessages, storage, actionSchema, events, channels, onAction, onTurnStart, onBeforeTurnComplete, onCompacted, compaction, pendingMessages: pendingMessagesConfig, prepareMessages, tools: toolsOption, onTurnComplete, maxTurns = 100, turnTimeout = "1h", idleTimeoutInSeconds = 30, chatAccessTokenTTL = "1h", preloadIdleTimeoutInSeconds, preloadTimeout, uiMessageStreamOptions, onChatSuspend, onChatResume, exitAfterPreloadIdle = false, oomMachine, registry: promptRegistry, system: agentSystem, cacheControl: agentCacheControl, systemProviderOptions: agentSystemProviderOptions, versionSkew, ...restOptions } = options;
|
|
4894
|
+
const { run: userRun, clientDataSchema, onBoot, onRecoveryBoot, onPreload, onChatStart, onValidateMessages, hydrateMessages, storage, actionSchema, events, channels, onAction, onTurnStart, onBeforeTurnComplete, onCompacted, compaction, pendingMessages: pendingMessagesConfig, prepareMessages, tools: toolsOption, onTurnComplete, maxTurns = 100, turnTimeout = "1h", idleTimeoutInSeconds = 30, chatAccessTokenTTL = "1h", preloadIdleTimeoutInSeconds, preloadTimeout, uiMessageStreamOptions, onChatSuspend, onChatResume, exitAfterPreloadIdle = false, oomMachine, registry: promptRegistry, system: agentSystem, cacheControl: agentCacheControl, systemProviderOptions: agentSystemProviderOptions, versionSkew, telemetry: telemetryOptions, ...restOptions } = options;
|
|
4895
|
+
const recordUserMessage = telemetryOptions?.recordUserMessage ?? true;
|
|
4896
|
+
const recordClientData = telemetryOptions?.recordClientData ?? true;
|
|
4835
4897
|
if (hydrateMessages) {
|
|
4836
4898
|
if (storage) {
|
|
4837
4899
|
throw new Error(`chat.agent: "${options.id}" sets both \`hydrateMessages\` and \`storage\`. ` +
|
|
@@ -6113,6 +6175,8 @@ function chatAgent(options) {
|
|
|
6113
6175
|
let channelFinalSendFailed = false;
|
|
6114
6176
|
/** The stream-level error (an `error` chunk) this turn ended on, if any; posted to the channel in place of an empty reply. */
|
|
6115
6177
|
let channelStreamErrorText;
|
|
6178
|
+
/** The original error behind that chunk, captured from `toUIMessageStream`'s `onError` when auto-piping. */
|
|
6179
|
+
let channelStreamError;
|
|
6116
6180
|
/** The text this turn streamed, so the channel reply is this turn's answer and not the whole message. */
|
|
6117
6181
|
let channelTurnText;
|
|
6118
6182
|
try {
|
|
@@ -6520,7 +6584,7 @@ function chatAgent(options) {
|
|
|
6520
6584
|
: "tabler-message-chatbot",
|
|
6521
6585
|
[v3_1.SemanticInternalAttributes.ENTITY_TYPE]: isAction ? "chat-action" : "chat-turn",
|
|
6522
6586
|
};
|
|
6523
|
-
if (lastUserMessage) {
|
|
6587
|
+
if (lastUserMessage && recordUserMessage) {
|
|
6524
6588
|
turnAttributes["chat.user_message"] = lastUserMessage;
|
|
6525
6589
|
// Show a truncated preview of the user message as an accessory
|
|
6526
6590
|
const preview = lastUserMessage.length > 80
|
|
@@ -6531,7 +6595,7 @@ function chatAgent(options) {
|
|
|
6531
6595
|
style: "codepath",
|
|
6532
6596
|
}));
|
|
6533
6597
|
}
|
|
6534
|
-
if (wireMetadata !== undefined) {
|
|
6598
|
+
if (wireMetadata !== undefined && recordClientData) {
|
|
6535
6599
|
turnAttributes["chat.client_data"] =
|
|
6536
6600
|
typeof wireMetadata === "string" ? wireMetadata : JSON.stringify(wireMetadata);
|
|
6537
6601
|
}
|
|
@@ -6556,6 +6620,7 @@ function chatAgent(options) {
|
|
|
6556
6620
|
turn,
|
|
6557
6621
|
continuation,
|
|
6558
6622
|
clientData,
|
|
6623
|
+
recordUserMessage,
|
|
6559
6624
|
});
|
|
6560
6625
|
// Resolve the per-turn `tools` set now that turn context
|
|
6561
6626
|
// (incl. parsed clientData) exists, so every toModelMessages
|
|
@@ -7456,6 +7521,12 @@ function chatAgent(options) {
|
|
|
7456
7521
|
// messageId. Without this, the frontend and backend generate IDs
|
|
7457
7522
|
// independently and they won't match for ID-based dedup.
|
|
7458
7523
|
generateMessageId: resolvedOptions.generateMessageId ?? ai_runtime_js_1.generateId,
|
|
7524
|
+
onError: (error) => {
|
|
7525
|
+
channelStreamError ??= error;
|
|
7526
|
+
return resolvedOptions.onError
|
|
7527
|
+
? resolvedOptions.onError(error)
|
|
7528
|
+
: uiStreamErrorText(error);
|
|
7529
|
+
},
|
|
7459
7530
|
onFinish: ({ responseMessage, finishReason, }) => {
|
|
7460
7531
|
capturedResponseMessage = responseMessage;
|
|
7461
7532
|
capturedPartialResponse = responseMessage;
|
|
@@ -7980,6 +8051,21 @@ function chatAgent(options) {
|
|
|
7980
8051
|
const renderControls = !!((wireChannelEvent || boundTurn) &&
|
|
7981
8052
|
pendingToolCalls.length > 0 &&
|
|
7982
8053
|
channelConn?.renderInteraction);
|
|
8054
|
+
let channelErrorLine;
|
|
8055
|
+
if (channelStreamErrorText && (wireChannelEvent || boundTurn)) {
|
|
8056
|
+
v3_1.logger.warn("chat.agent: channel turn ended on a model or stream error", {
|
|
8057
|
+
errorText: channelStreamErrorText,
|
|
8058
|
+
});
|
|
8059
|
+
channelErrorLine = await channelTurnErrorMessage(channelConn, {
|
|
8060
|
+
error: channelStreamError instanceof Error
|
|
8061
|
+
? channelStreamError
|
|
8062
|
+
: new Error(channelStreamErrorText),
|
|
8063
|
+
partialText: channelTurnText?.trim() ?? "",
|
|
8064
|
+
event: channelWireEvent?.event,
|
|
8065
|
+
runId: ctx.run.id,
|
|
8066
|
+
chatId: currentWirePayload.chatId,
|
|
8067
|
+
});
|
|
8068
|
+
}
|
|
7983
8069
|
let channelReplyDelivered = false;
|
|
7984
8070
|
if (channelReplyStream) {
|
|
7985
8071
|
const replyStream = channelReplyStream;
|
|
@@ -7988,7 +8074,9 @@ function chatAgent(options) {
|
|
|
7988
8074
|
const ended = await replyStream.end({
|
|
7989
8075
|
stopped: turnCompleteEvent.stopped,
|
|
7990
8076
|
pending: renderControls,
|
|
7991
|
-
...(channelStreamErrorText
|
|
8077
|
+
...(channelStreamErrorText
|
|
8078
|
+
? { errorText: channelErrorLine ?? exports.CHANNEL_TURN_ERROR_MESSAGE }
|
|
8079
|
+
: {}),
|
|
7992
8080
|
});
|
|
7993
8081
|
channelReplyDelivered = ended.delivered;
|
|
7994
8082
|
}
|
|
@@ -8018,13 +8106,16 @@ function chatAgent(options) {
|
|
|
8018
8106
|
? channelTurnText
|
|
8019
8107
|
: channelReplyText(turnCompleteEvent.responseMessage);
|
|
8020
8108
|
// A model or stream error surfaces as an `error` chunk and an empty reply, not as a
|
|
8021
|
-
// thrown turn. The mapper gets it on this one call, with the error
|
|
8022
|
-
// for an empty reply, so the placeholder never sits there as if the agent
|
|
8023
|
-
// still working.
|
|
8109
|
+
// thrown turn. The mapper gets it on this one call, with the connector's error line
|
|
8110
|
+
// standing in for an empty reply, so the placeholder never sits there as if the agent
|
|
8111
|
+
// were still working. The error text itself stays on the run, not in the channel.
|
|
8024
8112
|
const finalReply = {
|
|
8025
8113
|
// Prefer what this turn streamed; a resumed message carries earlier turns' text too.
|
|
8026
|
-
|
|
8027
|
-
|
|
8114
|
+
// A failed turn always ends on the connector's error line, after any partial text.
|
|
8115
|
+
text: channelErrorLine
|
|
8116
|
+
? replyText.trim().length > 0
|
|
8117
|
+
? `${replyText.trimEnd()}\n\n${channelErrorLine}`
|
|
8118
|
+
: channelErrorLine
|
|
8028
8119
|
: replyText,
|
|
8029
8120
|
message: turnCompleteEvent.responseMessage,
|
|
8030
8121
|
final: true,
|
|
@@ -8393,18 +8484,16 @@ function chatAgent(options) {
|
|
|
8393
8484
|
v3_1.logger.warn("chat.agent: channel error reaction failed", { error: reactionError });
|
|
8394
8485
|
}
|
|
8395
8486
|
}
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
catch { }
|
|
8407
|
-
}
|
|
8487
|
+
// The channel gets the connector's error line, never the error itself: the run keeps that.
|
|
8488
|
+
const channelErrorText = channelReplyStream || ((channelWireEvent || boundTurn) && channelConn?.send)
|
|
8489
|
+
? await channelTurnErrorMessage(channelConn, {
|
|
8490
|
+
error: turnError instanceof Error ? turnError : new Error(String(turnError)),
|
|
8491
|
+
partialText: channelTurnText?.trim() ?? "",
|
|
8492
|
+
event: channelWireEvent?.event,
|
|
8493
|
+
runId: ctx.run.id,
|
|
8494
|
+
chatId: currentWirePayload.chatId,
|
|
8495
|
+
})
|
|
8496
|
+
: exports.CHANNEL_TURN_ERROR_MESSAGE;
|
|
8408
8497
|
let errorStreamDelivered = false;
|
|
8409
8498
|
if (channelReplyStream) {
|
|
8410
8499
|
const replyStream = channelReplyStream;
|
|
@@ -11212,7 +11301,8 @@ exports.chat = {
|
|
|
11212
11301
|
/**
|
|
11213
11302
|
* Returns an options object ready to spread into `streamText()`.
|
|
11214
11303
|
* Reads the stored prompt and returns `{ system, experimental_telemetry, ...config }`.
|
|
11215
|
-
*
|
|
11304
|
+
* With no stored prompt it still returns `experimental_telemetry` (on), so the model call is
|
|
11305
|
+
* traced.
|
|
11216
11306
|
*/
|
|
11217
11307
|
toStreamTextOptions,
|
|
11218
11308
|
/**
|