@llblab/pi-telegram 0.52.2 → 0.53.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/AGENTS.md +9 -7
- package/BACKLOG.md +1 -18
- package/CHANGELOG.md +11 -0
- package/README.md +7 -11
- package/api/commands.ts +3 -0
- package/dist/api/commands.d.ts +1 -1
- package/dist/lib/activity-verbosity.d.ts +1 -5
- package/dist/lib/activity-verbosity.js +15 -42
- package/dist/lib/activity.d.ts +9 -0
- package/dist/lib/activity.js +39 -10
- package/dist/lib/agent-messages.js +7 -3
- package/dist/lib/bindings.d.ts +43 -5
- package/dist/lib/bindings.js +163 -20
- package/dist/lib/bus-api.d.ts +12 -0
- package/dist/lib/bus-api.js +182 -79
- package/dist/lib/bus-follower.d.ts +111 -31
- package/dist/lib/bus-follower.js +1324 -359
- package/dist/lib/bus-leader.d.ts +41 -91
- package/dist/lib/bus-leader.js +969 -637
- package/dist/lib/bus-transport.js +16 -9
- package/dist/lib/bus.d.ts +215 -18
- package/dist/lib/bus.js +1048 -327
- package/dist/lib/channel-posts.d.ts +5 -0
- package/dist/lib/channel-posts.js +434 -261
- package/dist/lib/command-templates.d.ts +26 -5
- package/dist/lib/command-templates.js +92 -176
- package/dist/lib/commands.d.ts +168 -82
- package/dist/lib/commands.js +1409 -291
- package/dist/lib/config.d.ts +1 -8
- package/dist/lib/config.js +34 -76
- package/dist/lib/delivery.d.ts +2 -2
- package/dist/lib/delivery.js +16 -16
- package/dist/lib/extension.js +639 -171
- package/dist/lib/generative-app-worker.mjs +19 -7
- package/dist/lib/generative-apps.d.ts +0 -5
- package/dist/lib/generative-apps.js +61 -49
- package/dist/lib/inbound.d.ts +5 -0
- package/dist/lib/inbound.js +35 -59
- package/dist/lib/journal.d.ts +33 -3
- package/dist/lib/journal.js +2063 -782
- package/dist/lib/lifecycle.d.ts +2 -6
- package/dist/lib/lifecycle.js +75 -58
- package/dist/lib/locks.d.ts +29 -3
- package/dist/lib/locks.js +289 -108
- package/dist/lib/logging.js +50 -14
- package/dist/lib/media.d.ts +22 -1
- package/dist/lib/media.js +46 -28
- package/dist/lib/menu-model.d.ts +19 -5
- package/dist/lib/menu-model.js +53 -11
- package/dist/lib/menu-queue.d.ts +5 -4
- package/dist/lib/menu-queue.js +45 -63
- package/dist/lib/menu-settings.d.ts +5 -4
- package/dist/lib/menu-settings.js +114 -78
- package/dist/lib/menu-status.d.ts +1 -1
- package/dist/lib/menu-status.js +8 -25
- package/dist/lib/menu-thinking.d.ts +6 -1
- package/dist/lib/menu-thinking.js +14 -21
- package/dist/lib/menu.d.ts +8 -61
- package/dist/lib/menu.js +92 -164
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/model.js +2 -16
- package/dist/lib/outbound-attachments.d.ts +6 -27
- package/dist/lib/outbound-attachments.js +45 -38
- package/dist/lib/outbound-buttons.js +22 -16
- package/dist/lib/outbound-markup.d.ts +0 -2
- package/dist/lib/outbound-markup.js +51 -64
- package/dist/lib/outbound-voice.js +6 -3
- package/dist/lib/outbound.d.ts +6 -6
- package/dist/lib/outbound.js +61 -51
- package/dist/lib/ownership.js +6 -2
- package/dist/lib/paths.d.ts +5 -0
- package/dist/lib/paths.js +37 -21
- package/dist/lib/pi.d.ts +2 -0
- package/dist/lib/pi.js +8 -1
- package/dist/lib/polling.d.ts +21 -37
- package/dist/lib/polling.js +59 -50
- package/dist/lib/preview.js +39 -19
- package/dist/lib/process-identity.d.ts +24 -0
- package/dist/lib/process-identity.js +133 -0
- package/dist/lib/prompts.js +2 -7
- package/dist/lib/queue.d.ts +14 -16
- package/dist/lib/queue.js +249 -126
- package/dist/lib/recovery.d.ts +2 -83
- package/dist/lib/recovery.js +20 -274
- package/dist/lib/replies.d.ts +16 -24
- package/dist/lib/replies.js +99 -116
- package/dist/lib/routing.d.ts +120 -7
- package/dist/lib/routing.js +4667 -1152
- package/dist/lib/runtime.d.ts +1 -11
- package/dist/lib/sections.d.ts +4 -29
- package/dist/lib/sections.js +7 -20
- package/dist/lib/skills.js +4 -3
- package/dist/lib/status.js +86 -57
- package/dist/lib/sync.d.ts +1 -3
- package/dist/lib/sync.js +67 -43
- package/dist/lib/target.d.ts +4 -0
- package/dist/lib/target.js +18 -0
- package/dist/lib/telegram-api.d.ts +18 -13
- package/dist/lib/telegram-api.js +148 -53
- package/dist/lib/text-groups.js +4 -39
- package/dist/lib/thread-cleanup-manager.d.ts +6 -27
- package/dist/lib/thread-cleanup-manager.js +369 -186
- package/dist/lib/thread-display.d.ts +1 -2
- package/dist/lib/thread-display.js +58 -38
- package/dist/lib/thread-naming.d.ts +28 -8
- package/dist/lib/thread-naming.js +175 -66
- package/dist/lib/thread-reconciler.d.ts +42 -16
- package/dist/lib/thread-reconciler.js +90 -50
- package/dist/lib/threads.d.ts +82 -20
- package/dist/lib/threads.js +2247 -855
- package/dist/lib/time-injection.js +1 -2
- package/dist/lib/turns.js +1 -19
- package/dist/lib/updates.d.ts +169 -80
- package/dist/lib/updates.js +2418 -641
- package/dist/lib/voice.d.ts +7 -22
- package/dist/lib/voice.js +7 -22
- package/dist/lib/wire.js +1 -1
- package/dist/lib/workspace-admission.d.ts +3 -1
- package/dist/lib/workspace-admission.js +425 -211
- package/dist/lib/workspace-identity.js +8 -13
- package/dist/lib/workspace-retirement.d.ts +1 -1
- package/dist/lib/workspace-retirement.js +328 -140
- package/dist/lib/workspace-slots.js +8 -4
- package/dist/package.json +1 -1
- package/docs/architecture.md +31 -29
- package/docs/inbound.md +1 -1
- package/docs/multi-instance-bus.md +15 -3
- package/docs/outbound.md +1 -1
- package/docs/public-api.md +29 -1
- package/docs/ui-style.md +25 -8
- package/lib/activity-verbosity.ts +59 -82
- package/lib/activity.ts +146 -102
- package/lib/agent-messages.ts +12 -5
- package/lib/bindings.ts +389 -82
- package/lib/bus-api.ts +263 -102
- package/lib/bus-follower.ts +2440 -601
- package/lib/bus-leader.ts +2209 -1290
- package/lib/bus-transport.ts +46 -12
- package/lib/bus.ts +1673 -444
- package/lib/channel-posts.ts +848 -327
- package/lib/command-templates.ts +152 -265
- package/lib/commands.ts +2398 -555
- package/lib/config.ts +177 -170
- package/lib/delivery.ts +41 -29
- package/lib/extension.ts +1206 -433
- package/lib/generative-app-worker.mjs +19 -7
- package/lib/generative-apps.ts +324 -211
- package/lib/inbound.ts +95 -97
- package/lib/journal.ts +5311 -1763
- package/lib/keyboard.ts +1 -3
- package/lib/lifecycle.ts +128 -78
- package/lib/locks.ts +677 -203
- package/lib/logging.ts +147 -58
- package/lib/media.ts +82 -43
- package/lib/menu-model.ts +85 -18
- package/lib/menu-queue.ts +88 -129
- package/lib/menu-settings.ts +260 -155
- package/lib/menu-status.ts +20 -60
- package/lib/menu-thinking.ts +41 -56
- package/lib/menu.ts +112 -285
- package/lib/model.ts +8 -22
- package/lib/outbound-attachments.ts +156 -125
- package/lib/outbound-buttons.ts +76 -49
- package/lib/outbound-markup.ts +96 -94
- package/lib/outbound-voice.ts +33 -27
- package/lib/outbound.ts +125 -125
- package/lib/ownership.ts +19 -10
- package/lib/paths.ts +148 -49
- package/lib/pi.ts +35 -15
- package/lib/polling.ts +144 -147
- package/lib/preview.ts +93 -40
- package/lib/process-identity.ts +164 -0
- package/lib/prompts.ts +4 -11
- package/lib/queue.ts +511 -300
- package/lib/recovery.ts +50 -454
- package/lib/rendering.ts +1 -3
- package/lib/replies.ts +248 -209
- package/lib/routing.ts +8509 -2186
- package/lib/runtime.ts +1 -12
- package/lib/sections.ts +24 -89
- package/lib/setup.ts +1 -3
- package/lib/skills.ts +9 -4
- package/lib/status.ts +215 -110
- package/lib/sync.ts +448 -361
- package/lib/target.ts +22 -3
- package/lib/telegram-api.ts +302 -127
- package/lib/text-groups.ts +5 -39
- package/lib/thread-cleanup-manager.ts +833 -331
- package/lib/thread-display.ts +213 -97
- package/lib/thread-naming.ts +232 -87
- package/lib/thread-reconciler.ts +155 -72
- package/lib/threads.ts +5318 -1845
- package/lib/time-injection.ts +1 -4
- package/lib/turns.ts +15 -28
- package/lib/updates.ts +5184 -1612
- package/lib/voice.ts +7 -35
- package/lib/wire.ts +1 -1
- package/lib/workspace-admission.ts +996 -416
- package/lib/workspace-identity.ts +14 -17
- package/lib/workspace-retirement.ts +878 -376
- package/lib/workspace-slots.ts +22 -13
- package/package.json +1 -1
- package/scripts/check-downgrade.mjs +0 -472
- package/scripts/measure-workspace.mjs +0 -108
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { execFile } from "node:child_process";
|
|
8
|
-
import { parentPort, workerData } from "node:worker_threads";
|
|
9
8
|
import { pathToFileURL } from "node:url";
|
|
9
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
10
10
|
|
|
11
|
-
if (!parentPort)
|
|
11
|
+
if (!parentPort) {
|
|
12
|
+
throw new Error("Generative App worker requires a parent port.");
|
|
13
|
+
}
|
|
12
14
|
|
|
13
15
|
const controller = new AbortController();
|
|
14
16
|
const runningChildren = new Set();
|
|
@@ -25,11 +27,17 @@ function runBoundedProcess(input) {
|
|
|
25
27
|
}
|
|
26
28
|
const command = input.command?.trim();
|
|
27
29
|
if (!command) throw new Error("Generative App run.command is required.");
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
+
if (
|
|
31
|
+
!Array.isArray(input.args ?? []) ||
|
|
32
|
+
(input.args?.length ?? 0) > workerData.runMaxArgs
|
|
33
|
+
) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Generative App run.args accepts at most ${workerData.runMaxArgs} strings.`,
|
|
36
|
+
);
|
|
30
37
|
}
|
|
31
38
|
const args = (input.args ?? []).map((argument) => {
|
|
32
|
-
if (typeof argument !== "string")
|
|
39
|
+
if (typeof argument !== "string")
|
|
40
|
+
throw new Error("Generative App run.args must contain strings.");
|
|
33
41
|
return argument;
|
|
34
42
|
});
|
|
35
43
|
if (!input.cwd || typeof input.cwd !== "string") {
|
|
@@ -82,11 +90,15 @@ function runBoundedProcess(input) {
|
|
|
82
90
|
try {
|
|
83
91
|
const module = await import(pathToFileURL(workerData.modulePath).href);
|
|
84
92
|
if (typeof module.init !== "function") {
|
|
85
|
-
throw new Error(
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Generative App ${workerData.app} must export named function init.`,
|
|
95
|
+
);
|
|
86
96
|
}
|
|
87
97
|
const method = module[workerData.method];
|
|
88
98
|
if (typeof method !== "function") {
|
|
89
|
-
throw new Error(
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Generative App ${workerData.app} does not export method ${workerData.method}.`,
|
|
101
|
+
);
|
|
90
102
|
}
|
|
91
103
|
const result = await method({
|
|
92
104
|
...(workerData.argumentPresent ? { argument: workerData.argument } : {}),
|
|
@@ -174,11 +174,6 @@ export declare function installGenerativeApp(options: GenerativeAppRuntimeOption
|
|
|
174
174
|
script: string;
|
|
175
175
|
}): Promise<GenerativeAppInvocationResult>;
|
|
176
176
|
export declare function parseGenerativeAppBoundAction(prompt: string): GenerativeAppBoundAction | undefined;
|
|
177
|
-
export declare function invokeGenerativeAppBoundAction(options: GenerativeAppRuntimeOptions & {
|
|
178
|
-
expectedGeneration?: string;
|
|
179
|
-
expectedRevision?: number;
|
|
180
|
-
prompt: string;
|
|
181
|
-
}): Promise<GenerativeAppInvocationResult | undefined>;
|
|
182
177
|
export declare function bindGenerativeApp(options: GenerativeAppRuntimeOptions & {
|
|
183
178
|
argument?: unknown;
|
|
184
179
|
method?: string;
|
|
@@ -8,6 +8,8 @@ import { appendFile, copyFile, lstat, mkdir, readFile, rename, rm, stat, writeFi
|
|
|
8
8
|
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
9
9
|
import { Worker } from "node:worker_threads";
|
|
10
10
|
import { Type } from "@sinclair/typebox";
|
|
11
|
+
import { renameTelegramPathWithRetry } from "./locks.js";
|
|
12
|
+
import { isProcessAlive } from "./process-identity.js";
|
|
11
13
|
const GENERATIVE_APP_NAME = /^[a-z][a-z0-9-]{0,31}$/u;
|
|
12
14
|
const GENERATIVE_APP_METHOD = /^[a-z][a-z0-9_]{0,31}$/u;
|
|
13
15
|
const GENERATIVE_APP_MAX_MODULE_BYTES = 1024 * 1024;
|
|
@@ -29,17 +31,6 @@ function byteLength(value) {
|
|
|
29
31
|
function wait(ms) {
|
|
30
32
|
return new Promise((resolveWait) => setTimeout(resolveWait, ms));
|
|
31
33
|
}
|
|
32
|
-
function isProcessAlive(pid) {
|
|
33
|
-
if (!Number.isInteger(pid) || pid <= 0)
|
|
34
|
-
return false;
|
|
35
|
-
try {
|
|
36
|
-
process.kill(pid, 0);
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
return error.code === "EPERM";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
34
|
function assertAppName(app) {
|
|
44
35
|
if (!GENERATIVE_APP_NAME.test(app)) {
|
|
45
36
|
throw new Error("Generative App name must match /^[a-z][a-z0-9-]{0,31}$/.");
|
|
@@ -102,7 +93,9 @@ async function writeFileAtomic(path, content) {
|
|
|
102
93
|
await mkdir(dirname(path), { recursive: true });
|
|
103
94
|
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
104
95
|
await writeFile(temporary, content, { encoding: "utf8", mode: 0o600 });
|
|
105
|
-
|
|
96
|
+
// Windows may briefly deny replacing a file another reader or scanner holds; share the bounded retry.
|
|
97
|
+
if (!renameTelegramPathWithRetry(temporary, path))
|
|
98
|
+
throw new Error("Generative App staging file disappeared before publication.");
|
|
106
99
|
}
|
|
107
100
|
async function acquireGenerativeAppTransitionLock(appDir, waitMs = GENERATIVE_APP_LOCK_WAIT_MS) {
|
|
108
101
|
const lockDir = `${appDir}.transition.lock`;
|
|
@@ -175,7 +168,8 @@ async function acquireGenerativeAppTransitionLock(appDir, waitMs = GENERATIVE_AP
|
|
|
175
168
|
.then((metadata) => Date.now() - metadata.mtimeMs > 1_000)
|
|
176
169
|
.catch(() => false)
|
|
177
170
|
: false;
|
|
178
|
-
if ((currentOwnerPid !== undefined &&
|
|
171
|
+
if ((currentOwnerPid !== undefined &&
|
|
172
|
+
!isProcessAlive(currentOwnerPid)) ||
|
|
179
173
|
currentOwnerlessStale) {
|
|
180
174
|
await rm(lockDir, { recursive: true, force: true });
|
|
181
175
|
}
|
|
@@ -278,7 +272,9 @@ async function readStateTimeline(appDir) {
|
|
|
278
272
|
envelopes.push(parsed);
|
|
279
273
|
}
|
|
280
274
|
catch {
|
|
281
|
-
const hasLaterContent = lines
|
|
275
|
+
const hasLaterContent = lines
|
|
276
|
+
.slice(index + 1)
|
|
277
|
+
.some((entry) => entry.trim());
|
|
282
278
|
if (!hasLaterContent) {
|
|
283
279
|
await writeFileAtomic(path, envelopes.map((envelope) => JSON.stringify(envelope)).join("\n") +
|
|
284
280
|
(envelopes.length > 0 ? "\n" : ""));
|
|
@@ -615,24 +611,6 @@ export function parseGenerativeAppBoundAction(prompt) {
|
|
|
615
611
|
app,
|
|
616
612
|
};
|
|
617
613
|
}
|
|
618
|
-
export async function invokeGenerativeAppBoundAction(options) {
|
|
619
|
-
const action = parseGenerativeAppBoundAction(options.prompt);
|
|
620
|
-
if (!action)
|
|
621
|
-
return undefined;
|
|
622
|
-
return await invokeGenerativeApp({
|
|
623
|
-
agentDir: options.agentDir,
|
|
624
|
-
...(action.argument !== undefined ? { argument: action.argument } : {}),
|
|
625
|
-
...(options.expectedGeneration !== undefined
|
|
626
|
-
? { expectedGeneration: options.expectedGeneration }
|
|
627
|
-
: {}),
|
|
628
|
-
...(options.expectedRevision !== undefined
|
|
629
|
-
? { expectedRevision: options.expectedRevision }
|
|
630
|
-
: {}),
|
|
631
|
-
method: action.method,
|
|
632
|
-
methodTimeoutMs: options.methodTimeoutMs,
|
|
633
|
-
app: action.app,
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
614
|
export async function bindGenerativeApp(options) {
|
|
637
615
|
const hasScript = typeof options.script === "string";
|
|
638
616
|
const hasMethod = typeof options.method === "string";
|
|
@@ -645,7 +623,9 @@ export async function bindGenerativeApp(options) {
|
|
|
645
623
|
return hasScript
|
|
646
624
|
? await installGenerativeApp({
|
|
647
625
|
agentDir: options.agentDir,
|
|
648
|
-
...(options.argument !== undefined
|
|
626
|
+
...(options.argument !== undefined
|
|
627
|
+
? { argument: options.argument }
|
|
628
|
+
: {}),
|
|
649
629
|
methodTimeoutMs: options.methodTimeoutMs,
|
|
650
630
|
app: options.app,
|
|
651
631
|
replace: options.replace,
|
|
@@ -653,7 +633,9 @@ export async function bindGenerativeApp(options) {
|
|
|
653
633
|
})
|
|
654
634
|
: await invokeGenerativeApp({
|
|
655
635
|
agentDir: options.agentDir,
|
|
656
|
-
...(options.argument !== undefined
|
|
636
|
+
...(options.argument !== undefined
|
|
637
|
+
? { argument: options.argument }
|
|
638
|
+
: {}),
|
|
657
639
|
method: options.method,
|
|
658
640
|
methodTimeoutMs: options.methodTimeoutMs,
|
|
659
641
|
app: options.app,
|
|
@@ -739,7 +721,9 @@ export function createGenerativeAppLiveSurfaceRuntime(deps) {
|
|
|
739
721
|
schedule(record, result.refreshAfterMs);
|
|
740
722
|
}
|
|
741
723
|
catch (error) {
|
|
742
|
-
const classification = deps.classifyEditError?.(error) ?? {
|
|
724
|
+
const classification = deps.classifyEditError?.(error) ?? {
|
|
725
|
+
kind: "unknown",
|
|
726
|
+
};
|
|
743
727
|
if (!ownsRecord(key, record))
|
|
744
728
|
return;
|
|
745
729
|
deps.recordRuntimeEvent?.("generative-app", error, {
|
|
@@ -785,7 +769,8 @@ export function createGenerativeAppLiveSurfaceRuntime(deps) {
|
|
|
785
769
|
const handle = frame.digest === surface.initialDigest
|
|
786
770
|
? surface.handle
|
|
787
771
|
: await deps.edit(frame);
|
|
788
|
-
if (result.refreshAfterMs === undefined ||
|
|
772
|
+
if (result.refreshAfterMs === undefined ||
|
|
773
|
+
!deps.isCurrent({ ...surface, handle }))
|
|
789
774
|
return;
|
|
790
775
|
open({
|
|
791
776
|
...surface,
|
|
@@ -842,7 +827,9 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
842
827
|
const view = {
|
|
843
828
|
text: planned.markdown,
|
|
844
829
|
parseMode: "markdown",
|
|
845
|
-
...(planned.replyMarkup !== undefined
|
|
830
|
+
...(planned.replyMarkup !== undefined
|
|
831
|
+
? { replyMarkup: planned.replyMarkup }
|
|
832
|
+
: {}),
|
|
846
833
|
};
|
|
847
834
|
return {
|
|
848
835
|
digest: createHash("sha256").update(JSON.stringify(view)).digest("hex"),
|
|
@@ -862,7 +849,9 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
862
849
|
if (!edited.ok)
|
|
863
850
|
throw Object.assign(new Error(edited.message), {
|
|
864
851
|
deliveryFailureReason: edited.reason,
|
|
865
|
-
...(edited.retryAfterMs === undefined
|
|
852
|
+
...(edited.retryAfterMs === undefined
|
|
853
|
+
? {}
|
|
854
|
+
: { retryAfterMs: edited.retryAfterMs }),
|
|
866
855
|
});
|
|
867
856
|
return { delivery: edited.value, view };
|
|
868
857
|
},
|
|
@@ -878,12 +867,18 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
878
867
|
return { kind: "unavailable" };
|
|
879
868
|
}
|
|
880
869
|
return {
|
|
881
|
-
kind: failure.deliveryFailureReason === "commit-unknown"
|
|
870
|
+
kind: failure.deliveryFailureReason === "commit-unknown"
|
|
871
|
+
? "unknown"
|
|
872
|
+
: "terminal",
|
|
882
873
|
};
|
|
883
874
|
},
|
|
884
875
|
recordRuntimeEvent: deps.recordRuntimeEvent,
|
|
885
|
-
...(deps.liveSurfaceSetTimer
|
|
886
|
-
|
|
876
|
+
...(deps.liveSurfaceSetTimer
|
|
877
|
+
? { setTimer: deps.liveSurfaceSetTimer }
|
|
878
|
+
: {}),
|
|
879
|
+
...(deps.liveSurfaceClearTimer
|
|
880
|
+
? { clearTimer: deps.liveSurfaceClearTimer }
|
|
881
|
+
: {}),
|
|
887
882
|
})
|
|
888
883
|
: undefined;
|
|
889
884
|
deps.setLiveSurfaceRuntime?.(liveSurfaces);
|
|
@@ -904,7 +899,9 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
904
899
|
try {
|
|
905
900
|
const result = await bindGenerativeApp({
|
|
906
901
|
agentDir: deps.agentDir,
|
|
907
|
-
...(params.argument !== undefined
|
|
902
|
+
...(params.argument !== undefined
|
|
903
|
+
? { argument: params.argument }
|
|
904
|
+
: {}),
|
|
908
905
|
...("method" in params && typeof params.method === "string"
|
|
909
906
|
? { method: params.method }
|
|
910
907
|
: {}),
|
|
@@ -917,10 +914,10 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
917
914
|
: {}),
|
|
918
915
|
methodTimeoutMs: deps.methodTimeoutMs,
|
|
919
916
|
});
|
|
920
|
-
const activeTurn = params.display === false
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
917
|
+
const activeTurn = params.display === false ? undefined : deps.getActiveTurn?.();
|
|
918
|
+
if (activeTurn &&
|
|
919
|
+
deps.planOutput &&
|
|
920
|
+
(deps.sendView || deps.sendMarkdownReply)) {
|
|
924
921
|
try {
|
|
925
922
|
const planned = deps.planOutput(result.output, {
|
|
926
923
|
binding: {
|
|
@@ -973,7 +970,12 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
973
970
|
});
|
|
974
971
|
}
|
|
975
972
|
return {
|
|
976
|
-
content: [
|
|
973
|
+
content: [
|
|
974
|
+
{
|
|
975
|
+
type: "text",
|
|
976
|
+
text: formatDisplayedGenerativeAppToolOutput(),
|
|
977
|
+
},
|
|
978
|
+
],
|
|
977
979
|
details: { ...result, displayed: true, messageId },
|
|
978
980
|
};
|
|
979
981
|
}
|
|
@@ -984,13 +986,23 @@ export function registerTelegramBindTool(pi, deps) {
|
|
|
984
986
|
method: result.method,
|
|
985
987
|
});
|
|
986
988
|
return {
|
|
987
|
-
content: [
|
|
989
|
+
content: [
|
|
990
|
+
{
|
|
991
|
+
type: "text",
|
|
992
|
+
text: formatGenerativeAppToolOutput(result.output),
|
|
993
|
+
},
|
|
994
|
+
],
|
|
988
995
|
details: { ...result, displayed: false, displayFailed: true },
|
|
989
996
|
};
|
|
990
997
|
}
|
|
991
998
|
}
|
|
992
999
|
return {
|
|
993
|
-
content: [
|
|
1000
|
+
content: [
|
|
1001
|
+
{
|
|
1002
|
+
type: "text",
|
|
1003
|
+
text: formatGenerativeAppToolOutput(result.output),
|
|
1004
|
+
},
|
|
1005
|
+
],
|
|
994
1006
|
details: { ...result, displayed: false },
|
|
995
1007
|
};
|
|
996
1008
|
}
|
package/dist/lib/inbound.d.ts
CHANGED
|
@@ -10,9 +10,13 @@ export interface TelegramInboundHandlerConfig {
|
|
|
10
10
|
mime?: string | string[];
|
|
11
11
|
type?: string | string[];
|
|
12
12
|
template?: string | TelegramInboundCommandTemplateConfig[];
|
|
13
|
+
/** Falsy skips this handler so selection continues with the next match. */
|
|
14
|
+
when?: CommandTemplateObjectConfig["when"];
|
|
13
15
|
args?: string[];
|
|
14
16
|
defaults?: Record<string, unknown>;
|
|
15
17
|
timeout?: number | string;
|
|
18
|
+
retry?: CommandTemplateObjectConfig["retry"];
|
|
19
|
+
recover?: CommandTemplateObjectConfig["recover"];
|
|
16
20
|
}
|
|
17
21
|
export interface TelegramInboundHandlerFile {
|
|
18
22
|
path: string;
|
|
@@ -38,6 +42,7 @@ export interface TelegramInboundHandlerExecOptions {
|
|
|
38
42
|
signal?: AbortSignal;
|
|
39
43
|
stdin?: string;
|
|
40
44
|
retry?: number;
|
|
45
|
+
recover?: () => Promise<void>;
|
|
41
46
|
}
|
|
42
47
|
export interface TelegramInboundHandlerExecResult {
|
|
43
48
|
stdout: string;
|
package/dist/lib/inbound.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
7
7
|
import { basename } from "node:path";
|
|
8
|
-
import { buildCommandTemplateInvocation,
|
|
8
|
+
import { buildCommandTemplateInvocation, createCommandTemplateRecovery, getCommandTemplateCompositionSteps, getCommandTemplateConfiguredTimeout, getCommandTemplateStepTimeout, normalizeCommandTemplateConfig, resolveCommandTemplateNumericField, shouldRunCommandTemplateConfig, } from "./command-templates.js";
|
|
9
9
|
import { getTelegramVoiceTranscriptionProviders } from "./voice.js";
|
|
10
10
|
const DEFAULT_INBOUND_HANDLER_TIMEOUT_MS = 120_000;
|
|
11
11
|
const INBOUND_HANDLER_REGISTRY_KEY = "__piTelegramInboundHandlers__";
|
|
@@ -155,42 +155,10 @@ export function buildTelegramInboundHandlerInvocation(handler, file, cwd, append
|
|
|
155
155
|
throw new Error("Inbound handler template is required");
|
|
156
156
|
return buildTelegramInboundTemplateInvocation(handler, file, cwd, appendFileIfMissing);
|
|
157
157
|
}
|
|
158
|
-
function resolveTelegramInboundNumericControlField(value, values, label) {
|
|
159
|
-
if (value === undefined)
|
|
160
|
-
return undefined;
|
|
161
|
-
const resolved = typeof value === "string"
|
|
162
|
-
? substituteCommandTemplateToken(value, values, label)
|
|
163
|
-
: value;
|
|
164
|
-
if (resolved === "")
|
|
165
|
-
return undefined;
|
|
166
|
-
const numeric = Number(resolved);
|
|
167
|
-
if (!Number.isFinite(numeric) || numeric < 0)
|
|
168
|
-
throw new Error(`Command template ${label} must be a non-negative number.`);
|
|
169
|
-
return numeric;
|
|
170
|
-
}
|
|
171
|
-
function getTelegramInboundHandlerConfiguredTimeout(handler) {
|
|
172
|
-
const timeout = typeof handler === "string" ? undefined : handler.timeout;
|
|
173
|
-
return resolveTelegramInboundNumericControlField(timeout, {}, "timeout");
|
|
174
|
-
}
|
|
175
158
|
function getTelegramInboundHandlerTimeout(handler) {
|
|
176
|
-
return (
|
|
159
|
+
return (getCommandTemplateConfiguredTimeout(handler) ??
|
|
177
160
|
DEFAULT_INBOUND_HANDLER_TIMEOUT_MS);
|
|
178
161
|
}
|
|
179
|
-
function getRemainingTelegramInboundTimeout(timeout, startedAt) {
|
|
180
|
-
return Math.max(1, timeout - (Date.now() - startedAt));
|
|
181
|
-
}
|
|
182
|
-
function getTelegramInboundInitialCompositionStepTimeout(handler, step) {
|
|
183
|
-
const timeout = getTelegramInboundHandlerTimeout(handler);
|
|
184
|
-
const stepTimeout = getTelegramInboundHandlerConfiguredTimeout(step);
|
|
185
|
-
return stepTimeout === undefined ? timeout : Math.min(stepTimeout, timeout);
|
|
186
|
-
}
|
|
187
|
-
function getTelegramInboundCompositionStepTimeout(handler, step, startedAt) {
|
|
188
|
-
const remaining = getRemainingTelegramInboundTimeout(getTelegramInboundHandlerTimeout(handler), startedAt);
|
|
189
|
-
const stepTimeout = getTelegramInboundHandlerConfiguredTimeout(step);
|
|
190
|
-
return stepTimeout === undefined
|
|
191
|
-
? remaining
|
|
192
|
-
: Math.min(stepTimeout, remaining);
|
|
193
|
-
}
|
|
194
162
|
function getTelegramInboundHandlerKind(handler) {
|
|
195
163
|
if (Array.isArray(handler.template))
|
|
196
164
|
return "composition";
|
|
@@ -208,28 +176,31 @@ function formatTelegramInboundHandlerFailure(result) {
|
|
|
208
176
|
parts.push(`stdout:\n${truncateTelegramInboundFailureStream(result.stdout)}`);
|
|
209
177
|
return parts.join("\n\n");
|
|
210
178
|
}
|
|
179
|
+
function getTelegramInboundHandlerRetryOptions(handler, values, cwd, timeout, deps) {
|
|
180
|
+
if (typeof handler !== "object" || handler.retry === undefined)
|
|
181
|
+
return {};
|
|
182
|
+
const recover = createCommandTemplateRecovery(handler, values, {
|
|
183
|
+
cwd,
|
|
184
|
+
timeout,
|
|
185
|
+
execCommand: deps.execCommand,
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
retry: resolveCommandTemplateNumericField(handler.retry, {}, "retry"),
|
|
189
|
+
...(recover ? { recover } : {}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
211
192
|
async function executeTelegramInboundHandlerInvocation(handler, file, cwd, deps, appendFileIfMissing = true, timeout = getTelegramInboundHandlerTimeout(handler), stdin) {
|
|
212
193
|
const invocation = buildTelegramInboundHandlerInvocation(handler, file, cwd, appendFileIfMissing);
|
|
213
194
|
const result = await deps.execCommand(invocation.command, invocation.args, {
|
|
214
195
|
cwd,
|
|
215
196
|
timeout,
|
|
216
|
-
...(
|
|
217
|
-
? {
|
|
218
|
-
retry: resolveTelegramInboundNumericControlField(handler.retry, {}, "retry"),
|
|
219
|
-
}
|
|
220
|
-
: {}),
|
|
197
|
+
...getTelegramInboundHandlerRetryOptions(handler, getTelegramInboundHandlerTemplateValues(file), cwd, timeout, deps),
|
|
221
198
|
...(stdin !== undefined ? { stdin } : {}),
|
|
222
199
|
});
|
|
223
200
|
if (result.code !== 0)
|
|
224
201
|
throw new Error(formatTelegramInboundHandlerFailure(result));
|
|
225
202
|
return truncateTelegramInboundOutput(result.stdout);
|
|
226
203
|
}
|
|
227
|
-
function getTelegramInboundHandlerCompositionSteps(handler) {
|
|
228
|
-
if (Array.isArray(handler.template)) {
|
|
229
|
-
return expandCommandTemplateConfigs(handler);
|
|
230
|
-
}
|
|
231
|
-
return [];
|
|
232
|
-
}
|
|
233
204
|
function getTelegramTextHandlerFile() {
|
|
234
205
|
return {
|
|
235
206
|
path: "",
|
|
@@ -264,28 +235,24 @@ async function executeTelegramTextHandlerInvocation(handler, text, cwd, deps, ti
|
|
|
264
235
|
cwd,
|
|
265
236
|
timeout,
|
|
266
237
|
stdin: text,
|
|
267
|
-
...(
|
|
268
|
-
? {
|
|
269
|
-
retry: resolveTelegramInboundNumericControlField(handler.retry, {}, "retry"),
|
|
270
|
-
}
|
|
271
|
-
: {}),
|
|
238
|
+
...getTelegramInboundHandlerRetryOptions(handler, getTelegramInboundHandlerTemplateValues(getTelegramTextHandlerFile(), text), cwd, timeout, deps),
|
|
272
239
|
});
|
|
273
240
|
if (result.code !== 0)
|
|
274
241
|
throw new Error(formatTelegramInboundHandlerFailure(result));
|
|
275
242
|
return truncateTelegramInboundOutput(result.stdout);
|
|
276
243
|
}
|
|
277
244
|
async function executeTelegramTextHandler(handler, text, cwd, deps) {
|
|
278
|
-
const steps =
|
|
245
|
+
const steps = getCommandTemplateCompositionSteps(handler);
|
|
279
246
|
if (steps.length === 0) {
|
|
280
247
|
return (await executeTelegramTextHandlerInvocation(handler, text, cwd, deps)).trim();
|
|
281
248
|
}
|
|
282
249
|
const startedAt = Date.now();
|
|
283
250
|
let output = text;
|
|
284
251
|
for (const [index, step] of steps.entries()) {
|
|
252
|
+
if (!shouldRunCommandTemplateConfig(step, getTelegramInboundHandlerTemplateValues(getTelegramTextHandlerFile(), output)))
|
|
253
|
+
continue;
|
|
285
254
|
try {
|
|
286
|
-
output = await executeTelegramTextHandlerInvocation(step, output, cwd, deps, index === 0
|
|
287
|
-
? getTelegramInboundInitialCompositionStepTimeout(handler, step)
|
|
288
|
-
: getTelegramInboundCompositionStepTimeout(handler, step, startedAt));
|
|
255
|
+
output = await executeTelegramTextHandlerInvocation(step, output, cwd, deps, getCommandTemplateStepTimeout(getTelegramInboundHandlerTimeout(handler), step, index === 0 ? undefined : Date.now() - startedAt));
|
|
289
256
|
}
|
|
290
257
|
catch (error) {
|
|
291
258
|
if (typeof step === "object" && step.failure === "root")
|
|
@@ -303,6 +270,9 @@ async function processTelegramTextHandlers(options) {
|
|
|
303
270
|
let text = options.rawText;
|
|
304
271
|
for (const handler of findTelegramTextHandlers(options.handlers)) {
|
|
305
272
|
try {
|
|
273
|
+
// An unresolvable guard fails only this handler, like its command would.
|
|
274
|
+
if (!shouldRunCommandTemplateConfig(handler, getTelegramInboundHandlerTemplateValues(getTelegramTextHandlerFile(), text)))
|
|
275
|
+
continue;
|
|
306
276
|
const output = await executeTelegramTextHandler(handler, text, options.cwd, options);
|
|
307
277
|
if (output)
|
|
308
278
|
text = output;
|
|
@@ -384,18 +354,22 @@ async function readBuiltInTelegramTextAttachment(file) {
|
|
|
384
354
|
return truncateTelegramInboundOutput(`[${name}]\n${normalized}`);
|
|
385
355
|
}
|
|
386
356
|
async function executeTelegramInboundHandler(handler, file, cwd, deps) {
|
|
387
|
-
const steps =
|
|
357
|
+
const steps = getCommandTemplateCompositionSteps(handler);
|
|
388
358
|
if (steps.length === 0) {
|
|
389
359
|
const output = await executeTelegramInboundHandlerInvocation(handler, file, cwd, deps);
|
|
390
360
|
return output.trim();
|
|
391
361
|
}
|
|
392
362
|
const startedAt = Date.now();
|
|
363
|
+
const values = getTelegramInboundHandlerTemplateValues(file);
|
|
393
364
|
let output = "";
|
|
394
|
-
|
|
365
|
+
let started = false;
|
|
366
|
+
for (const step of steps) {
|
|
367
|
+
if (!shouldRunCommandTemplateConfig(step, values))
|
|
368
|
+
continue;
|
|
369
|
+
const first = !started;
|
|
370
|
+
started = true;
|
|
395
371
|
try {
|
|
396
|
-
output = await executeTelegramInboundHandlerInvocation(step, file, cwd, deps, false,
|
|
397
|
-
? getTelegramInboundInitialCompositionStepTimeout(handler, step)
|
|
398
|
-
: getTelegramInboundCompositionStepTimeout(handler, step, startedAt), index === 0 ? undefined : output);
|
|
372
|
+
output = await executeTelegramInboundHandlerInvocation(step, file, cwd, deps, false, getCommandTemplateStepTimeout(getTelegramInboundHandlerTimeout(handler), step, first ? undefined : Date.now() - startedAt), first ? undefined : output);
|
|
399
373
|
}
|
|
400
374
|
catch (error) {
|
|
401
375
|
if (typeof step === "object" && step.failure === "root")
|
|
@@ -420,6 +394,8 @@ export async function processTelegramInboundHandlers(options) {
|
|
|
420
394
|
const handlers = findTelegramInboundHandlers(options.handlers, file);
|
|
421
395
|
for (const handler of handlers) {
|
|
422
396
|
try {
|
|
397
|
+
if (!shouldRunCommandTemplateConfig(handler, getTelegramInboundHandlerTemplateValues(file)))
|
|
398
|
+
continue;
|
|
423
399
|
const output = await executeTelegramInboundHandler(handler, file, options.cwd, options);
|
|
424
400
|
if (output) {
|
|
425
401
|
outputs.push({ file, output, handler });
|
package/dist/lib/journal.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* bounded atomic publication, durable queue-receipt/failure state, and compaction.
|
|
6
6
|
* It does not own polling, update execution, queue admission, or follower routing.
|
|
7
7
|
*/
|
|
8
|
-
import { type TelegramProcessLiveness } from "./
|
|
8
|
+
import { type TelegramProcessLiveness } from "./process-identity.ts";
|
|
9
9
|
import { type TelegramWorkspaceAdmissionLedger, type TelegramWorkspaceAdmissionScope } from "./workspace-admission.ts";
|
|
10
10
|
export declare const TELEGRAM_UPDATE_JOURNAL_VERSION: 1;
|
|
11
11
|
export declare const TELEGRAM_UPDATE_JOURNAL_EXCLUSION_VERSION: 2;
|
|
@@ -150,11 +150,18 @@ export interface TelegramUpdateJournalLegacyCustodyDisposition {
|
|
|
150
150
|
export type TelegramUpdateJournalOperatorDisposition = TelegramUpdateJournalTerminalOperatorDisposition | TelegramUpdateJournalLegacyCustodyDisposition;
|
|
151
151
|
export declare const TELEGRAM_ROUTING_INPUT_TTL_MS: number;
|
|
152
152
|
/** A source-only choice deadline, never a queue lease or a Thread deletion grant. */
|
|
153
|
+
/** Where a source's chooser was published, so a restarted owner can revive that exact message. */
|
|
154
|
+
export interface TelegramUpdateJournalRoutingChooser {
|
|
155
|
+
chatId: number;
|
|
156
|
+
threadId?: number;
|
|
157
|
+
messageId: number;
|
|
158
|
+
}
|
|
153
159
|
export interface TelegramUpdateJournalRoutingInput {
|
|
154
160
|
operatorUserId: number;
|
|
155
161
|
publishedAtMs: number;
|
|
156
162
|
expiresAtMs: number;
|
|
157
163
|
phase: "waiting" | "selected";
|
|
164
|
+
chooser?: TelegramUpdateJournalRoutingChooser;
|
|
158
165
|
}
|
|
159
166
|
export interface TelegramUpdateJournalEntry {
|
|
160
167
|
updateId: number;
|
|
@@ -381,6 +388,7 @@ export type TelegramRoutingInputExpiryEvidence = Omit<TelegramUpdateJournalAband
|
|
|
381
388
|
export interface TelegramRoutingInputJournal {
|
|
382
389
|
arm(input: TelegramRoutingInputAuthority & {
|
|
383
390
|
publishedAtMs: number;
|
|
391
|
+
chooser?: TelegramUpdateJournalRoutingChooser;
|
|
384
392
|
}): TelegramUpdateJournalEntry[];
|
|
385
393
|
select(input: TelegramRoutingInputAuthority): {
|
|
386
394
|
issued: boolean;
|
|
@@ -415,7 +423,7 @@ export interface TelegramUpdateJournalStore {
|
|
|
415
423
|
recoverDeadQueueOwner(input: TelegramUpdateJournalDeadQueueOwnerRecoveryInput): TelegramUpdateJournalDeadQueueOwnerRecoveryResult;
|
|
416
424
|
removeCompleted(updateIds: readonly number[]): TelegramUpdateJournalRemoveResult;
|
|
417
425
|
/** Guarded completion; every supplied source must still match, and absence is a conflict, not an ACK. */
|
|
418
|
-
removeCompletedExact(updateIds: readonly number[], expectedSources: readonly TelegramUpdateJournalEntryDigest[], completions?: readonly TelegramUpdateJournalSourceCompletion[]): TelegramUpdateJournalRemoveResult;
|
|
426
|
+
removeCompletedExact(updateIds: readonly number[], expectedSources: readonly TelegramUpdateJournalEntryDigest[], completions?: readonly TelegramUpdateJournalSourceCompletion[], isCurrent?: () => boolean): TelegramUpdateJournalRemoveResult;
|
|
419
427
|
/** Strict read-only observation; neither source absence nor a different scope is completion evidence. */
|
|
420
428
|
inspectSourceCompletion(expected: TelegramUpdateJournalSourceCompletion): TelegramUpdateJournalSourceCompletion | undefined;
|
|
421
429
|
/** Complete strict observation of a retained, unoffered v1 queue receipt; never acquires readiness. */
|
|
@@ -716,10 +724,32 @@ export interface TelegramJournalNamespaceInspection {
|
|
|
716
724
|
export declare function inspectTelegramProfileJournalNamespace(input: TelegramJournalNamespaceInspectionInput): TelegramJournalNamespaceInspection;
|
|
717
725
|
/** Read-only evidence over polling, retained flat recipients and role-neutral session journals. */
|
|
718
726
|
export declare function inspectTelegramSessionJournalNamespace(input: TelegramJournalNamespaceInspectionInput): TelegramJournalNamespaceInspection;
|
|
727
|
+
/** Whether an update addresses this private-chat Thread anywhere in its payload (message, callback, reaction, …). */
|
|
728
|
+
export declare function doesTelegramJournalUpdateNameThread(update: unknown, target: {
|
|
729
|
+
chatId: number;
|
|
730
|
+
threadId: number;
|
|
731
|
+
}): boolean;
|
|
732
|
+
/** A button tap alone carries no input, so it never keeps a tab whose inputs are resolved (the in-flight Cancel itself). */
|
|
733
|
+
export declare function isTelegramJournalLoneCallbackUpdate(update: unknown): boolean;
|
|
719
734
|
/** Complete-empty protection only; caller holds source serialization through consumption. Never deletion authority. */
|
|
720
735
|
export declare function isTelegramThreadCleanupJournalNamespaceClear(input: TelegramJournalNamespaceInspectionInput & {
|
|
721
736
|
requiredJournalBindingKeys: readonly string[];
|
|
722
737
|
withSourceReference: NonNullable<TelegramJournalNamespaceInspectionInput["withSourceReference"]>;
|
|
738
|
+
/**
|
|
739
|
+
* The tab being cleaned and its own recorded inputs. When given, a plain pending input with no custody that
|
|
740
|
+
* neither names this tab nor belongs to it cannot be delivered here and does not protect it, nor does a plain
|
|
741
|
+
* button tap even in this tab; without it, every non-empty journal protects, as before.
|
|
742
|
+
*/
|
|
743
|
+
cleanup?: {
|
|
744
|
+
target: {
|
|
745
|
+
chatId: number;
|
|
746
|
+
threadId: number;
|
|
747
|
+
};
|
|
748
|
+
ownInputs: readonly {
|
|
749
|
+
journalBindingKey: string;
|
|
750
|
+
updateIds: readonly number[];
|
|
751
|
+
}[];
|
|
752
|
+
};
|
|
723
753
|
}): boolean;
|
|
724
754
|
export declare function publishTelegramUpdateJournalSegment(path: string, segment: TelegramUpdateJournalSegment): TelegramUpdateJournalSegmentPublicationResult;
|
|
725
755
|
export declare function createTelegramUpdateQueueHandoffToken(): string;
|
|
@@ -761,7 +791,7 @@ export interface TelegramUpdateJournalRuntimeBindingResolverDeps {
|
|
|
761
791
|
withSourceSerialization?: TelegramUpdateJournalStoreOptions["withSourceSerialization"];
|
|
762
792
|
getWorkspaceAdmission?: () => Pick<TelegramWorkspaceAdmissionLedger, "acquireAdmission" | "releaseAdmission"> | undefined;
|
|
763
793
|
onRecovery?: (event: TelegramUpdateJournalRecoveryEvent) => void;
|
|
764
|
-
/** Strict
|
|
794
|
+
/** Strict private source handles; on by default on every platform (see TELEGRAM_STRICT_READ_FLAGS). */
|
|
765
795
|
strictSourceAccess?: boolean;
|
|
766
796
|
}
|
|
767
797
|
export declare function createTelegramUpdateJournalRuntimeBindingResolver(deps: TelegramUpdateJournalRuntimeBindingResolverDeps): () => TelegramUpdateJournalRuntimeBinding | undefined;
|