@segmentstream/agent 0.8.23 → 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.
- package/dist/_chunks/{build-metadata-26dmE9nn.mjs → build-metadata-DuHeGf1m.mjs} +1 -1
- package/dist/_chunks/content-CvFsrmSD.mjs +102 -0
- package/dist/extension/channels/telegram.mjs +1 -0
- package/dist/extension/config.d.ts +16 -2
- package/dist/extension/config.mjs +92 -3
- package/dist/extension/extension.d.ts +7 -0
- package/dist/extension/extension.mjs +8 -1
- package/dist/extension/hooks/conversations.mjs +1 -1
- package/dist/extension/instructions/conversations.mjs +1 -1
- package/dist/extension/lib/build-metadata.mjs +1 -1
- package/dist/extension/lib/conversation-runtime.mjs +132 -1
- package/dist/extension/lib/deferred-confirmations.mjs +1 -1
- package/dist/extension/lib/group-routing/engagement.d.ts +18 -0
- package/dist/extension/lib/group-routing/engagement.mjs +65 -0
- package/dist/extension/lib/group-routing/health.d.ts +11 -0
- package/dist/extension/lib/group-routing/health.mjs +36 -0
- package/dist/extension/lib/group-routing/observed.d.ts +100 -0
- package/dist/extension/lib/group-routing/observed.mjs +103 -0
- package/dist/extension/lib/group-routing/policy.d.ts +63 -0
- package/dist/extension/lib/group-routing/policy.mjs +162 -0
- package/dist/extension/lib/group-routing/record.d.ts +3 -0
- package/dist/extension/lib/group-routing/record.mjs +35 -0
- package/dist/extension/lib/group-routing/replay.d.ts +18 -0
- package/dist/extension/lib/group-routing/replay.mjs +70 -0
- package/dist/extension/lib/group-routing/router.d.ts +109 -0
- package/dist/extension/lib/group-routing/router.mjs +383 -0
- package/dist/extension/lib/group-routing/routing-context.d.ts +4 -0
- package/dist/extension/lib/group-routing/routing-context.mjs +96 -0
- package/dist/extension/lib/group-routing/settings.d.ts +14 -0
- package/dist/extension/lib/group-routing/settings.mjs +58 -0
- package/dist/extension/lib/group-routing/signals.d.ts +110 -0
- package/dist/extension/lib/group-routing/signals.mjs +47 -0
- package/dist/extension/lib/identities.d.ts +3 -0
- package/dist/extension/lib/identities.mjs +13 -1
- package/dist/extension/lib/ontology-connection.mjs +1 -1
- package/dist/extension/lib/ontology-tools.mjs +1 -1
- package/dist/extension/lib/telegram/adapter.d.ts +2 -0
- package/dist/extension/lib/telegram/adapter.mjs +17 -5
- package/dist/extension/lib/telegram/attachments-send.mjs +1 -1
- package/dist/extension/lib/telegram/audience.d.ts +3 -26
- package/dist/extension/lib/telegram/audience.mjs +1 -5
- package/dist/extension/lib/telegram/confirmation-expiry.mjs +2 -2
- package/dist/extension/lib/telegram/confirmations.mjs +2 -2
- package/dist/extension/lib/telegram/conversations.d.ts +1 -1
- package/dist/extension/lib/telegram/conversations.mjs +17 -4
- package/dist/extension/lib/telegram/deferred-confirmations.mjs +2 -2
- package/dist/extension/lib/telegram/health.d.ts +1 -0
- package/dist/extension/lib/telegram/health.mjs +2 -1
- package/dist/extension/lib/telegram/inbound.d.ts +7 -0
- package/dist/extension/lib/telegram/inbound.mjs +47 -15
- package/dist/extension/lib/telegram/lifecycle.mjs +1 -1
- package/dist/extension/lib/telegram/observed.d.ts +5 -98
- package/dist/extension/lib/telegram/observed.mjs +11 -92
- package/dist/extension/lib/telegram/router.d.ts +4 -114
- package/dist/extension/lib/telegram/router.mjs +4 -250
- package/dist/extension/lib/telegram/routing-context.d.ts +3 -3
- package/dist/extension/lib/telegram/routing-context.mjs +7 -86
- package/dist/extension/lib/telegram/signals.d.ts +5 -0
- package/dist/extension/lib/telegram/signals.mjs +60 -0
- package/dist/extension/lib/telegram/silent.mjs +1 -1
- package/dist/extension/tools/attachments_promote.mjs +1 -1
- package/dist/extension/tools/attachments_send.mjs +1 -1
- package/package.json +2 -2
- package/dist/_chunks/conversation-runtime-ovs8IhXJ.mjs +0 -212
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/** Channels report facts; unavailable signals must never be guessed. */
|
|
2
|
+
export interface AgentIdentity {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly username: string | undefined;
|
|
5
|
+
readonly displayName?: string;
|
|
6
|
+
readonly firstName?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GroupMessageSignals {
|
|
9
|
+
readonly provider: string;
|
|
10
|
+
readonly conversation: {
|
|
11
|
+
readonly externalId: string;
|
|
12
|
+
readonly kind: "direct" | "group" | "channel";
|
|
13
|
+
readonly scope?: string;
|
|
14
|
+
readonly title?: string;
|
|
15
|
+
};
|
|
16
|
+
readonly message: {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly at: string;
|
|
19
|
+
readonly text: string;
|
|
20
|
+
readonly edited?: {
|
|
21
|
+
readonly originalAt: string;
|
|
22
|
+
readonly editedAt: string;
|
|
23
|
+
};
|
|
24
|
+
readonly attachments: ReadonlyArray<{
|
|
25
|
+
readonly kind: string;
|
|
26
|
+
readonly filename?: string;
|
|
27
|
+
readonly mediaType?: string;
|
|
28
|
+
readonly size?: number;
|
|
29
|
+
}>;
|
|
30
|
+
readonly hasCaption: boolean;
|
|
31
|
+
};
|
|
32
|
+
readonly sender: {
|
|
33
|
+
readonly externalId: string;
|
|
34
|
+
readonly username?: string;
|
|
35
|
+
readonly displayName?: string;
|
|
36
|
+
readonly kind: "human" | "bot" | "other_bot" | "unknown";
|
|
37
|
+
readonly member?: {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly name: string | null;
|
|
40
|
+
readonly roles: ReadonlyArray<string>;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
readonly addressing: {
|
|
44
|
+
readonly agentMentioned: boolean;
|
|
45
|
+
readonly command: boolean;
|
|
46
|
+
readonly replyTo?: {
|
|
47
|
+
readonly messageId: string;
|
|
48
|
+
readonly author: "agent" | "human" | "other_bot" | "unknown";
|
|
49
|
+
readonly authorExternalId?: string;
|
|
50
|
+
readonly authorUsername?: string;
|
|
51
|
+
readonly authorName?: string;
|
|
52
|
+
readonly hasAttachments?: boolean;
|
|
53
|
+
readonly self?: boolean;
|
|
54
|
+
};
|
|
55
|
+
readonly mentions: ReadonlyArray<{
|
|
56
|
+
readonly externalId?: string;
|
|
57
|
+
readonly username?: string;
|
|
58
|
+
readonly kind: "human" | "bot" | "other_bot" | "unknown";
|
|
59
|
+
}>;
|
|
60
|
+
readonly threadWithAgent: boolean | "unavailable";
|
|
61
|
+
/** False when a channel does not admit ambient channel messages. */
|
|
62
|
+
readonly eligible?: boolean;
|
|
63
|
+
};
|
|
64
|
+
readonly derived?: {
|
|
65
|
+
readonly transcript?: string;
|
|
66
|
+
readonly attachmentDescription?: string;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export interface AgentMessageSignals {
|
|
70
|
+
readonly provider: string;
|
|
71
|
+
readonly conversation: GroupMessageSignals["conversation"];
|
|
72
|
+
readonly message: GroupMessageSignals["message"];
|
|
73
|
+
readonly replyToMessageId?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface GroupChannelAdapter<Message, Delivery, Principal> {
|
|
76
|
+
readonly provider: string;
|
|
77
|
+
signals(message: Message, bot: AgentIdentity | undefined): GroupMessageSignals;
|
|
78
|
+
outbound(delivery: Delivery): AgentMessageSignals;
|
|
79
|
+
address(signals: GroupMessageSignals, scope: "chat" | "thread"): string;
|
|
80
|
+
principal(signals: GroupMessageSignals): Principal;
|
|
81
|
+
}
|
|
82
|
+
export declare function conversationKey(signals: Pick<GroupMessageSignals, "provider" | "conversation">): string;
|
|
83
|
+
export interface MessageAudience {
|
|
84
|
+
readonly originalText: string;
|
|
85
|
+
readonly botTagged: boolean;
|
|
86
|
+
readonly mentions: ReadonlyArray<{
|
|
87
|
+
readonly kind: "bot" | "human" | "other_bot" | "unknown";
|
|
88
|
+
readonly id?: string;
|
|
89
|
+
readonly username?: string;
|
|
90
|
+
readonly name?: string;
|
|
91
|
+
readonly type: "mention" | "text_mention";
|
|
92
|
+
readonly text: string;
|
|
93
|
+
}>;
|
|
94
|
+
readonly replyTo: null | {
|
|
95
|
+
readonly kind: "bot" | "human" | "other_bot" | "unknown";
|
|
96
|
+
readonly id?: string;
|
|
97
|
+
readonly username?: string;
|
|
98
|
+
readonly name?: string;
|
|
99
|
+
readonly messageId: string;
|
|
100
|
+
readonly text: string;
|
|
101
|
+
readonly hasAttachments?: boolean;
|
|
102
|
+
readonly filename?: string;
|
|
103
|
+
readonly self?: boolean;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export declare function signalAudience(signals: GroupMessageSignals): MessageAudience;
|
|
107
|
+
export type AddressingReason = "private" | "mention" | "reply-to-bot" | "command" | "pending-question" | "thread-with-agent";
|
|
108
|
+
export declare function addressingReason(signals: GroupMessageSignals): AddressingReason | undefined;
|
|
109
|
+
/** Explicit recipients win; quoting an upload or one's own message remains inference evidence. */
|
|
110
|
+
export declare function otherRecipient(audience: MessageAudience | undefined): string | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
function conversationKey(signals) {
|
|
8
|
+
const scope = signals.conversation.scope === void 0 ? "" : `/${signals.conversation.scope}`;
|
|
9
|
+
return `${signals.provider}:${signals.conversation.externalId}${scope}`;
|
|
10
|
+
}
|
|
11
|
+
function signalAudience(signals) {
|
|
12
|
+
const reply = signals.addressing.replyTo;
|
|
13
|
+
return {
|
|
14
|
+
originalText: signals.message.text,
|
|
15
|
+
botTagged: signals.addressing.agentMentioned,
|
|
16
|
+
mentions: signals.addressing.mentions.map((m) => ({
|
|
17
|
+
kind: m.kind,
|
|
18
|
+
id: m.externalId,
|
|
19
|
+
username: m.username,
|
|
20
|
+
type: "mention",
|
|
21
|
+
text: m.username === void 0 ? "" : `@${m.username}`
|
|
22
|
+
})),
|
|
23
|
+
replyTo: reply === void 0 ? null : {
|
|
24
|
+
kind: reply.author === "agent" ? "bot" : reply.author,
|
|
25
|
+
id: reply.authorExternalId,
|
|
26
|
+
username: reply.authorUsername,
|
|
27
|
+
name: reply.authorName,
|
|
28
|
+
messageId: reply.messageId,
|
|
29
|
+
text: "",
|
|
30
|
+
hasAttachments: reply.hasAttachments,
|
|
31
|
+
self: reply.self
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function addressingReason(signals) {
|
|
36
|
+
if (signals.conversation.kind === "direct") return "private";
|
|
37
|
+
if (signals.addressing.command) return "command";
|
|
38
|
+
if (signals.addressing.agentMentioned) return "mention";
|
|
39
|
+
if (signals.addressing.replyTo?.author === "agent") return "reply-to-bot";
|
|
40
|
+
return signals.addressing.threadWithAgent === true ? "thread-with-agent" : void 0;
|
|
41
|
+
}
|
|
42
|
+
function otherRecipient(audience) {
|
|
43
|
+
if (audience === void 0 || audience.botTagged) return;
|
|
44
|
+
if (audience.mentions.some((item) => item.kind !== "bot")) return "Message tags another recipient; this agent was not addressed.";
|
|
45
|
+
if (audience.replyTo?.kind === "other_bot" || audience.replyTo?.kind === "human" && !audience.replyTo.hasAttachments && !audience.replyTo.self) return "Reply targets another person or bot; this agent was not addressed.";
|
|
46
|
+
}
|
|
47
|
+
export { addressingReason, conversationKey, otherRecipient, signalAudience };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ChatOverrideInput } from "@segmentstream-cloud/ontology/groups";
|
|
1
2
|
import type { AdmissionLimitsInput } from "../config.js";
|
|
2
3
|
import type { RuntimeToken } from "./runtime-token.js";
|
|
3
4
|
/**
|
|
@@ -68,6 +69,8 @@ export interface ChatAccount {
|
|
|
68
69
|
}
|
|
69
70
|
/** A group chat in the ontology's `agent_chat` registry, with what members said it is for. */
|
|
70
71
|
export interface AgentChat {
|
|
72
|
+
readonly routing?: ChatOverrideInput;
|
|
73
|
+
readonly scope?: string;
|
|
71
74
|
readonly id: string;
|
|
72
75
|
readonly title: string;
|
|
73
76
|
readonly purpose: string | null;
|
|
@@ -5,6 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { redactDiagnostic } from "./diagnostics.mjs";
|
|
8
|
+
import { groupPolicyIssues } from "@segmentstream-cloud/ontology/groups";
|
|
8
9
|
var AgentIdentityError = class extends Error {
|
|
9
10
|
name = "AgentIdentityError";
|
|
10
11
|
code;
|
|
@@ -93,11 +94,22 @@ function agentChat(value) {
|
|
|
93
94
|
code: "invalid_response",
|
|
94
95
|
message: "The ontology service answered the chat report with an invalid body."
|
|
95
96
|
});
|
|
97
|
+
const override = {
|
|
98
|
+
...isRecord(value.routing) ? value.routing : {},
|
|
99
|
+
...isRecord(value.participants) ? { participants: value.participants } : {}
|
|
100
|
+
};
|
|
101
|
+
const valid = groupPolicyIssues(override, true).length === 0;
|
|
102
|
+
if (!valid) console.error("[segmentstream] invalid chat routing override", {
|
|
103
|
+
chatId: value.id,
|
|
104
|
+
issues: groupPolicyIssues(override, true)
|
|
105
|
+
});
|
|
96
106
|
return {
|
|
97
107
|
id: value.id,
|
|
98
108
|
title: value.title,
|
|
99
109
|
purpose: value.purpose,
|
|
100
|
-
whenToUse: value.whenToUse
|
|
110
|
+
whenToUse: value.whenToUse,
|
|
111
|
+
...typeof value.scope === "string" ? { scope: value.scope } : {},
|
|
112
|
+
...valid && Object.keys(override).length > 0 ? { routing: override } : {}
|
|
101
113
|
};
|
|
102
114
|
}
|
|
103
115
|
async function refusal(response, call) {
|
|
@@ -6,9 +6,9 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { appOrigin } from "./environment.mjs";
|
|
8
8
|
import { identityProviderOf, memberIdOf } from "./telegram/principal.mjs";
|
|
9
|
+
import { runtimeToken, tokenExpiry } from "./runtime-token.mjs";
|
|
9
10
|
import { CHAT_POST_ENVELOPE, chatPostDigest, chatPostOperationId, isChatPost } from "./chat-post-confirmation.mjs";
|
|
10
11
|
import { actionApproval, confirmations } from "./confirmations.mjs";
|
|
11
|
-
import { runtimeToken, tokenExpiry } from "./runtime-token.mjs";
|
|
12
12
|
import { ontologyTools } from "./ontology-tools.mjs";
|
|
13
13
|
import { defineMcpClientConnection } from "eve/connections";
|
|
14
14
|
const ACT_AS_HEADER = "X-SegmentStream-Act-As";
|
|
@@ -6,10 +6,10 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { appOrigin } from "./environment.mjs";
|
|
8
8
|
import { identityProviderOf, memberIdOf } from "./telegram/principal.mjs";
|
|
9
|
+
import { runtimeToken } from "./runtime-token.mjs";
|
|
9
10
|
import { redactDiagnostic } from "./diagnostics.mjs";
|
|
10
11
|
import { describeConfirmation, object } from "./confirmation-description.mjs";
|
|
11
12
|
import { describeChatPost, isChatPost, supportsChatPost } from "./chat-post-confirmation.mjs";
|
|
12
|
-
import { runtimeToken } from "./runtime-token.mjs";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
14
|
var OntologyToolRejected = class extends Error {
|
|
15
15
|
code = "ontology_tool_rejected";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GroupPolicy } from "../group-routing/policy.js";
|
|
1
2
|
import { type AttachmentDescriber } from "./attachment-description.js";
|
|
2
3
|
import { type TelegramChannel } from "eve/channels/telegram";
|
|
3
4
|
import type { ChatModelChoice, AdmissionSettings, SessionSettings, TelegramSettings } from "../../config.js";
|
|
@@ -21,6 +22,7 @@ import { type Transcriber } from "./voice.js";
|
|
|
21
22
|
export interface TelegramAdapterOptions {
|
|
22
23
|
/** The mounted `channels.telegram`, or `null` when the workspace has no Telegram channel. */
|
|
23
24
|
readonly settings: () => TelegramSettings | null;
|
|
25
|
+
readonly groups?: () => GroupPolicy;
|
|
24
26
|
readonly models: () => {
|
|
25
27
|
readonly stt: string | false;
|
|
26
28
|
readonly decision: string;
|
|
@@ -8,13 +8,16 @@ import { manifestOf } from "../../config.mjs";
|
|
|
8
8
|
import { appOrigin, channelsEnabled, proxyEnvironment, runtimeIdentityEnvironment, webhookSecret } from "../environment.mjs";
|
|
9
9
|
import { conversationLanguage, telegramPrincipal } from "./principal.mjs";
|
|
10
10
|
import { chooseModel } from "../../model.mjs";
|
|
11
|
-
import {
|
|
11
|
+
import { groupRoutingHealth } from "../group-routing/health.mjs";
|
|
12
|
+
import { decisionRouter } from "../group-routing/router.mjs";
|
|
13
|
+
import { runtimeToken } from "../runtime-token.mjs";
|
|
14
|
+
import { groupSettings } from "../group-routing/settings.mjs";
|
|
15
|
+
import { conversations } from "../conversations.mjs";
|
|
16
|
+
import { t as agentBuild } from "../../../_chunks/build-metadata-DuHeGf1m.mjs";
|
|
12
17
|
import { confirmationLocale } from "./confirmation-text.mjs";
|
|
13
18
|
import { telegramSendScope } from "./send-queue.mjs";
|
|
14
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-B8Eyjz1O.mjs";
|
|
15
|
-
import { runtimeToken } from "../runtime-token.mjs";
|
|
16
20
|
import { attachmentLifecycle } from "./lifecycle.mjs";
|
|
17
|
-
import { conversations } from "../conversations.mjs";
|
|
18
21
|
import { scopedAddress, sessionPolicy } from "./sessions.mjs";
|
|
19
22
|
import { observedMessages } from "./observed.mjs";
|
|
20
23
|
import { expireDeferredCards, handleDeferredCallback, isDeferredCallback } from "./deferred-confirmations.mjs";
|
|
@@ -23,7 +26,6 @@ import { gatewayAttachmentDescriber } from "./attachment-description.mjs";
|
|
|
23
26
|
import { MAXIMUM_DOWNLOAD_BYTES, connectionProxy } from "../connection-proxy.mjs";
|
|
24
27
|
import { agentAttachments, parseAttachmentUrl } from "../attachments.mjs";
|
|
25
28
|
import { agentIdentities } from "../identities.mjs";
|
|
26
|
-
import { decisionRouter } from "./router.mjs";
|
|
27
29
|
import { replyDelivery } from "./silent.mjs";
|
|
28
30
|
import { handleConfirmationCallback, telegramConfirmationEvents } from "./confirmations.mjs";
|
|
29
31
|
import { captureRouteDecider, captureTelegramFetch, conversationIdentities, recordGateDecision, telegramConversationCapture } from "./conversations.mjs";
|
|
@@ -68,7 +70,12 @@ const eveInteractions = async (sessionId) => {
|
|
|
68
70
|
function segmentstreamTelegram(options) {
|
|
69
71
|
const environment = options.environment ?? process.env;
|
|
70
72
|
const token = options.token ?? runtimeToken;
|
|
71
|
-
const
|
|
73
|
+
const readGroups = groupSettings({
|
|
74
|
+
environment,
|
|
75
|
+
token,
|
|
76
|
+
fetch: options.fetch
|
|
77
|
+
});
|
|
78
|
+
const observed = options.observed ?? observedMessages(60);
|
|
72
79
|
const readHistory = options.history ?? eveHistory;
|
|
73
80
|
const readInteractions = options.history ?? eveInteractions;
|
|
74
81
|
const capabilities = options.modelCapabilities ?? gatewayMediaCapabilities(options.fetch);
|
|
@@ -166,6 +173,10 @@ function segmentstreamTelegram(options) {
|
|
|
166
173
|
request: currentInboundRequest(),
|
|
167
174
|
dependencies: {
|
|
168
175
|
policy: settings().policy,
|
|
176
|
+
decisionModel: options.models().decision,
|
|
177
|
+
groups: options.groups?.(),
|
|
178
|
+
cloudGroups: options.groups === void 0 ? void 0 : readGroups,
|
|
179
|
+
signalSettings: settings().groups,
|
|
169
180
|
recoverHeldApprovals: options.confirmationMode?.() === "deferred",
|
|
170
181
|
...settings().attachmentLifecycle === void 0 ? {} : { lifecycle: (principal, memberId, message) => attachmentLifecycle({
|
|
171
182
|
configuration: settings().attachmentLifecycle,
|
|
@@ -403,6 +414,7 @@ function segmentstreamTelegram(options) {
|
|
|
403
414
|
capture
|
|
404
415
|
})), healthRoute({
|
|
405
416
|
chats,
|
|
417
|
+
...options.groups === void 0 ? {} : { routing: groupRoutingHealth },
|
|
406
418
|
enabled: () => channelsEnabled(environment),
|
|
407
419
|
configured: () => options.settings() !== null,
|
|
408
420
|
verify: () => verify ??= runtimeTokenVerifier(runtimeIdentityEnvironment(environment)),
|
|
@@ -6,11 +6,11 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { appOrigin, channelsEnabled, proxyEnvironment } from "../environment.mjs";
|
|
8
8
|
import "./principal.mjs";
|
|
9
|
+
import { runtimeToken } from "../runtime-token.mjs";
|
|
9
10
|
import { redactDiagnostic } from "../diagnostics.mjs";
|
|
10
11
|
import { confirmationLocale } from "./confirmation-text.mjs";
|
|
11
12
|
import { inTelegramSendQueue, telegramSendScope } from "./send-queue.mjs";
|
|
12
13
|
import { c as customerCopy, f as formattingRefused, l as customerMessage, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
|
|
13
|
-
import { runtimeToken } from "../runtime-token.mjs";
|
|
14
14
|
import { MAXIMUM_PROXY_BODY_BYTES, connectionProxy } from "../connection-proxy.mjs";
|
|
15
15
|
import { ACT_AS_HEADER } from "../ontology-connection.mjs";
|
|
16
16
|
import { AttachmentError, CONVERSATION_HEADER, SESSION_HEADER } from "../attachments.mjs";
|
|
@@ -1,30 +1,7 @@
|
|
|
1
1
|
import type { TelegramMessage } from "eve/channels/telegram";
|
|
2
2
|
import type { BotIdentity } from "./router.js";
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
readonly kind: TargetKind;
|
|
6
|
-
readonly id?: string;
|
|
7
|
-
readonly username?: string;
|
|
8
|
-
readonly name?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface MessageAudience {
|
|
11
|
-
readonly originalText: string;
|
|
12
|
-
readonly botTagged: boolean;
|
|
13
|
-
readonly mentions: ReadonlyArray<Recipient & {
|
|
14
|
-
readonly type: "mention" | "text_mention";
|
|
15
|
-
readonly text: string;
|
|
16
|
-
}>;
|
|
17
|
-
readonly replyTo: (Recipient & {
|
|
18
|
-
readonly messageId: string;
|
|
19
|
-
readonly text: string;
|
|
20
|
-
/** A reply can quote evidence instead of addressing its uploader. */
|
|
21
|
-
readonly hasAttachments?: boolean;
|
|
22
|
-
readonly filename?: string;
|
|
23
|
-
readonly self?: boolean;
|
|
24
|
-
}) | null;
|
|
25
|
-
}
|
|
3
|
+
export type { MessageAudience } from "../group-routing/signals.js";
|
|
4
|
+
import type { MessageAudience } from "../group-routing/signals.js";
|
|
26
5
|
/** Current-message entities only; mentions inside a quoted/code range are not addressees. */
|
|
27
6
|
export declare function messageAudience(message: TelegramMessage, bot: BotIdentity | undefined): MessageAudience;
|
|
28
|
-
|
|
29
|
-
export declare function otherRecipient(audience: MessageAudience | undefined): string | undefined;
|
|
30
|
-
export {};
|
|
7
|
+
export { otherRecipient } from "../group-routing/signals.js";
|
|
@@ -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 { otherRecipient } from "../group-routing/signals.mjs";
|
|
7
8
|
import { messageContent, telegramRecord } from "./content.mjs";
|
|
8
9
|
function recipient(user, bot) {
|
|
9
10
|
const id = typeof user.id === "string" || typeof user.id === "number" ? String(user.id) : void 0;
|
|
@@ -85,9 +86,4 @@ function messageAudience(message, bot) {
|
|
|
85
86
|
replyTo
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
|
-
function otherRecipient(audience) {
|
|
89
|
-
if (audience === void 0 || audience.botTagged) return;
|
|
90
|
-
if (audience.mentions.some((item) => item.kind !== "bot")) return "Message tags another recipient; this bot was not addressed.";
|
|
91
|
-
if (audience.replyTo?.kind === "other_bot" || audience.replyTo?.kind === "human" && !audience.replyTo.hasAttachments && !audience.replyTo.self) return "Reply targets another person or bot; this bot was not addressed.";
|
|
92
|
-
}
|
|
93
89
|
export { messageAudience, otherRecipient };
|
|
@@ -5,11 +5,11 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { proxyEnvironment } from "../environment.mjs";
|
|
8
|
+
import { runtimeToken } from "../runtime-token.mjs";
|
|
9
|
+
import { conversations } from "../conversations.mjs";
|
|
8
10
|
import { telegramSendScope } from "./send-queue.mjs";
|
|
9
11
|
import { m as safeTelegramFetch, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
|
|
10
|
-
import { runtimeToken } from "../runtime-token.mjs";
|
|
11
12
|
import { deferredConfirmations } from "../deferred-confirmations.mjs";
|
|
12
|
-
import { conversations } from "../conversations.mjs";
|
|
13
13
|
import { expireDeferredRecord } from "./deferred-confirmations.mjs";
|
|
14
14
|
import { connectionProxy } from "../connection-proxy.mjs";
|
|
15
15
|
import { TELEGRAM_PLACEHOLDER_TOKEN, TELEGRAM_PROXY_ORIGIN, telegramProxyFetch } from "./proxy-fetch.mjs";
|
|
@@ -5,15 +5,15 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { memberIdOf, telegramPrincipal } from "./principal.mjs";
|
|
8
|
+
import { agentMessage, observedChatKey, withConfirmationPrompt } from "../group-routing/observed.mjs";
|
|
9
|
+
import { conversationEvent } from "../conversations.mjs";
|
|
8
10
|
import { humanText } from "../confirmation-description.mjs";
|
|
9
11
|
import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
|
|
10
12
|
import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
|
|
11
13
|
import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
|
|
12
14
|
import { chatPostOperationId, isChatPost } from "../chat-post-confirmation.mjs";
|
|
13
15
|
import { confirmations } from "../confirmations.mjs";
|
|
14
|
-
import { conversationEvent } from "../conversations.mjs";
|
|
15
16
|
import { formatAddress, scopedAddress } from "./sessions.mjs";
|
|
16
|
-
import { agentMessage, observedChatKey, withConfirmationPrompt } from "./observed.mjs";
|
|
17
17
|
import { postDeferredCard } from "./deferred-confirmations.mjs";
|
|
18
18
|
import { answerMarker, isPendingQuestion, pendingQuestions, questionKey } from "../questions.mjs";
|
|
19
19
|
import { telegramTextLinks } from "@segmentstream-cloud/ontology/telegram";
|
|
@@ -17,7 +17,7 @@ export declare function captureTelegramWebhook(input: {
|
|
|
17
17
|
}): Promise<Response>;
|
|
18
18
|
/** Additive inbound hook: the router keeps ownership of the reply policy. */
|
|
19
19
|
export declare function recordGateDecision(reason: string, decision?: "reply" | "silent"): void;
|
|
20
|
-
export declare function recordRouteDecision(route: "reply" | "observe", addressed: boolean | AddressingReason | undefined, policy: string, audit?: Pick<RouteDecision, "reason" | "note" | "diagnostics">): void;
|
|
20
|
+
export declare function recordRouteDecision(route: "reply" | "observe", addressed: boolean | AddressingReason | undefined, policy: string, audit?: Pick<RouteDecision, "reason" | "note" | "diagnostics" | "router" | "shadow">): void;
|
|
21
21
|
export declare function captureRouteDecider(decide: RouteDecider): RouteDecider;
|
|
22
22
|
/** Update the existing inbound event after STT/description, under the same text retention policy. */
|
|
23
23
|
export declare function recordInboundContent(content: {
|
|
@@ -4,11 +4,12 @@ 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 {
|
|
7
|
+
import { currentConfirmationPrompt, observedChatKey } from "../group-routing/observed.mjs";
|
|
8
8
|
import { conversationEvent } from "../conversations.mjs";
|
|
9
|
+
import { archivedRoutingMessages } from "../group-routing/routing-context.mjs";
|
|
10
|
+
import { n as currentInboundRequest, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
|
|
9
11
|
import { contentShape, messageContent } from "./content.mjs";
|
|
10
|
-
import {
|
|
11
|
-
import { archivedRoutingMessages } from "./routing-context.mjs";
|
|
12
|
+
import { messageMetadata } from "./observed.mjs";
|
|
12
13
|
import { reportMembership } from "./membership.mjs";
|
|
13
14
|
import { createHash, randomUUID } from "node:crypto";
|
|
14
15
|
import { parseTelegramUpdate } from "eve/channels/telegram";
|
|
@@ -233,7 +234,7 @@ async function captureTelegramWebhook(input) {
|
|
|
233
234
|
});
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
|
-
if (!automated) for (const earlier of input.observed.recent(chat).length === 0 ? archivedRoutingMessages((history?.events ?? []).filter((item) => item.eventId !== event.eventId)) : []) if ("role" in earlier || history?.events.some((decision) => decision.kind === "decision" && decision.messageId === earlier.messageId && decision.reason === "turn_admitted")) input.observed.remember(chat, earlier);
|
|
237
|
+
if (!automated) for (const earlier of input.observed.recent(chat).length === 0 ? archivedRoutingMessages((history?.events ?? []).filter((item) => item.eventId !== event.eventId), 60) : []) if ("role" in earlier || history?.events.some((decision) => decision.kind === "decision" && decision.messageId === earlier.messageId && decision.reason === "turn_admitted")) input.observed.remember(chat, earlier);
|
|
237
238
|
else input.observed.add(chat, earlier);
|
|
238
239
|
if (automated || edited !== void 0) {
|
|
239
240
|
if (message.chat.type === "group" || message.chat.type === "supergroup") await input.chats?.seen({
|
|
@@ -382,6 +383,8 @@ async function captureTelegramWebhook(input) {
|
|
|
382
383
|
kind: "decision",
|
|
383
384
|
argsSummary: JSON.stringify({
|
|
384
385
|
...capture.diagnostics === void 0 ? {} : { decision: capture.diagnostics },
|
|
386
|
+
...capture.router === void 0 ? {} : { router: capture.router },
|
|
387
|
+
...capture.shadow === void 0 ? {} : { shadow: capture.shadow },
|
|
385
388
|
routing: { membership: capture.lookup === void 0 ? "unknown" : capture.lookup.status === "paired" || capture.lookup.status === "existing" || capture.lookup.status === "created" ? "linked" : "unlinked" }
|
|
386
389
|
}),
|
|
387
390
|
text: capture.note ?? (edited !== void 0 ? "Message edit recorded as context; no agent turn started." : null),
|
|
@@ -409,7 +412,10 @@ function recordRouteDecision(route, addressed, policy, audit) {
|
|
|
409
412
|
capture.decision = route === "reply" ? "reply" : "silent";
|
|
410
413
|
capture.reason ??= audit?.reason ?? (typeof addressed === "string" ? addressed : addressed ? "addressed_message" : policy === "mention" ? "mention_policy" : `decision_model_${route}`);
|
|
411
414
|
capture.note = audit?.note.slice(0, 500);
|
|
415
|
+
capture.routeReason = audit?.reason;
|
|
412
416
|
capture.diagnostics = audit?.diagnostics;
|
|
417
|
+
capture.router = audit?.router;
|
|
418
|
+
capture.shadow = audit?.shadow;
|
|
413
419
|
}
|
|
414
420
|
}
|
|
415
421
|
function captureRouteDecider(decide) {
|
|
@@ -493,6 +499,13 @@ function captureTelegramFetch(fetchImpl, archive, identities) {
|
|
|
493
499
|
...typeof body.parse_mode === "string" ? { parse_mode: body.parse_mode } : {}
|
|
494
500
|
},
|
|
495
501
|
routing: {
|
|
502
|
+
...capture?.routeReason !== void 0 && [
|
|
503
|
+
"mention",
|
|
504
|
+
"command",
|
|
505
|
+
"reply-to-bot",
|
|
506
|
+
"thread-with-agent",
|
|
507
|
+
"pending-question"
|
|
508
|
+
].includes(capture.routeReason) ? { invitation: capture.routeReason } : {},
|
|
496
509
|
...currentConfirmationPrompt() === void 0 ? {} : { confirmation: currentConfirmationPrompt() },
|
|
497
510
|
...capture?.event.chatId === chatId && capture.event.senderId !== null ? { inReplyTo: {
|
|
498
511
|
id: capture.event.senderId,
|
|
@@ -5,6 +5,8 @@ const __filename = __eveFileURLToPath(import.meta.url);
|
|
|
5
5
|
__eveDirname(__filename);
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { telegramPrincipal } from "./principal.mjs";
|
|
8
|
+
import { agentMessage, observedChatKey, withConfirmationPrompt } from "../group-routing/observed.mjs";
|
|
9
|
+
import { conversationEvent } from "../conversations.mjs";
|
|
8
10
|
import { humanText } from "../confirmation-description.mjs";
|
|
9
11
|
import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
|
|
10
12
|
import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
|
|
@@ -13,9 +15,7 @@ import { CONFIRMATION_TTL_MS, inputHash } from "../confirmations.mjs";
|
|
|
13
15
|
import { OntologyToolRejected } from "../ontology-tools.mjs";
|
|
14
16
|
import { confirmationOutcome } from "../confirmation-outcome.mjs";
|
|
15
17
|
import { deferredConfirmations, deferredKey, runDeferredAction } from "../deferred-confirmations.mjs";
|
|
16
|
-
import { conversationEvent } from "../conversations.mjs";
|
|
17
18
|
import { formatAddress } from "./sessions.mjs";
|
|
18
|
-
import { agentMessage, observedChatKey, withConfirmationPrompt } from "./observed.mjs";
|
|
19
19
|
import { telegramTextLinks } from "@segmentstream-cloud/ontology/telegram";
|
|
20
20
|
const PREFIX = "ss-confirm:d:";
|
|
21
21
|
const isDeferredCallback = (data) => data?.startsWith(PREFIX) === true;
|
|
@@ -6,6 +6,7 @@ export declare const HEALTH_ROUTE = "/eve/v1/telegram/health";
|
|
|
6
6
|
/** Runtime-only, per-instance health. It never exposes credentials or private provider bodies. */
|
|
7
7
|
export declare function healthRoute(input: {
|
|
8
8
|
readonly chats: AgentChats;
|
|
9
|
+
readonly routing?: () => unknown;
|
|
9
10
|
readonly enabled: () => boolean;
|
|
10
11
|
readonly configured: () => boolean;
|
|
11
12
|
readonly verify: () => RuntimeTokenVerifier;
|
|
@@ -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 { t as agentBuild } from "../../../_chunks/build-metadata-
|
|
7
|
+
import { t as agentBuild } from "../../../_chunks/build-metadata-DuHeGf1m.mjs";
|
|
8
8
|
import { runtimeRequestFailure } from "./runtime-request.mjs";
|
|
9
9
|
import { GET } from "eve/channels";
|
|
10
10
|
const HEALTH_ROUTE = "/eve/v1/telegram/health";
|
|
@@ -16,6 +16,7 @@ function healthRoute(input) {
|
|
|
16
16
|
return Response.json({
|
|
17
17
|
status: registry.degraded ? "degraded" : "ok",
|
|
18
18
|
registry,
|
|
19
|
+
...input.routing === void 0 ? {} : { routing: input.routing() },
|
|
19
20
|
runtime: agentBuild(),
|
|
20
21
|
...input.configuration === void 0 ? {} : { configuration: input.configuration() }
|
|
21
22
|
}, {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { CloudGroupSettings } from "../group-routing/settings.js";
|
|
2
|
+
import { type GroupPolicy } from "../group-routing/policy.js";
|
|
3
|
+
import type { TelegramSettings } from "../../config.js";
|
|
1
4
|
import { attachmentLifecycle } from "./lifecycle.js";
|
|
2
5
|
import type { TelegramContext, TelegramInboundResult, TelegramMessage } from "eve/channels/telegram";
|
|
3
6
|
import type { AdmissionSettings, SessionSettings, TelegramPolicy } from "../../config.js";
|
|
@@ -39,6 +42,10 @@ import type { PdfTextExtractor } from "./pdf-text.js";
|
|
|
39
42
|
*/
|
|
40
43
|
export interface InboundDependencies {
|
|
41
44
|
readonly policy: TelegramPolicy;
|
|
45
|
+
readonly decisionModel?: string;
|
|
46
|
+
readonly groups?: GroupPolicy;
|
|
47
|
+
readonly cloudGroups?: () => Promise<CloudGroupSettings | undefined>;
|
|
48
|
+
readonly signalSettings?: TelegramSettings["groups"];
|
|
42
49
|
/** Recover old held sessions only when the workspace has chosen non-blocking confirmations. */
|
|
43
50
|
readonly recoverHeldApprovals?: boolean;
|
|
44
51
|
readonly lifecycle?: (principal: import("eve/context").SessionAuthContext, memberId: string, message: TelegramMessage) => ReturnType<typeof attachmentLifecycle>;
|