@segmentstream/agent 0.12.1 → 0.13.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/README.md +29 -22
- package/dist/_chunks/{build-metadata-Dl-ZJp5p.mjs → build-metadata-BLeBanNg.mjs} +1 -1
- package/dist/_chunks/{inbound-request-BrWspFw5.mjs → inbound-request-BXhiIph-.mjs} +21 -19
- package/dist/_chunks/{workflow-serializable-BxrXgxjc.mjs → workflow-serializable-DVQBWK8p.mjs} +87 -4
- package/dist/extension/_manifest.json +0 -1
- package/dist/extension/config.d.ts +18 -5
- package/dist/extension/config.mjs +138 -18
- package/dist/extension/extension.d.ts +7 -1
- package/dist/extension/hooks/authorization.d.ts +3 -0
- package/dist/extension/hooks/authorization.mjs +16 -0
- package/dist/extension/instructions.md +3 -4
- package/dist/extension/lib/build-metadata.mjs +1 -1
- package/dist/extension/lib/chat-post-confirmation.d.ts +1 -0
- package/dist/extension/lib/chat-post-confirmation.mjs +4 -2
- package/dist/extension/lib/confirmation-outcome.d.ts +1 -1
- package/dist/extension/lib/confirmations.d.ts +2 -0
- package/dist/extension/lib/confirmations.mjs +7 -4
- package/dist/extension/lib/conversations.mjs +1 -1
- package/dist/extension/lib/deferred-confirmations.d.ts +3 -0
- package/dist/extension/lib/deferred-confirmations.mjs +2 -0
- package/dist/extension/lib/ontology-tools.mjs +1 -1
- package/dist/extension/lib/telegram/adapter.mjs +34 -7
- package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
- package/dist/extension/lib/telegram/attachments-send.mjs +13 -10
- package/dist/extension/lib/telegram/chat-post-card.d.ts +1 -1
- package/dist/extension/lib/telegram/chat-post-card.mjs +13 -10
- package/dist/extension/lib/telegram/confirmation-expiry.d.ts +2 -1
- package/dist/extension/lib/telegram/confirmation-expiry.mjs +5 -4
- package/dist/extension/lib/telegram/confirmation-text.d.ts +1 -1
- package/dist/extension/lib/telegram/confirmation-text.mjs +18 -12
- package/dist/extension/lib/telegram/confirmations.mjs +24 -19
- package/dist/extension/lib/telegram/conversations.d.ts +2 -0
- package/dist/extension/lib/telegram/conversations.mjs +14 -1
- package/dist/extension/lib/telegram/customer-text.d.ts +9 -8
- package/dist/extension/lib/telegram/customer-text.mjs +1 -1
- package/dist/extension/lib/telegram/deferred-confirmations.mjs +10 -9
- package/dist/extension/lib/telegram/files.mjs +1 -1
- package/dist/extension/lib/telegram/health.mjs +1 -1
- package/dist/extension/lib/telegram/images.mjs +1 -1
- package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
- package/dist/extension/lib/telegram/inbound.mjs +18 -17
- package/dist/extension/lib/telegram/lifecycle.mjs +2 -2
- package/dist/extension/lib/telegram/media-policy.mjs +1 -1
- package/dist/extension/lib/telegram/silent.mjs +1 -1
- package/dist/extension/lib/telegram/texts.d.ts +16 -0
- package/dist/extension/lib/telegram/texts.mjs +70 -0
- package/dist/extension/lib/telegram/turn-errors.d.ts +1 -1
- package/dist/extension/lib/telegram/turn-errors.mjs +37 -3
- package/dist/extension/lib/telegram/voice.mjs +1 -1
- package/dist/extension/lib/workflow-serializable.mjs +1 -1
- package/dist/extension/schedules/confirmations.mjs +1 -1
- 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 +3 -1
- 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.mjs +1 -1
- package/dist/extension/tools/questions_ask.mjs +1 -1
- package/package.json +2 -2
- package/dist/extension/connections/ontology.d.ts +0 -7
- package/dist/extension/connections/ontology.mjs +0 -11
|
@@ -5,6 +5,9 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { effectiveGroupPolicy, groupPolicy } from "./lib/group-routing/policy.mjs";
|
|
8
|
+
import { localizedText as localizedText$1 } from "./lib/admission.mjs";
|
|
9
|
+
import { TELEGRAM_TEXT_KEYS } from "./lib/telegram/texts.mjs";
|
|
10
|
+
import { isTechnicalText } from "./lib/customer-text-safety.mjs";
|
|
8
11
|
import { readFileSync, realpathSync } from "node:fs";
|
|
9
12
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
10
13
|
import { expandGroupFiles, groupPolicyIssues } from "@segmentstream-cloud/ontology/groups";
|
|
@@ -24,6 +27,9 @@ const DEFAULT_ADMISSION_LIMITS = {
|
|
|
24
27
|
workspaceTurnsPerDay: 3e3
|
|
25
28
|
};
|
|
26
29
|
const ADMISSION_REPLY_KEYS = [
|
|
30
|
+
"pairingRequired",
|
|
31
|
+
"pairingButton",
|
|
32
|
+
"groupPairingButton",
|
|
27
33
|
"limited",
|
|
28
34
|
"perSenderLimited",
|
|
29
35
|
"workspaceLimited",
|
|
@@ -72,7 +78,8 @@ function telegramSettings(value, issues) {
|
|
|
72
78
|
"groups",
|
|
73
79
|
"linkPreviews",
|
|
74
80
|
"additionalOwnOrigins",
|
|
75
|
-
"attachmentLifecycle"
|
|
81
|
+
"attachmentLifecycle",
|
|
82
|
+
"menuButton"
|
|
76
83
|
],
|
|
77
84
|
issues
|
|
78
85
|
});
|
|
@@ -115,6 +122,17 @@ function telegramSettings(value, issues) {
|
|
|
115
122
|
message: "must be an array of HTTP(S) origins without paths, credentials, queries or fragments",
|
|
116
123
|
path: [...path, "additionalOwnOrigins"]
|
|
117
124
|
});
|
|
125
|
+
const menuButton = section({
|
|
126
|
+
value: telegram.menuButton,
|
|
127
|
+
path: [...path, "menuButton"],
|
|
128
|
+
allowed: ["text"],
|
|
129
|
+
issues
|
|
130
|
+
});
|
|
131
|
+
const menuText = menuButton === void 0 ? void 0 : localizedText(menuButton.text, [
|
|
132
|
+
...path,
|
|
133
|
+
"menuButton",
|
|
134
|
+
"text"
|
|
135
|
+
], issues, 64);
|
|
118
136
|
const lifecycle = section({
|
|
119
137
|
value: telegram.attachmentLifecycle,
|
|
120
138
|
path: [...path, "attachmentLifecycle"],
|
|
@@ -143,6 +161,7 @@ function telegramSettings(value, issues) {
|
|
|
143
161
|
...signalSettings === void 0 ? {} : { groups: signalSettings },
|
|
144
162
|
linkPreviews,
|
|
145
163
|
additionalOwnOrigins,
|
|
164
|
+
...menuText === void 0 ? {} : { menuButton: { text: menuText } },
|
|
146
165
|
...lifecycle === void 0 ? {} : { attachmentLifecycle: {
|
|
147
166
|
entity: String(lifecycle.entity),
|
|
148
167
|
action: String(lifecycle.action),
|
|
@@ -265,7 +284,7 @@ function sessionSettings(value, issues) {
|
|
|
265
284
|
idleResetHours: typeof idleResetHours === "number" && Number.isFinite(idleResetHours) && idleResetHours > 0 ? idleResetHours : false
|
|
266
285
|
};
|
|
267
286
|
}
|
|
268
|
-
function localizedText(value, path, issues) {
|
|
287
|
+
function localizedText(value, path, issues, maximum = 4e3, safe = true) {
|
|
269
288
|
if (!isRecord(value) || Object.keys(value).length === 0) {
|
|
270
289
|
issues.push({
|
|
271
290
|
message: "must be a non-empty locale-to-text object",
|
|
@@ -282,14 +301,14 @@ function localizedText(value, path, issues) {
|
|
|
282
301
|
path: [...path, locale]
|
|
283
302
|
});
|
|
284
303
|
}
|
|
285
|
-
if (typeof text !== "string" || text.trim() === "" || text.length >
|
|
286
|
-
message:
|
|
304
|
+
if (typeof text !== "string" || text.trim() === "" || text.length > maximum || safe && typeof text === "string" && isTechnicalText(text)) issues.push({
|
|
305
|
+
message: `must be ${safe ? "safe " : ""}non-empty text of at most ${maximum} characters`,
|
|
287
306
|
path: [...path, locale]
|
|
288
307
|
});
|
|
289
308
|
}
|
|
290
309
|
return value;
|
|
291
310
|
}
|
|
292
|
-
function firstContactSettings(value, issues) {
|
|
311
|
+
function firstContactSettings(value, issues, safe = true) {
|
|
293
312
|
const path = ["firstContact"];
|
|
294
313
|
const settings = section({
|
|
295
314
|
value,
|
|
@@ -303,7 +322,7 @@ function firstContactSettings(value, issues) {
|
|
|
303
322
|
message: "must be non-empty text of at most 200 characters without surrounding whitespace",
|
|
304
323
|
path: [...path, "version"]
|
|
305
324
|
});
|
|
306
|
-
const notice = localizedText(settings.notice, [...path, "notice"], issues);
|
|
325
|
+
const notice = localizedText(settings.notice, [...path, "notice"], issues, 4e3, safe);
|
|
307
326
|
return {
|
|
308
327
|
version: typeof version === "string" ? version : "",
|
|
309
328
|
notice
|
|
@@ -351,7 +370,7 @@ function admissionLimits(value, issues) {
|
|
|
351
370
|
workspaceTurnsPerDay: limit(limits?.workspaceTurnsPerDay, DEFAULT_ADMISSION_LIMITS.workspaceTurnsPerDay, [...path, "workspaceTurnsPerDay"])
|
|
352
371
|
};
|
|
353
372
|
}
|
|
354
|
-
function admissionReplies(value, issues) {
|
|
373
|
+
function admissionReplies(value, issues, safe = true) {
|
|
355
374
|
const replies = section({
|
|
356
375
|
value,
|
|
357
376
|
path: ["replies"],
|
|
@@ -359,10 +378,90 @@ function admissionReplies(value, issues) {
|
|
|
359
378
|
issues
|
|
360
379
|
});
|
|
361
380
|
const configured = {};
|
|
362
|
-
for (const key of ADMISSION_REPLY_KEYS) if (replies?.[key] !== void 0) configured[key] = localizedText(replies[key], ["replies", key], issues);
|
|
381
|
+
for (const key of ADMISSION_REPLY_KEYS) if (replies?.[key] !== void 0) configured[key] = localizedText(replies[key], ["replies", key], issues, safe && key.endsWith("Button") ? 24 : 4e3, safe);
|
|
363
382
|
return configured;
|
|
364
383
|
}
|
|
365
|
-
function
|
|
384
|
+
function telegramTexts(value, issues) {
|
|
385
|
+
const root = section({
|
|
386
|
+
value,
|
|
387
|
+
path: ["texts"],
|
|
388
|
+
allowed: Object.keys(TELEGRAM_TEXT_KEYS),
|
|
389
|
+
issues
|
|
390
|
+
});
|
|
391
|
+
const output = {};
|
|
392
|
+
for (const [group, keys] of Object.entries(TELEGRAM_TEXT_KEYS)) {
|
|
393
|
+
const sectionValue = section({
|
|
394
|
+
value: root?.[group],
|
|
395
|
+
path: ["texts", group],
|
|
396
|
+
allowed: keys,
|
|
397
|
+
issues
|
|
398
|
+
});
|
|
399
|
+
if (sectionValue === void 0) continue;
|
|
400
|
+
output[group] = {};
|
|
401
|
+
for (const key of keys) if (sectionValue[key] !== void 0) {
|
|
402
|
+
const maximum = group === "confirmation" ? key === "question" ? 300 : 24 : group === "callback" ? 200 : group === "authorization" && key === "button" ? 24 : 4e3;
|
|
403
|
+
output[group][key] = localizedText(sectionValue[key], [
|
|
404
|
+
"texts",
|
|
405
|
+
group,
|
|
406
|
+
key
|
|
407
|
+
], issues, maximum);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const confirmation = output.confirmation;
|
|
411
|
+
if (confirmation?.confirm !== void 0 && confirmation.cancel !== void 0) {
|
|
412
|
+
const locales = new Set([
|
|
413
|
+
"en",
|
|
414
|
+
...Object.keys(confirmation.confirm),
|
|
415
|
+
...Object.keys(confirmation.cancel)
|
|
416
|
+
]);
|
|
417
|
+
for (const locale of locales) {
|
|
418
|
+
const confirm = localizedText$1(confirmation.confirm, locale);
|
|
419
|
+
const cancel = localizedText$1(confirmation.cancel, locale);
|
|
420
|
+
if (typeof confirm === "string" && typeof cancel === "string" && confirm.trim() === cancel.trim()) issues.push({
|
|
421
|
+
message: "confirm and cancel must have distinct effective localized labels",
|
|
422
|
+
path: [
|
|
423
|
+
"texts",
|
|
424
|
+
"confirmation",
|
|
425
|
+
"cancel",
|
|
426
|
+
locale
|
|
427
|
+
]
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const authorization = output.authorization;
|
|
432
|
+
if (authorization?.url !== void 0) for (const [locale, value] of Object.entries(authorization.url)) try {
|
|
433
|
+
const url = new URL(value);
|
|
434
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) throw new Error("Invalid authorization URL");
|
|
435
|
+
} catch {
|
|
436
|
+
issues.push({
|
|
437
|
+
message: "must be an HTTP(S) URL without credentials",
|
|
438
|
+
path: [
|
|
439
|
+
"texts",
|
|
440
|
+
"authorization",
|
|
441
|
+
"url",
|
|
442
|
+
locale
|
|
443
|
+
]
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
if ((authorization?.url !== void 0 || authorization?.button !== void 0) && authorization?.prompt === void 0) issues.push({
|
|
447
|
+
message: "is required when an authorization button is configured",
|
|
448
|
+
path: [
|
|
449
|
+
"texts",
|
|
450
|
+
"authorization",
|
|
451
|
+
"prompt"
|
|
452
|
+
]
|
|
453
|
+
});
|
|
454
|
+
if (authorization?.url === void 0 !== (authorization?.button === void 0)) issues.push({
|
|
455
|
+
message: "url and button must be supplied together",
|
|
456
|
+
path: ["texts", "authorization"]
|
|
457
|
+
});
|
|
458
|
+
return output;
|
|
459
|
+
}
|
|
460
|
+
function isLegacyAgentArchive(version) {
|
|
461
|
+
return /^0\.(?:[0-9]|1[0-2])\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version ?? "");
|
|
462
|
+
}
|
|
463
|
+
function validateConfig(input, options = {}) {
|
|
464
|
+
const legacyArchive = isLegacyAgentArchive(options.archiveSdkVersion);
|
|
366
465
|
const issues = [];
|
|
367
466
|
const root = section({
|
|
368
467
|
value: input ?? {},
|
|
@@ -376,7 +475,8 @@ function validateConfig(input) {
|
|
|
376
475
|
"confirmations",
|
|
377
476
|
"firstContact",
|
|
378
477
|
"limits",
|
|
379
|
-
"replies"
|
|
478
|
+
"replies",
|
|
479
|
+
"texts"
|
|
380
480
|
],
|
|
381
481
|
issues
|
|
382
482
|
});
|
|
@@ -410,8 +510,8 @@ function validateConfig(input) {
|
|
|
410
510
|
allowed: ["mode"],
|
|
411
511
|
issues
|
|
412
512
|
})?.mode ?? "deferred";
|
|
413
|
-
if (mode !== "deferred" && mode
|
|
414
|
-
message: "must be \"deferred\"
|
|
513
|
+
if (mode !== "deferred" && !(legacyArchive && mode === "held")) issues.push({
|
|
514
|
+
message: "must be \"deferred\"; Telegram Eve approval buttons are unsupported",
|
|
415
515
|
path: ["confirmations", "mode"]
|
|
416
516
|
});
|
|
417
517
|
const telegram = telegramSettings(channels?.telegram, issues);
|
|
@@ -502,9 +602,28 @@ function validateConfig(input) {
|
|
|
502
602
|
});
|
|
503
603
|
const connection = ontology?.connection ?? true;
|
|
504
604
|
const sessions = sessionSettings(root?.sessions, issues);
|
|
505
|
-
const firstContact = firstContactSettings(root?.firstContact, issues);
|
|
605
|
+
const firstContact = firstContactSettings(root?.firstContact, issues, !legacyArchive);
|
|
506
606
|
const limits = admissionLimits(root?.limits, issues);
|
|
507
|
-
const replies = admissionReplies(root?.replies, issues);
|
|
607
|
+
const replies = admissionReplies(root?.replies, issues, !legacyArchive);
|
|
608
|
+
const texts = telegramTexts(root?.texts, issues);
|
|
609
|
+
if (!legacyArchive && replies.groupPairingButton !== void 0 && replies.groupPairingRequired === void 0) issues.push({
|
|
610
|
+
message: "is required when groupPairingButton is configured",
|
|
611
|
+
path: ["replies", "groupPairingRequired"]
|
|
612
|
+
});
|
|
613
|
+
if (telegram !== null && !legacyArchive) {
|
|
614
|
+
for (const key of ["pairingRequired", "pairingButton"]) if (replies[key] === void 0) issues.push({
|
|
615
|
+
message: "is required for Telegram",
|
|
616
|
+
path: ["replies", key]
|
|
617
|
+
});
|
|
618
|
+
for (const key of TELEGRAM_TEXT_KEYS.confirmation) if (texts.confirmation?.[key] === void 0) issues.push({
|
|
619
|
+
message: "is required for Telegram confirmations",
|
|
620
|
+
path: [
|
|
621
|
+
"texts",
|
|
622
|
+
"confirmation",
|
|
623
|
+
key
|
|
624
|
+
]
|
|
625
|
+
});
|
|
626
|
+
}
|
|
508
627
|
if (typeof connection !== "boolean") issues.push({
|
|
509
628
|
message: "must be true or false",
|
|
510
629
|
path: ["ontology", "connection"]
|
|
@@ -524,17 +643,18 @@ function validateConfig(input) {
|
|
|
524
643
|
attachments
|
|
525
644
|
},
|
|
526
645
|
ontology: { connection: connection === true },
|
|
527
|
-
confirmations: { mode:
|
|
646
|
+
confirmations: { mode: "deferred" },
|
|
528
647
|
sessions,
|
|
529
648
|
firstContact,
|
|
530
649
|
limits,
|
|
531
|
-
replies
|
|
650
|
+
replies,
|
|
651
|
+
texts
|
|
532
652
|
} };
|
|
533
653
|
}
|
|
534
654
|
const configSchema = { "~standard": {
|
|
535
655
|
version: 1,
|
|
536
656
|
vendor: "segmentstream",
|
|
537
|
-
validate: validateConfig,
|
|
657
|
+
validate: (input) => validateConfig(input),
|
|
538
658
|
types: void 0
|
|
539
659
|
} };
|
|
540
660
|
function manifestOf(config) {
|
|
@@ -542,4 +662,4 @@ function manifestOf(config) {
|
|
|
542
662
|
if (validation.issues !== void 0) throw new SegmentStreamAgentConfigError(validation.issues);
|
|
543
663
|
return validation.value;
|
|
544
664
|
}
|
|
545
|
-
export { ADMISSION_REPLY_KEYS, DEFAULT_ADMISSION_LIMITS, DEFAULT_ATTACHMENTS_MODEL, DEFAULT_DECISION_MODEL, DEFAULT_IMAGE_DESCRIPTION_MODEL, DEFAULT_STT_MODEL, SESSION_SCOPES, SegmentStreamAgentConfigError, TELEGRAM_POLICIES, configSchema, manifestOf, validateConfig };
|
|
665
|
+
export { ADMISSION_REPLY_KEYS, DEFAULT_ADMISSION_LIMITS, DEFAULT_ATTACHMENTS_MODEL, DEFAULT_DECISION_MODEL, DEFAULT_IMAGE_DESCRIPTION_MODEL, DEFAULT_STT_MODEL, SESSION_SCOPES, SegmentStreamAgentConfigError, TELEGRAM_POLICIES, configSchema, isLegacyAgentArchive, manifestOf, validateConfig };
|
|
@@ -4,7 +4,12 @@ export declare const segmentstream: import("eve/extension").ExtensionHandle<{
|
|
|
4
4
|
readonly "~standard": {
|
|
5
5
|
readonly version: 1;
|
|
6
6
|
readonly vendor: "segmentstream";
|
|
7
|
-
readonly validate:
|
|
7
|
+
readonly validate: (input: unknown) => {
|
|
8
|
+
readonly value: import("./config.js").SegmentStreamAgentConfig;
|
|
9
|
+
readonly issues?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
readonly issues: ReadonlyArray<import("./config.js").ConfigIssue>;
|
|
12
|
+
};
|
|
8
13
|
readonly types: {
|
|
9
14
|
readonly input: import("./config.js").SegmentStreamAgentConfigInput;
|
|
10
15
|
readonly output: import("./config.js").SegmentStreamAgentConfig;
|
|
@@ -25,3 +30,4 @@ export { archivedRoutingMessages } from "./lib/group-routing/routing-context.js"
|
|
|
25
30
|
export { replayRouterPayload } from "./lib/group-routing/replay.js";
|
|
26
31
|
export { conversationState as groupConversationState, conversationAddressing as groupConversationAddressing, type ConversationAnalysis, type ConversationPath, } from "./lib/group-routing/conversation.js";
|
|
27
32
|
export { routingBurst, debounceBurst } from "./lib/group-routing/burst.js";
|
|
33
|
+
export type { TelegramTexts } from "./lib/telegram/texts.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { fileURLToPath as __eveFileURLToPath } from "node:url";
|
|
2
|
+
import { dirname as __eveDirname } from "node:path";
|
|
3
|
+
import { createRequire as __eveCreateRequire } from "node:module";
|
|
4
|
+
const __filename = __eveFileURLToPath(import.meta.url);
|
|
5
|
+
__eveDirname(__filename);
|
|
6
|
+
__eveCreateRequire(import.meta.url);
|
|
7
|
+
import { localizedText } from "../lib/admission.mjs";
|
|
8
|
+
import "../lib/telegram/principal.mjs";
|
|
9
|
+
import segmentstream from "../extension.mjs";
|
|
10
|
+
import { confirmationLocale } from "../lib/telegram/confirmation-text.mjs";
|
|
11
|
+
import { defineHook } from "eve/hooks";
|
|
12
|
+
var authorization_default = defineHook({ events: { "authorization.required": (event, context) => {
|
|
13
|
+
const principal = context.session.auth.current;
|
|
14
|
+
if (principal?.authenticator === "segmentstream-telegram" && event.data.candidateId === void 0 && localizedText(segmentstream.config.texts?.authorization?.prompt, confirmationLocale(principal)) === void 0) context.cancel();
|
|
15
|
+
} } });
|
|
16
|
+
export { authorization_default as default };
|
|
@@ -11,7 +11,6 @@ talking to you, and you act with exactly their permissions.
|
|
|
11
11
|
exact MCP names and input schemas. Pass returned ontology hashes as `expected_hash`
|
|
12
12
|
on subsequent describe/discover requests so a redeployment cannot mix definitions.
|
|
13
13
|
These tools are directly available; do not search a connection namespace to find them.
|
|
14
|
-
With held confirmations the same operations are reached through `segmentstream__ontology`.
|
|
15
14
|
Call `me` when you need to check whom you act for. For an unfamiliar task, call `describe`
|
|
16
15
|
without a ref for a compact entity index, or `discover` to search names and descriptions.
|
|
17
16
|
Inspect relevant `entity:`, `action:`, or `measure:` refs with `describe` for their complete
|
|
@@ -42,14 +41,14 @@ talking to you, and you act with exactly their permissions.
|
|
|
42
41
|
the member explicitly cancels or replaces the earlier task. If work is interrupted or blocked,
|
|
43
42
|
say what remains unfinished; never silently replace it with the latest question.
|
|
44
43
|
- Destructive or irreversible actions, and legacy custom actions without safety labels, require
|
|
45
|
-
the tool boundary's
|
|
44
|
+
the tool boundary's workspace-authored confirmation buttons. Call the action to start that flow; never ask for
|
|
46
45
|
approval in prose or treat a text acknowledgement as approval. Wait for the button outcome.
|
|
47
46
|
When the tool schema offers `_confirmation`, supply {question, confirm, cancel, done,
|
|
48
47
|
cancelled, failed, expired?, edit?} in the chat's language. Describe the action and key
|
|
49
48
|
parameters in a plain single-line question (at most 300 characters); labels are at most
|
|
50
49
|
24 characters. No IDs, tool names, snake_case, URLs, credentials, or markup. The platform
|
|
51
|
-
adds trusted facts
|
|
52
|
-
|
|
50
|
+
adds trusted facts. Omit this argument on older tools without schema support.
|
|
51
|
+
Use distinct confirm/cancel labels; all visible wording comes from the workspace. If trusted
|
|
53
52
|
target titles are unavailable or the facts are too long, resolve the targets or narrow the call.
|
|
54
53
|
Cancel ends that call; retry it only after a new instruction from the member.
|
|
55
54
|
- Every change goes through an action. Report results after success; never claim a record changed
|
|
@@ -4,5 +4,5 @@ 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 { t as agentBuild } from "../../_chunks/build-metadata-
|
|
7
|
+
import { t as agentBuild } from "../../_chunks/build-metadata-BLeBanNg.mjs";
|
|
8
8
|
export { agentBuild };
|
|
@@ -47,8 +47,9 @@ function describeChatPost(input) {
|
|
|
47
47
|
caller.attribution
|
|
48
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
49
|
const footer = escapeMarkdownV2(caller.attribution);
|
|
50
|
+
const separator = typeof caller.attribution_separator === "string" ? caller.attribution_separator : "\n\n";
|
|
50
51
|
return {
|
|
51
|
-
action: "
|
|
52
|
+
action: "",
|
|
52
53
|
fields: [],
|
|
53
54
|
chatPost: {
|
|
54
55
|
chatId: target.id,
|
|
@@ -56,8 +57,9 @@ function describeChatPost(input) {
|
|
|
56
57
|
externalId: target.external_id,
|
|
57
58
|
title: target.title,
|
|
58
59
|
attribution: caller.attribution,
|
|
60
|
+
...separator === "\n\n" ? {} : { attributionSeparator: separator },
|
|
59
61
|
text: values.text,
|
|
60
|
-
finalText: `${converter.fromMarkdown(values.text)}
|
|
62
|
+
finalText: `${converter.fromMarkdown(values.text)}${escapeMarkdownV2(separator)}_${footer}_`,
|
|
61
63
|
replyTo: typeof values.reply_to === "string" ? values.reply_to : null
|
|
62
64
|
}
|
|
63
65
|
};
|
|
@@ -22,6 +22,6 @@ export declare function confirmationOutcome(record: DeferredConfirmation, status
|
|
|
22
22
|
request?: string | undefined;
|
|
23
23
|
} | undefined;
|
|
24
24
|
confirmation: string;
|
|
25
|
-
status: "
|
|
25
|
+
status: "expired" | "done" | "cancelled" | "failed" | "approved";
|
|
26
26
|
summary: string;
|
|
27
27
|
};
|
|
@@ -2,6 +2,7 @@ import { type StateHandle } from "eve/context";
|
|
|
2
2
|
import type { ApprovalConfiguration } from "eve/tools/approval";
|
|
3
3
|
import type { ConfirmationDescription } from "./confirmation-description.js";
|
|
4
4
|
import { type ConfirmationCopy } from "./telegram/confirmation-text.js";
|
|
5
|
+
import { type TelegramTexts } from "./telegram/texts.js";
|
|
5
6
|
export declare const CONFIRMATION_TTL_MS: number;
|
|
6
7
|
export interface ActionAnnotations {
|
|
7
8
|
readonly readOnlyHint?: boolean;
|
|
@@ -33,6 +34,7 @@ export declare const confirmations: StateHandle<Record<string, Confirmation>>;
|
|
|
33
34
|
export declare function actionApproval(options: {
|
|
34
35
|
readonly labels: (memberId: string, action: string, input: Readonly<Record<string, unknown>>) => Promise<ActionAnnotations>;
|
|
35
36
|
readonly describe?: (memberId: string, action: string, input: Readonly<Record<string, unknown>>) => Promise<ConfirmationDescription>;
|
|
37
|
+
readonly texts?: () => TelegramTexts;
|
|
36
38
|
readonly state?: StateHandle<Record<string, Confirmation>>;
|
|
37
39
|
readonly now?: () => number;
|
|
38
40
|
}): ApprovalConfiguration;
|
|
@@ -4,8 +4,9 @@ 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 { withTelegramTexts } from "./telegram/texts.mjs";
|
|
7
8
|
import { memberIdOf } from "./telegram/principal.mjs";
|
|
8
|
-
import { confirmationCopy, renderConfirmation } from "./telegram/confirmation-text.mjs";
|
|
9
|
+
import { confirmationCopy, confirmationLocale, renderConfirmation } from "./telegram/confirmation-text.mjs";
|
|
9
10
|
import { chatPostCard } from "./telegram/chat-post-card.mjs";
|
|
10
11
|
import { chatPostDigest, isChatPost } from "./chat-post-confirmation.mjs";
|
|
11
12
|
import { createHash } from "node:crypto";
|
|
@@ -36,6 +37,7 @@ function actionApproval(options) {
|
|
|
36
37
|
async request(ctx) {
|
|
37
38
|
const memberId = memberIdOf(ctx.session.auth.current);
|
|
38
39
|
if (memberId === void 0) return denied("A paired member is required.");
|
|
40
|
+
const present = (run) => options.texts === void 0 ? run() : withTelegramTexts(options.texts(), run, () => confirmationLocale(ctx.session.auth.current));
|
|
39
41
|
const hash = inputHash(ctx.toolInput ?? {});
|
|
40
42
|
const saved = state.get()[ctx.callId];
|
|
41
43
|
if (saved !== void 0) {
|
|
@@ -59,10 +61,11 @@ function actionApproval(options) {
|
|
|
59
61
|
const preview = description?.chatPost;
|
|
60
62
|
const source = ctx.session.auth.current?.attributes;
|
|
61
63
|
if (description === void 0 || preview === void 0 || typeof source?.chatId !== "string" || source.chatId === preview.externalId) return denied("A complete preview for a different chat is required. Reply normally in this chat.");
|
|
62
|
-
|
|
64
|
+
const previewDescription = {
|
|
63
65
|
...description,
|
|
64
66
|
warning: labels.destructiveHint === true || labels.irreversibleHint === true
|
|
65
|
-
}
|
|
67
|
+
};
|
|
68
|
+
present(() => chatPostCard(previewDescription, copy));
|
|
66
69
|
if (saved !== void 0 && (saved.description?.chatPost === void 0 || chatPostDigest(saved.description.chatPost) !== chatPostDigest(preview) || saved.source?.chatId !== source.chatId || saved.source.threadId !== String(source.messageThreadId ?? ""))) return denied("The destination or attribution changed. Make a new call and confirmation.");
|
|
67
70
|
} catch (error) {
|
|
68
71
|
console.warn("The exact chat confirmation could not be prepared.", error);
|
|
@@ -92,7 +95,7 @@ function actionApproval(options) {
|
|
|
92
95
|
warning: labels.destructiveHint === true || labels.irreversibleHint === true
|
|
93
96
|
};
|
|
94
97
|
try {
|
|
95
|
-
if (!posting) renderConfirmation(description, copy);
|
|
98
|
+
if (!posting) present(() => renderConfirmation(description, copy));
|
|
96
99
|
} catch {
|
|
97
100
|
return denied("The complete confirmation facts are unsafe or too long. Narrow the action input.");
|
|
98
101
|
}
|
|
@@ -6,7 +6,7 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { proxyEnvironment } from "./environment.mjs";
|
|
8
8
|
import { runtimeToken } from "./runtime-token.mjs";
|
|
9
|
-
import { r as workflowValue } from "../../_chunks/workflow-serializable-
|
|
9
|
+
import { r as workflowValue } from "../../_chunks/workflow-serializable-DVQBWK8p.mjs";
|
|
10
10
|
function collapseConversationEvents(events) {
|
|
11
11
|
const latest = new Map();
|
|
12
12
|
for (const event of events) {
|
|
@@ -2,6 +2,7 @@ import type { ToolContext } from "eve/tools";
|
|
|
2
2
|
import { type Confirmation } from "./confirmations.js";
|
|
3
3
|
import { type Environment } from "./environment.js";
|
|
4
4
|
import { type RuntimeToken } from "./runtime-token.js";
|
|
5
|
+
import type { TelegramTexts } from "./telegram/texts.js";
|
|
5
6
|
export interface DeferredConfirmation {
|
|
6
7
|
readonly id: string;
|
|
7
8
|
readonly key: string;
|
|
@@ -18,12 +19,14 @@ export interface DeferredConfirmation {
|
|
|
18
19
|
readonly chatId: string;
|
|
19
20
|
readonly threadId: string;
|
|
20
21
|
readonly requester: string;
|
|
22
|
+
readonly locale?: string;
|
|
21
23
|
readonly requesterName?: string;
|
|
22
24
|
readonly messageId?: string;
|
|
23
25
|
readonly address?: string;
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
28
|
export type DeferredOptions = {
|
|
29
|
+
readonly texts?: () => TelegramTexts;
|
|
27
30
|
readonly environment?: Environment;
|
|
28
31
|
readonly token?: RuntimeToken;
|
|
29
32
|
readonly fetch?: typeof fetch;
|
|
@@ -60,6 +60,7 @@ async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
|
|
|
60
60
|
let saved = {};
|
|
61
61
|
const result = await actionApproval({
|
|
62
62
|
...tools,
|
|
63
|
+
...options.texts === void 0 ? {} : { texts: options.texts },
|
|
63
64
|
state: {
|
|
64
65
|
get: () => saved,
|
|
65
66
|
update: (update) => {
|
|
@@ -101,6 +102,7 @@ async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
|
|
|
101
102
|
chatId: attributes.chatId,
|
|
102
103
|
threadId: String(attributes.messageThreadId ?? ""),
|
|
103
104
|
requester: principal.subject,
|
|
105
|
+
locale: String(attributes.conversationLanguage ?? attributes.locale ?? "en"),
|
|
104
106
|
...humanText(attributes.memberName) === void 0 ? {} : { requesterName: humanText(attributes.memberName) }
|
|
105
107
|
}
|
|
106
108
|
}
|
|
@@ -154,7 +154,7 @@ function ontologyTools(options = {}) {
|
|
|
154
154
|
caller,
|
|
155
155
|
destinations
|
|
156
156
|
}),
|
|
157
|
-
action: typeof tool.title === "string" ? tool.title : "
|
|
157
|
+
action: typeof tool.title === "string" ? tool.title : typeof tool.description === "string" ? tool.description.split("\n\n")[0] : ""
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
let entities = [];
|
|
@@ -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 { telegramText, withTelegramTexts } from "./texts.mjs";
|
|
7
8
|
import { manifestOf } from "../../config.mjs";
|
|
8
9
|
import { appOrigin, channelsEnabled, proxyEnvironment, runtimeIdentityEnvironment, webhookSecret } from "../environment.mjs";
|
|
9
10
|
import { conversationLanguage, telegramPrincipal } from "./principal.mjs";
|
|
@@ -13,10 +14,10 @@ import { decisionRouter } from "../group-routing/router.mjs";
|
|
|
13
14
|
import { runtimeToken } from "../runtime-token.mjs";
|
|
14
15
|
import { conversations } from "../conversations.mjs";
|
|
15
16
|
import { archivedRoutingMessages } from "../group-routing/routing-context.mjs";
|
|
16
|
-
import { t as agentBuild } from "../../../_chunks/build-metadata-
|
|
17
|
+
import { t as agentBuild } from "../../../_chunks/build-metadata-BLeBanNg.mjs";
|
|
17
18
|
import { confirmationLocale } from "./confirmation-text.mjs";
|
|
18
19
|
import { telegramSendScope } from "./send-queue.mjs";
|
|
19
|
-
import { d as failureText, h as withDeliveryLocale, i as withReplacedText, m as safeTelegramFetch, n as currentInboundRequest, p as reportTelegramError, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-
|
|
20
|
+
import { d as failureText, h as withDeliveryLocale, i as withReplacedText, m as safeTelegramFetch, n as currentInboundRequest, o as currentLocale, p as reportTelegramError, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
|
|
20
21
|
import { attachmentLifecycle } from "./lifecycle.mjs";
|
|
21
22
|
import { scopedAddress, sessionPolicy } from "./sessions.mjs";
|
|
22
23
|
import { observedMessages } from "./observed.mjs";
|
|
@@ -120,7 +121,31 @@ function segmentstreamTelegram(options) {
|
|
|
120
121
|
identities: pairing,
|
|
121
122
|
observed,
|
|
122
123
|
chats,
|
|
123
|
-
verify: telegramWebhookVerifier(() => webhookSecret(environment))
|
|
124
|
+
verify: telegramWebhookVerifier(() => webhookSecret(environment)),
|
|
125
|
+
answerCallback: async (callbackQueryId, locale) => {
|
|
126
|
+
const text = telegramText("callback", "unsupported", locale);
|
|
127
|
+
const reply = await proxy().request({
|
|
128
|
+
api: "bot",
|
|
129
|
+
method: "POST",
|
|
130
|
+
path: "/answerCallbackQuery",
|
|
131
|
+
headers: [["content-type", "application/json"]],
|
|
132
|
+
body: new TextEncoder().encode(JSON.stringify({
|
|
133
|
+
callback_query_id: callbackQueryId,
|
|
134
|
+
...text === void 0 ? {} : { text }
|
|
135
|
+
}))
|
|
136
|
+
});
|
|
137
|
+
const body = new TextDecoder().decode(reply.body);
|
|
138
|
+
let answer;
|
|
139
|
+
try {
|
|
140
|
+
answer = JSON.parse(body);
|
|
141
|
+
} catch (cause) {
|
|
142
|
+
throw new Error(`Telegram callback acknowledgement was invalid (HTTP ${reply.status}): ${body}`, { cause });
|
|
143
|
+
}
|
|
144
|
+
if (reply.status < 200 || reply.status >= 300 || answer === null || typeof answer !== "object" || !("ok" in answer) || answer.ok !== true) throw new Error("Telegram callback acknowledgement was refused.", { cause: {
|
|
145
|
+
status: reply.status,
|
|
146
|
+
body
|
|
147
|
+
} });
|
|
148
|
+
}
|
|
124
149
|
});
|
|
125
150
|
let store = options.attachments;
|
|
126
151
|
function attachments() {
|
|
@@ -279,6 +304,8 @@ function segmentstreamTelegram(options) {
|
|
|
279
304
|
}
|
|
280
305
|
},
|
|
281
306
|
onCallbackQuery: async (context, query) => {
|
|
307
|
+
const inbound = currentInboundRequest();
|
|
308
|
+
if (inbound !== void 0) inbound.locale = query.from.languageCode;
|
|
282
309
|
try {
|
|
283
310
|
if (isDeferredCallback(query.data)) {
|
|
284
311
|
await handleDeferredCallback({
|
|
@@ -306,7 +333,7 @@ function segmentstreamTelegram(options) {
|
|
|
306
333
|
reportTelegramError("confirmation_callback_failed", error);
|
|
307
334
|
await context.telegram.answerCallbackQuery({
|
|
308
335
|
callbackQueryId: query.id,
|
|
309
|
-
text: "
|
|
336
|
+
...telegramText("callback", "error") === void 0 ? {} : { text: telegramText("callback", "error") }
|
|
310
337
|
});
|
|
311
338
|
}
|
|
312
339
|
},
|
|
@@ -404,7 +431,7 @@ function segmentstreamTelegram(options) {
|
|
|
404
431
|
const locale = confirmationLocale(principal ?? null, context.state.customerLocale ?? "en");
|
|
405
432
|
context.state.customerLocale = locale;
|
|
406
433
|
await withDeliveryLocale(locale, async () => {
|
|
407
|
-
await handler(event, context);
|
|
434
|
+
await withTelegramTexts(options.admission?.().texts ?? {}, () => handler(event, context), currentLocale);
|
|
408
435
|
}, context.state.messageThreadId === null ? void 0 : String(context.state.messageThreadId), typeof principal?.attributes.replyToMessageId === "string" ? principal.attributes.replyToMessageId : void 0, typeof principal?.attributes.chatId === "string" ? principal.attributes.chatId : void 0);
|
|
409
436
|
}]))
|
|
410
437
|
} },
|
|
@@ -482,7 +509,7 @@ function gatedRoute(input) {
|
|
|
482
509
|
};
|
|
483
510
|
inbound.waitUntil = waitUntil;
|
|
484
511
|
inbound.backgroundUntil = (task) => args.waitUntil(task);
|
|
485
|
-
return runInboundRequest(inbound, () => input.capture(request, async (routedRequest = request) => {
|
|
512
|
+
return withTelegramTexts(options.admission?.().texts ?? {}, () => runInboundRequest(inbound, () => input.capture(request, async (routedRequest = request) => {
|
|
486
513
|
const response = await route.handler(routedRequest, {
|
|
487
514
|
...args,
|
|
488
515
|
waitUntil,
|
|
@@ -501,7 +528,7 @@ function gatedRoute(input) {
|
|
|
501
528
|
headers: { "retry-after": "1" }
|
|
502
529
|
});
|
|
503
530
|
return response;
|
|
504
|
-
}));
|
|
531
|
+
})), currentLocale);
|
|
505
532
|
}
|
|
506
533
|
};
|
|
507
534
|
}
|
|
@@ -4,7 +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 { p as reportTelegramError } from "../../../_chunks/inbound-request-
|
|
7
|
+
import { p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
|
|
8
8
|
import { describableImage } from "./images.mjs";
|
|
9
9
|
import { MAXIMUM_ROUTING_PDF_CHARACTERS, extractRoutingPdf } from "./pdf-text.mjs";
|
|
10
10
|
import { gateway, generateText } from "ai";
|