@llblab/pi-telegram 0.55.1 → 0.56.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 +3 -2
- package/BACKLOG.md +4 -1
- package/CHANGELOG.md +9 -0
- package/README.md +26 -17
- package/dist/lib/bindings.d.ts +8 -4
- package/dist/lib/bindings.js +41 -1
- package/dist/lib/bus-follower.js +5 -1
- package/dist/lib/bus-leader.js +9 -1
- package/dist/lib/bus.d.ts +3 -0
- package/dist/lib/bus.js +6 -0
- package/dist/lib/extension.js +14 -2
- package/dist/lib/lifecycle.d.ts +2 -1
- package/dist/lib/lifecycle.js +28 -20
- package/dist/lib/menu-queue.d.ts +1 -0
- package/dist/lib/menu-queue.js +102 -99
- package/dist/lib/pi.d.ts +3 -2
- package/dist/lib/pi.js +3 -0
- package/dist/lib/polling.js +3 -1
- package/dist/lib/queue.d.ts +57 -5
- package/dist/lib/queue.js +313 -25
- package/dist/lib/status.d.ts +1 -2
- package/dist/lib/status.js +6 -7
- package/dist/lib/updates.d.ts +8 -6
- package/dist/lib/updates.js +20 -4
- package/dist/package.json +1 -1
- package/docs/README.md +1 -1
- package/docs/architecture.md +14 -13
- package/docs/callback-namespaces.md +4 -0
- package/docs/multi-instance-bus.md +2 -2
- package/docs/ui-style.md +14 -10
- package/lib/bindings.ts +52 -3
- package/lib/bus-follower.ts +5 -0
- package/lib/bus-leader.ts +9 -0
- package/lib/bus.ts +7 -0
- package/lib/extension.ts +14 -1
- package/lib/lifecycle.ts +34 -28
- package/lib/menu-queue.ts +116 -162
- package/lib/pi.ts +8 -0
- package/lib/polling.ts +3 -1
- package/lib/queue.ts +328 -33
- package/lib/status.ts +7 -7
- package/lib/updates.ts +22 -10
- package/package.json +1 -1
package/lib/status.ts
CHANGED
|
@@ -66,7 +66,7 @@ export function formatTelegramConnectionFailure(error: unknown): string {
|
|
|
66
66
|
|
|
67
67
|
const TELEGRAM_STATUS_DEFAULT_PROFILE_NAME = "default";
|
|
68
68
|
|
|
69
|
-
export type TelegramStatusQueueLane = "control" | "priority" | "default";
|
|
69
|
+
export type TelegramStatusQueueLane = "control" | "steer" | "priority" | "default";
|
|
70
70
|
|
|
71
71
|
export interface TelegramUsageStats {
|
|
72
72
|
totalInput: number;
|
|
@@ -441,7 +441,6 @@ export interface TelegramBridgeStatusRuntimeDeps<
|
|
|
441
441
|
hasPendingModelSwitch: () => boolean;
|
|
442
442
|
getQueuedItems: () => TQueueItem[];
|
|
443
443
|
getQueuedItemCount?: (items: TQueueItem[]) => number;
|
|
444
|
-
formatQueuedStatus: (items: TQueueItem[]) => string;
|
|
445
444
|
getRecentRuntimeEvents: () => TelegramRuntimeEvent[];
|
|
446
445
|
getRuntimeLockState?: () => string;
|
|
447
446
|
getBusRole?: () => TelegramBridgeBusRole | undefined;
|
|
@@ -1200,9 +1199,7 @@ export function buildTelegramStatusBarText(
|
|
|
1200
1199
|
state: TelegramStatusBarState,
|
|
1201
1200
|
): string {
|
|
1202
1201
|
const label = theme.fg("accent", getTelegramStatusBarLabel(state));
|
|
1203
|
-
const queued = state.queuedStatus
|
|
1204
|
-
? theme.fg("warning", state.queuedStatus)
|
|
1205
|
-
: "";
|
|
1202
|
+
const queued = state.queuedStatus ? theme.fg("warning", state.queuedStatus) : "";
|
|
1206
1203
|
if (!state.hasBotToken)
|
|
1207
1204
|
return `${label} ${theme.fg("muted", "not configured")}${queued}`;
|
|
1208
1205
|
if (
|
|
@@ -1612,6 +1609,7 @@ function countTelegramQueueLanes(
|
|
|
1612
1609
|
): Record<TelegramStatusQueueLane, number> {
|
|
1613
1610
|
const counts: Record<TelegramStatusQueueLane, number> = {
|
|
1614
1611
|
control: 0,
|
|
1612
|
+
steer: 0,
|
|
1615
1613
|
priority: 0,
|
|
1616
1614
|
default: 0,
|
|
1617
1615
|
};
|
|
@@ -1626,10 +1624,11 @@ function buildTelegramBridgeCompactStatusLines(
|
|
|
1626
1624
|
control: controlQueueCount,
|
|
1627
1625
|
priority: priorityQueueCount,
|
|
1628
1626
|
default: defaultQueueCount,
|
|
1627
|
+
steer: steerQueueCount,
|
|
1629
1628
|
} = countTelegramQueueLanes(state.queuedItems);
|
|
1630
1629
|
const queueLine = `- queued turns: ${state.queuedItems.length}${
|
|
1631
1630
|
state.queuedItems.length > 0
|
|
1632
|
-
? ` (control=${controlQueueCount}, priority=${priorityQueueCount}, default=${defaultQueueCount})`
|
|
1631
|
+
? ` (control=${controlQueueCount}${steerQueueCount > 0 ? `, steer=${steerQueueCount}` : ""}, priority=${priorityQueueCount}, default=${defaultQueueCount})`
|
|
1633
1632
|
: ""
|
|
1634
1633
|
}`;
|
|
1635
1634
|
const executionState = state.pendingDispatch
|
|
@@ -1698,6 +1697,7 @@ function buildTelegramBridgeDiagnosticStatusLines(
|
|
|
1698
1697
|
control: controlQueueCount,
|
|
1699
1698
|
priority: priorityQueueCount,
|
|
1700
1699
|
default: defaultQueueCount,
|
|
1700
|
+
steer: steerQueueCount,
|
|
1701
1701
|
} = countTelegramQueueLanes(state.queuedItems);
|
|
1702
1702
|
return [
|
|
1703
1703
|
"connection:",
|
|
@@ -1744,7 +1744,7 @@ function buildTelegramBridgeDiagnosticStatusLines(
|
|
|
1744
1744
|
"",
|
|
1745
1745
|
"queue:",
|
|
1746
1746
|
`- queued turns: ${state.queuedItems.length}`,
|
|
1747
|
-
`- lanes: control=${controlQueueCount}, priority=${priorityQueueCount}, default=${defaultQueueCount}`,
|
|
1747
|
+
`- lanes: control=${controlQueueCount}${steerQueueCount > 0 ? `, steer=${steerQueueCount}` : ""}, priority=${priorityQueueCount}, default=${defaultQueueCount}`,
|
|
1748
1748
|
...buildTelegramBusFollowerLines(state),
|
|
1749
1749
|
...buildTelegramLocalBusLines(state, { verbose: true }),
|
|
1750
1750
|
...buildTelegramTopicTargetDiagnosticLines(state),
|
package/lib/updates.ts
CHANGED
|
@@ -108,11 +108,10 @@ export type TelegramReactionType =
|
|
|
108
108
|
|
|
109
109
|
export const TELEGRAM_PRIORITY_REACTIONS = [
|
|
110
110
|
{ id: 10, name: "like", emoji: "👍" },
|
|
111
|
-
{ id: 11, name: "lightning", emoji: "⚡" },
|
|
112
111
|
{ id: 12, name: "heart", emoji: "❤" },
|
|
113
112
|
{ id: 13, name: "dove", emoji: "🕊" },
|
|
114
|
-
{ id: 14, name: "fire", emoji: "🔥" },
|
|
115
113
|
] as const;
|
|
114
|
+
export const TELEGRAM_STEER_REACTIONS = [{ id: 14, name: "fire", emoji: "🔥" }] as const;
|
|
116
115
|
export const TELEGRAM_REMOVAL_REACTIONS = [
|
|
117
116
|
{ id: 20, name: "dislike", emoji: "👎" },
|
|
118
117
|
{ id: 21, name: "ghost", emoji: "👻" },
|
|
@@ -160,14 +159,10 @@ function getTelegramQueueReactionTransition(
|
|
|
160
159
|
): TelegramQueueReactionDisposition | undefined {
|
|
161
160
|
const oldEmojis = collectTelegramReactionEmojis(oldReactions);
|
|
162
161
|
const newEmojis = collectTelegramReactionEmojis(newReactions);
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
);
|
|
167
|
-
const newPriorityEmoji = getTelegramReactionEmoji(
|
|
168
|
-
newEmojis,
|
|
169
|
-
TELEGRAM_PRIORITY_REACTION_EMOJIS,
|
|
170
|
-
);
|
|
162
|
+
// Fire is effective Steer intent; weaker positive aliases under it do not reorder the lane.
|
|
163
|
+
const steerEmoji = TELEGRAM_STEER_REACTIONS[0].emoji;
|
|
164
|
+
const oldPriorityEmoji = oldEmojis.has(steerEmoji) ? steerEmoji : getTelegramReactionEmoji(oldEmojis, TELEGRAM_PRIORITY_REACTION_EMOJIS);
|
|
165
|
+
const newPriorityEmoji = newEmojis.has(steerEmoji) ? steerEmoji : getTelegramReactionEmoji(newEmojis, TELEGRAM_PRIORITY_REACTION_EMOJIS);
|
|
171
166
|
const oldSuppressionEmoji = getTelegramReactionEmoji(
|
|
172
167
|
oldEmojis,
|
|
173
168
|
TELEGRAM_REMOVAL_REACTION_EMOJIS,
|
|
@@ -188,6 +183,7 @@ function getTelegramQueueReactionTransition(
|
|
|
188
183
|
> = { kind: "reaction-transition" };
|
|
189
184
|
if (oldPriorityEmoji !== newPriorityEmoji) {
|
|
190
185
|
transition.priorityEmoji = newPriorityEmoji ?? null;
|
|
186
|
+
if (newPriorityEmoji === steerEmoji) transition.promptLane = "steer";
|
|
191
187
|
}
|
|
192
188
|
if (oldSuppressionEmoji !== newSuppressionEmoji) {
|
|
193
189
|
transition.suppressionEmoji = newSuppressionEmoji ?? null;
|
|
@@ -9322,6 +9318,7 @@ export function createTelegramQueueHandoffControlExecutionFactory<TContext>(
|
|
|
9322
9318
|
|
|
9323
9319
|
export interface TelegramQueueHandoffCoordinatorInput<TContext> {
|
|
9324
9320
|
item: TelegramQueueItem<TContext>;
|
|
9321
|
+
steerSupported?: boolean;
|
|
9325
9322
|
expectedOwner: TelegramUpdateJournalQueueOwner;
|
|
9326
9323
|
recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
|
|
9327
9324
|
handoffToken: string;
|
|
@@ -9377,6 +9374,7 @@ export async function coordinateTelegramQueueHandoff<TContext>(
|
|
|
9377
9374
|
const handoff = createTelegramQueueHandoff({
|
|
9378
9375
|
handoffToken: input.handoffToken,
|
|
9379
9376
|
item: input.item,
|
|
9377
|
+
steerSupported: input.steerSupported,
|
|
9380
9378
|
});
|
|
9381
9379
|
const receipt = handoff.payload.admissionReceipts[0];
|
|
9382
9380
|
if (!receipt || handoff.payload.admissionReceipts.length !== 1) {
|
|
@@ -9553,6 +9551,8 @@ export function createTelegramQueueHandoffRecipientRuntime<TContext>(
|
|
|
9553
9551
|
}
|
|
9554
9552
|
|
|
9555
9553
|
export interface TelegramQueueHandoffReconcilerDeps<TContext> {
|
|
9554
|
+
canHandoffSteerWithRecipient?: (recipient: TelegramBusFollowerView) => boolean;
|
|
9555
|
+
hasPendingDispatch?: () => boolean;
|
|
9556
9556
|
ownsDirect: () => boolean;
|
|
9557
9557
|
isFollowerRegistered: () => boolean;
|
|
9558
9558
|
isBusEnabled: () => boolean;
|
|
@@ -9591,6 +9591,8 @@ export interface TelegramQueueHandoffReconcilerDeps<TContext> {
|
|
|
9591
9591
|
export interface TelegramQueueHandoffReconciliationRuntimeAssemblyDeps<
|
|
9592
9592
|
TContext,
|
|
9593
9593
|
> {
|
|
9594
|
+
canHandoffSteerWithRecipient?: (recipient: TelegramBusFollowerView) => boolean;
|
|
9595
|
+
hasPendingDispatch?: () => boolean;
|
|
9594
9596
|
ownsDirect: () => boolean;
|
|
9595
9597
|
isFollowerRegistered: () => boolean;
|
|
9596
9598
|
isBusEnabled: () => boolean;
|
|
@@ -9630,6 +9632,8 @@ export function createTelegramQueueHandoffReconciliationRuntimeAssembly<
|
|
|
9630
9632
|
deps: TelegramQueueHandoffReconciliationRuntimeAssemblyDeps<TContext>,
|
|
9631
9633
|
): (ctx: TContext) => Promise<void> {
|
|
9632
9634
|
return createTelegramQueueHandoffReconciler({
|
|
9635
|
+
canHandoffSteerWithRecipient: deps.canHandoffSteerWithRecipient,
|
|
9636
|
+
hasPendingDispatch: deps.hasPendingDispatch,
|
|
9633
9637
|
ownsDirect: deps.ownsDirect,
|
|
9634
9638
|
isFollowerRegistered: deps.isFollowerRegistered,
|
|
9635
9639
|
isBusEnabled: deps.isBusEnabled,
|
|
@@ -9706,6 +9710,8 @@ export function createTelegramQueueHandoffReconciler<TContext>(
|
|
|
9706
9710
|
.filter((follower) => follower.instanceId !== deps.donorInstanceId);
|
|
9707
9711
|
if (followers.length === 0) return;
|
|
9708
9712
|
for (const item of [...deps.getQueuedItems()]) {
|
|
9713
|
+
if ((deps.hasPendingDispatch?.() && deps.getQueuedItems()[0] === item) ||
|
|
9714
|
+
(item.kind === "prompt" && (item.steerAttempted || item.steerPacketTail !== undefined || item.steerPacketSourceOrders !== undefined))) continue;
|
|
9709
9715
|
const target = item.target;
|
|
9710
9716
|
const recipient = target
|
|
9711
9717
|
? followers.find(
|
|
@@ -9715,6 +9721,8 @@ export function createTelegramQueueHandoffReconciler<TContext>(
|
|
|
9715
9721
|
)
|
|
9716
9722
|
: undefined;
|
|
9717
9723
|
if (!recipient) continue;
|
|
9724
|
+
const steerSupported = item.queueLane === "steer" && deps.canHandoffSteerWithRecipient?.(recipient) === true;
|
|
9725
|
+
if (item.queueLane === "steer" && !steerSupported) continue;
|
|
9718
9726
|
const receipt = item.admissionReceipts?.[0];
|
|
9719
9727
|
if (!receipt || item.admissionReceipts?.length !== 1) continue;
|
|
9720
9728
|
if (
|
|
@@ -9741,6 +9749,7 @@ export function createTelegramQueueHandoffReconciler<TContext>(
|
|
|
9741
9749
|
const handoffToken = deps.createHandoffToken();
|
|
9742
9750
|
const result = await coordinateTelegramQueueHandoff({
|
|
9743
9751
|
item,
|
|
9752
|
+
steerSupported,
|
|
9744
9753
|
expectedOwner,
|
|
9745
9754
|
recipientOwner: {
|
|
9746
9755
|
instanceId: recipient.instanceId,
|
|
@@ -9751,6 +9760,9 @@ export function createTelegramQueueHandoffReconciler<TContext>(
|
|
|
9751
9760
|
handoffToken,
|
|
9752
9761
|
lifecycle,
|
|
9753
9762
|
stageRemote: async ({ payload: sourcePayload }) => {
|
|
9763
|
+
if (sourcePayload.queueLane === "steer" && deps.canHandoffSteerWithRecipient?.(recipient) !== true) {
|
|
9764
|
+
throw new Error("Steer queue handoff capability changed before staging.");
|
|
9765
|
+
}
|
|
9754
9766
|
const payload = {
|
|
9755
9767
|
...sourcePayload,
|
|
9756
9768
|
admissionReceipts: [
|