@llblab/pi-kit 0.27.5 → 0.28.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.
- package/BACKLOG.md +3 -1
- package/CHANGELOG.md +9 -0
- package/README.md +4 -4
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +6 -2
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +4 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +26 -13
- package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +3 -1
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +2 -1
- package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +25 -12
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/AGENTS.md +10 -8
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -9
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +13 -0
- package/node_modules/@llblab/pi-telegram/LICENSE +21 -0
- package/node_modules/@llblab/pi-telegram/README.md +15 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.d.ts +1 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.js +5 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +5 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +6 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.js +4 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +54 -56
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +206 -139
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +21 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +181 -25
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-transport.d.ts +4 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-transport.js +28 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +52 -56
- package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +78 -246
- package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.d.ts +1 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.js +23 -26
- package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.d.ts +0 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.js +5 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +0 -23
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +15 -15
- package/node_modules/@llblab/pi-telegram/dist/lib/config.d.ts +0 -17
- package/node_modules/@llblab/pi-telegram/dist/lib/config.js +12 -14
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +0 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +2 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +255 -61
- package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.d.ts +0 -19
- package/node_modules/@llblab/pi-telegram/dist/lib/inbound.d.ts +0 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/inbound.js +2 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/journal.d.ts +177 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/journal.js +1115 -249
- package/node_modules/@llblab/pi-telegram/dist/lib/keyboard.d.ts +0 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/keyboard.js +2 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/locks.d.ts +100 -12
- package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +380 -14
- package/node_modules/@llblab/pi-telegram/dist/lib/logging.d.ts +30 -12
- package/node_modules/@llblab/pi-telegram/dist/lib/logging.js +129 -72
- package/node_modules/@llblab/pi-telegram/dist/lib/media.d.ts +28 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/media.js +26 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.d.ts +0 -11
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.js +8 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +0 -18
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +18 -18
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.d.ts +4 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.js +12 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.d.ts +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/menu.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/menu.js +4 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.d.ts +0 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-buttons.js +1 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.d.ts +1 -6
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.js +4 -21
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound.d.ts +0 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound.js +5 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/paths.d.ts +50 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/paths.js +155 -17
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/polling.d.ts +0 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +5 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/preview.d.ts +0 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/preview.js +3 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/prompt-templates.d.ts +0 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/prompt-templates.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/queue.d.ts +3 -15
- package/node_modules/@llblab/pi-telegram/dist/lib/queue.js +69 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/recovery.d.ts +29 -9
- package/node_modules/@llblab/pi-telegram/dist/lib/recovery.js +104 -33
- package/node_modules/@llblab/pi-telegram/dist/lib/replies.d.ts +0 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/replies.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +73 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +2206 -307
- package/node_modules/@llblab/pi-telegram/dist/lib/sections.d.ts +0 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/sections.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/status.d.ts +44 -9
- package/node_modules/@llblab/pi-telegram/dist/lib/status.js +149 -27
- package/node_modules/@llblab/pi-telegram/dist/lib/sync.d.ts +0 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +5 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.d.ts +11 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.js +34 -23
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.js +18 -21
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.d.ts +32 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.js +191 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.d.ts +2 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +291 -59
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +1647 -369
- package/node_modules/@llblab/pi-telegram/dist/lib/turns.d.ts +0 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/turns.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +184 -28
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +1032 -114
- package/node_modules/@llblab/pi-telegram/dist/lib/wire.d.ts +12 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/wire.js +21 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.d.ts +25 -17
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.js +95 -20
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-identity.d.ts +20 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-identity.js +103 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +43 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +148 -52
- package/node_modules/@llblab/pi-telegram/dist/package.json +6 -6
- package/node_modules/@llblab/pi-telegram/dist/skills/generated-control-surface/SKILL.md +3 -3
- package/node_modules/@llblab/pi-telegram/dist/skills/telegram-bridge/references/diagnosis.md +3 -3
- package/node_modules/@llblab/pi-telegram/docs/README.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/activity.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +152 -34
- package/node_modules/@llblab/pi-telegram/docs/callback-namespaces.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/delivery.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/generative-apps.md +2 -2
- package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +125 -19
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +3 -1
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +22 -8
- package/node_modules/@llblab/pi-telegram/docs/updates.md +1 -1
- package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +5 -9
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +6 -0
- package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +5 -2
- package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +243 -224
- package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +178 -31
- package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +30 -8
- package/node_modules/@llblab/pi-telegram/lib/bus.ts +110 -334
- package/node_modules/@llblab/pi-telegram/lib/channel-posts.ts +29 -29
- package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +5 -5
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +15 -15
- package/node_modules/@llblab/pi-telegram/lib/config.ts +12 -17
- package/node_modules/@llblab/pi-telegram/lib/delivery.ts +2 -8
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +257 -72
- package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +0 -22
- package/node_modules/@llblab/pi-telegram/lib/inbound.ts +2 -2
- package/node_modules/@llblab/pi-telegram/lib/journal.ts +1182 -326
- package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +2 -2
- package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/locks.ts +402 -23
- package/node_modules/@llblab/pi-telegram/lib/logging.ts +151 -101
- package/node_modules/@llblab/pi-telegram/lib/media.ts +51 -9
- package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +8 -8
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +18 -18
- package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +11 -0
- package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +2 -2
- package/node_modules/@llblab/pi-telegram/lib/menu.ts +5 -1
- package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +1 -10
- package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +5 -24
- package/node_modules/@llblab/pi-telegram/lib/outbound.ts +5 -5
- package/node_modules/@llblab/pi-telegram/lib/paths.ts +177 -17
- package/node_modules/@llblab/pi-telegram/lib/pi.ts +5 -2
- package/node_modules/@llblab/pi-telegram/lib/polling.ts +5 -5
- package/node_modules/@llblab/pi-telegram/lib/preview.ts +3 -3
- package/node_modules/@llblab/pi-telegram/lib/prompt-templates.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/queue.ts +67 -9
- package/node_modules/@llblab/pi-telegram/lib/recovery.ts +104 -44
- package/node_modules/@llblab/pi-telegram/lib/replies.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +1955 -375
- package/node_modules/@llblab/pi-telegram/lib/sections.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/status.ts +156 -36
- package/node_modules/@llblab/pi-telegram/lib/sync.ts +4 -4
- package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +48 -33
- package/node_modules/@llblab/pi-telegram/lib/thread-cleanup-manager.ts +24 -21
- package/node_modules/@llblab/pi-telegram/lib/thread-naming.ts +267 -9
- package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +3 -1
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +1697 -488
- package/node_modules/@llblab/pi-telegram/lib/turns.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +1072 -151
- package/node_modules/@llblab/pi-telegram/lib/wire.ts +28 -0
- package/node_modules/@llblab/pi-telegram/lib/workspace-admission.ts +97 -47
- package/node_modules/@llblab/pi-telegram/lib/workspace-identity.ts +147 -0
- package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +188 -89
- package/node_modules/@llblab/pi-telegram/package.json +6 -6
- package/node_modules/@llblab/pi-telegram/scripts/audit-exports.mjs +100 -0
- package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +80 -43
- package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/SKILL.md +3 -3
- package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/references/diagnosis.md +3 -3
- package/package.json +3 -3
|
@@ -37,6 +37,8 @@ import {
|
|
|
37
37
|
getTelegramBusLeaderEndpoint,
|
|
38
38
|
getTelegramBusPipePath,
|
|
39
39
|
getTelegramBusTransportRetryPolicy,
|
|
40
|
+
type TelegramBusEndpointLayout,
|
|
41
|
+
TELEGRAM_BUS_MAX_DIRECT_UNIX_ENDPOINT_BYTES,
|
|
40
42
|
isTelegramBusPipePath,
|
|
41
43
|
isRetryableTelegramBusTransportError,
|
|
42
44
|
probeTelegramBusEndpoint,
|
|
@@ -44,20 +46,21 @@ import {
|
|
|
44
46
|
type TelegramBusTransportRetryPolicy,
|
|
45
47
|
} from "./bus-transport.ts";
|
|
46
48
|
import {
|
|
47
|
-
|
|
49
|
+
parseTelegramQueueHandoffPayload,
|
|
48
50
|
TELEGRAM_QUEUE_HANDOFF_PAYLOAD_MAX_BYTES,
|
|
49
51
|
type TelegramQueueHandoffPayload,
|
|
50
52
|
} from "./queue.ts";
|
|
51
53
|
import type { TelegramTarget } from "./target.ts";
|
|
52
54
|
import type { TelegramThreadDisplayMode } from "./config.ts";
|
|
53
55
|
import { isProcessAlive } from "./locks.ts";
|
|
56
|
+
import { isWireRecord as isRecord } from "./wire.ts";
|
|
54
57
|
import { resolveAgentDir } from "./paths.ts";
|
|
55
58
|
import {
|
|
56
59
|
normalizeTelegramSessionReplacementIntent,
|
|
57
60
|
type TelegramSessionReplacementIntent,
|
|
58
61
|
} from "./threads.ts";
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
interface TelegramBusProcessRuntime {
|
|
61
64
|
instanceId: string;
|
|
62
65
|
processId: number;
|
|
63
66
|
processBirthId: string;
|
|
@@ -66,19 +69,19 @@ export interface TelegramBusProcessRuntime {
|
|
|
66
69
|
getFollowerSocketPath: () => string;
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
interface TelegramProcessBirthIdentityOptions {
|
|
70
73
|
platform?: NodeJS.Platform;
|
|
71
74
|
readProcStat?: (pid: number) => string;
|
|
72
75
|
readDarwinProcessStart?: (pid: number) => string;
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
|
|
78
|
+
type TelegramProcessBirthProof =
|
|
76
79
|
| { status: "proven"; identity: string }
|
|
77
80
|
| { status: "unverifiable" };
|
|
78
81
|
|
|
79
82
|
export type TelegramProcessLiveness = "alive" | "dead" | "unverifiable";
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
interface TelegramProcessLivenessOptions
|
|
82
85
|
extends TelegramProcessBirthIdentityOptions {
|
|
83
86
|
isProcessAlive?: (pid: number) => boolean;
|
|
84
87
|
}
|
|
@@ -94,7 +97,7 @@ function readDarwinProcessStart(pid: number): string {
|
|
|
94
97
|
).trim();
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
function getTelegramProcessBirthProof(
|
|
98
101
|
pid: number,
|
|
99
102
|
options: TelegramProcessBirthIdentityOptions = {},
|
|
100
103
|
): TelegramProcessBirthProof {
|
|
@@ -175,12 +178,14 @@ export function getTelegramProcessBirthIdentityLiveness(
|
|
|
175
178
|
|
|
176
179
|
export function createCurrentTelegramBusProcessRuntime(input: {
|
|
177
180
|
getActiveProfileName: () => string | undefined;
|
|
181
|
+
endpointLayout?: TelegramBusEndpointLayout;
|
|
178
182
|
pid?: number;
|
|
179
183
|
parentPid?: number;
|
|
180
184
|
createdAtMs?: number;
|
|
181
185
|
}): TelegramBusProcessRuntime {
|
|
182
186
|
return createTelegramBusProcessRuntime({
|
|
183
187
|
getActiveProfileName: input.getActiveProfileName,
|
|
188
|
+
endpointLayout: input.endpointLayout,
|
|
184
189
|
pid: input.pid ?? process.pid,
|
|
185
190
|
parentPid: input.parentPid ?? process.ppid,
|
|
186
191
|
createdAtMs: input.createdAtMs ?? Date.now(),
|
|
@@ -189,11 +194,13 @@ export function createCurrentTelegramBusProcessRuntime(input: {
|
|
|
189
194
|
|
|
190
195
|
export function createTelegramBusProcessRuntime(input: {
|
|
191
196
|
getActiveProfileName: () => string | undefined;
|
|
197
|
+
endpointLayout?: TelegramBusEndpointLayout;
|
|
192
198
|
pid: number;
|
|
193
199
|
parentPid: number;
|
|
194
200
|
parentProcessIdentity?: string;
|
|
195
201
|
createdAtMs: number;
|
|
196
202
|
}): TelegramBusProcessRuntime {
|
|
203
|
+
const getActiveProfileName = input.getActiveProfileName, endpointLayout = input.endpointLayout;
|
|
197
204
|
const instanceId = `${input.pid}:${input.createdAtMs}`;
|
|
198
205
|
const ownerPid = input.parentPid || input.pid;
|
|
199
206
|
const manualFollowerOwnerId =
|
|
@@ -208,14 +215,16 @@ export function createTelegramBusProcessRuntime(input: {
|
|
|
208
215
|
getTelegramBusSocketPath(
|
|
209
216
|
undefined,
|
|
210
217
|
undefined,
|
|
211
|
-
|
|
218
|
+
getActiveProfileName(),
|
|
219
|
+
endpointLayout,
|
|
212
220
|
),
|
|
213
221
|
getFollowerSocketPath: () =>
|
|
214
222
|
getTelegramBusFollowerSocketPath(
|
|
215
223
|
instanceId,
|
|
216
224
|
undefined,
|
|
217
225
|
undefined,
|
|
218
|
-
|
|
226
|
+
getActiveProfileName(),
|
|
227
|
+
endpointLayout,
|
|
219
228
|
),
|
|
220
229
|
};
|
|
221
230
|
}
|
|
@@ -224,7 +233,7 @@ export function createTelegramBusAuthSecret(): string {
|
|
|
224
233
|
return randomBytes(32).toString("base64url");
|
|
225
234
|
}
|
|
226
235
|
|
|
227
|
-
|
|
236
|
+
const TELEGRAM_BUS_PROTOCOL_VERSION = 2 as const;
|
|
228
237
|
export const TELEGRAM_BUS_CAPABILITY_DURABLE_FOLLOWER_ADMISSION =
|
|
229
238
|
"durable-follower-admission-v1" as const;
|
|
230
239
|
export const TELEGRAM_BUS_CAPABILITY_QUEUE_HANDOFF =
|
|
@@ -240,6 +249,15 @@ export const TELEGRAM_BUS_CAPABILITY_WORKSPACE_FOLLOWER_AUTO_CONNECT =
|
|
|
240
249
|
"workspace-follower-auto-connect-v1" as const;
|
|
241
250
|
export const TELEGRAM_BUS_CAPABILITY_SESSION_REPLACEMENT_INTENT =
|
|
242
251
|
"session-replacement-intent-v1" as const;
|
|
252
|
+
export const TELEGRAM_BUS_CAPABILITY_WORKSPACE_RESTORE = "workspace-restore-v1" as const;
|
|
253
|
+
|
|
254
|
+
export interface TelegramBusWorkspaceRestoreObservation {
|
|
255
|
+
operationId: string;
|
|
256
|
+
recipient: { kind: "follower"; instanceId: string; sessionId: string; generation: string };
|
|
257
|
+
target: TelegramTarget & { threadId: number };
|
|
258
|
+
slot: string;
|
|
259
|
+
ready: boolean;
|
|
260
|
+
}
|
|
243
261
|
|
|
244
262
|
export interface TelegramBusProtocolIdentity {
|
|
245
263
|
protocolVersion: number;
|
|
@@ -247,7 +265,7 @@ export interface TelegramBusProtocolIdentity {
|
|
|
247
265
|
capabilities: string[];
|
|
248
266
|
}
|
|
249
267
|
|
|
250
|
-
|
|
268
|
+
interface TelegramBusProtocolCompatibility {
|
|
251
269
|
compatible: boolean;
|
|
252
270
|
reason?: "missing-identity" | "version-mismatch" | "missing-capability";
|
|
253
271
|
missingCapabilities: string[];
|
|
@@ -352,8 +370,9 @@ export function getTelegramBusSocketPath(
|
|
|
352
370
|
agentDir = resolveAgentDir(),
|
|
353
371
|
platform = getPlatform(),
|
|
354
372
|
profileName?: string,
|
|
373
|
+
layout?: TelegramBusEndpointLayout,
|
|
355
374
|
): string {
|
|
356
|
-
return getTelegramBusLeaderEndpoint({ agentDir, platform, profileName });
|
|
375
|
+
return getTelegramBusLeaderEndpoint({ agentDir, platform, profileName, layout });
|
|
357
376
|
}
|
|
358
377
|
|
|
359
378
|
export function getTelegramBusFollowerSocketPath(
|
|
@@ -361,12 +380,14 @@ export function getTelegramBusFollowerSocketPath(
|
|
|
361
380
|
agentDir = resolveAgentDir(),
|
|
362
381
|
platform = getPlatform(),
|
|
363
382
|
profileName?: string,
|
|
383
|
+
layout?: TelegramBusEndpointLayout,
|
|
364
384
|
): string {
|
|
365
385
|
return getTelegramBusFollowerEndpoint({
|
|
366
386
|
agentDir,
|
|
367
387
|
platform,
|
|
368
388
|
instanceId,
|
|
369
389
|
profileName,
|
|
390
|
+
layout,
|
|
370
391
|
});
|
|
371
392
|
}
|
|
372
393
|
|
|
@@ -447,7 +468,7 @@ export function markTelegramBusAggregateDelivery<
|
|
|
447
468
|
};
|
|
448
469
|
}
|
|
449
470
|
|
|
450
|
-
|
|
471
|
+
function isTelegramBusAggregateDelivery(body: unknown): boolean {
|
|
451
472
|
return Boolean(
|
|
452
473
|
body &&
|
|
453
474
|
typeof body === "object" &&
|
|
@@ -466,7 +487,7 @@ export function markTelegramBusCrossTargetDelivery<
|
|
|
466
487
|
};
|
|
467
488
|
}
|
|
468
489
|
|
|
469
|
-
|
|
490
|
+
function isTelegramBusCrossTargetDelivery(body: unknown): boolean {
|
|
470
491
|
return Boolean(
|
|
471
492
|
body &&
|
|
472
493
|
typeof body === "object" &&
|
|
@@ -628,7 +649,7 @@ export function isTelegramFollowerApiCallAllowed(input: {
|
|
|
628
649
|
return false;
|
|
629
650
|
}
|
|
630
651
|
|
|
631
|
-
|
|
652
|
+
interface TelegramFollowerApiCallAuthorizationInput {
|
|
632
653
|
follower: TelegramBusFollowerView;
|
|
633
654
|
method: string;
|
|
634
655
|
args: unknown[];
|
|
@@ -677,7 +698,7 @@ export interface TelegramBusFollowerDeliveryIdentity {
|
|
|
677
698
|
};
|
|
678
699
|
}
|
|
679
700
|
|
|
680
|
-
|
|
701
|
+
type TelegramBusForeignUpdateFailureClass =
|
|
681
702
|
| "source-update-identity-missing"
|
|
682
703
|
| "recipient-binding-missing"
|
|
683
704
|
| "recipient-generation-missing"
|
|
@@ -889,13 +910,12 @@ export type TelegramBusEnvelope = (
|
|
|
889
910
|
sentAtMs: number;
|
|
890
911
|
}
|
|
891
912
|
| {
|
|
892
|
-
kind: "leader.
|
|
913
|
+
kind: "leader.workspaceRestore";
|
|
893
914
|
requestId: string;
|
|
894
915
|
recipientInstanceId: string;
|
|
895
|
-
recipientRegistrationGeneration
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
reason: "thread-restore";
|
|
916
|
+
recipientRegistrationGeneration: string;
|
|
917
|
+
operationId: string;
|
|
918
|
+
mode: "apply" | "inspect";
|
|
899
919
|
sentAtMs: number;
|
|
900
920
|
}
|
|
901
921
|
| {
|
|
@@ -976,7 +996,7 @@ export type TelegramBusEnvelope = (
|
|
|
976
996
|
}
|
|
977
997
|
) & { auth?: string };
|
|
978
998
|
|
|
979
|
-
|
|
999
|
+
type TelegramBusEnvelopeTrafficClass =
|
|
980
1000
|
| "bootstrap"
|
|
981
1001
|
| "generation-fenced"
|
|
982
1002
|
| "response";
|
|
@@ -1114,8 +1134,16 @@ export function parseTelegramBusEnvelope(
|
|
|
1114
1134
|
"leader.forwardEditedMessage",
|
|
1115
1135
|
);
|
|
1116
1136
|
break;
|
|
1117
|
-
case "leader.
|
|
1118
|
-
|
|
1137
|
+
case "leader.workspaceRestore":
|
|
1138
|
+
if (typeof value.recipientInstanceId === "string" && value.recipientInstanceId &&
|
|
1139
|
+
typeof value.recipientRegistrationGeneration === "string" && value.recipientRegistrationGeneration &&
|
|
1140
|
+
typeof value.operationId === "string" && value.operationId.length > 0 && value.operationId.length <= 128 &&
|
|
1141
|
+
(value.mode === "apply" || value.mode === "inspect") &&
|
|
1142
|
+
typeof value.sentAtMs === "number" && Number.isFinite(value.sentAtMs)) {
|
|
1143
|
+
envelope = { kind: "leader.workspaceRestore", requestId, recipientInstanceId: value.recipientInstanceId,
|
|
1144
|
+
recipientRegistrationGeneration: value.recipientRegistrationGeneration, operationId: value.operationId,
|
|
1145
|
+
mode: value.mode, sentAtMs: value.sentAtMs };
|
|
1146
|
+
}
|
|
1119
1147
|
break;
|
|
1120
1148
|
case "leader.offerQueueHandoff":
|
|
1121
1149
|
envelope = parseQueueHandoffEnvelope(
|
|
@@ -1151,7 +1179,7 @@ export function parseTelegramBusEnvelope(
|
|
|
1151
1179
|
return envelope;
|
|
1152
1180
|
}
|
|
1153
1181
|
|
|
1154
|
-
|
|
1182
|
+
interface TelegramBusLocalServer {
|
|
1155
1183
|
start: () => Promise<void>;
|
|
1156
1184
|
stop: () => Promise<void>;
|
|
1157
1185
|
ensureEndpoint: () => Promise<boolean>;
|
|
@@ -1171,8 +1199,6 @@ function getActiveTelegramBusLocalServers(): Map<string, TelegramBusLocalServer>
|
|
|
1171
1199
|
|
|
1172
1200
|
export type TelegramBusSocketPathSource = string | (() => string);
|
|
1173
1201
|
|
|
1174
|
-
const TELEGRAM_BUS_MAX_DIRECT_UNIX_ENDPOINT_BYTES = 80;
|
|
1175
|
-
|
|
1176
1202
|
export function resolveTelegramBusSocketPath(
|
|
1177
1203
|
source: TelegramBusSocketPathSource,
|
|
1178
1204
|
platform: NodeJS.Platform | string = getPlatform(),
|
|
@@ -1205,7 +1231,7 @@ export function resolveTelegramBusSocketPath(
|
|
|
1205
1231
|
return join(fallbackDir, `${digest}.sock`);
|
|
1206
1232
|
}
|
|
1207
1233
|
|
|
1208
|
-
|
|
1234
|
+
interface TelegramBusLocalServerDeps {
|
|
1209
1235
|
socketPath: TelegramBusSocketPathSource;
|
|
1210
1236
|
handleEnvelope: (
|
|
1211
1237
|
envelope: TelegramBusEnvelope,
|
|
@@ -1221,7 +1247,7 @@ export interface TelegramBusLocalServerDeps {
|
|
|
1221
1247
|
) => boolean;
|
|
1222
1248
|
}
|
|
1223
1249
|
|
|
1224
|
-
|
|
1250
|
+
interface TelegramBusLocalClientOptions {
|
|
1225
1251
|
socketPath: string;
|
|
1226
1252
|
envelope: TelegramBusEnvelope;
|
|
1227
1253
|
timeoutMs?: number;
|
|
@@ -1229,7 +1255,7 @@ export interface TelegramBusLocalClientOptions {
|
|
|
1229
1255
|
recordTransportEvent?: TelegramBusTransportEventRecorder;
|
|
1230
1256
|
}
|
|
1231
1257
|
|
|
1232
|
-
|
|
1258
|
+
interface TelegramBusForeignOwnedForwarderDeps<TMessage = unknown> {
|
|
1233
1259
|
socketPath: TelegramBusSocketPathSource;
|
|
1234
1260
|
createRequestId: () => string;
|
|
1235
1261
|
getNowMs?: () => number;
|
|
@@ -1635,14 +1661,6 @@ export function createTelegramBusForeignOwnedUpdateForwarder<
|
|
|
1635
1661
|
};
|
|
1636
1662
|
}
|
|
1637
1663
|
|
|
1638
|
-
export interface TelegramBusFollowerThreadRestoreHandlerDeps {
|
|
1639
|
-
followerRegistry: Pick<TelegramBusFollowerRegistry, "get" | "register">;
|
|
1640
|
-
followerTargetController: ReturnType<
|
|
1641
|
-
typeof createTelegramBusFollowerTargetController
|
|
1642
|
-
>;
|
|
1643
|
-
onRestored?: () => void;
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
1664
|
export function listTelegramBusLiveThreadTargets(input: {
|
|
1647
1665
|
leaderTarget?: TelegramTarget;
|
|
1648
1666
|
followers: readonly TelegramBusFollowerView[];
|
|
@@ -1657,79 +1675,58 @@ export function listTelegramBusLiveThreadTargets(input: {
|
|
|
1657
1675
|
return targets;
|
|
1658
1676
|
}
|
|
1659
1677
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
} {
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
follower.target?.chatId !== oldTarget.chatId ||
|
|
1713
|
-
follower.target.threadId !== oldTarget.threadId ||
|
|
1714
|
-
target.chatId !== oldTarget.chatId || target.threadId === oldTarget.threadId) return false;
|
|
1715
|
-
const replaced = await deps.followerTargetController.replaceTarget({
|
|
1716
|
-
follower,
|
|
1717
|
-
target,
|
|
1718
|
-
oldTarget,
|
|
1719
|
-
reason: "thread-restore",
|
|
1720
|
-
});
|
|
1721
|
-
const current = deps.followerRegistry.get(record.instanceId);
|
|
1722
|
-
if (!replaced || !current ||
|
|
1723
|
-
current.registrationGeneration !== follower.registrationGeneration ||
|
|
1724
|
-
current.target?.chatId !== oldTarget.chatId ||
|
|
1725
|
-
current.target.threadId !== oldTarget.threadId) return false;
|
|
1726
|
-
deps.followerRegistry.register({
|
|
1727
|
-
...current,
|
|
1728
|
-
target,
|
|
1729
|
-
connectedAtMs: current.connectedAtMs,
|
|
1730
|
-
});
|
|
1731
|
-
deps.onRestored?.();
|
|
1732
|
-
return true;
|
|
1678
|
+
/** Caller owns the durable one-shot apply grant. Inspections never grant another apply. */
|
|
1679
|
+
export function createTelegramBusWorkspaceRestoreController(deps: {
|
|
1680
|
+
getFollower: (instanceId: string) => TelegramBusFollowerView | undefined;
|
|
1681
|
+
localProtocolIdentity: TelegramBusProtocolIdentity;
|
|
1682
|
+
createRequestId: () => string;
|
|
1683
|
+
getAuthSecret: () => string | undefined;
|
|
1684
|
+
timeoutMs?: number;
|
|
1685
|
+
}) {
|
|
1686
|
+
return async (input: { operationId: string; instanceId: string; sessionId: string; slot: string;
|
|
1687
|
+
target: TelegramTarget & { threadId: number }; oldTarget: TelegramTarget & { threadId: number };
|
|
1688
|
+
mode: "apply" | "inspect"; isCurrent: () => boolean }): Promise<TelegramBusWorkspaceRestoreObservation | undefined> => {
|
|
1689
|
+
const isCurrent = input.isCurrent.bind(input);
|
|
1690
|
+
if (!isCurrent()) return undefined;
|
|
1691
|
+
const follower = deps.getFollower(input.instanceId);
|
|
1692
|
+
const secret = deps.getAuthSecret();
|
|
1693
|
+
if (!secret || !follower?.registrationGeneration || !follower.busSocketPath ||
|
|
1694
|
+
follower.sessionId !== input.sessionId || follower.slot !== input.slot ||
|
|
1695
|
+
!hasTelegramBusCapability(deps.localProtocolIdentity, TELEGRAM_BUS_CAPABILITY_WORKSPACE_RESTORE) ||
|
|
1696
|
+
!hasTelegramBusCapability(follower.protocol, TELEGRAM_BUS_CAPABILITY_WORKSPACE_RESTORE) ||
|
|
1697
|
+
!getTelegramBusProtocolCompatibility({ local: deps.localProtocolIdentity, remote: follower.protocol }).compatible) return undefined;
|
|
1698
|
+
const captured = structuredClone(follower);
|
|
1699
|
+
const expected = { operationId: input.operationId, sessionId: input.sessionId, slot: input.slot,
|
|
1700
|
+
target: { ...input.target }, oldTarget: { ...input.oldTarget }, mode: input.mode };
|
|
1701
|
+
const current = (): boolean => {
|
|
1702
|
+
if (!isCurrent() || deps.getAuthSecret() !== secret ||
|
|
1703
|
+
!hasTelegramBusCapability(deps.localProtocolIdentity, TELEGRAM_BUS_CAPABILITY_WORKSPACE_RESTORE)) return false;
|
|
1704
|
+
const live = deps.getFollower(captured.instanceId);
|
|
1705
|
+
return !!live && live.registrationGeneration === captured.registrationGeneration &&
|
|
1706
|
+
live.sessionId === captured.sessionId && live.cwd === captured.cwd && live.slot === captured.slot &&
|
|
1707
|
+
live.busSocketPath === captured.busSocketPath && live.target?.chatId === captured.target?.chatId &&
|
|
1708
|
+
live.target?.threadId === captured.target?.threadId &&
|
|
1709
|
+
hasTelegramBusCapability(live.protocol, TELEGRAM_BUS_CAPABILITY_WORKSPACE_RESTORE) &&
|
|
1710
|
+
getTelegramBusProtocolCompatibility({ local: deps.localProtocolIdentity, remote: live.protocol }).compatible;
|
|
1711
|
+
};
|
|
1712
|
+
if (!current()) return undefined;
|
|
1713
|
+
const requestId = deps.createRequestId();
|
|
1714
|
+
const response = await sendTelegramBusLocalEnvelope({ socketPath: captured.busSocketPath!, timeoutMs: deps.timeoutMs,
|
|
1715
|
+
retry: { attempts: 1, delayMs: 0 }, envelope: { kind: "leader.workspaceRestore", requestId,
|
|
1716
|
+
recipientInstanceId: captured.instanceId, recipientRegistrationGeneration: captured.registrationGeneration!,
|
|
1717
|
+
operationId: expected.operationId, mode: expected.mode, auth: secret, sentAtMs: Date.now() } });
|
|
1718
|
+
if (!current() || response?.kind !== "bus.ack" || response.requestId !== requestId || response.ok !== true ||
|
|
1719
|
+
!response.result || typeof response.result !== "object") return undefined;
|
|
1720
|
+
const result = response.result as Record<string, unknown>;
|
|
1721
|
+
const recipient = result.recipient as Record<string, unknown> | undefined;
|
|
1722
|
+
const target = parseThreadTarget(result.target);
|
|
1723
|
+
const wanted = result.ready === true ? expected.target : expected.oldTarget;
|
|
1724
|
+
if (result.operationId !== expected.operationId || typeof result.ready !== "boolean" || result.slot !== expected.slot ||
|
|
1725
|
+
!target || target.chatId !== wanted.chatId || target.threadId !== wanted.threadId ||
|
|
1726
|
+
recipient?.kind !== "follower" || recipient.instanceId !== captured.instanceId ||
|
|
1727
|
+
recipient.sessionId !== expected.sessionId || recipient.generation !== captured.registrationGeneration) return undefined;
|
|
1728
|
+
return { operationId: expected.operationId, recipient: { kind: "follower", instanceId: captured.instanceId,
|
|
1729
|
+
sessionId: expected.sessionId, generation: captured.registrationGeneration! }, target, slot: expected.slot, ready: result.ready };
|
|
1733
1730
|
};
|
|
1734
1731
|
}
|
|
1735
1732
|
|
|
@@ -1817,14 +1814,8 @@ export function createTelegramBusLocalServer(
|
|
|
1817
1814
|
result: Promise.resolve().then(() => deps.handleEnvelope(envelope)),
|
|
1818
1815
|
};
|
|
1819
1816
|
requestLedger.set(key, entry);
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
entry.settled = true;
|
|
1823
|
-
},
|
|
1824
|
-
() => {
|
|
1825
|
-
entry.settled = true;
|
|
1826
|
-
},
|
|
1827
|
-
);
|
|
1817
|
+
const settled = () => { entry.settled = true; };
|
|
1818
|
+
void entry.result.then(settled, settled);
|
|
1828
1819
|
return entry.result;
|
|
1829
1820
|
};
|
|
1830
1821
|
let server: Server | undefined;
|
|
@@ -2572,217 +2563,6 @@ function parseWakeInputCustodyEnvelope(
|
|
|
2572
2563
|
: undefined;
|
|
2573
2564
|
}
|
|
2574
2565
|
|
|
2575
|
-
function parseReplaceFollowerTargetEnvelope(
|
|
2576
|
-
value: Record<string, unknown>,
|
|
2577
|
-
requestId: string,
|
|
2578
|
-
): TelegramBusEnvelope | undefined {
|
|
2579
|
-
const target = parseThreadTarget(value.target);
|
|
2580
|
-
const oldTarget = parseThreadTarget(value.oldTarget);
|
|
2581
|
-
if (
|
|
2582
|
-
typeof value.recipientInstanceId !== "string" ||
|
|
2583
|
-
!target ||
|
|
2584
|
-
(value.oldTarget !== undefined && !oldTarget) ||
|
|
2585
|
-
value.reason !== "thread-restore" ||
|
|
2586
|
-
typeof value.sentAtMs !== "number"
|
|
2587
|
-
) {
|
|
2588
|
-
return undefined;
|
|
2589
|
-
}
|
|
2590
|
-
return {
|
|
2591
|
-
kind: "leader.replaceFollowerTarget",
|
|
2592
|
-
requestId,
|
|
2593
|
-
recipientInstanceId: value.recipientInstanceId,
|
|
2594
|
-
...(typeof value.recipientRegistrationGeneration === "string"
|
|
2595
|
-
? {
|
|
2596
|
-
recipientRegistrationGeneration:
|
|
2597
|
-
value.recipientRegistrationGeneration,
|
|
2598
|
-
}
|
|
2599
|
-
: {}),
|
|
2600
|
-
target,
|
|
2601
|
-
...(oldTarget ? { oldTarget } : {}),
|
|
2602
|
-
reason: value.reason,
|
|
2603
|
-
sentAtMs: value.sentAtMs,
|
|
2604
|
-
};
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
|
-
function parseQueueAdmissionReceipt(
|
|
2608
|
-
value: unknown,
|
|
2609
|
-
queueKind: "prompt" | "control",
|
|
2610
|
-
):
|
|
2611
|
-
| {
|
|
2612
|
-
queueKind: "prompt" | "control";
|
|
2613
|
-
receiptId: string;
|
|
2614
|
-
sourceUpdateIds: number[];
|
|
2615
|
-
}
|
|
2616
|
-
| undefined {
|
|
2617
|
-
if (!isRecord(value) || value.queueKind !== queueKind) return undefined;
|
|
2618
|
-
const sourceUpdateIds = Array.isArray(value.sourceUpdateIds)
|
|
2619
|
-
? value.sourceUpdateIds
|
|
2620
|
-
: undefined;
|
|
2621
|
-
if (
|
|
2622
|
-
typeof value.receiptId !== "string" ||
|
|
2623
|
-
!value.receiptId ||
|
|
2624
|
-
(value.journalBindingKey !== undefined &&
|
|
2625
|
-
(typeof value.journalBindingKey !== "string" ||
|
|
2626
|
-
!value.journalBindingKey.trim())) ||
|
|
2627
|
-
!sourceUpdateIds ||
|
|
2628
|
-
sourceUpdateIds.length === 0 ||
|
|
2629
|
-
sourceUpdateIds.some(
|
|
2630
|
-
(updateId, index) =>
|
|
2631
|
-
!Number.isSafeInteger(updateId) ||
|
|
2632
|
-
(updateId as number) < 0 ||
|
|
2633
|
-
(index > 0 &&
|
|
2634
|
-
(updateId as number) <=
|
|
2635
|
-
(sourceUpdateIds[index - 1] as number)),
|
|
2636
|
-
)
|
|
2637
|
-
) {
|
|
2638
|
-
return undefined;
|
|
2639
|
-
}
|
|
2640
|
-
return {
|
|
2641
|
-
queueKind,
|
|
2642
|
-
receiptId: value.receiptId,
|
|
2643
|
-
sourceUpdateIds: sourceUpdateIds as number[],
|
|
2644
|
-
...(typeof value.journalBindingKey === "string"
|
|
2645
|
-
? { journalBindingKey: value.journalBindingKey }
|
|
2646
|
-
: {}),
|
|
2647
|
-
};
|
|
2648
|
-
}
|
|
2649
|
-
|
|
2650
|
-
function parseQueueHandoffPayload(
|
|
2651
|
-
value: unknown,
|
|
2652
|
-
): TelegramQueueHandoffPayload | undefined {
|
|
2653
|
-
if (!isRecord(value) || (value.kind !== "prompt" && value.kind !== "control")) {
|
|
2654
|
-
return undefined;
|
|
2655
|
-
}
|
|
2656
|
-
const queueKind = value.kind;
|
|
2657
|
-
const target = parseTarget(value.target);
|
|
2658
|
-
const transportStamp = isRecord(value.transportStamp) &&
|
|
2659
|
-
typeof value.transportStamp.profile === "string" &&
|
|
2660
|
-
typeof value.transportStamp.generation === "string"
|
|
2661
|
-
? {
|
|
2662
|
-
profile: value.transportStamp.profile,
|
|
2663
|
-
generation: value.transportStamp.generation,
|
|
2664
|
-
}
|
|
2665
|
-
: undefined;
|
|
2666
|
-
if (
|
|
2667
|
-
!Number.isSafeInteger(value.chatId) ||
|
|
2668
|
-
(value.target !== undefined && !target) ||
|
|
2669
|
-
(value.transportStamp !== undefined && !transportStamp) ||
|
|
2670
|
-
!Number.isSafeInteger(value.replyToMessageId) ||
|
|
2671
|
-
(value.guestQueryId !== undefined &&
|
|
2672
|
-
typeof value.guestQueryId !== "string") ||
|
|
2673
|
-
(value.guestInlineMessageId !== undefined &&
|
|
2674
|
-
typeof value.guestInlineMessageId !== "string") ||
|
|
2675
|
-
!Number.isSafeInteger(value.queueOrder) ||
|
|
2676
|
-
(value.queueLane !== "control" &&
|
|
2677
|
-
value.queueLane !== "priority" &&
|
|
2678
|
-
value.queueLane !== "default") ||
|
|
2679
|
-
!Number.isSafeInteger(value.laneOrder) ||
|
|
2680
|
-
typeof value.statusSummary !== "string" ||
|
|
2681
|
-
!Array.isArray(value.admissionReceipts)
|
|
2682
|
-
) {
|
|
2683
|
-
return undefined;
|
|
2684
|
-
}
|
|
2685
|
-
const admissionReceipts = value.admissionReceipts.map((receipt) =>
|
|
2686
|
-
parseQueueAdmissionReceipt(receipt, queueKind),
|
|
2687
|
-
);
|
|
2688
|
-
if (
|
|
2689
|
-
admissionReceipts.length === 0 ||
|
|
2690
|
-
admissionReceipts.length > TELEGRAM_QUEUE_HANDOFF_MAX_RECEIPTS ||
|
|
2691
|
-
admissionReceipts.some((receipt) => receipt === undefined)
|
|
2692
|
-
) {
|
|
2693
|
-
return undefined;
|
|
2694
|
-
}
|
|
2695
|
-
const queueLane = value.queueLane as "control" | "priority" | "default";
|
|
2696
|
-
const base = {
|
|
2697
|
-
chatId: value.chatId as number,
|
|
2698
|
-
...(target ? { target } : {}),
|
|
2699
|
-
...(transportStamp ? { transportStamp } : {}),
|
|
2700
|
-
replyToMessageId: value.replyToMessageId as number,
|
|
2701
|
-
...(typeof value.guestQueryId === "string"
|
|
2702
|
-
? { guestQueryId: value.guestQueryId }
|
|
2703
|
-
: {}),
|
|
2704
|
-
...(typeof value.guestInlineMessageId === "string"
|
|
2705
|
-
? { guestInlineMessageId: value.guestInlineMessageId }
|
|
2706
|
-
: {}),
|
|
2707
|
-
queueOrder: value.queueOrder as number,
|
|
2708
|
-
queueLane,
|
|
2709
|
-
laneOrder: value.laneOrder as number,
|
|
2710
|
-
statusSummary: value.statusSummary,
|
|
2711
|
-
admissionReceipts: admissionReceipts as NonNullable<
|
|
2712
|
-
(typeof admissionReceipts)[number]
|
|
2713
|
-
>[],
|
|
2714
|
-
};
|
|
2715
|
-
if (queueKind === "control") {
|
|
2716
|
-
if (
|
|
2717
|
-
value.queueLane !== "control" ||
|
|
2718
|
-
(value.controlType !== "status" && value.controlType !== "model")
|
|
2719
|
-
) {
|
|
2720
|
-
return undefined;
|
|
2721
|
-
}
|
|
2722
|
-
return { kind: "control", controlType: value.controlType, ...base };
|
|
2723
|
-
}
|
|
2724
|
-
if (
|
|
2725
|
-
value.queueLane === "control" ||
|
|
2726
|
-
!Array.isArray(value.sourceMessageIds) ||
|
|
2727
|
-
value.sourceMessageIds.some((id) => !Number.isSafeInteger(id)) ||
|
|
2728
|
-
!Array.isArray(value.queuedAttachments) ||
|
|
2729
|
-
value.queuedAttachments.some(
|
|
2730
|
-
(attachment) =>
|
|
2731
|
-
!isRecord(attachment) ||
|
|
2732
|
-
typeof attachment.path !== "string" ||
|
|
2733
|
-
typeof attachment.fileName !== "string",
|
|
2734
|
-
) ||
|
|
2735
|
-
!Array.isArray(value.content) ||
|
|
2736
|
-
value.content.some(
|
|
2737
|
-
(content) =>
|
|
2738
|
-
!isRecord(content) ||
|
|
2739
|
-
(content.type === "text"
|
|
2740
|
-
? typeof content.text !== "string"
|
|
2741
|
-
: content.type === "image"
|
|
2742
|
-
? typeof content.data !== "string" ||
|
|
2743
|
-
typeof content.mimeType !== "string"
|
|
2744
|
-
: true),
|
|
2745
|
-
) ||
|
|
2746
|
-
typeof value.historyText !== "string" ||
|
|
2747
|
-
(value.priorityEmoji !== undefined &&
|
|
2748
|
-
typeof value.priorityEmoji !== "string") ||
|
|
2749
|
-
(value.reactionSuppressionEmoji !== undefined &&
|
|
2750
|
-
typeof value.reactionSuppressionEmoji !== "string") ||
|
|
2751
|
-
(value.voiceReplyPreferred !== undefined &&
|
|
2752
|
-
typeof value.voiceReplyPreferred !== "boolean") ||
|
|
2753
|
-
(value.voiceReplyRequired !== undefined &&
|
|
2754
|
-
typeof value.voiceReplyRequired !== "boolean")
|
|
2755
|
-
) {
|
|
2756
|
-
return undefined;
|
|
2757
|
-
}
|
|
2758
|
-
return {
|
|
2759
|
-
kind: "prompt",
|
|
2760
|
-
...base,
|
|
2761
|
-
sourceMessageIds: value.sourceMessageIds as number[],
|
|
2762
|
-
queuedAttachments: value.queuedAttachments as Array<{
|
|
2763
|
-
path: string;
|
|
2764
|
-
fileName: string;
|
|
2765
|
-
}>,
|
|
2766
|
-
content: value.content as Array<
|
|
2767
|
-
| { type: "text"; text: string }
|
|
2768
|
-
| { type: "image"; data: string; mimeType: string }
|
|
2769
|
-
>,
|
|
2770
|
-
historyText: value.historyText,
|
|
2771
|
-
...(typeof value.priorityEmoji === "string"
|
|
2772
|
-
? { priorityEmoji: value.priorityEmoji }
|
|
2773
|
-
: {}),
|
|
2774
|
-
...(typeof value.reactionSuppressionEmoji === "string"
|
|
2775
|
-
? { reactionSuppressionEmoji: value.reactionSuppressionEmoji }
|
|
2776
|
-
: {}),
|
|
2777
|
-
...(typeof value.voiceReplyPreferred === "boolean"
|
|
2778
|
-
? { voiceReplyPreferred: value.voiceReplyPreferred }
|
|
2779
|
-
: {}),
|
|
2780
|
-
...(typeof value.voiceReplyRequired === "boolean"
|
|
2781
|
-
? { voiceReplyRequired: value.voiceReplyRequired }
|
|
2782
|
-
: {}),
|
|
2783
|
-
};
|
|
2784
|
-
}
|
|
2785
|
-
|
|
2786
2566
|
function parseQueueHandoffEnvelope(
|
|
2787
2567
|
value: Record<string, unknown>,
|
|
2788
2568
|
requestId: string,
|
|
@@ -2797,7 +2577,7 @@ function parseQueueHandoffEnvelope(
|
|
|
2797
2577
|
if (serializedPayloadBytes > TELEGRAM_QUEUE_HANDOFF_PAYLOAD_MAX_BYTES) {
|
|
2798
2578
|
return undefined;
|
|
2799
2579
|
}
|
|
2800
|
-
const payload =
|
|
2580
|
+
const payload = parseTelegramQueueHandoffPayload(value.payload);
|
|
2801
2581
|
if (
|
|
2802
2582
|
!payload ||
|
|
2803
2583
|
typeof value.recipientInstanceId !== "string" ||
|
|
@@ -3102,7 +2882,3 @@ function parseThreadTarget(
|
|
|
3102
2882
|
? { chatId: target.chatId, threadId: target.threadId }
|
|
3103
2883
|
: undefined;
|
|
3104
2884
|
}
|
|
3105
|
-
|
|
3106
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
3107
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3108
|
-
}
|