@segmentstream/agent 0.18.3 → 0.19.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.
- package/README.md +4 -4
- package/dist/_chunks/{build-metadata-DZ9Nb8Q2.mjs → build-metadata-CZ245Pl3.mjs} +1 -1
- package/dist/_chunks/{inbound-request-8xhK7EaW.mjs → inbound-request-Dx1B6Y5r.mjs} +1 -1
- package/dist/_chunks/{principal-qyR3jKAr.mjs → principal-BnJuWJtk.mjs} +1 -1
- package/dist/extension/_manifest.json +3 -15
- package/dist/extension/connections/ontology.d.ts +1 -1
- package/dist/extension/connections/ontology.mjs +2 -2
- package/dist/extension/hooks/authorization.d.ts +1 -1
- package/dist/extension/hooks/authorization.mjs +3 -3
- package/dist/extension/hooks/ontology-files.d.ts +1 -1
- package/dist/extension/hooks/ontology-files.mjs +3 -1
- package/dist/extension/hooks/sandbox.d.ts +2 -2
- package/dist/extension/hooks/sandbox.mjs +2 -2
- package/dist/extension/instructions/conversations.d.ts +1 -1
- package/dist/extension/instructions/conversations.mjs +3 -3
- package/dist/extension/instructions/sandbox.d.ts +1 -1
- package/dist/extension/instructions/sandbox.mjs +2 -2
- package/dist/extension/instructions.md +13 -12
- package/dist/extension/lib/attachment-tools.mjs +1 -1
- package/dist/extension/lib/build-metadata.mjs +1 -1
- package/dist/extension/lib/confirmations.mjs +3 -3
- package/dist/extension/lib/conversation-runtime.d.ts +2 -2
- package/dist/extension/lib/conversation-runtime.mjs +40 -55
- package/dist/extension/lib/conversations.mjs +1 -1
- package/dist/extension/lib/group-routing/conversation-router.d.ts +1 -1
- package/dist/extension/lib/group-routing/conversation-router.mjs +2 -2
- package/dist/extension/lib/group-routing/dequeue.mjs +2 -2
- package/dist/extension/lib/group-routing/record.mjs +1 -1
- package/dist/extension/lib/group-routing/replay.mjs +1 -1
- package/dist/extension/lib/group-routing/router.d.ts +1 -1
- package/dist/extension/lib/group-routing/router.mjs +3 -3
- package/dist/extension/lib/ontology-connection.mjs +2 -2
- package/dist/extension/lib/ontology-file-call.mjs +2 -2
- package/dist/extension/lib/ontology-tools.mjs +1 -1
- package/dist/extension/lib/runtime-envelope.mjs +1 -1
- package/dist/extension/lib/sandbox.d.ts +3 -2
- package/dist/extension/lib/sandbox.mjs +1 -1
- package/dist/extension/lib/stored-files.mjs +1 -1
- package/dist/extension/lib/telegram/adapter.mjs +43 -28
- package/dist/extension/lib/telegram/archive-message.d.ts +4 -0
- package/dist/extension/lib/telegram/archive-message.mjs +85 -0
- package/dist/extension/lib/telegram/attachment-description.mjs +1 -1
- package/dist/extension/lib/telegram/attachments-send.mjs +2 -2
- package/dist/extension/lib/telegram/callbacks.mjs +2 -2
- package/dist/extension/lib/telegram/confirmation-expiry.mjs +20 -9
- package/dist/extension/lib/telegram/confirmations.d.ts +2 -2
- package/dist/extension/lib/telegram/confirmations.mjs +206 -181
- package/dist/extension/lib/telegram/conversations.mjs +5 -6
- package/dist/extension/lib/telegram/customer-text.mjs +1 -1
- package/dist/extension/lib/telegram/deferred-confirmations.mjs +2 -2
- package/dist/extension/lib/telegram/delivery-diagnostics.mjs +1 -1
- package/dist/extension/lib/telegram/durable-typing.d.ts +11 -0
- package/dist/extension/lib/telegram/durable-typing.mjs +10 -10
- package/dist/extension/lib/telegram/files.mjs +2 -2
- package/dist/extension/lib/telegram/health.mjs +1 -1
- package/dist/extension/lib/telegram/held-approvals.d.ts +3 -3
- package/dist/extension/lib/telegram/held-approvals.mjs +23 -19
- package/dist/extension/lib/telegram/images.d.ts +1 -1
- package/dist/extension/lib/telegram/images.mjs +1 -1
- package/dist/extension/lib/telegram/inbound-request.d.ts +2 -2
- package/dist/extension/lib/telegram/inbound-request.mjs +1 -1
- package/dist/extension/lib/telegram/inbound.mjs +5 -6
- package/dist/extension/lib/telegram/lifecycle.d.ts +2 -2
- package/dist/extension/lib/telegram/lifecycle.mjs +23 -27
- package/dist/extension/lib/telegram/media-policy.mjs +1 -1
- package/dist/extension/lib/telegram/principal.mjs +1 -1
- package/dist/extension/lib/telegram/routing-context.mjs +4 -4
- package/dist/extension/lib/telegram/session-recovery.d.ts +1 -1
- package/dist/extension/lib/telegram/session-recovery.mjs +2 -1
- package/dist/extension/lib/telegram/sessions.d.ts +7 -4
- package/dist/extension/lib/telegram/sessions.mjs +6 -3
- package/dist/extension/lib/telegram/silent.d.ts +1 -1
- package/dist/extension/lib/telegram/silent.mjs +11 -8
- package/dist/extension/lib/telegram/structured.mjs +1 -1
- package/dist/extension/lib/telegram/turn-errors.d.ts +1 -1
- package/dist/extension/lib/telegram/turn-errors.mjs +47 -31
- package/dist/extension/lib/telegram/voice.mjs +1 -1
- package/dist/extension/lib/workflow-serializable.mjs +1 -1
- package/dist/extension/model.mjs +7 -4
- package/dist/extension/tools/attachments_discard.mjs +1 -1
- package/dist/extension/tools/attachments_list.mjs +1 -1
- package/dist/extension/tools/attachments_promote.mjs +2 -2
- package/dist/extension/tools/attachments_read.mjs +1 -1
- package/dist/extension/tools/attachments_send.mjs +1 -1
- package/dist/extension/tools/attachments_table.mjs +1 -1
- package/dist/extension/tools/ontology_call_file.d.ts +1 -1
- package/dist/extension/tools/ontology_call_file.mjs +1 -1
- package/dist/extension/tools/questions_ask.mjs +2 -2
- package/dist/extension/tools/sandbox.d.ts +1 -8
- package/dist/extension/tools/sandbox.mjs +1 -1
- package/package.json +5 -5
- /package/dist/_chunks/{content-TRaZitQZ.mjs → content-cDtVnr8Y.mjs} +0 -0
- /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-
|
|
7
|
+
import { t as agentBuild } from "../../../_chunks/build-metadata-CZ245Pl3.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
|
|
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<
|
|
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: "
|
|
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 === "
|
|
14
|
-
if (event.type === "
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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.
|
|
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-
|
|
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 {
|
|
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<
|
|
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-
|
|
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-
|
|
10
|
-
import { p as reportTelegramError } from "../../../_chunks/inbound-request-
|
|
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.
|
|
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
|
|
508
|
-
|
|
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 {
|
|
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:
|
|
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-
|
|
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-
|
|
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-
|
|
12
|
+
import { t as agentBuild } from "../../../_chunks/build-metadata-CZ245Pl3.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
|
|
87
|
+
const iterator = session.stream({ signal })[Symbol.asyncIterator]();
|
|
88
88
|
let turn;
|
|
89
89
|
let firstResponse = false;
|
|
90
90
|
const abort = () => {
|
|
91
|
-
|
|
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
|
|
97
|
+
const item = await iterator.next();
|
|
98
98
|
if (item.done) break;
|
|
99
99
|
const event = item.value;
|
|
100
|
-
if (event.type === "
|
|
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.
|
|
106
|
+
sessionId: session.sessionId,
|
|
107
107
|
turnId: turn
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
|
-
if (turn && event.
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"turn.
|
|
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.
|
|
119
|
+
sessionId: session.sessionId,
|
|
122
120
|
turnId: turn
|
|
123
121
|
});
|
|
124
|
-
if (turn && !firstResponse &&
|
|
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.
|
|
128
|
+
sessionId: session.sessionId,
|
|
131
129
|
turnId: turn
|
|
132
130
|
});
|
|
133
131
|
}
|
|
134
|
-
if (event.type === "session.
|
|
135
|
-
if (turn &&
|
|
136
|
-
"turn.
|
|
137
|
-
"turn.
|
|
138
|
-
"
|
|
139
|
-
|
|
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
|
|
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-
|
|
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-
|
|
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 === "
|
|
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 === "
|
|
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 === "
|
|
74
|
-
text: data.
|
|
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
|
-
*
|
|
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-
|
|
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 {
|
|
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<
|
|
66
|
+
}) => Promise<import("eve/sessions").Delivery>;
|
|
64
67
|
} | undefined>;
|
|
65
68
|
readonly from: (address: string) => {
|
|
66
69
|
readonly send?: ChannelSource<TelegramChannelState>["send"];
|
|
67
|
-
compact
|
|
68
|
-
clear
|
|
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 === "
|
|
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.
|
|
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["
|
|
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-
|
|
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-
|
|
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,
|
|
41
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
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-
|
|
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.
|
|
8
|
+
}): Pick<TelegramChannelEvents, "turn.settled" | "session.ended" | "interaction.settled" | "interaction.opened">;
|