@llblab/pi-kit 0.29.1 → 0.30.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 +10 -0
- package/README.md +4 -4
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +12 -0
- package/node_modules/@llblab/pi-state-flow/README.md +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +17 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +7 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +3 -2
- package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +3 -3
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +3 -2
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +17 -8
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +6 -3
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +4 -2
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/AGENTS.md +13 -10
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -1
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +23 -0
- package/node_modules/@llblab/pi-telegram/README.md +10 -11
- package/node_modules/@llblab/pi-telegram/api/commands.ts +3 -0
- package/node_modules/@llblab/pi-telegram/dist/api/commands.d.ts +1 -1
- 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 +15 -42
- package/node_modules/@llblab/pi-telegram/dist/lib/activity.d.ts +9 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/activity.js +39 -10
- package/node_modules/@llblab/pi-telegram/dist/lib/agent-messages.js +7 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +43 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +164 -20
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.d.ts +12 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.js +181 -77
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +111 -31
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +1324 -359
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +41 -91
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +969 -637
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-transport.js +16 -9
- package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +215 -18
- package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +1048 -327
- package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.d.ts +5 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.js +434 -261
- package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.d.ts +26 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.js +92 -176
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +168 -82
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +1409 -291
- package/node_modules/@llblab/pi-telegram/dist/lib/config.d.ts +1 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/config.js +34 -76
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +2 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +16 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +642 -170
- package/node_modules/@llblab/pi-telegram/dist/lib/generative-app-worker.mjs +19 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.d.ts +0 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.js +61 -49
- package/node_modules/@llblab/pi-telegram/dist/lib/inbound.d.ts +5 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/inbound.js +35 -59
- package/node_modules/@llblab/pi-telegram/dist/lib/journal.d.ts +40 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/journal.js +2102 -760
- package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.d.ts +2 -6
- package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +75 -58
- package/node_modules/@llblab/pi-telegram/dist/lib/locks.d.ts +34 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +318 -119
- package/node_modules/@llblab/pi-telegram/dist/lib/logging.js +50 -14
- package/node_modules/@llblab/pi-telegram/dist/lib/media.d.ts +22 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/media.js +46 -28
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.d.ts +19 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.js +53 -11
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.d.ts +5 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.js +45 -63
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +5 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +114 -78
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.d.ts +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.js +8 -25
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.d.ts +6 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.js +14 -21
- package/node_modules/@llblab/pi-telegram/dist/lib/menu.d.ts +8 -61
- package/node_modules/@llblab/pi-telegram/dist/lib/menu.js +92 -164
- package/node_modules/@llblab/pi-telegram/dist/lib/model.d.ts +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/model.js +2 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.d.ts +6 -27
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.js +45 -38
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-buttons.js +22 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.d.ts +0 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.js +51 -64
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound-voice.js +6 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound.d.ts +6 -6
- package/node_modules/@llblab/pi-telegram/dist/lib/outbound.js +61 -51
- package/node_modules/@llblab/pi-telegram/dist/lib/ownership.js +6 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/paths.d.ts +5 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/paths.js +37 -21
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +2 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +8 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/polling.d.ts +23 -37
- package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +71 -52
- package/node_modules/@llblab/pi-telegram/dist/lib/preview.js +39 -19
- package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.d.ts +24 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.js +133 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/prompts.js +2 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/queue.d.ts +16 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/queue.js +261 -116
- package/node_modules/@llblab/pi-telegram/dist/lib/recovery.d.ts +2 -83
- package/node_modules/@llblab/pi-telegram/dist/lib/recovery.js +20 -274
- package/node_modules/@llblab/pi-telegram/dist/lib/replies.d.ts +16 -24
- package/node_modules/@llblab/pi-telegram/dist/lib/replies.js +99 -116
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +121 -7
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +4750 -1161
- package/node_modules/@llblab/pi-telegram/dist/lib/runtime.d.ts +1 -11
- package/node_modules/@llblab/pi-telegram/dist/lib/sections.d.ts +4 -29
- package/node_modules/@llblab/pi-telegram/dist/lib/sections.js +7 -20
- package/node_modules/@llblab/pi-telegram/dist/lib/skills.js +4 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/status.js +86 -57
- package/node_modules/@llblab/pi-telegram/dist/lib/sync.d.ts +6 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +112 -45
- package/node_modules/@llblab/pi-telegram/dist/lib/target.d.ts +4 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/target.js +18 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.d.ts +18 -11
- package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.js +165 -49
- package/node_modules/@llblab/pi-telegram/dist/lib/text-groups.js +4 -39
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.d.ts +6 -27
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.js +369 -186
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.d.ts +1 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.js +58 -38
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.d.ts +28 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.js +175 -66
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.d.ts +42 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.js +90 -50
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +88 -24
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +2276 -842
- package/node_modules/@llblab/pi-telegram/dist/lib/time-injection.js +1 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/turns.js +1 -19
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +178 -82
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +2438 -645
- package/node_modules/@llblab/pi-telegram/dist/lib/voice.d.ts +7 -22
- package/node_modules/@llblab/pi-telegram/dist/lib/voice.js +7 -22
- package/node_modules/@llblab/pi-telegram/dist/lib/wire.js +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.d.ts +3 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.js +425 -211
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-identity.js +8 -13
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +328 -140
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-slots.js +8 -4
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +43 -35
- package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +15 -3
- package/node_modules/@llblab/pi-telegram/docs/outbound.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +29 -1
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +25 -8
- package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +59 -82
- package/node_modules/@llblab/pi-telegram/lib/activity.ts +146 -102
- package/node_modules/@llblab/pi-telegram/lib/agent-messages.ts +12 -5
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +390 -82
- package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +262 -99
- package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +2440 -601
- package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +2209 -1290
- package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +46 -12
- package/node_modules/@llblab/pi-telegram/lib/bus.ts +1673 -444
- package/node_modules/@llblab/pi-telegram/lib/channel-posts.ts +848 -327
- package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +152 -265
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +2398 -555
- package/node_modules/@llblab/pi-telegram/lib/config.ts +177 -170
- package/node_modules/@llblab/pi-telegram/lib/delivery.ts +41 -29
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +1209 -431
- package/node_modules/@llblab/pi-telegram/lib/generative-app-worker.mjs +19 -7
- package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +324 -211
- package/node_modules/@llblab/pi-telegram/lib/inbound.ts +95 -97
- package/node_modules/@llblab/pi-telegram/lib/journal.ts +5329 -1712
- package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +1 -3
- package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +128 -78
- package/node_modules/@llblab/pi-telegram/lib/locks.ts +703 -212
- package/node_modules/@llblab/pi-telegram/lib/logging.ts +147 -58
- package/node_modules/@llblab/pi-telegram/lib/media.ts +82 -43
- package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +85 -18
- package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +88 -129
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +260 -155
- package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +20 -60
- package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +41 -56
- package/node_modules/@llblab/pi-telegram/lib/menu.ts +112 -285
- package/node_modules/@llblab/pi-telegram/lib/model.ts +8 -22
- package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +156 -125
- package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +76 -49
- package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +96 -94
- package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +33 -27
- package/node_modules/@llblab/pi-telegram/lib/outbound.ts +125 -125
- package/node_modules/@llblab/pi-telegram/lib/ownership.ts +19 -10
- package/node_modules/@llblab/pi-telegram/lib/paths.ts +148 -49
- package/node_modules/@llblab/pi-telegram/lib/pi.ts +35 -15
- package/node_modules/@llblab/pi-telegram/lib/polling.ts +165 -149
- package/node_modules/@llblab/pi-telegram/lib/preview.ts +93 -40
- package/node_modules/@llblab/pi-telegram/lib/process-identity.ts +164 -0
- package/node_modules/@llblab/pi-telegram/lib/prompts.ts +4 -11
- package/node_modules/@llblab/pi-telegram/lib/queue.ts +523 -289
- package/node_modules/@llblab/pi-telegram/lib/recovery.ts +50 -454
- package/node_modules/@llblab/pi-telegram/lib/rendering.ts +1 -3
- package/node_modules/@llblab/pi-telegram/lib/replies.ts +248 -209
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +8527 -2149
- package/node_modules/@llblab/pi-telegram/lib/runtime.ts +1 -12
- package/node_modules/@llblab/pi-telegram/lib/sections.ts +24 -89
- package/node_modules/@llblab/pi-telegram/lib/setup.ts +1 -3
- package/node_modules/@llblab/pi-telegram/lib/skills.ts +9 -4
- package/node_modules/@llblab/pi-telegram/lib/status.ts +215 -110
- package/node_modules/@llblab/pi-telegram/lib/sync.ts +488 -359
- package/node_modules/@llblab/pi-telegram/lib/target.ts +22 -3
- package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +322 -122
- package/node_modules/@llblab/pi-telegram/lib/text-groups.ts +5 -39
- package/node_modules/@llblab/pi-telegram/lib/thread-cleanup-manager.ts +833 -331
- package/node_modules/@llblab/pi-telegram/lib/thread-display.ts +213 -97
- package/node_modules/@llblab/pi-telegram/lib/thread-naming.ts +232 -87
- package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +155 -72
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +5329 -1817
- package/node_modules/@llblab/pi-telegram/lib/time-injection.ts +1 -4
- package/node_modules/@llblab/pi-telegram/lib/turns.ts +15 -28
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +5194 -1600
- package/node_modules/@llblab/pi-telegram/lib/voice.ts +7 -35
- package/node_modules/@llblab/pi-telegram/lib/wire.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/workspace-admission.ts +996 -416
- package/node_modules/@llblab/pi-telegram/lib/workspace-identity.ts +14 -17
- package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +878 -376
- package/node_modules/@llblab/pi-telegram/lib/workspace-slots.ts +22 -13
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +3 -3
- package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +0 -472
- package/node_modules/@llblab/pi-telegram/scripts/measure-workspace.mjs +0 -108
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Owns queue item contracts, lane admission, pure queue mutations, and dispatch planning
|
|
5
5
|
*/
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
|
+
import { isPiStaleContextError } from "./pi.js";
|
|
8
|
+
import { isTelegramApiCommitUnknownError } from "./telegram-api.js";
|
|
7
9
|
import { isVoiceTurn } from "./voice.js";
|
|
8
10
|
import { isWireRecord as isQueuePayloadRecord } from "./wire.js";
|
|
9
|
-
import { isTelegramApiCommitUnknownError } from "./telegram-api.js";
|
|
10
11
|
export const TELEGRAM_QUEUE_LANE_CONTRACTS = [
|
|
11
12
|
// Control lane intentionally accepts both direct controls and resume prompts.
|
|
12
13
|
// Model-switch continuations need prompt semantics but must run before queued user work.
|
|
@@ -33,64 +34,139 @@ export const TELEGRAM_QUEUE_LANE_CONTRACTS = [
|
|
|
33
34
|
export const TELEGRAM_QUEUE_HANDOFF_PAYLOAD_MAX_BYTES = 8 * 1024 * 1024;
|
|
34
35
|
const TELEGRAM_QUEUE_HANDOFF_MAX_RECEIPTS = 256;
|
|
35
36
|
function parseQueuePayloadReceipt(value, kind) {
|
|
36
|
-
if (!isQueuePayloadRecord(value) ||
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
!
|
|
40
|
-
value.
|
|
37
|
+
if (!isQueuePayloadRecord(value) ||
|
|
38
|
+
value.queueKind !== kind ||
|
|
39
|
+
typeof value.receiptId !== "string" ||
|
|
40
|
+
!value.receiptId ||
|
|
41
|
+
(value.journalBindingKey !== undefined &&
|
|
42
|
+
(typeof value.journalBindingKey !== "string" ||
|
|
43
|
+
!value.journalBindingKey.trim())) ||
|
|
44
|
+
!Array.isArray(value.sourceUpdateIds) ||
|
|
45
|
+
value.sourceUpdateIds.length === 0 ||
|
|
46
|
+
value.sourceUpdateIds.some((id, index) => !Number.isSafeInteger(id) ||
|
|
47
|
+
id < 0 ||
|
|
41
48
|
(index > 0 && id <= value.sourceUpdateIds[index - 1])))
|
|
42
49
|
return undefined;
|
|
43
|
-
return {
|
|
44
|
-
|
|
50
|
+
return {
|
|
51
|
+
queueKind: kind,
|
|
52
|
+
receiptId: value.receiptId,
|
|
53
|
+
sourceUpdateIds: value.sourceUpdateIds,
|
|
54
|
+
...(typeof value.journalBindingKey === "string"
|
|
55
|
+
? { journalBindingKey: value.journalBindingKey }
|
|
56
|
+
: {}),
|
|
57
|
+
};
|
|
45
58
|
}
|
|
46
59
|
/** Data decoder shared by authenticated IPC and cold storage; decoding grants no admission. */
|
|
47
60
|
export function parseTelegramQueueHandoffPayload(value) {
|
|
48
|
-
if (!isQueuePayloadRecord(value) ||
|
|
61
|
+
if (!isQueuePayloadRecord(value) ||
|
|
62
|
+
(value.kind !== "prompt" && value.kind !== "control"))
|
|
49
63
|
return undefined;
|
|
50
|
-
const target = isQueuePayloadRecord(value.target) &&
|
|
51
|
-
|
|
64
|
+
const target = isQueuePayloadRecord(value.target) &&
|
|
65
|
+
typeof value.target.chatId === "number"
|
|
66
|
+
? {
|
|
67
|
+
chatId: value.target.chatId,
|
|
68
|
+
...(typeof value.target.threadId === "number"
|
|
69
|
+
? { threadId: value.target.threadId }
|
|
70
|
+
: {}),
|
|
71
|
+
}
|
|
72
|
+
: undefined;
|
|
52
73
|
const transportStamp = isQueuePayloadRecord(value.transportStamp) &&
|
|
53
|
-
typeof value.transportStamp.profile === "string" &&
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
74
|
+
typeof value.transportStamp.profile === "string" &&
|
|
75
|
+
typeof value.transportStamp.generation === "string"
|
|
76
|
+
? {
|
|
77
|
+
profile: value.transportStamp.profile,
|
|
78
|
+
generation: value.transportStamp.generation,
|
|
79
|
+
}
|
|
80
|
+
: undefined;
|
|
81
|
+
if (!Number.isSafeInteger(value.chatId) ||
|
|
82
|
+
(value.target !== undefined && !target) ||
|
|
83
|
+
(value.transportStamp !== undefined && !transportStamp) ||
|
|
84
|
+
!Number.isSafeInteger(value.replyToMessageId) ||
|
|
85
|
+
(value.guestQueryId !== undefined &&
|
|
86
|
+
typeof value.guestQueryId !== "string") ||
|
|
87
|
+
(value.guestInlineMessageId !== undefined &&
|
|
88
|
+
typeof value.guestInlineMessageId !== "string") ||
|
|
89
|
+
!Number.isSafeInteger(value.queueOrder) ||
|
|
90
|
+
(value.queueLane !== "control" &&
|
|
91
|
+
value.queueLane !== "priority" &&
|
|
92
|
+
value.queueLane !== "default") ||
|
|
93
|
+
!Number.isSafeInteger(value.laneOrder) ||
|
|
94
|
+
typeof value.statusSummary !== "string" ||
|
|
95
|
+
!Array.isArray(value.admissionReceipts))
|
|
61
96
|
return undefined;
|
|
62
|
-
const admissionReceipts = value.admissionReceipts.map(receipt => parseQueuePayloadReceipt(receipt, value.kind));
|
|
63
|
-
if (admissionReceipts.length === 0 ||
|
|
64
|
-
admissionReceipts.
|
|
97
|
+
const admissionReceipts = value.admissionReceipts.map((receipt) => parseQueuePayloadReceipt(receipt, value.kind));
|
|
98
|
+
if (admissionReceipts.length === 0 ||
|
|
99
|
+
admissionReceipts.length > TELEGRAM_QUEUE_HANDOFF_MAX_RECEIPTS ||
|
|
100
|
+
admissionReceipts.some((receipt) => !receipt))
|
|
65
101
|
return undefined;
|
|
66
|
-
const base = {
|
|
102
|
+
const base = {
|
|
103
|
+
chatId: value.chatId,
|
|
104
|
+
...(target ? { target } : {}),
|
|
105
|
+
...(transportStamp ? { transportStamp } : {}),
|
|
67
106
|
replyToMessageId: value.replyToMessageId,
|
|
68
|
-
...(typeof value.guestQueryId === "string"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
...(typeof value.guestQueryId === "string"
|
|
108
|
+
? { guestQueryId: value.guestQueryId }
|
|
109
|
+
: {}),
|
|
110
|
+
...(typeof value.guestInlineMessageId === "string"
|
|
111
|
+
? { guestInlineMessageId: value.guestInlineMessageId }
|
|
112
|
+
: {}),
|
|
113
|
+
queueOrder: value.queueOrder,
|
|
114
|
+
queueLane: value.queueLane,
|
|
115
|
+
laneOrder: value.laneOrder,
|
|
116
|
+
statusSummary: value.statusSummary,
|
|
117
|
+
admissionReceipts: admissionReceipts,
|
|
118
|
+
};
|
|
73
119
|
if (value.kind === "control") {
|
|
74
|
-
return value.queueLane === "control" &&
|
|
75
|
-
|
|
120
|
+
return value.queueLane === "control" &&
|
|
121
|
+
(value.controlType === "status" || value.controlType === "model")
|
|
122
|
+
? { kind: "control", controlType: value.controlType, ...base }
|
|
123
|
+
: undefined;
|
|
76
124
|
}
|
|
77
|
-
if (value.queueLane === "control" ||
|
|
78
|
-
!Array.isArray(value.
|
|
79
|
-
|
|
80
|
-
!Array.isArray(value.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
(value.
|
|
85
|
-
|
|
86
|
-
|
|
125
|
+
if (value.queueLane === "control" ||
|
|
126
|
+
!Array.isArray(value.sourceMessageIds) ||
|
|
127
|
+
value.sourceMessageIds.some((id) => !Number.isSafeInteger(id)) ||
|
|
128
|
+
!Array.isArray(value.queuedAttachments) ||
|
|
129
|
+
value.queuedAttachments.some((attachment) => !isQueuePayloadRecord(attachment) ||
|
|
130
|
+
typeof attachment.path !== "string" ||
|
|
131
|
+
typeof attachment.fileName !== "string") ||
|
|
132
|
+
!Array.isArray(value.content) ||
|
|
133
|
+
value.content.some((content) => !isQueuePayloadRecord(content) ||
|
|
134
|
+
(content.type === "text"
|
|
135
|
+
? typeof content.text !== "string"
|
|
136
|
+
: content.type === "image"
|
|
137
|
+
? typeof content.data !== "string" ||
|
|
138
|
+
typeof content.mimeType !== "string"
|
|
139
|
+
: true)) ||
|
|
140
|
+
typeof value.historyText !== "string" ||
|
|
141
|
+
(value.priorityEmoji !== undefined &&
|
|
142
|
+
typeof value.priorityEmoji !== "string") ||
|
|
143
|
+
(value.reactionSuppressionEmoji !== undefined &&
|
|
144
|
+
typeof value.reactionSuppressionEmoji !== "string") ||
|
|
145
|
+
(value.voiceReplyPreferred !== undefined &&
|
|
146
|
+
typeof value.voiceReplyPreferred !== "boolean") ||
|
|
147
|
+
(value.voiceReplyRequired !== undefined &&
|
|
148
|
+
typeof value.voiceReplyRequired !== "boolean"))
|
|
87
149
|
return undefined;
|
|
88
|
-
return {
|
|
89
|
-
|
|
90
|
-
...
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
150
|
+
return {
|
|
151
|
+
kind: "prompt",
|
|
152
|
+
...base,
|
|
153
|
+
sourceMessageIds: value.sourceMessageIds,
|
|
154
|
+
queuedAttachments: value.queuedAttachments,
|
|
155
|
+
content: value.content,
|
|
156
|
+
historyText: value.historyText,
|
|
157
|
+
...(typeof value.priorityEmoji === "string"
|
|
158
|
+
? { priorityEmoji: value.priorityEmoji }
|
|
159
|
+
: {}),
|
|
160
|
+
...(typeof value.reactionSuppressionEmoji === "string"
|
|
161
|
+
? { reactionSuppressionEmoji: value.reactionSuppressionEmoji }
|
|
162
|
+
: {}),
|
|
163
|
+
...(typeof value.voiceReplyPreferred === "boolean"
|
|
164
|
+
? { voiceReplyPreferred: value.voiceReplyPreferred }
|
|
165
|
+
: {}),
|
|
166
|
+
...(typeof value.voiceReplyRequired === "boolean"
|
|
167
|
+
? { voiceReplyRequired: value.voiceReplyRequired }
|
|
168
|
+
: {}),
|
|
169
|
+
};
|
|
94
170
|
}
|
|
95
171
|
export function createTelegramQueueAdmissionReceipt(options) {
|
|
96
172
|
if (options.sourceUpdateIds.length === 0)
|
|
@@ -120,19 +196,12 @@ export function createTelegramQueueAdmissionReceipt(options) {
|
|
|
120
196
|
journalBindingKey: scope,
|
|
121
197
|
};
|
|
122
198
|
}
|
|
123
|
-
export function isTelegramQueueItemDurablyAdmitted(item, isReceiptCommitted) {
|
|
124
|
-
assertTelegramQueueItemAdmissionValid(item);
|
|
125
|
-
return (item.admissionReceipts ?? []).every(isReceiptCommitted);
|
|
126
|
-
}
|
|
127
199
|
export function getTelegramQueueLaneContract(lane) {
|
|
128
200
|
const contract = TELEGRAM_QUEUE_LANE_CONTRACTS.find((entry) => entry.lane === lane);
|
|
129
201
|
if (!contract)
|
|
130
202
|
throw new Error(`Unknown Telegram queue lane: ${lane}`);
|
|
131
203
|
return contract;
|
|
132
204
|
}
|
|
133
|
-
export function getTelegramQueueItemAdmissionMode(item) {
|
|
134
|
-
return getTelegramQueueLaneContract(item.queueLane).admissionMode;
|
|
135
|
-
}
|
|
136
205
|
export function isTelegramQueueItemAdmissionValid(item) {
|
|
137
206
|
return getTelegramQueueLaneContract(item.queueLane).allowedKinds.includes(item.kind);
|
|
138
207
|
}
|
|
@@ -248,6 +317,33 @@ export function createTelegramActiveTurnStore() {
|
|
|
248
317
|
getSourceMessageIds: () => activeTurn?.sourceMessageIds,
|
|
249
318
|
};
|
|
250
319
|
}
|
|
320
|
+
/** Current captured targets only; skipped/receipt-held items remain work, never historical census. */
|
|
321
|
+
export function observeTelegramTargetQueueWork(target, activeTurn, items) {
|
|
322
|
+
let protectedWork = false, unknown = !Number.isSafeInteger(target.chatId) ||
|
|
323
|
+
!Number.isSafeInteger(target.threadId) ||
|
|
324
|
+
target.threadId <= 0;
|
|
325
|
+
const observe = (item) => {
|
|
326
|
+
if (item.chatId !== target.chatId && item.target?.chatId !== target.chatId)
|
|
327
|
+
return;
|
|
328
|
+
const captured = item.target;
|
|
329
|
+
if (!captured ||
|
|
330
|
+
captured.chatId !== item.chatId ||
|
|
331
|
+
!Number.isSafeInteger(captured.threadId) ||
|
|
332
|
+
!captured.threadId ||
|
|
333
|
+
captured.threadId < 0) {
|
|
334
|
+
unknown = true;
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (captured.chatId === target.chatId &&
|
|
338
|
+
captured.threadId === target.threadId)
|
|
339
|
+
protectedWork = true;
|
|
340
|
+
};
|
|
341
|
+
if (activeTurn)
|
|
342
|
+
observe(activeTurn);
|
|
343
|
+
for (const item of items)
|
|
344
|
+
observe(item);
|
|
345
|
+
return { protected: protectedWork, unknown };
|
|
346
|
+
}
|
|
251
347
|
// --- Queue Mutations ---
|
|
252
348
|
export function partitionTelegramQueueItemsForHistory(items) {
|
|
253
349
|
const historyTurns = [];
|
|
@@ -275,10 +371,7 @@ export function areTelegramQueueAdmissionReceiptsEqual(left, right) {
|
|
|
275
371
|
left.sourceUpdateIds.every((updateId, index) => updateId === right.sourceUpdateIds[index]));
|
|
276
372
|
}
|
|
277
373
|
function getTelegramQueueAdmissionReceiptKey(receipt) {
|
|
278
|
-
return JSON.stringify([
|
|
279
|
-
receipt.receiptId,
|
|
280
|
-
receipt.journalBindingKey ?? null,
|
|
281
|
-
]);
|
|
374
|
+
return JSON.stringify([receipt.receiptId, receipt.journalBindingKey ?? null]);
|
|
282
375
|
}
|
|
283
376
|
function isDuplicateTelegramQueueAdmission(items, item) {
|
|
284
377
|
const incomingReceipts = item.admissionReceipts ?? [];
|
|
@@ -326,7 +419,8 @@ export function createTelegramQueueHandoff(input) {
|
|
|
326
419
|
handoffToken: input.handoffToken,
|
|
327
420
|
payload: createTelegramQueueHandoffPayload(input.item),
|
|
328
421
|
};
|
|
329
|
-
if (Buffer.byteLength(JSON.stringify(handoff)) >
|
|
422
|
+
if (Buffer.byteLength(JSON.stringify(handoff)) >
|
|
423
|
+
TELEGRAM_QUEUE_HANDOFF_PAYLOAD_MAX_BYTES) {
|
|
330
424
|
throw new Error("Telegram queue handoff payload exceeds its byte limit.");
|
|
331
425
|
}
|
|
332
426
|
return handoff;
|
|
@@ -339,27 +433,7 @@ export function createTelegramQueueHandoffPayload(item) {
|
|
|
339
433
|
if (item.admissionReceipts.length > TELEGRAM_QUEUE_HANDOFF_MAX_RECEIPTS) {
|
|
340
434
|
throw new Error("Telegram queue handoff has too many admission receipts.");
|
|
341
435
|
}
|
|
342
|
-
|
|
343
|
-
return structuredClone({
|
|
344
|
-
kind: item.kind,
|
|
345
|
-
controlType: item.controlType,
|
|
346
|
-
chatId: item.chatId,
|
|
347
|
-
...(item.target ? { target: item.target } : {}),
|
|
348
|
-
...(item.transportStamp ? { transportStamp: item.transportStamp } : {}),
|
|
349
|
-
replyToMessageId: item.replyToMessageId,
|
|
350
|
-
...(item.guestQueryId ? { guestQueryId: item.guestQueryId } : {}),
|
|
351
|
-
...(item.guestInlineMessageId
|
|
352
|
-
? { guestInlineMessageId: item.guestInlineMessageId }
|
|
353
|
-
: {}),
|
|
354
|
-
queueOrder: item.queueOrder,
|
|
355
|
-
queueLane: item.queueLane,
|
|
356
|
-
laneOrder: item.laneOrder,
|
|
357
|
-
statusSummary: item.statusSummary,
|
|
358
|
-
admissionReceipts: item.admissionReceipts,
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
return structuredClone({
|
|
362
|
-
kind: item.kind,
|
|
436
|
+
const base = {
|
|
363
437
|
chatId: item.chatId,
|
|
364
438
|
...(item.target ? { target: item.target } : {}),
|
|
365
439
|
...(item.transportStamp ? { transportStamp: item.transportStamp } : {}),
|
|
@@ -373,6 +447,17 @@ export function createTelegramQueueHandoffPayload(item) {
|
|
|
373
447
|
laneOrder: item.laneOrder,
|
|
374
448
|
statusSummary: item.statusSummary,
|
|
375
449
|
admissionReceipts: item.admissionReceipts,
|
|
450
|
+
};
|
|
451
|
+
if (item.kind === "control") {
|
|
452
|
+
return structuredClone({
|
|
453
|
+
kind: item.kind,
|
|
454
|
+
controlType: item.controlType,
|
|
455
|
+
...base,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
return structuredClone({
|
|
459
|
+
kind: item.kind,
|
|
460
|
+
...base,
|
|
376
461
|
sourceMessageIds: item.sourceMessageIds,
|
|
377
462
|
queuedAttachments: item.queuedAttachments,
|
|
378
463
|
content: item.content,
|
|
@@ -566,9 +651,9 @@ export function removeTelegramQueueItemsByMessageIds(items, messageIds, scope) {
|
|
|
566
651
|
}
|
|
567
652
|
function removeTelegramQueuedGuestPromptByOrder(items, queueOrder) {
|
|
568
653
|
const index = items.findIndex((item) => {
|
|
569
|
-
return isPendingTelegramTurn(item) &&
|
|
654
|
+
return (isPendingTelegramTurn(item) &&
|
|
570
655
|
item.guestQueryId !== undefined &&
|
|
571
|
-
item.queueOrder === queueOrder;
|
|
656
|
+
item.queueOrder === queueOrder);
|
|
572
657
|
});
|
|
573
658
|
if (index < 0)
|
|
574
659
|
return { items, removedItems: [], removedCount: 0 };
|
|
@@ -583,6 +668,7 @@ export function applyTelegramQueuePromptReactionDisposition(items, messageId, di
|
|
|
583
668
|
let nextItems = items;
|
|
584
669
|
for (const [index, item] of items.entries()) {
|
|
585
670
|
if (!isPendingTelegramTurn(item) ||
|
|
671
|
+
item.queueLane === "control" ||
|
|
586
672
|
!isTelegramQueueItemInMessageScope(item, scope) ||
|
|
587
673
|
!item.sourceMessageIds.includes(messageId)) {
|
|
588
674
|
continue;
|
|
@@ -594,16 +680,14 @@ export function applyTelegramQueuePromptReactionDisposition(items, messageId, di
|
|
|
594
680
|
: disposition.kind === "priority" ||
|
|
595
681
|
disposition.kind === "priority-suppressed";
|
|
596
682
|
const queueLane = isPriority ? "priority" : "default";
|
|
597
|
-
const laneOrder = item.queueLane === queueLane
|
|
598
|
-
? item.laneOrder
|
|
599
|
-
: destinationLaneOrder;
|
|
683
|
+
const laneOrder = item.queueLane === queueLane ? item.laneOrder : destinationLaneOrder;
|
|
600
684
|
if (laneOrder === undefined) {
|
|
601
685
|
throw new Error("Telegram destination lane order is unavailable.");
|
|
602
686
|
}
|
|
603
687
|
const priorityEmoji = disposition.kind === "reaction-transition"
|
|
604
688
|
? disposition.priorityEmoji === undefined
|
|
605
689
|
? item.priorityEmoji
|
|
606
|
-
: disposition.priorityEmoji ?? undefined
|
|
690
|
+
: (disposition.priorityEmoji ?? undefined)
|
|
607
691
|
: disposition.kind === "priority"
|
|
608
692
|
? disposition.emoji
|
|
609
693
|
: disposition.kind === "priority-suppressed"
|
|
@@ -612,7 +696,7 @@ export function applyTelegramQueuePromptReactionDisposition(items, messageId, di
|
|
|
612
696
|
const reactionSuppressionEmoji = disposition.kind === "reaction-transition"
|
|
613
697
|
? disposition.suppressionEmoji === undefined
|
|
614
698
|
? item.reactionSuppressionEmoji
|
|
615
|
-
: disposition.suppressionEmoji ?? undefined
|
|
699
|
+
: (disposition.suppressionEmoji ?? undefined)
|
|
616
700
|
: disposition.kind === "suppressed"
|
|
617
701
|
? disposition.emoji
|
|
618
702
|
: disposition.kind === "priority-suppressed"
|
|
@@ -944,12 +1028,17 @@ export function createTelegramAgentEndHook(deps) {
|
|
|
944
1028
|
const assistant = deps.isAssistantAlreadyPublished?.(extractedAssistant)
|
|
945
1029
|
? { stopReason: extractedAssistant.stopReason }
|
|
946
1030
|
: extractedAssistant;
|
|
947
|
-
const hasPublication = !!assistant.text ||
|
|
948
|
-
|
|
1031
|
+
const hasPublication = !!assistant.text ||
|
|
1032
|
+
assistant.stopReason === "error" ||
|
|
1033
|
+
!!turn?.queuedAttachments.length;
|
|
1034
|
+
const reservation = turn && !turn.guestQueryId && hasPublication
|
|
1035
|
+
? deps.reserveActiveTurnDelivery?.()
|
|
1036
|
+
: undefined;
|
|
949
1037
|
const scheduleDelivery = reservation?.schedule ?? deps.scheduleActiveTurnDelivery;
|
|
950
1038
|
try {
|
|
951
1039
|
await deps.loadConfig?.();
|
|
952
|
-
if (deps.isSessionActive?.(ctx) === false ||
|
|
1040
|
+
if (deps.isSessionActive?.(ctx) === false ||
|
|
1041
|
+
deps.getActiveTurn() !== turn)
|
|
953
1042
|
return;
|
|
954
1043
|
await handleTelegramAgentEndRuntime({
|
|
955
1044
|
turn,
|
|
@@ -1026,20 +1115,25 @@ export async function handleTelegramAgentEndRuntime(deps) {
|
|
|
1026
1115
|
const replyMarkup = outboundReply?.replyMarkup;
|
|
1027
1116
|
const isDeliveryActive = () => deps.isSessionActive?.() !== false &&
|
|
1028
1117
|
(!turn || deps.isTurnTransportActive?.(turn) !== false);
|
|
1029
|
-
const preview = turn && !turn.guestQueryId
|
|
1118
|
+
const preview = turn && !turn.guestQueryId
|
|
1119
|
+
? deps.preparePreviewDelivery?.(isDeliveryActive)
|
|
1120
|
+
: undefined;
|
|
1030
1121
|
const setPreviewPendingText = preview?.setPreviewPendingText ?? deps.setPreviewPendingText;
|
|
1031
1122
|
const finalizeMarkdownPreview = preview?.finalizeMarkdownPreview ?? deps.finalizeMarkdownPreview;
|
|
1032
1123
|
const clearPreview = turn
|
|
1033
|
-
? preview
|
|
1034
|
-
|
|
1035
|
-
|
|
1124
|
+
? preview
|
|
1125
|
+
? () => preview.clearPreview(turn.chatId, { target: turn.target })
|
|
1126
|
+
: (deps.preparePreviewClear?.(turn.chatId, {
|
|
1127
|
+
target: turn.target,
|
|
1128
|
+
isDeliveryActive,
|
|
1129
|
+
}) ?? (() => deps.clearPreview(turn.chatId, { target: turn.target })))
|
|
1036
1130
|
: undefined;
|
|
1037
1131
|
const updateStatusIgnoringStaleContext = () => {
|
|
1038
1132
|
try {
|
|
1039
1133
|
deps.updateStatus();
|
|
1040
1134
|
}
|
|
1041
1135
|
catch (error) {
|
|
1042
|
-
if (!
|
|
1136
|
+
if (!isPiStaleContextError(error))
|
|
1043
1137
|
throw error;
|
|
1044
1138
|
}
|
|
1045
1139
|
};
|
|
@@ -1349,7 +1443,11 @@ export async function handleTelegramAgentEndRuntime(deps) {
|
|
|
1349
1443
|
deps.dispatchNextQueuedTelegramTurn();
|
|
1350
1444
|
};
|
|
1351
1445
|
if (deps.scheduleActiveTurnDelivery &&
|
|
1352
|
-
(endPlan.kind === "text" ||
|
|
1446
|
+
(endPlan.kind === "text" ||
|
|
1447
|
+
endPlan.kind === "attachments-only" ||
|
|
1448
|
+
endPlan.shouldSendAbortMessage ||
|
|
1449
|
+
endPlan.shouldSendErrorMessage ||
|
|
1450
|
+
endPlan.shouldClearPreview)) {
|
|
1353
1451
|
deps.scheduleActiveTurnDelivery(deliverActiveTurn);
|
|
1354
1452
|
return;
|
|
1355
1453
|
}
|
|
@@ -1372,11 +1470,6 @@ export function createTelegramSessionStateApplier(deps) {
|
|
|
1372
1470
|
},
|
|
1373
1471
|
};
|
|
1374
1472
|
}
|
|
1375
|
-
function isTelegramStaleContextError(error) {
|
|
1376
|
-
return (error instanceof Error &&
|
|
1377
|
-
(error.message.includes("stale after session") ||
|
|
1378
|
-
error.message.includes("stale ctx")));
|
|
1379
|
-
}
|
|
1380
1473
|
export function buildTelegramSessionStartState(currentModel) {
|
|
1381
1474
|
return {
|
|
1382
1475
|
currentTelegramModel: currentModel,
|
|
@@ -1413,7 +1506,7 @@ export async function startTelegramSessionRuntime(deps) {
|
|
|
1413
1506
|
deps.bindDeferredDispatchContext?.(deps.ctx);
|
|
1414
1507
|
}
|
|
1415
1508
|
catch (error) {
|
|
1416
|
-
if (!
|
|
1509
|
+
if (!isPiStaleContextError(error))
|
|
1417
1510
|
throw error;
|
|
1418
1511
|
}
|
|
1419
1512
|
deps.updateStatus();
|
|
@@ -1545,12 +1638,24 @@ function updateTelegramQueueStatusRuntime(deps) {
|
|
|
1545
1638
|
deps.updateStatus(deps.ctx);
|
|
1546
1639
|
}
|
|
1547
1640
|
catch (error) {
|
|
1548
|
-
if (!
|
|
1641
|
+
if (!isPiStaleContextError(error))
|
|
1549
1642
|
throw error;
|
|
1550
1643
|
}
|
|
1551
1644
|
}
|
|
1552
1645
|
function commitReorderedTelegramQueueItemsRuntime(items, deps) {
|
|
1553
|
-
deps.
|
|
1646
|
+
const pendingHead = deps.hasPendingDispatch?.()
|
|
1647
|
+
? deps.getQueuedItems()[0]
|
|
1648
|
+
: undefined;
|
|
1649
|
+
const ordered = [...items].sort(compareTelegramQueueItems);
|
|
1650
|
+
if (pendingHead) {
|
|
1651
|
+
const index = ordered.findIndex((item) => item.queueOrder === pendingHead.queueOrder &&
|
|
1652
|
+
item.kind === pendingHead.kind &&
|
|
1653
|
+
item.chatId === pendingHead.chatId &&
|
|
1654
|
+
item.replyToMessageId === pendingHead.replyToMessageId);
|
|
1655
|
+
if (index > 0)
|
|
1656
|
+
ordered.unshift(ordered.splice(index, 1)[0]);
|
|
1657
|
+
}
|
|
1658
|
+
deps.setQueuedItems(ordered);
|
|
1554
1659
|
updateTelegramQueueStatusRuntime(deps);
|
|
1555
1660
|
}
|
|
1556
1661
|
function appendTelegramQueueItemRuntime(item, deps) {
|
|
@@ -1602,8 +1707,34 @@ function removeTelegramQueuedGuestPromptByOrderRuntime(queueOrder, deps) {
|
|
|
1602
1707
|
}
|
|
1603
1708
|
export function applyTelegramQueuePromptReactionDispositionRuntime(messageId, disposition, deps, scope) {
|
|
1604
1709
|
const queuedItems = deps.getQueuedItems();
|
|
1710
|
+
const suppression = disposition.kind === "reaction-transition"
|
|
1711
|
+
? disposition.suppressionEmoji
|
|
1712
|
+
: disposition.kind === "suppressed"
|
|
1713
|
+
? disposition.emoji
|
|
1714
|
+
: disposition.kind === "priority-suppressed"
|
|
1715
|
+
? disposition.suppressionEmoji
|
|
1716
|
+
: undefined;
|
|
1717
|
+
// Source-addressed control-lane prompts are explicit continuations. Synthetic model-switch turns have no source IDs.
|
|
1718
|
+
// A Pi-owned dispatched head cannot be removed: agent_start must consume that exact item, not its successor.
|
|
1719
|
+
const cancelled = suppression && deps.hasPendingDispatch
|
|
1720
|
+
? queuedItems.filter((item, index) => isPendingTelegramTurn(item) &&
|
|
1721
|
+
item.queueLane === "control" &&
|
|
1722
|
+
isTelegramQueueItemInMessageScope(item, scope) &&
|
|
1723
|
+
item.sourceMessageIds.includes(messageId) &&
|
|
1724
|
+
!(index === 0 && deps.hasPendingDispatch()))
|
|
1725
|
+
: [];
|
|
1726
|
+
if (cancelled.length) {
|
|
1727
|
+
if (cancelled.some((item) => (item.admissionReceipts?.length ?? 0) > 0) &&
|
|
1728
|
+
!deps.onItemsDiscarded)
|
|
1729
|
+
return false;
|
|
1730
|
+
deps.onItemsDiscarded?.(cancelled, deps.ctx);
|
|
1731
|
+
deps.setQueuedItems(queuedItems.filter((item) => !cancelled.includes(item)));
|
|
1732
|
+
updateTelegramQueueStatusRuntime(deps);
|
|
1733
|
+
return true;
|
|
1734
|
+
}
|
|
1605
1735
|
const changesLane = queuedItems.some((item) => {
|
|
1606
1736
|
if (!isPendingTelegramTurn(item) ||
|
|
1737
|
+
item.queueLane === "control" ||
|
|
1607
1738
|
!isTelegramQueueItemInMessageScope(item, scope) ||
|
|
1608
1739
|
!item.sourceMessageIds.includes(messageId)) {
|
|
1609
1740
|
return false;
|
|
@@ -1633,21 +1764,26 @@ export function applyTelegramQueuePromptReactionDispositionRuntime(messageId, di
|
|
|
1633
1764
|
}
|
|
1634
1765
|
export async function enqueueTelegramPromptTurnRuntime(messages, deps) {
|
|
1635
1766
|
deps.assertExecutionCurrent?.();
|
|
1636
|
-
const historyOrders = new Set(
|
|
1637
|
-
|
|
1767
|
+
const historyOrders = new Set(deps.preserveQueued
|
|
1768
|
+
? []
|
|
1769
|
+
: planTelegramPromptEnqueue(deps.getQueuedItems(), deps.getFoldQueuedPromptsIntoHistory()).historyTurns.map((turn) => turn.queueOrder));
|
|
1770
|
+
if (!deps.preserveQueued)
|
|
1771
|
+
deps.setFoldQueuedPromptsIntoHistory(false);
|
|
1638
1772
|
const buildTurn = await deps.prepareTurn(messages);
|
|
1639
1773
|
deps.assertExecutionCurrent?.();
|
|
1640
1774
|
// Preserve the Pi-owned head until agent_start, plus later arrivals and current edits/reactions.
|
|
1641
1775
|
const pendingDispatch = deps.hasPendingDispatch();
|
|
1642
1776
|
const historyTurns = [];
|
|
1643
1777
|
const remainingItems = deps.getQueuedItems().filter((item, index) => {
|
|
1644
|
-
if ((pendingDispatch && index === 0) ||
|
|
1778
|
+
if ((pendingDispatch && index === 0) ||
|
|
1779
|
+
!isPendingTelegramTurn(item) ||
|
|
1645
1780
|
!historyOrders.has(item.queueOrder))
|
|
1646
1781
|
return true;
|
|
1647
1782
|
historyTurns.push(item);
|
|
1648
1783
|
return false;
|
|
1649
1784
|
});
|
|
1650
1785
|
const turn = buildTurn(historyTurns);
|
|
1786
|
+
deps.assertExecutionCurrent?.();
|
|
1651
1787
|
deps.setQueuedItems(appendTelegramQueueItem(remainingItems, turn));
|
|
1652
1788
|
deps.onQueued?.(turn);
|
|
1653
1789
|
deps.updateStatus();
|
|
@@ -1656,12 +1792,16 @@ export async function enqueueTelegramPromptTurnRuntime(messages, deps) {
|
|
|
1656
1792
|
}
|
|
1657
1793
|
export function createTelegramPromptEnqueueController(deps) {
|
|
1658
1794
|
return {
|
|
1659
|
-
enqueue: (messages, ctx, onQueued) => enqueueTelegramPromptTurnRuntime(messages, {
|
|
1795
|
+
enqueue: (messages, ctx, onQueued, options) => enqueueTelegramPromptTurnRuntime(messages, {
|
|
1660
1796
|
...deps,
|
|
1661
1797
|
prepareTurn: (nextMessages) => deps.prepareTurn(nextMessages, ctx),
|
|
1662
1798
|
updateStatus: () => deps.updateStatus(ctx),
|
|
1663
1799
|
dispatchNextQueuedTelegramTurn: () => deps.dispatchNextQueuedTelegramTurn(ctx),
|
|
1664
|
-
assertExecutionCurrent: () =>
|
|
1800
|
+
assertExecutionCurrent: () => {
|
|
1801
|
+
deps.assertExecutionCurrent?.(messages);
|
|
1802
|
+
options?.assertCurrent?.();
|
|
1803
|
+
},
|
|
1804
|
+
preserveQueued: options?.preserveQueued,
|
|
1665
1805
|
onQueued,
|
|
1666
1806
|
}),
|
|
1667
1807
|
};
|
|
@@ -1963,8 +2103,7 @@ export function createTelegramQueueDispatchController(deps) {
|
|
|
1963
2103
|
nextDispatchAnnouncementRequested = false;
|
|
1964
2104
|
}
|
|
1965
2105
|
}
|
|
1966
|
-
if (nextItem &&
|
|
1967
|
-
deps.hasPendingInboundQueueMutationForItem?.(nextItem)) {
|
|
2106
|
+
if (nextItem && deps.hasPendingInboundQueueMutationForItem?.(nextItem)) {
|
|
1968
2107
|
deps.updateStatus(ctx);
|
|
1969
2108
|
return;
|
|
1970
2109
|
}
|
|
@@ -1984,9 +2123,10 @@ export function createTelegramQueueDispatchController(deps) {
|
|
|
1984
2123
|
const queueDrifted = currentItems.length !== dispatchBasisItems.length ||
|
|
1985
2124
|
currentItems.some((item, index) => item !== dispatchBasisItems[index]);
|
|
1986
2125
|
const dispatchEligibilityDrifted = !deps.canDispatch(ctx) ||
|
|
1987
|
-
deps.hasPendingInboundQueueMutationForItem?.(dispatchPlan.item) ===
|
|
1988
|
-
|
|
1989
|
-
|
|
2126
|
+
deps.hasPendingInboundQueueMutationForItem?.(dispatchPlan.item) ===
|
|
2127
|
+
true ||
|
|
2128
|
+
deps.isQueueItemAdmissionReady?.(dispatchPlan.item) === false ||
|
|
2129
|
+
deps.isQueueItemTransportActive?.(dispatchPlan.item) === false;
|
|
1990
2130
|
if (queueDrifted || dispatchEligibilityDrifted) {
|
|
1991
2131
|
const selectedItemRetained = currentItems.includes(dispatchPlan.item);
|
|
1992
2132
|
const selectedTransportActive = deps.isQueueItemTransportActive?.(dispatchPlan.item) !== false;
|
|
@@ -1996,7 +2136,9 @@ export function createTelegramQueueDispatchController(deps) {
|
|
|
1996
2136
|
? dispatchPlan.item
|
|
1997
2137
|
: undefined;
|
|
1998
2138
|
deps.updateStatus(ctx);
|
|
1999
|
-
if (nextDispatchAnnouncementRequested &&
|
|
2139
|
+
if (nextDispatchAnnouncementRequested &&
|
|
2140
|
+
queueDrifted &&
|
|
2141
|
+
!dispatchEligibilityDrifted) {
|
|
2000
2142
|
controller.dispatchNext(ctx);
|
|
2001
2143
|
}
|
|
2002
2144
|
return false;
|
|
@@ -2065,11 +2207,14 @@ export function createTelegramQueueDispatchController(deps) {
|
|
|
2065
2207
|
const announcementGeneration = nextDispatchAnnouncementGeneration;
|
|
2066
2208
|
const dispatchGeneration = deps.getDispatchGeneration?.();
|
|
2067
2209
|
deps.updateStatus(ctx);
|
|
2068
|
-
void deps
|
|
2210
|
+
void deps
|
|
2211
|
+
.sendTextReply(dispatchPlan.item.chatId, dispatchPlan.item.replyToMessageId, "<b>⏩ Dispatching next queued turn.</b>", { target: dispatchPlan.item.target, parseMode: "HTML" })
|
|
2212
|
+
.catch((error) => {
|
|
2069
2213
|
deps.recordRuntimeEvent?.("dispatch", error, {
|
|
2070
2214
|
phase: "next-announcement",
|
|
2071
2215
|
});
|
|
2072
|
-
})
|
|
2216
|
+
})
|
|
2217
|
+
.finally(() => {
|
|
2073
2218
|
try {
|
|
2074
2219
|
deps.reconcileNextDispatchAnnouncementReplyOwnership?.(dispatchPlan.item);
|
|
2075
2220
|
}
|