@segmentstream/agent 0.9.1 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +8 -0
  2. package/dist/_chunks/{build-metadata-DMD3azjO.mjs → build-metadata-BD1PqnN9.mjs} +1 -1
  3. package/dist/_chunks/{inbound-request-B8Eyjz1O.mjs → inbound-request-BrWspFw5.mjs} +2 -1
  4. package/dist/extension/extension.d.ts +2 -0
  5. package/dist/extension/extension.mjs +3 -1
  6. package/dist/extension/hooks/group-routing.d.ts +2 -0
  7. package/dist/extension/hooks/group-routing.mjs +10 -0
  8. package/dist/extension/lib/build-metadata.mjs +1 -1
  9. package/dist/extension/lib/conversation-runtime.d.ts +1 -1
  10. package/dist/extension/lib/conversation-runtime.mjs +23 -1
  11. package/dist/extension/lib/group-routing/burst.d.ts +28 -0
  12. package/dist/extension/lib/group-routing/burst.mjs +64 -0
  13. package/dist/extension/lib/group-routing/conversation-prompt.d.ts +10 -0
  14. package/dist/extension/lib/group-routing/conversation-prompt.mjs +16 -0
  15. package/dist/extension/lib/group-routing/conversation-router.d.ts +58 -0
  16. package/dist/extension/lib/group-routing/conversation-router.mjs +182 -0
  17. package/dist/extension/lib/group-routing/conversation.d.ts +46 -0
  18. package/dist/extension/lib/group-routing/conversation.mjs +262 -0
  19. package/dist/extension/lib/group-routing/dequeue.d.ts +5 -0
  20. package/dist/extension/lib/group-routing/dequeue.mjs +141 -0
  21. package/dist/extension/lib/group-routing/observed.d.ts +2 -0
  22. package/dist/extension/lib/group-routing/policy.d.ts +19 -1
  23. package/dist/extension/lib/group-routing/policy.mjs +49 -11
  24. package/dist/extension/lib/group-routing/replay.d.ts +2 -2
  25. package/dist/extension/lib/group-routing/replay.mjs +51 -11
  26. package/dist/extension/lib/group-routing/router.d.ts +8 -1
  27. package/dist/extension/lib/group-routing/router.mjs +65 -0
  28. package/dist/extension/lib/group-routing/routing-context.mjs +17 -2
  29. package/dist/extension/lib/telegram/adapter.mjs +10 -2
  30. package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
  31. package/dist/extension/lib/telegram/attachments-send.mjs +1 -1
  32. package/dist/extension/lib/telegram/confirmation-expiry.mjs +1 -1
  33. package/dist/extension/lib/telegram/confirmations.mjs +1 -1
  34. package/dist/extension/lib/telegram/conversations.mjs +1 -1
  35. package/dist/extension/lib/telegram/customer-text.mjs +1 -1
  36. package/dist/extension/lib/telegram/deferred-confirmations.mjs +1 -1
  37. package/dist/extension/lib/telegram/files.mjs +1 -1
  38. package/dist/extension/lib/telegram/health.mjs +1 -1
  39. package/dist/extension/lib/telegram/images.mjs +1 -1
  40. package/dist/extension/lib/telegram/inbound-request.d.ts +2 -0
  41. package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
  42. package/dist/extension/lib/telegram/inbound.d.ts +2 -0
  43. package/dist/extension/lib/telegram/inbound.mjs +122 -11
  44. package/dist/extension/lib/telegram/lifecycle.mjs +2 -2
  45. package/dist/extension/lib/telegram/media-policy.mjs +1 -1
  46. package/dist/extension/lib/telegram/silent.mjs +1 -1
  47. package/dist/extension/lib/telegram/turn-errors.mjs +1 -1
  48. package/dist/extension/lib/telegram/voice.mjs +1 -1
  49. package/package.json +2 -2
@@ -4,19 +4,34 @@ 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 { routeMessage } from "./router.mjs";
7
+ import { decisionRouter, routeMessage } from "./router.mjs";
8
8
  async function replayRouterPayload(input) {
9
9
  const policy = input.policy ?? input.payload.policy;
10
10
  const signals = input.payload.signals;
11
11
  const state = input.payload.state;
12
12
  const questions = input.payload.questions;
13
13
  const answer = input.payload.answer;
14
- if (signals === void 0 || policy === void 0 || input.payload.truncated === true) return {
14
+ if (!signals || !policy || input.payload.truncated === true) return {
15
15
  status: "unavailable",
16
16
  reason: "stored_router_input_unavailable"
17
17
  };
18
- const recent = input.payload.question?.recent ?? [];
18
+ const conversation = policy.smart.engagement.policy === "conversation";
19
+ const captured = input.payload.question;
20
+ const storedAddressing = answer && "addressee" in answer ? answer : void 0;
21
+ if (conversation && !input.decide && !storedAddressing) return {
22
+ status: "unavailable",
23
+ reason: "stored_conversation_classifier_unavailable"
24
+ };
25
+ let description = String(state?.agent ?? "");
26
+ if (conversation) try {
27
+ const a = JSON.parse(description);
28
+ if (typeof a.role === "string") description = a.role;
29
+ } catch {}
19
30
  const decisions = [];
31
+ const fresh = input.decide ? decisionRouter({
32
+ decide: input.decide,
33
+ model: policy.smart.model
34
+ }) : void 0;
20
35
  return {
21
36
  status: "replayed",
22
37
  route: await routeMessage({
@@ -29,25 +44,50 @@ async function replayRouterPayload(input) {
29
44
  pendingQuestionAt: typeof input.payload.pending_question_at === "string" ? input.payload.pending_question_at : void 0,
30
45
  recipientAnswer: input.payload.recipient_answer === true,
31
46
  question: async () => ({
47
+ ...captured,
32
48
  signals,
33
49
  groups: policy,
34
- agent: String(state?.agent ?? ""),
35
- recent,
50
+ agent: description,
51
+ recent: captured?.recent ?? [],
36
52
  message: {
37
53
  author: signals.sender.displayName ?? signals.sender.externalId,
38
54
  authorId: signals.sender.externalId,
55
+ messageId: signals.message.id,
39
56
  text: signals.message.text,
40
57
  at: signals.message.at
41
- }
58
+ },
59
+ burstId: typeof input.payload.burst_id === "string" ? input.payload.burst_id : void 0
42
60
  }),
43
- decide: async () => {
44
- if (state === void 0 || questions === void 0 || answer === void 0) throw new Error("Stored classifier contract unavailable.");
45
- const result = input.decide === void 0 ? answer : (await input.decide({
61
+ decide: async (q) => {
62
+ if (conversation) {
63
+ if (fresh) return fresh(q);
64
+ const p = storedAddressing?.addressee.probabilities?.agent;
65
+ if (p === void 0) throw new Error("Stored addressing probability unavailable.");
66
+ return {
67
+ route: "reply",
68
+ diagnostics: {
69
+ model: policy.smart.model,
70
+ latencyMs: 0,
71
+ probabilities: {
72
+ reply: p,
73
+ observe: 1 - p
74
+ },
75
+ addressing: storedAddressing
76
+ },
77
+ router: {
78
+ state,
79
+ questions,
80
+ answer
81
+ }
82
+ };
83
+ }
84
+ if (!state || !questions || !answer || !("choice" in answer)) throw new Error("Stored classifier contract unavailable.");
85
+ const result = input.decide ? (await input.decide({
46
86
  model: policy.smart.model,
47
87
  state,
48
88
  questions,
49
89
  abortSignal: AbortSignal.timeout(Math.ceil(policy.smart.timeoutSeconds * 1e3))
50
- })).answers.route;
90
+ })).answers.route : answer;
51
91
  return {
52
92
  route: result.choice,
53
93
  diagnostics: {
@@ -62,7 +102,7 @@ async function replayRouterPayload(input) {
62
102
  }
63
103
  };
64
104
  },
65
- record: (decision) => decisions.push(decision)
105
+ record: (d) => decisions.push(d)
66
106
  }),
67
107
  decisions
68
108
  };
@@ -1,3 +1,5 @@
1
+ import { type ConversationAnalysis } from "./conversation.js";
2
+ import { type AddressingAnswers } from "./conversation-router.js";
1
3
  import { type GroupPolicy } from "./policy.js";
2
4
  import type { ObservedMessage, PendingConfirmation, RecentMessage } from "./observed.js";
3
5
  import { type MessageAudience, type AgentIdentity as BotIdentity, type AddressingReason, type GroupMessageSignals } from "./signals.js";
@@ -7,6 +9,10 @@ export type Route = "observe" | "reply";
7
9
  /** What the decision model sees. */
8
10
  export interface RouteQuestion {
9
11
  readonly groups?: GroupPolicy;
12
+ readonly conversation?: ConversationAnalysis;
13
+ readonly burstId?: string;
14
+ readonly processingAt?: string;
15
+ readonly messagesToClassify?: ReadonlyArray<ObservedMessage>;
10
16
  readonly signals?: GroupMessageSignals;
11
17
  readonly agentInstructions?: string;
12
18
  /** The agent's own description, so the model knows what it can be asked for. */
@@ -39,6 +45,7 @@ export interface RouteDecision {
39
45
  export interface RouteDiagnostics {
40
46
  readonly model: string;
41
47
  readonly latencyMs: number;
48
+ readonly addressing?: AddressingAnswers;
42
49
  readonly probabilities?: Readonly<Record<Route, number>>;
43
50
  }
44
51
  /** Decides whether a group message not addressed to the bot is still for it. */
@@ -104,6 +111,6 @@ export declare function routeMessage(input: {
104
111
  readonly record?: (decision: RouteDecision) => void;
105
112
  /** Builds the question only when a decision is needed: it reads the agent's description. */
106
113
  readonly question: () => Promise<RouteQuestion>;
107
- readonly beforeDecide?: () => Promise<boolean>;
114
+ readonly beforeDecide?: (direct?: boolean) => Promise<boolean>;
108
115
  readonly decide: RouteDecider;
109
116
  }): Promise<Route>;
@@ -6,6 +6,8 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { DEFAULT_GROUP_POLICY, groupPolicy, overlaySmartPolicy } from "./policy.mjs";
8
8
  import { addressingReason, otherRecipient, signalAudience } from "./signals.mjs";
9
+ import { conversationState, conversationThreshold } from "./conversation.mjs";
10
+ import { conversationDecisionRouter } from "./conversation-router.mjs";
9
11
  import { recordRoutingMetric } from "./health.mjs";
10
12
  import { humanAddressee, humanThread, questionInvitation, restoreEngagement } from "./engagement.mjs";
11
13
  import { boundedRouterPayload, policyHash } from "./record.mjs";
@@ -172,6 +174,7 @@ function conversationContext(question) {
172
174
  }
173
175
  function decisionRouter(input) {
174
176
  return async (question) => {
177
+ if (question.groups?.smart.engagement.policy === "conversation") return conversationDecisionRouter(input.decide)(question);
175
178
  const policy = question.groups?.smart;
176
179
  const started = performance.now();
177
180
  const abortSignal = AbortSignal.timeout(Math.ceil((policy?.timeoutSeconds ?? 15) * 1e3));
@@ -292,6 +295,68 @@ async function routeMessage(input) {
292
295
  });
293
296
  return route;
294
297
  };
298
+ if (groups.smart.engagement.policy === "conversation" && signals !== void 0 && signals.conversation.kind !== "direct") try {
299
+ question = {
300
+ ...await input.question(),
301
+ groups,
302
+ signals
303
+ };
304
+ const analysis = conversationState({
305
+ signals,
306
+ recent: question.recent,
307
+ policy: groups,
308
+ agentNames: [...question.agentIdentity?.aliases ?? [], ...question.agentIdentity?.username ? [question.agentIdentity.username] : []],
309
+ pendingQuestionAt: input.pendingQuestionAt,
310
+ asOf: question.processingAt
311
+ });
312
+ question = {
313
+ ...question,
314
+ conversation: analysis
315
+ };
316
+ payload = {
317
+ ...payload,
318
+ burst_id: question.burstId,
319
+ path: analysis.path,
320
+ conversation: analysis.conversation,
321
+ human_exchange: analysis.human_exchange,
322
+ pending_question_voided: input.pendingQuestionAt !== void 0 && !analysis.pending_question_live,
323
+ question: {
324
+ recent: question.recent,
325
+ pendingQuestions: question.pendingQuestions,
326
+ agentIdentity: question.agentIdentity,
327
+ chat: question.chat,
328
+ processingAt: question.processingAt,
329
+ messagesToClassify: question.messagesToClassify
330
+ }
331
+ };
332
+ if (analysis.path === "A") {
333
+ if (input.beforeDecide && !await input.beforeDecide(true)) return complete("observe", "admission_refused", "Admission refused before direct turn.");
334
+ return complete("reply", addressed && addressed !== "pending-question" ? addressed : "mention", "Agent explicitly addressed.");
335
+ }
336
+ if (analysis.path === "H") return complete("observe", "human_addressee", "Message addresses another participant; conversation and question invitation closed.");
337
+ if (signals.addressing.eligible === false) return complete("observe", "channel_ineligible", "Channel excludes ambient messages.");
338
+ if (groups.mode === "mention") return complete("observe", "mention_policy", "Mention policy observes unaddressed messages.");
339
+ if (input.beforeDecide && !await input.beforeDecide()) return complete("observe", "admission_refused", "Admission refused before inference.");
340
+ const result = await input.decide(question);
341
+ const diagnostics = typeof result === "string" ? void 0 : result.diagnostics;
342
+ const probabilities = diagnostics?.addressing;
343
+ const threshold = conversationThreshold(analysis.path, groups);
344
+ const valid = probabilities !== void 0 && probabilities.addressee.choice === "agent" && (probabilities.addressee.probabilities?.agent ?? NaN) >= threshold && (probabilities.needs_response.probabilities?.true ?? NaN) >= (analysis.path === "B" || analysis.path === "X" ? .7 : .5) && (probabilities.ends_conversation.probabilities?.true ?? NaN) < .7;
345
+ payload = {
346
+ ...payload,
347
+ ...typeof result === "string" ? {} : result.router,
348
+ thresholds_applied: {
349
+ threshold,
350
+ path: analysis.path,
351
+ needs_response: analysis.path === "B" || analysis.path === "X" ? .7 : .5,
352
+ ends_conversation: .7
353
+ }
354
+ };
355
+ return complete(valid ? "reply" : "observe", `decision_model_${valid ? "reply" : "observe"}`, "Conversation addressing probabilities evaluated.", "decision-model", diagnostics);
356
+ } catch (error) {
357
+ console.error("[segmentstream] conversation routing failed", { error });
358
+ return complete("observe", error instanceof Error && error.name === "TimeoutError" ? "decision_model_timeout" : "decision_model_failed", "Conversation routing unavailable; observe fallback.");
359
+ }
295
360
  if (addressed !== void 0 && addressed !== "pending-question" && addressed !== "reply-to-bot") return complete("reply", addressed, `Bot addressed directly: ${addressed}.`);
296
361
  if (input.recipientAnswer && addressed === "reply-to-bot") return complete("reply", "pending-question", "Recipient supplied as the pending question's answer.");
297
362
  const elsewhere = otherRecipient(audience);
@@ -34,6 +34,15 @@ function archivedRoutingMessages(events, limit = 30) {
34
34
  "thread-with-agent",
35
35
  "pending-question"
36
36
  ].includes(event.reason ?? "")).map((event) => [event.messageId, event.reason]));
37
+ const ended = new Set(events.filter((event) => {
38
+ if (event.kind !== "decision" || event.messageId === null) return false;
39
+ try {
40
+ const data = JSON.parse(event.argsSummary ?? "{}");
41
+ return data.router?.conversation_ended === true || data.routing?.conversationEnded === true;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }).map((event) => event.messageId));
37
46
  const membership = new Map();
38
47
  for (const event of [...events].reverse()) {
39
48
  if (event.kind !== "decision" || event.senderId === null) continue;
@@ -45,17 +54,23 @@ function archivedRoutingMessages(events, limit = 30) {
45
54
  const metadata = archivedMetadata(event);
46
55
  const prompt = metadata.confirmation;
47
56
  const decision = prompt?.mode === "deferred" ? deferredStates.get(prompt.requestId) : void 0;
48
- const parent = messages.find((candidate) => candidate.messageId !== null && candidate.messageId === event.replyToMessageId);
49
- const replyTo = metadata.replyTo ?? (event.replyToMessageId === null ? void 0 : {
57
+ const replyMessageId = metadata.replyTo?.messageId ?? event.replyToMessageId;
58
+ const parent = messages.find((candidate) => candidate.messageId !== null && candidate.messageId === replyMessageId);
59
+ const recordedReply = metadata.replyTo ?? (event.replyToMessageId === null ? void 0 : {
50
60
  messageId: event.replyToMessageId,
51
61
  kind: parent === void 0 ? "unknown" : parent.kind === "outbound" ? "bot" : parent.senderIsBot ? "other_bot" : "human",
52
62
  ...parent?.senderId == null ? {} : { id: parent.senderId },
53
63
  ...parent?.senderName == null ? {} : { name: parent.senderName }
54
64
  });
65
+ const replyTo = recordedReply !== void 0 && parent?.kind === "outbound" && recordedReply.messageId === parent.messageId ? {
66
+ ...recordedReply,
67
+ kind: "bot"
68
+ } : recordedReply;
55
69
  const derivedText = metadata.decoded?.flatMap((item) => item.content === void 0 ? [] : [item.content]).join("\n");
56
70
  const text = (event.text || derivedText || (metadata.media ? "" : "[attachment or service message]")).slice(0, 2e3);
57
71
  const common = {
58
72
  invitation: metadata.invitation ?? invitations.get(event.messageId ?? ""),
73
+ ...ended.has(event.messageId) ? { conversationEnded: true } : {},
59
74
  author: event.senderName ?? event.senderId ?? "unknown sender",
60
75
  text,
61
76
  ...metadata.media === void 0 ? {} : { media: metadata.media },
@@ -13,10 +13,11 @@ import { decisionRouter } from "../group-routing/router.mjs";
13
13
  import { runtimeToken } from "../runtime-token.mjs";
14
14
  import { groupSettings } from "../group-routing/settings.mjs";
15
15
  import { conversations } from "../conversations.mjs";
16
- import { t as agentBuild } from "../../../_chunks/build-metadata-DMD3azjO.mjs";
16
+ import { archivedRoutingMessages } from "../group-routing/routing-context.mjs";
17
+ import { t as agentBuild } from "../../../_chunks/build-metadata-BD1PqnN9.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-B8Eyjz1O.mjs";
20
+ 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-BrWspFw5.mjs";
20
21
  import { attachmentLifecycle } from "./lifecycle.mjs";
21
22
  import { scopedAddress, sessionPolicy } from "./sessions.mjs";
22
23
  import { observedMessages } from "./observed.mjs";
@@ -175,6 +176,13 @@ function segmentstreamTelegram(options) {
175
176
  policy: settings().policy,
176
177
  decisionModel: options.models().decision,
177
178
  groups: options.groups?.(),
179
+ recentConversation: async (chatId, threadId) => archivedRoutingMessages((await archive.context({
180
+ provider: "telegram",
181
+ chatId,
182
+ ...threadId === void 0 ? {} : { threadId },
183
+ limit: 200,
184
+ includeDecisions: true
185
+ })).events, 100),
178
186
  cloudGroups: options.groups === void 0 ? void 0 : readGroups,
179
187
  signalSettings: settings().groups,
180
188
  recoverHeldApprovals: options.confirmationMode?.() === "deferred",
@@ -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-B8Eyjz1O.mjs";
7
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.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";
@@ -10,7 +10,7 @@ import { runtimeToken } from "../runtime-token.mjs";
10
10
  import { redactDiagnostic } from "../diagnostics.mjs";
11
11
  import { confirmationLocale } from "./confirmation-text.mjs";
12
12
  import { inTelegramSendQueue, telegramSendScope } from "./send-queue.mjs";
13
- import { c as customerCopy, f as formattingRefused, l as customerMessage, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
13
+ import { c as customerCopy, f as formattingRefused, l as customerMessage, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.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";
@@ -8,7 +8,7 @@ import { proxyEnvironment } from "../environment.mjs";
8
8
  import { runtimeToken } from "../runtime-token.mjs";
9
9
  import { conversations } from "../conversations.mjs";
10
10
  import { telegramSendScope } from "./send-queue.mjs";
11
- import { m as safeTelegramFetch, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
11
+ import { m as safeTelegramFetch, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
12
12
  import { deferredConfirmations } from "../deferred-confirmations.mjs";
13
13
  import { expireDeferredRecord } from "./deferred-confirmations.mjs";
14
14
  import { connectionProxy } from "../connection-proxy.mjs";
@@ -10,7 +10,7 @@ import { conversationEvent } from "../conversations.mjs";
10
10
  import { humanText } from "../confirmation-description.mjs";
11
11
  import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
12
12
  import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
13
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
13
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
14
14
  import { chatPostOperationId, isChatPost } from "../chat-post-confirmation.mjs";
15
15
  import { confirmations } from "../confirmations.mjs";
16
16
  import { formatAddress, scopedAddress } from "./sessions.mjs";
@@ -7,7 +7,7 @@ __eveCreateRequire(import.meta.url);
7
7
  import { currentConfirmationPrompt, observedChatKey } from "../group-routing/observed.mjs";
8
8
  import { conversationEvent } from "../conversations.mjs";
9
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";
10
+ import { n as currentInboundRequest, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
11
11
  import { contentShape, messageContent } from "./content.mjs";
12
12
  import { messageMetadata } from "./observed.mjs";
13
13
  import { reportMembership } from "./membership.mjs";
@@ -5,5 +5,5 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { isTechnicalText } from "../customer-text-safety.mjs";
8
- import { a as TelegramDeliveryError, c as customerCopy, d as failureText, f as formattingRefused, h as withDeliveryLocale, l as customerMessage, m as safeTelegramFetch, o as currentLocale, p as reportTelegramError, s as currentThreadId, u as customerText } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
8
+ import { a as TelegramDeliveryError, c as customerCopy, d as failureText, f as formattingRefused, h as withDeliveryLocale, l as customerMessage, m as safeTelegramFetch, o as currentLocale, p as reportTelegramError, s as currentThreadId, u as customerText } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
9
9
  export { TelegramDeliveryError, currentLocale, currentThreadId, customerCopy, customerMessage, customerText, failureText, formattingRefused, isTechnicalText, reportTelegramError, safeTelegramFetch, withDeliveryLocale };
@@ -10,7 +10,7 @@ import { conversationEvent } from "../conversations.mjs";
10
10
  import { humanText } from "../confirmation-description.mjs";
11
11
  import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
12
12
  import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
13
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
13
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
14
14
  import { CONFIRMATION_TTL_MS, inputHash } from "../confirmations.mjs";
15
15
  import { OntologyToolRejected } from "../ontology-tools.mjs";
16
16
  import { confirmationOutcome } from "../confirmation-outcome.mjs";
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { conversationLanguage } from "./principal.mjs";
8
- import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
8
+ import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
9
9
  import { describableImage, describeReceivedImage } from "./images.mjs";
10
10
  import { MAXIMUM_ATTACHMENT_BYTES, attachmentUrl } from "../attachments.mjs";
11
11
  function telegramConversation(chatId) {
@@ -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-DMD3azjO.mjs";
7
+ import { t as agentBuild } from "../../../_chunks/build-metadata-BD1PqnN9.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";
@@ -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-B8Eyjz1O.mjs";
7
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
8
8
  import { gateway, generateText } from "ai";
9
9
  const MAXIMUM_IMAGE_DESCRIPTION_BYTES = 5242880;
10
10
  const MAXIMUM_NATIVE_IMAGE_BYTES = 3145728;
@@ -30,6 +30,8 @@ export declare class InboundRequest {
30
30
  readonly agentDescription: () => Promise<string>;
31
31
  readonly agentName: () => Promise<string>;
32
32
  readonly traceId: `${string}-${string}-${string}-${string}-${string}`;
33
+ /** Conversation policy coalesces only the active caller; Eve queues other callers. */
34
+ turnPolicy: "queue" | "steer";
33
35
  edited: boolean;
34
36
  triggeringMessageId: string | undefined;
35
37
  chatId: string | undefined;
@@ -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 { i as withReplacedText, n as currentInboundRequest, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
7
+ import { i as withReplacedText, n as currentInboundRequest, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
8
8
  export { InboundRequest, currentInboundRequest, runInboundRequest, withReplacedText };
@@ -1,3 +1,4 @@
1
+ import type { RecentMessage } from "../group-routing/observed.js";
1
2
  import type { CloudGroupSettings } from "../group-routing/settings.js";
2
3
  import { type GroupPolicy } from "../group-routing/policy.js";
3
4
  import type { TelegramSettings } from "../../config.js";
@@ -44,6 +45,7 @@ export interface InboundDependencies {
44
45
  readonly policy: TelegramPolicy;
45
46
  readonly decisionModel?: string;
46
47
  readonly groups?: GroupPolicy;
48
+ readonly recentConversation?: (chatId: string, threadId?: string) => Promise<ReadonlyArray<RecentMessage>>;
47
49
  readonly cloudGroups?: () => Promise<CloudGroupSettings | undefined>;
48
50
  readonly signalSettings?: TelegramSettings["groups"];
49
51
  /** Recover old held sessions only when the workspace has chosen non-blocking confirmations. */