@segmentstream/agent 0.8.24 → 0.9.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.
Files changed (64) hide show
  1. package/dist/_chunks/{build-metadata-BrXE_Dxu.mjs → build-metadata-DuHeGf1m.mjs} +1 -1
  2. package/dist/_chunks/content-CvFsrmSD.mjs +102 -0
  3. package/dist/extension/channels/telegram.mjs +1 -0
  4. package/dist/extension/config.d.ts +16 -2
  5. package/dist/extension/config.mjs +92 -3
  6. package/dist/extension/extension.d.ts +7 -0
  7. package/dist/extension/extension.mjs +8 -1
  8. package/dist/extension/hooks/conversations.mjs +1 -1
  9. package/dist/extension/instructions/conversations.mjs +1 -1
  10. package/dist/extension/lib/build-metadata.mjs +1 -1
  11. package/dist/extension/lib/conversation-runtime.mjs +132 -1
  12. package/dist/extension/lib/deferred-confirmations.mjs +1 -1
  13. package/dist/extension/lib/group-routing/engagement.d.ts +18 -0
  14. package/dist/extension/lib/group-routing/engagement.mjs +65 -0
  15. package/dist/extension/lib/group-routing/health.d.ts +11 -0
  16. package/dist/extension/lib/group-routing/health.mjs +36 -0
  17. package/dist/extension/lib/group-routing/observed.d.ts +100 -0
  18. package/dist/extension/lib/group-routing/observed.mjs +103 -0
  19. package/dist/extension/lib/group-routing/policy.d.ts +63 -0
  20. package/dist/extension/lib/group-routing/policy.mjs +162 -0
  21. package/dist/extension/lib/group-routing/record.d.ts +3 -0
  22. package/dist/extension/lib/group-routing/record.mjs +35 -0
  23. package/dist/extension/lib/group-routing/replay.d.ts +18 -0
  24. package/dist/extension/lib/group-routing/replay.mjs +70 -0
  25. package/dist/extension/lib/group-routing/router.d.ts +109 -0
  26. package/dist/extension/lib/group-routing/router.mjs +383 -0
  27. package/dist/extension/lib/group-routing/routing-context.d.ts +4 -0
  28. package/dist/extension/lib/group-routing/routing-context.mjs +96 -0
  29. package/dist/extension/lib/group-routing/settings.d.ts +14 -0
  30. package/dist/extension/lib/group-routing/settings.mjs +58 -0
  31. package/dist/extension/lib/group-routing/signals.d.ts +110 -0
  32. package/dist/extension/lib/group-routing/signals.mjs +47 -0
  33. package/dist/extension/lib/identities.d.ts +3 -0
  34. package/dist/extension/lib/identities.mjs +13 -1
  35. package/dist/extension/lib/ontology-connection.mjs +1 -1
  36. package/dist/extension/lib/ontology-tools.mjs +1 -1
  37. package/dist/extension/lib/telegram/adapter.d.ts +2 -0
  38. package/dist/extension/lib/telegram/adapter.mjs +17 -5
  39. package/dist/extension/lib/telegram/attachments-send.mjs +1 -1
  40. package/dist/extension/lib/telegram/audience.d.ts +3 -26
  41. package/dist/extension/lib/telegram/audience.mjs +1 -5
  42. package/dist/extension/lib/telegram/confirmation-expiry.mjs +2 -2
  43. package/dist/extension/lib/telegram/confirmations.mjs +2 -2
  44. package/dist/extension/lib/telegram/conversations.d.ts +1 -1
  45. package/dist/extension/lib/telegram/conversations.mjs +17 -4
  46. package/dist/extension/lib/telegram/deferred-confirmations.mjs +2 -2
  47. package/dist/extension/lib/telegram/health.d.ts +1 -0
  48. package/dist/extension/lib/telegram/health.mjs +2 -1
  49. package/dist/extension/lib/telegram/inbound.d.ts +7 -0
  50. package/dist/extension/lib/telegram/inbound.mjs +47 -15
  51. package/dist/extension/lib/telegram/lifecycle.mjs +1 -1
  52. package/dist/extension/lib/telegram/observed.d.ts +5 -98
  53. package/dist/extension/lib/telegram/observed.mjs +11 -92
  54. package/dist/extension/lib/telegram/router.d.ts +4 -114
  55. package/dist/extension/lib/telegram/router.mjs +4 -250
  56. package/dist/extension/lib/telegram/routing-context.d.ts +3 -3
  57. package/dist/extension/lib/telegram/routing-context.mjs +7 -86
  58. package/dist/extension/lib/telegram/signals.d.ts +5 -0
  59. package/dist/extension/lib/telegram/signals.mjs +60 -0
  60. package/dist/extension/lib/telegram/silent.mjs +1 -1
  61. package/dist/extension/tools/attachments_promote.mjs +1 -1
  62. package/dist/extension/tools/attachments_send.mjs +1 -1
  63. package/package.json +2 -2
  64. package/dist/_chunks/conversation-runtime-ovs8IhXJ.mjs +0 -212
@@ -1,212 +0,0 @@
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 { memberIdOf } from "../extension/lib/telegram/principal.mjs";
8
- import { conversationEvent, conversations, summarizeArguments } from "../extension/lib/conversations.mjs";
9
- import { parseAddress } from "../extension/lib/telegram/sessions.mjs";
10
- import { completionKind } from "../extension/lib/telegram/silent.mjs";
11
- const CONTENT_CAPS = {
12
- args: 16384,
13
- result: 32768,
14
- error: 4096
15
- };
16
- const sensitive = /token|password|passwd|secret|authorization|cookie|credential|api.?key|private.?key|session|iban|card|cvv|ssn|email|phone|address|birth|document.?text|raw.?content|body|bytes|base64/i;
17
- const encoder = new TextEncoder();
18
- function luhn(value) {
19
- const digits = value.replace(/\D/g, "");
20
- if (digits.length < 13 || digits.length > 19) return false;
21
- let sum = 0;
22
- let double = false;
23
- for (let i = digits.length - 1; i >= 0; i--) {
24
- let n = Number(digits[i]);
25
- if (double && (n *= 2) > 9) n -= 9;
26
- sum += n;
27
- double = !double;
28
- }
29
- return sum % 10 === 0;
30
- }
31
- function redactText(value) {
32
- return value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "[binary data]").replace(/-----BEGIN [^-\r\n]+-----[\s\S]*?(?:-----END [^-\r\n]+-----|$)/g, "[redacted PEM]").replace(/data:[^\s"']+/gi, "[binary data]").replace(/\b(?:Bearer|Basic)\s+[A-Za-z0-9+/_=.:~\-]+/gi, "[redacted authorization]").replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g, "[redacted JWT]").replace(/\b(?:ssw_|sscli_|sk[-_]|rk[-_])[A-Za-z0-9._~\-]+/gi, "[redacted key]").replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+@/gi, "$1[redacted]@").replace(/([?&](?:[^=&#\s]*(?:token|password|secret|key|signature|credential|session|auth|cookie)[^=&#\s]*|sig)=)[^&#\s"']*/gi, "$1[redacted]").replace(/((?:["']?)(?:[\w-]*(?:token|password|passwd|secret|authorization|cookie|credential|api.?key|private.?key|session|iban|card|cvv|ssn)[\w-]*)(?:["']?)\s*[:=]\s*)(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[^\s,;})]+)/gi, "$1[redacted]").replace(/\b[A-Z]{2}\d{2}(?:[ -]?[A-Z0-9]){11,30}\b/gi, "[redacted IBAN]").replace(/\b\d(?:[ -]?\d){12,18}\b/g, (candidate) => luhn(candidate) ? "[redacted card]" : candidate).replace(/[A-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[A-Z0-9](?:[A-Z0-9.-]*[A-Z0-9])?\.[A-Z]{2,}/gi, "[email]").replace(/\b\d{3}-\d{2}-\d{4}\b/g, "[redacted SSN]").replace(/\b[A-Za-z0-9+/]{128,}={0,2}/g, "[binary data]");
33
- }
34
- const documentField = /^(?:text|content|body|csv|tsv|file[_-]?body|email[_-]?body)$/i;
35
- const omittedDocument = "[omitted: unstructured document content]";
36
- function redactContent(value) {
37
- const seen = new WeakSet();
38
- let nodes = 0;
39
- const visit = (item, depth, field) => {
40
- if (++nodes > 5e3 || depth > 12) return "[omitted: content complexity]";
41
- if (typeof item === "string") {
42
- try {
43
- const embedded = JSON.parse(item);
44
- if (embedded !== null && typeof embedded === "object") return JSON.stringify(visit(embedded, depth + 1, field));
45
- } catch {}
46
- if (documentField.test(field ?? "")) return omittedDocument;
47
- return redactText(item);
48
- }
49
- if (typeof item === "bigint") return item.toString();
50
- if (item === null || typeof item !== "object") return item;
51
- if (ArrayBuffer.isView(item) || item instanceof ArrayBuffer) return "[binary data]";
52
- if (seen.has(item)) return "[omitted: circular]";
53
- seen.add(item);
54
- if (Array.isArray(item)) {
55
- const entries = item.slice(0, 200).map((entry) => visit(entry, depth + 1, field));
56
- if (item.length > 200) entries.push("[omitted: array entries]");
57
- return entries;
58
- }
59
- const entries = Object.entries(item);
60
- return Object.fromEntries([...entries.slice(0, 200).map(([key, entry]) => [redactText(key), sensitive.test(key) && !documentField.test(key) ? "[redacted]" : visit(entry, depth + 1, key)]), ...entries.length > 200 ? [["_omitted", "[omitted: object entries]"]] : []]);
61
- };
62
- return visit(value, 0);
63
- }
64
- function contentText(value, cap) {
65
- if (value == null) return null;
66
- let parsed = value;
67
- if (typeof value === "string") try {
68
- parsed = JSON.parse(value);
69
- } catch {}
70
- const redacted = redactContent(parsed);
71
- const text = typeof redacted === "string" ? redacted : JSON.stringify(redacted) ?? "[omitted]";
72
- if (encoder.encode(text).length <= cap) return text;
73
- let preview = text;
74
- while (true) {
75
- const result = JSON.stringify({
76
- truncated: true,
77
- preview
78
- });
79
- const bytes = encoder.encode(result).length;
80
- if (bytes <= cap) return result;
81
- const available = Math.max(0, encoder.encode(preview).length - (bytes - cap) - 4);
82
- preview = new TextDecoder().decode(encoder.encode(preview).slice(0, available), { stream: true });
83
- }
84
- }
85
- function conversationCoordinates(context) {
86
- const principal = context.session.auth.current;
87
- const telegram = principal?.authenticator === "segmentstream-telegram" || context.channel.kind?.includes("telegram");
88
- const address = context.channel.continuationToken;
89
- const attributes = principal?.attributes;
90
- const fields = address?.split(":");
91
- const localAddress = telegram && fields?.length === 4 ? fields.slice(1).join(":") : address;
92
- const parsed = telegram && localAddress !== void 0 && /^-?\d+:\d*:\d*$/u.test(localAddress) ? parseAddress(localAddress) : void 0;
93
- const attributeChatId = typeof attributes?.chatId === "string" && (!telegram || /^-?\d+$/u.test(attributes.chatId)) ? attributes.chatId : void 0;
94
- const chatId = telegram ? parsed?.chatId ?? attributeChatId : attributeChatId !== void 0 ? attributeChatId : address;
95
- if (!chatId) return;
96
- const memberId = memberIdOf(principal);
97
- const chatType = attributes?.chatType;
98
- return {
99
- provider: telegram ? "telegram" : context.channel.kind ?? "eve",
100
- chatId,
101
- chatType: chatType === "group" || chatType === "supergroup" || chatType === void 0 && telegram && chatId.startsWith("-") ? "group" : chatType === "channel" ? "channel" : "private",
102
- threadId: !telegram ? null : parsed !== void 0 ? parsed.messageThreadId || null : typeof attributes?.messageThreadId === "string" ? attributes.messageThreadId : null,
103
- participantIds: memberId === void 0 ? [] : [memberId],
104
- senderId: principal?.subject ?? null
105
- };
106
- }
107
- function conversationRecorder(archive = conversations()) {
108
- return async (event, context) => {
109
- const coordinates = conversationCoordinates(context);
110
- if (coordinates === void 0) return;
111
- const base = {
112
- ...coordinates,
113
- sessionId: context.session.id,
114
- turnId: event.data !== void 0 && "turnId" in event.data ? event.data.turnId : context.session.turn.id,
115
- at: event.meta.at
116
- };
117
- const eventId = `eve:${context.session.id}:${event.meta.id}`;
118
- if (event.type === "actions.requested") for (const action of event.data.actions) {
119
- const name = "toolName" in action ? action.toolName : action.name;
120
- await archive.append(conversationEvent({
121
- ...base,
122
- eventId: `${eventId}:${action.callId}`,
123
- kind: "tool_call",
124
- toolCallId: action.callId,
125
- toolName: name,
126
- argsSummary: summarizeArguments(action.input),
127
- argsText: contentText(action.input, CONTENT_CAPS.args),
128
- status: "requested"
129
- }));
130
- }
131
- else if (event.type === "action.result") {
132
- const result = event.data.result;
133
- const name = "toolName" in result ? result.toolName : "name" in result ? result.name : result.subagentName;
134
- await archive.append(conversationEvent({
135
- ...base,
136
- eventId,
137
- kind: "tool_result",
138
- toolCallId: result.callId,
139
- toolName: name,
140
- status: event.data.status,
141
- resultText: contentText("output" in result ? result.output : null, CONTENT_CAPS.result),
142
- errorText: contentText(event.data.error?.message ?? (event.data.status === "failed" ? resultErrorMessage(result.output) : null), CONTENT_CAPS.error)
143
- }));
144
- } else if (event.type === "task.started" || event.type === "task.settled") await archive.append(conversationEvent({
145
- ...base,
146
- eventId,
147
- kind: event.type === "task.started" ? "tool_call" : "tool_result",
148
- toolCallId: event.data.callId,
149
- toolName: event.data.name ?? "task",
150
- argsSummary: "{}",
151
- ...event.type === "task.settled" ? {
152
- resultText: contentText(event.data.output, CONTENT_CAPS.result),
153
- errorText: contentText(event.data.error?.message, CONTENT_CAPS.error)
154
- } : {},
155
- status: event.type === "task.started" ? "requested" : event.data.status === "cancelled" ? "cancelled" : event.data.status === "failed" ? "failed" : "completed"
156
- }));
157
- else if (event.type === "turn.failed" || event.type === "step.failed") await archive.append(conversationEvent({
158
- ...base,
159
- turnId: event.data.turnId,
160
- eventId,
161
- kind: "decision",
162
- decision: "silent",
163
- reason: event.type,
164
- status: "failed",
165
- errorText: contentText(event.data.message, CONTENT_CAPS.error)
166
- }));
167
- else if (event.type === "message.completed" && event.data.finishReason !== "tool-calls") {
168
- const kind = completionKind(event.data.message, event.data.finishReason);
169
- const silent = kind !== "reply";
170
- const note = kind === "silent_marker" ? "Model returned an explicit silence marker; no message delivery." : kind === "empty" ? "Model completed without final text; no message delivery." : kind === "whitespace" ? "Model returned only whitespace; no message delivery." : "Model produced a reply; transport delivery is recorded separately.";
171
- await archive.append(conversationEvent({
172
- ...base,
173
- eventId,
174
- kind: "decision",
175
- decision: silent ? "silent" : "reply",
176
- reason: kind === "reply" ? "model_reply" : `model_${kind}_output`,
177
- text: note,
178
- argsSummary: JSON.stringify({
179
- outputKind: kind,
180
- outputCharacters: event.data.message?.length ?? 0,
181
- finishReason: event.data.finishReason
182
- })
183
- }));
184
- if (coordinates.provider !== "telegram" && !silent) await archive.append(conversationEvent({
185
- ...base,
186
- eventId: `${eventId}:outbound`,
187
- kind: "outbound",
188
- text: event.data.message,
189
- senderId: "agent",
190
- senderIsBot: true,
191
- status: "completed"
192
- }));
193
- } else if (event.type === "message.received" && coordinates.provider !== "telegram") await archive.append(conversationEvent({
194
- ...base,
195
- eventId,
196
- kind: "inbound",
197
- text: event.data.message,
198
- attachments: (event.data.parts ?? []).filter((part) => part.type === "file").map((part, index) => ({
199
- id: `${eventId}:file:${index}`,
200
- kind: "file",
201
- ...part.filename ? { filename: part.filename } : {},
202
- contentType: part.mediaType
203
- }))
204
- }));
205
- };
206
- }
207
- function resultErrorMessage(output) {
208
- if (typeof output === "string") return output;
209
- if (output !== null && typeof output === "object" && "message" in output && typeof output.message === "string") return output.message;
210
- return null;
211
- }
212
- export { conversationRecorder as n, conversationCoordinates as t };