@llblab/pi-kit 0.1.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 (523) hide show
  1. package/AGENTS.md +35 -0
  2. package/BACKLOG.md +3 -0
  3. package/CHANGELOG.md +9 -0
  4. package/LICENSE +21 -0
  5. package/README.md +43 -0
  6. package/node_modules/@llblab/pi-actors/AGENTS.md +150 -0
  7. package/node_modules/@llblab/pi-actors/BACKLOG.md +6 -0
  8. package/node_modules/@llblab/pi-actors/CHANGELOG.md +865 -0
  9. package/node_modules/@llblab/pi-actors/README.md +231 -0
  10. package/node_modules/@llblab/pi-actors/banner.jpg +0 -0
  11. package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/artifact-manifest.json +9 -0
  12. package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/control-endpoint.json +6 -0
  13. package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/control-record.json +9 -0
  14. package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/recipe-summary.json +8 -0
  15. package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/run-state.json +10 -0
  16. package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/trace-event.json +9 -0
  17. package/node_modules/@llblab/pi-actors/dist/index.d.ts +7 -0
  18. package/node_modules/@llblab/pi-actors/dist/index.js +17 -0
  19. package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +146 -0
  20. package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +800 -0
  21. package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.d.ts +20 -0
  22. package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.js +103 -0
  23. package/node_modules/@llblab/pi-actors/dist/lib/command-templates.d.ts +85 -0
  24. package/node_modules/@llblab/pi-actors/dist/lib/command-templates.js +804 -0
  25. package/node_modules/@llblab/pi-actors/dist/lib/config.d.ts +34 -0
  26. package/node_modules/@llblab/pi-actors/dist/lib/config.js +216 -0
  27. package/node_modules/@llblab/pi-actors/dist/lib/control-projection.d.ts +20 -0
  28. package/node_modules/@llblab/pi-actors/dist/lib/control-projection.js +66 -0
  29. package/node_modules/@llblab/pi-actors/dist/lib/control.d.ts +15 -0
  30. package/node_modules/@llblab/pi-actors/dist/lib/control.js +97 -0
  31. package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation-transaction.d.ts +65 -0
  32. package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation-transaction.js +610 -0
  33. package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation.d.ts +35 -0
  34. package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation.js +126 -0
  35. package/node_modules/@llblab/pi-actors/dist/lib/draft-review.d.ts +56 -0
  36. package/node_modules/@llblab/pi-actors/dist/lib/draft-review.js +254 -0
  37. package/node_modules/@llblab/pi-actors/dist/lib/draft-sleep.d.ts +65 -0
  38. package/node_modules/@llblab/pi-actors/dist/lib/draft-sleep.js +467 -0
  39. package/node_modules/@llblab/pi-actors/dist/lib/execution-output.d.ts +25 -0
  40. package/node_modules/@llblab/pi-actors/dist/lib/execution-output.js +88 -0
  41. package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.d.ts +17 -0
  42. package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.js +85 -0
  43. package/node_modules/@llblab/pi-actors/dist/lib/execution.d.ts +99 -0
  44. package/node_modules/@llblab/pi-actors/dist/lib/execution.js +725 -0
  45. package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +21 -0
  46. package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +141 -0
  47. package/node_modules/@llblab/pi-actors/dist/lib/file-state.d.ts +18 -0
  48. package/node_modules/@llblab/pi-actors/dist/lib/file-state.js +310 -0
  49. package/node_modules/@llblab/pi-actors/dist/lib/identity.d.ts +9 -0
  50. package/node_modules/@llblab/pi-actors/dist/lib/identity.js +27 -0
  51. package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.d.ts +16 -0
  52. package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.js +57 -0
  53. package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.d.ts +7 -0
  54. package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.js +37 -0
  55. package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.d.ts +100 -0
  56. package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.js +824 -0
  57. package/node_modules/@llblab/pi-actors/dist/lib/inspector.d.ts +20 -0
  58. package/node_modules/@llblab/pi-actors/dist/lib/inspector.js +136 -0
  59. package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +28 -0
  60. package/node_modules/@llblab/pi-actors/dist/lib/limits.js +28 -0
  61. package/node_modules/@llblab/pi-actors/dist/lib/model-context.d.ts +56 -0
  62. package/node_modules/@llblab/pi-actors/dist/lib/model-context.js +220 -0
  63. package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +186 -0
  64. package/node_modules/@llblab/pi-actors/dist/lib/observability.js +951 -0
  65. package/node_modules/@llblab/pi-actors/dist/lib/paths.d.ts +27 -0
  66. package/node_modules/@llblab/pi-actors/dist/lib/paths.js +72 -0
  67. package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +19 -0
  68. package/node_modules/@llblab/pi-actors/dist/lib/pi.js +21 -0
  69. package/node_modules/@llblab/pi-actors/dist/lib/preflight-diagnostics.d.ts +27 -0
  70. package/node_modules/@llblab/pi-actors/dist/lib/preflight-diagnostics.js +86 -0
  71. package/node_modules/@llblab/pi-actors/dist/lib/prompts.d.ts +24 -0
  72. package/node_modules/@llblab/pi-actors/dist/lib/prompts.js +49 -0
  73. package/node_modules/@llblab/pi-actors/dist/lib/recipe-control.d.ts +7 -0
  74. package/node_modules/@llblab/pi-actors/dist/lib/recipe-control.js +43 -0
  75. package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.d.ts +36 -0
  76. package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.js +197 -0
  77. package/node_modules/@llblab/pi-actors/dist/lib/recipes-discovery.d.ts +77 -0
  78. package/node_modules/@llblab/pi-actors/dist/lib/recipes-discovery.js +783 -0
  79. package/node_modules/@llblab/pi-actors/dist/lib/recipes-references.d.ts +113 -0
  80. package/node_modules/@llblab/pi-actors/dist/lib/recipes-references.js +1108 -0
  81. package/node_modules/@llblab/pi-actors/dist/lib/recipes-usage.d.ts +21 -0
  82. package/node_modules/@llblab/pi-actors/dist/lib/recipes-usage.js +494 -0
  83. package/node_modules/@llblab/pi-actors/dist/lib/registry.d.ts +67 -0
  84. package/node_modules/@llblab/pi-actors/dist/lib/registry.js +504 -0
  85. package/node_modules/@llblab/pi-actors/dist/lib/review-control.d.ts +14 -0
  86. package/node_modules/@llblab/pi-actors/dist/lib/review-control.js +110 -0
  87. package/node_modules/@llblab/pi-actors/dist/lib/review-diagnostics.d.ts +11 -0
  88. package/node_modules/@llblab/pi-actors/dist/lib/review-diagnostics.js +148 -0
  89. package/node_modules/@llblab/pi-actors/dist/lib/review-projection.d.ts +14 -0
  90. package/node_modules/@llblab/pi-actors/dist/lib/review-projection.js +166 -0
  91. package/node_modules/@llblab/pi-actors/dist/lib/run-evidence-policy.d.ts +95 -0
  92. package/node_modules/@llblab/pi-actors/dist/lib/run-evidence-policy.js +177 -0
  93. package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +18 -0
  94. package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +125 -0
  95. package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.d.ts +21 -0
  96. package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.js +68 -0
  97. package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.d.ts +28 -0
  98. package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.js +150 -0
  99. package/node_modules/@llblab/pi-actors/dist/lib/runs-control.d.ts +21 -0
  100. package/node_modules/@llblab/pi-actors/dist/lib/runs-control.js +89 -0
  101. package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.d.ts +39 -0
  102. package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.js +283 -0
  103. package/node_modules/@llblab/pi-actors/dist/lib/runs-identity.d.ts +5 -0
  104. package/node_modules/@llblab/pi-actors/dist/lib/runs-identity.js +11 -0
  105. package/node_modules/@llblab/pi-actors/dist/lib/runs-index.d.ts +27 -0
  106. package/node_modules/@llblab/pi-actors/dist/lib/runs-index.js +142 -0
  107. package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.d.ts +7 -0
  108. package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.js +96 -0
  109. package/node_modules/@llblab/pi-actors/dist/lib/runs-parent-teardown.d.ts +51 -0
  110. package/node_modules/@llblab/pi-actors/dist/lib/runs-parent-teardown.js +172 -0
  111. package/node_modules/@llblab/pi-actors/dist/lib/runs-process.d.ts +22 -0
  112. package/node_modules/@llblab/pi-actors/dist/lib/runs-process.js +125 -0
  113. package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.d.ts +18 -0
  114. package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.js +108 -0
  115. package/node_modules/@llblab/pi-actors/dist/lib/runs-start.d.ts +12 -0
  116. package/node_modules/@llblab/pi-actors/dist/lib/runs-start.js +68 -0
  117. package/node_modules/@llblab/pi-actors/dist/lib/runs-status.d.ts +10 -0
  118. package/node_modules/@llblab/pi-actors/dist/lib/runs-status.js +68 -0
  119. package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +48 -0
  120. package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +491 -0
  121. package/node_modules/@llblab/pi-actors/dist/lib/runtime-identity.d.ts +7 -0
  122. package/node_modules/@llblab/pi-actors/dist/lib/runtime-identity.js +35 -0
  123. package/node_modules/@llblab/pi-actors/dist/lib/runtime-triage.d.ts +29 -0
  124. package/node_modules/@llblab/pi-actors/dist/lib/runtime-triage.js +60 -0
  125. package/node_modules/@llblab/pi-actors/dist/lib/runtime.d.ts +69 -0
  126. package/node_modules/@llblab/pi-actors/dist/lib/runtime.js +339 -0
  127. package/node_modules/@llblab/pi-actors/dist/lib/schema.d.ts +60 -0
  128. package/node_modules/@llblab/pi-actors/dist/lib/schema.js +428 -0
  129. package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +45 -0
  130. package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +204 -0
  131. package/node_modules/@llblab/pi-actors/dist/lib/state-readers.d.ts +21 -0
  132. package/node_modules/@llblab/pi-actors/dist/lib/state-readers.js +74 -0
  133. package/node_modules/@llblab/pi-actors/dist/lib/temp.d.ts +10 -0
  134. package/node_modules/@llblab/pi-actors/dist/lib/temp.js +90 -0
  135. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage-transaction.d.ts +27 -0
  136. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage-transaction.js +597 -0
  137. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage.d.ts +24 -0
  138. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage.js +98 -0
  139. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-scheduler.d.ts +80 -0
  140. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-scheduler.js +494 -0
  141. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-transaction.d.ts +50 -0
  142. package/node_modules/@llblab/pi-actors/dist/lib/tool-review-transaction.js +362 -0
  143. package/node_modules/@llblab/pi-actors/dist/lib/tool-review.d.ts +56 -0
  144. package/node_modules/@llblab/pi-actors/dist/lib/tool-review.js +197 -0
  145. package/node_modules/@llblab/pi-actors/dist/lib/tools-access.d.ts +19 -0
  146. package/node_modules/@llblab/pi-actors/dist/lib/tools-access.js +44 -0
  147. package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.d.ts +15 -0
  148. package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +532 -0
  149. package/node_modules/@llblab/pi-actors/dist/lib/tools-local.d.ts +17 -0
  150. package/node_modules/@llblab/pi-actors/dist/lib/tools-local.js +191 -0
  151. package/node_modules/@llblab/pi-actors/dist/lib/tools-message.d.ts +9 -0
  152. package/node_modules/@llblab/pi-actors/dist/lib/tools-message.js +139 -0
  153. package/node_modules/@llblab/pi-actors/dist/lib/tools-register.d.ts +18 -0
  154. package/node_modules/@llblab/pi-actors/dist/lib/tools-register.js +41 -0
  155. package/node_modules/@llblab/pi-actors/dist/lib/tools-response.d.ts +20 -0
  156. package/node_modules/@llblab/pi-actors/dist/lib/tools-response.js +243 -0
  157. package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.d.ts +15 -0
  158. package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.js +133 -0
  159. package/node_modules/@llblab/pi-actors/dist/lib/tools.d.ts +28 -0
  160. package/node_modules/@llblab/pi-actors/dist/lib/tools.js +49 -0
  161. package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.d.ts +22 -0
  162. package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.js +231 -0
  163. package/node_modules/@llblab/pi-actors/dist/pi-actors/index.js +1 -0
  164. package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +555 -0
  165. package/node_modules/@llblab/pi-actors/dist/scripts/build-dist.mjs +60 -0
  166. package/node_modules/@llblab/pi-actors/dist/scripts/conformance.mjs +63 -0
  167. package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +126 -0
  168. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/command-validate.json +13 -0
  169. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/jsonl-tail.json +10 -0
  170. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/recipe-validate.json +11 -0
  171. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/resource-locker-snapshot.json +11 -0
  172. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/resource-locker.json +25 -0
  173. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/run-ops-snapshot.json +15 -0
  174. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/run-state-files.json +13 -0
  175. package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/run-summary.json +9 -0
  176. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/diagnostics.md +44 -0
  177. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/persistent-tools.md +76 -0
  178. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/recipes.md +51 -0
  179. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +41 -0
  180. package/node_modules/@llblab/pi-actors/dist/skills/actors/scripts/resource-locker.mjs +425 -0
  181. package/node_modules/@llblab/pi-actors/dist/skills/actors/scripts/run-utils.mjs +164 -0
  182. package/node_modules/@llblab/pi-actors/dist/skills/actors/scripts/validate-recipe.mjs +370 -0
  183. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/SKILL.md +33 -0
  184. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/bundle.json +77 -0
  185. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/file-write.json +14 -0
  186. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/manifest.json +14 -0
  187. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/report.json +39 -0
  188. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/write.json +53 -0
  189. package/node_modules/@llblab/pi-actors/dist/skills/artifacts/scripts/artifact-utils.mjs +63 -0
  190. package/node_modules/@llblab/pi-actors/dist/skills/music-player/SKILL.md +57 -0
  191. package/node_modules/@llblab/pi-actors/dist/skills/music-player/genapps/music-player.mjs +360 -0
  192. package/node_modules/@llblab/pi-actors/dist/skills/music-player/recipes/playback.json +29 -0
  193. package/node_modules/@llblab/pi-actors/dist/skills/music-player/scripts/playback-client.mjs +143 -0
  194. package/node_modules/@llblab/pi-actors/dist/skills/music-player/scripts/playback.mjs +1446 -0
  195. package/node_modules/@llblab/pi-actors/dist/skills/project-work/SKILL.md +37 -0
  196. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/changelog-head.json +11 -0
  197. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/changelog-section.json +11 -0
  198. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/docs-maintenance.json +66 -0
  199. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/git-log.json +11 -0
  200. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/git-status.json +9 -0
  201. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/markdown-index.json +14 -0
  202. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/package-summary.json +9 -0
  203. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/release-readiness.json +115 -0
  204. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/release-summary.json +74 -0
  205. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/repo-health.json +75 -0
  206. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/run-ops.json +56 -0
  207. package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/skill-summary.json +11 -0
  208. package/node_modules/@llblab/pi-actors/dist/skills/project-work/scripts/project-utils.mjs +89 -0
  209. package/node_modules/@llblab/pi-actors/dist/skills/recipe-memory/SKILL.md +36 -0
  210. package/node_modules/@llblab/pi-actors/dist/skills/recipe-memory/recipes/draft-review.json +14 -0
  211. package/node_modules/@llblab/pi-actors/dist/skills/recipe-memory/recipes/tool-review.json +14 -0
  212. package/node_modules/@llblab/pi-actors/dist/skills/swarm/SKILL.md +84 -0
  213. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/architect.json +82 -0
  214. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/checkpoint-continuation.json +51 -0
  215. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/development-tasking.json +67 -0
  216. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/lens-review.json +63 -0
  217. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/quorum-review.json +65 -0
  218. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/research-synthesis.json +81 -0
  219. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/review-readiness.json +59 -0
  220. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-artifact.json +21 -0
  221. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-checkpoint.json +21 -0
  222. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-conflict-report.json +19 -0
  223. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-contradiction-map.json +20 -0
  224. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-critic.json +22 -0
  225. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-evidence-map.json +20 -0
  226. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-followup.json +21 -0
  227. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-judge.json +22 -0
  228. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-merge.json +24 -0
  229. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-normalize.json +20 -0
  230. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-plan.json +20 -0
  231. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-preflight.json +18 -0
  232. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-prompt.json +16 -0
  233. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-prompts.json +39 -0
  234. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-quorum.json +31 -0
  235. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-review-coordinator.json +170 -0
  236. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-review.json +26 -0
  237. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-task-card.json +22 -0
  238. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-tools.json +15 -0
  239. package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-verify.json +23 -0
  240. package/node_modules/@llblab/pi-actors/dist/skills/swarm/references/development-swarm.md +189 -0
  241. package/node_modules/@llblab/pi-actors/dist/skills/swarm/references/review-swarms.md +115 -0
  242. package/node_modules/@llblab/pi-actors/docs/README.md +20 -0
  243. package/node_modules/@llblab/pi-actors/docs/actor-inspector.md +50 -0
  244. package/node_modules/@llblab/pi-actors/docs/async-runs.md +141 -0
  245. package/node_modules/@llblab/pi-actors/docs/command-templates.md +321 -0
  246. package/node_modules/@llblab/pi-actors/docs/recipe-library.md +89 -0
  247. package/node_modules/@llblab/pi-actors/docs/releasing.md +28 -0
  248. package/node_modules/@llblab/pi-actors/docs/template-recipes.md +175 -0
  249. package/node_modules/@llblab/pi-actors/docs/tool-registry.md +90 -0
  250. package/node_modules/@llblab/pi-actors/fixtures/protocol/artifact-manifest.json +9 -0
  251. package/node_modules/@llblab/pi-actors/fixtures/protocol/control-endpoint.json +6 -0
  252. package/node_modules/@llblab/pi-actors/fixtures/protocol/control-record.json +9 -0
  253. package/node_modules/@llblab/pi-actors/fixtures/protocol/recipe-summary.json +8 -0
  254. package/node_modules/@llblab/pi-actors/fixtures/protocol/run-state.json +10 -0
  255. package/node_modules/@llblab/pi-actors/fixtures/protocol/trace-event.json +9 -0
  256. package/node_modules/@llblab/pi-actors/index.ts +30 -0
  257. package/node_modules/@llblab/pi-actors/lib/async-runs.ts +1245 -0
  258. package/node_modules/@llblab/pi-actors/lib/automatic-review-runtime.ts +148 -0
  259. package/node_modules/@llblab/pi-actors/lib/command-templates.ts +1116 -0
  260. package/node_modules/@llblab/pi-actors/lib/config.ts +261 -0
  261. package/node_modules/@llblab/pi-actors/lib/control-projection.ts +105 -0
  262. package/node_modules/@llblab/pi-actors/lib/control.ts +117 -0
  263. package/node_modules/@llblab/pi-actors/lib/draft-consolidation-transaction.ts +821 -0
  264. package/node_modules/@llblab/pi-actors/lib/draft-consolidation.ts +181 -0
  265. package/node_modules/@llblab/pi-actors/lib/draft-review.ts +325 -0
  266. package/node_modules/@llblab/pi-actors/lib/draft-sleep.ts +575 -0
  267. package/node_modules/@llblab/pi-actors/lib/execution-output.ts +123 -0
  268. package/node_modules/@llblab/pi-actors/lib/execution-sessions.ts +111 -0
  269. package/node_modules/@llblab/pi-actors/lib/execution.ts +1153 -0
  270. package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +181 -0
  271. package/node_modules/@llblab/pi-actors/lib/file-state.ts +306 -0
  272. package/node_modules/@llblab/pi-actors/lib/identity.ts +29 -0
  273. package/node_modules/@llblab/pi-actors/lib/inspector-actions.ts +79 -0
  274. package/node_modules/@llblab/pi-actors/lib/inspector-command.ts +54 -0
  275. package/node_modules/@llblab/pi-actors/lib/inspector-overlay.ts +901 -0
  276. package/node_modules/@llblab/pi-actors/lib/inspector.ts +204 -0
  277. package/node_modules/@llblab/pi-actors/lib/limits.ts +29 -0
  278. package/node_modules/@llblab/pi-actors/lib/model-context.ts +359 -0
  279. package/node_modules/@llblab/pi-actors/lib/observability.ts +1337 -0
  280. package/node_modules/@llblab/pi-actors/lib/paths.ts +111 -0
  281. package/node_modules/@llblab/pi-actors/lib/pi.ts +47 -0
  282. package/node_modules/@llblab/pi-actors/lib/preflight-diagnostics.ts +132 -0
  283. package/node_modules/@llblab/pi-actors/lib/prompts.ts +69 -0
  284. package/node_modules/@llblab/pi-actors/lib/recipe-control.ts +52 -0
  285. package/node_modules/@llblab/pi-actors/lib/recipes-context.ts +268 -0
  286. package/node_modules/@llblab/pi-actors/lib/recipes-discovery.ts +1060 -0
  287. package/node_modules/@llblab/pi-actors/lib/recipes-references.ts +1598 -0
  288. package/node_modules/@llblab/pi-actors/lib/recipes-usage.ts +638 -0
  289. package/node_modules/@llblab/pi-actors/lib/registry.ts +806 -0
  290. package/node_modules/@llblab/pi-actors/lib/review-control.ts +136 -0
  291. package/node_modules/@llblab/pi-actors/lib/review-diagnostics.ts +164 -0
  292. package/node_modules/@llblab/pi-actors/lib/review-projection.ts +196 -0
  293. package/node_modules/@llblab/pi-actors/lib/run-evidence-policy.ts +242 -0
  294. package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +155 -0
  295. package/node_modules/@llblab/pi-actors/lib/runs-artifacts.ts +96 -0
  296. package/node_modules/@llblab/pi-actors/lib/runs-control-delivery.ts +209 -0
  297. package/node_modules/@llblab/pi-actors/lib/runs-control.ts +148 -0
  298. package/node_modules/@llblab/pi-actors/lib/runs-controls.ts +282 -0
  299. package/node_modules/@llblab/pi-actors/lib/runs-identity.ts +14 -0
  300. package/node_modules/@llblab/pi-actors/lib/runs-index.ts +192 -0
  301. package/node_modules/@llblab/pi-actors/lib/runs-ownership.ts +136 -0
  302. package/node_modules/@llblab/pi-actors/lib/runs-parent-teardown.ts +257 -0
  303. package/node_modules/@llblab/pi-actors/lib/runs-process.ts +174 -0
  304. package/node_modules/@llblab/pi-actors/lib/runs-retention.ts +140 -0
  305. package/node_modules/@llblab/pi-actors/lib/runs-start.ts +113 -0
  306. package/node_modules/@llblab/pi-actors/lib/runs-status.ts +101 -0
  307. package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +611 -0
  308. package/node_modules/@llblab/pi-actors/lib/runtime-identity.ts +39 -0
  309. package/node_modules/@llblab/pi-actors/lib/runtime-triage.ts +106 -0
  310. package/node_modules/@llblab/pi-actors/lib/runtime.ts +430 -0
  311. package/node_modules/@llblab/pi-actors/lib/schema.ts +525 -0
  312. package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +302 -0
  313. package/node_modules/@llblab/pi-actors/lib/state-readers.ts +93 -0
  314. package/node_modules/@llblab/pi-actors/lib/temp.ts +99 -0
  315. package/node_modules/@llblab/pi-actors/lib/tool-review-lineage-transaction.ts +881 -0
  316. package/node_modules/@llblab/pi-actors/lib/tool-review-lineage.ts +145 -0
  317. package/node_modules/@llblab/pi-actors/lib/tool-review-scheduler.ts +635 -0
  318. package/node_modules/@llblab/pi-actors/lib/tool-review-transaction.ts +563 -0
  319. package/node_modules/@llblab/pi-actors/lib/tool-review.ts +270 -0
  320. package/node_modules/@llblab/pi-actors/lib/tools-access.ts +68 -0
  321. package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +673 -0
  322. package/node_modules/@llblab/pi-actors/lib/tools-local.ts +303 -0
  323. package/node_modules/@llblab/pi-actors/lib/tools-message.ts +176 -0
  324. package/node_modules/@llblab/pi-actors/lib/tools-register.ts +63 -0
  325. package/node_modules/@llblab/pi-actors/lib/tools-response.ts +285 -0
  326. package/node_modules/@llblab/pi-actors/lib/tools-spawn.ts +212 -0
  327. package/node_modules/@llblab/pi-actors/lib/tools.ts +88 -0
  328. package/node_modules/@llblab/pi-actors/lib/trace-projection.ts +306 -0
  329. package/node_modules/@llblab/pi-actors/package.json +76 -0
  330. package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +555 -0
  331. package/node_modules/@llblab/pi-actors/scripts/build-dist.mjs +60 -0
  332. package/node_modules/@llblab/pi-actors/scripts/conformance.mjs +63 -0
  333. package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +126 -0
  334. package/node_modules/@llblab/pi-actors/skills/actors/recipes/command-validate.json +13 -0
  335. package/node_modules/@llblab/pi-actors/skills/actors/recipes/jsonl-tail.json +10 -0
  336. package/node_modules/@llblab/pi-actors/skills/actors/recipes/recipe-validate.json +11 -0
  337. package/node_modules/@llblab/pi-actors/skills/actors/recipes/resource-locker-snapshot.json +11 -0
  338. package/node_modules/@llblab/pi-actors/skills/actors/recipes/resource-locker.json +25 -0
  339. package/node_modules/@llblab/pi-actors/skills/actors/recipes/run-ops-snapshot.json +15 -0
  340. package/node_modules/@llblab/pi-actors/skills/actors/recipes/run-state-files.json +13 -0
  341. package/node_modules/@llblab/pi-actors/skills/actors/recipes/run-summary.json +9 -0
  342. package/node_modules/@llblab/pi-actors/skills/actors/references/diagnostics.md +44 -0
  343. package/node_modules/@llblab/pi-actors/skills/actors/references/persistent-tools.md +76 -0
  344. package/node_modules/@llblab/pi-actors/skills/actors/references/recipes.md +51 -0
  345. package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +41 -0
  346. package/node_modules/@llblab/pi-actors/skills/actors/scripts/resource-locker.mjs +425 -0
  347. package/node_modules/@llblab/pi-actors/skills/actors/scripts/run-utils.mjs +164 -0
  348. package/node_modules/@llblab/pi-actors/skills/actors/scripts/validate-recipe.mjs +370 -0
  349. package/node_modules/@llblab/pi-actors/skills/artifacts/SKILL.md +33 -0
  350. package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/bundle.json +77 -0
  351. package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/file-write.json +14 -0
  352. package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/manifest.json +14 -0
  353. package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/report.json +39 -0
  354. package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/write.json +53 -0
  355. package/node_modules/@llblab/pi-actors/skills/artifacts/scripts/artifact-utils.mjs +63 -0
  356. package/node_modules/@llblab/pi-actors/skills/music-player/SKILL.md +57 -0
  357. package/node_modules/@llblab/pi-actors/skills/music-player/genapps/music-player.mjs +360 -0
  358. package/node_modules/@llblab/pi-actors/skills/music-player/recipes/playback.json +29 -0
  359. package/node_modules/@llblab/pi-actors/skills/music-player/scripts/playback-client.mjs +143 -0
  360. package/node_modules/@llblab/pi-actors/skills/music-player/scripts/playback.mjs +1446 -0
  361. package/node_modules/@llblab/pi-actors/skills/project-work/SKILL.md +37 -0
  362. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/changelog-head.json +11 -0
  363. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/changelog-section.json +11 -0
  364. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/docs-maintenance.json +66 -0
  365. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/git-log.json +11 -0
  366. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/git-status.json +9 -0
  367. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/markdown-index.json +14 -0
  368. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/package-summary.json +9 -0
  369. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/release-readiness.json +115 -0
  370. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/release-summary.json +74 -0
  371. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/repo-health.json +75 -0
  372. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/run-ops.json +56 -0
  373. package/node_modules/@llblab/pi-actors/skills/project-work/recipes/skill-summary.json +11 -0
  374. package/node_modules/@llblab/pi-actors/skills/project-work/scripts/project-utils.mjs +89 -0
  375. package/node_modules/@llblab/pi-actors/skills/recipe-memory/SKILL.md +36 -0
  376. package/node_modules/@llblab/pi-actors/skills/recipe-memory/recipes/draft-review.json +14 -0
  377. package/node_modules/@llblab/pi-actors/skills/recipe-memory/recipes/tool-review.json +14 -0
  378. package/node_modules/@llblab/pi-actors/skills/swarm/SKILL.md +84 -0
  379. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/architect.json +82 -0
  380. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/checkpoint-continuation.json +51 -0
  381. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/development-tasking.json +67 -0
  382. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/lens-review.json +63 -0
  383. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/quorum-review.json +65 -0
  384. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/research-synthesis.json +81 -0
  385. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/review-readiness.json +59 -0
  386. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-artifact.json +21 -0
  387. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-checkpoint.json +21 -0
  388. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-conflict-report.json +19 -0
  389. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-contradiction-map.json +20 -0
  390. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-critic.json +22 -0
  391. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-evidence-map.json +20 -0
  392. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-followup.json +21 -0
  393. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-judge.json +22 -0
  394. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-merge.json +24 -0
  395. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-normalize.json +20 -0
  396. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-plan.json +20 -0
  397. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-preflight.json +18 -0
  398. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-prompt.json +16 -0
  399. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-prompts.json +39 -0
  400. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-quorum.json +31 -0
  401. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-review-coordinator.json +170 -0
  402. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-review.json +26 -0
  403. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-task-card.json +22 -0
  404. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-tools.json +15 -0
  405. package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-verify.json +23 -0
  406. package/node_modules/@llblab/pi-actors/skills/swarm/references/development-swarm.md +189 -0
  407. package/node_modules/@llblab/pi-actors/skills/swarm/references/review-swarms.md +115 -0
  408. package/node_modules/@llblab/pi-codex-usage/AGENTS.md +17 -0
  409. package/node_modules/@llblab/pi-codex-usage/BACKLOG.md +8 -0
  410. package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +80 -0
  411. package/node_modules/@llblab/pi-codex-usage/LICENSE +22 -0
  412. package/node_modules/@llblab/pi-codex-usage/README.md +113 -0
  413. package/node_modules/@llblab/pi-codex-usage/banner.jpg +0 -0
  414. package/node_modules/@llblab/pi-codex-usage/index.ts +1525 -0
  415. package/node_modules/@llblab/pi-codex-usage/package.json +59 -0
  416. package/node_modules/@llblab/pi-grow-loop/AGENTS.md +56 -0
  417. package/node_modules/@llblab/pi-grow-loop/BACKLOG.md +3 -0
  418. package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +126 -0
  419. package/node_modules/@llblab/pi-grow-loop/README.md +216 -0
  420. package/node_modules/@llblab/pi-grow-loop/banner.jpg +0 -0
  421. package/node_modules/@llblab/pi-grow-loop/index.ts +219 -0
  422. package/node_modules/@llblab/pi-grow-loop/package.json +64 -0
  423. package/node_modules/@llblab/pi-grow-loop/skills/grow-loop/SKILL.md +131 -0
  424. package/node_modules/@llblab/pi-grow-loop/skills/while-true/SKILL.md +233 -0
  425. package/node_modules/@llblab/pi-telegram/AGENTS.md +157 -0
  426. package/node_modules/@llblab/pi-telegram/BACKLOG.md +15 -0
  427. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +886 -0
  428. package/node_modules/@llblab/pi-telegram/README.md +330 -0
  429. package/node_modules/@llblab/pi-telegram/api/activity.ts +15 -0
  430. package/node_modules/@llblab/pi-telegram/api/commands.ts +11 -0
  431. package/node_modules/@llblab/pi-telegram/api/delivery.ts +21 -0
  432. package/node_modules/@llblab/pi-telegram/api/inbound.ts +14 -0
  433. package/node_modules/@llblab/pi-telegram/api/keyboard.ts +11 -0
  434. package/node_modules/@llblab/pi-telegram/api/outbound.ts +11 -0
  435. package/node_modules/@llblab/pi-telegram/api/sections.ts +17 -0
  436. package/node_modules/@llblab/pi-telegram/api/status.ts +12 -0
  437. package/node_modules/@llblab/pi-telegram/api/updates.ts +16 -0
  438. package/node_modules/@llblab/pi-telegram/api/voice.ts +24 -0
  439. package/node_modules/@llblab/pi-telegram/docs/README.md +25 -0
  440. package/node_modules/@llblab/pi-telegram/docs/activity.md +304 -0
  441. package/node_modules/@llblab/pi-telegram/docs/architecture.md +418 -0
  442. package/node_modules/@llblab/pi-telegram/docs/callback-namespaces.md +48 -0
  443. package/node_modules/@llblab/pi-telegram/docs/command-templates.md +365 -0
  444. package/node_modules/@llblab/pi-telegram/docs/compact-matrix-literal.md +176 -0
  445. package/node_modules/@llblab/pi-telegram/docs/delivery.md +225 -0
  446. package/node_modules/@llblab/pi-telegram/docs/generative-apps.md +310 -0
  447. package/node_modules/@llblab/pi-telegram/docs/inbound.md +136 -0
  448. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +467 -0
  449. package/node_modules/@llblab/pi-telegram/docs/outbound.md +193 -0
  450. package/node_modules/@llblab/pi-telegram/docs/public-api.md +599 -0
  451. package/node_modules/@llblab/pi-telegram/docs/sections.md +452 -0
  452. package/node_modules/@llblab/pi-telegram/docs/ui-style.md +256 -0
  453. package/node_modules/@llblab/pi-telegram/docs/updates.md +171 -0
  454. package/node_modules/@llblab/pi-telegram/docs/voice.md +217 -0
  455. package/node_modules/@llblab/pi-telegram/index.ts +1336 -0
  456. package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +714 -0
  457. package/node_modules/@llblab/pi-telegram/lib/activity.ts +782 -0
  458. package/node_modules/@llblab/pi-telegram/lib/agent-messages.ts +121 -0
  459. package/node_modules/@llblab/pi-telegram/lib/bindings.ts +1129 -0
  460. package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +379 -0
  461. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +1941 -0
  462. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +2119 -0
  463. package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +244 -0
  464. package/node_modules/@llblab/pi-telegram/lib/bus.ts +2645 -0
  465. package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +954 -0
  466. package/node_modules/@llblab/pi-telegram/lib/commands.ts +1854 -0
  467. package/node_modules/@llblab/pi-telegram/lib/config.ts +1143 -0
  468. package/node_modules/@llblab/pi-telegram/lib/delivery.ts +891 -0
  469. package/node_modules/@llblab/pi-telegram/lib/generative-app-worker.mjs +104 -0
  470. package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +958 -0
  471. package/node_modules/@llblab/pi-telegram/lib/inbound.ts +824 -0
  472. package/node_modules/@llblab/pi-telegram/lib/journal.ts +3140 -0
  473. package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +59 -0
  474. package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +623 -0
  475. package/node_modules/@llblab/pi-telegram/lib/locks.ts +1422 -0
  476. package/node_modules/@llblab/pi-telegram/lib/logs.ts +393 -0
  477. package/node_modules/@llblab/pi-telegram/lib/media.ts +921 -0
  478. package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +1182 -0
  479. package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +926 -0
  480. package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +876 -0
  481. package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +274 -0
  482. package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +185 -0
  483. package/node_modules/@llblab/pi-telegram/lib/menu.ts +867 -0
  484. package/node_modules/@llblab/pi-telegram/lib/model.ts +672 -0
  485. package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +981 -0
  486. package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +331 -0
  487. package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +515 -0
  488. package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +285 -0
  489. package/node_modules/@llblab/pi-telegram/lib/outbound.ts +1007 -0
  490. package/node_modules/@llblab/pi-telegram/lib/ownership.ts +298 -0
  491. package/node_modules/@llblab/pi-telegram/lib/paths.ts +127 -0
  492. package/node_modules/@llblab/pi-telegram/lib/pi.ts +197 -0
  493. package/node_modules/@llblab/pi-telegram/lib/polling.ts +1588 -0
  494. package/node_modules/@llblab/pi-telegram/lib/preview.ts +846 -0
  495. package/node_modules/@llblab/pi-telegram/lib/prompt-templates.ts +158 -0
  496. package/node_modules/@llblab/pi-telegram/lib/prompts.ts +218 -0
  497. package/node_modules/@llblab/pi-telegram/lib/queue.ts +3075 -0
  498. package/node_modules/@llblab/pi-telegram/lib/recovery.ts +464 -0
  499. package/node_modules/@llblab/pi-telegram/lib/rendering.ts +1213 -0
  500. package/node_modules/@llblab/pi-telegram/lib/replies.ts +892 -0
  501. package/node_modules/@llblab/pi-telegram/lib/routing.ts +2889 -0
  502. package/node_modules/@llblab/pi-telegram/lib/runtime.ts +628 -0
  503. package/node_modules/@llblab/pi-telegram/lib/sections.ts +710 -0
  504. package/node_modules/@llblab/pi-telegram/lib/setup.ts +220 -0
  505. package/node_modules/@llblab/pi-telegram/lib/skills.ts +21 -0
  506. package/node_modules/@llblab/pi-telegram/lib/status.ts +1550 -0
  507. package/node_modules/@llblab/pi-telegram/lib/sync.ts +883 -0
  508. package/node_modules/@llblab/pi-telegram/lib/target.ts +49 -0
  509. package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +1747 -0
  510. package/node_modules/@llblab/pi-telegram/lib/text-groups.ts +487 -0
  511. package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +1002 -0
  512. package/node_modules/@llblab/pi-telegram/lib/threads.ts +3183 -0
  513. package/node_modules/@llblab/pi-telegram/lib/time-injection.ts +78 -0
  514. package/node_modules/@llblab/pi-telegram/lib/turns.ts +753 -0
  515. package/node_modules/@llblab/pi-telegram/lib/updates.ts +4950 -0
  516. package/node_modules/@llblab/pi-telegram/lib/voice.ts +340 -0
  517. package/node_modules/@llblab/pi-telegram/package.json +83 -0
  518. package/node_modules/@llblab/pi-telegram/screenshot.png +0 -0
  519. package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +435 -0
  520. package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/SKILL.md +241 -0
  521. package/node_modules/@llblab/pi-telegram/skills/generative-apps/SKILL.md +114 -0
  522. package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/SKILL.md +149 -0
  523. package/package.json +67 -0
@@ -0,0 +1,1337 @@
1
+ /**
2
+ * Async run observability helpers
3
+ * Zones: async runtime, ambient UI, diagnostics
4
+ * Owns ambient summaries, terminal events, and Trace-attention delivery for detached Runs
5
+ */
6
+
7
+ import {
8
+ closeSync,
9
+ existsSync,
10
+ fstatSync,
11
+ openSync,
12
+ readdirSync,
13
+ readFileSync,
14
+ readSync,
15
+ watch,
16
+ type FSWatcher,
17
+ } from "node:fs";
18
+ import {
19
+ basename,
20
+ dirname,
21
+ isAbsolute,
22
+ join,
23
+ relative,
24
+ } from "node:path";
25
+
26
+ import * as AsyncRuns from "./async-runs.ts";
27
+ import * as Paths from "./paths.ts";
28
+ import * as RunsTrace from "./runs-trace.ts";
29
+ import { readJsonlFileResilient } from "./state-readers.ts";
30
+
31
+ export type RunObservedStatus =
32
+ | "running"
33
+ | "done"
34
+ | "failed"
35
+ | "exited"
36
+ | "cancelled"
37
+ | "killed";
38
+ export type RunTraceAttention = "log" | "notify" | "followup";
39
+ export type RunTraceLevel = "info" | "warning" | "error";
40
+
41
+ export interface RunObservation {
42
+ activeSubagents?: number;
43
+ completed?: number;
44
+ descendantSubagents?: number;
45
+ failures?: number;
46
+ ownerId?: string;
47
+ artifacts?: Record<string, string>;
48
+ launchCorrelation?: Record<string, string>;
49
+ launchSource?: AsyncRuns.AsyncRunLaunchSource;
50
+ modelPolicy?: Record<string, unknown>;
51
+ notificationPolicy?: "normal" | "silent";
52
+ recipeFile?: string;
53
+ terminalHandled?: boolean;
54
+ retireWhen?: string;
55
+ run: string;
56
+ semanticResult?: RunTerminalSemanticResult;
57
+ tool?: string;
58
+ stateDir?: string;
59
+ status: RunObservedStatus;
60
+ updatedAt?: string;
61
+ }
62
+
63
+ export interface RunSummary {
64
+ cancelled: number;
65
+ done: number;
66
+ exited: number;
67
+ failed: number;
68
+ killed: number;
69
+ running: number;
70
+ runningSubagents: number;
71
+ runs: RunObservation[];
72
+ total: number;
73
+ }
74
+
75
+ export interface RunUiObservationState {
76
+ attentionEventIds: Map<string, Set<string>>;
77
+ legacyEventLines: Map<string, number>;
78
+ frame: number;
79
+ observed: Map<string, RunObservedStatus>;
80
+ }
81
+
82
+ export interface RunUiSnapshot {
83
+ attentionEvents: RunAttentionEvent[];
84
+ status: string | undefined;
85
+ summary: RunSummary;
86
+ transitions: RunTransition[];
87
+ }
88
+
89
+ export interface RunUiNotificationSink {
90
+ notify(message: string, level: "info" | "warning" | "error"): void;
91
+ sendFollowUp(message: {
92
+ customType: string;
93
+ content: string;
94
+ display: false;
95
+ details: unknown;
96
+ }): void;
97
+ }
98
+
99
+ export function createRunUiObservationState(): RunUiObservationState {
100
+ return {
101
+ attentionEventIds: new Map<string, Set<string>>(),
102
+ legacyEventLines: new Map<string, number>(),
103
+ frame: 0,
104
+ observed: new Map<string, RunObservedStatus>(),
105
+ };
106
+ }
107
+
108
+ export function primeRunAttentionState(
109
+ state: RunUiObservationState, ownerId: string, stateRoot?: string,
110
+ ): void {
111
+ detectRunAttentionEvents(state.legacyEventLines, summarizeRuns(stateRoot, ownerId),
112
+ state.attentionEventIds, true);
113
+ }
114
+
115
+ export function readRunUiSnapshot(
116
+ state: RunUiObservationState,
117
+ ownerId: string,
118
+ options: { includeAttention?: boolean; stateRoot?: string } = {},
119
+ ): RunUiSnapshot {
120
+ const summary = summarizeRuns(options.stateRoot, ownerId);
121
+ const status = renderRunStatus(summary, state.frame++);
122
+ return {
123
+ attentionEvents:
124
+ options.includeAttention === false
125
+ ? []
126
+ : detectRunAttentionEvents(
127
+ state.legacyEventLines,
128
+ summary,
129
+ state.attentionEventIds,
130
+ ),
131
+ status,
132
+ summary,
133
+ transitions: detectRunTransitions(state.observed, summary),
134
+ };
135
+ }
136
+
137
+ export function pruneRunUiObservationState(
138
+ state: RunUiObservationState,
139
+ snapshot: Pick<RunUiSnapshot, "summary" | "transitions">,
140
+ ): void {
141
+ pruneRunObservationState(
142
+ state.observed,
143
+ state.legacyEventLines,
144
+ snapshot.summary,
145
+ snapshot.transitions.map(
146
+ (transition) => transition.stateDir ?? transition.run,
147
+ ),
148
+ state.attentionEventIds,
149
+ );
150
+ }
151
+
152
+ export function deliverRunTransitionNotifications(
153
+ transitions: RunTransition[],
154
+ sink: RunUiNotificationSink,
155
+ inFlight: Set<string> = new Set(),
156
+ ): void {
157
+ for (const transition of transitions) {
158
+ if (!shouldNotifyRunTransition(transition)) continue;
159
+ const key = transition.stateDir ?? transition.run;
160
+ if (inFlight.has(key)) continue;
161
+ inFlight.add(key);
162
+ try {
163
+ const text = formatRunTransitionMessage(transition);
164
+ sink.notify(text, getRunTransitionNotificationType(transition));
165
+ if (!shouldSendRunTransitionFollowUp(transition)) continue;
166
+ sink.sendFollowUp({
167
+ customType: "pi-actors-run",
168
+ content: text,
169
+ display: false,
170
+ details: transition,
171
+ });
172
+ if (transition.stateDir) {
173
+ AsyncRuns.markRunTerminalNotificationHandled(
174
+ transition.stateDir,
175
+ transition.to,
176
+ );
177
+ }
178
+ } catch (error) {
179
+ if (transition.stateDir) {
180
+ AsyncRuns.recordRunTerminalDeliveryFailure(
181
+ transition.stateDir,
182
+ transition.to,
183
+ error,
184
+ );
185
+ }
186
+ const message = error instanceof Error ? error.message : String(error);
187
+ sink.notify(
188
+ `Actor terminal delivery failed for run:${transition.run}: ${message.replaceAll(/\s+/g, " ").slice(0, 240)}`,
189
+ "error",
190
+ );
191
+ } finally {
192
+ inFlight.delete(key);
193
+ }
194
+ }
195
+ }
196
+
197
+ export function reconcileRunTerminalNotifications(input: {
198
+ inFlight?: Set<string>;
199
+ ownerId: string;
200
+ sink: RunUiNotificationSink;
201
+ state: RunUiObservationState;
202
+ stateRoot?: string;
203
+ includeAttention?: boolean;
204
+ }): RunUiSnapshot {
205
+ const snapshot = readRunUiSnapshot(input.state, input.ownerId, {
206
+ includeAttention: input.includeAttention,
207
+ stateRoot: input.stateRoot,
208
+ });
209
+ if (input.includeAttention)
210
+ deliverRunAttentionNotifications(snapshot.attentionEvents, input.sink);
211
+ deliverRunTransitionNotifications(snapshot.transitions, input.sink, input.inFlight);
212
+ pruneRunUiObservationState(input.state, snapshot);
213
+ return snapshot;
214
+ }
215
+
216
+ export function deliverRunAttentionNotifications(
217
+ events: RunAttentionEvent[],
218
+ sink: RunUiNotificationSink,
219
+ ): void {
220
+ for (const event of events) {
221
+ if (!shouldNotifyRunAttentionEvent(event)) continue;
222
+ const text = formatRunAttentionMessage(event);
223
+ sink.notify(text, getRunAttentionNotificationType(event));
224
+ if (!shouldSendRunAttentionFollowUp(event)) continue;
225
+ sink.sendFollowUp({
226
+ customType: "pi-actors-run-trace",
227
+ content: text,
228
+ display: false,
229
+ details: event,
230
+ });
231
+ }
232
+ }
233
+
234
+ export interface RunRetirementCandidate {
235
+ activeSubagents: number;
236
+ childRuns: number;
237
+ descendantSubagents: number;
238
+ run: string;
239
+ stateDir: string;
240
+ terminalChildRuns: number;
241
+ }
242
+
243
+ export interface RunRetirementExecution {
244
+ action: "stop" | "cancel" | "skip" | "failed";
245
+ error?: string;
246
+ run: string;
247
+ stateDir: string;
248
+ }
249
+
250
+ export type RunStateWatcherDiagnosticCode =
251
+ | "attach_failed"
252
+ | "error"
253
+ | "removed"
254
+ | "rearmed";
255
+
256
+ export interface RunStateWatcherDiagnostic {
257
+ code: RunStateWatcherDiagnosticCode;
258
+ id: number;
259
+ message: string;
260
+ path: string;
261
+ scope: "root" | "run";
262
+ ts: string;
263
+ }
264
+
265
+ export interface RunStateWatcher {
266
+ close(): void;
267
+ getDiagnostics(): RunStateWatcherDiagnostic[];
268
+ refresh(): void;
269
+ }
270
+
271
+ const RUN_WATCHER_DIAGNOSTIC_LIMIT = 32;
272
+
273
+ export function createRunStateWatcher(input: {
274
+ exists?: (path: string) => boolean;
275
+ listDirectories?: (path: string) => string[];
276
+ onChange: () => void;
277
+ stateRoot?: string;
278
+ watchPath?: (path: string, onChange: () => void) => FSWatcher;
279
+ }): RunStateWatcher {
280
+ const stateRoot = input.stateRoot ?? Paths.getRunStateRoot();
281
+ const pathExists = input.exists ?? existsSync;
282
+ const listDirectories =
283
+ input.listDirectories ??
284
+ ((path: string) =>
285
+ readdirSync(path, { withFileTypes: true })
286
+ .filter((entry) => entry.isDirectory())
287
+ .map((entry) => join(path, entry.name)));
288
+ const watchPath = input.watchPath ?? ((path, onChange) => watch(path, onChange));
289
+ let diagnosticId = 0;
290
+ let rootDegraded = false;
291
+ let stateRootWatcher: FSWatcher | undefined;
292
+ const degradedRunDirs = new Set<string>();
293
+ const diagnostics: RunStateWatcherDiagnostic[] = [];
294
+ const lastDiagnosticSignatures = new Map<string, string>();
295
+ const runDirWatchers = new Map<string, FSWatcher>();
296
+ const record = (
297
+ code: RunStateWatcherDiagnosticCode,
298
+ scope: "root" | "run",
299
+ path: string,
300
+ error?: unknown,
301
+ ): void => {
302
+ const detail = error instanceof Error ? `: ${error.message}` : "";
303
+ const signature = `${code}${detail}`;
304
+ const signatureKey = `${scope}:${path}`;
305
+ if (lastDiagnosticSignatures.get(signatureKey) === signature) return;
306
+ lastDiagnosticSignatures.set(signatureKey, signature);
307
+ const recovery =
308
+ code === "rearmed"
309
+ ? "; terminal watch acceleration restored"
310
+ : "; terminal reconciliation remains active and watcher rearm will retry";
311
+ diagnostics.push({
312
+ code,
313
+ id: ++diagnosticId,
314
+ message: `Run-state ${scope} watcher ${code.replace("_", " ")} for ${path}${detail}${recovery}`,
315
+ path,
316
+ scope,
317
+ ts: new Date().toISOString(),
318
+ });
319
+ if (diagnostics.length > RUN_WATCHER_DIAGNOSTIC_LIMIT) diagnostics.shift();
320
+ };
321
+ const removeRunWatcher = (
322
+ stateDir: string,
323
+ watcher: FSWatcher,
324
+ options: { degraded?: boolean; error?: unknown } = {},
325
+ ): void => {
326
+ if (runDirWatchers.get(stateDir) !== watcher) return;
327
+ watcher.close();
328
+ runDirWatchers.delete(stateDir);
329
+ if (options.degraded === false) {
330
+ degradedRunDirs.delete(stateDir);
331
+ lastDiagnosticSignatures.delete(`run:${stateDir}`);
332
+ return;
333
+ }
334
+ degradedRunDirs.add(stateDir);
335
+ if (options.error) record("error", "run", stateDir, options.error);
336
+ record("removed", "run", stateDir);
337
+ };
338
+ const close = (): void => {
339
+ stateRootWatcher?.close();
340
+ stateRootWatcher = undefined;
341
+ for (const watcher of runDirWatchers.values()) watcher.close();
342
+ runDirWatchers.clear();
343
+ };
344
+ const watchRunDir = (stateDir: string): void => {
345
+ if (runDirWatchers.has(stateDir) || !pathExists(stateDir)) return;
346
+ try {
347
+ const watcher = watchPath(stateDir, input.onChange);
348
+ watcher.on("error", (error) =>
349
+ removeRunWatcher(stateDir, watcher, { error }),
350
+ );
351
+ runDirWatchers.set(stateDir, watcher);
352
+ if (degradedRunDirs.delete(stateDir)) record("rearmed", "run", stateDir);
353
+ } catch (error) {
354
+ degradedRunDirs.add(stateDir);
355
+ record("attach_failed", "run", stateDir, error);
356
+ }
357
+ };
358
+ function refresh(): void {
359
+ if (!pathExists(stateRoot)) return;
360
+ if (!stateRootWatcher) {
361
+ try {
362
+ const watcher = watchPath(stateRoot, input.onChange);
363
+ stateRootWatcher = watcher;
364
+ watcher.on("error", (error) => {
365
+ if (stateRootWatcher !== watcher) return;
366
+ watcher.close();
367
+ stateRootWatcher = undefined;
368
+ rootDegraded = true;
369
+ record("error", "root", stateRoot, error);
370
+ record("removed", "root", stateRoot);
371
+ });
372
+ if (rootDegraded) {
373
+ rootDegraded = false;
374
+ record("rearmed", "root", stateRoot);
375
+ }
376
+ } catch (error) {
377
+ rootDegraded = true;
378
+ record("attach_failed", "root", stateRoot, error);
379
+ }
380
+ }
381
+ let stateDirs: string[];
382
+ try {
383
+ stateDirs = listDirectories(stateRoot);
384
+ } catch (error) {
385
+ record("attach_failed", "root", stateRoot, error);
386
+ return;
387
+ }
388
+ const present = new Set(stateDirs);
389
+ for (const [stateDir, watcher] of runDirWatchers) {
390
+ if (present.has(stateDir) && pathExists(stateDir)) continue;
391
+ removeRunWatcher(stateDir, watcher, { degraded: false });
392
+ }
393
+ for (const stateDir of stateDirs) watchRunDir(stateDir);
394
+ }
395
+ return {
396
+ close,
397
+ getDiagnostics: () => [...diagnostics],
398
+ refresh,
399
+ };
400
+ }
401
+
402
+ export interface RunTerminalReconciliationLoop {
403
+ close(): void;
404
+ reconcileNow(): void;
405
+ start(): void;
406
+ }
407
+
408
+ export function createRunTerminalReconciliationLoop(input: {
409
+ intervalMs?: number;
410
+ onError?: (error: unknown) => void;
411
+ reconcile: () => void;
412
+ refreshWatcher: () => void;
413
+ }): RunTerminalReconciliationLoop {
414
+ const intervalMs = input.intervalMs ?? 10_000;
415
+ let interval: NodeJS.Timeout | undefined;
416
+ const reconcileNow = (): void => {
417
+ try {
418
+ input.refreshWatcher();
419
+ input.reconcile();
420
+ } catch (error) {
421
+ input.onError?.(error);
422
+ }
423
+ };
424
+ const close = (): void => {
425
+ if (interval) clearInterval(interval);
426
+ interval = undefined;
427
+ };
428
+ const start = (): void => {
429
+ close();
430
+ interval = setInterval(reconcileNow, intervalMs);
431
+ interval.unref?.();
432
+ };
433
+ return { close, reconcileNow, start };
434
+ }
435
+
436
+ export interface RunRetirementExecutorOptions {
437
+ attempted?: Set<string>;
438
+ cancelRun: (candidate: RunRetirementCandidate) => Record<string, unknown>;
439
+ notify?: (message: string, level: "info" | "warning" | "error") => void;
440
+ sendStop: (candidate: RunRetirementCandidate) => Promise<unknown>;
441
+ }
442
+
443
+ export interface RunTransition {
444
+ from: RunObservedStatus;
445
+ run: string;
446
+ stateDir?: string;
447
+ artifacts?: Record<string, string>;
448
+ launchCorrelation?: Record<string, string>;
449
+ launchSource?: AsyncRuns.AsyncRunLaunchSource;
450
+ modelPolicy?: Record<string, unknown>;
451
+ recipeFile?: string;
452
+ terminalHandled?: boolean;
453
+ to: RunObservedStatus;
454
+ tool?: string;
455
+ semanticResult?: RunTerminalSemanticResult;
456
+ }
457
+
458
+ export interface RunTerminalSemanticResult {
459
+ body?: string;
460
+ correlationId?: string;
461
+ metadata: Record<string, unknown>;
462
+ summary: string;
463
+ synthesized: boolean;
464
+ type: string;
465
+ }
466
+
467
+ export interface RunAttentionEvent {
468
+ body?: unknown;
469
+ data?: unknown;
470
+ attention: RunTraceAttention;
471
+ id: string;
472
+ kind: string;
473
+ level: RunTraceLevel;
474
+ metadata?: Record<string, unknown>;
475
+ run: string;
476
+ stateDir: string;
477
+ summary: string;
478
+ ts: string;
479
+ }
480
+
481
+ export type RunTransitionNotificationType = "info" | "warning" | "error";
482
+
483
+ const TERMINAL = new Set<RunObservedStatus>([
484
+ "done",
485
+ "failed",
486
+ "exited",
487
+ "cancelled",
488
+ "killed",
489
+ ]);
490
+ const PROC_DESCENDANT_SCAN_TTL_MS = 1000;
491
+ const RUN_STATE_DISCOVERY_MAX_DEPTH = 8;
492
+
493
+ const procDescendantScanCache = new Map<
494
+ string,
495
+ { counts: Map<string, number>; expiresAt: number; signature: string }
496
+ >();
497
+
498
+ function toNumber(value: unknown): number | undefined {
499
+ const number = Number(value);
500
+ return Number.isFinite(number) ? number : undefined;
501
+ }
502
+
503
+ function getProgress(status: Record<string, unknown>): Record<string, unknown> {
504
+ const progress = status.progress;
505
+ return progress && typeof progress === "object"
506
+ ? (progress as Record<string, unknown>)
507
+ : {};
508
+ }
509
+
510
+ function getUpdatedAt(status: Record<string, unknown>): string | undefined {
511
+ const progress = getProgress(status);
512
+ return typeof progress.updatedAt === "string"
513
+ ? progress.updatedAt
514
+ : typeof status.createdAt === "string"
515
+ ? status.createdAt
516
+ : undefined;
517
+ }
518
+
519
+ function scanRunStateDirs(
520
+ stateRoot: string,
521
+ depth = 0,
522
+ seen = new Set<string>(),
523
+ ): string[] {
524
+ if (!existsSync(stateRoot) || seen.has(stateRoot)) return [];
525
+ seen.add(stateRoot);
526
+ let entries: import("node:fs").Dirent[];
527
+ try {
528
+ entries = readdirSync(stateRoot, { withFileTypes: true });
529
+ } catch {
530
+ return [];
531
+ }
532
+ const result: string[] = [];
533
+ for (const entry of entries) {
534
+ if (!entry.isDirectory()) continue;
535
+ const child = join(stateRoot, entry.name);
536
+ if (existsSync(join(child, "run.json"))) result.push(child);
537
+ if (depth + 1 < RUN_STATE_DISCOVERY_MAX_DEPTH)
538
+ result.push(...scanRunStateDirs(child, depth + 1, seen));
539
+ }
540
+ return result;
541
+ }
542
+
543
+ const TERMINAL_RESULT_BYTES = 8 * 1024;
544
+ const TERMINAL_RESULT_CHARS = 4_000;
545
+
546
+ function readBoundedStart(path: string): string {
547
+ if (!existsSync(path)) return "";
548
+ const fd = openSync(path, "r");
549
+ try {
550
+ const size = Math.min(fstatSync(fd).size, TERMINAL_RESULT_BYTES);
551
+ const buffer = Buffer.alloc(size);
552
+ const bytes = readSync(fd, buffer, 0, size, 0);
553
+ const text = buffer.subarray(0, bytes).toString("utf8").trim();
554
+ return text.length > TERMINAL_RESULT_CHARS
555
+ ? `${text.slice(0, TERMINAL_RESULT_CHARS - 1)}…`
556
+ : text;
557
+ } finally {
558
+ closeSync(fd);
559
+ }
560
+ }
561
+
562
+ function semanticBodyFromStdout(stateDir: string): string | undefined {
563
+ const text = readBoundedStart(join(stateDir, "stdout.log"));
564
+ if (!text) return undefined;
565
+ const withoutMarker = text.replace(/^ACTOR_REVIEW_RESULT\s*(?:\r?\n)?/, "").trim();
566
+ return withoutMarker || undefined;
567
+ }
568
+
569
+ function terminalSemanticResult(
570
+ status: Record<string, unknown>,
571
+ stateDir: string,
572
+ observedStatus: RunObservedStatus,
573
+ ): RunTerminalSemanticResult {
574
+ const correlation = status.launch_correlation &&
575
+ typeof status.launch_correlation === "object" &&
576
+ !Array.isArray(status.launch_correlation)
577
+ ? status.launch_correlation as Record<string, unknown>
578
+ : {};
579
+ const correlationId =
580
+ typeof correlation.correlation_id === "string"
581
+ ? correlation.correlation_id
582
+ : typeof correlation.tool_call_id === "string"
583
+ ? correlation.tool_call_id
584
+ : undefined;
585
+ const reviewCompleted = false;
586
+ const result = status.result &&
587
+ typeof status.result === "object" &&
588
+ !Array.isArray(status.result)
589
+ ? status.result as Record<string, unknown>
590
+ : {};
591
+ const type = reviewCompleted
592
+ ? "review.completed"
593
+ : observedStatus === "done" ? "run.done" : "run.failed";
594
+ const stdoutBody = observedStatus === "done"
595
+ ? semanticBodyFromStdout(stateDir) : undefined;
596
+ return {
597
+ ...(stdoutBody
598
+ ? { body: stdoutBody }
599
+ : typeof result.error === "string" ? { body: result.error } : {}),
600
+ ...(correlationId ? { correlationId } : {}),
601
+ metadata: {
602
+ ...(status.transport_context &&
603
+ typeof status.transport_context === "object" &&
604
+ !Array.isArray(status.transport_context)
605
+ ? {
606
+ transport_context: status.transport_context as Record<string, unknown>,
607
+ } : {}),
608
+ run: String(status.run ?? ""), status: observedStatus,
609
+ },
610
+ summary: reviewCompleted ? "Review completed." :
611
+ observedStatus === "done" ? "Run completed." : `Run ${observedStatus}.`,
612
+ synthesized: true,
613
+ type,
614
+ };
615
+ }
616
+
617
+ function observeRun(stateDir: string): RunObservation | undefined {
618
+ try {
619
+ const status = AsyncRuns.getRunStatus(stateDir);
620
+ const progress = getProgress(status);
621
+ const run = typeof status.run === "string" ? status.run : undefined;
622
+ if (!run) return undefined;
623
+ const observedStatus = status.status as RunObservedStatus;
624
+ return {
625
+ activeSubagents: toNumber(progress.activeSubagents),
626
+ completed: toNumber(progress.completed),
627
+ ...(status.launch_correlation &&
628
+ typeof status.launch_correlation === "object" &&
629
+ !Array.isArray(status.launch_correlation)
630
+ ? { launchCorrelation: status.launch_correlation as Record<string, string> }
631
+ : {}),
632
+ failures: Array.isArray(progress.failures)
633
+ ? progress.failures.length
634
+ : undefined,
635
+ ...(typeof status.ownerId === "string"
636
+ ? { ownerId: status.ownerId }
637
+ : {}),
638
+ ...(status.artifacts &&
639
+ typeof status.artifacts === "object" &&
640
+ !Array.isArray(status.artifacts)
641
+ ? { artifacts: status.artifacts as Record<string, string> }
642
+ : {}),
643
+ ...(status.launch_source === "spawn" || status.launch_source === "tool"
644
+ ? { launchSource: status.launch_source }
645
+ : {}),
646
+ ...(status.model_policy &&
647
+ typeof status.model_policy === "object" &&
648
+ !Array.isArray(status.model_policy)
649
+ ? { modelPolicy: status.model_policy as Record<string, unknown> }
650
+ : {}),
651
+ ...(status.notification_policy === "silent"
652
+ ? { notificationPolicy: "silent" as const }
653
+ : {}),
654
+ ...(typeof status.recipe_file === "string"
655
+ ? { recipeFile: status.recipe_file }
656
+ : {}),
657
+ ...(status.terminal_handled ? { terminalHandled: true } : {}),
658
+ ...(typeof status.retire_when === "string"
659
+ ? { retireWhen: status.retire_when }
660
+ : {}),
661
+ ...(TERMINAL.has(observedStatus)
662
+ ? { semanticResult: terminalSemanticResult(status, stateDir, observedStatus) }
663
+ : {}),
664
+ run,
665
+ stateDir,
666
+ status: observedStatus,
667
+ ...(typeof status.tool === "string" ? { tool: status.tool } : {}),
668
+ updatedAt: getUpdatedAt(status),
669
+ };
670
+ } catch {
671
+ return undefined;
672
+ }
673
+ }
674
+
675
+ export function summarizeRuns(
676
+ stateRoot = Paths.getRunStateRoot(),
677
+ ownerId?: string,
678
+ ): RunSummary {
679
+ if (!existsSync(stateRoot)) {
680
+ return {
681
+ cancelled: 0,
682
+ done: 0,
683
+ exited: 0,
684
+ failed: 0,
685
+ killed: 0,
686
+ running: 0,
687
+ runningSubagents: 0,
688
+ runs: [],
689
+ total: 0,
690
+ };
691
+ }
692
+ const runs = (
693
+ AsyncRuns.readRunStateIndex(stateRoot)?.map((entry) => entry.state_dir) ??
694
+ scanRunStateDirs(stateRoot)
695
+ )
696
+ .map((stateDir) => observeRun(stateDir))
697
+ .filter((run): run is RunObservation => Boolean(run))
698
+ .filter((run) => ownerId === undefined || run.ownerId === ownerId)
699
+ .sort((a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? ""));
700
+ const processSubagentsByRun = countRunningSubagentsByRun(stateRoot, ownerId);
701
+ const runsWithDescendants = runs.map((run) => {
702
+ const descendantSubagents = processSubagentsByRun.get(run.run) ?? 0;
703
+ return descendantSubagents > 0 ? { ...run, descendantSubagents } : run;
704
+ });
705
+ const runningRuns = runsWithDescendants.filter(
706
+ (run) => run.status === "running",
707
+ );
708
+ const running = runningRuns.length;
709
+ const done = runsWithDescendants.filter(
710
+ (run) => run.status === "done",
711
+ ).length;
712
+ const exited = runsWithDescendants.filter(
713
+ (run) => run.status === "exited",
714
+ ).length;
715
+ const failed = runsWithDescendants.filter(
716
+ (run) => run.status === "failed",
717
+ ).length;
718
+ const cancelled = runsWithDescendants.filter(
719
+ (run) => run.status === "cancelled",
720
+ ).length;
721
+ const killed = runsWithDescendants.filter(
722
+ (run) => run.status === "killed",
723
+ ).length;
724
+ const progressSubagents = runningRuns.reduce(
725
+ (sum, run) => sum + Math.max(1, Math.floor(run.activeSubagents ?? 0)),
726
+ 0,
727
+ );
728
+ const processSubagents = [...processSubagentsByRun.values()].reduce(
729
+ (sum, count) => sum + count,
730
+ 0,
731
+ );
732
+ const runningSubagents = Math.max(
733
+ progressSubagents,
734
+ running + processSubagents,
735
+ );
736
+ return {
737
+ cancelled,
738
+ done,
739
+ exited,
740
+ failed,
741
+ killed,
742
+ running,
743
+ runningSubagents,
744
+ runs: runsWithDescendants,
745
+ total: runsWithDescendants.length,
746
+ };
747
+ }
748
+
749
+ function readProcFile(path: string): string | undefined {
750
+ try {
751
+ return readFileSync(path, "utf8");
752
+ } catch {
753
+ return undefined;
754
+ }
755
+ }
756
+
757
+ function getProcPpid(pid: string): string | undefined {
758
+ const stat = readProcFile(`/proc/${pid}/stat`);
759
+ if (!stat) return undefined;
760
+ const close = stat.lastIndexOf(")");
761
+ if (close === -1) return undefined;
762
+ return stat.slice(close + 2).split(" ")[1];
763
+ }
764
+
765
+ function getProcCommand(pid: string): string {
766
+ return (readProcFile(`/proc/${pid}/cmdline`) ?? "").replaceAll("\0", " ");
767
+ }
768
+
769
+ function getRunningRunPidMap(
770
+ stateRoot: string,
771
+ ownerId?: string,
772
+ ): Map<string, string> {
773
+ const pids = new Map<string, string>();
774
+ for (const run of summarizeRunsWithoutSubagents(stateRoot, ownerId).runs) {
775
+ if (run.status !== "running") continue;
776
+ const status = AsyncRuns.getRunStatus(
777
+ run.stateDir ?? join(stateRoot, run.run),
778
+ );
779
+ const pid = Number(status.pid || 0);
780
+ if (pid > 0) pids.set(String(pid), run.run);
781
+ }
782
+ return pids;
783
+ }
784
+
785
+ function summarizeRunsWithoutSubagents(
786
+ stateRoot: string,
787
+ ownerId?: string,
788
+ ): Omit<RunSummary, "runningSubagents"> {
789
+ if (!existsSync(stateRoot))
790
+ return {
791
+ cancelled: 0,
792
+ done: 0,
793
+ exited: 0,
794
+ failed: 0,
795
+ killed: 0,
796
+ running: 0,
797
+ runs: [],
798
+ total: 0,
799
+ };
800
+ const runs = (
801
+ AsyncRuns.readRunStateIndex(stateRoot)?.map((entry) => entry.state_dir) ??
802
+ scanRunStateDirs(stateRoot)
803
+ )
804
+ .map((stateDir) => observeRun(stateDir))
805
+ .filter((run): run is RunObservation => Boolean(run))
806
+ .filter((run) => ownerId === undefined || run.ownerId === ownerId)
807
+ .sort((a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? ""));
808
+ const running = runs.filter((run) => run.status === "running").length;
809
+ const done = runs.filter((run) => run.status === "done").length;
810
+ const exited = runs.filter((run) => run.status === "exited").length;
811
+ const failed = runs.filter((run) => run.status === "failed").length;
812
+ const cancelled = runs.filter((run) => run.status === "cancelled").length;
813
+ const killed = runs.filter((run) => run.status === "killed").length;
814
+ return {
815
+ cancelled,
816
+ done,
817
+ exited,
818
+ failed,
819
+ killed,
820
+ running,
821
+ runs,
822
+ total: runs.length,
823
+ };
824
+ }
825
+
826
+ export function countRunningSubagentsByRun(
827
+ stateRoot = Paths.getRunStateRoot(),
828
+ ownerId?: string,
829
+ ): Map<string, number> {
830
+ const runPidMap = getRunningRunPidMap(stateRoot, ownerId);
831
+ if (runPidMap.size === 0 || !existsSync("/proc")) return new Map();
832
+ const signature = [...runPidMap.keys()].sort().join(",");
833
+ const cacheKey = `${stateRoot}\0${ownerId ?? ""}`;
834
+ const cached = procDescendantScanCache.get(cacheKey);
835
+ const now = Date.now();
836
+ if (cached && cached.signature === signature && cached.expiresAt > now) {
837
+ return new Map(cached.counts);
838
+ }
839
+ const parentByPid = new Map<string, string>();
840
+ const commandByPid = new Map<string, string>();
841
+ let procEntries: import("node:fs").Dirent[];
842
+ try {
843
+ procEntries = readdirSync("/proc", { withFileTypes: true });
844
+ } catch {
845
+ return new Map();
846
+ }
847
+ for (const entry of procEntries) {
848
+ if (!entry.isDirectory() || !/^\d+$/.test(entry.name)) continue;
849
+ const ppid = getProcPpid(entry.name);
850
+ if (!ppid) continue;
851
+ parentByPid.set(entry.name, ppid);
852
+ commandByPid.set(entry.name, getProcCommand(entry.name));
853
+ }
854
+ const runForDescendant = (pid: string): string | undefined => {
855
+ let current = parentByPid.get(pid);
856
+ const seen = new Set<string>();
857
+ while (current && !seen.has(current)) {
858
+ const run = runPidMap.get(current);
859
+ if (run) return run;
860
+ seen.add(current);
861
+ current = parentByPid.get(current);
862
+ }
863
+ return undefined;
864
+ };
865
+ const counts = new Map<string, number>();
866
+ for (const [pid, command] of commandByPid.entries()) {
867
+ if (!command.includes("pi -p") && !command.includes("pi\0-p")) continue;
868
+ const run = runForDescendant(pid);
869
+ if (run) counts.set(run, (counts.get(run) ?? 0) + 1);
870
+ }
871
+ procDescendantScanCache.set(cacheKey, {
872
+ counts,
873
+ expiresAt: now + PROC_DESCENDANT_SCAN_TTL_MS,
874
+ signature,
875
+ });
876
+ return new Map(counts);
877
+ }
878
+
879
+ export function countRunningSubagents(
880
+ stateRoot = Paths.getRunStateRoot(),
881
+ ownerId?: string,
882
+ ): number {
883
+ return [...countRunningSubagentsByRun(stateRoot, ownerId).values()].reduce(
884
+ (sum, count) => sum + count,
885
+ 0,
886
+ );
887
+ }
888
+
889
+ export function renderSubagentStatus(
890
+ count: number,
891
+ frame = 0,
892
+ ): string | undefined {
893
+ if (count <= 0) return undefined;
894
+ if (count === 1) return frame % 2 === 0 ? "▶" : "▷";
895
+ const active = frame % count;
896
+ return Array.from({ length: count }, (_value, index) =>
897
+ index === active ? "▶" : "▷",
898
+ ).join(" ");
899
+ }
900
+
901
+ export function renderRunStatus(
902
+ summary: RunSummary,
903
+ frame = 0,
904
+ ): string | undefined {
905
+ return renderSubagentStatus(summary.runningSubagents, frame);
906
+ }
907
+
908
+ function isNestedStateDir(parent: string, child: string): boolean {
909
+ const path = relative(parent, child);
910
+ return Boolean(path) && !path.startsWith("..") && !isAbsolute(path);
911
+ }
912
+
913
+ export function findRunRetirementCandidates(
914
+ summary: RunSummary,
915
+ ): RunRetirementCandidate[] {
916
+ return summary.runs
917
+ .map((run) => {
918
+ const activeSubagents = Math.max(0, Math.floor(run.activeSubagents ?? 0));
919
+ const descendantSubagents = Math.max(
920
+ 0,
921
+ Math.floor(run.descendantSubagents ?? 0),
922
+ );
923
+ const childRuns = run.stateDir
924
+ ? summary.runs.filter(
925
+ (child) =>
926
+ child.stateDir !== undefined &&
927
+ child.stateDir !== run.stateDir &&
928
+ isNestedStateDir(run.stateDir!, child.stateDir),
929
+ )
930
+ : [];
931
+ const runningChildRuns = childRuns.filter(
932
+ (child) => child.status === "running",
933
+ ).length;
934
+ return {
935
+ activeSubagents,
936
+ childRuns: childRuns.length,
937
+ descendantSubagents,
938
+ ready:
939
+ run.status === "running" &&
940
+ run.retireWhen === "children_terminal" &&
941
+ run.stateDir !== undefined &&
942
+ !run.terminalHandled &&
943
+ activeSubagents + descendantSubagents + runningChildRuns <= 0,
944
+ run,
945
+ terminalChildRuns: childRuns.filter((child) =>
946
+ TERMINAL.has(child.status),
947
+ ).length,
948
+ };
949
+ })
950
+ .filter((item) => item.ready)
951
+ .map((item) => ({
952
+ activeSubagents: item.activeSubagents,
953
+ childRuns: item.childRuns,
954
+ descendantSubagents: item.descendantSubagents,
955
+ run: item.run.run,
956
+ stateDir: item.run.stateDir!,
957
+ terminalChildRuns: item.terminalChildRuns,
958
+ }));
959
+ }
960
+
961
+ export async function executeRunRetirements(
962
+ summary: RunSummary,
963
+ options: RunRetirementExecutorOptions,
964
+ ): Promise<RunRetirementExecution[]> {
965
+ const results: RunRetirementExecution[] = [];
966
+ for (const candidate of findRunRetirementCandidates(summary)) {
967
+ if (options.attempted?.has(candidate.stateDir)) {
968
+ results.push({
969
+ action: "skip",
970
+ run: candidate.run,
971
+ stateDir: candidate.stateDir,
972
+ });
973
+ continue;
974
+ }
975
+ options.attempted?.add(candidate.stateDir);
976
+ try {
977
+ await options.sendStop(candidate);
978
+ options.notify?.(
979
+ `Retiring actor ${candidate.run} after child runs reached terminal state`,
980
+ "info",
981
+ );
982
+ results.push({
983
+ action: "stop",
984
+ run: candidate.run,
985
+ stateDir: candidate.stateDir,
986
+ });
987
+ continue;
988
+ } catch (error) {
989
+ try {
990
+ const cancelResult = options.cancelRun(candidate);
991
+ const cancelled = Boolean(
992
+ (cancelResult as { cancelled?: unknown }).cancelled,
993
+ );
994
+ options.notify?.(
995
+ cancelled
996
+ ? `Retiring actor ${candidate.run} by cancellation after graceful stop failed`
997
+ : `Actor retirement skipped for ${candidate.run}: ${error instanceof Error ? error.message : String(error)}`,
998
+ cancelled ? "warning" : "error",
999
+ );
1000
+ results.push({
1001
+ action: cancelled ? "cancel" : "skip",
1002
+ ...(cancelled
1003
+ ? {}
1004
+ : {
1005
+ error: error instanceof Error ? error.message : String(error),
1006
+ }),
1007
+ run: candidate.run,
1008
+ stateDir: candidate.stateDir,
1009
+ });
1010
+ } catch (cancelError) {
1011
+ const message =
1012
+ cancelError instanceof Error
1013
+ ? cancelError.message
1014
+ : String(cancelError);
1015
+ options.notify?.(
1016
+ `Actor retirement failed for ${candidate.run}: ${message}`,
1017
+ "error",
1018
+ );
1019
+ results.push({
1020
+ action: "failed",
1021
+ error: message,
1022
+ run: candidate.run,
1023
+ stateDir: candidate.stateDir,
1024
+ });
1025
+ }
1026
+ }
1027
+ }
1028
+ return results;
1029
+ }
1030
+
1031
+ function runObservationKey(
1032
+ run: Pick<RunObservation, "run" | "stateDir">,
1033
+ ): string {
1034
+ return run.stateDir ?? run.run;
1035
+ }
1036
+
1037
+ export function detectRunTransitions(
1038
+ previous: Map<string, RunObservedStatus>,
1039
+ summary: RunSummary,
1040
+ ): RunTransition[] {
1041
+ const transitions: RunTransition[] = [];
1042
+ for (const run of summary.runs) {
1043
+ const key = runObservationKey(run);
1044
+ const old = previous.get(key);
1045
+ if (
1046
+ run.notificationPolicy !== "silent" &&
1047
+ !run.terminalHandled &&
1048
+ TERMINAL.has(run.status)
1049
+ ) {
1050
+ transitions.push({
1051
+ from: old ?? "running",
1052
+ run: run.run,
1053
+ ...(run.stateDir ? { stateDir: run.stateDir } : {}),
1054
+ ...(run.artifacts ? { artifacts: run.artifacts } : {}),
1055
+ ...(run.launchCorrelation ? { launchCorrelation: run.launchCorrelation } : {}),
1056
+ ...(run.launchSource ? { launchSource: run.launchSource } : {}),
1057
+ ...(run.modelPolicy ? { modelPolicy: run.modelPolicy } : {}),
1058
+ ...(run.recipeFile ? { recipeFile: run.recipeFile } : {}),
1059
+ ...(run.semanticResult ? { semanticResult: run.semanticResult } : {}),
1060
+ ...(run.terminalHandled ? { terminalHandled: true } : {}),
1061
+ to: run.status,
1062
+ ...(run.tool ? { tool: run.tool } : {}),
1063
+ });
1064
+ }
1065
+ previous.set(key, run.status);
1066
+ }
1067
+ return transitions;
1068
+ }
1069
+
1070
+ function normalizeTraceAttention(value: unknown): RunTraceAttention {
1071
+ return value === "notify" || value === "followup" ? value : "log";
1072
+ }
1073
+
1074
+ function normalizeTraceLevel(value: unknown): RunTraceLevel {
1075
+ return value === "warning" || value === "error" ? value : "info";
1076
+ }
1077
+
1078
+ function parseAttentionRecord(
1079
+ raw: Record<string, unknown>,
1080
+ run: RunObservation,
1081
+ index: number,
1082
+ ): RunAttentionEvent | undefined {
1083
+ if (!run.stateDir) return undefined;
1084
+ const event =
1085
+ typeof raw.kind === "string" && raw.kind.trim()
1086
+ ? raw.kind.trim()
1087
+ : typeof raw.event === "string" && raw.event.trim()
1088
+ ? raw.event.trim()
1089
+ : "run.event";
1090
+ const summary =
1091
+ typeof raw.summary === "string" && raw.summary.trim()
1092
+ ? raw.summary.trim()
1093
+ : event;
1094
+ const ts =
1095
+ typeof raw.ts === "string" && raw.ts.trim()
1096
+ ? raw.ts.trim()
1097
+ : new Date(0).toISOString();
1098
+ const id =
1099
+ typeof raw.id === "string" && raw.id.trim()
1100
+ ? raw.id.trim()
1101
+ : `${run.run}:${index}`;
1102
+ return {
1103
+ ...(raw.body !== undefined ? { body: raw.body } : {}),
1104
+ ...(raw.data !== undefined ? { data: raw.data } : {}),
1105
+ attention:
1106
+ raw.attention === "notify" || raw.attention === "followup"
1107
+ ? raw.attention
1108
+ : normalizeTraceAttention(raw.delivery),
1109
+ id,
1110
+ kind: event,
1111
+ level: normalizeTraceLevel(raw.level),
1112
+ ...(raw.metadata &&
1113
+ typeof raw.metadata === "object" &&
1114
+ !Array.isArray(raw.metadata)
1115
+ ? { metadata: raw.metadata as Record<string, unknown> }
1116
+ : {}),
1117
+ run: run.run,
1118
+ stateDir: run.stateDir,
1119
+ summary,
1120
+ ts,
1121
+ };
1122
+ }
1123
+
1124
+ function readTraceAttentionRecords(run: RunObservation): {
1125
+ canonical: boolean; records: Record<string, unknown>[];
1126
+ } {
1127
+ if (!run.stateDir) return { canonical: true, records: [] };
1128
+ if (existsSync(join(run.stateDir, "trace.jsonl"))) return {
1129
+ canonical: true,
1130
+ records: RunsTrace.readRunTraceJournal(run.stateDir).events.map(
1131
+ ({ event }) => event as unknown as Record<string, unknown>),
1132
+ };
1133
+ return { canonical: false, records: readJsonlFileResilient<Record<string, unknown>>(
1134
+ join(run.stateDir, "outbox.jsonl")).records };
1135
+ }
1136
+
1137
+ export function pruneRunObservationState(
1138
+ previousStatuses: Map<string, RunObservedStatus>,
1139
+ previousLineCounts: Map<string, number>,
1140
+ summary: RunSummary,
1141
+ terminalRuns: Iterable<string> = [],
1142
+ seenEventIds: Map<string, Set<string>> = new Map(),
1143
+ ): void {
1144
+ const activeRuns = new Set(summary.runs.map((run) => runObservationKey(run)));
1145
+ const terminalRunSet = new Set(terminalRuns);
1146
+ const activeLineKeys = new Set(summary.runs.map((run) => run.stateDir ?? run.run));
1147
+ for (const run of terminalRunSet) previousStatuses.delete(run);
1148
+ for (const run of previousStatuses.keys())
1149
+ if (!activeRuns.has(run)) previousStatuses.delete(run);
1150
+ for (const key of previousLineCounts.keys())
1151
+ if (!activeLineKeys.has(key)) previousLineCounts.delete(key);
1152
+ for (const key of seenEventIds.keys())
1153
+ if (!activeLineKeys.has(key)) seenEventIds.delete(key);
1154
+ }
1155
+
1156
+ export function detectRunAttentionEvents(
1157
+ legacyLineCounts: Map<string, number>, summary: RunSummary,
1158
+ seenEventIds: Map<string, Set<string>> = new Map(), prime = false,
1159
+ ): RunAttentionEvent[] {
1160
+ const events: RunAttentionEvent[] = [];
1161
+ for (const run of summary.runs) {
1162
+ const key = run.stateDir ?? run.run;
1163
+ const read = readTraceAttentionRecords(run);
1164
+ const retained = new Set<string>();
1165
+ const seen = seenEventIds.get(key) ?? new Set<string>();
1166
+ const start = read.canonical ? 0
1167
+ : Math.min(legacyLineCounts.get(key) ?? 0, read.records.length);
1168
+ for (const [index, record] of read.records.entries()) {
1169
+ const event = parseAttentionRecord(record, run, index);
1170
+ if (!event || !shouldNotifyRunAttentionEvent(event) ||
1171
+ event.kind === "runtime.trace_compacted") continue;
1172
+ retained.add(event.id);
1173
+ if (prime || run.notificationPolicy === "silent") seen.add(event.id);
1174
+ else if (index >= start && !seen.has(event.id)) {
1175
+ events.push(event); seen.add(event.id);
1176
+ }
1177
+ }
1178
+ seenEventIds.set(key, new Set([...retained].filter((id) => seen.has(id))));
1179
+ if (read.canonical) legacyLineCounts.delete(key);
1180
+ else legacyLineCounts.set(key, read.records.length);
1181
+ }
1182
+ return events;
1183
+ }
1184
+
1185
+ export function getRunAttentionNotificationType(
1186
+ event: RunAttentionEvent,
1187
+ ): RunTransitionNotificationType {
1188
+ return event.level;
1189
+ }
1190
+
1191
+ export function shouldNotifyRunAttentionEvent(event: RunAttentionEvent): boolean {
1192
+ return event.attention === "notify" || event.attention === "followup";
1193
+ }
1194
+
1195
+ export function shouldSendRunAttentionFollowUp(event: RunAttentionEvent): boolean {
1196
+ return event.attention === "followup";
1197
+ }
1198
+
1199
+ function commonDirectory(paths: string[]): string | undefined {
1200
+ if (paths.length === 0) return undefined;
1201
+ const split = (path: string): string[] =>
1202
+ dirname(path).split("/").filter(Boolean);
1203
+ const first = split(paths[0]);
1204
+ let length = first.length;
1205
+ for (const path of paths.slice(1)) {
1206
+ const parts = split(path);
1207
+ length = Math.min(length, parts.length);
1208
+ for (let index = 0; index < length; index += 1) {
1209
+ if (first[index] !== parts[index]) {
1210
+ length = index;
1211
+ break;
1212
+ }
1213
+ }
1214
+ }
1215
+ if (length === 0) return paths[0].startsWith("/") ? "/" : undefined;
1216
+ return `${paths[0].startsWith("/") ? "/" : ""}${first.slice(0, length).join("/")}`;
1217
+ }
1218
+
1219
+ function relativeName(base: string | undefined, path: string): string {
1220
+ if (!base) return basename(path) || path;
1221
+ const name = relative(base, path);
1222
+ return name && !name.startsWith("..") ? name : basename(path) || path;
1223
+ }
1224
+
1225
+ function formatPathGroup(label: string, paths: string[]): string {
1226
+ const unique = [...new Set(paths.filter(Boolean))].slice(0, 8);
1227
+ if (unique.length === 0) return "";
1228
+ const base = commonDirectory(unique);
1229
+ const names = unique
1230
+ .map((path) => `\`${relativeName(base, path)}\``)
1231
+ .join(", ");
1232
+ return `\n${label}:\n- Base: ${base ? `\`${base}\`` : "current run"}\n- Files: ${names}`;
1233
+ }
1234
+
1235
+ function formatRunFileList(files: unknown): string {
1236
+ if (!Array.isArray(files)) return "";
1237
+ return formatPathGroup(
1238
+ "Run files",
1239
+ files.filter((file): file is string => typeof file === "string"),
1240
+ );
1241
+ }
1242
+
1243
+ function formatNamedArtifacts(artifacts: unknown): string {
1244
+ if (!artifacts || typeof artifacts !== "object" || Array.isArray(artifacts))
1245
+ return "";
1246
+ return formatPathGroup(
1247
+ "Artifacts",
1248
+ Object.values(artifacts as Record<string, unknown>).filter(
1249
+ (path): path is string => typeof path === "string",
1250
+ ),
1251
+ );
1252
+ }
1253
+
1254
+ function getAttentionDataField(event: RunAttentionEvent, key: string): unknown {
1255
+ return event.data &&
1256
+ typeof event.data === "object" &&
1257
+ !Array.isArray(event.data)
1258
+ ? (event.data as Record<string, unknown>)[key]
1259
+ : undefined;
1260
+ }
1261
+
1262
+ function formatBodyPreview(body: unknown): string {
1263
+ if (body === undefined) return "";
1264
+ const rendered = typeof body === "string" ? body : JSON.stringify(body);
1265
+ const compact = rendered.replaceAll(/\s+/g, " ").trim();
1266
+ if (!compact) return "";
1267
+ return `\nBody: ${compact.length > 500 ? `${compact.slice(0, 500)}…` : compact}`;
1268
+ }
1269
+
1270
+ export function formatRunAttentionMessage(event: RunAttentionEvent): string {
1271
+ if (event.kind === "command.done")
1272
+ return `Run ${event.run}: ${event.summary}`;
1273
+ return `Run ${event.run}: ${event.summary}${formatBodyPreview(event.body)}${formatNamedArtifacts(getAttentionDataField(event, "artifacts"))}${formatRunFileList(getAttentionDataField(event, "run_files"))}`;
1274
+ }
1275
+
1276
+ export function getRunTransitionNotificationType(
1277
+ transition: RunTransition,
1278
+ ): RunTransitionNotificationType {
1279
+ if (transition.to === "done" || transition.to === "cancelled") return "info";
1280
+ if (transition.to === "killed" || transition.to === "exited")
1281
+ return "warning";
1282
+ return "error";
1283
+ }
1284
+
1285
+ export function shouldNotifyRunTransition(transition: RunTransition): boolean {
1286
+ if (transition.terminalHandled) return false;
1287
+ return (
1288
+ transition.to === "done" ||
1289
+ transition.to === "failed" ||
1290
+ transition.to === "killed" ||
1291
+ transition.to === "exited"
1292
+ );
1293
+ }
1294
+
1295
+ export function shouldSendRunTransitionFollowUp(
1296
+ transition: RunTransition,
1297
+ ): boolean {
1298
+ return shouldNotifyRunTransition(transition);
1299
+ }
1300
+
1301
+ const TERMINAL_FOLLOW_UP_ARTIFACT_LIMIT = 4;
1302
+ const TERMINAL_FOLLOW_UP_IDENTIFIER_CHARS = 120;
1303
+ const TERMINAL_FOLLOW_UP_PATH_CHARS = 320;
1304
+
1305
+ function compactTerminalText(value: string, limit: number): string {
1306
+ const compact = value.replaceAll(/\s+/g, " ").trim();
1307
+ return compact.length > limit ? `${compact.slice(0, limit - 1)}…` : compact;
1308
+ }
1309
+
1310
+ function formatTerminalPath(path: string): string {
1311
+ return `\`${compactTerminalText(path, TERMINAL_FOLLOW_UP_PATH_CHARS)}\``;
1312
+ }
1313
+
1314
+ function formatTerminalResultLocations(transition: RunTransition): string {
1315
+ const artifactPaths = [...new Set(
1316
+ Object.values(transition.artifacts ?? {}).filter(
1317
+ (path): path is string => typeof path === "string" && path.length > 0,
1318
+ ),
1319
+ )];
1320
+ if (artifactPaths.length === 0)
1321
+ return transition.stateDir ? `\nBase: ${formatTerminalPath(transition.stateDir)}` : "";
1322
+ const base = commonDirectory(artifactPaths);
1323
+ const artifactPreview = artifactPaths
1324
+ .slice(0, TERMINAL_FOLLOW_UP_ARTIFACT_LIMIT)
1325
+ .map((path) => formatTerminalPath(base ? relativeName(base, path) : path));
1326
+ const omitted = artifactPaths.length - artifactPreview.length;
1327
+ const artifacts = `${artifactPreview.join(", ")}${omitted > 0 ? ` (+${omitted} more)` : ""}`;
1328
+ return `${base ? `\nBase: ${formatTerminalPath(base)}` : ""}\nArtifacts: ${artifacts}`;
1329
+ }
1330
+
1331
+ export function formatRunTransitionMessage(transition: RunTransition): string {
1332
+ const run = compactTerminalText(
1333
+ transition.run,
1334
+ TERMINAL_FOLLOW_UP_IDENTIFIER_CHARS,
1335
+ );
1336
+ return `Run: \`${run}\`\nStatus: \`${transition.to}\`${formatTerminalResultLocations(transition)}`;
1337
+ }