chat 4.20.0 → 4.20.2
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/index.d.ts +90 -5
- package/dist/index.js +139 -9
- package/dist/index.js.map +1 -1
- package/docs/api/index.mdx +6 -0
- package/docs/api/message.mdx +48 -0
- package/docs/handling-events.mdx +5 -5
- package/docs/streaming.mdx +54 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1001,6 +1001,27 @@ interface Attachment {
|
|
|
1001
1001
|
/** Image/video width (if applicable) */
|
|
1002
1002
|
width?: number;
|
|
1003
1003
|
}
|
|
1004
|
+
/**
|
|
1005
|
+
* A link found in a message, with optional unfurl metadata.
|
|
1006
|
+
*
|
|
1007
|
+
* On the initial message event, only `url` is available (unfurl metadata
|
|
1008
|
+
* arrives later via `message_changed`). The `fetchMessage` callback is
|
|
1009
|
+
* provided when the URL points to another chat message on the same platform.
|
|
1010
|
+
*/
|
|
1011
|
+
interface LinkPreview {
|
|
1012
|
+
/** Description from unfurl metadata (if available) */
|
|
1013
|
+
description?: string;
|
|
1014
|
+
/** If this links to a chat message, fetch the full Message */
|
|
1015
|
+
fetchMessage?: () => Promise<Message>;
|
|
1016
|
+
/** Preview image URL (if available) */
|
|
1017
|
+
imageUrl?: string;
|
|
1018
|
+
/** Site name (e.g., "Vercel") */
|
|
1019
|
+
siteName?: string;
|
|
1020
|
+
/** Title from unfurl metadata (if available) */
|
|
1021
|
+
title?: string;
|
|
1022
|
+
/** The URL */
|
|
1023
|
+
url: string;
|
|
1024
|
+
}
|
|
1004
1025
|
/**
|
|
1005
1026
|
* File to upload with a message.
|
|
1006
1027
|
*/
|
|
@@ -1496,6 +1517,8 @@ interface MessageData<TRawMessage = unknown> {
|
|
|
1496
1517
|
id: string;
|
|
1497
1518
|
/** Whether the bot is @-mentioned in this message */
|
|
1498
1519
|
isMention?: boolean;
|
|
1520
|
+
/** Links found in the message */
|
|
1521
|
+
links?: LinkPreview[];
|
|
1499
1522
|
/** Message metadata */
|
|
1500
1523
|
metadata: MessageMetadata;
|
|
1501
1524
|
/** Platform-specific raw payload (escape hatch) */
|
|
@@ -1530,6 +1553,13 @@ interface SerializedMessage {
|
|
|
1530
1553
|
formatted: Root;
|
|
1531
1554
|
id: string;
|
|
1532
1555
|
isMention?: boolean;
|
|
1556
|
+
links?: Array<{
|
|
1557
|
+
url: string;
|
|
1558
|
+
title?: string;
|
|
1559
|
+
description?: string;
|
|
1560
|
+
imageUrl?: string;
|
|
1561
|
+
siteName?: string;
|
|
1562
|
+
}>;
|
|
1533
1563
|
metadata: {
|
|
1534
1564
|
dateSent: string;
|
|
1535
1565
|
edited: boolean;
|
|
@@ -1598,6 +1628,8 @@ declare class Message<TRawMessage = unknown> {
|
|
|
1598
1628
|
* ```
|
|
1599
1629
|
*/
|
|
1600
1630
|
isMention?: boolean;
|
|
1631
|
+
/** Links found in the message */
|
|
1632
|
+
links: LinkPreview[];
|
|
1601
1633
|
constructor(data: MessageData<TRawMessage>);
|
|
1602
1634
|
/**
|
|
1603
1635
|
* Serialize the message to a plain JSON object.
|
|
@@ -1624,12 +1656,44 @@ declare class Message<TRawMessage = unknown> {
|
|
|
1624
1656
|
static [WORKFLOW_DESERIALIZE](data: SerializedMessage): Message;
|
|
1625
1657
|
}
|
|
1626
1658
|
|
|
1659
|
+
/**
|
|
1660
|
+
* Content part types structurally identical to AI SDK's TextPart, ImagePart,
|
|
1661
|
+
* FilePart so that AiMessage[] is directly assignable to ModelMessage[].
|
|
1662
|
+
* @see https://ai-sdk.dev/docs/reference/ai-sdk-core/model-message
|
|
1663
|
+
*/
|
|
1664
|
+
/** Matches AI SDK's DataContent */
|
|
1665
|
+
type DataContent = string | Uint8Array | ArrayBuffer | Buffer;
|
|
1666
|
+
interface AiTextPart {
|
|
1667
|
+
text: string;
|
|
1668
|
+
type: "text";
|
|
1669
|
+
}
|
|
1670
|
+
interface AiImagePart {
|
|
1671
|
+
image: DataContent | URL;
|
|
1672
|
+
mediaType?: string;
|
|
1673
|
+
type: "image";
|
|
1674
|
+
}
|
|
1675
|
+
interface AiFilePart {
|
|
1676
|
+
data: DataContent | URL;
|
|
1677
|
+
filename?: string;
|
|
1678
|
+
mediaType: string;
|
|
1679
|
+
type: "file";
|
|
1680
|
+
}
|
|
1681
|
+
type AiMessagePart = AiTextPart | AiImagePart | AiFilePart;
|
|
1627
1682
|
/**
|
|
1628
1683
|
* A message formatted for AI SDK consumption.
|
|
1684
|
+
*
|
|
1685
|
+
* This is a discriminated union matching AI SDK's ModelMessage type:
|
|
1686
|
+
* - User messages can have text, image, and file parts
|
|
1687
|
+
* - Assistant messages have string content only
|
|
1629
1688
|
*/
|
|
1630
|
-
|
|
1689
|
+
type AiMessage = AiUserMessage | AiAssistantMessage;
|
|
1690
|
+
interface AiUserMessage {
|
|
1691
|
+
content: string | AiMessagePart[];
|
|
1692
|
+
role: "user";
|
|
1693
|
+
}
|
|
1694
|
+
interface AiAssistantMessage {
|
|
1631
1695
|
content: string;
|
|
1632
|
-
role: "
|
|
1696
|
+
role: "assistant";
|
|
1633
1697
|
}
|
|
1634
1698
|
/**
|
|
1635
1699
|
* Options for converting messages to AI SDK format.
|
|
@@ -1637,6 +1701,20 @@ interface AiMessage {
|
|
|
1637
1701
|
interface ToAiMessagesOptions {
|
|
1638
1702
|
/** When true, prefixes user messages with "[username]: " for multi-user context */
|
|
1639
1703
|
includeNames?: boolean;
|
|
1704
|
+
/**
|
|
1705
|
+
* Called when an attachment type is not supported (video, audio).
|
|
1706
|
+
* Defaults to `console.warn`.
|
|
1707
|
+
*/
|
|
1708
|
+
onUnsupportedAttachment?: (attachment: Attachment, message: Message) => void;
|
|
1709
|
+
/**
|
|
1710
|
+
* Called for each message after default processing (text, links, attachments).
|
|
1711
|
+
* Return the message (modified or as-is) to include it, or `null` to skip it.
|
|
1712
|
+
*
|
|
1713
|
+
* @param aiMessage - The processed AI message
|
|
1714
|
+
* @param source - The original chat Message
|
|
1715
|
+
* @returns The message to include, or null to skip
|
|
1716
|
+
*/
|
|
1717
|
+
transformMessage?: (aiMessage: AiMessage, source: Message) => AiMessage | null | Promise<AiMessage | null>;
|
|
1640
1718
|
}
|
|
1641
1719
|
/**
|
|
1642
1720
|
* Convert chat SDK messages to AI SDK conversation format.
|
|
@@ -1644,17 +1722,21 @@ interface ToAiMessagesOptions {
|
|
|
1644
1722
|
* - Filters out messages with empty/whitespace-only text
|
|
1645
1723
|
* - Maps `author.isMe === true` to `"assistant"`, otherwise `"user"`
|
|
1646
1724
|
* - Uses `message.text` for content
|
|
1725
|
+
* - Appends link metadata when available
|
|
1726
|
+
* - Includes image attachments and text files as `FilePart`
|
|
1727
|
+
* - Uses `fetchData()` when available to include attachment data inline (base64)
|
|
1728
|
+
* - Warns on unsupported attachment types (video, audio)
|
|
1647
1729
|
*
|
|
1648
1730
|
* Works with `FetchResult.messages`, `thread.recentMessages`, or collected iterables.
|
|
1649
1731
|
*
|
|
1650
1732
|
* @example
|
|
1651
1733
|
* ```typescript
|
|
1652
1734
|
* const result = await thread.adapter.fetchMessages(thread.id, { limit: 20 });
|
|
1653
|
-
* const history = toAiMessages(result.messages);
|
|
1735
|
+
* const history = await toAiMessages(result.messages);
|
|
1654
1736
|
* const response = await agent.stream({ prompt: history });
|
|
1655
1737
|
* ```
|
|
1656
1738
|
*/
|
|
1657
|
-
declare function toAiMessages(messages: Message[], options?: ToAiMessagesOptions): AiMessage[]
|
|
1739
|
+
declare function toAiMessages(messages: Message[], options?: ToAiMessagesOptions): Promise<AiMessage[]>;
|
|
1658
1740
|
|
|
1659
1741
|
interface MessageHistoryConfig {
|
|
1660
1742
|
/** Maximum messages to keep per thread (default: 100) */
|
|
@@ -2315,6 +2397,7 @@ interface ThreadImplConfigWithAdapter {
|
|
|
2315
2397
|
initialMessage?: Message;
|
|
2316
2398
|
isDM?: boolean;
|
|
2317
2399
|
isSubscribedContext?: boolean;
|
|
2400
|
+
logger?: Logger;
|
|
2318
2401
|
messageHistory?: MessageHistoryCache;
|
|
2319
2402
|
stateAdapter: StateAdapter;
|
|
2320
2403
|
streamingUpdateIntervalMs?: number;
|
|
@@ -2332,6 +2415,7 @@ interface ThreadImplConfigLazy {
|
|
|
2332
2415
|
initialMessage?: Message;
|
|
2333
2416
|
isDM?: boolean;
|
|
2334
2417
|
isSubscribedContext?: boolean;
|
|
2418
|
+
logger?: Logger;
|
|
2335
2419
|
streamingUpdateIntervalMs?: number;
|
|
2336
2420
|
}
|
|
2337
2421
|
type ThreadImplConfig = ThreadImplConfigWithAdapter | ThreadImplConfigLazy;
|
|
@@ -2357,6 +2441,7 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
|
|
|
2357
2441
|
private _channel?;
|
|
2358
2442
|
/** Message history cache (set only for adapters with persistMessageHistory) */
|
|
2359
2443
|
private readonly _messageHistory?;
|
|
2444
|
+
private readonly _logger?;
|
|
2360
2445
|
constructor(config: ThreadImplConfig);
|
|
2361
2446
|
/**
|
|
2362
2447
|
* Get the adapter for this thread.
|
|
@@ -2904,4 +2989,4 @@ declare const Select: SelectComponent;
|
|
|
2904
2989
|
declare const SelectOption: SelectOptionComponent;
|
|
2905
2990
|
declare const TextInput: TextInputComponent;
|
|
2906
2991
|
|
|
2907
|
-
export { type ActionEvent, type ActionHandler, Actions, ActionsComponent, type Adapter, type AdapterPostableMessage, type AiMessage, type AppHomeOpenedEvent, type AppHomeOpenedHandler, type AssistantContextChangedEvent, type AssistantContextChangedHandler, type AssistantThreadStartedEvent, type AssistantThreadStartedHandler, type Attachment, type Author, BaseFormatConverter, Button, ButtonComponent, Card, CardChild, CardComponent, CardElement, CardLink, CardLinkComponent, CardText, type Channel, ChannelImpl, type ChannelInfo, Chat, type ChatConfig, ChatElement, ChatError, type ChatInstance, ConsoleLogger, type CustomEmojiMap, DEFAULT_EMOJI_MAP, type DirectMessageHandler, Divider, DividerComponent, type Emoji, type EmojiFormats, type EmojiMapConfig, EmojiResolver, type EmojiValue, type EphemeralMessage, type FetchDirection, type FetchOptions, type FetchResult, Field, FieldComponent, Fields, FieldsComponent, type FileUpload, type FormatConverter, type FormattedContent, Image, ImageComponent, LinkButton, LinkButtonComponent, type ListThreadsOptions, type ListThreadsResult, type Lock, LockError, type LogLevel, type Logger, type MarkdownConverter, type MarkdownTextChunk, type MemberJoinedChannelEvent, type MemberJoinedChannelHandler, type MentionHandler, Message, type MessageData, type MessageHandler, MessageHistoryCache, type MessageHistoryConfig, type MessageMetadata, Modal, type ModalCloseEvent, type ModalCloseHandler, type ModalCloseResponse, ModalComponent, ModalElement, type ModalErrorsResponse, type ModalPushResponse, type ModalResponse, type ModalSubmitEvent, type ModalSubmitHandler, type ModalUpdateResponse, NotImplementedError, type PlanUpdateChunk, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableRaw, RadioSelect, RadioSelectComponent, RateLimitError, type RawMessage, type ReactionEvent, type ReactionHandler, type ScheduledMessage, Section, SectionComponent, Select, SelectComponent, SelectOption, SelectOptionComponent, type SentMessage, type SerializedChannel, type SerializedMessage, type SerializedThread, type SlashCommandEvent, type SlashCommandHandler, type StateAdapter, type StreamChunk, type StreamEvent, type StreamOptions, StreamingMarkdownRenderer, type SubscribedMessageHandler, THREAD_STATE_TTL_MS, Table, type TaskUpdateChunk, TextComponent, TextInput, TextInputComponent, type Thread, ThreadImpl, type ThreadInfo, type ThreadSummary, type WebhookOptions, type WellKnownEmoji, blockquote, cardChildToFallbackText, codeBlock, convertEmojiPlaceholders, createEmoji, defaultEmojiResolver, deriveChannelId, emoji, emphasis, fromFullStream, fromReactElement, fromReactModalElement, getEmoji, getNodeChildren, getNodeValue, inlineCode, isBlockquoteNode, isCardElement, isCodeNode, isDeleteNode, isEmphasisNode, isInlineCodeNode, isJSX, isLinkNode, isListItemNode, isListNode, isModalElement, isParagraphNode, isStrongNode, isTableCellNode, isTableNode, isTableRowNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, root, strikethrough, stringifyMarkdown, strong, tableElementToAscii, tableToAscii, text, toAiMessages, toCardElement, toModalElement, toPlainText, walkAst };
|
|
2992
|
+
export { type ActionEvent, type ActionHandler, Actions, ActionsComponent, type Adapter, type AdapterPostableMessage, type AiAssistantMessage, type AiFilePart, type AiImagePart, type AiMessage, type AiMessagePart, type AiTextPart, type AiUserMessage, type AppHomeOpenedEvent, type AppHomeOpenedHandler, type AssistantContextChangedEvent, type AssistantContextChangedHandler, type AssistantThreadStartedEvent, type AssistantThreadStartedHandler, type Attachment, type Author, BaseFormatConverter, Button, ButtonComponent, Card, CardChild, CardComponent, CardElement, CardLink, CardLinkComponent, CardText, type Channel, ChannelImpl, type ChannelInfo, Chat, type ChatConfig, ChatElement, ChatError, type ChatInstance, ConsoleLogger, type CustomEmojiMap, DEFAULT_EMOJI_MAP, type DirectMessageHandler, Divider, DividerComponent, type Emoji, type EmojiFormats, type EmojiMapConfig, EmojiResolver, type EmojiValue, type EphemeralMessage, type FetchDirection, type FetchOptions, type FetchResult, Field, FieldComponent, Fields, FieldsComponent, type FileUpload, type FormatConverter, type FormattedContent, Image, ImageComponent, LinkButton, LinkButtonComponent, type LinkPreview, type ListThreadsOptions, type ListThreadsResult, type Lock, LockError, type LogLevel, type Logger, type MarkdownConverter, type MarkdownTextChunk, type MemberJoinedChannelEvent, type MemberJoinedChannelHandler, type MentionHandler, Message, type MessageData, type MessageHandler, MessageHistoryCache, type MessageHistoryConfig, type MessageMetadata, Modal, type ModalCloseEvent, type ModalCloseHandler, type ModalCloseResponse, ModalComponent, ModalElement, type ModalErrorsResponse, type ModalPushResponse, type ModalResponse, type ModalSubmitEvent, type ModalSubmitHandler, type ModalUpdateResponse, NotImplementedError, type PlanUpdateChunk, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableRaw, RadioSelect, RadioSelectComponent, RateLimitError, type RawMessage, type ReactionEvent, type ReactionHandler, type ScheduledMessage, Section, SectionComponent, Select, SelectComponent, SelectOption, SelectOptionComponent, type SentMessage, type SerializedChannel, type SerializedMessage, type SerializedThread, type SlashCommandEvent, type SlashCommandHandler, type StateAdapter, type StreamChunk, type StreamEvent, type StreamOptions, StreamingMarkdownRenderer, type SubscribedMessageHandler, THREAD_STATE_TTL_MS, Table, type TaskUpdateChunk, TextComponent, TextInput, TextInputComponent, type Thread, ThreadImpl, type ThreadInfo, type ThreadSummary, type WebhookOptions, type WellKnownEmoji, blockquote, cardChildToFallbackText, codeBlock, convertEmojiPlaceholders, createEmoji, defaultEmojiResolver, deriveChannelId, emoji, emphasis, fromFullStream, fromReactElement, fromReactModalElement, getEmoji, getNodeChildren, getNodeValue, inlineCode, isBlockquoteNode, isCardElement, isCodeNode, isDeleteNode, isEmphasisNode, isInlineCodeNode, isJSX, isLinkNode, isListItemNode, isListNode, isModalElement, isParagraphNode, isStrongNode, isTableCellNode, isTableNode, isTableRowNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, root, strikethrough, stringifyMarkdown, strong, tableElementToAscii, tableToAscii, text, toAiMessages, toCardElement, toModalElement, toPlainText, walkAst };
|
package/dist/index.js
CHANGED
|
@@ -62,16 +62,128 @@ import {
|
|
|
62
62
|
} from "./chunk-JW7GYSMH.js";
|
|
63
63
|
|
|
64
64
|
// src/ai.ts
|
|
65
|
-
|
|
65
|
+
var TEXT_MIME_PREFIXES = [
|
|
66
|
+
"text/",
|
|
67
|
+
"application/json",
|
|
68
|
+
"application/xml",
|
|
69
|
+
"application/javascript",
|
|
70
|
+
"application/typescript",
|
|
71
|
+
"application/yaml",
|
|
72
|
+
"application/x-yaml",
|
|
73
|
+
"application/toml"
|
|
74
|
+
];
|
|
75
|
+
function isTextMimeType(mimeType) {
|
|
76
|
+
return TEXT_MIME_PREFIXES.some(
|
|
77
|
+
(prefix) => mimeType === prefix || mimeType.startsWith(prefix)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
async function attachmentToPart(att) {
|
|
81
|
+
if (att.type === "image") {
|
|
82
|
+
if (att.fetchData) {
|
|
83
|
+
try {
|
|
84
|
+
const buffer = await att.fetchData();
|
|
85
|
+
const mimeType = att.mimeType ?? "image/png";
|
|
86
|
+
return {
|
|
87
|
+
type: "file",
|
|
88
|
+
data: `data:${mimeType};base64,${buffer.toString("base64")}`,
|
|
89
|
+
mediaType: mimeType,
|
|
90
|
+
filename: att.name
|
|
91
|
+
};
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("toAiMessages: failed to fetch image data", error);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
if (att.type === "file" && att.mimeType && isTextMimeType(att.mimeType)) {
|
|
100
|
+
if (att.fetchData) {
|
|
101
|
+
try {
|
|
102
|
+
const buffer = await att.fetchData();
|
|
103
|
+
return {
|
|
104
|
+
type: "file",
|
|
105
|
+
data: `data:${att.mimeType};base64,${buffer.toString("base64")}`,
|
|
106
|
+
filename: att.name,
|
|
107
|
+
mediaType: att.mimeType
|
|
108
|
+
};
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error("toAiMessages: failed to fetch file data", error);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
async function toAiMessages(messages, options) {
|
|
66
119
|
const includeNames = options?.includeNames ?? false;
|
|
120
|
+
const transformMessage = options?.transformMessage;
|
|
121
|
+
const onUnsupported = options?.onUnsupportedAttachment ?? ((att) => {
|
|
122
|
+
console.warn(
|
|
123
|
+
`toAiMessages: unsupported attachment type "${att.type}"${att.name ? ` (${att.name})` : ""} \u2014 skipped`
|
|
124
|
+
);
|
|
125
|
+
});
|
|
67
126
|
const sorted = [...messages].sort(
|
|
68
127
|
(a, b) => (a.metadata.dateSent?.getTime() ?? 0) - (b.metadata.dateSent?.getTime() ?? 0)
|
|
69
128
|
);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
129
|
+
const filtered = sorted.filter((msg) => msg.text.trim());
|
|
130
|
+
const results = await Promise.all(
|
|
131
|
+
filtered.map(async (msg) => {
|
|
132
|
+
const role = msg.author.isMe ? "assistant" : "user";
|
|
133
|
+
let textContent = includeNames && role === "user" ? `[${msg.author.userName}]: ${msg.text}` : msg.text;
|
|
134
|
+
if (msg.links.length > 0) {
|
|
135
|
+
const linkParts = msg.links.map((link2) => {
|
|
136
|
+
const parts = link2.fetchMessage ? [`[Embedded message: ${link2.url}]`] : [link2.url];
|
|
137
|
+
if (link2.title) {
|
|
138
|
+
parts.push(`Title: ${link2.title}`);
|
|
139
|
+
}
|
|
140
|
+
if (link2.description) {
|
|
141
|
+
parts.push(`Description: ${link2.description}`);
|
|
142
|
+
}
|
|
143
|
+
if (link2.siteName) {
|
|
144
|
+
parts.push(`Site: ${link2.siteName}`);
|
|
145
|
+
}
|
|
146
|
+
return parts.join("\n");
|
|
147
|
+
}).join("\n\n");
|
|
148
|
+
textContent += `
|
|
149
|
+
|
|
150
|
+
Links:
|
|
151
|
+
${linkParts}`;
|
|
152
|
+
}
|
|
153
|
+
let aiMessage;
|
|
154
|
+
if (role === "user") {
|
|
155
|
+
const attachmentParts = [];
|
|
156
|
+
for (const att of msg.attachments) {
|
|
157
|
+
const part = await attachmentToPart(att);
|
|
158
|
+
if (part) {
|
|
159
|
+
attachmentParts.push(part);
|
|
160
|
+
} else if (att.type === "video" || att.type === "audio") {
|
|
161
|
+
onUnsupported(att, msg);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (attachmentParts.length > 0) {
|
|
165
|
+
aiMessage = {
|
|
166
|
+
role,
|
|
167
|
+
content: [
|
|
168
|
+
{ type: "text", text: textContent },
|
|
169
|
+
...attachmentParts
|
|
170
|
+
]
|
|
171
|
+
};
|
|
172
|
+
} else {
|
|
173
|
+
aiMessage = { role, content: textContent };
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
aiMessage = { role, content: textContent };
|
|
177
|
+
}
|
|
178
|
+
if (transformMessage) {
|
|
179
|
+
return { result: await transformMessage(aiMessage, msg), source: msg };
|
|
180
|
+
}
|
|
181
|
+
return { result: aiMessage, source: msg };
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
return results.filter(
|
|
185
|
+
(r) => r.result != null
|
|
186
|
+
).map((r) => r.result);
|
|
75
187
|
}
|
|
76
188
|
|
|
77
189
|
// src/channel.ts
|
|
@@ -170,6 +282,8 @@ var Message = class _Message {
|
|
|
170
282
|
* ```
|
|
171
283
|
*/
|
|
172
284
|
isMention;
|
|
285
|
+
/** Links found in the message */
|
|
286
|
+
links;
|
|
173
287
|
constructor(data) {
|
|
174
288
|
this.id = data.id;
|
|
175
289
|
this.threadId = data.threadId;
|
|
@@ -180,6 +294,7 @@ var Message = class _Message {
|
|
|
180
294
|
this.metadata = data.metadata;
|
|
181
295
|
this.attachments = data.attachments;
|
|
182
296
|
this.isMention = data.isMention;
|
|
297
|
+
this.links = data.links ?? [];
|
|
183
298
|
}
|
|
184
299
|
/**
|
|
185
300
|
* Serialize the message to a plain JSON object.
|
|
@@ -217,7 +332,14 @@ var Message = class _Message {
|
|
|
217
332
|
width: att.width,
|
|
218
333
|
height: att.height
|
|
219
334
|
})),
|
|
220
|
-
isMention: this.isMention
|
|
335
|
+
isMention: this.isMention,
|
|
336
|
+
links: this.links.length > 0 ? this.links.map((link2) => ({
|
|
337
|
+
url: link2.url,
|
|
338
|
+
title: link2.title,
|
|
339
|
+
description: link2.description,
|
|
340
|
+
imageUrl: link2.imageUrl,
|
|
341
|
+
siteName: link2.siteName
|
|
342
|
+
})) : void 0
|
|
221
343
|
};
|
|
222
344
|
}
|
|
223
345
|
/**
|
|
@@ -238,7 +360,8 @@ var Message = class _Message {
|
|
|
238
360
|
editedAt: json.metadata.editedAt ? new Date(json.metadata.editedAt) : void 0
|
|
239
361
|
},
|
|
240
362
|
attachments: json.attachments,
|
|
241
|
-
isMention: json.isMention
|
|
363
|
+
isMention: json.isMention,
|
|
364
|
+
links: json.links
|
|
242
365
|
});
|
|
243
366
|
}
|
|
244
367
|
/**
|
|
@@ -615,6 +738,7 @@ var ChannelImpl = class _ChannelImpl {
|
|
|
615
738
|
edited: false
|
|
616
739
|
},
|
|
617
740
|
attachments,
|
|
741
|
+
links: [],
|
|
618
742
|
toJSON() {
|
|
619
743
|
return new Message(this).toJSON();
|
|
620
744
|
},
|
|
@@ -993,12 +1117,14 @@ var ThreadImpl = class _ThreadImpl {
|
|
|
993
1117
|
_channel;
|
|
994
1118
|
/** Message history cache (set only for adapters with persistMessageHistory) */
|
|
995
1119
|
_messageHistory;
|
|
1120
|
+
_logger;
|
|
996
1121
|
constructor(config) {
|
|
997
1122
|
this.id = config.id;
|
|
998
1123
|
this.channelId = config.channelId;
|
|
999
1124
|
this.isDM = config.isDM ?? false;
|
|
1000
1125
|
this._isSubscribedContext = config.isSubscribedContext ?? false;
|
|
1001
1126
|
this._currentMessage = config.currentMessage;
|
|
1127
|
+
this._logger = config.logger;
|
|
1002
1128
|
this._streamingUpdateIntervalMs = config.streamingUpdateIntervalMs ?? 500;
|
|
1003
1129
|
this._fallbackStreamingPlaceholderText = config.fallbackStreamingPlaceholderText !== void 0 ? config.fallbackStreamingPlaceholderText : "...";
|
|
1004
1130
|
if (isLazyConfig2(config)) {
|
|
@@ -1355,7 +1481,8 @@ var ThreadImpl = class _ThreadImpl {
|
|
|
1355
1481
|
markdown: content
|
|
1356
1482
|
});
|
|
1357
1483
|
lastEditContent = content;
|
|
1358
|
-
} catch {
|
|
1484
|
+
} catch (error) {
|
|
1485
|
+
this._logger?.warn("fallbackStream edit failed", error);
|
|
1359
1486
|
}
|
|
1360
1487
|
}
|
|
1361
1488
|
if (!stopped) {
|
|
@@ -1505,6 +1632,7 @@ var ThreadImpl = class _ThreadImpl {
|
|
|
1505
1632
|
formatted,
|
|
1506
1633
|
raw: null,
|
|
1507
1634
|
// Will be populated if needed
|
|
1635
|
+
links: [],
|
|
1508
1636
|
author: {
|
|
1509
1637
|
userId: "self",
|
|
1510
1638
|
userName: adapter.userName,
|
|
@@ -1558,6 +1686,7 @@ var ThreadImpl = class _ThreadImpl {
|
|
|
1558
1686
|
author: message.author,
|
|
1559
1687
|
metadata: message.metadata,
|
|
1560
1688
|
attachments: message.attachments,
|
|
1689
|
+
links: message.links,
|
|
1561
1690
|
isMention: message.isMention,
|
|
1562
1691
|
toJSON() {
|
|
1563
1692
|
return message.toJSON();
|
|
@@ -2788,6 +2917,7 @@ var Chat = class {
|
|
|
2788
2917
|
isSubscribedContext,
|
|
2789
2918
|
isDM,
|
|
2790
2919
|
currentMessage: initialMessage,
|
|
2920
|
+
logger: this.logger,
|
|
2791
2921
|
streamingUpdateIntervalMs: this._streamingUpdateIntervalMs,
|
|
2792
2922
|
fallbackStreamingPlaceholderText: this._fallbackStreamingPlaceholderText,
|
|
2793
2923
|
messageHistory: adapter.persistMessageHistory ? this._messageHistory : void 0
|