@segmentstream/agent 0.18.3 → 0.19.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 (92) hide show
  1. package/README.md +4 -4
  2. package/dist/_chunks/{build-metadata-DZ9Nb8Q2.mjs → build-metadata-CkW-D9NI.mjs} +1 -1
  3. package/dist/_chunks/{inbound-request-8xhK7EaW.mjs → inbound-request-Dx1B6Y5r.mjs} +1 -1
  4. package/dist/_chunks/{principal-qyR3jKAr.mjs → principal-BnJuWJtk.mjs} +1 -1
  5. package/dist/extension/_manifest.json +3 -15
  6. package/dist/extension/connections/ontology.d.ts +1 -1
  7. package/dist/extension/connections/ontology.mjs +2 -2
  8. package/dist/extension/hooks/authorization.d.ts +1 -1
  9. package/dist/extension/hooks/authorization.mjs +3 -3
  10. package/dist/extension/hooks/ontology-files.d.ts +1 -1
  11. package/dist/extension/hooks/ontology-files.mjs +3 -1
  12. package/dist/extension/hooks/sandbox.d.ts +2 -2
  13. package/dist/extension/hooks/sandbox.mjs +2 -2
  14. package/dist/extension/instructions/conversations.d.ts +1 -1
  15. package/dist/extension/instructions/conversations.mjs +3 -3
  16. package/dist/extension/instructions/sandbox.d.ts +1 -1
  17. package/dist/extension/instructions/sandbox.mjs +2 -2
  18. package/dist/extension/lib/attachment-tools.mjs +1 -1
  19. package/dist/extension/lib/build-metadata.mjs +1 -1
  20. package/dist/extension/lib/confirmations.mjs +3 -3
  21. package/dist/extension/lib/conversation-runtime.d.ts +2 -2
  22. package/dist/extension/lib/conversation-runtime.mjs +40 -55
  23. package/dist/extension/lib/conversations.mjs +1 -1
  24. package/dist/extension/lib/group-routing/conversation-router.d.ts +1 -1
  25. package/dist/extension/lib/group-routing/conversation-router.mjs +2 -2
  26. package/dist/extension/lib/group-routing/dequeue.mjs +2 -2
  27. package/dist/extension/lib/group-routing/record.mjs +1 -1
  28. package/dist/extension/lib/group-routing/replay.mjs +1 -1
  29. package/dist/extension/lib/group-routing/router.d.ts +1 -1
  30. package/dist/extension/lib/group-routing/router.mjs +3 -3
  31. package/dist/extension/lib/ontology-connection.mjs +2 -2
  32. package/dist/extension/lib/ontology-file-call.mjs +2 -2
  33. package/dist/extension/lib/ontology-tools.mjs +1 -1
  34. package/dist/extension/lib/runtime-envelope.mjs +1 -1
  35. package/dist/extension/lib/sandbox.d.ts +3 -2
  36. package/dist/extension/lib/sandbox.mjs +1 -1
  37. package/dist/extension/lib/stored-files.mjs +1 -1
  38. package/dist/extension/lib/telegram/adapter.mjs +43 -28
  39. package/dist/extension/lib/telegram/archive-message.d.ts +4 -0
  40. package/dist/extension/lib/telegram/archive-message.mjs +85 -0
  41. package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
  42. package/dist/extension/lib/telegram/attachments-send.mjs +2 -2
  43. package/dist/extension/lib/telegram/callbacks.mjs +2 -2
  44. package/dist/extension/lib/telegram/confirmation-expiry.mjs +20 -9
  45. package/dist/extension/lib/telegram/confirmations.d.ts +2 -2
  46. package/dist/extension/lib/telegram/confirmations.mjs +206 -181
  47. package/dist/extension/lib/telegram/conversations.mjs +5 -6
  48. package/dist/extension/lib/telegram/customer-text.mjs +1 -1
  49. package/dist/extension/lib/telegram/deferred-confirmations.mjs +2 -2
  50. package/dist/extension/lib/telegram/delivery-diagnostics.mjs +1 -1
  51. package/dist/extension/lib/telegram/durable-typing.d.ts +11 -0
  52. package/dist/extension/lib/telegram/durable-typing.mjs +10 -10
  53. package/dist/extension/lib/telegram/files.mjs +2 -2
  54. package/dist/extension/lib/telegram/health.mjs +1 -1
  55. package/dist/extension/lib/telegram/held-approvals.d.ts +3 -3
  56. package/dist/extension/lib/telegram/held-approvals.mjs +23 -19
  57. package/dist/extension/lib/telegram/images.d.ts +1 -1
  58. package/dist/extension/lib/telegram/images.mjs +1 -1
  59. package/dist/extension/lib/telegram/inbound-request.d.ts +2 -2
  60. package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
  61. package/dist/extension/lib/telegram/inbound.mjs +5 -6
  62. package/dist/extension/lib/telegram/lifecycle.d.ts +2 -2
  63. package/dist/extension/lib/telegram/lifecycle.mjs +23 -27
  64. package/dist/extension/lib/telegram/media-policy.mjs +1 -1
  65. package/dist/extension/lib/telegram/principal.mjs +1 -1
  66. package/dist/extension/lib/telegram/routing-context.mjs +4 -4
  67. package/dist/extension/lib/telegram/session-recovery.d.ts +1 -1
  68. package/dist/extension/lib/telegram/session-recovery.mjs +2 -1
  69. package/dist/extension/lib/telegram/sessions.d.ts +7 -4
  70. package/dist/extension/lib/telegram/sessions.mjs +6 -3
  71. package/dist/extension/lib/telegram/silent.d.ts +1 -1
  72. package/dist/extension/lib/telegram/silent.mjs +11 -8
  73. package/dist/extension/lib/telegram/structured.mjs +1 -1
  74. package/dist/extension/lib/telegram/turn-errors.d.ts +1 -1
  75. package/dist/extension/lib/telegram/turn-errors.mjs +47 -31
  76. package/dist/extension/lib/telegram/voice.mjs +1 -1
  77. package/dist/extension/lib/workflow-serializable.mjs +1 -1
  78. package/dist/extension/model.mjs +7 -4
  79. package/dist/extension/tools/attachments_discard.mjs +1 -1
  80. package/dist/extension/tools/attachments_list.mjs +1 -1
  81. package/dist/extension/tools/attachments_promote.mjs +2 -2
  82. package/dist/extension/tools/attachments_read.mjs +1 -1
  83. package/dist/extension/tools/attachments_send.mjs +1 -1
  84. package/dist/extension/tools/attachments_table.mjs +1 -1
  85. package/dist/extension/tools/ontology_call_file.d.ts +1 -1
  86. package/dist/extension/tools/ontology_call_file.mjs +1 -1
  87. package/dist/extension/tools/questions_ask.mjs +2 -2
  88. package/dist/extension/tools/sandbox.d.ts +1 -8
  89. package/dist/extension/tools/sandbox.mjs +1 -1
  90. package/package.json +4 -4
  91. /package/dist/_chunks/{content-TRaZitQZ.mjs → content-cDtVnr8Y.mjs} +0 -0
  92. /package/dist/_chunks/{workflow-serializable-_g4JRau5.mjs → workflow-serializable-DU7WeCIW.mjs} +0 -0
@@ -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-DZ9Nb8Q2.mjs";
7
+ import { t as agentBuild } from "../../../_chunks/build-metadata-CkW-D9NI.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";
@@ -1,4 +1,4 @@
1
- import type { CancelTurnResult } from "eve/channels";
1
+ import { type Delivery } from "eve/sessions";
2
2
  import type { RecordedEvent } from "./sessions.js";
3
3
  /** An approval is an input barrier, never permission to execute it while recovering a chat. */
4
4
  export declare function heldApprovals(events: readonly RecordedEvent[]): {
@@ -15,13 +15,13 @@ export declare function releaseHeldApproval(input: {
15
15
  readonly now: number;
16
16
  readonly cancel: (options: {
17
17
  readonly turnId: string;
18
- }) => Promise<CancelTurnResult>;
18
+ }) => Promise<Delivery>;
19
19
  }): Promise<{
20
20
  status: string;
21
21
  reason: string;
22
22
  turnId: string;
23
23
  startedAt: string;
24
24
  actions: string[];
25
- cancellation: "accepted";
25
+ cancellation: "cancelled" | "failed" | "completed" | "awaiting-input";
26
26
  executionRequested: boolean;
27
27
  } | undefined>;
@@ -6,27 +6,24 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { object } from "../confirmation-description.mjs";
8
8
  import { CONFIRMATION_TTL_MS } from "../confirmations.mjs";
9
+ import { SessionNotActiveError } from "eve/sessions";
9
10
  function heldApprovals(events) {
10
11
  const pending = new Map();
12
+ const calls = new Map();
11
13
  for (const event of events) {
12
14
  const data = object(event.data);
13
- if (event.type === "context.cleared" || event.type === "session.started") pending.clear();
14
- if (event.type === "input.requested" && Array.isArray(data.requests)) for (const item of data.requests) {
15
- const request = object(item);
16
- const action = object(request.action);
17
- if (request.kind === "tool-approval" && typeof request.requestId === "string" && typeof action.callId === "string" && typeof data.turnId === "string") pending.set(request.requestId, {
18
- requestId: request.requestId,
19
- callId: action.callId,
20
- action: String(action.toolName ?? ""),
21
- turnId: data.turnId,
22
- at: event.meta.at
23
- });
24
- }
25
- for (const [id, approval] of pending) if (event.type === "input.resolved" && Array.isArray(data.resolutions) && data.resolutions.some((item) => object(item).requestId === id) || event.type === "action.result" && object(data.result).callId === approval.callId || [
26
- "turn.completed",
27
- "turn.failed",
28
- "turn.cancelled"
29
- ].includes(event.type) && data.turnId === approval.turnId) pending.delete(id);
15
+ if (event.type === "session.started" || event.type === "context.settled" && data.kind === "clear" && data.outcome === "completed") pending.clear();
16
+ if (event.type === "call.requested" && typeof data.callId === "string") calls.set(data.callId, String(object(data.capability).name ?? ""));
17
+ const callId = object(data.subject).callId;
18
+ const turnId = event.scope?.turnId;
19
+ if (event.type === "interaction.opened" && object(data.request).kind === "approval" && typeof data.interactionId === "string" && typeof callId === "string" && turnId !== void 0) pending.set(data.interactionId, {
20
+ requestId: data.interactionId,
21
+ callId,
22
+ action: calls.get(callId) ?? "",
23
+ turnId,
24
+ at: event.meta.at
25
+ });
26
+ for (const [id, approval] of pending) if (event.type === "interaction.settled" && data.interactionId === id || event.type === "call.settled" && data.callId === approval.callId || event.type === "turn.settled" && data.turnId === approval.turnId) pending.delete(id);
30
27
  }
31
28
  return [...pending.values()];
32
29
  }
@@ -36,8 +33,15 @@ async function releaseHeldApproval(input) {
36
33
  const expired = pending.some((approval) => input.now - Date.parse(approval.at) >= CONFIRMATION_TTL_MS);
37
34
  if (!input.addressed && !expired) return;
38
35
  const turnId = pending[0].turnId;
39
- const result = await input.cancel({ turnId });
40
- if (result.status === "no_active_turn") return;
36
+ let delivery;
37
+ try {
38
+ delivery = await input.cancel({ turnId });
39
+ } catch (error) {
40
+ if (SessionNotActiveError.is(error) && !error.retryable) return;
41
+ throw error;
42
+ }
43
+ const result = await delivery.result();
44
+ if (result.outcome === "ignored" || result.outcome === "refused") return;
41
45
  return {
42
46
  status: "cancellation_requested",
43
47
  reason: expired ? "expired" : "addressed",
@@ -1,6 +1,6 @@
1
1
  /** Storage still accepts up to 20 MiB; description has its own lower cost/transfer bound. */
2
2
  export declare const MAXIMUM_IMAGE_DESCRIPTION_BYTES: number;
3
- /** Eve 0.76.3's actual inbound image inlining limit. */
3
+ /** Eve 0.85.0's actual inbound image inlining limit. */
4
4
  export declare const MAXIMUM_NATIVE_IMAGE_BYTES: number;
5
5
  export declare const MAXIMUM_IMAGE_DESCRIPTIONS = 1;
6
6
  export type ImageDescriber = (input: {
@@ -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-8xhK7EaW.mjs";
7
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
8
8
  import { gateway, generateText } from "ai";
9
9
  const MAXIMUM_IMAGE_DESCRIPTION_BYTES = 5242880;
10
10
  const MAXIMUM_NATIVE_IMAGE_BYTES = 3145728;
@@ -1,5 +1,5 @@
1
1
  import type { DeferredConfirmation } from "../deferred-confirmations.js";
2
- import type { UserContent } from "ai";
2
+ import type { MessageContent } from "eve/channels";
3
3
  import type { ChannelSource } from "eve/channels";
4
4
  import type { SessionAuthContext } from "eve/context";
5
5
  import type { DecodedAttachment } from "./attachment-description.js";
@@ -79,7 +79,7 @@ export declare class InboundRequest {
79
79
  */
80
80
  files: ReadonlyMap<string, StagedFile> | undefined;
81
81
  /** Earlier observed native images, rebound to this turn's authenticated requester. */
82
- extraFiles: Exclude<UserContent, string> | undefined;
82
+ extraFiles: Exclude<MessageContent, string> | undefined;
83
83
  /** The route's session operations, on addresses already mapped to the configured scope. */
84
84
  sessions: SessionOperations | undefined;
85
85
  /** Host background lifetime; long-running observers must never enter the routing drain. */
@@ -4,5 +4,5 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { i as withReplacedText, n as currentInboundRequest, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-8xhK7EaW.mjs";
7
+ import { i as withReplacedText, n as currentInboundRequest, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
8
8
  export { InboundRequest, currentInboundRequest, runInboundRequest, withReplacedText };
@@ -6,8 +6,8 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { effectiveGroupPolicy, groupPolicy } from "../group-routing/policy.mjs";
8
8
  import { admitMessage, localizedText } from "../admission.mjs";
9
- import { d as telegramRuntimeSource, n as conversationLanguage, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-qyR3jKAr.mjs";
10
- import { p as reportTelegramError } from "../../../_chunks/inbound-request-8xhK7EaW.mjs";
9
+ import { d as telegramRuntimeSource, n as conversationLanguage, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-BnJuWJtk.mjs";
10
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
11
11
  import { addressingReason, conversationKey, otherRecipient } from "../group-routing/signals.mjs";
12
12
  import { conversationAddressing, conversationState } from "../group-routing/conversation.mjs";
13
13
  import { questionInvitation } from "../group-routing/engagement.mjs";
@@ -461,7 +461,7 @@ async function handleInboundMessage(input) {
461
461
  chatId: sent.chat.id,
462
462
  messageId: sent.messageId
463
463
  }).catch((error) => {
464
- reportTelegramError("typing_monitor_failed", error, { sessionId: session.id });
464
+ reportTelegramError("typing_monitor_failed", error, { sessionId: session.sessionId });
465
465
  }));
466
466
  };
467
467
  }
@@ -504,9 +504,8 @@ async function handleInboundMessage(input) {
504
504
  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 ?? "");
505
505
  const asked = questionHistory.findLast((event) => {
506
506
  const data = isRecord(event.data) ? event.data : {};
507
- const result = isRecord(data.result) ? data.result : {};
508
- const output = isRecord(result.output) ? result.output : {};
509
- return event.type === "action.result" && typeof result.toolName === "string" && result.toolName.endsWith("__questions_ask") && isRecord(output.pendingQuestion) && output.pendingQuestion.id === pending?.id;
507
+ const output = isRecord(data.output) ? data.output : {};
508
+ return event.type === "call.settled" && data.outcome === "completed" && isRecord(output.pendingQuestion) && output.pendingQuestion.id === pending?.id;
510
509
  });
511
510
  const questionAge = Date.parse(sentAt(sent)) - Date.parse(asked?.meta.at ?? "");
512
511
  if (answering && addressed === void 0 && !questionInvitation(asked?.meta.at, sentAt(sent), groups.smart.engagement.openQuestionMinutes)) answering = false;
@@ -1,6 +1,6 @@
1
1
  import type { SessionAuthContext } from "eve/context";
2
2
  import type { TelegramContext } from "eve/channels/telegram";
3
- import type { Session } from "eve/channels";
3
+ import type { Delivery } from "eve/sessions";
4
4
  import type { Environment } from "../environment.js";
5
5
  import type { RuntimeToken } from "../runtime-token.js";
6
6
  export interface AttachmentLifecycle {
@@ -51,6 +51,6 @@ export declare function attachmentLifecycle(options: {
51
51
  readonly fetch?: typeof fetch;
52
52
  }): (phase: "admitted" | "stored" | "retained" | "ready" | "completed", data?: Record<string, unknown>) => Promise<LifecycleResult>;
53
53
  /** Kept inside the webhook's waitUntil lifetime; terminal durable stream events close the reader. */
54
- export declare function typingUntilComplete(session: Session, marker: string, telegram: TelegramContext["telegram"], signal: AbortSignal, metadata?: Readonly<Record<string, string | undefined>>): Promise<void>;
54
+ export declare function typingUntilComplete(session: Delivery, marker: string, telegram: TelegramContext["telegram"], signal: AbortSignal, metadata?: Readonly<Record<string, string | undefined>>): Promise<void>;
55
55
  /** No global timer survives a request or terminal event; failures retain safe method/status telemetry. */
56
56
  export declare function startTypingHeartbeat(telegram: TelegramContext["telegram"]): () => void;
@@ -4,12 +4,12 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { d as telegramRuntimeSource, l as principalRuntimeSource, u as runtimeEnvelope } from "../../../_chunks/principal-qyR3jKAr.mjs";
7
+ import { d as telegramRuntimeSource, l as principalRuntimeSource, u as runtimeEnvelope } from "../../../_chunks/principal-BnJuWJtk.mjs";
8
8
  import { object } from "../confirmation-description.mjs";
9
- import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-8xhK7EaW.mjs";
9
+ import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
10
10
  import { needsConfirmation } from "../confirmations.mjs";
11
11
  import { OntologyActionNotPermitted, actionToolName, ontologyTools } from "../ontology-tools.mjs";
12
- import { t as agentBuild } from "../../../_chunks/build-metadata-DZ9Nb8Q2.mjs";
12
+ import { t as agentBuild } from "../../../_chunks/build-metadata-CkW-D9NI.mjs";
13
13
  var AttachmentLifecycleNotPermitted = class extends Error {
14
14
  code = "attachment_lifecycle_not_permitted";
15
15
  };
@@ -84,66 +84,62 @@ function attachmentLifecycle(options) {
84
84
  };
85
85
  }
86
86
  async function typingUntilComplete(session, marker, telegram, signal, metadata = {}) {
87
- const reader = (await session.getEventStream({ follow: true })).getReader();
87
+ const iterator = session.stream({ signal })[Symbol.asyncIterator]();
88
88
  let turn;
89
89
  let firstResponse = false;
90
90
  const abort = () => {
91
- reader.cancel().catch(() => void 0);
91
+ iterator.return?.().catch(() => void 0);
92
92
  };
93
93
  signal.addEventListener("abort", abort, { once: true });
94
94
  const stop = startTypingHeartbeat(telegram);
95
95
  try {
96
96
  while (!signal.aborted) {
97
- const item = await reader.read();
97
+ const item = await iterator.next();
98
98
  if (item.done) break;
99
99
  const event = item.value;
100
- if (event.type === "message.received" && event.data.message.includes(marker)) {
100
+ if (event.type === "delivery.consumed" && event.data.parts.some((part) => part.kind === "text" && part.text.includes(marker))) {
101
101
  turn = event.data.turnId;
102
102
  console.info("[segmentstream] telegram.phase", {
103
103
  ...metadata,
104
104
  phase: "turn_received",
105
105
  at: new Date().toISOString(),
106
- sessionId: session.id,
106
+ sessionId: session.sessionId,
107
107
  turnId: turn
108
108
  });
109
109
  }
110
- if (turn && event.data !== void 0 && "turnId" in event.data && event.data.turnId === turn && [
111
- "step.started",
112
- "actions.requested",
113
- "action.result",
114
- "turn.completed",
115
- "turn.failed",
116
- "turn.cancelled"
110
+ if (turn && event.scope?.turnId === turn && [
111
+ "model.started",
112
+ "call.requested",
113
+ "call.settled",
114
+ "turn.settled"
117
115
  ].includes(event.type)) console.info("[segmentstream] telegram.phase", {
118
116
  ...metadata,
119
117
  phase: event.type,
120
118
  at: new Date().toISOString(),
121
- sessionId: session.id,
119
+ sessionId: session.sessionId,
122
120
  turnId: turn
123
121
  });
124
- if (turn && !firstResponse && (event.type === "message.appended" || event.type === "reasoning.appended") && "turnId" in event.data && event.data.turnId === turn) {
122
+ if (turn && !firstResponse && event.type === "content.delta" && event.scope?.turnId === turn) {
125
123
  firstResponse = true;
126
124
  console.info("[segmentstream] telegram.phase", {
127
125
  ...metadata,
128
126
  phase: "model_first_response",
129
127
  at: new Date().toISOString(),
130
- sessionId: session.id,
128
+ sessionId: session.sessionId,
131
129
  turnId: turn
132
130
  });
133
131
  }
134
- if (event.type === "session.failed" || event.type === "session.completed") break;
135
- if (turn && "turnId" in event.data && event.data.turnId === turn && ([
136
- "turn.completed",
137
- "turn.failed",
138
- "turn.cancelled",
139
- "input.requested"
140
- ].includes(event.type) || event.type === "turn.waiting" && event.data.on === "input")) break;
132
+ if (event.type === "session.ended") break;
133
+ if (turn && event.scope?.turnId === turn && [
134
+ "turn.settled",
135
+ "turn.paused",
136
+ "interaction.opened"
137
+ ].includes(event.type)) break;
141
138
  }
142
139
  } finally {
143
140
  stop();
144
141
  signal.removeEventListener("abort", abort);
145
- await reader.cancel().catch(() => void 0);
146
- reader.releaseLock();
142
+ await iterator.return?.().catch(() => void 0);
147
143
  }
148
144
  }
149
145
  function startTypingHeartbeat(telegram) {
@@ -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-8xhK7EaW.mjs";
8
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
9
9
  function planMedia(capabilities, descriptionModel = null) {
10
10
  if (typeof descriptionModel === "string") return {
11
11
  images: "describe",
@@ -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 { a as rolesOf, i as memberIdOf, n as conversationLanguage, o as telegramPrincipal, r as identityProviderOf, t as TELEGRAM_AUTHENTICATOR } from "../../../_chunks/principal-qyR3jKAr.mjs";
7
+ import { a as rolesOf, i as memberIdOf, n as conversationLanguage, o as telegramPrincipal, r as identityProviderOf, t as TELEGRAM_AUTHENTICATOR } from "../../../_chunks/principal-BnJuWJtk.mjs";
8
8
  export { TELEGRAM_AUTHENTICATOR, conversationLanguage, identityProviderOf, memberIdOf, rolesOf, telegramPrincipal };
@@ -19,7 +19,7 @@ async function routingContext(input) {
19
19
  for (const history of histories.values()) for (const question of questionsFromHistory(history)) {
20
20
  const asked = history.findLast((event) => {
21
21
  const data = event.data;
22
- return event.type === "action.result" && data?.result?.output?.pendingQuestion?.id === question.id;
22
+ return event.type === "call.settled" && data?.output?.pendingQuestion?.id === question.id;
23
23
  });
24
24
  pending.set(questionKey(question), {
25
25
  ...question,
@@ -64,14 +64,14 @@ async function routingContext(input) {
64
64
  const recovered = [];
65
65
  let resetAt = 0;
66
66
  for (const event of events) {
67
- if (event.type === "context.cleared" || event.type === "session.started") {
67
+ if (event.type === "session.started" || event.type === "context.settled" && event.data?.kind === "clear" && event.data?.outcome === "completed") {
68
68
  recovered.length = 0;
69
69
  resetAt = Date.parse(event.meta.at);
70
70
  }
71
71
  const age = sentAt - Date.parse(event.meta.at);
72
72
  const data = typeof event.data === "object" && event.data !== null ? event.data : void 0;
73
- if (event.type === "message.completed" && data !== void 0 && typeof data.message === "string" && typeof data.finishReason === "string" && data.finishReason !== "tool-calls" && data.message.trim() !== "" && !isSilentReply(data.message) && age >= 0 && age <= (input.followUpMinutes === void 0 ? 18e5 : input.followUpMinutes * 6e4)) recovered.push(agentMessage({
74
- text: data.message,
73
+ if (event.type === "content.completed" && data !== void 0 && typeof data.value === "string" && data.kind === "text" && data.phase === "reply" && !data.interrupted && data.value.trim() !== "" && !isSilentReply(data.value) && age >= 0 && age <= (input.followUpMinutes === void 0 ? 18e5 : input.followUpMinutes * 6e4)) recovered.push(agentMessage({
74
+ text: data.value,
75
75
  at: event.meta.at
76
76
  }));
77
77
  }
@@ -1,7 +1,7 @@
1
1
  import type { ChannelReceiveContext } from "eve/channels";
2
2
  import type { HistoryReader } from "./sessions.js";
3
3
  /**
4
- * Eve 0.76.3 cannot resolve/reset an inbox whose metadata key belonged to a deleted deployment.
4
+ * A deleted deployment can make the Workflow metadata key unreadable before Eve can hand off a session.
5
5
  * Recover on a read, before dispatch: independent requests on this deployment use the same fresh
6
6
  * continuation. Healthy addresses keep their owner across deploys. An already broken address
7
7
  * gets a fresh owner on each deployment; the archive remains the source of routing context.
@@ -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-8xhK7EaW.mjs";
7
+ import { p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
8
8
  import { createHash } from "node:crypto";
9
9
  function missingDeployment(error) {
10
10
  if (!(error instanceof Error) || error.name !== "RunKeyFetchError" || !("status" in error) || error.status !== 404) return false;
@@ -54,6 +54,7 @@ function recoverableSessions(operations, deploymentId, readHistory) {
54
54
  return {
55
55
  resolveSession,
56
56
  from: (address) => ({
57
+ create: async (options) => (await source(address)).create(options),
57
58
  send: async (message, options) => (await source(address)).send(message, options),
58
59
  respond: async (responses, options) => (await source(address)).respond(responses, options),
59
60
  cancel: async (options) => (await source(address)).cancel(options),
@@ -1,5 +1,5 @@
1
1
  import type { TelegramMessage } from "eve/channels/telegram";
2
- import type { CancelTurnResult, ChannelSource } from "eve/channels";
2
+ import type { ChannelSource } from "eve/channels";
3
3
  import type { TelegramChannelState } from "eve/channels/telegram";
4
4
  import type { SessionSettings } from "../../config.js";
5
5
  /**
@@ -42,6 +42,9 @@ export interface SessionHistory {
42
42
  /** One recorded event used by session policy, routing context and interaction projections. */
43
43
  export interface RecordedEvent {
44
44
  readonly type: string;
45
+ readonly scope?: {
46
+ readonly turnId?: string;
47
+ };
45
48
  readonly meta: {
46
49
  readonly at: string;
47
50
  };
@@ -60,12 +63,12 @@ export interface SessionOperations {
60
63
  readonly id: string;
61
64
  readonly cancel?: (options: {
62
65
  readonly turnId: string;
63
- }) => Promise<CancelTurnResult>;
66
+ }) => Promise<import("eve/sessions").Delivery>;
64
67
  } | undefined>;
65
68
  readonly from: (address: string) => {
66
69
  readonly send?: ChannelSource<TelegramChannelState>["send"];
67
- compact(): Promise<unknown>;
68
- clear(): Promise<unknown>;
70
+ compact: ChannelSource<TelegramChannelState>["compact"];
71
+ clear: ChannelSource<TelegramChannelState>["clear"];
69
72
  };
70
73
  }
71
74
  export type SessionAction = "none" | "cleared" | "compacted";
@@ -96,11 +96,11 @@ function historyOf(events) {
96
96
  if (Number.isNaN(at)) continue;
97
97
  lastAt = Math.max(lastAt, at);
98
98
  earliest = earliest === 0 ? at : Math.min(earliest, at);
99
- if (event.type === "session.started" || event.type === "compaction.completed" || event.type === "context.cleared") {
99
+ if (event.type === "session.started" || event.type === "context.settled" && typeof event.data === "object" && event.data !== null && "outcome" in event.data && event.data.outcome === "completed") {
100
100
  resetAt = at;
101
101
  marked = true;
102
102
  turnsSinceReset = 0;
103
- } else if (event.type === "turn.completed") turnsSinceReset += 1;
103
+ } else if (event.type === "turn.settled") turnsSinceReset += 1;
104
104
  }
105
105
  return {
106
106
  lastAt,
@@ -166,7 +166,10 @@ function sessionPolicy(input) {
166
166
  action = due(known, settings, now, activeAt);
167
167
  }
168
168
  if (action === "clear") try {
169
- await operations.from(address).clear();
169
+ if ((await (await operations.from(address).clear()).result()).outcome !== "applied") {
170
+ remembered.delete(address);
171
+ return "none";
172
+ }
170
173
  remember(address, {
171
174
  lastAt: known.lastAt,
172
175
  resetAt: now.getTime(),
@@ -3,7 +3,7 @@ import { type ObservedMessages } from "./observed.js";
3
3
  export declare function isSilentReply(text: string): boolean;
4
4
  /** Use the same classification for delivery and its archive decision. Never strip real prose. */
5
5
  export declare function completionKind(message: string | null | undefined, finishReason?: string): "reply" | "tool_calls" | "empty" | "whitespace" | "silent_marker";
6
- type MessageCompleted = NonNullable<TelegramChannelEvents["message.completed"]>;
6
+ type MessageCompleted = NonNullable<TelegramChannelEvents["content.completed"]>;
7
7
  /** The texts one runtime delivered as interim messages, per session turn. */
8
8
  export interface InterimTexts {
9
9
  has(turn: string, text: string): boolean;
@@ -4,11 +4,11 @@ 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 "../../../_chunks/principal-qyR3jKAr.mjs";
7
+ import "../../../_chunks/principal-BnJuWJtk.mjs";
8
8
  import { confirmationLocale } from "./confirmation-text.mjs";
9
9
  import { splitTelegramText } from "./format.mjs";
10
10
  import { inTelegramSendQueue } from "./send-queue.mjs";
11
- import { a as TelegramDeliveryError, l as customerMessage, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-8xhK7EaW.mjs";
11
+ import { a as TelegramDeliveryError, l as customerMessage, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-Dx1B6Y5r.mjs";
12
12
  import { agentMessage, observedChatKey } from "../group-routing/observed.mjs";
13
13
  const SILENT_MARKERS = new Set(["[silent]", "no_reply"]);
14
14
  function isSilentReply(text) {
@@ -37,15 +37,18 @@ function interimTexts(limit = 256) {
37
37
  };
38
38
  }
39
39
  function replyDelivery(observed, scope = () => "telegram", interim) {
40
- return async (event, channel, context) => {
41
- const kind = completionKind(event.message, event.finishReason);
40
+ return async (event, context) => {
41
+ if (event.data.kind !== "text" || event.data.interrupted) return;
42
+ const channel = context.channel;
43
+ const textValue = typeof event.data.value === "string" ? event.data.value : "";
44
+ const kind = completionKind(textValue, event.data.phase === "reply" ? "stop" : "tool-calls");
42
45
  const interimOn = interim?.enabled() === true;
43
- const isInterim = kind === "tool_calls" && interimOn && completionKind(event.message) === "reply";
46
+ const isInterim = kind === "tool_calls" && interimOn && completionKind(textValue) === "reply";
44
47
  if (kind !== "reply" && !isInterim) return;
45
- const turn = interimOn && typeof event.turnId === "string" && event.turnId !== "" ? JSON.stringify([context.session?.id ?? "", event.turnId]) : void 0;
46
- const key = event.message.trim();
48
+ const turn = interimOn && typeof event.scope?.turnId === "string" && event.scope?.turnId !== "" ? JSON.stringify([context.session?.id ?? "", event.scope?.turnId]) : void 0;
49
+ const key = textValue.trim();
47
50
  if (turn !== void 0 && interim.delivered.has(turn, key)) return;
48
- const message = customerMessage(event.message, confirmationLocale(context.session?.auth.current ?? null, currentLocale()));
51
+ const message = customerMessage(textValue, confirmationLocale(context.session?.auth.current ?? null, currentLocale()));
49
52
  const principal = context.session?.auth.current;
50
53
  const replyTo = principal?.attributes.replyToMessageId;
51
54
  const replyParameters = typeof replyTo === "string" && /^[1-9]\d*$/u.test(replyTo) ? { reply_parameters: {
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { STRUCTURED_KINDS } from "./structured-settings.mjs";
8
- import { d as telegramRuntimeSource, u as runtimeEnvelope } from "../../../_chunks/principal-qyR3jKAr.mjs";
8
+ import { d as telegramRuntimeSource, u as runtimeEnvelope } from "../../../_chunks/principal-BnJuWJtk.mjs";
9
9
  import { workspaceAction } from "./workspace-action.mjs";
10
10
  const record = (value) => {
11
11
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid structured Telegram object.");
@@ -5,4 +5,4 @@ import type { AgentIdentities } from "../identities.js";
5
5
  export declare function telegramFailureEvents(input: {
6
6
  readonly archive: Conversations;
7
7
  readonly identities: () => AgentIdentities;
8
- }): Pick<TelegramChannelEvents, "turn.failed" | "turn.cancelled" | "session.failed" | "authorization.completed" | "authorization.required">;
8
+ }): Pick<TelegramChannelEvents, "turn.settled" | "session.ended" | "interaction.settled" | "interaction.opened">;