@segmentstream/agent 0.14.0 → 0.15.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 (53) hide show
  1. package/README.md +7 -1
  2. package/dist/_chunks/{build-metadata-BB2uSGsI.mjs → build-metadata-DKb_DN2g.mjs} +1 -1
  3. package/dist/_chunks/{inbound-request-BXhiIph-.mjs → inbound-request-RIRNBxUC.mjs} +3 -0
  4. package/dist/_chunks/{principal-VFQWqe5S.mjs → principal-MEMlG3EG.mjs} +1 -1
  5. package/dist/extension/config.d.ts +6 -0
  6. package/dist/extension/config.mjs +31 -1
  7. package/dist/extension/hooks/authorization.mjs +1 -1
  8. package/dist/extension/lib/attachment-tools.mjs +1 -1
  9. package/dist/extension/lib/build-metadata.mjs +1 -1
  10. package/dist/extension/lib/confirmations.mjs +1 -1
  11. package/dist/extension/lib/conversation-runtime.mjs +1 -1
  12. package/dist/extension/lib/deferred-confirmations.mjs +1 -1
  13. package/dist/extension/lib/ontology-connection.mjs +1 -1
  14. package/dist/extension/lib/ontology-gateway.mjs +1 -1
  15. package/dist/extension/lib/ontology-metadata-read.mjs +1 -1
  16. package/dist/extension/lib/ontology-tools.d.ts +2 -0
  17. package/dist/extension/lib/ontology-tools.mjs +2 -1
  18. package/dist/extension/lib/runtime-envelope.mjs +1 -1
  19. package/dist/extension/lib/stored-files.mjs +1 -1
  20. package/dist/extension/lib/telegram/adapter.mjs +23 -4
  21. package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
  22. package/dist/extension/lib/telegram/attachments-send.mjs +2 -2
  23. package/dist/extension/lib/telegram/callbacks.mjs +3 -3
  24. package/dist/extension/lib/telegram/confirmation-expiry.mjs +1 -1
  25. package/dist/extension/lib/telegram/confirmations.mjs +3 -3
  26. package/dist/extension/lib/telegram/conversations.d.ts +3 -0
  27. package/dist/extension/lib/telegram/conversations.mjs +57 -12
  28. package/dist/extension/lib/telegram/customer-text.mjs +1 -1
  29. package/dist/extension/lib/telegram/deferred-confirmations.mjs +3 -3
  30. package/dist/extension/lib/telegram/files.mjs +2 -2
  31. package/dist/extension/lib/telegram/health.mjs +1 -1
  32. package/dist/extension/lib/telegram/images.mjs +1 -1
  33. package/dist/extension/lib/telegram/inbound-request.d.ts +7 -0
  34. package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
  35. package/dist/extension/lib/telegram/inbound.d.ts +5 -0
  36. package/dist/extension/lib/telegram/inbound.mjs +104 -14
  37. package/dist/extension/lib/telegram/lifecycle.mjs +3 -3
  38. package/dist/extension/lib/telegram/media-policy.mjs +1 -1
  39. package/dist/extension/lib/telegram/principal.mjs +1 -1
  40. package/dist/extension/lib/telegram/silent.mjs +2 -2
  41. package/dist/extension/lib/telegram/structured-settings.d.ts +6 -0
  42. package/dist/extension/lib/telegram/structured-settings.mjs +12 -0
  43. package/dist/extension/lib/telegram/structured.d.ts +28 -0
  44. package/dist/extension/lib/telegram/structured.mjs +114 -0
  45. package/dist/extension/lib/telegram/turn-errors.mjs +2 -2
  46. package/dist/extension/lib/telegram/voice.mjs +1 -1
  47. package/dist/extension/lib/telegram/workspace-action.d.ts +3 -0
  48. package/dist/extension/lib/telegram/workspace-action.mjs +8 -2
  49. package/dist/extension/model.mjs +1 -1
  50. package/dist/extension/tools/attachments_promote.mjs +1 -1
  51. package/dist/extension/tools/ontology.mjs +1 -1
  52. package/dist/extension/tools/questions_ask.mjs +1 -1
  53. package/package.json +2 -2
package/README.md CHANGED
@@ -549,7 +549,7 @@ Eve resolution, so member/topic routing survives a cold start. No second provide
549
549
 
550
550
  ## Release and migration
551
551
 
552
- The coordinated release uses Agent SDK 0.14.0, Eve 0.76.3, Ontology SDK 0.50.0 and App SDK 0.24.1.
552
+ The coordinated release uses Agent SDK 0.15.1, Eve 0.76.3, Ontology SDK 0.51.0 and App SDK 0.24.1.
553
553
  The compatible Cloud archive/API must be deployed first; migrations run only through its CI/CD gate.
554
554
  Publish the ontology SDK before the agent SDK. Upgrade the workspace ontology before its agent,
555
555
  with the declared Telegram provider mapping and explicit `agent_chat:post_message` grant.
@@ -651,3 +651,9 @@ reports the effective confirmation mode and attachment-lifecycle presence behind
651
651
  runtime authentication; source pins and public health alone are not settings-adoption proof.
652
652
 
653
653
  Telegram 0.13.0 requires workspace-authored pairing and confirmation text. See [workspace Telegram text](../../docs/agent.md#workspace-telegram-text) for keys, limits, neutral fallbacks and unsupported Eve buttons.
654
+
655
+ Workspace [callback actions](../../docs/agent.md#workspace-callback-actions) and
656
+ [structured Telegram input](../../docs/agent.md#structured-telegram-input) are separate opt-in
657
+ mappings. They require the ontology runtime-source capability and dispatch only a currently
658
+ permitted routine action as the verified member. The workspace owns callback tokens, presentation
659
+ and business idempotency.
@@ -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
- var version = "0.14.0";
7
+ var version = "0.15.1";
8
8
  function agentBuild(environment = process.env) {
9
9
  return {
10
10
  agent: version,
@@ -256,6 +256,9 @@ var InboundRequest = class {
256
256
  claimTurn;
257
257
  beginDispatch;
258
258
  finishClaim;
259
+ structuredContext;
260
+ recordStructuredContext;
261
+ beginStructuredContinuation;
259
262
  locale;
260
263
  threadId;
261
264
  text;
@@ -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 { n as currentInboundRequest } from "./inbound-request-BXhiIph-.mjs";
7
+ import { n as currentInboundRequest } from "./inbound-request-RIRNBxUC.mjs";
8
8
  import { randomUUID } from "node:crypto";
9
9
  function telegramRuntimeSource(message, files, callbackQueryId) {
10
10
  const attachments = [];
@@ -1,5 +1,6 @@
1
1
  import { type GroupPolicyInput } from "@segmentstream-cloud/ontology/groups";
2
2
  import { type GroupPolicy } from "./lib/group-routing/policy.js";
3
+ import { type StructuredInbound } from "./lib/telegram/structured-settings.js";
3
4
  import type { WorkspaceActionHook } from "./lib/telegram/workspace-action.js";
4
5
  import { type TelegramTexts } from "./lib/telegram/texts.js";
5
6
  import type { AttachmentLifecycle } from "./lib/telegram/lifecycle.js";
@@ -76,6 +77,10 @@ export interface SegmentStreamAgentConfigInput {
76
77
  readonly linkPreviews?: string;
77
78
  /** Additional exact HTTP(S) origins belonging to this workspace. */
78
79
  readonly additionalOwnOrigins?: readonly string[];
80
+ readonly inbound?: Omit<StructuredInbound, "contextVersion" | "kinds"> & {
81
+ readonly kinds: ReadonlyArray<string>;
82
+ readonly contextVersion: number;
83
+ };
79
84
  readonly callbacks?: Omit<WorkspaceActionHook, "contextVersion"> & {
80
85
  readonly contextVersion: number;
81
86
  };
@@ -138,6 +143,7 @@ export interface TelegramSettings {
138
143
  readonly topicScope?: boolean;
139
144
  readonly commandsAddress?: boolean;
140
145
  };
146
+ readonly inbound?: StructuredInbound;
141
147
  readonly callbacks?: WorkspaceActionHook;
142
148
  readonly connection: string;
143
149
  readonly policy: TelegramPolicy;
@@ -6,6 +6,7 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { effectiveGroupPolicy, groupPolicy } from "./lib/group-routing/policy.mjs";
8
8
  import { localizedText as localizedText$1 } from "./lib/admission.mjs";
9
+ import { STRUCTURED_KINDS } from "./lib/telegram/structured-settings.mjs";
9
10
  import { TELEGRAM_TEXT_KEYS } from "./lib/telegram/texts.mjs";
10
11
  import { isTechnicalText } from "./lib/customer-text-safety.mjs";
11
12
  import { readFileSync, realpathSync } from "node:fs";
@@ -80,7 +81,8 @@ function telegramSettings(value, issues) {
80
81
  "additionalOwnOrigins",
81
82
  "attachmentLifecycle",
82
83
  "menuButton",
83
- "callbacks"
84
+ "callbacks",
85
+ "inbound"
84
86
  ],
85
87
  issues
86
88
  });
@@ -123,6 +125,30 @@ function telegramSettings(value, issues) {
123
125
  message: "must be an array of HTTP(S) origins without paths, credentials, queries or fragments",
124
126
  path: [...path, "additionalOwnOrigins"]
125
127
  });
128
+ const inboundConfig = section({
129
+ value: telegram.inbound,
130
+ path: [...path, "inbound"],
131
+ allowed: [
132
+ "entity",
133
+ "action",
134
+ "kinds",
135
+ "contextVersion"
136
+ ],
137
+ issues
138
+ });
139
+ const inbound = inboundConfig === void 0 ? void 0 : workspaceHook({
140
+ entity: inboundConfig.entity,
141
+ action: inboundConfig.action,
142
+ contextVersion: inboundConfig.contextVersion
143
+ }, [...path, "inbound"], issues);
144
+ if (inboundConfig !== void 0 && (!Array.isArray(inboundConfig.kinds) || inboundConfig.kinds.length === 0 || inboundConfig.kinds.length > 3 || new Set(inboundConfig.kinds).size !== inboundConfig.kinds.length || !inboundConfig.kinds.every((kind) => STRUCTURED_KINDS.includes(kind)))) issues.push({
145
+ message: "must be distinct location, venue or contact kinds",
146
+ path: [
147
+ ...path,
148
+ "inbound",
149
+ "kinds"
150
+ ]
151
+ });
126
152
  const callbacks = workspaceHook(telegram.callbacks, [...path, "callbacks"], issues);
127
153
  const menuButton = section({
128
154
  value: telegram.menuButton,
@@ -162,6 +188,10 @@ function telegramSettings(value, issues) {
162
188
  policy,
163
189
  ...signalSettings === void 0 ? {} : { groups: signalSettings },
164
190
  ...callbacks === void 0 ? {} : { callbacks },
191
+ ...inbound === void 0 ? {} : { inbound: {
192
+ ...inbound,
193
+ kinds: inboundConfig.kinds
194
+ } },
165
195
  linkPreviews,
166
196
  additionalOwnOrigins,
167
197
  ...menuText === void 0 ? {} : { menuButton: { text: menuText } },
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { localizedText } from "../lib/admission.mjs";
8
- import "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { confirmationLocale } from "../lib/telegram/confirmation-text.mjs";
10
10
  import segmentstream from "../extension.mjs";
11
11
  import { defineHook } from "eve/hooks";
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { appOrigin } from "./environment.mjs";
8
- import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { i as memberIdOf } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { runtimeToken } from "./runtime-token.mjs";
10
10
  import { agentAttachments } from "./attachments.mjs";
11
11
  import { telegramConversation } from "./telegram/files.mjs";
@@ -4,5 +4,5 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { t as agentBuild } from "../../_chunks/build-metadata-BB2uSGsI.mjs";
7
+ import { t as agentBuild } from "../../_chunks/build-metadata-DKb_DN2g.mjs";
8
8
  export { agentBuild };
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { withTelegramTexts } from "./telegram/texts.mjs";
8
- import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { i as memberIdOf } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { confirmationCopy, confirmationLocale, renderConfirmation } from "./telegram/confirmation-text.mjs";
10
10
  import { chatPostCard } from "./telegram/chat-post-card.mjs";
11
11
  import { chatPostDigest, isChatPost } from "./chat-post-confirmation.mjs";
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { ENDS_CONVERSATION_INSTRUCTIONS } from "./group-routing/conversation-prompt.mjs";
8
- import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { i as memberIdOf } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { n as contentText, t as CONTENT_CAPS } from "../../_chunks/content-CvFsrmSD.mjs";
10
10
  import { conversationEvent, conversations, summarizeArguments } from "./conversations.mjs";
11
11
  import { parseAddress } from "./telegram/sessions.mjs";
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { appOrigin } from "./environment.mjs";
8
- import { i as memberIdOf, l as principalRuntimeSource, u as runtimeEnvelope } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { i as memberIdOf, l as principalRuntimeSource, u as runtimeEnvelope } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { redactDiagnostic } from "./diagnostics.mjs";
10
10
  import { humanText, object } from "./confirmation-description.mjs";
11
11
  import { runtimeToken } from "./runtime-token.mjs";
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { appOrigin } from "./environment.mjs";
8
- import { c as compatibleRuntimeEnvelope, i as memberIdOf, r as identityProviderOf, u as runtimeEnvelope } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { c as compatibleRuntimeEnvelope, i as memberIdOf, r as identityProviderOf, u as runtimeEnvelope } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { runtimeToken, tokenExpiry } from "./runtime-token.mjs";
10
10
  import { CHAT_POST_ENVELOPE, chatPostDigest, chatPostOperationId, isChatPost } from "./chat-post-confirmation.mjs";
11
11
  import { actionApproval, confirmations } from "./confirmations.mjs";
@@ -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 { i as memberIdOf, u as runtimeEnvelope } from "../../_chunks/principal-VFQWqe5S.mjs";
7
+ import { i as memberIdOf, u as runtimeEnvelope } from "../../_chunks/principal-MEMlG3EG.mjs";
8
8
  import { object } from "./confirmation-description.mjs";
9
9
  import { readOntologyMetadata } from "./ontology-metadata-read.mjs";
10
10
  async function ontologyMetadata(memberId, operation, input, context, options = {}) {
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { appOrigin } from "./environment.mjs";
8
- import { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { i as memberIdOf } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { redactDiagnostic } from "./diagnostics.mjs";
10
10
  import { object } from "./confirmation-description.mjs";
11
11
  import { OntologyToolRejected, ontologyTools } from "./ontology-tools.mjs";
@@ -18,6 +18,8 @@ export declare function ontologyTools(options?: {
18
18
  readonly environment?: Environment;
19
19
  readonly token?: RuntimeToken;
20
20
  readonly fetch?: typeof fetch;
21
+ /** Install a durable dispatch fence after safe metadata/auth work, immediately before the action request. */
22
+ readonly beforeCall?: (name: string) => Promise<void>;
21
23
  }): {
22
24
  rpc: (memberId: string, method: string, params: Record<string, unknown>, signal?: AbortSignal) => Promise<Record<string, unknown>>;
23
25
  list(memberId: string): Promise<Record<string, unknown>[]>;
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { appOrigin } from "./environment.mjs";
8
- import { c as compatibleRuntimeEnvelope, i as memberIdOf, r as identityProviderOf, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { c as compatibleRuntimeEnvelope, i as memberIdOf, r as identityProviderOf, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { redactDiagnostic } from "./diagnostics.mjs";
10
10
  import { describeConfirmation, object } from "./confirmation-description.mjs";
11
11
  import { runtimeToken } from "./runtime-token.mjs";
@@ -34,6 +34,7 @@ function ontologyTools(options = {}) {
34
34
  const provider = memberIdOf(options.principal) === memberId ? identityProviderOf(options.principal) : void 0;
35
35
  const credential = await (options.token ?? runtimeToken)();
36
36
  const secrets = new Set([credential]);
37
+ if (method === "tools/call") await options.beforeCall?.(String(params.name));
37
38
  try {
38
39
  const response = await (options.fetch ?? fetch)(`${appOrigin(options.environment ?? process.env)}/mcp`, {
39
40
  method: "POST",
@@ -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 { c as compatibleRuntimeEnvelope, d as telegramRuntimeSource, l as principalRuntimeSource, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-VFQWqe5S.mjs";
7
+ import { c as compatibleRuntimeEnvelope, d as telegramRuntimeSource, l as principalRuntimeSource, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-MEMlG3EG.mjs";
8
8
  export { RUNTIME_SOURCE_PROTOCOL, compatibleRuntimeEnvelope, principalRuntimeSource, runtimeEnvelope, telegramRuntimeSource };
@@ -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 { i as memberIdOf } from "../../_chunks/principal-VFQWqe5S.mjs";
7
+ import { i as memberIdOf } from "../../_chunks/principal-MEMlG3EG.mjs";
8
8
  import { redactDiagnostic } from "./diagnostics.mjs";
9
9
  import { object } from "./confirmation-description.mjs";
10
10
  import { ontologyTools } from "./ontology-tools.mjs";
@@ -7,19 +7,20 @@ __eveCreateRequire(import.meta.url);
7
7
  import { telegramText, withTelegramTexts } from "./texts.mjs";
8
8
  import { manifestOf } from "../../config.mjs";
9
9
  import { appOrigin, channelsEnabled, proxyEnvironment, runtimeIdentityEnvironment, webhookSecret } from "../environment.mjs";
10
- import { n as conversationLanguage, o as telegramPrincipal } from "../../../_chunks/principal-VFQWqe5S.mjs";
10
+ import { n as conversationLanguage, o as telegramPrincipal } from "../../../_chunks/principal-MEMlG3EG.mjs";
11
11
  import { confirmationLocale } from "./confirmation-text.mjs";
12
12
  import { telegramSendScope } from "./send-queue.mjs";
13
- import { d as failureText, h as withDeliveryLocale, i as withReplacedText, m as safeTelegramFetch, n as currentInboundRequest, o as currentLocale, p as reportTelegramError, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
13
+ import { d as failureText, h as withDeliveryLocale, i as withReplacedText, m as safeTelegramFetch, n as currentInboundRequest, o as currentLocale, p as reportTelegramError, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
14
14
  import { chooseModel } from "../../model.mjs";
15
15
  import { groupRoutingHealth } from "../group-routing/health.mjs";
16
16
  import { decisionRouter } from "../group-routing/router.mjs";
17
17
  import { runtimeToken } from "../runtime-token.mjs";
18
18
  import { conversations } from "../conversations.mjs";
19
19
  import { archivedRoutingMessages } from "../group-routing/routing-context.mjs";
20
+ import { dispatchStructuredMessage, structuredMessage } from "./structured.mjs";
20
21
  import { scopedAddress, sessionPolicy } from "./sessions.mjs";
21
22
  import { handleWorkspaceCallback, isWorkspaceCallback } from "./callbacks.mjs";
22
- import { t as agentBuild } from "../../../_chunks/build-metadata-BB2uSGsI.mjs";
23
+ import { t as agentBuild } from "../../../_chunks/build-metadata-DKb_DN2g.mjs";
23
24
  import { attachmentLifecycle } from "./lifecycle.mjs";
24
25
  import { observedMessages } from "./observed.mjs";
25
26
  import { expireDeferredCards, handleDeferredCallback, isDeferredCallback } from "./deferred-confirmations.mjs";
@@ -122,6 +123,10 @@ function segmentstreamTelegram(options) {
122
123
  identities: pairing,
123
124
  observed,
124
125
  chats,
126
+ structured: (raw) => {
127
+ const inbound = settings().inbound;
128
+ return inbound === void 0 ? void 0 : structuredMessage(raw, inbound.kinds);
129
+ },
125
130
  verify: telegramWebhookVerifier(() => webhookSecret(environment)),
126
131
  answerCallback: async (callbackQueryId, locale) => {
127
132
  const text = telegramText("callback", "unsupported", locale);
@@ -204,6 +209,20 @@ function segmentstreamTelegram(options) {
204
209
  includeDecisions: true
205
210
  })).events, 100),
206
211
  signalSettings: settings().groups,
212
+ ...settings().inbound === void 0 ? {} : { structured: {
213
+ configuration: settings().inbound,
214
+ run: (principal, memberId, message, event, beforeDispatch) => dispatchStructuredMessage({
215
+ configuration: settings().inbound,
216
+ principal,
217
+ memberId,
218
+ message,
219
+ event,
220
+ beforeDispatch,
221
+ environment,
222
+ token,
223
+ ...options.fetch ? { fetch: options.fetch } : {}
224
+ })
225
+ } },
207
226
  recoverHeldApprovals: options.confirmationMode?.() === "deferred",
208
227
  ...settings().attachmentLifecycle === void 0 ? {} : { lifecycle: (principal, memberId, message) => attachmentLifecycle({
209
228
  configuration: settings().attachmentLifecycle,
@@ -297,7 +316,7 @@ function segmentstreamTelegram(options) {
297
316
  reportTelegramError("intake_dispatch_release_failed", cleanupError);
298
317
  }
299
318
  const errorId = reportTelegramError("inbound_message_failed", error, { chatId: message.chat.id });
300
- if (inbound?.retryReference !== void 0 || inbound?.lifecycleKey !== void 0) inbound.retryReference = errorId;
319
+ if (inbound?.retryReference !== void 0 || inbound?.lifecycleKey !== void 0 || inbound?.structuredContext !== void 0) inbound.retryReference = errorId;
301
320
  else await context.telegram.post(failureText(errorId));
302
321
  return null;
303
322
  } finally {
@@ -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-BXhiIph-.mjs";
7
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.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";
@@ -5,11 +5,11 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { appOrigin, channelsEnabled, proxyEnvironment } from "../environment.mjs";
8
- import "../../../_chunks/principal-VFQWqe5S.mjs";
8
+ import "../../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { redactDiagnostic } from "../diagnostics.mjs";
10
10
  import { confirmationLocale } from "./confirmation-text.mjs";
11
11
  import { inTelegramSendQueue, telegramSendScope } from "./send-queue.mjs";
12
- import { d as failureText, f as formattingRefused, l as customerMessage, p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
12
+ import { d as failureText, f as formattingRefused, l as customerMessage, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
13
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";
@@ -6,11 +6,11 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { admitMessage } from "../admission.mjs";
8
8
  import { telegramText } from "./texts.mjs";
9
- import { d as telegramRuntimeSource, i as memberIdOf, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-VFQWqe5S.mjs";
9
+ import { d as telegramRuntimeSource, i as memberIdOf, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-MEMlG3EG.mjs";
10
10
  import { object } from "../confirmation-description.mjs";
11
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
12
- import { formatAddress, parseAddress, scopedAddress } from "./sessions.mjs";
11
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
13
12
  import { workspaceAction } from "./workspace-action.mjs";
13
+ import { formatAddress, parseAddress, scopedAddress } from "./sessions.mjs";
14
14
  const isWorkspaceCallback = (data) => data?.startsWith("ws:") === true;
15
15
  async function handleWorkspaceCallback(input) {
16
16
  const { query, context } = input;
@@ -7,7 +7,7 @@ __eveCreateRequire(import.meta.url);
7
7
  import { withTelegramTexts } from "./texts.mjs";
8
8
  import { proxyEnvironment } from "../environment.mjs";
9
9
  import { telegramSendScope } from "./send-queue.mjs";
10
- import { m as safeTelegramFetch, p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
10
+ import { m as safeTelegramFetch, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
11
11
  import { runtimeToken } from "../runtime-token.mjs";
12
12
  import { conversations } from "../conversations.mjs";
13
13
  import { deferredConfirmations } from "../deferred-confirmations.mjs";
@@ -5,16 +5,16 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { telegramText } from "./texts.mjs";
8
- import { i as memberIdOf, o as telegramPrincipal } from "../../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { i as memberIdOf, o as telegramPrincipal } from "../../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { humanText } from "../confirmation-description.mjs";
10
10
  import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
11
11
  import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
12
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
12
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
13
13
  import { agentMessage, observedChatKey, withConfirmationPrompt } from "../group-routing/observed.mjs";
14
14
  import { conversationEvent } from "../conversations.mjs";
15
- import { formatAddress, scopedAddress } from "./sessions.mjs";
16
15
  import { chatPostOperationId, isChatPost } from "../chat-post-confirmation.mjs";
17
16
  import { confirmations } from "../confirmations.mjs";
17
+ import { formatAddress, scopedAddress } from "./sessions.mjs";
18
18
  import { postDeferredCard } from "./deferred-confirmations.mjs";
19
19
  import { answerMarker, isPendingQuestion, pendingQuestions, questionKey } from "../questions.mjs";
20
20
  import { createHash } from "node:crypto";
@@ -1,3 +1,4 @@
1
+ import type { StructuredMessage } from "./structured.js";
1
2
  import type { AgentIdentities } from "../identities.js";
2
3
  import { type Conversations } from "../conversations.js";
3
4
  import type { AgentChats } from "./chats.js";
@@ -9,6 +10,7 @@ export declare const REVISION_CLAIM_TTL_MS: number;
9
10
  /** Runs after webhook verification, before eve drops bot/channel/service updates. */
10
11
  export declare function captureTelegramWebhook(input: {
11
12
  readonly answerCallback?: (id: string, locale?: string) => Promise<unknown>;
13
+ readonly structured?: (raw: Readonly<Record<string, unknown>>) => StructuredMessage | undefined;
12
14
  readonly request: Request;
13
15
  readonly archive: Conversations;
14
16
  readonly identities: AgentIdentities;
@@ -33,6 +35,7 @@ export declare function conversationIdentities(identities: AgentIdentities): Age
33
35
  /** Verification and failure acknowledgement stay outside eve's swallowed onMessage failures. */
34
36
  export declare function telegramConversationCapture(input: {
35
37
  readonly answerCallback?: (id: string, locale?: string) => Promise<unknown>;
38
+ readonly structured?: (raw: Readonly<Record<string, unknown>>) => StructuredMessage | undefined;
36
39
  readonly archive: Conversations;
37
40
  readonly identities: () => AgentIdentities;
38
41
  readonly observed: ObservedMessages;
@@ -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 { n as currentInboundRequest, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
7
+ import { n as currentInboundRequest, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
8
8
  import { currentConfirmationPrompt, observedChatKey } from "../group-routing/observed.mjs";
9
9
  import { conversationEvent } from "../conversations.mjs";
10
10
  import { archivedRoutingMessages } from "../group-routing/routing-context.mjs";
@@ -108,6 +108,7 @@ async function captureTelegramWebhook(input) {
108
108
  if (parsed?.kind !== "message") return input.next();
109
109
  const message = parsed.message;
110
110
  const content = messageContent(message.raw);
111
+ const structured = input.structured?.(message.raw);
111
112
  const time = edited === void 0 ? message.raw.date : message.raw.edit_date ?? message.raw.date;
112
113
  const sentAt = typeof time === "number" ? time * 1e3 : Date.now();
113
114
  const senderChat = record(message.raw.sender_chat);
@@ -158,8 +159,10 @@ async function captureTelegramWebhook(input) {
158
159
  const revisionId = edited === void 0 ? void 0 : `telegram:${message.chat.id}:${message.messageId}:routing:${createHash("sha256").update(JSON.stringify({
159
160
  at: event.at,
160
161
  content,
162
+ ...structured === void 0 ? {} : { structured },
161
163
  ...event.attachments.length === 0 ? {} : { attachments: attachmentIdentity(event.attachments) }
162
164
  })).digest("hex")}`;
165
+ const dispatchKey = `telegram:${message.chat.id}:${message.messageId}` + (structured === void 0 ? "" : `:structured:${revisionId ?? "initial"}`);
163
166
  const revisionEvents = [];
164
167
  let revisionClaim;
165
168
  const finishRevision = async (status) => {
@@ -197,12 +200,31 @@ async function captureTelegramWebhook(input) {
197
200
  ...lookup?.status === "paired" ? { participantId: lookup.member.id } : {}
198
201
  })).events;
199
202
  const routing = messageHistory.filter((earlier) => earlier.kind === "decision" && earlier.senderId === event.senderId);
200
- const previousClaim = routing.find((earlier) => earlier.reason === "turn_claimed");
201
- const admitted = routing.some((earlier) => earlier.reason === "turn_admitted");
202
- const released = previousClaim !== void 0 && routing.some((earlier) => earlier.eventId === `${previousClaim.eventId}:released`);
203
- const dispatched = routing.some((earlier) => earlier.reason === "turn_dispatch_started");
203
+ const dispatchHistory = structured === void 0 ? routing : routing.filter((earlier) => earlier.eventId.startsWith(`${dispatchKey}:`));
204
+ const previousClaim = dispatchHistory.find((earlier) => earlier.reason === "turn_claimed");
205
+ const admitted = dispatchHistory.some((earlier) => earlier.reason === "turn_admitted");
206
+ const released = previousClaim !== void 0 && dispatchHistory.some((earlier) => earlier.eventId === `${previousClaim.eventId}:released`);
207
+ const dispatched = dispatchHistory.some((earlier) => earlier.reason === "turn_dispatch_started");
204
208
  const reserved = previousClaim !== void 0 && !released && Date.now() - Date.parse(previousClaim.at) < 6e5;
205
- const alreadyHandled = admitted || dispatched || reserved;
209
+ const result = dispatchHistory.find((earlier) => earlier.reason === "structured_action_completed" && earlier.status === "completed");
210
+ let structuredContext;
211
+ if (structured !== void 0 && result?.argsSummary && lookup === void 0 && message.from !== void 0 && !message.from.isBot) {
212
+ lookup = await input.identities.lookup({
213
+ provider: "telegram",
214
+ externalId: message.from.id
215
+ });
216
+ capture.lookup = lookup;
217
+ }
218
+ if (structured !== void 0 && lookup?.status === "paired" && result?.argsSummary) try {
219
+ const value = record(JSON.parse(result.argsSummary));
220
+ if (typeof value.memberId === "string" && value.memberId === lookup.member.id && typeof value.context === "string" && value.context.trim() && value.context.length <= 16384) structuredContext = {
221
+ text: value.context,
222
+ memberId: value.memberId
223
+ };
224
+ } catch {}
225
+ const continuationDispatched = dispatchHistory.some((earlier) => earlier.reason === "structured_context_dispatch_started");
226
+ const continuationPending = dispatched && structuredContext !== void 0 && !admitted && !continuationDispatched;
227
+ const alreadyHandled = (admitted || dispatched || reserved) && !continuationPending;
206
228
  const rememberRevision = (events) => {
207
229
  if (revisionId !== void 0) revisionEvents.push(...events.filter((item) => item.eventId === revisionId || item.eventId.startsWith(`${revisionId}:`)));
208
230
  };
@@ -282,8 +304,9 @@ async function captureTelegramWebhook(input) {
282
304
  }
283
305
  let accepted = false;
284
306
  if (inbound !== void 0) {
285
- inbound.edited = edited !== void 0;
286
- if (revisionId !== void 0) inbound.claimRevision = async () => {
307
+ inbound.structuredContext = continuationPending ? structuredContext : void 0;
308
+ inbound.edited = edited !== void 0 && !continuationPending;
309
+ if (revisionId !== void 0 && !continuationPending) inbound.claimRevision = async () => {
287
310
  if (revisionEvents.some((item) => item.eventId === `${revisionId}:completed`)) return false;
288
311
  const claims = revisionEvents.filter((item) => item.reason === "routing_claimed");
289
312
  const latest = claims[0];
@@ -305,9 +328,9 @@ async function captureTelegramWebhook(input) {
305
328
  return inserted !== false;
306
329
  };
307
330
  const nextClaim = previousClaim === void 0 ? void 0 : createHash("sha256").update(previousClaim.eventId).digest("hex");
308
- const claimId = previousClaim === void 0 ? `telegram:${message.chat.id}:${message.messageId}:turn` : `telegram:${message.chat.id}:${message.messageId}:turn:${nextClaim}`;
309
- let claimed = false;
310
- let dispatchStarted = false;
331
+ const claimId = continuationPending && previousClaim !== void 0 ? previousClaim.eventId : previousClaim === void 0 ? `${dispatchKey}:turn` : `${dispatchKey}:turn:${nextClaim}`;
332
+ let claimed = continuationPending;
333
+ let dispatchStarted = continuationPending;
311
334
  const claimEvent = (reason, status, suffix = "") => ({
312
335
  ...capture.event,
313
336
  eventId: `${claimId}${suffix}`,
@@ -327,10 +350,32 @@ async function captureTelegramWebhook(input) {
327
350
  inbound.beginDispatch = async () => {
328
351
  dispatchStarted = await input.archive.append({
329
352
  ...claimEvent("turn_dispatch_started", "requested"),
330
- eventId: `telegram:${message.chat.id}:${message.messageId}:dispatch`
353
+ eventId: `${dispatchKey}:dispatch`
331
354
  }) === true;
332
355
  return dispatchStarted;
333
356
  };
357
+ inbound.recordStructuredContext = async (context, memberId) => {
358
+ if (await input.archive.append({
359
+ ...claimEvent("structured_action_completed", "completed"),
360
+ eventId: `${dispatchKey}:result`,
361
+ argsSummary: JSON.stringify({
362
+ context,
363
+ memberId
364
+ })
365
+ }) !== true) throw new Error("The archive did not acknowledge the structured continuation.");
366
+ inbound.structuredContext = {
367
+ text: context,
368
+ memberId
369
+ };
370
+ };
371
+ inbound.beginStructuredContinuation = async () => {
372
+ const inserted = await input.archive.append({
373
+ ...claimEvent("structured_context_dispatch_started", "requested"),
374
+ eventId: `${dispatchKey}:context-dispatch`
375
+ });
376
+ dispatchStarted ||= inserted === true;
377
+ return inserted === true;
378
+ };
334
379
  inbound.finishClaim = async (delivered) => {
335
380
  if ((accepted || dispatchStarted) && !delivered) return;
336
381
  accepted ||= delivered;
@@ -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-BXhiIph-.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-RIRNBxUC.mjs";
9
9
  export { TelegramDeliveryError, currentLocale, currentThreadId, customerCopy, customerMessage, customerText, failureText, formattingRefused, isTechnicalText, reportTelegramError, safeTelegramFetch, withDeliveryLocale };
@@ -5,16 +5,16 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { telegramText, withTelegramLocale } from "./texts.mjs";
8
- import { o as telegramPrincipal } from "../../../_chunks/principal-VFQWqe5S.mjs";
8
+ import { o as telegramPrincipal } from "../../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { humanText } from "../confirmation-description.mjs";
10
10
  import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
11
11
  import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
12
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
12
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
13
13
  import { agentMessage, observedChatKey, withConfirmationPrompt } from "../group-routing/observed.mjs";
14
14
  import { conversationEvent } from "../conversations.mjs";
15
- import { formatAddress } from "./sessions.mjs";
16
15
  import { CONFIRMATION_TTL_MS, inputHash } from "../confirmations.mjs";
17
16
  import { OntologyToolRejected } from "../ontology-tools.mjs";
17
+ import { formatAddress } from "./sessions.mjs";
18
18
  import { confirmationOutcome } from "../confirmation-outcome.mjs";
19
19
  import { deferredConfirmations, deferredKey, runDeferredAction } from "../deferred-confirmations.mjs";
20
20
  import { telegramTextLinks } from "@segmentstream-cloud/ontology/telegram";
@@ -4,8 +4,8 @@ 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 { n as conversationLanguage } from "../../../_chunks/principal-VFQWqe5S.mjs";
8
- import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-BXhiIph-.mjs";
7
+ import { n as conversationLanguage } from "../../../_chunks/principal-MEMlG3EG.mjs";
8
+ import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.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-BB2uSGsI.mjs";
7
+ import { t as agentBuild } from "../../../_chunks/build-metadata-DKb_DN2g.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";