@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.
Files changed (222) hide show
  1. package/BACKLOG.md +3 -1
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +4 -4
  4. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +12 -0
  5. package/node_modules/@llblab/pi-state-flow/README.md +2 -2
  6. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +2 -2
  7. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +17 -8
  8. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +7 -3
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +2 -1
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +3 -2
  11. package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
  12. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +3 -3
  13. package/node_modules/@llblab/pi-state-flow/docs/usage.md +3 -2
  14. package/node_modules/@llblab/pi-state-flow/lib/context.ts +17 -8
  15. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +6 -3
  16. package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +4 -2
  17. package/node_modules/@llblab/pi-state-flow/package.json +1 -1
  18. package/node_modules/@llblab/pi-telegram/AGENTS.md +13 -10
  19. package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -1
  20. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +23 -0
  21. package/node_modules/@llblab/pi-telegram/README.md +10 -11
  22. package/node_modules/@llblab/pi-telegram/api/commands.ts +3 -0
  23. package/node_modules/@llblab/pi-telegram/dist/api/commands.d.ts +1 -1
  24. package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.d.ts +1 -5
  25. package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.js +15 -42
  26. package/node_modules/@llblab/pi-telegram/dist/lib/activity.d.ts +9 -0
  27. package/node_modules/@llblab/pi-telegram/dist/lib/activity.js +39 -10
  28. package/node_modules/@llblab/pi-telegram/dist/lib/agent-messages.js +7 -3
  29. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +43 -5
  30. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +164 -20
  31. package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.d.ts +12 -0
  32. package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.js +181 -77
  33. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +111 -31
  34. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +1324 -359
  35. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +41 -91
  36. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +969 -637
  37. package/node_modules/@llblab/pi-telegram/dist/lib/bus-transport.js +16 -9
  38. package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +215 -18
  39. package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +1048 -327
  40. package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.d.ts +5 -0
  41. package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.js +434 -261
  42. package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.d.ts +26 -5
  43. package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.js +92 -176
  44. package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +168 -82
  45. package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +1409 -291
  46. package/node_modules/@llblab/pi-telegram/dist/lib/config.d.ts +1 -8
  47. package/node_modules/@llblab/pi-telegram/dist/lib/config.js +34 -76
  48. package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +2 -2
  49. package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +16 -16
  50. package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +642 -170
  51. package/node_modules/@llblab/pi-telegram/dist/lib/generative-app-worker.mjs +19 -7
  52. package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.d.ts +0 -5
  53. package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.js +61 -49
  54. package/node_modules/@llblab/pi-telegram/dist/lib/inbound.d.ts +5 -0
  55. package/node_modules/@llblab/pi-telegram/dist/lib/inbound.js +35 -59
  56. package/node_modules/@llblab/pi-telegram/dist/lib/journal.d.ts +40 -4
  57. package/node_modules/@llblab/pi-telegram/dist/lib/journal.js +2102 -760
  58. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.d.ts +2 -6
  59. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +75 -58
  60. package/node_modules/@llblab/pi-telegram/dist/lib/locks.d.ts +34 -3
  61. package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +318 -119
  62. package/node_modules/@llblab/pi-telegram/dist/lib/logging.js +50 -14
  63. package/node_modules/@llblab/pi-telegram/dist/lib/media.d.ts +22 -1
  64. package/node_modules/@llblab/pi-telegram/dist/lib/media.js +46 -28
  65. package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.d.ts +19 -5
  66. package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.js +53 -11
  67. package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.d.ts +5 -4
  68. package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.js +45 -63
  69. package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +5 -4
  70. package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +114 -78
  71. package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.d.ts +1 -1
  72. package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.js +8 -25
  73. package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.d.ts +6 -1
  74. package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.js +14 -21
  75. package/node_modules/@llblab/pi-telegram/dist/lib/menu.d.ts +8 -61
  76. package/node_modules/@llblab/pi-telegram/dist/lib/menu.js +92 -164
  77. package/node_modules/@llblab/pi-telegram/dist/lib/model.d.ts +1 -1
  78. package/node_modules/@llblab/pi-telegram/dist/lib/model.js +2 -16
  79. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.d.ts +6 -27
  80. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.js +45 -38
  81. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-buttons.js +22 -16
  82. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.d.ts +0 -2
  83. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.js +51 -64
  84. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-voice.js +6 -3
  85. package/node_modules/@llblab/pi-telegram/dist/lib/outbound.d.ts +6 -6
  86. package/node_modules/@llblab/pi-telegram/dist/lib/outbound.js +61 -51
  87. package/node_modules/@llblab/pi-telegram/dist/lib/ownership.js +6 -2
  88. package/node_modules/@llblab/pi-telegram/dist/lib/paths.d.ts +5 -0
  89. package/node_modules/@llblab/pi-telegram/dist/lib/paths.js +37 -21
  90. package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +2 -0
  91. package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +8 -1
  92. package/node_modules/@llblab/pi-telegram/dist/lib/polling.d.ts +23 -37
  93. package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +71 -52
  94. package/node_modules/@llblab/pi-telegram/dist/lib/preview.js +39 -19
  95. package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.d.ts +24 -0
  96. package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.js +133 -0
  97. package/node_modules/@llblab/pi-telegram/dist/lib/prompts.js +2 -7
  98. package/node_modules/@llblab/pi-telegram/dist/lib/queue.d.ts +16 -16
  99. package/node_modules/@llblab/pi-telegram/dist/lib/queue.js +261 -116
  100. package/node_modules/@llblab/pi-telegram/dist/lib/recovery.d.ts +2 -83
  101. package/node_modules/@llblab/pi-telegram/dist/lib/recovery.js +20 -274
  102. package/node_modules/@llblab/pi-telegram/dist/lib/replies.d.ts +16 -24
  103. package/node_modules/@llblab/pi-telegram/dist/lib/replies.js +99 -116
  104. package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +121 -7
  105. package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +4750 -1161
  106. package/node_modules/@llblab/pi-telegram/dist/lib/runtime.d.ts +1 -11
  107. package/node_modules/@llblab/pi-telegram/dist/lib/sections.d.ts +4 -29
  108. package/node_modules/@llblab/pi-telegram/dist/lib/sections.js +7 -20
  109. package/node_modules/@llblab/pi-telegram/dist/lib/skills.js +4 -3
  110. package/node_modules/@llblab/pi-telegram/dist/lib/status.js +86 -57
  111. package/node_modules/@llblab/pi-telegram/dist/lib/sync.d.ts +6 -3
  112. package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +112 -45
  113. package/node_modules/@llblab/pi-telegram/dist/lib/target.d.ts +4 -0
  114. package/node_modules/@llblab/pi-telegram/dist/lib/target.js +18 -0
  115. package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.d.ts +18 -11
  116. package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.js +165 -49
  117. package/node_modules/@llblab/pi-telegram/dist/lib/text-groups.js +4 -39
  118. package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.d.ts +6 -27
  119. package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.js +369 -186
  120. package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.d.ts +1 -2
  121. package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.js +58 -38
  122. package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.d.ts +28 -8
  123. package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.js +175 -66
  124. package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.d.ts +42 -16
  125. package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.js +90 -50
  126. package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +88 -24
  127. package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +2276 -842
  128. package/node_modules/@llblab/pi-telegram/dist/lib/time-injection.js +1 -2
  129. package/node_modules/@llblab/pi-telegram/dist/lib/turns.js +1 -19
  130. package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +178 -82
  131. package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +2438 -645
  132. package/node_modules/@llblab/pi-telegram/dist/lib/voice.d.ts +7 -22
  133. package/node_modules/@llblab/pi-telegram/dist/lib/voice.js +7 -22
  134. package/node_modules/@llblab/pi-telegram/dist/lib/wire.js +1 -1
  135. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.d.ts +3 -1
  136. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.js +425 -211
  137. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-identity.js +8 -13
  138. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +1 -1
  139. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +328 -140
  140. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-slots.js +8 -4
  141. package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
  142. package/node_modules/@llblab/pi-telegram/docs/architecture.md +43 -35
  143. package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
  144. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +15 -3
  145. package/node_modules/@llblab/pi-telegram/docs/outbound.md +1 -1
  146. package/node_modules/@llblab/pi-telegram/docs/public-api.md +29 -1
  147. package/node_modules/@llblab/pi-telegram/docs/ui-style.md +25 -8
  148. package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +59 -82
  149. package/node_modules/@llblab/pi-telegram/lib/activity.ts +146 -102
  150. package/node_modules/@llblab/pi-telegram/lib/agent-messages.ts +12 -5
  151. package/node_modules/@llblab/pi-telegram/lib/bindings.ts +390 -82
  152. package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +262 -99
  153. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +2440 -601
  154. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +2209 -1290
  155. package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +46 -12
  156. package/node_modules/@llblab/pi-telegram/lib/bus.ts +1673 -444
  157. package/node_modules/@llblab/pi-telegram/lib/channel-posts.ts +848 -327
  158. package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +152 -265
  159. package/node_modules/@llblab/pi-telegram/lib/commands.ts +2398 -555
  160. package/node_modules/@llblab/pi-telegram/lib/config.ts +177 -170
  161. package/node_modules/@llblab/pi-telegram/lib/delivery.ts +41 -29
  162. package/node_modules/@llblab/pi-telegram/lib/extension.ts +1209 -431
  163. package/node_modules/@llblab/pi-telegram/lib/generative-app-worker.mjs +19 -7
  164. package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +324 -211
  165. package/node_modules/@llblab/pi-telegram/lib/inbound.ts +95 -97
  166. package/node_modules/@llblab/pi-telegram/lib/journal.ts +5329 -1712
  167. package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +1 -3
  168. package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +128 -78
  169. package/node_modules/@llblab/pi-telegram/lib/locks.ts +703 -212
  170. package/node_modules/@llblab/pi-telegram/lib/logging.ts +147 -58
  171. package/node_modules/@llblab/pi-telegram/lib/media.ts +82 -43
  172. package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +85 -18
  173. package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +88 -129
  174. package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +260 -155
  175. package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +20 -60
  176. package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +41 -56
  177. package/node_modules/@llblab/pi-telegram/lib/menu.ts +112 -285
  178. package/node_modules/@llblab/pi-telegram/lib/model.ts +8 -22
  179. package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +156 -125
  180. package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +76 -49
  181. package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +96 -94
  182. package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +33 -27
  183. package/node_modules/@llblab/pi-telegram/lib/outbound.ts +125 -125
  184. package/node_modules/@llblab/pi-telegram/lib/ownership.ts +19 -10
  185. package/node_modules/@llblab/pi-telegram/lib/paths.ts +148 -49
  186. package/node_modules/@llblab/pi-telegram/lib/pi.ts +35 -15
  187. package/node_modules/@llblab/pi-telegram/lib/polling.ts +165 -149
  188. package/node_modules/@llblab/pi-telegram/lib/preview.ts +93 -40
  189. package/node_modules/@llblab/pi-telegram/lib/process-identity.ts +164 -0
  190. package/node_modules/@llblab/pi-telegram/lib/prompts.ts +4 -11
  191. package/node_modules/@llblab/pi-telegram/lib/queue.ts +523 -289
  192. package/node_modules/@llblab/pi-telegram/lib/recovery.ts +50 -454
  193. package/node_modules/@llblab/pi-telegram/lib/rendering.ts +1 -3
  194. package/node_modules/@llblab/pi-telegram/lib/replies.ts +248 -209
  195. package/node_modules/@llblab/pi-telegram/lib/routing.ts +8527 -2149
  196. package/node_modules/@llblab/pi-telegram/lib/runtime.ts +1 -12
  197. package/node_modules/@llblab/pi-telegram/lib/sections.ts +24 -89
  198. package/node_modules/@llblab/pi-telegram/lib/setup.ts +1 -3
  199. package/node_modules/@llblab/pi-telegram/lib/skills.ts +9 -4
  200. package/node_modules/@llblab/pi-telegram/lib/status.ts +215 -110
  201. package/node_modules/@llblab/pi-telegram/lib/sync.ts +488 -359
  202. package/node_modules/@llblab/pi-telegram/lib/target.ts +22 -3
  203. package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +322 -122
  204. package/node_modules/@llblab/pi-telegram/lib/text-groups.ts +5 -39
  205. package/node_modules/@llblab/pi-telegram/lib/thread-cleanup-manager.ts +833 -331
  206. package/node_modules/@llblab/pi-telegram/lib/thread-display.ts +213 -97
  207. package/node_modules/@llblab/pi-telegram/lib/thread-naming.ts +232 -87
  208. package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +155 -72
  209. package/node_modules/@llblab/pi-telegram/lib/threads.ts +5329 -1817
  210. package/node_modules/@llblab/pi-telegram/lib/time-injection.ts +1 -4
  211. package/node_modules/@llblab/pi-telegram/lib/turns.ts +15 -28
  212. package/node_modules/@llblab/pi-telegram/lib/updates.ts +5194 -1600
  213. package/node_modules/@llblab/pi-telegram/lib/voice.ts +7 -35
  214. package/node_modules/@llblab/pi-telegram/lib/wire.ts +1 -1
  215. package/node_modules/@llblab/pi-telegram/lib/workspace-admission.ts +996 -416
  216. package/node_modules/@llblab/pi-telegram/lib/workspace-identity.ts +14 -17
  217. package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +878 -376
  218. package/node_modules/@llblab/pi-telegram/lib/workspace-slots.ts +22 -13
  219. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  220. package/package.json +3 -3
  221. package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +0 -472
  222. package/node_modules/@llblab/pi-telegram/scripts/measure-workspace.mjs +0 -108
@@ -9,9 +9,13 @@ import { basename } from "node:path";
9
9
 
10
10
  import {
11
11
  buildCommandTemplateInvocation,
12
- expandCommandTemplateConfigs,
12
+ createCommandTemplateRecovery,
13
+ getCommandTemplateCompositionSteps,
14
+ getCommandTemplateConfiguredTimeout,
15
+ getCommandTemplateStepTimeout,
13
16
  normalizeCommandTemplateConfig,
14
- substituteCommandTemplateToken,
17
+ resolveCommandTemplateNumericField,
18
+ shouldRunCommandTemplateConfig,
15
19
  type CommandTemplateConfig,
16
20
  type CommandTemplateObjectConfig,
17
21
  } from "./command-templates.ts";
@@ -30,9 +34,13 @@ export interface TelegramInboundHandlerConfig {
30
34
  mime?: string | string[];
31
35
  type?: string | string[];
32
36
  template?: string | TelegramInboundCommandTemplateConfig[];
37
+ /** Falsy skips this handler so selection continues with the next match. */
38
+ when?: CommandTemplateObjectConfig["when"];
33
39
  args?: string[];
34
40
  defaults?: Record<string, unknown>;
35
41
  timeout?: number | string;
42
+ retry?: CommandTemplateObjectConfig["retry"];
43
+ recover?: CommandTemplateObjectConfig["recover"];
36
44
  }
37
45
 
38
46
  export interface TelegramInboundHandlerFile {
@@ -64,6 +72,7 @@ export interface TelegramInboundHandlerExecOptions {
64
72
  signal?: AbortSignal;
65
73
  stdin?: string;
66
74
  retry?: number;
75
+ recover?: () => Promise<void>;
67
76
  }
68
77
 
69
78
  export interface TelegramInboundHandlerExecResult {
@@ -321,70 +330,15 @@ export function buildTelegramInboundHandlerInvocation(
321
330
  );
322
331
  }
323
332
 
324
- function resolveTelegramInboundNumericControlField(
325
- value: number | string | undefined,
326
- values: Record<string, unknown>,
327
- label: string,
328
- ): number | undefined {
329
- if (value === undefined) return undefined;
330
- const resolved =
331
- typeof value === "string"
332
- ? substituteCommandTemplateToken(value, values, label)
333
- : value;
334
- if (resolved === "") return undefined;
335
- const numeric = Number(resolved);
336
- if (!Number.isFinite(numeric) || numeric < 0)
337
- throw new Error(`Command template ${label} must be a non-negative number.`);
338
- return numeric;
339
- }
340
-
341
- function getTelegramInboundHandlerConfiguredTimeout(
342
- handler: TelegramInboundCommandTemplateConfig,
343
- ): number | undefined {
344
- const timeout = typeof handler === "string" ? undefined : handler.timeout;
345
- return resolveTelegramInboundNumericControlField(timeout, {}, "timeout");
346
- }
347
-
348
333
  function getTelegramInboundHandlerTimeout(
349
334
  handler: TelegramInboundCommandTemplateConfig,
350
335
  ): number {
351
336
  return (
352
- getTelegramInboundHandlerConfiguredTimeout(handler) ??
337
+ getCommandTemplateConfiguredTimeout(handler) ??
353
338
  DEFAULT_INBOUND_HANDLER_TIMEOUT_MS
354
339
  );
355
340
  }
356
341
 
357
- function getRemainingTelegramInboundTimeout(
358
- timeout: number,
359
- startedAt: number,
360
- ): number {
361
- return Math.max(1, timeout - (Date.now() - startedAt));
362
- }
363
-
364
- function getTelegramInboundInitialCompositionStepTimeout(
365
- handler: TelegramInboundHandlerConfig,
366
- step: TelegramInboundCommandTemplateConfig,
367
- ): number {
368
- const timeout = getTelegramInboundHandlerTimeout(handler);
369
- const stepTimeout = getTelegramInboundHandlerConfiguredTimeout(step);
370
- return stepTimeout === undefined ? timeout : Math.min(stepTimeout, timeout);
371
- }
372
-
373
- function getTelegramInboundCompositionStepTimeout(
374
- handler: TelegramInboundHandlerConfig,
375
- step: TelegramInboundCommandTemplateConfig,
376
- startedAt: number,
377
- ): number {
378
- const remaining = getRemainingTelegramInboundTimeout(
379
- getTelegramInboundHandlerTimeout(handler),
380
- startedAt,
381
- );
382
- const stepTimeout = getTelegramInboundHandlerConfiguredTimeout(step);
383
- return stepTimeout === undefined
384
- ? remaining
385
- : Math.min(stepTimeout, remaining);
386
- }
387
-
388
342
  function getTelegramInboundHandlerKind(
389
343
  handler: TelegramInboundHandlerConfig,
390
344
  ): string {
@@ -410,6 +364,25 @@ function formatTelegramInboundHandlerFailure(
410
364
  return parts.join("\n\n");
411
365
  }
412
366
 
367
+ function getTelegramInboundHandlerRetryOptions(
368
+ handler: TelegramInboundCommandTemplateConfig,
369
+ values: Record<string, string>,
370
+ cwd: string,
371
+ timeout: number,
372
+ deps: Pick<TelegramInboundHandlerRuntimeDeps<unknown>, "execCommand">,
373
+ ): Pick<TelegramInboundHandlerExecOptions, "retry" | "recover"> {
374
+ if (typeof handler !== "object" || handler.retry === undefined) return {};
375
+ const recover = createCommandTemplateRecovery(handler, values, {
376
+ cwd,
377
+ timeout,
378
+ execCommand: deps.execCommand,
379
+ });
380
+ return {
381
+ retry: resolveCommandTemplateNumericField(handler.retry, {}, "retry"),
382
+ ...(recover ? { recover } : {}),
383
+ };
384
+ }
385
+
413
386
  async function executeTelegramInboundHandlerInvocation(
414
387
  handler: TelegramInboundCommandTemplateConfig,
415
388
  file: TelegramInboundHandlerFile,
@@ -428,15 +401,13 @@ async function executeTelegramInboundHandlerInvocation(
428
401
  const result = await deps.execCommand(invocation.command, invocation.args, {
429
402
  cwd,
430
403
  timeout,
431
- ...(typeof handler === "object" && handler.retry !== undefined
432
- ? {
433
- retry: resolveTelegramInboundNumericControlField(
434
- handler.retry,
435
- {},
436
- "retry",
437
- ),
438
- }
439
- : {}),
404
+ ...getTelegramInboundHandlerRetryOptions(
405
+ handler,
406
+ getTelegramInboundHandlerTemplateValues(file),
407
+ cwd,
408
+ timeout,
409
+ deps,
410
+ ),
440
411
  ...(stdin !== undefined ? { stdin } : {}),
441
412
  });
442
413
  if (result.code !== 0)
@@ -444,17 +415,6 @@ async function executeTelegramInboundHandlerInvocation(
444
415
  return truncateTelegramInboundOutput(result.stdout);
445
416
  }
446
417
 
447
- function getTelegramInboundHandlerCompositionSteps(
448
- handler: TelegramInboundHandlerConfig,
449
- ): TelegramInboundCommandTemplateConfig[] {
450
- if (Array.isArray(handler.template)) {
451
- return expandCommandTemplateConfigs(
452
- handler,
453
- ) as TelegramInboundCommandTemplateConfig[];
454
- }
455
- return [];
456
- }
457
-
458
418
  function getTelegramTextHandlerFile(): TelegramInboundHandlerFile {
459
419
  return {
460
420
  path: "",
@@ -508,15 +468,16 @@ async function executeTelegramTextHandlerInvocation(
508
468
  cwd,
509
469
  timeout,
510
470
  stdin: text,
511
- ...(typeof handler === "object" && handler.retry !== undefined
512
- ? {
513
- retry: resolveTelegramInboundNumericControlField(
514
- handler.retry,
515
- {},
516
- "retry",
517
- ),
518
- }
519
- : {}),
471
+ ...getTelegramInboundHandlerRetryOptions(
472
+ handler,
473
+ getTelegramInboundHandlerTemplateValues(
474
+ getTelegramTextHandlerFile(),
475
+ text,
476
+ ),
477
+ cwd,
478
+ timeout,
479
+ deps,
480
+ ),
520
481
  });
521
482
  if (result.code !== 0)
522
483
  throw new Error(formatTelegramInboundHandlerFailure(result));
@@ -529,7 +490,7 @@ async function executeTelegramTextHandler(
529
490
  cwd: string,
530
491
  deps: Pick<TelegramInboundHandlerRuntimeDeps<unknown>, "execCommand">,
531
492
  ): Promise<string> {
532
- const steps = getTelegramInboundHandlerCompositionSteps(handler);
493
+ const steps = getCommandTemplateCompositionSteps(handler);
533
494
  if (steps.length === 0) {
534
495
  return (
535
496
  await executeTelegramTextHandlerInvocation(handler, text, cwd, deps)
@@ -538,15 +499,27 @@ async function executeTelegramTextHandler(
538
499
  const startedAt = Date.now();
539
500
  let output = text;
540
501
  for (const [index, step] of steps.entries()) {
502
+ if (
503
+ !shouldRunCommandTemplateConfig(
504
+ step,
505
+ getTelegramInboundHandlerTemplateValues(
506
+ getTelegramTextHandlerFile(),
507
+ output,
508
+ ),
509
+ )
510
+ )
511
+ continue;
541
512
  try {
542
513
  output = await executeTelegramTextHandlerInvocation(
543
514
  step,
544
515
  output,
545
516
  cwd,
546
517
  deps,
547
- index === 0
548
- ? getTelegramInboundInitialCompositionStepTimeout(handler, step)
549
- : getTelegramInboundCompositionStepTimeout(handler, step, startedAt),
518
+ getCommandTemplateStepTimeout(
519
+ getTelegramInboundHandlerTimeout(handler),
520
+ step,
521
+ index === 0 ? undefined : Date.now() - startedAt,
522
+ ),
550
523
  );
551
524
  } catch (error) {
552
525
  if (typeof step === "object" && step.failure === "root") throw error;
@@ -568,6 +541,17 @@ async function processTelegramTextHandlers(options: {
568
541
  let text = options.rawText;
569
542
  for (const handler of findTelegramTextHandlers(options.handlers)) {
570
543
  try {
544
+ // An unresolvable guard fails only this handler, like its command would.
545
+ if (
546
+ !shouldRunCommandTemplateConfig(
547
+ handler,
548
+ getTelegramInboundHandlerTemplateValues(
549
+ getTelegramTextHandlerFile(),
550
+ text,
551
+ ),
552
+ )
553
+ )
554
+ continue;
571
555
  const output = await executeTelegramTextHandler(
572
556
  handler,
573
557
  text,
@@ -681,7 +665,7 @@ async function executeTelegramInboundHandler(
681
665
  cwd: string,
682
666
  deps: Pick<TelegramInboundHandlerRuntimeDeps<unknown>, "execCommand">,
683
667
  ): Promise<string> {
684
- const steps = getTelegramInboundHandlerCompositionSteps(handler);
668
+ const steps = getCommandTemplateCompositionSteps(handler);
685
669
  if (steps.length === 0) {
686
670
  const output = await executeTelegramInboundHandlerInvocation(
687
671
  handler,
@@ -692,8 +676,13 @@ async function executeTelegramInboundHandler(
692
676
  return output.trim();
693
677
  }
694
678
  const startedAt = Date.now();
679
+ const values = getTelegramInboundHandlerTemplateValues(file);
695
680
  let output = "";
696
- for (const [index, step] of steps.entries()) {
681
+ let started = false;
682
+ for (const step of steps) {
683
+ if (!shouldRunCommandTemplateConfig(step, values)) continue;
684
+ const first = !started;
685
+ started = true;
697
686
  try {
698
687
  output = await executeTelegramInboundHandlerInvocation(
699
688
  step,
@@ -701,10 +690,12 @@ async function executeTelegramInboundHandler(
701
690
  cwd,
702
691
  deps,
703
692
  false,
704
- index === 0
705
- ? getTelegramInboundInitialCompositionStepTimeout(handler, step)
706
- : getTelegramInboundCompositionStepTimeout(handler, step, startedAt),
707
- index === 0 ? undefined : output,
693
+ getCommandTemplateStepTimeout(
694
+ getTelegramInboundHandlerTimeout(handler),
695
+ step,
696
+ first ? undefined : Date.now() - startedAt,
697
+ ),
698
+ first ? undefined : output,
708
699
  );
709
700
  } catch (error) {
710
701
  if (typeof step === "object" && step.failure === "root") throw error;
@@ -738,6 +729,13 @@ export async function processTelegramInboundHandlers<
738
729
  const handlers = findTelegramInboundHandlers(options.handlers, file);
739
730
  for (const handler of handlers) {
740
731
  try {
732
+ if (
733
+ !shouldRunCommandTemplateConfig(
734
+ handler,
735
+ getTelegramInboundHandlerTemplateValues(file),
736
+ )
737
+ )
738
+ continue;
741
739
  const output = await executeTelegramInboundHandler(
742
740
  handler,
743
741
  file,