@segmentstream/agent 0.6.6 → 0.6.7
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/extension/lib/chat-post-confirmation.mjs +5 -1
- package/dist/extension/lib/telegram/chat-post-card.d.ts +2 -0
- package/dist/extension/lib/telegram/chat-post-card.mjs +7 -4
- package/dist/extension/lib/telegram/confirmations.mjs +3 -3
- package/dist/extension/lib/telegram/customer-text.mjs +14 -11
- package/package.json +2 -1
|
@@ -6,8 +6,10 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { object } from "./confirmation-description.mjs";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
|
+
import { TelegramFormatConverter, escapeMarkdownV2 } from "@chat-adapter/telegram";
|
|
9
10
|
const CHAT_POST_PROTOCOL = "segmentstream/chat-post";
|
|
10
11
|
const CHAT_POST_ENVELOPE = "_segmentstream";
|
|
12
|
+
const converter = new TelegramFormatConverter();
|
|
11
13
|
function isChatPost(action) {
|
|
12
14
|
return action.split("__").at(-1) === "chat_post_message";
|
|
13
15
|
}
|
|
@@ -16,6 +18,7 @@ function supportsChatPost(tool) {
|
|
|
16
18
|
}
|
|
17
19
|
function chatPostDigest(preview) {
|
|
18
20
|
return createHash("sha256").update(JSON.stringify([
|
|
21
|
+
"v2",
|
|
19
22
|
preview.chatId,
|
|
20
23
|
preview.provider,
|
|
21
24
|
preview.externalId,
|
|
@@ -43,6 +46,7 @@ function describeChatPost(input) {
|
|
|
43
46
|
target.external_id,
|
|
44
47
|
caller.attribution
|
|
45
48
|
].every((value) => typeof value === "string" && value.length > 0) || target.provider !== "telegram" || target.id !== values.chat && target.title !== values.chat) throw new Error("An unambiguous destination and a complete exact chat preview are required.");
|
|
49
|
+
const footer = escapeMarkdownV2(caller.attribution);
|
|
46
50
|
return {
|
|
47
51
|
action: "Post message",
|
|
48
52
|
fields: [],
|
|
@@ -53,7 +57,7 @@ function describeChatPost(input) {
|
|
|
53
57
|
title: target.title,
|
|
54
58
|
attribution: caller.attribution,
|
|
55
59
|
text: values.text,
|
|
56
|
-
finalText: `${
|
|
60
|
+
finalText: `${converter.fromMarkdown(values.text)}\n\n_${footer}_`,
|
|
57
61
|
replyTo: typeof values.reply_to === "string" ? values.reply_to : null
|
|
58
62
|
}
|
|
59
63
|
};
|
|
@@ -12,4 +12,6 @@ export declare function chatPostCopy(locale: string): {
|
|
|
12
12
|
expired: string;
|
|
13
13
|
};
|
|
14
14
|
export declare function chatPostCard(preview: ChatPostPreview, locale: string): ConfirmationText;
|
|
15
|
+
/** Status/receipt strings are data outside the already rendered preview. */
|
|
16
|
+
export declare function chatPostCardStatus(text: string, status: string): string;
|
|
15
17
|
export declare function chatPostReceipt(output: unknown, locale: string): string | undefined;
|
|
@@ -4,6 +4,7 @@ import { createRequire as __eveCreateRequire } from "node:module";
|
|
|
4
4
|
const __filename = __eveFileURLToPath(import.meta.url);
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
|
+
import { escapeMarkdownV2 } from "@chat-adapter/telegram";
|
|
7
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
9
|
const MAX_PREVIEW_LENGTH = 3584;
|
|
9
10
|
const exactText = new AsyncLocalStorage();
|
|
@@ -37,9 +38,8 @@ function chatPostCard(preview, locale) {
|
|
|
37
38
|
russian ? "Отправить сообщение?" : "Send message?",
|
|
38
39
|
`${russian ? "Чат" : "Chat"}: ${preview.title} (${preview.provider})`,
|
|
39
40
|
...preview.replyTo === null ? [] : [`${russian ? "В ответ на" : "Reply to"}: ${preview.replyTo}`],
|
|
40
|
-
""
|
|
41
|
-
|
|
42
|
-
].join("\n");
|
|
41
|
+
""
|
|
42
|
+
].map(escapeMarkdownV2).join("\n") + `\n${preview.finalText}`;
|
|
43
43
|
if (text.length > MAX_PREVIEW_LENGTH) throw new Error("The full message and receipt cannot fit in one Telegram confirmation. Make a shorter draft.");
|
|
44
44
|
return {
|
|
45
45
|
text,
|
|
@@ -51,6 +51,9 @@ function chatPostCard(preview, locale) {
|
|
|
51
51
|
failed: russian ? "Ошибка отправки сообщения." : "Chat posting failed."
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
function chatPostCardStatus(text, status) {
|
|
55
|
+
return `${text}\n\n${escapeMarkdownV2(status)}`;
|
|
56
|
+
}
|
|
54
57
|
function chatPostReceipt(output, locale) {
|
|
55
58
|
const value = typeof output === "object" && output !== null ? output : {};
|
|
56
59
|
if (value.status !== "sent" && value.status !== "uncertain" || typeof value.history_recorded !== "boolean" || typeof value.duplicate !== "boolean" || value.message_id !== null && typeof value.message_id !== "string" || value.url !== null && typeof value.url !== "string") return;
|
|
@@ -62,4 +65,4 @@ function chatPostReceipt(output, locale) {
|
|
|
62
65
|
...value.history_recorded ? [] : [copy.history]
|
|
63
66
|
].join("\n");
|
|
64
67
|
}
|
|
65
|
-
export { chatPostCard, chatPostCopy, chatPostReceipt, isExactChatPostCard, withChatPostCard };
|
|
68
|
+
export { chatPostCard, chatPostCardStatus, chatPostCopy, chatPostReceipt, isExactChatPostCard, withChatPostCard };
|
|
@@ -6,7 +6,7 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { conversationLanguage, memberIdOf, telegramPrincipal } from "./principal.mjs";
|
|
8
8
|
import { chatPostOperationId, isChatPost } from "../chat-post-confirmation.mjs";
|
|
9
|
-
import { chatPostCard, chatPostCopy, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
|
|
9
|
+
import { chatPostCard, chatPostCardStatus, chatPostCopy, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
|
|
10
10
|
import { confirmations } from "../confirmations.mjs";
|
|
11
11
|
import { conversationEvent } from "../conversations.mjs";
|
|
12
12
|
import { currentInboundRequest } from "./inbound-request.mjs";
|
|
@@ -302,7 +302,7 @@ function telegramConfirmationEvents(render = async (description, locale) => fall
|
|
|
302
302
|
const copy = message.copy ?? confirmationCopy(message.locale ?? confirmationLocale(ctx.session.auth.current, currentLocale()));
|
|
303
303
|
const reason = confirmations.get()[callId]?.cancellationReason;
|
|
304
304
|
const status = resolution.outcome === "approved" ? copy.executing : reason === "expired" ? chatPostCopy(message.locale ?? "en").expired : copy.cancelled;
|
|
305
|
-
const text = message.exactPost ?
|
|
305
|
+
const text = message.exactPost ? chatPostCardStatus(message.text, status) : status;
|
|
306
306
|
const edit = () => channel.telegram.editMessageText({
|
|
307
307
|
messageId: message.messageId,
|
|
308
308
|
replyMarkup: { inline_keyboard: [] },
|
|
@@ -390,7 +390,7 @@ function telegramConfirmationEvents(render = async (description, locale) => fall
|
|
|
390
390
|
const receipt = !failed && data.result.kind === "tool-result" ? chatPostReceipt(data.result.output, locale) : void 0;
|
|
391
391
|
const errorId = failed ? reportTelegramError("confirmed_chat_post_failed", data, { callId: data.result.callId }) : void 0;
|
|
392
392
|
const status = receipt ?? (failed ? `${message.copy?.failed ?? "Chat posting failed."} ${errorId}\n${chatPostCopy(locale).uncertain}` : chatPostCopy(locale).uncertain);
|
|
393
|
-
const text =
|
|
393
|
+
const text = chatPostCardStatus(message.text, status);
|
|
394
394
|
await withChatPostCard(text, () => channel.telegram.editMessageText({
|
|
395
395
|
messageId: message.messageId,
|
|
396
396
|
replyMarkup: { inline_keyboard: [] },
|
|
@@ -140,17 +140,20 @@ function safeTelegramFetch(fetchImpl, scope = "telegram") {
|
|
|
140
140
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
141
141
|
if (!methods.has(url.split("/").at(-1) ?? "") || typeof init?.body !== "string") return fetchImpl(input, init);
|
|
142
142
|
const body = JSON.parse(init.body);
|
|
143
|
-
for (const field of ["text", "caption"])
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
143
|
+
for (const field of ["text", "caption"]) {
|
|
144
|
+
if (typeof body[field] === "string" && isExactChatPostCard(body[field])) body.parse_mode = "MarkdownV2";
|
|
145
|
+
if (typeof body[field] === "string" && !isExactChatPostCard(body[field])) {
|
|
146
|
+
const entityField = field === "text" ? "entities" : "caption_entities";
|
|
147
|
+
const existing = body[entityField];
|
|
148
|
+
const message = Array.isArray(existing) ? {
|
|
149
|
+
text: body[field],
|
|
150
|
+
entities: existing
|
|
151
|
+
} : customerMessage(body[field]);
|
|
152
|
+
const guarded = customerText(message.text);
|
|
153
|
+
body[field] = message.entities.some((entity) => typeof entity.url === "string" && isTechnicalText(entity.url)) ? failureText(reportTelegramError("unsafe_entity_link", new Error("Credential-bearing link refused.")), "response") : guarded;
|
|
154
|
+
if (!url.endsWith("/answerCallbackQuery")) body[entityField] = body[field] === message.text ? message.entities : [];
|
|
155
|
+
delete body.parse_mode;
|
|
156
|
+
}
|
|
154
157
|
}
|
|
155
158
|
if (Array.isArray(body.media)) body.media = body.media.map((item) => ({
|
|
156
159
|
...item,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@segmentstream/agent",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "Mount a SegmentStream workspace's agent on eve: the ontology as tools, acting as the member who writes, and Telegram through the workspace's connection.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "SegmentStream",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"prepack": "npm run build"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
+
"@chat-adapter/telegram": "4.41.0",
|
|
63
64
|
"@vercel/oidc": "^3.8.4",
|
|
64
65
|
"ai": "^7.0.128",
|
|
65
66
|
"csv-parse": "^7.0.3",
|