@pasko70/pibo 1.0.5 → 1.2.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 (429) hide show
  1. package/README.md +106 -250
  2. package/context/codex-base-prompt.md +4 -0
  3. package/context/compute-worker.md +23 -0
  4. package/context/pibo-native-tooling.md +18 -0
  5. package/context/pibo-system-prompt.md +69 -8
  6. package/dist/api/simple-agent-api.js +136 -0
  7. package/dist/app-context.js +4 -0
  8. package/dist/apps/chat/agent-profiles.js +42 -5
  9. package/dist/apps/chat/agent-store.js +113 -16
  10. package/dist/apps/chat/chat-api-routes.js +311 -0
  11. package/dist/apps/chat/chat-capability-routes.js +90 -0
  12. package/dist/apps/chat/chat-files.js +178 -0
  13. package/dist/apps/chat/chat-request-normalizers.js +681 -0
  14. package/dist/apps/chat/chat-settings-routes.js +75 -0
  15. package/dist/apps/chat/chat-trace-helpers.js +94 -0
  16. package/dist/apps/chat/chat-user-skill-routes.js +149 -0
  17. package/dist/apps/chat/cron-api.js +213 -0
  18. package/dist/apps/chat/data/chat-data-mappers.js +74 -0
  19. package/dist/apps/chat/data/event-command-service.js +75 -0
  20. package/dist/apps/chat/data/navigation-query-service.js +11 -0
  21. package/dist/apps/chat/data/project-service.js +844 -0
  22. package/dist/apps/chat/data/read-state-service.js +42 -0
  23. package/dist/apps/chat/data/room-service.js +52 -0
  24. package/dist/apps/chat/data/session-query-service.js +63 -0
  25. package/dist/apps/chat/data/timeline-query-service.js +96 -0
  26. package/dist/apps/chat/event-log.js +1 -307
  27. package/dist/apps/chat/model-catalog.js +47 -0
  28. package/dist/apps/chat/output-compactor.js +126 -0
  29. package/dist/apps/chat/output-event-policy.js +17 -0
  30. package/dist/apps/chat/project-workflow-human-actions.js +347 -0
  31. package/dist/apps/chat/project-workflow-sessions.js +260 -0
  32. package/dist/apps/chat/provider-auth-actions.js +43 -0
  33. package/dist/apps/chat/ralph-api.js +156 -0
  34. package/dist/apps/chat/read-model.js +1 -218
  35. package/dist/apps/chat/rooms.js +1 -321
  36. package/dist/apps/chat/static-assets.js +996 -0
  37. package/dist/apps/chat/stream.js +29 -6
  38. package/dist/apps/chat/trace.js +179 -1003
  39. package/dist/apps/chat/types/event-store.js +1 -0
  40. package/dist/apps/chat/types/read-model.js +1 -0
  41. package/dist/apps/chat/types/rooms.js +36 -0
  42. package/dist/apps/chat/web-app.js +3168 -1811
  43. package/dist/apps/chat/workflow-catalog.js +572 -0
  44. package/dist/apps/chat/workflow-edge-compatibility.js +51 -0
  45. package/dist/apps/chat/workflow-json-schema-validation.js +335 -0
  46. package/dist/apps/chat/workflow-persistence-model.js +140 -0
  47. package/dist/apps/chat/workflow-persistence.js +633 -0
  48. package/dist/apps/chat/workflow-registered-ref-params.js +130 -0
  49. package/dist/apps/chat/workflow-registered-ref-pickers.js +179 -0
  50. package/dist/apps/chat/workflow-registered-ref-validation.js +210 -0
  51. package/dist/apps/chat/workflow-v2-security-validation.js +93 -0
  52. package/dist/apps/chat/workflow-validation-helpers.js +114 -0
  53. package/dist/apps/chat-ui/assets/{dist-CI0Xj2Cp.js → dist-B4lw9z4F.js} +1 -1
  54. package/dist/apps/chat-ui/assets/{dist-aMr2VYOu.js → dist-BbTaHWON.js} +1 -1
  55. package/dist/apps/chat-ui/assets/{dist-u2OzzOTm.js → dist-BcT_c1EJ.js} +1 -1
  56. package/dist/apps/chat-ui/assets/{dist-Di1ScJ22.js → dist-CGINd7XU.js} +1 -1
  57. package/dist/apps/chat-ui/assets/{dist-wiRpAHIv.js → dist-CrBzZkUp.js} +1 -1
  58. package/dist/apps/chat-ui/assets/{dist-CaNOvqMY.js → dist-CyyISotB.js} +1 -1
  59. package/dist/apps/chat-ui/assets/{dist-zgYUl2B-.js → dist-DFbnFNpX.js} +1 -1
  60. package/dist/apps/chat-ui/assets/{dist-CNlhGq5i.js → dist-DGLWQLX8.js} +1 -1
  61. package/dist/apps/chat-ui/assets/{dist-BGxHKHPX.js → dist-DfcIkFSN.js} +1 -1
  62. package/dist/apps/chat-ui/assets/{dist-DrM-H3e1.js → dist-sKDHTwaT.js} +1 -1
  63. package/dist/apps/chat-ui/assets/{dist-DpmEro5R.js → dist-y9D6la48.js} +1 -1
  64. package/dist/apps/chat-ui/assets/index-C25VYnyb.css +1 -0
  65. package/dist/apps/chat-ui/assets/index-CUkuvI3v.js +165 -0
  66. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-144x144.png +0 -0
  67. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-192x192.png +0 -0
  68. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-48x48.png +0 -0
  69. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-512x512.png +0 -0
  70. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-72x72.png +0 -0
  71. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-96x96.png +0 -0
  72. package/dist/apps/chat-ui/assets/pwa-images/ios/100.png +0 -0
  73. package/dist/apps/chat-ui/assets/pwa-images/ios/1024.png +0 -0
  74. package/dist/apps/chat-ui/assets/pwa-images/ios/114.png +0 -0
  75. package/dist/apps/chat-ui/assets/pwa-images/ios/120.png +0 -0
  76. package/dist/apps/chat-ui/assets/pwa-images/ios/128.png +0 -0
  77. package/dist/apps/chat-ui/assets/pwa-images/ios/144.png +0 -0
  78. package/dist/apps/chat-ui/assets/pwa-images/ios/152.png +0 -0
  79. package/dist/apps/chat-ui/assets/pwa-images/ios/16.png +0 -0
  80. package/dist/apps/chat-ui/assets/pwa-images/ios/167.png +0 -0
  81. package/dist/apps/chat-ui/assets/pwa-images/ios/180.png +0 -0
  82. package/dist/apps/chat-ui/assets/pwa-images/ios/192.png +0 -0
  83. package/dist/apps/chat-ui/assets/pwa-images/ios/20.png +0 -0
  84. package/dist/apps/chat-ui/assets/pwa-images/ios/256.png +0 -0
  85. package/dist/apps/chat-ui/assets/pwa-images/ios/29.png +0 -0
  86. package/dist/apps/chat-ui/assets/pwa-images/ios/32.png +0 -0
  87. package/dist/apps/chat-ui/assets/pwa-images/ios/40.png +0 -0
  88. package/dist/apps/chat-ui/assets/pwa-images/ios/50.png +0 -0
  89. package/dist/apps/chat-ui/assets/pwa-images/ios/512.png +0 -0
  90. package/dist/apps/chat-ui/assets/pwa-images/ios/57.png +0 -0
  91. package/dist/apps/chat-ui/assets/pwa-images/ios/58.png +0 -0
  92. package/dist/apps/chat-ui/assets/pwa-images/ios/60.png +0 -0
  93. package/dist/apps/chat-ui/assets/pwa-images/ios/64.png +0 -0
  94. package/dist/apps/chat-ui/assets/pwa-images/ios/72.png +0 -0
  95. package/dist/apps/chat-ui/assets/pwa-images/ios/76.png +0 -0
  96. package/dist/apps/chat-ui/assets/pwa-images/ios/80.png +0 -0
  97. package/dist/apps/chat-ui/assets/pwa-images/ios/87.png +0 -0
  98. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-100.png +0 -0
  99. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-125.png +0 -0
  100. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-150.png +0 -0
  101. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-200.png +0 -0
  102. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-400.png +0 -0
  103. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-100.png +0 -0
  104. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-125.png +0 -0
  105. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-150.png +0 -0
  106. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-200.png +0 -0
  107. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-400.png +0 -0
  108. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-100.png +0 -0
  109. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-125.png +0 -0
  110. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-150.png +0 -0
  111. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-200.png +0 -0
  112. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-400.png +0 -0
  113. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-100.png +0 -0
  114. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-125.png +0 -0
  115. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-150.png +0 -0
  116. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-200.png +0 -0
  117. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-400.png +0 -0
  118. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-16.png +0 -0
  119. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-20.png +0 -0
  120. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-24.png +0 -0
  121. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-256.png +0 -0
  122. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-30.png +0 -0
  123. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-32.png +0 -0
  124. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-36.png +0 -0
  125. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-40.png +0 -0
  126. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-44.png +0 -0
  127. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-48.png +0 -0
  128. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-60.png +0 -0
  129. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-64.png +0 -0
  130. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-72.png +0 -0
  131. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-80.png +0 -0
  132. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-96.png +0 -0
  133. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-16.png +0 -0
  134. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-20.png +0 -0
  135. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-24.png +0 -0
  136. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-256.png +0 -0
  137. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-30.png +0 -0
  138. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-32.png +0 -0
  139. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-36.png +0 -0
  140. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-40.png +0 -0
  141. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-44.png +0 -0
  142. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-48.png +0 -0
  143. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-60.png +0 -0
  144. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-64.png +0 -0
  145. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-72.png +0 -0
  146. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-80.png +0 -0
  147. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-96.png +0 -0
  148. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-100.png +0 -0
  149. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-125.png +0 -0
  150. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-150.png +0 -0
  151. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-200.png +0 -0
  152. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-400.png +0 -0
  153. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-16.png +0 -0
  154. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-20.png +0 -0
  155. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-24.png +0 -0
  156. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-256.png +0 -0
  157. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-30.png +0 -0
  158. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-32.png +0 -0
  159. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-36.png +0 -0
  160. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-40.png +0 -0
  161. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-44.png +0 -0
  162. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-48.png +0 -0
  163. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-60.png +0 -0
  164. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-64.png +0 -0
  165. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-72.png +0 -0
  166. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-80.png +0 -0
  167. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-96.png +0 -0
  168. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-100.png +0 -0
  169. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-125.png +0 -0
  170. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-150.png +0 -0
  171. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-200.png +0 -0
  172. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-400.png +0 -0
  173. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-100.png +0 -0
  174. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-125.png +0 -0
  175. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-150.png +0 -0
  176. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-200.png +0 -0
  177. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-400.png +0 -0
  178. package/dist/apps/chat-ui/index.html +8 -3
  179. package/dist/apps/chat-ui/manifest.webmanifest +25 -0
  180. package/dist/apps/chat-ui/sw.js +41 -0
  181. package/dist/apps/cli-ui/InkSessionApp.js +1218 -0
  182. package/dist/apps/cli-ui/InkTerminalLine.js +53 -0
  183. package/dist/apps/cli-ui/InkTerminalRow.js +304 -0
  184. package/dist/apps/cli-ui/InkTerminalView.js +25 -0
  185. package/dist/apps/cli-ui/cliSessionsCommand.js +232 -0
  186. package/dist/apps/cli-ui/index.js +8 -0
  187. package/dist/apps/cli-ui/inkColors.js +67 -0
  188. package/dist/apps/cli-ui/inkJson.js +244 -0
  189. package/dist/apps/cli-ui/inkMarkdown.js +122 -0
  190. package/dist/apps/context-files-ui/assets/{dist-DFi2YGux.js → dist-BOiGdrG-.js} +1 -1
  191. package/dist/apps/context-files-ui/assets/{dist-DyfSeBMu.js → dist-DK01b7x4.js} +1 -1
  192. package/dist/apps/context-files-ui/assets/{dist-CwbH_3RN.js → dist-DPG9jOQ-.js} +1 -1
  193. package/dist/apps/context-files-ui/assets/{dist-dTBsFYAl.js → dist-Dp5AH00p.js} +1 -1
  194. package/dist/apps/context-files-ui/assets/{dist-CxRLRmMx.js → dist-DqYw0LH7.js} +1 -1
  195. package/dist/apps/context-files-ui/assets/{dist-MyZgX9K2.js → dist-TF5iO5ML.js} +1 -1
  196. package/dist/apps/context-files-ui/assets/{dist-DQXzt2Ng.js → dist-TbjAhles.js} +1 -1
  197. package/dist/apps/context-files-ui/assets/{dist-YwR9dpb-.js → dist-ZsBbt0uY.js} +1 -1
  198. package/dist/apps/context-files-ui/assets/{dist-CKQF1zEu.js → dist-kmsvtHkH.js} +1 -1
  199. package/dist/apps/context-files-ui/assets/{dist-BJW3917N.js → dist-vnd7PMu3.js} +1 -1
  200. package/dist/apps/context-files-ui/assets/{index-BwRDoHMC.css → index-B92tL3Pp.css} +1 -1
  201. package/dist/apps/context-files-ui/assets/{index-GwvjXytt.js → index-BhAWD3dv.js} +2 -2
  202. package/dist/apps/context-files-ui/index.html +2 -2
  203. package/dist/auth/better-auth.js +2 -1
  204. package/dist/auth/login-actions.js +251 -0
  205. package/dist/auth/openai-codex-usage.js +147 -0
  206. package/dist/bin/pibo.js +0 -0
  207. package/dist/bin/rg.js +15 -0
  208. package/dist/cli-session/fakeSessionSource.js +804 -0
  209. package/dist/cli-session/index.js +3 -0
  210. package/dist/cli-session/localSessionSource.js +1144 -0
  211. package/dist/cli-session/sessionSource.js +13 -0
  212. package/dist/cli.js +142 -14
  213. package/dist/compute/cli.js +415 -0
  214. package/dist/compute/docker.js +827 -0
  215. package/dist/compute/resource-health.js +333 -0
  216. package/dist/compute/resource-policy.js +98 -0
  217. package/dist/config/config.js +9 -5
  218. package/dist/core/context-build.js +677 -0
  219. package/dist/core/model-defaults.js +51 -9
  220. package/dist/core/pibo-home.js +8 -0
  221. package/dist/core/profiles.js +48 -0
  222. package/dist/core/provider-telemetry.js +222 -0
  223. package/dist/core/routed-session.js +441 -47
  224. package/dist/core/runtime-telemetry.js +853 -0
  225. package/dist/core/runtime.js +103 -15
  226. package/dist/core/session-errors.js +47 -0
  227. package/dist/core/session-model.js +39 -0
  228. package/dist/core/session-router.js +292 -62
  229. package/dist/core/shared-app.js +17 -0
  230. package/dist/core/skill-expansion.js +43 -0
  231. package/dist/core/system-prompt-template.js +9 -9
  232. package/dist/core/telemetry-staleness.js +128 -0
  233. package/dist/core/test-output-compaction.js +145 -0
  234. package/dist/core/user-settings.js +73 -0
  235. package/dist/cron/channel.js +28 -0
  236. package/dist/cron/cli.js +230 -0
  237. package/dist/cron/plugin.js +11 -0
  238. package/dist/cron/schedule.js +214 -0
  239. package/dist/cron/service.js +177 -0
  240. package/dist/cron/store.js +349 -0
  241. package/dist/cron/types.js +1 -0
  242. package/dist/data/cli.js +184 -0
  243. package/dist/data/event-log.js +106 -0
  244. package/dist/data/final-app-space-cutover-migration.js +728 -0
  245. package/dist/data/ingest-service.js +389 -0
  246. package/dist/data/message-store.js +62 -0
  247. package/dist/data/navigation-store.js +75 -0
  248. package/dist/data/observation-store.js +46 -0
  249. package/dist/data/payload-store.js +144 -0
  250. package/dist/data/pibo-store.js +59 -0
  251. package/dist/data/schema.js +434 -0
  252. package/dist/data/session-store.js +63 -0
  253. package/dist/data/shared-app-migration.js +757 -0
  254. package/dist/data/sqlite-schema.js +12 -0
  255. package/dist/data/telemetry-preview.js +65 -0
  256. package/dist/data/telemetry-queries.js +212 -0
  257. package/dist/data/telemetry-retention.js +50 -0
  258. package/dist/data/telemetry-rows.js +158 -0
  259. package/dist/data/telemetry.js +357 -0
  260. package/dist/debug/delta-compaction.js +99 -0
  261. package/dist/debug/detail-format.js +86 -0
  262. package/dist/debug/events.js +149 -29
  263. package/dist/debug/failures.js +162 -0
  264. package/dist/debug/index.js +655 -30
  265. package/dist/debug/messages.js +185 -0
  266. package/dist/debug/next-commands.js +6 -0
  267. package/dist/debug/payloads.js +123 -0
  268. package/dist/debug/pty.js +924 -0
  269. package/dist/debug/session.js +45 -15
  270. package/dist/debug/sql.js +1 -1
  271. package/dist/debug/stores.js +18 -13
  272. package/dist/debug/summary.js +72 -0
  273. package/dist/debug/telemetry.js +649 -0
  274. package/dist/debug/tools.js +168 -0
  275. package/dist/debug/trace-render-check.js +151 -0
  276. package/dist/debug/trace.js +152 -27
  277. package/dist/debug/web-artifacts.js +63 -0
  278. package/dist/debug/web-options.js +313 -0
  279. package/dist/debug/web-render-analysis.js +310 -0
  280. package/dist/debug/web-snapshot-browser-scripts.js +303 -0
  281. package/dist/debug/web-streaming-benchmark-analysis.js +605 -0
  282. package/dist/debug/web-streaming-browser-library.js +928 -0
  283. package/dist/debug/web-streaming-browser-scripts.js +242 -0
  284. package/dist/debug/web-streaming-provider-telemetry.js +194 -0
  285. package/dist/debug/web-streaming-report.js +493 -0
  286. package/dist/debug/web-streaming-types.js +1 -0
  287. package/dist/debug/web.js +574 -0
  288. package/dist/gateway/backup.js +83 -0
  289. package/dist/gateway/cli.js +511 -0
  290. package/dist/gateway/fallback.js +155 -0
  291. package/dist/gateway/pidfile.js +84 -0
  292. package/dist/gateway/protocol.js +16 -0
  293. package/dist/gateway/server.js +174 -17
  294. package/dist/gateway/tool.js +54 -51
  295. package/dist/gateway/web.js +74 -2
  296. package/dist/index.js +3 -1
  297. package/dist/local/client.js +3 -3
  298. package/dist/local/extension.js +8 -5
  299. package/dist/plugins/builtin.js +252 -49
  300. package/dist/plugins/chat-vscode-web.js +28 -0
  301. package/dist/plugins/codex-compat.js +0 -41
  302. package/dist/plugins/context-files.js +98 -18
  303. package/dist/plugins/dev-auth.js +124 -0
  304. package/dist/plugins/native-tooling.js +15 -0
  305. package/dist/plugins/registry.js +66 -2
  306. package/dist/plugins/web-annotations.js +27 -0
  307. package/dist/providers/minimax.js +70 -0
  308. package/dist/providers/openai-compat.js +48 -0
  309. package/dist/ralph/channel.js +8 -0
  310. package/dist/ralph/cli.js +152 -0
  311. package/dist/ralph/plugin.js +14 -0
  312. package/dist/ralph/service.js +271 -0
  313. package/dist/ralph/stopping.js +151 -0
  314. package/dist/ralph/store.js +450 -0
  315. package/dist/ralph/templates.js +200 -0
  316. package/dist/ralph/types.js +1 -0
  317. package/dist/reliability/store.js +42 -26
  318. package/dist/runs/registry.js +72 -35
  319. package/dist/session-ui/commandCatalog.js +193 -0
  320. package/dist/session-ui/commandResults.js +95 -0
  321. package/dist/session-ui/index.js +7 -0
  322. package/dist/session-ui/ownerViewModel.js +27 -0
  323. package/dist/session-ui/roomSessionViewModel.js +69 -0
  324. package/dist/session-ui/statusViewModel.js +127 -0
  325. package/dist/session-ui/terminalCards.js +210 -0
  326. package/dist/session-ui/terminalRows.js +937 -0
  327. package/dist/session-ui/terminalValue.js +45 -0
  328. package/dist/sessions/pibo-data-store.js +178 -0
  329. package/dist/sessions/sqlite-store.js +78 -12
  330. package/dist/sessions/store.js +11 -4
  331. package/dist/sessions/workflow-session-kind.js +20 -0
  332. package/dist/setup/cli.js +567 -0
  333. package/dist/shared/trace-async-agent-runs.js +127 -0
  334. package/dist/shared/trace-engine.js +96 -0
  335. package/dist/shared/trace-event-projection.js +679 -0
  336. package/dist/shared/trace-live-reducer.js +191 -0
  337. package/dist/shared/trace-nodes.js +76 -0
  338. package/dist/shared/trace-order.js +11 -10
  339. package/dist/shared/trace-patch-nodes.js +83 -0
  340. package/dist/shared/trace-run-notifications.js +69 -0
  341. package/dist/shared/trace-subagent-links.js +46 -0
  342. package/dist/shared/trace-transcript.js +303 -0
  343. package/dist/shared/trace-types.js +1 -0
  344. package/dist/shared-app.js +4 -0
  345. package/dist/signals/aggregate.js +65 -0
  346. package/dist/signals/events.js +1 -0
  347. package/dist/signals/projector.js +158 -0
  348. package/dist/signals/registry.js +513 -0
  349. package/dist/signals/store.js +1 -0
  350. package/dist/signals/types.js +1 -0
  351. package/dist/skills/cli.js +117 -0
  352. package/dist/tools/agent-browser-leases.js +219 -0
  353. package/dist/tools/agent-browser-wrapper.js +99 -0
  354. package/dist/tools/browser-pool.js +623 -0
  355. package/dist/tools/browser-use-cdp.js +56 -4
  356. package/dist/tools/browser-use-leases.js +215 -37
  357. package/dist/tools/browser-use-wrapper.js +508 -65
  358. package/dist/tools/cdp-client.js +189 -0
  359. package/dist/tools/guides.js +203 -4
  360. package/dist/tools/index.js +666 -16
  361. package/dist/tools/npm-runtime.js +136 -0
  362. package/dist/tools/registry.js +107 -8
  363. package/dist/tools/runtime/index.js +3 -0
  364. package/dist/tools/runtime/node-backend.js +225 -0
  365. package/dist/tools/runtime/node-worker-source.js +206 -0
  366. package/dist/tools/runtime/python-backend.js +227 -0
  367. package/dist/tools/runtime/python-worker-source.js +178 -0
  368. package/dist/tools/runtime/registry.js +255 -0
  369. package/dist/tools/runtime/tool.js +168 -0
  370. package/dist/tools/runtime/types.js +1 -0
  371. package/dist/tools/web-search.js +2 -1
  372. package/dist/user-skills/installer.js +214 -0
  373. package/dist/user-skills/manager.js +35 -0
  374. package/dist/user-skills/store.js +267 -0
  375. package/dist/user-skills/types.js +1 -0
  376. package/dist/web/auth.js +5 -1
  377. package/dist/web/channel.js +86 -0
  378. package/dist/web/http.js +79 -14
  379. package/dist/web-annotations/api.js +348 -0
  380. package/dist/web-annotations/attachments.js +201 -0
  381. package/dist/web-annotations/cdp.js +1107 -0
  382. package/dist/web-annotations/index.js +7 -0
  383. package/dist/web-annotations/store.js +407 -0
  384. package/dist/web-annotations/tools.js +350 -0
  385. package/dist/web-annotations/types.js +34 -0
  386. package/dist/web-annotations/validation.js +288 -0
  387. package/docs/README.md +23 -0
  388. package/docs/ops/install-developer-host.md +112 -0
  389. package/docs/ops/install-user-host.md +76 -0
  390. package/docs/ops/upgrade-user-to-developer-host.md +69 -0
  391. package/package.json +24 -10
  392. package/{.codex/skills → skills/builtin}/pi-agent-harness/SKILL.md +24 -24
  393. package/skills/builtin/pibo-docker-system/SKILL.md +170 -0
  394. package/skills/builtin/pibo-spec-writing/SKILL.md +330 -0
  395. package/skills/builtin/prd/SKILL.md +143 -0
  396. package/skills/builtin/ralph-loop/SKILL.md +359 -0
  397. package/skills/builtin/ralph-prd-json/SKILL.md +123 -0
  398. package/skills/builtin/skill-creator/LICENSE.txt +202 -0
  399. package/skills/builtin/skill-creator/SKILL.md +513 -0
  400. package/skills/builtin/skill-creator/agents/analyzer.md +274 -0
  401. package/skills/builtin/skill-creator/agents/comparator.md +202 -0
  402. package/skills/builtin/skill-creator/agents/grader.md +223 -0
  403. package/skills/builtin/skill-creator/assets/eval_review.html +146 -0
  404. package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -0
  405. package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -0
  406. package/skills/builtin/skill-creator/references/schemas.md +430 -0
  407. package/skills/builtin/skill-creator/scripts/__init__.py +0 -0
  408. package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -0
  409. package/skills/builtin/skill-creator/scripts/generate_report.py +326 -0
  410. package/skills/builtin/skill-creator/scripts/improve_description.py +247 -0
  411. package/skills/builtin/skill-creator/scripts/package_skill.py +136 -0
  412. package/skills/builtin/skill-creator/scripts/quick_validate.py +103 -0
  413. package/skills/builtin/skill-creator/scripts/run_eval.py +310 -0
  414. package/skills/builtin/skill-creator/scripts/run_loop.py +328 -0
  415. package/skills/builtin/skill-creator/scripts/utils.py +47 -0
  416. package/skills/builtin/web-annotations/SKILL.md +93 -0
  417. package/dist/apps/chat-ui/assets/index-B_E935fP.js +0 -151
  418. package/dist/apps/chat-ui/assets/index-Dk-opWl3.css +0 -1
  419. package/dist/env.js +0 -32
  420. package/dist/plugins/core-tools.js +0 -94
  421. package/dist/plugins/example.js +0 -67
  422. package/dist/plugins/remote-agent.js +0 -9
  423. package/dist/remote/channel.js +0 -176
  424. package/dist/remote/client.js +0 -92
  425. package/dist/remote/examples/tui-controller.js +0 -263
  426. package/dist/remote/protocol.js +0 -55
  427. package/dist/remote/session-client.js +0 -189
  428. package/dist/sessions/bindings.js +0 -41
  429. /package/{.codex/skills → skills/builtin}/pi-agent-harness/agents/openai.yaml +0 -0
@@ -1,6 +1,8 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { mkdirSync } from "node:fs";
3
3
  import { dirname, resolve } from "node:path";
4
+ import { piboHomePath } from "../core/pibo-home.js";
5
+ import { sqliteTableColumns } from "../data/sqlite-schema.js";
4
6
  import { DatabaseSync } from "node:sqlite";
5
7
  function now() {
6
8
  return new Date().toISOString();
@@ -17,9 +19,24 @@ function parseJson(value) {
17
19
  function asDate(value) {
18
20
  return value ?? new Date();
19
21
  }
22
+ function migratePiboRunControllerColumn(db) {
23
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'pibo_runs'").get();
24
+ if (!table)
25
+ return;
26
+ const legacyColumn = ["o", "wner_pibo_session_id"].join("");
27
+ const columns = sqliteTableColumns(db, "pibo_runs");
28
+ if (!columns.has(legacyColumn) || columns.has("controller_pibo_session_id"))
29
+ return;
30
+ db.exec("DROP INDEX IF EXISTS idx_pibo_runs_" + ["o", "wner_updated"].join(""));
31
+ db.exec(`ALTER TABLE pibo_runs RENAME COLUMN ${legacyColumn} TO controller_pibo_session_id`);
32
+ }
20
33
  export class PiboReliabilityStore {
21
34
  db;
22
- constructor(path = resolve(process.cwd(), ".pibo/pibo-events.sqlite")) {
35
+ appendEventStatement;
36
+ getEventByStreamIdStatement;
37
+ getEventByTopicEventIdStatement;
38
+ getEventByTopicIdempotencyKeyStatement;
39
+ constructor(path = piboHomePath("pibo-events.sqlite")) {
23
40
  const resolvedPath = path === ":memory:" ? path : resolve(path);
24
41
  if (resolvedPath !== ":memory:")
25
42
  mkdirSync(dirname(resolvedPath), { recursive: true });
@@ -28,6 +45,7 @@ export class PiboReliabilityStore {
28
45
  this.db.exec("PRAGMA foreign_keys = ON");
29
46
  if (resolvedPath !== ":memory:")
30
47
  this.db.exec("PRAGMA journal_mode = WAL");
48
+ migratePiboRunControllerColumn(this.db);
31
49
  this.db.exec(`
32
50
  CREATE TABLE IF NOT EXISTS pibo_event_stream (
33
51
  stream_id INTEGER PRIMARY KEY,
@@ -102,7 +120,7 @@ export class PiboReliabilityStore {
102
120
  CREATE TABLE IF NOT EXISTS pibo_runs (
103
121
  run_id TEXT PRIMARY KEY,
104
122
  kind TEXT NOT NULL,
105
- owner_pibo_session_id TEXT NOT NULL,
123
+ controller_pibo_session_id TEXT NOT NULL,
106
124
  status TEXT NOT NULL,
107
125
  completion_policy TEXT NOT NULL,
108
126
  consumed INTEGER NOT NULL DEFAULT 0,
@@ -119,21 +137,23 @@ export class PiboReliabilityStore {
119
137
  retryable INTEGER NOT NULL DEFAULT 0,
120
138
  max_attempts INTEGER NOT NULL DEFAULT 1
121
139
  );
122
- CREATE INDEX IF NOT EXISTS idx_pibo_runs_owner_updated
123
- ON pibo_runs(owner_pibo_session_id, updated_at);
140
+ CREATE INDEX IF NOT EXISTS idx_pibo_runs_controller_updated
141
+ ON pibo_runs(controller_pibo_session_id, updated_at);
124
142
  CREATE INDEX IF NOT EXISTS idx_pibo_runs_status
125
143
  ON pibo_runs(status);
126
144
  `);
145
+ this.appendEventStatement = this.db.prepare(`
146
+ INSERT INTO pibo_event_stream (topic, key, event_id, idempotency_key, created_at, retention_class, payload_json)
147
+ VALUES (?, ?, ?, ?, ?, ?, ?)
148
+ `);
149
+ this.getEventByStreamIdStatement = this.db.prepare("SELECT * FROM pibo_event_stream WHERE stream_id = ?");
150
+ this.getEventByTopicEventIdStatement = this.db.prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND event_id = ?");
151
+ this.getEventByTopicIdempotencyKeyStatement = this.db.prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND idempotency_key = ?");
127
152
  }
128
153
  append(input) {
129
154
  const eventId = input.eventId ?? `evt_${randomUUID()}`;
130
155
  const createdAt = input.createdAt ?? now();
131
- const result = this.db
132
- .prepare(`
133
- INSERT INTO pibo_event_stream (topic, key, event_id, idempotency_key, created_at, retention_class, payload_json)
134
- VALUES (?, ?, ?, ?, ?, ?, ?)
135
- `)
136
- .run(input.topic, input.key ?? null, eventId, input.idempotencyKey ?? null, createdAt, input.retentionClass ?? "audit_event", json(input.payload));
156
+ const result = this.appendEventStatement.run(input.topic, input.key ?? null, eventId, input.idempotencyKey ?? null, createdAt, input.retentionClass ?? "audit_event", json(input.payload));
137
157
  return this.getEventByStreamId(Number(result.lastInsertRowid));
138
158
  }
139
159
  appendOnce(input) {
@@ -450,7 +470,7 @@ export class PiboReliabilityStore {
450
470
  queue: "runs",
451
471
  payload: {
452
472
  runId,
453
- ownerPiboSessionId: input.ownerPiboSessionId,
473
+ controllerPiboSessionId: input.controllerPiboSessionId,
454
474
  toolName: input.toolName,
455
475
  params: input.params,
456
476
  },
@@ -459,12 +479,12 @@ export class PiboReliabilityStore {
459
479
  this.db
460
480
  .prepare(`
461
481
  INSERT INTO pibo_runs (
462
- run_id, kind, owner_pibo_session_id, status, completion_policy, consumed, tool_name,
482
+ run_id, kind, controller_pibo_session_id, status, completion_policy, consumed, tool_name,
463
483
  summary, result_json, error, notified_status, acknowledged_status, created_at, updated_at,
464
484
  completed_at, job_id, retryable, max_attempts
465
485
  ) VALUES (?, 'tool', ?, 'running', ?, 0, ?, ?, NULL, NULL, NULL, NULL, ?, ?, NULL, ?, ?, ?)
466
486
  `)
467
- .run(runId, input.ownerPiboSessionId, input.completionPolicy, input.toolName, `${input.toolName} run is running.`, timestamp, timestamp, job.jobId, input.retryable ? 1 : 0, maxAttempts);
487
+ .run(runId, input.controllerPiboSessionId, input.completionPolicy, input.toolName, `${input.toolName} run is running.`, timestamp, timestamp, job.jobId, input.retryable ? 1 : 0, maxAttempts);
468
488
  this.claimJob(job.jobId, `run-registry:${process.pid}`, 24 * 60 * 60 * 1000);
469
489
  return this.requireRun(runId);
470
490
  }
@@ -501,9 +521,9 @@ export class PiboReliabilityStore {
501
521
  listRuns(input = {}) {
502
522
  const clauses = [];
503
523
  const values = [];
504
- if (input.ownerPiboSessionId) {
505
- clauses.push("owner_pibo_session_id = ?");
506
- values.push(input.ownerPiboSessionId);
524
+ if (input.controllerPiboSessionId) {
525
+ clauses.push("controller_pibo_session_id = ?");
526
+ values.push(input.controllerPiboSessionId);
507
527
  }
508
528
  if (!input.includeConsumed)
509
529
  clauses.push("consumed = 0");
@@ -566,21 +586,17 @@ export class PiboReliabilityStore {
566
586
  this.db.close();
567
587
  }
568
588
  getEventByStreamId(streamId) {
569
- const row = this.db.prepare("SELECT * FROM pibo_event_stream WHERE stream_id = ?").get(streamId);
589
+ const row = this.getEventByStreamIdStatement.get(streamId);
570
590
  if (!row)
571
591
  throw new Error(`Unknown pibo event stream id "${streamId}"`);
572
592
  return eventFromRow(row);
573
593
  }
574
594
  getEventByTopicEventId(topic, eventId) {
575
- const row = this.db
576
- .prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND event_id = ?")
577
- .get(topic, eventId);
595
+ const row = this.getEventByTopicEventIdStatement.get(topic, eventId);
578
596
  return row ? eventFromRow(row) : undefined;
579
597
  }
580
598
  getEventByTopicIdempotencyKey(topic, idempotencyKey) {
581
- const row = this.db
582
- .prepare("SELECT * FROM pibo_event_stream WHERE topic = ? AND idempotency_key = ?")
583
- .get(topic, idempotencyKey);
599
+ const row = this.getEventByTopicIdempotencyKeyStatement.get(topic, idempotencyKey);
584
600
  return row ? eventFromRow(row) : undefined;
585
601
  }
586
602
  getConsumerOffset(topic, consumer) {
@@ -666,8 +682,8 @@ export class PiboReliabilityStore {
666
682
  return run;
667
683
  }
668
684
  }
669
- export function createDefaultPiboReliabilityStore(cwd = process.cwd()) {
670
- return new PiboReliabilityStore(resolve(cwd, ".pibo/pibo-events.sqlite"));
685
+ export function createDefaultPiboReliabilityStore(_cwd) {
686
+ return new PiboReliabilityStore(piboHomePath("pibo-events.sqlite"));
671
687
  }
672
688
  function eventFromRow(row) {
673
689
  return {
@@ -720,7 +736,7 @@ function runFromRow(row) {
720
736
  const output = {
721
737
  runId: row.run_id,
722
738
  kind: row.kind,
723
- ownerPiboSessionId: row.owner_pibo_session_id,
739
+ controllerPiboSessionId: row.controller_pibo_session_id,
724
740
  status: row.status,
725
741
  completionPolicy: row.completion_policy,
726
742
  consumed: row.consumed === 1,
@@ -8,7 +8,7 @@ function snapshot(record) {
8
8
  const output = {
9
9
  runId: record.runId,
10
10
  kind: record.kind,
11
- ownerPiboSessionId: record.ownerPiboSessionId,
11
+ controllerPiboSessionId: record.controllerPiboSessionId,
12
12
  status: record.status,
13
13
  completionPolicy: record.completionPolicy,
14
14
  consumed: record.consumed,
@@ -29,6 +29,11 @@ export class PiboRunRegistry {
29
29
  options;
30
30
  runs = new Map();
31
31
  waiters = new Map();
32
+ listeners = new Set();
33
+ subscribe(listener) {
34
+ this.listeners.add(listener);
35
+ return () => this.listeners.delete(listener);
36
+ }
32
37
  constructor(options = {}) {
33
38
  this.options = options;
34
39
  if (this.options.store) {
@@ -42,7 +47,7 @@ export class PiboRunRegistry {
42
47
  this.prune();
43
48
  if (this.options.store) {
44
49
  const stored = this.options.store.createRun({
45
- ownerPiboSessionId: input.ownerPiboSessionId,
50
+ controllerPiboSessionId: input.controllerPiboSessionId,
46
51
  toolName: input.toolName,
47
52
  completionPolicy: input.completionPolicy ?? "tracked",
48
53
  params: input.params,
@@ -51,14 +56,16 @@ export class PiboRunRegistry {
51
56
  });
52
57
  const record = recordFromStored(stored);
53
58
  this.runs.set(record.runId, record);
54
- return snapshot(record);
59
+ const output = snapshot(record);
60
+ this.notify({ type: "run_started", run: output });
61
+ return output;
55
62
  }
56
63
  const timestamp = now();
57
64
  const runId = `run_${randomUUID()}`;
58
65
  const record = {
59
66
  runId,
60
67
  kind: "tool",
61
- ownerPiboSessionId: input.ownerPiboSessionId,
68
+ controllerPiboSessionId: input.controllerPiboSessionId,
62
69
  status: "running",
63
70
  completionPolicy: input.completionPolicy ?? "tracked",
64
71
  consumed: false,
@@ -70,12 +77,15 @@ export class PiboRunRegistry {
70
77
  maxAttempts: Math.max(1, input.maxAttempts ?? 1),
71
78
  };
72
79
  this.runs.set(runId, record);
73
- return snapshot(record);
80
+ const output = snapshot(record);
81
+ this.notify({ type: "run_started", run: output });
82
+ return output;
74
83
  }
75
84
  complete(runId, result) {
76
85
  const record = this.runs.get(runId);
77
86
  if (!record || terminal(record.status))
78
87
  return undefined;
88
+ const previousStatus = record.status;
79
89
  record.status = "completed";
80
90
  record.result = result;
81
91
  record.summary = `${record.toolName} run completed.`;
@@ -83,12 +93,15 @@ export class PiboRunRegistry {
83
93
  this.options.store?.updateRun(runId, record);
84
94
  if (record.jobId)
85
95
  this.options.store?.ack(record.jobId, `run-registry:${process.pid}`);
86
- return snapshot(record);
96
+ const output = snapshot(record);
97
+ this.notify({ type: "run_changed", run: output, previousStatus });
98
+ return output;
87
99
  }
88
100
  fail(runId, error) {
89
101
  const record = this.runs.get(runId);
90
102
  if (!record || terminal(record.status))
91
103
  return undefined;
104
+ const previousStatus = record.status;
92
105
  record.status = "failed";
93
106
  record.error = error;
94
107
  record.summary = `${record.toolName} run failed.`;
@@ -96,21 +109,30 @@ export class PiboRunRegistry {
96
109
  this.options.store?.updateRun(runId, record);
97
110
  if (record.jobId)
98
111
  this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, error);
99
- return snapshot(record);
112
+ const output = snapshot(record);
113
+ this.notify({ type: "run_changed", run: output, previousStatus, reason: error });
114
+ return output;
100
115
  }
101
- list(ownerPiboSessionId, options = {}) {
116
+ list(controllerPiboSessionId, options = {}) {
102
117
  this.prune();
103
118
  return [...this.runs.values()]
104
- .filter((record) => record.ownerPiboSessionId === ownerPiboSessionId)
119
+ .filter((record) => record.controllerPiboSessionId === controllerPiboSessionId)
105
120
  .filter((record) => options.includeConsumed || !record.consumed)
106
121
  .filter((record) => options.includeDetached || record.completionPolicy !== "detached")
107
122
  .map(snapshot);
108
123
  }
109
- status(ownerPiboSessionId, runId) {
110
- return snapshot(this.requireOwned(ownerPiboSessionId, runId));
124
+ listAll(options = {}) {
125
+ this.prune();
126
+ return [...this.runs.values()]
127
+ .filter((record) => options.includeConsumed || !record.consumed)
128
+ .filter((record) => options.includeDetached || record.completionPolicy !== "detached")
129
+ .map(snapshot);
130
+ }
131
+ status(controllerPiboSessionId, runId) {
132
+ return snapshot(this.requireRunForController(controllerPiboSessionId, runId));
111
133
  }
112
- async wait(ownerPiboSessionId, runId, timeoutMs) {
113
- const record = this.requireOwned(ownerPiboSessionId, runId);
134
+ async wait(controllerPiboSessionId, runId, timeoutMs) {
135
+ const record = this.requireRunForController(controllerPiboSessionId, runId);
114
136
  if (terminal(record.status))
115
137
  return { ...snapshot(record), timedOut: false };
116
138
  const boundedTimeoutMs = Math.max(0, Math.min(timeoutMs, 300000));
@@ -143,12 +165,13 @@ export class PiboRunRegistry {
143
165
  return { ...snapshot(record), timedOut: true };
144
166
  return { ...snapshot(completed), timedOut: false };
145
167
  }
146
- read(ownerPiboSessionId, runId) {
147
- const record = this.requireOwned(ownerPiboSessionId, runId);
168
+ read(controllerPiboSessionId, runId) {
169
+ const record = this.requireRunForController(controllerPiboSessionId, runId);
148
170
  if (terminal(record.status)) {
149
171
  record.consumed = true;
150
172
  record.updatedAt = now();
151
173
  this.options.store?.updateRun(runId, record);
174
+ this.notify({ type: "run_consumed", run: snapshot(record) });
152
175
  }
153
176
  const output = { ...snapshot(record) };
154
177
  if (record.result)
@@ -157,8 +180,9 @@ export class PiboRunRegistry {
157
180
  output.error = record.error;
158
181
  return output;
159
182
  }
160
- cancel(ownerPiboSessionId, runId) {
161
- const record = this.requireOwned(ownerPiboSessionId, runId);
183
+ cancel(controllerPiboSessionId, runId) {
184
+ const record = this.requireRunForController(controllerPiboSessionId, runId);
185
+ const previousStatus = record.status;
162
186
  if (!terminal(record.status)) {
163
187
  record.status = "cancelled";
164
188
  record.summary = `${record.toolName} run cancelled.`;
@@ -169,19 +193,23 @@ export class PiboRunRegistry {
169
193
  record.consumed = true;
170
194
  record.updatedAt = now();
171
195
  this.options.store?.updateRun(runId, record);
172
- return snapshot(record);
196
+ const output = snapshot(record);
197
+ this.notify({ type: "run_changed", run: output, previousStatus, reason: "Run was cancelled." });
198
+ return output;
173
199
  }
174
- ack(ownerPiboSessionId, runId) {
175
- const record = this.requireOwned(ownerPiboSessionId, runId);
200
+ ack(controllerPiboSessionId, runId) {
201
+ const record = this.requireRunForController(controllerPiboSessionId, runId);
176
202
  record.acknowledgedStatus = record.status;
177
203
  if (terminal(record.status))
178
204
  record.consumed = true;
179
205
  record.updatedAt = now();
180
206
  this.options.store?.updateRun(runId, record);
181
- return snapshot(record);
207
+ const output = snapshot(record);
208
+ this.notify({ type: "run_acknowledged", run: output });
209
+ return output;
182
210
  }
183
- createNotification(ownerPiboSessionId, options = {}) {
184
- const records = [...this.runs.values()].filter((record) => this.needsNotification(record, ownerPiboSessionId, options));
211
+ createNotification(controllerPiboSessionId, options = {}) {
212
+ const records = [...this.runs.values()].filter((record) => this.needsNotification(record, controllerPiboSessionId, options));
185
213
  if (records.length === 0)
186
214
  return undefined;
187
215
  for (const record of records) {
@@ -207,13 +235,13 @@ export class PiboRunRegistry {
207
235
  }
208
236
  return notification;
209
237
  }
210
- hasPendingNotification(ownerPiboSessionId, options = {}) {
211
- return [...this.runs.values()].some((record) => this.needsNotification(record, ownerPiboSessionId, options));
238
+ hasPendingNotification(controllerPiboSessionId, options = {}) {
239
+ return [...this.runs.values()].some((record) => this.needsNotification(record, controllerPiboSessionId, options));
212
240
  }
213
- cancelOwnerRuns(ownerPiboSessionId, reason = "Owner Pibo session was disposed.") {
241
+ cancelControllerRuns(controllerPiboSessionId, reason = "Controller Pibo session was disposed.") {
214
242
  const cancelled = [];
215
243
  for (const record of this.runs.values()) {
216
- if (record.ownerPiboSessionId !== ownerPiboSessionId || terminal(record.status))
244
+ if (record.controllerPiboSessionId !== controllerPiboSessionId || terminal(record.status))
217
245
  continue;
218
246
  record.status = "cancelled";
219
247
  record.error = reason;
@@ -223,7 +251,9 @@ export class PiboRunRegistry {
223
251
  this.options.store?.updateRun(record.runId, record);
224
252
  if (record.jobId)
225
253
  this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, reason);
226
- cancelled.push(snapshot(record));
254
+ const output = snapshot(record);
255
+ this.notify({ type: "run_changed", run: output, previousStatus: "running", reason });
256
+ cancelled.push(output);
227
257
  }
228
258
  return cancelled;
229
259
  }
@@ -240,7 +270,9 @@ export class PiboRunRegistry {
240
270
  this.options.store?.updateRun(record.runId, record);
241
271
  if (record.jobId)
242
272
  this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, reason);
243
- cancelled.push(snapshot(record));
273
+ const output = snapshot(record);
274
+ this.notify({ type: "run_changed", run: output, previousStatus: "running", reason });
275
+ cancelled.push(output);
244
276
  }
245
277
  return cancelled;
246
278
  }
@@ -262,6 +294,7 @@ export class PiboRunRegistry {
262
294
  if (!shouldPrune)
263
295
  continue;
264
296
  this.runs.delete(runId);
297
+ this.notify({ type: "run_removed", runId, controllerPiboSessionId: record.controllerPiboSessionId });
265
298
  pruned += 1;
266
299
  }
267
300
  if (this.options.store) {
@@ -269,15 +302,15 @@ export class PiboRunRegistry {
269
302
  }
270
303
  return pruned;
271
304
  }
272
- requireOwned(ownerPiboSessionId, runId) {
305
+ requireRunForController(controllerPiboSessionId, runId) {
273
306
  const record = this.runs.get(runId);
274
- if (!record || record.ownerPiboSessionId !== ownerPiboSessionId) {
275
- throw new Error(`Unknown run "${runId}" for session "${ownerPiboSessionId}"`);
307
+ if (!record || record.controllerPiboSessionId !== controllerPiboSessionId) {
308
+ throw new Error(`Unknown run "${runId}" for session "${controllerPiboSessionId}"`);
276
309
  }
277
310
  return record;
278
311
  }
279
- needsNotification(record, ownerPiboSessionId, options = {}) {
280
- return (record.ownerPiboSessionId === ownerPiboSessionId &&
312
+ needsNotification(record, controllerPiboSessionId, options = {}) {
313
+ return (record.controllerPiboSessionId === controllerPiboSessionId &&
281
314
  record.completionPolicy === "tracked" &&
282
315
  !record.consumed &&
283
316
  record.acknowledgedStatus !== record.status &&
@@ -298,12 +331,16 @@ export class PiboRunRegistry {
298
331
  waiter.resolve(record);
299
332
  }
300
333
  }
334
+ notify(event) {
335
+ for (const listener of this.listeners)
336
+ listener(event);
337
+ }
301
338
  }
302
339
  function recordFromStored(record) {
303
340
  return {
304
341
  runId: record.runId,
305
342
  kind: record.kind,
306
- ownerPiboSessionId: record.ownerPiboSessionId,
343
+ controllerPiboSessionId: record.controllerPiboSessionId,
307
344
  status: record.status,
308
345
  completionPolicy: record.completionPolicy,
309
346
  consumed: record.consumed,
@@ -0,0 +1,193 @@
1
+ import { redactTerminalSecret } from "./statusViewModel.js";
2
+ export const CLI_ONLY_SLASH_COMMANDS = [
3
+ { id: "help", slash: "/help", description: "Show command help and keyboard controls.", group: "cli", support: "supported" },
4
+ { id: "new", slash: "/new", description: "Create a new session in the active or selected room.", group: "navigation", support: "supported" },
5
+ { id: "room", slash: "/room", description: "Select the active room in the app context.", group: "navigation", support: "supported" },
6
+ { id: "session", slash: "/session", description: "Select a room, then open or create a session.", group: "navigation", support: "supported" },
7
+ { id: "agent", slash: "/agent", description: "Select an existing agent/profile for the session.", group: "navigation", support: "supported" },
8
+ { id: "profile", slash: "/profile", description: "Select an existing agent/profile for the session.", group: "navigation", support: "supported" },
9
+ { id: "repair-user-unknown", slash: "/repair-user-unknown", description: "Repair legacy CLI sessions stored under user:unknown.", group: "cli", support: "supported" },
10
+ { id: "exit", slash: "/exit", description: "Exit the terminal UI.", group: "cli", support: "supported", aliases: ["/quit"] },
11
+ { id: "quit", slash: "/quit", description: "Exit the terminal UI.", group: "cli", support: "supported" },
12
+ ];
13
+ export const WEB_PARITY_SLASH_COMMANDS = [
14
+ { id: "status", slash: "/status", actionName: "status", description: "Show session, runtime, model, queue, and usage status.", group: "session", support: "supported" },
15
+ { id: "compact", slash: "/compact", actionName: "compact", description: "Run session compaction when the runtime supports it.", group: "runtime", support: "terminal-adapted" },
16
+ { id: "clear", slash: "/clear", actionName: "clear_queue", description: "Clear queued messages that have not started yet; terminal currently also clears local display.", group: "runtime", support: "terminal-adapted" },
17
+ { id: "abort", slash: "/abort", actionName: "abort", description: "Abort the active response.", group: "runtime", support: "terminal-adapted" },
18
+ { id: "kill", slash: "/kill", actionName: "kill", description: "Dispose the active session runtime.", group: "runtime", support: "terminal-adapted" },
19
+ { id: "kill-all", slash: "/kill-all", actionName: "kill-all", description: "Dispose all routed runtimes for the selected app context when supported.", group: "runtime", support: "terminal-adapted" },
20
+ { id: "fast", slash: "/fast", actionName: "fast_mode", description: "Toggle fast mode for the active session.", argumentHint: "[on|off]", group: "runtime", support: "terminal-adapted" },
21
+ { id: "thinking", slash: "/thinking", actionName: "thinking", description: "Show or set model thinking level.", argumentHint: "[off|minimal|low|medium|high|xhigh]", group: "runtime", support: "terminal-adapted", terminalAdaptation: "Without an argument, open a keyboard picker." },
22
+ { id: "model", slash: "/model", actionName: "model", description: "Choose an authenticated provider model.", group: "runtime", support: "terminal-adapted", terminalAdaptation: "Open provider and model pickers." },
23
+ { id: "login", slash: "/login", actionName: "login", description: "Authenticate a model provider.", group: "runtime", support: "terminal-adapted", terminalAdaptation: "Show provider/auth-method instructions in terminal." },
24
+ { id: "session-current", slash: "/session-current", actionName: "session-current", description: "Show metadata for the active session.", group: "session", support: "terminal-adapted" },
25
+ { id: "sessions", slash: "/sessions", actionName: "sessions", description: "List sessions for the selected shared room.", group: "session", support: "terminal-adapted" },
26
+ { id: "clone", slash: "/clone", actionName: "clone", description: "Clone or derive the active session when supported.", group: "session", support: "terminal-adapted" },
27
+ { id: "fork-candidates", slash: "/fork-candidates", actionName: "session.fork_candidates", description: "Inspect terminal-selectable fork candidates.", argumentHint: "[entry-id]", group: "session", support: "terminal-adapted", terminalAdaptation: "Without an argument, list candidates; selecting one attempts a routed fork." },
28
+ { id: "download", slash: "/download", actionName: "download", description: "Show terminal-safe download instructions for a server path.", argumentHint: "<path>", group: "session", support: "terminal-adapted", terminalAdaptation: "Use shell/server paths instead of browser download APIs." },
29
+ { id: "upload", slash: "/upload", actionName: "upload", description: "Show terminal-safe upload instructions for a local path.", argumentHint: "<path>", group: "session", support: "terminal-adapted", terminalAdaptation: "Use path-based terminal instructions instead of browser file picker APIs." },
30
+ { id: "thinking-show", slash: "/thinking-show", actionName: "thinking", description: "Show thinking controls in Web.", group: "unsupported", support: "deferred", unsupportedReason: "Use /thinking in terminal." },
31
+ ];
32
+ export function buildSlashCommandCatalog(capabilities = []) {
33
+ const bySlash = new Map();
34
+ for (const command of [...WEB_PARITY_SLASH_COMMANDS, ...CLI_ONLY_SLASH_COMMANDS])
35
+ bySlash.set(command.slash, command);
36
+ for (const capability of expandGatewayCommandCapabilities(capabilities)) {
37
+ if (capability.hidden)
38
+ continue;
39
+ const slash = normalizeSlash(capability.slash ?? capability.name);
40
+ if (!slash)
41
+ continue;
42
+ const existing = bySlash.get(slash);
43
+ if (existing && isCliOwnedCommand(existing) && capability.name !== undefined)
44
+ continue;
45
+ bySlash.set(slash, {
46
+ id: slash.slice(1),
47
+ slash,
48
+ actionName: capability.actionName ?? existing?.actionName ?? capability.name,
49
+ description: redactTerminalSecret(capability.description ?? existing?.description ?? `Run ${slash}.`),
50
+ argumentHint: capability.argumentHint ?? existing?.argumentHint,
51
+ group: capability.browserOnly || capability.productArea ? "unsupported" : existing?.group ?? "session",
52
+ support: supportForCapability(capability, existing),
53
+ unsupportedReason: redactTerminalSecret(capability.unsupportedReason ?? existing?.unsupportedReason ?? "") || undefined,
54
+ terminalAdaptation: existing?.terminalAdaptation,
55
+ aliases: existing?.aliases,
56
+ });
57
+ }
58
+ return [...bySlash.values()].sort((left, right) => left.slash.localeCompare(right.slash));
59
+ }
60
+ export function filterSlashCommands(catalog, input) {
61
+ const normalized = input.trim().split(/\s+/, 1)[0]?.toLowerCase() ?? "";
62
+ const prefix = normalized.startsWith("/") ? normalized : `/${normalized}`;
63
+ return catalog.filter((command) => command.slash.toLowerCase().startsWith(prefix) || command.aliases?.some((alias) => alias.toLowerCase().startsWith(prefix)));
64
+ }
65
+ export function formatSlashCommand(command) {
66
+ return `${command.slash}${command.argumentHint ? ` ${command.argumentHint}` : ""}`;
67
+ }
68
+ export function commandSupportLabel(command) {
69
+ if (command.support === "supported")
70
+ return "available";
71
+ if (command.support === "terminal-adapted")
72
+ return "terminal";
73
+ if (command.support === "browser-only")
74
+ return "browser-only";
75
+ if (command.support === "product-area")
76
+ return "product-area";
77
+ return "deferred";
78
+ }
79
+ export function groupSlashCommandsForHelp(catalog) {
80
+ return {
81
+ available: catalog.filter((command) => (command.group === "session" || command.group === "runtime") && (command.support === "supported" || command.support === "terminal-adapted")),
82
+ navigation: catalog.filter((command) => command.group === "navigation" || command.group === "cli"),
83
+ unsupported: catalog.filter((command) => command.group === "unsupported" || command.support === "browser-only" || command.support === "product-area" || command.support === "deferred"),
84
+ };
85
+ }
86
+ export function buildSlashCommandBehaviorMatrix(catalog = buildSlashCommandCatalog()) {
87
+ return catalog.map((command) => ({
88
+ id: command.id,
89
+ slash: command.slash,
90
+ aliases: command.aliases ?? [],
91
+ group: command.group,
92
+ support: command.support,
93
+ supportLabel: commandSupportLabel(command),
94
+ palette: "shown",
95
+ argumentBehavior: slashArgumentBehavior(command),
96
+ enterBehavior: slashEnterBehavior(command),
97
+ resultPlacement: slashResultPlacement(command),
98
+ contextRequirement: slashContextRequirement(command),
99
+ errorBehavior: slashErrorBehavior(command),
100
+ terminalAdaptation: command.terminalAdaptation,
101
+ }));
102
+ }
103
+ function slashArgumentBehavior(command) {
104
+ if (command.argumentHint)
105
+ return command.argumentHint;
106
+ if (command.slash === "/model")
107
+ return "no argument opens provider/model picker; provider/model applies selection";
108
+ if (command.slash === "/login")
109
+ return "no argument opens provider/auth picker; provider/method applies selection";
110
+ if (command.slash === "/thinking")
111
+ return "no argument opens thinking picker; level applies selection";
112
+ return "none";
113
+ }
114
+ function slashEnterBehavior(command) {
115
+ if (command.slash === "/help")
116
+ return "append help text above transcript guidance";
117
+ if (command.slash === "/new")
118
+ return "create session in active or selected room";
119
+ if (["/room", "/session", "/profile", "/agent"].includes(command.slash))
120
+ return "open keyboard picker overlay";
121
+ if (["/exit", "/quit"].includes(command.slash))
122
+ return "exit terminal UI";
123
+ if (command.slash === "/repair-user-unknown")
124
+ return "append compact repair result";
125
+ if (["/model", "/login", "/thinking"].includes(command.slash))
126
+ return "open picker without arguments or append result with arguments";
127
+ if (command.slash === "/fork-candidates")
128
+ return "open candidate picker without entry id or dispatch fork with entry id";
129
+ if (command.support === "browser-only" || command.support === "product-area" || command.support === "deferred")
130
+ return "append unsupported/deferred transcript result";
131
+ return "append command and result rows to transcript";
132
+ }
133
+ function slashResultPlacement(command) {
134
+ if (["/exit", "/quit"].includes(command.slash))
135
+ return "exit";
136
+ if (["/room", "/session", "/profile", "/agent"].includes(command.slash))
137
+ return "overlay";
138
+ if (command.slash === "/new")
139
+ return "navigation";
140
+ if (["/model", "/login", "/thinking", "/fork-candidates"].includes(command.slash))
141
+ return "transcript-or-overlay";
142
+ return "transcript";
143
+ }
144
+ function slashContextRequirement(command) {
145
+ if (["/room", "/session", "/new", "/profile", "/repair-user-unknown"].includes(command.slash))
146
+ return "app room/session navigation";
147
+ if (["/status", "/sessions", "/session-current", "/clone", "/fork-candidates"].includes(command.slash))
148
+ return "active session when available; named room context preferred";
149
+ if (["/compact", "/clear", "/abort", "/kill", "/kill-all", "/fast", "/thinking", "/model", "/login"].includes(command.slash))
150
+ return "active routed session/runtime";
151
+ if (["/download", "/upload"].includes(command.slash))
152
+ return "terminal path argument";
153
+ return "none";
154
+ }
155
+ function slashErrorBehavior(command) {
156
+ if (command.support === "browser-only" || command.support === "product-area" || command.support === "deferred")
157
+ return "render compact unsupported result";
158
+ if (["/room", "/session", "/profile", "/agent", "/model", "/login", "/thinking", "/fork-candidates"].includes(command.slash))
159
+ return "keep overlay compact or append redacted error row after confirmed action";
160
+ return "append redacted command error row";
161
+ }
162
+ function expandGatewayCommandCapabilities(capabilities) {
163
+ const expanded = [];
164
+ for (const capability of capabilities) {
165
+ if (capability.slashCommands && capability.slashCommands.length > 0) {
166
+ for (const slash of capability.slashCommands)
167
+ expanded.push({ ...capability, slash, actionName: capability.actionName ?? capability.name });
168
+ continue;
169
+ }
170
+ expanded.push(capability);
171
+ }
172
+ return expanded;
173
+ }
174
+ function isCliOwnedCommand(command) {
175
+ return command.group === "cli" || command.slash === "/new" || command.slash === "/room" || command.slash === "/session" || command.slash === "/agent" || command.slash === "/profile";
176
+ }
177
+ function normalizeSlash(value) {
178
+ if (!value)
179
+ return undefined;
180
+ const trimmed = value.trim().toLowerCase();
181
+ if (!trimmed)
182
+ return undefined;
183
+ return (trimmed.startsWith("/") ? trimmed : `/${trimmed}`);
184
+ }
185
+ function supportForCapability(capability, existing) {
186
+ if (capability.browserOnly)
187
+ return "browser-only";
188
+ if (capability.productArea)
189
+ return "product-area";
190
+ if (capability.supported === false)
191
+ return "deferred";
192
+ return existing?.support ?? "terminal-adapted";
193
+ }