@llblab/pi-telegram 0.55.0 → 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.
Files changed (50) hide show
  1. package/AGENTS.md +3 -2
  2. package/BACKLOG.md +4 -1
  3. package/CHANGELOG.md +14 -0
  4. package/README.md +27 -18
  5. package/dist/lib/bindings.d.ts +8 -4
  6. package/dist/lib/bindings.js +41 -1
  7. package/dist/lib/bus-follower.d.ts +1 -0
  8. package/dist/lib/bus-follower.js +5 -1
  9. package/dist/lib/bus-leader.js +9 -1
  10. package/dist/lib/bus.d.ts +5 -0
  11. package/dist/lib/bus.js +17 -6
  12. package/dist/lib/extension.js +14 -2
  13. package/dist/lib/lifecycle.d.ts +2 -1
  14. package/dist/lib/lifecycle.js +28 -20
  15. package/dist/lib/menu-queue.d.ts +1 -0
  16. package/dist/lib/menu-queue.js +102 -99
  17. package/dist/lib/pi.d.ts +3 -2
  18. package/dist/lib/pi.js +3 -0
  19. package/dist/lib/polling.js +3 -1
  20. package/dist/lib/queue.d.ts +57 -5
  21. package/dist/lib/queue.js +313 -25
  22. package/dist/lib/routing.d.ts +1 -1
  23. package/dist/lib/routing.js +261 -29
  24. package/dist/lib/status.d.ts +1 -2
  25. package/dist/lib/status.js +6 -7
  26. package/dist/lib/turns.d.ts +4 -0
  27. package/dist/lib/turns.js +6 -0
  28. package/dist/lib/updates.d.ts +10 -6
  29. package/dist/lib/updates.js +20 -4
  30. package/dist/package.json +1 -1
  31. package/docs/README.md +1 -1
  32. package/docs/architecture.md +17 -14
  33. package/docs/callback-namespaces.md +4 -0
  34. package/docs/multi-instance-bus.md +4 -2
  35. package/docs/ui-style.md +14 -10
  36. package/lib/bindings.ts +52 -3
  37. package/lib/bus-follower.ts +5 -0
  38. package/lib/bus-leader.ts +9 -0
  39. package/lib/bus.ts +20 -3
  40. package/lib/extension.ts +14 -1
  41. package/lib/lifecycle.ts +34 -28
  42. package/lib/menu-queue.ts +116 -162
  43. package/lib/pi.ts +8 -0
  44. package/lib/polling.ts +3 -1
  45. package/lib/queue.ts +328 -33
  46. package/lib/routing.ts +299 -29
  47. package/lib/status.ts +7 -7
  48. package/lib/turns.ts +7 -0
  49. package/lib/updates.ts +24 -10
  50. package/package.json +1 -1
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
- const oldPriorityEmoji = getTelegramReactionEmoji(
164
- oldEmojis,
165
- TELEGRAM_PRIORITY_REACTION_EMOJIS,
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;
@@ -374,6 +370,8 @@ export interface TelegramForeignOwnedUpdateForwarder<
374
370
  message: TMessage;
375
371
  ownership: TelegramTargetOwnershipView;
376
372
  ctx: TContext;
373
+ /** Local issuance/ACK fence; implementations must not serialize it into payloads. */
374
+ assertAuthority?: () => void;
377
375
  }) =>
378
376
  | Promise<TelegramBusForeignUpdateSettlement>
379
377
  | TelegramBusForeignUpdateSettlement;
@@ -9320,6 +9318,7 @@ export function createTelegramQueueHandoffControlExecutionFactory<TContext>(
9320
9318
 
9321
9319
  export interface TelegramQueueHandoffCoordinatorInput<TContext> {
9322
9320
  item: TelegramQueueItem<TContext>;
9321
+ steerSupported?: boolean;
9323
9322
  expectedOwner: TelegramUpdateJournalQueueOwner;
9324
9323
  recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
9325
9324
  handoffToken: string;
@@ -9375,6 +9374,7 @@ export async function coordinateTelegramQueueHandoff<TContext>(
9375
9374
  const handoff = createTelegramQueueHandoff({
9376
9375
  handoffToken: input.handoffToken,
9377
9376
  item: input.item,
9377
+ steerSupported: input.steerSupported,
9378
9378
  });
9379
9379
  const receipt = handoff.payload.admissionReceipts[0];
9380
9380
  if (!receipt || handoff.payload.admissionReceipts.length !== 1) {
@@ -9551,6 +9551,8 @@ export function createTelegramQueueHandoffRecipientRuntime<TContext>(
9551
9551
  }
9552
9552
 
9553
9553
  export interface TelegramQueueHandoffReconcilerDeps<TContext> {
9554
+ canHandoffSteerWithRecipient?: (recipient: TelegramBusFollowerView) => boolean;
9555
+ hasPendingDispatch?: () => boolean;
9554
9556
  ownsDirect: () => boolean;
9555
9557
  isFollowerRegistered: () => boolean;
9556
9558
  isBusEnabled: () => boolean;
@@ -9589,6 +9591,8 @@ export interface TelegramQueueHandoffReconcilerDeps<TContext> {
9589
9591
  export interface TelegramQueueHandoffReconciliationRuntimeAssemblyDeps<
9590
9592
  TContext,
9591
9593
  > {
9594
+ canHandoffSteerWithRecipient?: (recipient: TelegramBusFollowerView) => boolean;
9595
+ hasPendingDispatch?: () => boolean;
9592
9596
  ownsDirect: () => boolean;
9593
9597
  isFollowerRegistered: () => boolean;
9594
9598
  isBusEnabled: () => boolean;
@@ -9628,6 +9632,8 @@ export function createTelegramQueueHandoffReconciliationRuntimeAssembly<
9628
9632
  deps: TelegramQueueHandoffReconciliationRuntimeAssemblyDeps<TContext>,
9629
9633
  ): (ctx: TContext) => Promise<void> {
9630
9634
  return createTelegramQueueHandoffReconciler({
9635
+ canHandoffSteerWithRecipient: deps.canHandoffSteerWithRecipient,
9636
+ hasPendingDispatch: deps.hasPendingDispatch,
9631
9637
  ownsDirect: deps.ownsDirect,
9632
9638
  isFollowerRegistered: deps.isFollowerRegistered,
9633
9639
  isBusEnabled: deps.isBusEnabled,
@@ -9704,6 +9710,8 @@ export function createTelegramQueueHandoffReconciler<TContext>(
9704
9710
  .filter((follower) => follower.instanceId !== deps.donorInstanceId);
9705
9711
  if (followers.length === 0) return;
9706
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;
9707
9715
  const target = item.target;
9708
9716
  const recipient = target
9709
9717
  ? followers.find(
@@ -9713,6 +9721,8 @@ export function createTelegramQueueHandoffReconciler<TContext>(
9713
9721
  )
9714
9722
  : undefined;
9715
9723
  if (!recipient) continue;
9724
+ const steerSupported = item.queueLane === "steer" && deps.canHandoffSteerWithRecipient?.(recipient) === true;
9725
+ if (item.queueLane === "steer" && !steerSupported) continue;
9716
9726
  const receipt = item.admissionReceipts?.[0];
9717
9727
  if (!receipt || item.admissionReceipts?.length !== 1) continue;
9718
9728
  if (
@@ -9739,6 +9749,7 @@ export function createTelegramQueueHandoffReconciler<TContext>(
9739
9749
  const handoffToken = deps.createHandoffToken();
9740
9750
  const result = await coordinateTelegramQueueHandoff({
9741
9751
  item,
9752
+ steerSupported,
9742
9753
  expectedOwner,
9743
9754
  recipientOwner: {
9744
9755
  instanceId: recipient.instanceId,
@@ -9749,6 +9760,9 @@ export function createTelegramQueueHandoffReconciler<TContext>(
9749
9760
  handoffToken,
9750
9761
  lifecycle,
9751
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
+ }
9752
9766
  const payload = {
9753
9767
  ...sourcePayload,
9754
9768
  admissionReceipts: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-telegram",
3
- "version": "0.55.0",
3
+ "version": "0.56.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"