@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
@@ -7,10 +7,12 @@ __eveCreateRequire(import.meta.url);
7
7
  import { effectiveGroupPolicy, groupPolicy } from "../group-routing/policy.mjs";
8
8
  import { conversationLanguage, telegramPrincipal } from "./principal.mjs";
9
9
  import { addressingReason, conversationKey, otherRecipient } from "../group-routing/signals.mjs";
10
+ import { conversationAddressing, conversationState } from "../group-routing/conversation.mjs";
10
11
  import { questionInvitation } from "../group-routing/engagement.mjs";
11
12
  import { conversationContext, routeMessage } from "../group-routing/router.mjs";
12
13
  import { observedContext } from "../group-routing/observed.mjs";
13
- import { p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
14
+ import { debounceBurst, routingBurst } from "../group-routing/burst.mjs";
15
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
14
16
  import { startTypingHeartbeat, typingUntilComplete } from "./lifecycle.mjs";
15
17
  import { formatAddress, messageAddress, scopedAddress } from "./sessions.mjs";
16
18
  import { contentShape, messageContent } from "./content.mjs";
@@ -453,6 +455,19 @@ async function handleInboundMessage(input) {
453
455
  mode: dependencies.policy,
454
456
  model: dependencies.decisionModel
455
457
  }), conversationKey(policySignals), registryChat?.scope !== void 0 && registryChat.scope !== policySignals.conversation.scope ? void 0 : registryChat?.routing, cloudGroups?.settings);
458
+ const conversationPolicy = group && groups.smart.engagement.policy === "conversation";
459
+ const agentAliases = [...groups.smart.engagement.agentAliases, ...[
460
+ bot?.username,
461
+ bot?.firstName,
462
+ bot?.displayName
463
+ ].filter((n) => !!n)];
464
+ const freshConversation = async () => dependencies.recentConversation ? dependencies.recentConversation(sent.chat.id, sent.messageThreadId === void 0 ? void 0 : String(sent.messageThreadId)) : dependencies.observed.recent(chat);
465
+ let conversationRecent = conversationPolicy ? await freshConversation() : dependencies.observed.recent(chat);
466
+ if (conversationPolicy && input.request && input.request.lifecycleKey === void 0) {
467
+ address = topicAddress;
468
+ input.request.address = topicAddress;
469
+ input.request.turnPolicy = "steer";
470
+ }
456
471
  const pending = questionFromHistory(questionHistory, questionOwner);
457
472
  let answering = pending !== void 0 && (input.request?.lifecycleKey === void 0 || pending.taskId === input.request.lifecycleKey) && pending.memberId === member.id && pending.chatId === sent.chat.id && pending.messageThreadId === String(sent.messageThreadId ?? "");
458
473
  const asked = questionHistory.findLast((event) => {
@@ -463,12 +478,21 @@ async function handleInboundMessage(input) {
463
478
  });
464
479
  const questionAge = Date.parse(sentAt(sent)) - Date.parse(asked?.meta.at ?? "");
465
480
  if (answering && addressed === void 0 && !questionInvitation(asked?.meta.at, sentAt(sent), groups.smart.engagement.openQuestionMinutes)) answering = false;
466
- const recipientAnswer = answering && (groups.smart.engagement.policy === "engaged" || questionAge >= 0 && questionAge <= groups.smart.engagement.followUpMinutes * 6e4) && audience.replyTo?.kind === "bot" && isRecipientAnswer(audience);
467
- if (answering && pending !== void 0 && input.request !== void 0) {
481
+ if (conversationPolicy && answering) {
482
+ if (!conversationState({
483
+ signals: policySignals,
484
+ recent: conversationRecent,
485
+ policy: groups,
486
+ agentNames: agentAliases,
487
+ pendingQuestionAt: asked?.meta.at
488
+ }).pending_question_live) answering = false;
489
+ }
490
+ const recipientAnswer = !conversationPolicy && answering && (groups.smart.engagement.policy === "engaged" || questionAge >= 0 && questionAge <= groups.smart.engagement.followUpMinutes * 6e4) && audience.replyTo?.kind === "bot" && isRecipientAnswer(audience);
491
+ if (!conversationPolicy && answering && pending !== void 0 && input.request !== void 0) {
468
492
  address = pending.address || (questionSession === void 0 ? topicAddress : memberQuestionAddress);
469
493
  input.request.address = address;
470
494
  }
471
- if (input.request?.lifecycleKey === void 0 && group && (addressed === void 0 && !answering && groups.mode === "mention" || elsewhere !== void 0 && (addressed === void 0 || addressed === "reply-to-bot" && !recipientAnswer))) {
495
+ if (input.request?.lifecycleKey === void 0 && group && (addressed === void 0 && !answering && groups.mode === "mention" || !conversationPolicy && elsewhere !== void 0 && (addressed === void 0 || addressed === "reply-to-bot" && !recipientAnswer))) {
472
496
  await recordInboundContent({
473
497
  text,
474
498
  decoded
@@ -480,7 +504,7 @@ async function handleInboundMessage(input) {
480
504
  });
481
505
  return null;
482
506
  }
483
- if (hasContent && answering && !await admitTurn(true)) {
507
+ if (!conversationPolicy && hasContent && answering && !await admitTurn(true)) {
484
508
  await observeRaw();
485
509
  return null;
486
510
  }
@@ -529,7 +553,7 @@ async function handleInboundMessage(input) {
529
553
  address,
530
554
  operations,
531
555
  read: dependencies.history ?? dependencies.readHistory,
532
- remembered: dependencies.observed.recent(chat),
556
+ remembered: conversationPolicy ? conversationRecent : dependencies.observed.recent(chat),
533
557
  at: sentAt(sent),
534
558
  questionHistory,
535
559
  questionSessionId: owner?.id
@@ -539,7 +563,8 @@ async function handleInboundMessage(input) {
539
563
  name,
540
564
  bot?.displayName,
541
565
  bot?.firstName,
542
- bot?.username
566
+ bot?.username,
567
+ ...groups.smart.engagement.agentAliases
543
568
  ].filter((alias) => alias !== void 0 && alias !== ""))].slice(0, 8).map((alias) => alias.slice(0, 128));
544
569
  question = {
545
570
  groups,
@@ -558,7 +583,7 @@ async function handleInboundMessage(input) {
558
583
  aliases
559
584
  },
560
585
  chat: group ? chatContext(dependencies.chats.chat(sent.chat.id)) : [],
561
- recent: context.recent,
586
+ recent: conversationPolicy ? conversationRecent : context.recent,
562
587
  pendingConfirmations: context.pendingConfirmations,
563
588
  pendingQuestions: context.pendingQuestions.filter((question) => question.chatId === sent.chat.id && question.messageThreadId === String(sent.messageThreadId ?? "")),
564
589
  message: observedMessage(sent, text, member, media, bot),
@@ -567,6 +592,48 @@ async function handleInboundMessage(input) {
567
592
  };
568
593
  return question;
569
594
  };
595
+ let burstId;
596
+ if (conversationPolicy && input.request?.lifecycleKey === void 0) {
597
+ if (voice !== void 0) await transcribeVoice(true);
598
+ const routingSignals = {
599
+ ...policySignals,
600
+ message: {
601
+ ...policySignals.message,
602
+ text
603
+ }
604
+ };
605
+ const evidence = conversationAddressing(routingSignals, conversationRecent, groups, agentAliases);
606
+ if (!evidence.agent_named && !evidence.reply_to_agent && evidence.human_targets.length === 0) {
607
+ await recordInboundContent({
608
+ text,
609
+ decoded
610
+ });
611
+ const refreshed = await debounceBurst({
612
+ signals: routingSignals,
613
+ policy: groups,
614
+ read: freshConversation
615
+ });
616
+ conversationRecent = refreshed.recent;
617
+ question = void 0;
618
+ if (refreshed.burst.superseded) {
619
+ recordGateDecision("burst_superseded");
620
+ return null;
621
+ }
622
+ }
623
+ const burst = routingBurst(routingSignals, conversationRecent, groups);
624
+ burstId = burst.id;
625
+ const q = await conversation();
626
+ question = {
627
+ ...q,
628
+ signals: routingSignals,
629
+ message: {
630
+ ...q.message,
631
+ text
632
+ },
633
+ burstId: burst.id,
634
+ messagesToClassify: burst.messages
635
+ };
636
+ }
570
637
  const route = input.request?.lifecycleKey !== void 0 ? "reply" : await routeMessage({
571
638
  chatId: sent.chat.id,
572
639
  memberId: member.id,
@@ -574,6 +641,10 @@ async function handleInboundMessage(input) {
574
641
  groups,
575
642
  signals: {
576
643
  ...policySignals,
644
+ message: {
645
+ ...policySignals.message,
646
+ text
647
+ },
577
648
  sender: {
578
649
  ...policySignals.sender,
579
650
  member
@@ -586,7 +657,7 @@ async function handleInboundMessage(input) {
586
657
  record: (decision) => {
587
658
  if (decision.reason !== "admission_refused") recordRouteDecision(decision.route, addressed, groups.mode, decision);
588
659
  },
589
- beforeDecide: () => admitTurn(false),
660
+ beforeDecide: (direct) => admitTurn(direct ?? false),
590
661
  decide: dependencies.decide,
591
662
  question: async () => {
592
663
  classified = true;
@@ -631,6 +702,19 @@ async function handleInboundMessage(input) {
631
702
  decoded,
632
703
  ...processedMedia === void 0 ? {} : { media: processedMedia }
633
704
  });
705
+ if (conversationPolicy) {
706
+ const current = await conversation();
707
+ const message = {
708
+ ...current.message,
709
+ text,
710
+ media
711
+ };
712
+ question = {
713
+ ...current,
714
+ message,
715
+ messagesToClassify: current.messagesToClassify?.map((m) => m.messageId === message.messageId ? message : m)
716
+ };
717
+ }
634
718
  return conversation();
635
719
  }
636
720
  });
@@ -810,7 +894,7 @@ async function handleInboundMessage(input) {
810
894
  }
811
895
  if (voice !== void 0 && input.request !== void 0) input.request.text = text;
812
896
  else if (voice !== void 0) notes.push(text);
813
- if (answering && pending !== void 0 && input.request !== void 0) {
897
+ if (!conversationPolicy && answering && pending !== void 0 && input.request !== void 0) {
814
898
  input.request.replyTo = pending.replyToMessageId ?? input.request.replyTo;
815
899
  input.request.lifecycleKey = pending.taskId ?? input.request.lifecycleKey;
816
900
  input.request.text = `${answerMarker(pending.id)}\n${text}`;
@@ -868,7 +952,7 @@ async function handleInboundMessage(input) {
868
952
  return null;
869
953
  }
870
954
  dependencies.observed.remember(chat, observedMessage(sent, text, member, retainedMedia, bot));
871
- const principal = telegramPrincipal({
955
+ let principal = telegramPrincipal({
872
956
  message: {
873
957
  ...sent,
874
958
  text
@@ -876,6 +960,32 @@ async function handleInboundMessage(input) {
876
960
  member,
877
961
  conversationLanguage: language
878
962
  });
963
+ if (conversationPolicy && input.request?.lifecycleKey === void 0) principal = {
964
+ ...principal,
965
+ attributes: {
966
+ ...principal.attributes,
967
+ groupRouting: JSON.stringify({
968
+ policy: {
969
+ ...groups,
970
+ chats: {}
971
+ },
972
+ signals: {
973
+ ...policySignals,
974
+ message: {
975
+ ...policySignals.message,
976
+ text
977
+ }
978
+ },
979
+ agent: question?.agent.slice(0, 600) ?? "",
980
+ agentIdentity: question?.agentIdentity,
981
+ chat: question?.chat,
982
+ burst_id: burstId ?? routingBurst(policySignals, conversationRecent, groups).id,
983
+ message: question?.message,
984
+ pendingQuestions: question?.pendingQuestions,
985
+ pendingQuestionAt: asked?.meta.at
986
+ })
987
+ }
988
+ };
879
989
  return {
880
990
  auth: answering && pending !== void 0 ? {
881
991
  ...principal,
@@ -923,6 +1033,7 @@ async function handleInboundMessage(input) {
923
1033
  group
924
1034
  }),
925
1035
  ...processedMedia === void 0 ? [] : [processedMedia],
1036
+ ...conversationPolicy ? ["If this member declines your involvement or closes the conversation, output exactly [SILENT]. Do not acknowledge the rejection or perform actions."] : [],
926
1037
  ...notes
927
1038
  ]
928
1039
  };
@@ -4,9 +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 { t as agentBuild } from "../../../_chunks/build-metadata-DMD3azjO.mjs";
7
+ import { t as agentBuild } from "../../../_chunks/build-metadata-BD1PqnN9.mjs";
8
8
  import { object } from "../confirmation-description.mjs";
9
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
9
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
10
10
  import { needsConfirmation } from "../confirmations.mjs";
11
11
  import { actionToolName, ontologyTools } from "../ontology-tools.mjs";
12
12
  function attachmentLifecycle(options) {
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { DEFAULT_IMAGE_DESCRIPTION_MODEL } from "../../config.mjs";
8
- import { p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
8
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
9
9
  function planMedia(capabilities, descriptionModel = null) {
10
10
  if (typeof descriptionModel === "string") return {
11
11
  images: "describe",
@@ -9,7 +9,7 @@ import { agentMessage, observedChatKey } from "../group-routing/observed.mjs";
9
9
  import { confirmationLocale } from "./confirmation-text.mjs";
10
10
  import { splitTelegramText } from "./format.mjs";
11
11
  import { inTelegramSendQueue } from "./send-queue.mjs";
12
- import { a as TelegramDeliveryError, l as customerMessage, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
12
+ import { a as TelegramDeliveryError, l as customerMessage, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
13
13
  const SILENT_MARKERS = new Set(["[silent]", "no_reply"]);
14
14
  function isSilentReply(text) {
15
15
  return SILENT_MARKERS.has(text.trim().toLowerCase());
@@ -6,7 +6,7 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { memberIdOf } from "./principal.mjs";
8
8
  import { confirmationLocale } from "./confirmation-text.mjs";
9
- import { c as customerCopy, d as failureText, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-B8Eyjz1O.mjs";
9
+ import { c as customerCopy, d as failureText, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-BrWspFw5.mjs";
10
10
  const telegramFailureEvents = {
11
11
  async "turn.cancelled"(event, channel, context) {
12
12
  const errorId = reportTelegramError("turn_cancelled", event, {
@@ -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 "../connection-proxy.mjs";
9
9
  import { gateway, transcribe } from "ai";
10
10
  const LABELS = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@segmentstream/agent",
3
- "version": "0.9.1",
3
+ "version": "0.10.1",
4
4
  "description": "Mount a SegmentStream workspace's agent on eve: the ontology as tools, acting as the member who writes, and Telegram through the workspace's connection.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "SegmentStream",
@@ -62,7 +62,7 @@
62
62
  },
63
63
  "dependencies": {
64
64
  "@chat-adapter/telegram": "4.41.0",
65
- "@segmentstream-cloud/ontology": "0.43.1",
65
+ "@segmentstream-cloud/ontology": "0.44.1",
66
66
  "@vercel/oidc": "^3.8.4",
67
67
  "ai": "^7.0.128",
68
68
  "csv-parse": "^7.0.3",