@segmentstream/agent 0.18.3 → 0.19.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 +4 -4
- package/dist/_chunks/{build-metadata-DZ9Nb8Q2.mjs → build-metadata-CZ245Pl3.mjs} +1 -1
- package/dist/_chunks/{inbound-request-8xhK7EaW.mjs → inbound-request-Dx1B6Y5r.mjs} +1 -1
- package/dist/_chunks/{principal-qyR3jKAr.mjs → principal-BnJuWJtk.mjs} +1 -1
- package/dist/extension/_manifest.json +3 -15
- package/dist/extension/connections/ontology.d.ts +1 -1
- package/dist/extension/connections/ontology.mjs +2 -2
- package/dist/extension/hooks/authorization.d.ts +1 -1
- package/dist/extension/hooks/authorization.mjs +3 -3
- package/dist/extension/hooks/ontology-files.d.ts +1 -1
- package/dist/extension/hooks/ontology-files.mjs +3 -1
- package/dist/extension/hooks/sandbox.d.ts +2 -2
- package/dist/extension/hooks/sandbox.mjs +2 -2
- package/dist/extension/instructions/conversations.d.ts +1 -1
- package/dist/extension/instructions/conversations.mjs +3 -3
- package/dist/extension/instructions/sandbox.d.ts +1 -1
- package/dist/extension/instructions/sandbox.mjs +2 -2
- package/dist/extension/instructions.md +13 -12
- package/dist/extension/lib/attachment-tools.mjs +1 -1
- package/dist/extension/lib/build-metadata.mjs +1 -1
- package/dist/extension/lib/confirmations.mjs +3 -3
- package/dist/extension/lib/conversation-runtime.d.ts +2 -2
- package/dist/extension/lib/conversation-runtime.mjs +40 -55
- package/dist/extension/lib/conversations.mjs +1 -1
- package/dist/extension/lib/group-routing/conversation-router.d.ts +1 -1
- package/dist/extension/lib/group-routing/conversation-router.mjs +2 -2
- package/dist/extension/lib/group-routing/dequeue.mjs +2 -2
- package/dist/extension/lib/group-routing/record.mjs +1 -1
- package/dist/extension/lib/group-routing/replay.mjs +1 -1
- package/dist/extension/lib/group-routing/router.d.ts +1 -1
- package/dist/extension/lib/group-routing/router.mjs +3 -3
- package/dist/extension/lib/ontology-connection.mjs +2 -2
- package/dist/extension/lib/ontology-file-call.mjs +2 -2
- package/dist/extension/lib/ontology-tools.mjs +1 -1
- package/dist/extension/lib/runtime-envelope.mjs +1 -1
- package/dist/extension/lib/sandbox.d.ts +3 -2
- package/dist/extension/lib/sandbox.mjs +1 -1
- package/dist/extension/lib/stored-files.mjs +1 -1
- package/dist/extension/lib/telegram/adapter.mjs +43 -28
- package/dist/extension/lib/telegram/archive-message.d.ts +4 -0
- package/dist/extension/lib/telegram/archive-message.mjs +85 -0
- package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
- package/dist/extension/lib/telegram/attachments-send.mjs +2 -2
- package/dist/extension/lib/telegram/callbacks.mjs +2 -2
- package/dist/extension/lib/telegram/confirmation-expiry.mjs +20 -9
- package/dist/extension/lib/telegram/confirmations.d.ts +2 -2
- package/dist/extension/lib/telegram/confirmations.mjs +206 -181
- package/dist/extension/lib/telegram/conversations.mjs +5 -6
- package/dist/extension/lib/telegram/customer-text.mjs +1 -1
- package/dist/extension/lib/telegram/deferred-confirmations.mjs +2 -2
- package/dist/extension/lib/telegram/delivery-diagnostics.mjs +1 -1
- package/dist/extension/lib/telegram/durable-typing.d.ts +11 -0
- package/dist/extension/lib/telegram/durable-typing.mjs +10 -10
- package/dist/extension/lib/telegram/files.mjs +2 -2
- package/dist/extension/lib/telegram/health.mjs +1 -1
- package/dist/extension/lib/telegram/held-approvals.d.ts +3 -3
- package/dist/extension/lib/telegram/held-approvals.mjs +23 -19
- package/dist/extension/lib/telegram/images.d.ts +1 -1
- package/dist/extension/lib/telegram/images.mjs +1 -1
- package/dist/extension/lib/telegram/inbound-request.d.ts +2 -2
- package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
- package/dist/extension/lib/telegram/inbound.mjs +5 -6
- package/dist/extension/lib/telegram/lifecycle.d.ts +2 -2
- package/dist/extension/lib/telegram/lifecycle.mjs +23 -27
- package/dist/extension/lib/telegram/media-policy.mjs +1 -1
- package/dist/extension/lib/telegram/principal.mjs +1 -1
- package/dist/extension/lib/telegram/routing-context.mjs +4 -4
- package/dist/extension/lib/telegram/session-recovery.d.ts +1 -1
- package/dist/extension/lib/telegram/session-recovery.mjs +2 -1
- package/dist/extension/lib/telegram/sessions.d.ts +7 -4
- package/dist/extension/lib/telegram/sessions.mjs +6 -3
- package/dist/extension/lib/telegram/silent.d.ts +1 -1
- package/dist/extension/lib/telegram/silent.mjs +11 -8
- package/dist/extension/lib/telegram/structured.mjs +1 -1
- package/dist/extension/lib/telegram/turn-errors.d.ts +1 -1
- package/dist/extension/lib/telegram/turn-errors.mjs +47 -31
- package/dist/extension/lib/telegram/voice.mjs +1 -1
- package/dist/extension/lib/workflow-serializable.mjs +1 -1
- package/dist/extension/model.mjs +7 -4
- package/dist/extension/tools/attachments_discard.mjs +1 -1
- package/dist/extension/tools/attachments_list.mjs +1 -1
- package/dist/extension/tools/attachments_promote.mjs +2 -2
- package/dist/extension/tools/attachments_read.mjs +1 -1
- package/dist/extension/tools/attachments_send.mjs +1 -1
- package/dist/extension/tools/attachments_table.mjs +1 -1
- package/dist/extension/tools/ontology_call_file.d.ts +1 -1
- package/dist/extension/tools/ontology_call_file.mjs +1 -1
- package/dist/extension/tools/questions_ask.mjs +2 -2
- package/dist/extension/tools/sandbox.d.ts +1 -8
- package/dist/extension/tools/sandbox.mjs +1 -1
- package/package.json +5 -5
- /package/dist/_chunks/{content-TRaZitQZ.mjs → content-cDtVnr8Y.mjs} +0 -0
- /package/dist/_chunks/{workflow-serializable-_g4JRau5.mjs → workflow-serializable-DU7WeCIW.mjs} +0 -0
|
@@ -5,12 +5,12 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { telegramText } from "./texts.mjs";
|
|
8
|
-
import { i as memberIdOf, o as telegramPrincipal } from "../../../_chunks/principal-
|
|
8
|
+
import { i as memberIdOf, o as telegramPrincipal } from "../../../_chunks/principal-BnJuWJtk.mjs";
|
|
9
9
|
import { humanText } from "../confirmation-description.mjs";
|
|
10
10
|
import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
|
|
11
11
|
import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
|
|
12
12
|
import { conversationEvent } from "../conversations.mjs";
|
|
13
|
-
import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-
|
|
13
|
+
import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
|
|
14
14
|
import { agentMessage, observedChatKey, withConfirmationPrompt } from "../group-routing/observed.mjs";
|
|
15
15
|
import { chatPostOperationId, isChatPost } from "../chat-post-confirmation.mjs";
|
|
16
16
|
import { confirmations } from "../confirmations.mjs";
|
|
@@ -19,7 +19,7 @@ import { postDeferredCard } from "./deferred-confirmations.mjs";
|
|
|
19
19
|
import { answerMarker, isPendingQuestion, pendingQuestions, questionKey } from "../questions.mjs";
|
|
20
20
|
import { createHash } from "node:crypto";
|
|
21
21
|
import { telegramTextLinks } from "@segmentstream-cloud/ontology/telegram";
|
|
22
|
-
import {
|
|
22
|
+
import { call } from "eve/events";
|
|
23
23
|
const PREFIX = "ss-confirm:";
|
|
24
24
|
function shortHash(value) {
|
|
25
25
|
return createHash("sha256").update(value).digest("hex").slice(0, 20);
|
|
@@ -33,26 +33,29 @@ function object(value) {
|
|
|
33
33
|
}
|
|
34
34
|
function openConfirmations(events) {
|
|
35
35
|
const open = new Map();
|
|
36
|
+
const calls = new Map();
|
|
36
37
|
for (const event of events) {
|
|
37
38
|
const data = object(event.data);
|
|
38
|
-
if (event.type === "
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
if (event.type === "session.started" || event.type === "context.settled" && data.kind === "clear" && data.outcome === "completed") {
|
|
40
|
+
open.clear();
|
|
41
|
+
calls.clear();
|
|
42
|
+
}
|
|
43
|
+
if (event.type === "call.requested" && typeof data.callId === "string") calls.set(data.callId, data);
|
|
44
|
+
const request = object(data.request);
|
|
45
|
+
const callId = object(data.subject).callId;
|
|
46
|
+
if (event.type === "interaction.opened" && request.kind === "approval" && typeof data.interactionId === "string" && typeof callId === "string" && data.origin === void 0) {
|
|
47
|
+
const action = calls.get(callId);
|
|
48
|
+
if (action) open.set(data.interactionId, {
|
|
49
|
+
requestId: data.interactionId,
|
|
50
|
+
callId,
|
|
45
51
|
at: Date.parse(event.meta.at),
|
|
46
|
-
toolName: String(action.
|
|
52
|
+
toolName: String(object(action.capability).name ?? ""),
|
|
47
53
|
input: object(action.input)
|
|
48
54
|
});
|
|
49
55
|
}
|
|
50
|
-
if (event.type === "
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
}
|
|
54
|
-
if (event.type === "action.result") {
|
|
55
|
-
for (const [key, prompt] of open) if (prompt.callId === object(data.result).callId) open.delete(key);
|
|
56
|
+
if (event.type === "interaction.settled" && typeof data.interactionId === "string") open.delete(data.interactionId);
|
|
57
|
+
if (event.type === "call.settled") {
|
|
58
|
+
for (const [key, prompt] of open) if (prompt.callId === data.callId) open.delete(key);
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
61
|
return [...open.values()];
|
|
@@ -63,17 +66,17 @@ function routingConfirmationState(events, prompt, at) {
|
|
|
63
66
|
let callId;
|
|
64
67
|
for (const event of prompt.mode === "deferred" ? [] : events) {
|
|
65
68
|
const data = object(event.data);
|
|
66
|
-
if ((event.type === "
|
|
67
|
-
if (event.type === "
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
state = prompt.state ?? "pending";
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (event.type === "input.resolved" && Array.isArray(data.resolutions)) {
|
|
74
|
-
for (const resolution of data.resolutions) if (object(resolution).requestId === prompt.requestId) state = object(resolution).outcome === "approved" ? "approved" : object(resolution).outcome === "ignored" ? "interrupted" : "cancelled";
|
|
69
|
+
if ((event.type === "session.started" || event.type === "context.settled" && data.kind === "clear" && data.outcome === "completed") && Date.parse(event.meta.at) >= Date.parse(prompt.at)) state = "expired";
|
|
70
|
+
if (event.type === "interaction.opened" && data.interactionId === prompt.requestId) {
|
|
71
|
+
callId = String(object(data.subject).callId);
|
|
72
|
+
state = prompt.state ?? "pending";
|
|
75
73
|
}
|
|
76
|
-
if (event.type === "
|
|
74
|
+
if (event.type === "interaction.settled" && data.interactionId === prompt.requestId) state = data.outcome === "accepted" ? "approved" : [
|
|
75
|
+
"withdrawn",
|
|
76
|
+
"interrupted",
|
|
77
|
+
"abandoned"
|
|
78
|
+
].includes(String(data.outcome)) ? "interrupted" : data.outcome === "expired" ? "expired" : "cancelled";
|
|
79
|
+
if (event.type === "call.settled" && callId !== void 0 && data.callId === callId) state = data.outcome === "completed" ? "completed" : "failed";
|
|
77
80
|
}
|
|
78
81
|
if (state === "pending" && Date.parse(at) - Date.parse(prompt.at) >= 6e5) return "expired";
|
|
79
82
|
return state;
|
|
@@ -101,16 +104,17 @@ function questionFromHistory(events, owner) {
|
|
|
101
104
|
}
|
|
102
105
|
function questionsFromHistory(events) {
|
|
103
106
|
const pending = new Map();
|
|
107
|
+
const calls = new Map();
|
|
104
108
|
for (const event of events) {
|
|
105
109
|
const data = object(event.data);
|
|
106
|
-
if (event.type === "context.
|
|
107
|
-
if (event.type === "
|
|
108
|
-
|
|
109
|
-
const candidate = object(
|
|
110
|
-
if (
|
|
110
|
+
if (event.type === "context.settled" && data.kind === "clear" && data.outcome === "completed") pending.clear();
|
|
111
|
+
if (event.type === "call.requested" && typeof data.callId === "string") calls.set(data.callId, String(object(data.capability).name ?? ""));
|
|
112
|
+
if (event.type === "call.settled" && data.outcome === "completed") {
|
|
113
|
+
const candidate = object(data.output).pendingQuestion;
|
|
114
|
+
if (calls.get(String(data.callId))?.endsWith("__questions_ask") && isPendingQuestion(candidate)) pending.set(questionKey(candidate), candidate);
|
|
111
115
|
}
|
|
112
|
-
if (event.type === "
|
|
113
|
-
const message = data.
|
|
116
|
+
if (event.type === "delivery.consumed" && Array.isArray(data.parts)) {
|
|
117
|
+
const message = data.parts.filter((part) => object(part).kind === "text").map((part) => object(part).text).join("\n").replace(/^\[source-message:\d+;trigger:\d+\]\r?\n/u, "");
|
|
114
118
|
for (const [key, question] of pending) if (message.startsWith(answerMarker(question.id))) pending.delete(key);
|
|
115
119
|
}
|
|
116
120
|
}
|
|
@@ -243,169 +247,189 @@ function telegramConfirmationEvents(archive, observed, deferredOptions) {
|
|
|
243
247
|
}
|
|
244
248
|
};
|
|
245
249
|
return {
|
|
246
|
-
"context.
|
|
250
|
+
"context.settled"(event, ctx) {
|
|
251
|
+
if (event.data.kind !== "clear" || event.data.outcome !== "completed") return;
|
|
252
|
+
const channel = ctx.channel;
|
|
247
253
|
confirmations.update(() => ({}));
|
|
248
254
|
pendingQuestions.update(() => ({}));
|
|
249
255
|
const state = channel.state;
|
|
250
256
|
state.confirmationMessages = {};
|
|
251
257
|
state.pendingQuestions = {};
|
|
252
258
|
},
|
|
253
|
-
async "
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
}));
|
|
265
|
-
remember(channel, ctx, sent.id, text);
|
|
266
|
-
registerTelegramFreeformPrompt(channel.state, {
|
|
267
|
-
messageId: sent.id,
|
|
268
|
-
requestId: request.requestId
|
|
269
|
-
});
|
|
270
|
-
channel.state.hitlPrompts = {
|
|
271
|
-
...channel.state.hitlPrompts,
|
|
272
|
-
[request.requestId]: {
|
|
273
|
-
messageId: sent.id,
|
|
274
|
-
text,
|
|
275
|
-
options: (request.options ?? []).map(({ id, label }) => ({
|
|
276
|
-
id,
|
|
277
|
-
label
|
|
278
|
-
}))
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
const memberId = confirmations.get()[request.action.callId]?.memberId ?? memberIdOf(ctx.session.auth.current);
|
|
284
|
-
if (memberId === void 0) throw new Error("Confirmation requires a member.");
|
|
285
|
-
const saved = confirmations.get()[request.action.callId];
|
|
286
|
-
const description = saved?.description;
|
|
287
|
-
const exactPost = isChatPost(request.action.toolName);
|
|
288
|
-
if (description === void 0) throw new Error("Approval buttons require trusted confirmation facts.");
|
|
289
|
-
if (exactPost && description?.chatPost === void 0) throw new Error("An exact chat post cannot show a generic confirmation.");
|
|
290
|
-
const copy = description?.chatPost === void 0 ? renderConfirmation(description, saved?.copy) : chatPostCard(description, saved?.copy);
|
|
291
|
-
const text = copy.text;
|
|
292
|
-
await record(request.action.callId, "preview", text, "requested", ctx);
|
|
293
|
-
const send = () => channel.telegram.post({
|
|
259
|
+
async "interaction.opened"(event, ctx) {
|
|
260
|
+
const channel = ctx.channel;
|
|
261
|
+
const data = event.data;
|
|
262
|
+
const request = data.request;
|
|
263
|
+
if (request.kind === "sign-in") return;
|
|
264
|
+
const requestId = data.interactionId;
|
|
265
|
+
if (request.kind !== "approval") {
|
|
266
|
+
const text = [request.prompt, ...(request.options ?? []).map((option, index) => `${index + 1}. ${option.label}`)].join("\n");
|
|
267
|
+
if (text.length > 4096) throw new Error("A typed Telegram question must fit in one message.");
|
|
268
|
+
const sent = await withConfirmationText(text, () => channel.telegram.post({
|
|
294
269
|
text,
|
|
295
|
-
reply_markup: {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
},
|
|
300
|
-
...exactPost ? [{
|
|
301
|
-
text: copy.edit,
|
|
302
|
-
callback_data: confirmationCallback(request.requestId, memberId, "edit")
|
|
303
|
-
}] : [],
|
|
304
|
-
{
|
|
305
|
-
text: copy.cancel,
|
|
306
|
-
callback_data: confirmationCallback(request.requestId, memberId, "cancel")
|
|
307
|
-
}
|
|
308
|
-
]] }
|
|
309
|
-
});
|
|
310
|
-
const prompt = {
|
|
311
|
-
requestId: request.requestId,
|
|
312
|
-
state: "pending",
|
|
313
|
-
sessionId: ctx.session.id,
|
|
314
|
-
address: channel.continuation?.token ?? formatAddress({
|
|
315
|
-
chatId: channel.telegram.chatId,
|
|
316
|
-
messageThreadId: String(channel.telegram.messageThreadId ?? ""),
|
|
317
|
-
conversationId: channel.telegram.conversationId ?? ""
|
|
318
|
-
}),
|
|
319
|
-
action: humanText(description?.action) ?? "the requested action",
|
|
320
|
-
requestedBy: humanText(ctx.session.auth.current?.attributes.memberName) ?? null,
|
|
321
|
-
at: new Date().toISOString(),
|
|
322
|
-
...ctx.session.auth.current?.subject === void 0 ? {} : { requester: {
|
|
323
|
-
id: ctx.session.auth.current.subject,
|
|
324
|
-
author: humanText(ctx.session.auth.current.attributes.memberName) ?? "the requester"
|
|
325
|
-
} }
|
|
326
|
-
};
|
|
327
|
-
const sent = await withConfirmationPrompt(prompt, () => exactPost ? withChatPostCard(text, send, copy.previewLinks) : withConfirmationText(text, send));
|
|
328
|
-
remember(channel, ctx, sent.id, text, prompt);
|
|
329
|
-
channel.continuation?.alias(formatAddress({
|
|
330
|
-
chatId: channel.telegram.chatId,
|
|
331
|
-
messageThreadId: String(channel.telegram.messageThreadId ?? ""),
|
|
332
|
-
conversationId: ""
|
|
270
|
+
reply_markup: {
|
|
271
|
+
force_reply: true,
|
|
272
|
+
selective: true
|
|
273
|
+
}
|
|
333
274
|
}));
|
|
334
|
-
|
|
335
|
-
state.
|
|
336
|
-
...state.
|
|
337
|
-
[
|
|
338
|
-
|
|
275
|
+
remember(channel, ctx, sent.id, text);
|
|
276
|
+
channel.state.pendingFreeformReplies = {
|
|
277
|
+
...channel.state.pendingFreeformReplies,
|
|
278
|
+
[sent.id]: requestId
|
|
279
|
+
};
|
|
280
|
+
channel.state.hitlPrompts = {
|
|
281
|
+
...channel.state.hitlPrompts,
|
|
282
|
+
[requestId]: {
|
|
339
283
|
messageId: sent.id,
|
|
340
284
|
text,
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
285
|
+
options: (request.options ?? []).map(({ id, label }) => ({
|
|
286
|
+
id,
|
|
287
|
+
label
|
|
288
|
+
}))
|
|
345
289
|
}
|
|
346
290
|
};
|
|
291
|
+
return;
|
|
347
292
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
293
|
+
const callId = "callId" in data.subject ? data.subject.callId : void 0;
|
|
294
|
+
const action = callId === void 0 ? void 0 : call(ctx.view, callId);
|
|
295
|
+
if (callId === void 0 || action === void 0 || data.origin !== void 0) throw new Error("A local tool call is required for confirmation.");
|
|
296
|
+
const memberId = confirmations.get()[callId]?.memberId ?? memberIdOf(ctx.session.auth.current);
|
|
297
|
+
if (memberId === void 0) throw new Error("Confirmation requires a member.");
|
|
298
|
+
const saved = confirmations.get()[callId];
|
|
299
|
+
const description = saved?.description;
|
|
300
|
+
const exactPost = isChatPost(action.name);
|
|
301
|
+
if (description === void 0) throw new Error("Approval buttons require trusted confirmation facts.");
|
|
302
|
+
if (exactPost && description?.chatPost === void 0) throw new Error("An exact chat post cannot show a generic confirmation.");
|
|
303
|
+
const copy = description?.chatPost === void 0 ? renderConfirmation(description, saved?.copy) : chatPostCard(description, saved?.copy);
|
|
304
|
+
const text = copy.text;
|
|
305
|
+
await record(callId, "preview", text, "requested", ctx);
|
|
306
|
+
const send = () => channel.telegram.post({
|
|
307
|
+
text,
|
|
308
|
+
reply_markup: { inline_keyboard: [[
|
|
309
|
+
{
|
|
310
|
+
text: copy.confirm,
|
|
311
|
+
callback_data: confirmationCallback(requestId, memberId, "approve")
|
|
312
|
+
},
|
|
313
|
+
...exactPost ? [{
|
|
314
|
+
text: copy.edit,
|
|
315
|
+
callback_data: confirmationCallback(requestId, memberId, "edit")
|
|
316
|
+
}] : [],
|
|
317
|
+
{
|
|
318
|
+
text: copy.cancel,
|
|
319
|
+
callback_data: confirmationCallback(requestId, memberId, "cancel")
|
|
364
320
|
}
|
|
365
|
-
|
|
321
|
+
]] }
|
|
322
|
+
});
|
|
323
|
+
const prompt = {
|
|
324
|
+
requestId,
|
|
325
|
+
state: "pending",
|
|
326
|
+
sessionId: ctx.session.id,
|
|
327
|
+
address: channel.continuation?.token ?? formatAddress({
|
|
328
|
+
chatId: channel.telegram.chatId,
|
|
329
|
+
messageThreadId: String(channel.telegram.messageThreadId ?? ""),
|
|
330
|
+
conversationId: channel.telegram.conversationId ?? ""
|
|
331
|
+
}),
|
|
332
|
+
action: humanText(description?.action) ?? "the requested action",
|
|
333
|
+
requestedBy: humanText(ctx.session.auth.current?.attributes.memberName) ?? null,
|
|
334
|
+
at: new Date().toISOString(),
|
|
335
|
+
...ctx.session.auth.current?.subject === void 0 ? {} : { requester: {
|
|
336
|
+
id: ctx.session.auth.current.subject,
|
|
337
|
+
author: humanText(ctx.session.auth.current.attributes.memberName) ?? "the requester"
|
|
338
|
+
} }
|
|
339
|
+
};
|
|
340
|
+
const sent = await withConfirmationPrompt(prompt, () => exactPost ? withChatPostCard(text, send, copy.previewLinks) : withConfirmationText(text, send));
|
|
341
|
+
remember(channel, ctx, sent.id, text, prompt);
|
|
342
|
+
channel.continuation?.alias(formatAddress({
|
|
343
|
+
chatId: channel.telegram.chatId,
|
|
344
|
+
messageThreadId: String(channel.telegram.messageThreadId ?? ""),
|
|
345
|
+
conversationId: ""
|
|
346
|
+
}));
|
|
347
|
+
const state = channel.state;
|
|
348
|
+
state.confirmationMessages = {
|
|
349
|
+
...state.confirmationMessages,
|
|
350
|
+
[callId]: {
|
|
351
|
+
requestId,
|
|
352
|
+
messageId: sent.id,
|
|
353
|
+
text,
|
|
354
|
+
copy,
|
|
355
|
+
exactPost,
|
|
356
|
+
prompt,
|
|
357
|
+
previewLinks: copy.previewLinks
|
|
366
358
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
delete state.confirmationMessages?.[callId];
|
|
387
|
-
confirmations.update((all) => ({
|
|
388
|
-
...all,
|
|
389
|
-
...all[callId] === void 0 ? {} : { [callId]: {
|
|
390
|
-
...all[callId],
|
|
391
|
-
status: "cancelled"
|
|
392
|
-
} }
|
|
393
|
-
}));
|
|
359
|
+
};
|
|
360
|
+
},
|
|
361
|
+
async "interaction.settled"(event, ctx) {
|
|
362
|
+
const channel = ctx.channel;
|
|
363
|
+
const state = channel.state;
|
|
364
|
+
const resolution = event.data;
|
|
365
|
+
const entry = Object.entries(state.confirmationMessages ?? {}).find(([, message]) => message.requestId === resolution.interactionId);
|
|
366
|
+
if (entry === void 0) {
|
|
367
|
+
const prompt = channel.state.hitlPrompts?.[resolution.interactionId];
|
|
368
|
+
if (prompt !== void 0) {
|
|
369
|
+
const response = resolution.response;
|
|
370
|
+
const label = response?.text ?? prompt.options.find((option) => option.id === response?.optionId)?.label;
|
|
371
|
+
await channel.telegram.editMessageText({
|
|
372
|
+
messageId: prompt.messageId,
|
|
373
|
+
replyMarkup: { inline_keyboard: [] },
|
|
374
|
+
text: label === void 0 ? prompt.text : `${prompt.text}\n\n${label}`
|
|
375
|
+
});
|
|
376
|
+
delete channel.state.hitlPrompts?.[resolution.interactionId];
|
|
377
|
+
delete channel.state.pendingFreeformReplies?.[prompt.messageId];
|
|
394
378
|
}
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const [callId, message] = entry;
|
|
382
|
+
const copy = message.copy ?? renderConfirmation();
|
|
383
|
+
const reason = confirmations.get()[callId]?.cancellationReason;
|
|
384
|
+
const status = resolution.outcome === "accepted" ? copy.executing : reason === "expired" ? copy.expired : [
|
|
385
|
+
"withdrawn",
|
|
386
|
+
"interrupted",
|
|
387
|
+
"abandoned"
|
|
388
|
+
].includes(resolution.outcome) ? copy.interrupted : copy.cancelled;
|
|
389
|
+
const text = message.exactPost ? chatPostCardStatus(message.text, status) : `${message.text}\n\n${status}`;
|
|
390
|
+
const edit = () => channel.telegram.editMessageText({
|
|
391
|
+
messageId: message.messageId,
|
|
392
|
+
replyMarkup: { inline_keyboard: [] },
|
|
393
|
+
text
|
|
394
|
+
});
|
|
395
|
+
const prompt = {
|
|
396
|
+
...messagePrompt(message),
|
|
397
|
+
state: resolution.outcome === "accepted" ? "approved" : reason === "expired" ? "expired" : [
|
|
398
|
+
"withdrawn",
|
|
399
|
+
"interrupted",
|
|
400
|
+
"abandoned"
|
|
401
|
+
].includes(resolution.outcome) ? "interrupted" : "cancelled"
|
|
402
|
+
};
|
|
403
|
+
message.prompt = prompt;
|
|
404
|
+
await withConfirmationPrompt(prompt, () => message.exactPost ? withChatPostCard(text, edit, [...message.previewLinks ?? [], ...telegramTextLinks(status)]) : withConfirmationText(text, edit));
|
|
405
|
+
remember(channel, ctx, message.messageId, text, prompt);
|
|
406
|
+
await record(callId, reason ?? (resolution.outcome === "accepted" ? "approved" : resolution.outcome === "declined" ? "cancelled" : "ignored"), text, resolution.outcome === "accepted" ? "requested" : "cancelled", ctx);
|
|
407
|
+
if (resolution.outcome !== "accepted") {
|
|
408
|
+
delete state.confirmationMessages?.[callId];
|
|
409
|
+
confirmations.update((all) => ({
|
|
410
|
+
...all,
|
|
411
|
+
...all[callId] === void 0 ? {} : { [callId]: {
|
|
412
|
+
...all[callId],
|
|
413
|
+
status: "cancelled"
|
|
414
|
+
} }
|
|
415
|
+
}));
|
|
395
416
|
}
|
|
396
417
|
},
|
|
397
|
-
async "
|
|
418
|
+
async "call.settled"(event, ctx) {
|
|
419
|
+
const channel = ctx.channel;
|
|
398
420
|
const state = channel.state;
|
|
399
|
-
|
|
400
|
-
|
|
421
|
+
const data = event.data;
|
|
422
|
+
const action = call(ctx.view, data.callId);
|
|
423
|
+
if (action?.kind === "tool" && deferredOptions !== void 0 && archive !== void 0) {
|
|
424
|
+
const output = object(data.output);
|
|
401
425
|
if (output.status === "awaiting_confirmation" && typeof output.confirmation === "string") {
|
|
402
426
|
await postDeferredCard(output.confirmation, channel, ctx, deferredOptions, archive, observed);
|
|
403
427
|
return;
|
|
404
428
|
}
|
|
405
429
|
}
|
|
406
|
-
if (
|
|
407
|
-
const question = object(data.
|
|
408
|
-
if (
|
|
430
|
+
if (action?.kind === "tool") {
|
|
431
|
+
const question = object(data.output).pendingQuestion;
|
|
432
|
+
if (action.name.endsWith("__questions_ask") && isPendingQuestion(question)) {
|
|
409
433
|
const address = channel.continuation?.token ?? formatAddress({
|
|
410
434
|
chatId: channel.telegram.chatId,
|
|
411
435
|
messageThreadId: String(channel.telegram.messageThreadId ?? ""),
|
|
@@ -439,13 +463,13 @@ function telegramConfirmationEvents(archive, observed, deferredOptions) {
|
|
|
439
463
|
remember(channel, ctx, sent.id, question.question);
|
|
440
464
|
}
|
|
441
465
|
}
|
|
442
|
-
const message = state.confirmationMessages?.[data.
|
|
466
|
+
const message = state.confirmationMessages?.[data.callId];
|
|
443
467
|
if (message === void 0) return;
|
|
444
|
-
const failed = data.
|
|
468
|
+
const failed = data.outcome !== "completed" || action?.kind === "tool" && (object(data.output).isError === true || object(object(data.output).validation).ok === false);
|
|
445
469
|
if (message.exactPost) {
|
|
446
470
|
const copy = message.copy ?? renderConfirmation();
|
|
447
|
-
const receipt = !failed &&
|
|
448
|
-
const errorId = failed ? reportTelegramError("confirmed_chat_post_failed", data, { callId: data.
|
|
471
|
+
const receipt = !failed && action?.kind === "tool" ? chatPostReceipt(data.output) : void 0;
|
|
472
|
+
const errorId = failed ? reportTelegramError("confirmed_chat_post_failed", data, { callId: data.callId }) : void 0;
|
|
449
473
|
const status = receipt ?? (failed ? `${copy.failed} ${errorId}` : telegramText("chatPost", "uncertain") ?? "");
|
|
450
474
|
const text = chatPostCardStatus(message.text, status);
|
|
451
475
|
const prompt = {
|
|
@@ -458,10 +482,10 @@ function telegramConfirmationEvents(archive, observed, deferredOptions) {
|
|
|
458
482
|
text
|
|
459
483
|
}), [...message.previewLinks ?? [], ...telegramTextLinks(status)]));
|
|
460
484
|
remember(channel, ctx, message.messageId, text, prompt);
|
|
461
|
-
await record(data.
|
|
485
|
+
await record(data.callId, "receipt", text, failed ? "failed" : object(action?.kind === "tool" ? data.output : void 0).status === "sent" ? "completed" : "unknown", ctx);
|
|
462
486
|
} else {
|
|
463
487
|
const copy = message.copy ?? renderConfirmation();
|
|
464
|
-
const errorId = failed ? reportTelegramError("confirmed_action_failed", data, { callId: data.
|
|
488
|
+
const errorId = failed ? reportTelegramError("confirmed_action_failed", data, { callId: data.callId }) : void 0;
|
|
465
489
|
const status = failed ? `${copy.failed} ${errorId}` : copy.completed;
|
|
466
490
|
const text = `${message.text}\n\n${status}`;
|
|
467
491
|
const prompt = {
|
|
@@ -475,9 +499,10 @@ function telegramConfirmationEvents(archive, observed, deferredOptions) {
|
|
|
475
499
|
})));
|
|
476
500
|
remember(channel, ctx, message.messageId, text, prompt);
|
|
477
501
|
}
|
|
478
|
-
delete state.confirmationMessages?.[data.
|
|
502
|
+
delete state.confirmationMessages?.[data.callId];
|
|
479
503
|
},
|
|
480
|
-
"turn.started"(
|
|
504
|
+
"turn.started"(_event, ctx) {
|
|
505
|
+
const channel = ctx.channel;
|
|
481
506
|
const memberId = memberIdOf(ctx.session.auth.current);
|
|
482
507
|
const answeredId = ctx.session.auth.current?.attributes.pendingQuestionId;
|
|
483
508
|
if (memberId !== void 0 && typeof answeredId === "string") {
|
|
@@ -4,16 +4,16 @@ 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 { n as contentText, t as CONTENT_CAPS } from "../../../_chunks/content-
|
|
7
|
+
import { n as contentText, t as CONTENT_CAPS } from "../../../_chunks/content-cDtVnr8Y.mjs";
|
|
8
8
|
import { conversationEvent, sessionFailureEventId } from "../conversations.mjs";
|
|
9
|
-
import { n as currentInboundRequest, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-
|
|
9
|
+
import { n as currentInboundRequest, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
|
|
10
10
|
import { currentConfirmationPrompt, observedChatKey } from "../group-routing/observed.mjs";
|
|
11
11
|
import { archivedRoutingMessages } from "../group-routing/routing-context.mjs";
|
|
12
12
|
import { contentShape, messageContent } from "./content.mjs";
|
|
13
13
|
import { messageMetadata } from "./observed.mjs";
|
|
14
|
+
import { parseArchivedMessage } from "./archive-message.mjs";
|
|
14
15
|
import { reportMembership } from "./membership.mjs";
|
|
15
16
|
import { createHash, randomUUID } from "node:crypto";
|
|
16
|
-
import { parseTelegramUpdate } from "eve/channels/telegram";
|
|
17
17
|
const captures = new WeakMap();
|
|
18
18
|
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
19
19
|
const id = (value) => typeof value === "number" || typeof value === "string" ? String(value) : null;
|
|
@@ -105,9 +105,8 @@ async function captureTelegramWebhook(input) {
|
|
|
105
105
|
}
|
|
106
106
|
const edited = update.edited_message ?? update.edited_channel_post;
|
|
107
107
|
const messagePayload = edited ?? update.channel_post ?? update.message;
|
|
108
|
-
const
|
|
109
|
-
if (
|
|
110
|
-
const message = parsed.message;
|
|
108
|
+
const message = parseArchivedMessage(messagePayload);
|
|
109
|
+
if (message === void 0) return input.next();
|
|
111
110
|
const content = messageContent(message.raw);
|
|
112
111
|
const structured = input.structured?.(message.raw);
|
|
113
112
|
const time = edited === void 0 ? message.raw.date : message.raw.edit_date ?? message.raw.date;
|
|
@@ -5,5 +5,5 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { isTechnicalText } from "../customer-text-safety.mjs";
|
|
8
|
-
import { a as TelegramDeliveryError, c as customerCopy, d as failureText, f as formattingRefused, h as withDeliveryLocale, l as customerMessage, m as safeTelegramFetch, o as currentLocale, p as reportTelegramError, s as currentThreadId, u as customerText } from "../../../_chunks/inbound-request-
|
|
8
|
+
import { a as TelegramDeliveryError, c as customerCopy, d as failureText, f as formattingRefused, h as withDeliveryLocale, l as customerMessage, m as safeTelegramFetch, o as currentLocale, p as reportTelegramError, s as currentThreadId, u as customerText } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
|
|
9
9
|
export { TelegramDeliveryError, currentLocale, currentThreadId, customerCopy, customerMessage, customerText, failureText, formattingRefused, isTechnicalText, reportTelegramError, safeTelegramFetch, withDeliveryLocale };
|
|
@@ -5,12 +5,12 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { telegramText, withTelegramLocale } from "./texts.mjs";
|
|
8
|
-
import { o as telegramPrincipal } from "../../../_chunks/principal-
|
|
8
|
+
import { o as telegramPrincipal } from "../../../_chunks/principal-BnJuWJtk.mjs";
|
|
9
9
|
import { humanText } from "../confirmation-description.mjs";
|
|
10
10
|
import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
|
|
11
11
|
import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
|
|
12
12
|
import { conversationEvent } from "../conversations.mjs";
|
|
13
|
-
import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-
|
|
13
|
+
import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
|
|
14
14
|
import { agentMessage, observedChatKey, withConfirmationPrompt } from "../group-routing/observed.mjs";
|
|
15
15
|
import { CONFIRMATION_TTL_MS, inputHash } from "../confirmations.mjs";
|
|
16
16
|
import { OntologyToolRejected } from "../ontology-tools.mjs";
|
|
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { redactTelegramDiagnostic } from "./diagnostic-redaction.mjs";
|
|
8
|
-
import { n as contentText, t as CONTENT_CAPS } from "../../../_chunks/content-
|
|
8
|
+
import { n as contentText, t as CONTENT_CAPS } from "../../../_chunks/content-cDtVnr8Y.mjs";
|
|
9
9
|
import { conversationEvent } from "../conversations.mjs";
|
|
10
10
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
11
|
const pending = new AsyncLocalStorage();
|
|
@@ -14,6 +14,17 @@ export interface TypingCursor {
|
|
|
14
14
|
}
|
|
15
15
|
interface TypingEvent {
|
|
16
16
|
readonly type: string;
|
|
17
|
+
readonly scope?: {
|
|
18
|
+
readonly turnId?: string;
|
|
19
|
+
};
|
|
20
|
+
readonly meta?: {
|
|
21
|
+
readonly position?: {
|
|
22
|
+
readonly line: number;
|
|
23
|
+
readonly index: number;
|
|
24
|
+
};
|
|
25
|
+
readonly endOfLine?: boolean;
|
|
26
|
+
readonly next?: number;
|
|
27
|
+
};
|
|
17
28
|
readonly data?: unknown;
|
|
18
29
|
}
|
|
19
30
|
interface TypingBlockDependencies {
|
|
@@ -8,7 +8,7 @@ import { channelsEnabled, proxyEnvironment } from "../environment.mjs";
|
|
|
8
8
|
import { redactTelegramDiagnostic } from "./diagnostic-redaction.mjs";
|
|
9
9
|
import { runtimeToken } from "../runtime-token.mjs";
|
|
10
10
|
import { conversationEvent, conversations } from "../conversations.mjs";
|
|
11
|
-
import { p as reportTelegramError } from "../../../_chunks/inbound-request-
|
|
11
|
+
import { p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
|
|
12
12
|
import { connectionProxy } from "../connection-proxy.mjs";
|
|
13
13
|
import { sessions } from "eve/server";
|
|
14
14
|
const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -46,16 +46,16 @@ async function runTypingBlock(source, cursor, dependencies) {
|
|
|
46
46
|
if (next === null) return result(false, "history_read_timeout");
|
|
47
47
|
if (next.done) break;
|
|
48
48
|
const event = next.value;
|
|
49
|
-
index += 1;
|
|
49
|
+
if (event.meta?.position === void 0) index += 1;
|
|
50
|
+
else if (event.meta.endOfLine !== false) index = event.meta.next ?? event.meta.position.line + 1;
|
|
50
51
|
const data = object(event.data) ? event.data : {};
|
|
51
|
-
if (event.type === "
|
|
52
|
-
if (
|
|
53
|
-
if (turnId !== null && data.turnId === turnId &&
|
|
54
|
-
"turn.
|
|
55
|
-
"turn.
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
].includes(event.type) || event.type === "turn.waiting" && data.on === "input")) return result(true, event.type);
|
|
52
|
+
if (event.type === "delivery.consumed" && Array.isArray(data.parts) && typeof source.marker === "string" && source.marker !== "" && data.parts.some((part) => object(part) && part.kind === "text" && typeof part.text === "string" && part.text.includes(source.marker)) && typeof data.turnId === "string") turnId = data.turnId;
|
|
53
|
+
if (event.type === "session.ended") return result(true, event.type);
|
|
54
|
+
if (turnId !== null && (event.scope?.turnId ?? data.turnId) === turnId && [
|
|
55
|
+
"turn.settled",
|
|
56
|
+
"turn.paused",
|
|
57
|
+
"interaction.opened"
|
|
58
|
+
].includes(event.type)) return result(true, event.type);
|
|
59
59
|
}
|
|
60
60
|
} finally {
|
|
61
61
|
clearTimeout(timer);
|
|
@@ -4,8 +4,8 @@ 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 { n as conversationLanguage } from "../../../_chunks/principal-
|
|
8
|
-
import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-
|
|
7
|
+
import { n as conversationLanguage } from "../../../_chunks/principal-BnJuWJtk.mjs";
|
|
8
|
+
import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
|
|
9
9
|
import { describableImage, describeReceivedImage } from "./images.mjs";
|
|
10
10
|
import { MAXIMUM_ATTACHMENT_BYTES, attachmentUrl } from "../attachments.mjs";
|
|
11
11
|
function telegramConversation(chatId) {
|