@segmentstream/agent 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +7 -1
  2. package/dist/_chunks/{build-metadata-BLeBanNg.mjs → build-metadata-CJlaXNhc.mjs} +1 -1
  3. package/dist/_chunks/{inbound-request-BXhiIph-.mjs → inbound-request-RIRNBxUC.mjs} +3 -0
  4. package/dist/_chunks/principal-MEMlG3EG.mjs +126 -0
  5. package/dist/extension/config.d.ts +11 -0
  6. package/dist/extension/config.mjs +60 -1
  7. package/dist/extension/hooks/authorization.mjs +2 -2
  8. package/dist/extension/lib/attachment-tools.mjs +1 -1
  9. package/dist/extension/lib/attachments.d.ts +2 -0
  10. package/dist/extension/lib/attachments.mjs +1 -0
  11. package/dist/extension/lib/build-metadata.mjs +1 -1
  12. package/dist/extension/lib/confirmations.mjs +1 -1
  13. package/dist/extension/lib/conversation-runtime.mjs +1 -1
  14. package/dist/extension/lib/deferred-confirmations.d.ts +2 -0
  15. package/dist/extension/lib/deferred-confirmations.mjs +21 -10
  16. package/dist/extension/lib/ontology-connection.d.ts +1 -0
  17. package/dist/extension/lib/ontology-connection.mjs +18 -12
  18. package/dist/extension/lib/ontology-gateway.mjs +9 -2
  19. package/dist/extension/lib/ontology-metadata-read.mjs +1 -1
  20. package/dist/extension/lib/ontology-tools.d.ts +11 -2
  21. package/dist/extension/lib/ontology-tools.mjs +29 -4
  22. package/dist/extension/lib/runtime-envelope.d.ts +28 -0
  23. package/dist/extension/lib/runtime-envelope.mjs +8 -0
  24. package/dist/extension/lib/stored-files.mjs +1 -1
  25. package/dist/extension/lib/telegram/adapter.mjs +41 -7
  26. package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
  27. package/dist/extension/lib/telegram/attachments-send.mjs +3 -3
  28. package/dist/extension/lib/telegram/callbacks.d.ts +18 -0
  29. package/dist/extension/lib/telegram/callbacks.mjs +155 -0
  30. package/dist/extension/lib/telegram/confirmation-expiry.mjs +2 -2
  31. package/dist/extension/lib/telegram/confirmations.mjs +4 -4
  32. package/dist/extension/lib/telegram/conversations.d.ts +3 -0
  33. package/dist/extension/lib/telegram/conversations.mjs +57 -12
  34. package/dist/extension/lib/telegram/customer-text.mjs +1 -1
  35. package/dist/extension/lib/telegram/deferred-confirmations.mjs +5 -5
  36. package/dist/extension/lib/telegram/files.mjs +2 -2
  37. package/dist/extension/lib/telegram/health.mjs +1 -1
  38. package/dist/extension/lib/telegram/images.mjs +1 -1
  39. package/dist/extension/lib/telegram/inbound-request.d.ts +7 -0
  40. package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
  41. package/dist/extension/lib/telegram/inbound.d.ts +5 -0
  42. package/dist/extension/lib/telegram/inbound.mjs +110 -16
  43. package/dist/extension/lib/telegram/lifecycle.mjs +15 -3
  44. package/dist/extension/lib/telegram/media-policy.mjs +1 -1
  45. package/dist/extension/lib/telegram/principal.d.ts +1 -0
  46. package/dist/extension/lib/telegram/principal.mjs +1 -49
  47. package/dist/extension/lib/telegram/sessions.d.ts +3 -1
  48. package/dist/extension/lib/telegram/silent.mjs +3 -3
  49. package/dist/extension/lib/telegram/structured-settings.d.ts +6 -0
  50. package/dist/extension/lib/telegram/structured-settings.mjs +12 -0
  51. package/dist/extension/lib/telegram/structured.d.ts +28 -0
  52. package/dist/extension/lib/telegram/structured.mjs +114 -0
  53. package/dist/extension/lib/telegram/turn-errors.mjs +2 -2
  54. package/dist/extension/lib/telegram/voice.mjs +1 -1
  55. package/dist/extension/lib/telegram/workspace-action.d.ts +24 -0
  56. package/dist/extension/lib/telegram/workspace-action.mjs +29 -0
  57. package/dist/extension/model.mjs +1 -1
  58. package/dist/extension/tools/attachments_promote.mjs +6 -0
  59. package/dist/extension/tools/ontology.mjs +1 -1
  60. package/dist/extension/tools/questions_ask.mjs +1 -1
  61. 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.13.0, Eve 0.76.3, Ontology SDK 0.49.0 and App SDK 0.24.1.
552
+ The coordinated release uses Agent SDK 0.15.0, Eve 0.76.3, Ontology SDK 0.50.1 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.13.0";
7
+ var version = "0.15.0";
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;
@@ -0,0 +1,126 @@
1
+ import { fileURLToPath as __eveFileURLToPath } from "node:url";
2
+ import { dirname as __eveDirname } from "node:path";
3
+ import { createRequire as __eveCreateRequire } from "node:module";
4
+ const __filename = __eveFileURLToPath(import.meta.url);
5
+ __eveDirname(__filename);
6
+ __eveCreateRequire(import.meta.url);
7
+ import { n as currentInboundRequest } from "./inbound-request-RIRNBxUC.mjs";
8
+ import { randomUUID } from "node:crypto";
9
+ function telegramRuntimeSource(message, files, callbackQueryId) {
10
+ const attachments = [];
11
+ for (const file of message.attachments) {
12
+ const staged = files?.get(file.fileId);
13
+ if (staged?.status !== "stored" || attachments.length >= 10) continue;
14
+ let kind = file.kind;
15
+ for (const candidate of [
16
+ "voice",
17
+ "audio",
18
+ "video",
19
+ "video_note",
20
+ "sticker",
21
+ "animation"
22
+ ]) {
23
+ const raw = message.raw[candidate];
24
+ if (raw !== null && typeof raw === "object" && !Array.isArray(raw) && raw.file_id === file.fileId) kind = candidate;
25
+ }
26
+ attachments.push({
27
+ file_id: file.fileId,
28
+ kind,
29
+ staged_id: staged.attachment.id,
30
+ ...file.fileUniqueId === void 0 ? {} : { file_unique_id: file.fileUniqueId },
31
+ media_type: staged.attachment.contentType
32
+ });
33
+ }
34
+ return {
35
+ provider: "telegram",
36
+ chat_id: message.chat.id,
37
+ thread_id: String(message.messageThreadId ?? ""),
38
+ message_id: message.messageId,
39
+ ...message.replyToMessage === void 0 ? {} : { reply_to_message_id: message.replyToMessage.messageId },
40
+ ...message.from === void 0 ? {} : { sender: message.from.id },
41
+ ...callbackQueryId === void 0 ? {} : { callback_query_id: callbackQueryId },
42
+ ...attachments.length === 0 ? {} : { attachments }
43
+ };
44
+ }
45
+ function principalRuntimeSource(principal) {
46
+ if (principal?.authenticator !== "segmentstream-telegram") return;
47
+ const value = principal.attributes.segmentstreamRuntimeSource;
48
+ if (typeof value !== "string") return;
49
+ try {
50
+ return JSON.parse(value);
51
+ } catch {
52
+ return;
53
+ }
54
+ }
55
+ function runtimeEnvelope(input = {}) {
56
+ const source = input.source ?? principalRuntimeSource(input.principal);
57
+ return {
58
+ version: 1,
59
+ session_id: input.sessionId ?? randomUUID(),
60
+ call_id: input.callId ?? randomUUID(),
61
+ ...source === void 0 ? {} : { source }
62
+ };
63
+ }
64
+ function compatibleRuntimeEnvelope(envelope, extended) {
65
+ const source = envelope.source;
66
+ return extended || source === void 0 ? envelope : {
67
+ ...envelope,
68
+ source: {
69
+ provider: source.provider,
70
+ chat_id: source.chat_id,
71
+ thread_id: source.thread_id
72
+ }
73
+ };
74
+ }
75
+ const RUNTIME_SOURCE_PROTOCOL = "segmentstream/runtime-source";
76
+ const TELEGRAM_AUTHENTICATOR = "segmentstream-telegram";
77
+ function isGroup(message) {
78
+ return message.chat.type === "group" || message.chat.type === "supergroup";
79
+ }
80
+ function telegramPrincipal(input) {
81
+ const { message, member } = input;
82
+ const sender = message.from.id;
83
+ const attributes = {
84
+ memberId: member.id,
85
+ segmentstreamRuntimeSource: JSON.stringify(telegramRuntimeSource(message, currentInboundRequest()?.files, input.callbackQueryId)),
86
+ identityProvider: "telegram",
87
+ roles: member.roles,
88
+ chatId: message.chat.id,
89
+ chatType: message.chat.type
90
+ };
91
+ if (member.name !== null) attributes.memberName = member.name;
92
+ if (message.messageThreadId !== void 0) attributes.messageThreadId = String(message.messageThreadId);
93
+ if (message.from.username !== void 0) attributes.username = message.from.username;
94
+ const locale = member.locale ?? message.from.languageCode;
95
+ if (locale !== void 0) attributes.locale = locale;
96
+ const language = input.conversationLanguage ?? conversationLanguage([message.text || message.caption]);
97
+ if (language !== void 0) attributes.conversationLanguage = language;
98
+ return {
99
+ authenticator: TELEGRAM_AUTHENTICATOR,
100
+ issuer: "telegram",
101
+ principalId: isGroup(message) ? `telegram:${message.chat.id}:${sender}` : `telegram:${sender}`,
102
+ principalType: "user",
103
+ subject: sender,
104
+ attributes
105
+ };
106
+ }
107
+ function conversationLanguage(texts) {
108
+ for (const text of texts) {
109
+ if (/[\u0430-\u044f\u0451]/iu.test(text)) return "ru";
110
+ if ((text.match(/\b[a-z]+\b/gi)?.length ?? 0) >= 3) return "en";
111
+ }
112
+ }
113
+ function memberIdOf(principal) {
114
+ const memberId = principal?.attributes.memberId;
115
+ return typeof memberId === "string" && memberId !== "" ? memberId : void 0;
116
+ }
117
+ function rolesOf(principal) {
118
+ const roles = principal?.attributes.roles;
119
+ if (typeof roles === "string") return [roles];
120
+ return roles ?? [];
121
+ }
122
+ function identityProviderOf(principal) {
123
+ const provider = principal?.attributes.identityProvider;
124
+ return typeof provider === "string" && provider !== "" ? provider : void 0;
125
+ }
126
+ export { rolesOf as a, compatibleRuntimeEnvelope as c, telegramRuntimeSource as d, memberIdOf as i, principalRuntimeSource as l, conversationLanguage as n, telegramPrincipal as o, identityProviderOf as r, RUNTIME_SOURCE_PROTOCOL as s, TELEGRAM_AUTHENTICATOR as t, runtimeEnvelope as u };
@@ -1,5 +1,7 @@
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";
4
+ import type { WorkspaceActionHook } from "./lib/telegram/workspace-action.js";
3
5
  import { type TelegramTexts } from "./lib/telegram/texts.js";
4
6
  import type { AttachmentLifecycle } from "./lib/telegram/lifecycle.js";
5
7
  import { type TelegramLinkPreviews } from "@segmentstream-cloud/ontology/telegram";
@@ -75,6 +77,13 @@ export interface SegmentStreamAgentConfigInput {
75
77
  readonly linkPreviews?: string;
76
78
  /** Additional exact HTTP(S) origins belonging to this workspace. */
77
79
  readonly additionalOwnOrigins?: readonly string[];
80
+ readonly inbound?: Omit<StructuredInbound, "contextVersion" | "kinds"> & {
81
+ readonly kinds: ReadonlyArray<string>;
82
+ readonly contextVersion: number;
83
+ };
84
+ readonly callbacks?: Omit<WorkspaceActionHook, "contextVersion"> & {
85
+ readonly contextVersion: number;
86
+ };
78
87
  readonly menuButton?: {
79
88
  readonly text: LocalizedText;
80
89
  };
@@ -134,6 +143,8 @@ export interface TelegramSettings {
134
143
  readonly topicScope?: boolean;
135
144
  readonly commandsAddress?: boolean;
136
145
  };
146
+ readonly inbound?: StructuredInbound;
147
+ readonly callbacks?: WorkspaceActionHook;
137
148
  readonly connection: string;
138
149
  readonly policy: TelegramPolicy;
139
150
  readonly linkPreviews?: TelegramLinkPreviews;
@@ -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";
@@ -79,7 +80,9 @@ function telegramSettings(value, issues) {
79
80
  "linkPreviews",
80
81
  "additionalOwnOrigins",
81
82
  "attachmentLifecycle",
82
- "menuButton"
83
+ "menuButton",
84
+ "callbacks",
85
+ "inbound"
83
86
  ],
84
87
  issues
85
88
  });
@@ -122,6 +125,31 @@ function telegramSettings(value, issues) {
122
125
  message: "must be an array of HTTP(S) origins without paths, credentials, queries or fragments",
123
126
  path: [...path, "additionalOwnOrigins"]
124
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
+ });
152
+ const callbacks = workspaceHook(telegram.callbacks, [...path, "callbacks"], issues);
125
153
  const menuButton = section({
126
154
  value: telegram.menuButton,
127
155
  path: [...path, "menuButton"],
@@ -159,6 +187,11 @@ function telegramSettings(value, issues) {
159
187
  connection,
160
188
  policy,
161
189
  ...signalSettings === void 0 ? {} : { groups: signalSettings },
190
+ ...callbacks === void 0 ? {} : { callbacks },
191
+ ...inbound === void 0 ? {} : { inbound: {
192
+ ...inbound,
193
+ kinds: inboundConfig.kinds
194
+ } },
162
195
  linkPreviews,
163
196
  additionalOwnOrigins,
164
197
  ...menuText === void 0 ? {} : { menuButton: { text: menuText } },
@@ -169,6 +202,32 @@ function telegramSettings(value, issues) {
169
202
  } }
170
203
  } : null;
171
204
  }
205
+ function workspaceHook(value, path, issues) {
206
+ const configured = section({
207
+ value,
208
+ path,
209
+ allowed: [
210
+ "entity",
211
+ "action",
212
+ "contextVersion"
213
+ ],
214
+ issues
215
+ });
216
+ if (configured === void 0) return;
217
+ for (const key of ["entity", "action"]) if (typeof configured[key] !== "string" || !/^(?:[a-z][a-zA-Z0-9]*|[a-z][a-z0-9]*(?:_[a-z0-9]+)*)$/.test(String(configured[key]))) issues.push({
218
+ message: "must name an ontology entity or action",
219
+ path: [...path, key]
220
+ });
221
+ if (configured.contextVersion !== 2) issues.push({
222
+ message: "must be 2",
223
+ path: [...path, "contextVersion"]
224
+ });
225
+ return {
226
+ entity: String(configured.entity),
227
+ action: String(configured.action),
228
+ contextVersion: 2
229
+ };
230
+ }
172
231
  function modelId(input) {
173
232
  if (input.value === void 0) return input.fallback;
174
233
  if (typeof input.value !== "string" || input.value === "" || input.value !== input.value.trim()) {
@@ -5,9 +5,9 @@ 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 "../lib/telegram/principal.mjs";
9
- import segmentstream from "../extension.mjs";
8
+ import "../../_chunks/principal-MEMlG3EG.mjs";
10
9
  import { confirmationLocale } from "../lib/telegram/confirmation-text.mjs";
10
+ import segmentstream from "../extension.mjs";
11
11
  import { defineHook } from "eve/hooks";
12
12
  var authorization_default = defineHook({ events: { "authorization.required": (event, context) => {
13
13
  const principal = context.session.auth.current;
@@ -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 { memberIdOf } from "./telegram/principal.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";
@@ -1,3 +1,4 @@
1
+ import type { RuntimeEnvelope } from "./runtime-envelope.js";
1
2
  import type { RuntimeToken } from "./runtime-token.js";
2
3
  /**
3
4
  * The ontology service's attachment routes (`docs/agent.md`, "Attachments"). A file a member sends
@@ -35,6 +36,7 @@ export interface Attachment {
35
36
  readonly promotion: unknown;
36
37
  }
37
38
  export interface PromotionRequest {
39
+ readonly runtime?: RuntimeEnvelope;
38
40
  readonly entity: string;
39
41
  readonly action: string;
40
42
  readonly input?: Readonly<Record<string, unknown>>;
@@ -192,6 +192,7 @@ function agentAttachments(input) {
192
192
  const answer = await call(owner, `/${encodeURIComponent(id)}/promote`, "promotion", {
193
193
  entity: request.entity,
194
194
  action: request.action,
195
+ ...request.runtime === void 0 ? {} : { _meta: { _segmentstream: request.runtime } },
195
196
  input: request.input ?? {},
196
197
  ...request.field === void 0 ? {} : { field: request.field },
197
198
  ...request.recordId === void 0 ? {} : { record_id: request.recordId }
@@ -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-BLeBanNg.mjs";
7
+ import { t as agentBuild } from "../../_chunks/build-metadata-CJlaXNhc.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 { memberIdOf } from "./telegram/principal.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 { memberIdOf } from "./telegram/principal.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";
@@ -1,3 +1,4 @@
1
+ import { type RuntimeEnvelope } from "./runtime-envelope.js";
1
2
  import type { ToolContext } from "eve/tools";
2
3
  import { type Confirmation } from "./confirmations.js";
3
4
  import { type Environment } from "./environment.js";
@@ -11,6 +12,7 @@ export interface DeferredConfirmation {
11
12
  readonly expiresAt: number;
12
13
  readonly status: "pending" | "approved" | "cancelled" | "expired" | "done" | "failed";
13
14
  readonly data: {
15
+ readonly runtimeSource?: RuntimeEnvelope["source"];
14
16
  readonly action: string;
15
17
  readonly input: Readonly<Record<string, unknown>>;
16
18
  readonly confirmation: Confirmation;
@@ -5,10 +5,10 @@ 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 { memberIdOf } from "./telegram/principal.mjs";
9
- import { runtimeToken } from "./runtime-token.mjs";
8
+ import { i as memberIdOf, l as principalRuntimeSource, u as runtimeEnvelope } from "../../_chunks/principal-MEMlG3EG.mjs";
10
9
  import { redactDiagnostic } from "./diagnostics.mjs";
11
10
  import { humanText, object } from "./confirmation-description.mjs";
11
+ import { runtimeToken } from "./runtime-token.mjs";
12
12
  import { chatPostDigest, chatPostOperationId, isChatPost } from "./chat-post-confirmation.mjs";
13
13
  import { actionApproval, inputHash } from "./confirmations.mjs";
14
14
  import { ontologyTools } from "./ontology-tools.mjs";
@@ -37,7 +37,7 @@ function deferredConfirmations(options = {}) {
37
37
  }
38
38
  async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
39
39
  if (memberIdOf(ctx.session.auth.current) !== memberId) throw new Error("The ontology tool belongs to another member.");
40
- if (Object.hasOwn(input, "_segmentstream")) throw new Error("Runtime call metadata is application-owned.");
40
+ input = Object.fromEntries(Object.entries(input).filter(([key]) => key !== "_segmentstream"));
41
41
  const principal = ctx.session.auth.current;
42
42
  const attributes = principal?.attributes;
43
43
  const id = chatPostOperationId(ctx.session.id, ctx.callId);
@@ -56,7 +56,15 @@ async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
56
56
  };
57
57
  };
58
58
  if (existing !== null) return boundResult(existing);
59
- const tools = ontologyTools(options);
59
+ const tools = ontologyTools({
60
+ ...options,
61
+ principal: ctx.session.auth.current,
62
+ envelope: runtimeEnvelope({
63
+ principal: ctx.session.auth.current,
64
+ sessionId: ctx.session.id,
65
+ callId: ctx.callId
66
+ })
67
+ });
60
68
  let saved = {};
61
69
  const result = await actionApproval({
62
70
  ...tools,
@@ -96,6 +104,7 @@ async function executeDeferredTool(memberId, action, input, ctx, options = {}) {
96
104
  data: {
97
105
  action,
98
106
  input,
107
+ ...principalRuntimeSource(principal) === void 0 ? {} : { runtimeSource: principalRuntimeSource(principal) },
99
108
  confirmation,
100
109
  sessionId: ctx.session.id,
101
110
  callId: ctx.callId,
@@ -125,11 +134,13 @@ async function runDeferredAction(record, options) {
125
134
  session_id: record.data.sessionId,
126
135
  call_id: record.data.callId,
127
136
  operation_id: record.id,
137
+ ...record.data.runtimeSource === void 0 ? {} : { source: record.data.runtimeSource },
128
138
  ...preview ? {
129
139
  source: {
130
140
  provider: "telegram",
131
141
  chat_id: record.data.chatId,
132
- thread_id: record.data.threadId
142
+ thread_id: record.data.threadId,
143
+ ...record.data.runtimeSource
133
144
  },
134
145
  expected: {
135
146
  chat_id: preview.chatId,
@@ -137,12 +148,12 @@ async function runDeferredAction(record, options) {
137
148
  }
138
149
  } : {}
139
150
  };
140
- const result = await tools.rpc(record.memberId, "tools/call", {
151
+ const result = await ontologyTools({
152
+ ...options,
153
+ envelope
154
+ }).rpc(record.memberId, "tools/call", {
141
155
  name: record.data.action.split("__").at(-1),
142
- arguments: {
143
- ...record.data.input,
144
- _segmentstream: envelope
145
- }
156
+ arguments: record.data.input
146
157
  });
147
158
  const output = result.structuredContent;
148
159
  if (result.isError === true || (output?.validation)?.ok === false || preview !== void 0 && output?.status !== "sent") throw new Error("The confirmed action did not complete; its outcome may be uncertain.", { cause: result });
@@ -36,6 +36,7 @@ export declare function ontologyConnection(input: {
36
36
  readonly fetch?: typeof fetch;
37
37
  /** Set only by the authenticated catalog handshake, never by model input. */
38
38
  readonly chatPosting?: boolean;
39
+ readonly runtimeSource?: boolean;
39
40
  }): McpClientConnectionDefinition | null;
40
41
  /** Negotiate before opening Eve's client: old strict schemas never receive the new envelope. */
41
42
  export declare function ontologyConnectionForTurn(input: Parameters<typeof ontologyConnection>[0]): Promise<McpClientConnectionDefinition | null>;
@@ -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 { identityProviderOf, memberIdOf } from "./telegram/principal.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";
@@ -31,21 +31,23 @@ function ontologyConnection(input) {
31
31
  if (memberId === void 0) return null;
32
32
  const origin = appOrigin(input.environment ?? process.env);
33
33
  const token = input.token ?? runtimeToken;
34
+ const chatProtocol = input.chatPosting ? ":chat-post-v1" : "";
35
+ const sourceProtocol = input.runtimeSource ? ":runtime-source-v1" : "";
34
36
  return defineMcpClientConnection({
35
37
  url: `${origin}/mcp`,
36
38
  description: DESCRIPTION,
37
- instanceKey: `${origin}/mcp#member:${memberId}${input.chatPosting ? ":chat-post-v1" : ""}`,
39
+ instanceKey: `${origin}/mcp#member:${memberId}${chatProtocol}${sourceProtocol}`,
38
40
  approval: actionApproval(ontologyTools(input)),
39
- ...input.chatPosting ? { toolCall: { providedArguments: { [CHAT_POST_ENVELOPE]: (ctx) => {
41
+ ...input.chatPosting || input.runtimeSource ? { toolCall: { providedArguments: { [CHAT_POST_ENVELOPE]: (ctx) => {
40
42
  actAsHeaders({
41
43
  principal: ctx.session.auth.current,
42
44
  expectedMemberId: memberId
43
45
  });
44
- const base = {
45
- version: 1,
46
- session_id: ctx.session.id,
47
- call_id: ctx.callId
48
- };
46
+ const base = compatibleRuntimeEnvelope(runtimeEnvelope({
47
+ principal: ctx.session.auth.current,
48
+ sessionId: ctx.session.id,
49
+ callId: ctx.callId
50
+ }), input.runtimeSource === true);
49
51
  if (!isChatPost(ctx.toolName)) return base;
50
52
  const saved = confirmations.get()[ctx.callId];
51
53
  const preview = saved?.description?.chatPost;
@@ -56,7 +58,8 @@ function ontologyConnection(input) {
56
58
  source: {
57
59
  provider: "telegram",
58
60
  chat_id: saved.source.chatId,
59
- thread_id: saved.source.threadId
61
+ thread_id: saved.source.threadId,
62
+ ...base.source
60
63
  },
61
64
  expected: {
62
65
  chat_id: preview.chatId,
@@ -84,15 +87,18 @@ function ontologyConnection(input) {
84
87
  async function ontologyConnectionForTurn(input) {
85
88
  const memberId = memberIdOf(input.principal);
86
89
  if (memberId === void 0) return null;
87
- let chatPosting = false;
90
+ let capabilities = {
91
+ chatPosting: false,
92
+ runtimeSource: false
93
+ };
88
94
  try {
89
- chatPosting = await ontologyTools(input).supportsChatPosting(memberId);
95
+ capabilities = await ontologyTools(input).capabilities(memberId);
90
96
  } catch (error) {
91
97
  console.warn("Chat posting capability unavailable; keeping the compatible ontology connection.", error);
92
98
  }
93
99
  return ontologyConnection({
94
100
  ...input,
95
- chatPosting
101
+ ...capabilities
96
102
  });
97
103
  }
98
104
  export { ACT_AS_HEADER, MemberRequiredError, actAsHeaders, ontologyConnection, ontologyConnectionForTurn };
@@ -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 { memberIdOf } from "./telegram/principal.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 = {}) {
@@ -16,7 +16,14 @@ async function ontologyMetadata(memberId, operation, input, context, options = {
16
16
  name: operation,
17
17
  arguments: input
18
18
  }
19
- }, context, options);
19
+ }, context, {
20
+ ...options,
21
+ envelope: runtimeEnvelope({
22
+ principal,
23
+ sessionId: context.session.id,
24
+ callId: context.callId
25
+ })
26
+ });
20
27
  return result.structuredContent === void 0 ? result : object(result.structuredContent);
21
28
  }
22
29
  async function ontologyInspect(memberId, 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 { memberIdOf } from "./telegram/principal.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";
@@ -1,3 +1,4 @@
1
+ import { type RuntimeEnvelope } from "./runtime-envelope.js";
1
2
  import type { SessionAuthContext } from "eve/context";
2
3
  import type { ActionAnnotations } from "./confirmations.js";
3
4
  import { type Environment } from "./environment.js";
@@ -13,17 +14,25 @@ export declare class OntologyActionNotPermitted extends Error {
13
14
  /** A fresh, permission-filtered catalog. Listing tools cannot run an action's prepare step. */
14
15
  export declare function ontologyTools(options?: {
15
16
  readonly principal?: SessionAuthContext | null;
17
+ readonly envelope?: RuntimeEnvelope;
16
18
  readonly environment?: Environment;
17
19
  readonly token?: RuntimeToken;
18
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>;
19
23
  }): {
20
24
  rpc: (memberId: string, method: string, params: Record<string, unknown>, signal?: AbortSignal) => Promise<Record<string, unknown>>;
21
25
  list(memberId: string): Promise<Record<string, unknown>[]>;
26
+ supportsRuntimeSource(memberId: string, signal?: AbortSignal): Promise<boolean>;
27
+ capabilities(memberId: string): Promise<{
28
+ chatPosting: boolean;
29
+ runtimeSource: boolean;
30
+ }>;
22
31
  supportsChatPosting(memberId: string): Promise<boolean>;
23
- labels(memberId: string, action: string, input?: Readonly<Record<string, unknown>>): Promise<ActionAnnotations>;
32
+ labels(memberId: string, action: string, input?: Readonly<Record<string, unknown>>, signal?: AbortSignal): Promise<ActionAnnotations>;
24
33
  describe(memberId: string, action: string, input: Readonly<Record<string, unknown>>): Promise<import("./confirmation-description.js").ConfirmationDescription>;
25
34
  };
26
- export declare function ontologyToolLabels(options?: Parameters<typeof ontologyTools>[0]): (memberId: string, action: string, input?: Readonly<Record<string, unknown>>) => Promise<ActionAnnotations>;
35
+ export declare function ontologyToolLabels(options?: Parameters<typeof ontologyTools>[0]): (memberId: string, action: string, input?: Readonly<Record<string, unknown>>, signal?: AbortSignal) => Promise<ActionAnnotations>;
27
36
  /** MCP normalizes an authored camelCase action to snake_case. */
28
37
  export declare function actionToolName(entity: string, action: string): string;
29
38
  /** One target contract for native and MCP attachment promotion; never trust supplied safety hints. */