@segmentstream/agent 0.12.2 → 0.14.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-CLprTpsn.mjs → build-metadata-BB2uSGsI.mjs} +1 -1
- package/dist/_chunks/{inbound-request-BrWspFw5.mjs → inbound-request-BXhiIph-.mjs} +21 -19
- package/dist/_chunks/principal-VFQWqe5S.mjs +126 -0
- package/dist/extension/_manifest.json +0 -1
- package/dist/extension/config.d.ts +23 -5
- package/dist/extension/config.mjs +167 -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/attachment-tools.mjs +1 -1
- package/dist/extension/lib/attachments.d.ts +2 -0
- package/dist/extension/lib/attachments.mjs +1 -0
- 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 +8 -5
- package/dist/extension/lib/conversation-runtime.mjs +1 -1
- package/dist/extension/lib/deferred-confirmations.d.ts +5 -0
- package/dist/extension/lib/deferred-confirmations.mjs +23 -10
- package/dist/extension/lib/ontology-connection.d.ts +1 -0
- package/dist/extension/lib/ontology-connection.mjs +18 -12
- package/dist/extension/lib/ontology-gateway.mjs +9 -2
- package/dist/extension/lib/ontology-metadata-read.mjs +1 -1
- package/dist/extension/lib/ontology-tools.d.ts +9 -2
- package/dist/extension/lib/ontology-tools.mjs +29 -5
- package/dist/extension/lib/runtime-envelope.d.ts +28 -0
- package/dist/extension/lib/runtime-envelope.mjs +8 -0
- package/dist/extension/lib/stored-files.mjs +1 -1
- package/dist/extension/lib/telegram/adapter.mjs +53 -11
- package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
- package/dist/extension/lib/telegram/attachments-send.mjs +15 -12
- package/dist/extension/lib/telegram/callbacks.d.ts +18 -0
- package/dist/extension/lib/telegram/callbacks.mjs +155 -0
- 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 +6 -5
- 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 +28 -23
- 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 +14 -13
- package/dist/extension/lib/telegram/files.mjs +2 -2
- 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 +25 -20
- package/dist/extension/lib/telegram/lifecycle.mjs +15 -3
- package/dist/extension/lib/telegram/media-policy.mjs +1 -1
- package/dist/extension/lib/telegram/principal.d.ts +1 -0
- package/dist/extension/lib/telegram/principal.mjs +1 -49
- package/dist/extension/lib/telegram/sessions.d.ts +3 -1
- package/dist/extension/lib/telegram/silent.mjs +3 -3
- 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 +38 -4
- package/dist/extension/lib/telegram/voice.mjs +1 -1
- package/dist/extension/lib/telegram/workspace-action.d.ts +21 -0
- package/dist/extension/lib/telegram/workspace-action.mjs +23 -0
- package/dist/extension/model.mjs +1 -1
- package/dist/extension/schedules/confirmations.mjs +1 -1
- package/dist/extension/tools/attachments_promote.mjs +8 -0
- package/dist/extension/tools/ontology.mjs +2 -2
- 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,9 @@ function telegramSettings(value, issues) {
|
|
|
72
78
|
"groups",
|
|
73
79
|
"linkPreviews",
|
|
74
80
|
"additionalOwnOrigins",
|
|
75
|
-
"attachmentLifecycle"
|
|
81
|
+
"attachmentLifecycle",
|
|
82
|
+
"menuButton",
|
|
83
|
+
"callbacks"
|
|
76
84
|
],
|
|
77
85
|
issues
|
|
78
86
|
});
|
|
@@ -115,6 +123,18 @@ function telegramSettings(value, issues) {
|
|
|
115
123
|
message: "must be an array of HTTP(S) origins without paths, credentials, queries or fragments",
|
|
116
124
|
path: [...path, "additionalOwnOrigins"]
|
|
117
125
|
});
|
|
126
|
+
const callbacks = workspaceHook(telegram.callbacks, [...path, "callbacks"], issues);
|
|
127
|
+
const menuButton = section({
|
|
128
|
+
value: telegram.menuButton,
|
|
129
|
+
path: [...path, "menuButton"],
|
|
130
|
+
allowed: ["text"],
|
|
131
|
+
issues
|
|
132
|
+
});
|
|
133
|
+
const menuText = menuButton === void 0 ? void 0 : localizedText(menuButton.text, [
|
|
134
|
+
...path,
|
|
135
|
+
"menuButton",
|
|
136
|
+
"text"
|
|
137
|
+
], issues, 64);
|
|
118
138
|
const lifecycle = section({
|
|
119
139
|
value: telegram.attachmentLifecycle,
|
|
120
140
|
path: [...path, "attachmentLifecycle"],
|
|
@@ -141,8 +161,10 @@ function telegramSettings(value, issues) {
|
|
|
141
161
|
connection,
|
|
142
162
|
policy,
|
|
143
163
|
...signalSettings === void 0 ? {} : { groups: signalSettings },
|
|
164
|
+
...callbacks === void 0 ? {} : { callbacks },
|
|
144
165
|
linkPreviews,
|
|
145
166
|
additionalOwnOrigins,
|
|
167
|
+
...menuText === void 0 ? {} : { menuButton: { text: menuText } },
|
|
146
168
|
...lifecycle === void 0 ? {} : { attachmentLifecycle: {
|
|
147
169
|
entity: String(lifecycle.entity),
|
|
148
170
|
action: String(lifecycle.action),
|
|
@@ -150,6 +172,32 @@ function telegramSettings(value, issues) {
|
|
|
150
172
|
} }
|
|
151
173
|
} : null;
|
|
152
174
|
}
|
|
175
|
+
function workspaceHook(value, path, issues) {
|
|
176
|
+
const configured = section({
|
|
177
|
+
value,
|
|
178
|
+
path,
|
|
179
|
+
allowed: [
|
|
180
|
+
"entity",
|
|
181
|
+
"action",
|
|
182
|
+
"contextVersion"
|
|
183
|
+
],
|
|
184
|
+
issues
|
|
185
|
+
});
|
|
186
|
+
if (configured === void 0) return;
|
|
187
|
+
for (const key of ["entity", "action"]) if (typeof configured[key] !== "string" || !/^(?:[a-z][a-zA-Z0-9]*|[a-z][a-z0-9]*(?:_[a-z0-9]+)*)$/.test(String(configured[key]))) issues.push({
|
|
188
|
+
message: "must name an ontology entity or action",
|
|
189
|
+
path: [...path, key]
|
|
190
|
+
});
|
|
191
|
+
if (configured.contextVersion !== 2) issues.push({
|
|
192
|
+
message: "must be 2",
|
|
193
|
+
path: [...path, "contextVersion"]
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
entity: String(configured.entity),
|
|
197
|
+
action: String(configured.action),
|
|
198
|
+
contextVersion: 2
|
|
199
|
+
};
|
|
200
|
+
}
|
|
153
201
|
function modelId(input) {
|
|
154
202
|
if (input.value === void 0) return input.fallback;
|
|
155
203
|
if (typeof input.value !== "string" || input.value === "" || input.value !== input.value.trim()) {
|
|
@@ -265,7 +313,7 @@ function sessionSettings(value, issues) {
|
|
|
265
313
|
idleResetHours: typeof idleResetHours === "number" && Number.isFinite(idleResetHours) && idleResetHours > 0 ? idleResetHours : false
|
|
266
314
|
};
|
|
267
315
|
}
|
|
268
|
-
function localizedText(value, path, issues) {
|
|
316
|
+
function localizedText(value, path, issues, maximum = 4e3, safe = true) {
|
|
269
317
|
if (!isRecord(value) || Object.keys(value).length === 0) {
|
|
270
318
|
issues.push({
|
|
271
319
|
message: "must be a non-empty locale-to-text object",
|
|
@@ -282,14 +330,14 @@ function localizedText(value, path, issues) {
|
|
|
282
330
|
path: [...path, locale]
|
|
283
331
|
});
|
|
284
332
|
}
|
|
285
|
-
if (typeof text !== "string" || text.trim() === "" || text.length >
|
|
286
|
-
message:
|
|
333
|
+
if (typeof text !== "string" || text.trim() === "" || text.length > maximum || safe && typeof text === "string" && isTechnicalText(text)) issues.push({
|
|
334
|
+
message: `must be ${safe ? "safe " : ""}non-empty text of at most ${maximum} characters`,
|
|
287
335
|
path: [...path, locale]
|
|
288
336
|
});
|
|
289
337
|
}
|
|
290
338
|
return value;
|
|
291
339
|
}
|
|
292
|
-
function firstContactSettings(value, issues) {
|
|
340
|
+
function firstContactSettings(value, issues, safe = true) {
|
|
293
341
|
const path = ["firstContact"];
|
|
294
342
|
const settings = section({
|
|
295
343
|
value,
|
|
@@ -303,7 +351,7 @@ function firstContactSettings(value, issues) {
|
|
|
303
351
|
message: "must be non-empty text of at most 200 characters without surrounding whitespace",
|
|
304
352
|
path: [...path, "version"]
|
|
305
353
|
});
|
|
306
|
-
const notice = localizedText(settings.notice, [...path, "notice"], issues);
|
|
354
|
+
const notice = localizedText(settings.notice, [...path, "notice"], issues, 4e3, safe);
|
|
307
355
|
return {
|
|
308
356
|
version: typeof version === "string" ? version : "",
|
|
309
357
|
notice
|
|
@@ -351,7 +399,7 @@ function admissionLimits(value, issues) {
|
|
|
351
399
|
workspaceTurnsPerDay: limit(limits?.workspaceTurnsPerDay, DEFAULT_ADMISSION_LIMITS.workspaceTurnsPerDay, [...path, "workspaceTurnsPerDay"])
|
|
352
400
|
};
|
|
353
401
|
}
|
|
354
|
-
function admissionReplies(value, issues) {
|
|
402
|
+
function admissionReplies(value, issues, safe = true) {
|
|
355
403
|
const replies = section({
|
|
356
404
|
value,
|
|
357
405
|
path: ["replies"],
|
|
@@ -359,10 +407,90 @@ function admissionReplies(value, issues) {
|
|
|
359
407
|
issues
|
|
360
408
|
});
|
|
361
409
|
const configured = {};
|
|
362
|
-
for (const key of ADMISSION_REPLY_KEYS) if (replies?.[key] !== void 0) configured[key] = localizedText(replies[key], ["replies", key], issues);
|
|
410
|
+
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
411
|
return configured;
|
|
364
412
|
}
|
|
365
|
-
function
|
|
413
|
+
function telegramTexts(value, issues) {
|
|
414
|
+
const root = section({
|
|
415
|
+
value,
|
|
416
|
+
path: ["texts"],
|
|
417
|
+
allowed: Object.keys(TELEGRAM_TEXT_KEYS),
|
|
418
|
+
issues
|
|
419
|
+
});
|
|
420
|
+
const output = {};
|
|
421
|
+
for (const [group, keys] of Object.entries(TELEGRAM_TEXT_KEYS)) {
|
|
422
|
+
const sectionValue = section({
|
|
423
|
+
value: root?.[group],
|
|
424
|
+
path: ["texts", group],
|
|
425
|
+
allowed: keys,
|
|
426
|
+
issues
|
|
427
|
+
});
|
|
428
|
+
if (sectionValue === void 0) continue;
|
|
429
|
+
output[group] = {};
|
|
430
|
+
for (const key of keys) if (sectionValue[key] !== void 0) {
|
|
431
|
+
const maximum = group === "confirmation" ? key === "question" ? 300 : 24 : group === "callback" ? 200 : group === "authorization" && key === "button" ? 24 : 4e3;
|
|
432
|
+
output[group][key] = localizedText(sectionValue[key], [
|
|
433
|
+
"texts",
|
|
434
|
+
group,
|
|
435
|
+
key
|
|
436
|
+
], issues, maximum);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
const confirmation = output.confirmation;
|
|
440
|
+
if (confirmation?.confirm !== void 0 && confirmation.cancel !== void 0) {
|
|
441
|
+
const locales = new Set([
|
|
442
|
+
"en",
|
|
443
|
+
...Object.keys(confirmation.confirm),
|
|
444
|
+
...Object.keys(confirmation.cancel)
|
|
445
|
+
]);
|
|
446
|
+
for (const locale of locales) {
|
|
447
|
+
const confirm = localizedText$1(confirmation.confirm, locale);
|
|
448
|
+
const cancel = localizedText$1(confirmation.cancel, locale);
|
|
449
|
+
if (typeof confirm === "string" && typeof cancel === "string" && confirm.trim() === cancel.trim()) issues.push({
|
|
450
|
+
message: "confirm and cancel must have distinct effective localized labels",
|
|
451
|
+
path: [
|
|
452
|
+
"texts",
|
|
453
|
+
"confirmation",
|
|
454
|
+
"cancel",
|
|
455
|
+
locale
|
|
456
|
+
]
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const authorization = output.authorization;
|
|
461
|
+
if (authorization?.url !== void 0) for (const [locale, value] of Object.entries(authorization.url)) try {
|
|
462
|
+
const url = new URL(value);
|
|
463
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) throw new Error("Invalid authorization URL");
|
|
464
|
+
} catch {
|
|
465
|
+
issues.push({
|
|
466
|
+
message: "must be an HTTP(S) URL without credentials",
|
|
467
|
+
path: [
|
|
468
|
+
"texts",
|
|
469
|
+
"authorization",
|
|
470
|
+
"url",
|
|
471
|
+
locale
|
|
472
|
+
]
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
if ((authorization?.url !== void 0 || authorization?.button !== void 0) && authorization?.prompt === void 0) issues.push({
|
|
476
|
+
message: "is required when an authorization button is configured",
|
|
477
|
+
path: [
|
|
478
|
+
"texts",
|
|
479
|
+
"authorization",
|
|
480
|
+
"prompt"
|
|
481
|
+
]
|
|
482
|
+
});
|
|
483
|
+
if (authorization?.url === void 0 !== (authorization?.button === void 0)) issues.push({
|
|
484
|
+
message: "url and button must be supplied together",
|
|
485
|
+
path: ["texts", "authorization"]
|
|
486
|
+
});
|
|
487
|
+
return output;
|
|
488
|
+
}
|
|
489
|
+
function isLegacyAgentArchive(version) {
|
|
490
|
+
return /^0\.(?:[0-9]|1[0-2])\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version ?? "");
|
|
491
|
+
}
|
|
492
|
+
function validateConfig(input, options = {}) {
|
|
493
|
+
const legacyArchive = isLegacyAgentArchive(options.archiveSdkVersion);
|
|
366
494
|
const issues = [];
|
|
367
495
|
const root = section({
|
|
368
496
|
value: input ?? {},
|
|
@@ -376,7 +504,8 @@ function validateConfig(input) {
|
|
|
376
504
|
"confirmations",
|
|
377
505
|
"firstContact",
|
|
378
506
|
"limits",
|
|
379
|
-
"replies"
|
|
507
|
+
"replies",
|
|
508
|
+
"texts"
|
|
380
509
|
],
|
|
381
510
|
issues
|
|
382
511
|
});
|
|
@@ -410,8 +539,8 @@ function validateConfig(input) {
|
|
|
410
539
|
allowed: ["mode"],
|
|
411
540
|
issues
|
|
412
541
|
})?.mode ?? "deferred";
|
|
413
|
-
if (mode !== "deferred" && mode
|
|
414
|
-
message: "must be \"deferred\"
|
|
542
|
+
if (mode !== "deferred" && !(legacyArchive && mode === "held")) issues.push({
|
|
543
|
+
message: "must be \"deferred\"; Telegram Eve approval buttons are unsupported",
|
|
415
544
|
path: ["confirmations", "mode"]
|
|
416
545
|
});
|
|
417
546
|
const telegram = telegramSettings(channels?.telegram, issues);
|
|
@@ -502,9 +631,28 @@ function validateConfig(input) {
|
|
|
502
631
|
});
|
|
503
632
|
const connection = ontology?.connection ?? true;
|
|
504
633
|
const sessions = sessionSettings(root?.sessions, issues);
|
|
505
|
-
const firstContact = firstContactSettings(root?.firstContact, issues);
|
|
634
|
+
const firstContact = firstContactSettings(root?.firstContact, issues, !legacyArchive);
|
|
506
635
|
const limits = admissionLimits(root?.limits, issues);
|
|
507
|
-
const replies = admissionReplies(root?.replies, issues);
|
|
636
|
+
const replies = admissionReplies(root?.replies, issues, !legacyArchive);
|
|
637
|
+
const texts = telegramTexts(root?.texts, issues);
|
|
638
|
+
if (!legacyArchive && replies.groupPairingButton !== void 0 && replies.groupPairingRequired === void 0) issues.push({
|
|
639
|
+
message: "is required when groupPairingButton is configured",
|
|
640
|
+
path: ["replies", "groupPairingRequired"]
|
|
641
|
+
});
|
|
642
|
+
if (telegram !== null && !legacyArchive) {
|
|
643
|
+
for (const key of ["pairingRequired", "pairingButton"]) if (replies[key] === void 0) issues.push({
|
|
644
|
+
message: "is required for Telegram",
|
|
645
|
+
path: ["replies", key]
|
|
646
|
+
});
|
|
647
|
+
for (const key of TELEGRAM_TEXT_KEYS.confirmation) if (texts.confirmation?.[key] === void 0) issues.push({
|
|
648
|
+
message: "is required for Telegram confirmations",
|
|
649
|
+
path: [
|
|
650
|
+
"texts",
|
|
651
|
+
"confirmation",
|
|
652
|
+
key
|
|
653
|
+
]
|
|
654
|
+
});
|
|
655
|
+
}
|
|
508
656
|
if (typeof connection !== "boolean") issues.push({
|
|
509
657
|
message: "must be true or false",
|
|
510
658
|
path: ["ontology", "connection"]
|
|
@@ -524,17 +672,18 @@ function validateConfig(input) {
|
|
|
524
672
|
attachments
|
|
525
673
|
},
|
|
526
674
|
ontology: { connection: connection === true },
|
|
527
|
-
confirmations: { mode:
|
|
675
|
+
confirmations: { mode: "deferred" },
|
|
528
676
|
sessions,
|
|
529
677
|
firstContact,
|
|
530
678
|
limits,
|
|
531
|
-
replies
|
|
679
|
+
replies,
|
|
680
|
+
texts
|
|
532
681
|
} };
|
|
533
682
|
}
|
|
534
683
|
const configSchema = { "~standard": {
|
|
535
684
|
version: 1,
|
|
536
685
|
vendor: "segmentstream",
|
|
537
|
-
validate: validateConfig,
|
|
686
|
+
validate: (input) => validateConfig(input),
|
|
538
687
|
types: void 0
|
|
539
688
|
} };
|
|
540
689
|
function manifestOf(config) {
|
|
@@ -542,4 +691,4 @@ function manifestOf(config) {
|
|
|
542
691
|
if (validation.issues !== void 0) throw new SegmentStreamAgentConfigError(validation.issues);
|
|
543
692
|
return validation.value;
|
|
544
693
|
}
|
|
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 };
|
|
694
|
+
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 "../../_chunks/principal-VFQWqe5S.mjs";
|
|
9
|
+
import { confirmationLocale } from "../lib/telegram/confirmation-text.mjs";
|
|
10
|
+
import segmentstream from "../extension.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
|
|
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { appOrigin } from "./environment.mjs";
|
|
8
|
-
import { memberIdOf } from "
|
|
8
|
+
import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
|
|
9
9
|
import { runtimeToken } from "./runtime-token.mjs";
|
|
10
10
|
import { agentAttachments } from "./attachments.mjs";
|
|
11
11
|
import { telegramConversation } from "./telegram/files.mjs";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RuntimeEnvelope } from "./runtime-envelope.js";
|
|
1
2
|
import type { RuntimeToken } from "./runtime-token.js";
|
|
2
3
|
/**
|
|
3
4
|
* The ontology service's attachment routes (`docs/agent.md`, "Attachments"). A file a member sends
|
|
@@ -35,6 +36,7 @@ export interface Attachment {
|
|
|
35
36
|
readonly promotion: unknown;
|
|
36
37
|
}
|
|
37
38
|
export interface PromotionRequest {
|
|
39
|
+
readonly runtime?: RuntimeEnvelope;
|
|
38
40
|
readonly entity: string;
|
|
39
41
|
readonly action: string;
|
|
40
42
|
readonly input?: Readonly<Record<string, unknown>>;
|
|
@@ -192,6 +192,7 @@ function agentAttachments(input) {
|
|
|
192
192
|
const answer = await call(owner, `/${encodeURIComponent(id)}/promote`, "promotion", {
|
|
193
193
|
entity: request.entity,
|
|
194
194
|
action: request.action,
|
|
195
|
+
...request.runtime === void 0 ? {} : { _meta: { _segmentstream: request.runtime } },
|
|
195
196
|
input: request.input ?? {},
|
|
196
197
|
...request.field === void 0 ? {} : { field: request.field },
|
|
197
198
|
...request.recordId === void 0 ? {} : { record_id: request.recordId }
|
|
@@ -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-BB2uSGsI.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 {
|
|
8
|
-
import {
|
|
7
|
+
import { withTelegramTexts } from "./telegram/texts.mjs";
|
|
8
|
+
import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.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
|
}
|
|
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { ENDS_CONVERSATION_INSTRUCTIONS } from "./group-routing/conversation-prompt.mjs";
|
|
8
|
-
import { memberIdOf } from "
|
|
8
|
+
import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
|
|
9
9
|
import { n as contentText, t as CONTENT_CAPS } from "../../_chunks/content-CvFsrmSD.mjs";
|
|
10
10
|
import { conversationEvent, conversations, summarizeArguments } from "./conversations.mjs";
|
|
11
11
|
import { parseAddress } from "./telegram/sessions.mjs";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type RuntimeEnvelope } from "./runtime-envelope.js";
|
|
1
2
|
import type { ToolContext } from "eve/tools";
|
|
2
3
|
import { type Confirmation } from "./confirmations.js";
|
|
3
4
|
import { type Environment } from "./environment.js";
|
|
4
5
|
import { type RuntimeToken } from "./runtime-token.js";
|
|
6
|
+
import type { TelegramTexts } from "./telegram/texts.js";
|
|
5
7
|
export interface DeferredConfirmation {
|
|
6
8
|
readonly id: string;
|
|
7
9
|
readonly key: string;
|
|
@@ -10,6 +12,7 @@ export interface DeferredConfirmation {
|
|
|
10
12
|
readonly expiresAt: number;
|
|
11
13
|
readonly status: "pending" | "approved" | "cancelled" | "expired" | "done" | "failed";
|
|
12
14
|
readonly data: {
|
|
15
|
+
readonly runtimeSource?: RuntimeEnvelope["source"];
|
|
13
16
|
readonly action: string;
|
|
14
17
|
readonly input: Readonly<Record<string, unknown>>;
|
|
15
18
|
readonly confirmation: Confirmation;
|
|
@@ -18,12 +21,14 @@ export interface DeferredConfirmation {
|
|
|
18
21
|
readonly chatId: string;
|
|
19
22
|
readonly threadId: string;
|
|
20
23
|
readonly requester: string;
|
|
24
|
+
readonly locale?: string;
|
|
21
25
|
readonly requesterName?: string;
|
|
22
26
|
readonly messageId?: string;
|
|
23
27
|
readonly address?: string;
|
|
24
28
|
};
|
|
25
29
|
}
|
|
26
30
|
export type DeferredOptions = {
|
|
31
|
+
readonly texts?: () => TelegramTexts;
|
|
27
32
|
readonly environment?: Environment;
|
|
28
33
|
readonly token?: RuntimeToken;
|
|
29
34
|
readonly fetch?: typeof fetch;
|
|
@@ -5,10 +5,10 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { appOrigin } from "./environment.mjs";
|
|
8
|
-
import { memberIdOf } from "
|
|
9
|
-
import { runtimeToken } from "./runtime-token.mjs";
|
|
8
|
+
import { i as memberIdOf, l as principalRuntimeSource, u as runtimeEnvelope } from "../../_chunks/principal-VFQWqe5S.mjs";
|
|
10
9
|
import { redactDiagnostic } from "./diagnostics.mjs";
|
|
11
10
|
import { humanText, object } from "./confirmation-description.mjs";
|
|
11
|
+
import { runtimeToken } from "./runtime-token.mjs";
|
|
12
12
|
import { chatPostDigest, chatPostOperationId, isChatPost } from "./chat-post-confirmation.mjs";
|
|
13
13
|
import { actionApproval, inputHash } from "./confirmations.mjs";
|
|
14
14
|
import { ontologyTools } from "./ontology-tools.mjs";
|
|
@@ -37,7 +37,7 @@ function deferredConfirmations(options = {}) {
|
|
|
37
37
|
}
|
|
38
38
|
async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
|
|
39
39
|
if (memberIdOf(ctx.session.auth.current) !== memberId) throw new Error("The ontology tool belongs to another member.");
|
|
40
|
-
|
|
40
|
+
input = Object.fromEntries(Object.entries(input).filter(([key]) => key !== "_segmentstream"));
|
|
41
41
|
const principal = ctx.session.auth.current;
|
|
42
42
|
const attributes = principal?.attributes;
|
|
43
43
|
const id = chatPostOperationId(ctx.session.id, ctx.callId);
|
|
@@ -56,10 +56,19 @@ async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
|
|
|
56
56
|
};
|
|
57
57
|
};
|
|
58
58
|
if (existing !== null) return boundResult(existing);
|
|
59
|
-
const tools = ontologyTools(
|
|
59
|
+
const tools = ontologyTools({
|
|
60
|
+
...options,
|
|
61
|
+
principal: ctx.session.auth.current,
|
|
62
|
+
envelope: runtimeEnvelope({
|
|
63
|
+
principal: ctx.session.auth.current,
|
|
64
|
+
sessionId: ctx.session.id,
|
|
65
|
+
callId: ctx.callId
|
|
66
|
+
})
|
|
67
|
+
});
|
|
60
68
|
let saved = {};
|
|
61
69
|
const result = await actionApproval({
|
|
62
70
|
...tools,
|
|
71
|
+
...options.texts === void 0 ? {} : { texts: options.texts },
|
|
63
72
|
state: {
|
|
64
73
|
get: () => saved,
|
|
65
74
|
update: (update) => {
|
|
@@ -95,12 +104,14 @@ async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
|
|
|
95
104
|
data: {
|
|
96
105
|
action,
|
|
97
106
|
input,
|
|
107
|
+
...principalRuntimeSource(principal) === void 0 ? {} : { runtimeSource: principalRuntimeSource(principal) },
|
|
98
108
|
confirmation,
|
|
99
109
|
sessionId: ctx.session.id,
|
|
100
110
|
callId: ctx.callId,
|
|
101
111
|
chatId: attributes.chatId,
|
|
102
112
|
threadId: String(attributes.messageThreadId ?? ""),
|
|
103
113
|
requester: principal.subject,
|
|
114
|
+
locale: String(attributes.conversationLanguage ?? attributes.locale ?? "en"),
|
|
104
115
|
...humanText(attributes.memberName) === void 0 ? {} : { requesterName: humanText(attributes.memberName) }
|
|
105
116
|
}
|
|
106
117
|
}
|
|
@@ -123,11 +134,13 @@ async function runDeferredAction(record, options) {
|
|
|
123
134
|
session_id: record.data.sessionId,
|
|
124
135
|
call_id: record.data.callId,
|
|
125
136
|
operation_id: record.id,
|
|
137
|
+
...record.data.runtimeSource === void 0 ? {} : { source: record.data.runtimeSource },
|
|
126
138
|
...preview ? {
|
|
127
139
|
source: {
|
|
128
140
|
provider: "telegram",
|
|
129
141
|
chat_id: record.data.chatId,
|
|
130
|
-
thread_id: record.data.threadId
|
|
142
|
+
thread_id: record.data.threadId,
|
|
143
|
+
...record.data.runtimeSource
|
|
131
144
|
},
|
|
132
145
|
expected: {
|
|
133
146
|
chat_id: preview.chatId,
|
|
@@ -135,12 +148,12 @@ async function runDeferredAction(record, options) {
|
|
|
135
148
|
}
|
|
136
149
|
} : {}
|
|
137
150
|
};
|
|
138
|
-
const result = await
|
|
151
|
+
const result = await ontologyTools({
|
|
152
|
+
...options,
|
|
153
|
+
envelope
|
|
154
|
+
}).rpc(record.memberId, "tools/call", {
|
|
139
155
|
name: record.data.action.split("__").at(-1),
|
|
140
|
-
arguments:
|
|
141
|
-
...record.data.input,
|
|
142
|
-
_segmentstream: envelope
|
|
143
|
-
}
|
|
156
|
+
arguments: record.data.input
|
|
144
157
|
});
|
|
145
158
|
const output = result.structuredContent;
|
|
146
159
|
if (result.isError === true || (output?.validation)?.ok === false || preview !== void 0 && output?.status !== "sent") throw new Error("The confirmed action did not complete; its outcome may be uncertain.", { cause: result });
|