@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
@@ -0,0 +1,1144 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { DEFAULT_PIBO_PROFILE_NAME, createDefaultPiboPluginRegistry, resolvePiboProfileNameFromRegistryOrDefault, } from "../plugins/builtin.js";
3
+ import { createDefaultPiboDataSessionStore } from "../sessions/pibo-data-store.js";
4
+ import { getDefaultPiboWorkspace } from "../core/workspace.js";
5
+ import { buildTraceView } from "../apps/chat/trace.js";
6
+ import { storedPiboEventFromV2Row, } from "../apps/chat/data/chat-data-mappers.js";
7
+ import { ChatDataIngestService } from "../data/ingest-service.js";
8
+ import { ChatRoomService } from "../apps/chat/data/room-service.js";
9
+ import { buildSlashCommandCatalog, normalizeCommandErrorDescriptor, normalizeCommandResultDescriptor, } from "../session-ui/index.js";
10
+ import { CliSourceError, } from "./sessionSource.js";
11
+ export const CLI_LOCAL_RECOVERY_SOURCE_ID = "local:root";
12
+ export const CLI_LOCAL_RECOVERY_SOURCE_LABEL = "Local recovery";
13
+ export class LocalCliSessionSource {
14
+ sessionStore;
15
+ ownsSessionStore;
16
+ roomProvider;
17
+ pluginRegistry;
18
+ router;
19
+ ownsRouter;
20
+ unsubscribeRouter;
21
+ now;
22
+ statusMessage;
23
+ dataStore;
24
+ ownsDataStore;
25
+ ingestService;
26
+ roomService;
27
+ agentSummaries;
28
+ traceViews = new Map();
29
+ listeners = new Map();
30
+ openHandles = new Set();
31
+ closed = false;
32
+ constructor(options = {}) {
33
+ this.sessionStore =
34
+ options.sessionStore ?? createDefaultPiboDataSessionStore();
35
+ this.ownsSessionStore =
36
+ options.ownsSessionStore ?? options.sessionStore === undefined;
37
+ this.roomProvider = options.roomProvider;
38
+ this.pluginRegistry =
39
+ options.pluginRegistry ?? createDefaultPiboPluginRegistry();
40
+ this.router = options.router;
41
+ this.ownsRouter = options.ownsRouter ?? false;
42
+ this.unsubscribeRouter = this.router?.subscribe((event) => this.handleRouterEvent(event));
43
+ this.now = options.now ?? (() => new Date().toISOString());
44
+ this.statusMessage = options.statusMessage;
45
+ this.dataStore = options.dataStore;
46
+ this.ownsDataStore = options.ownsDataStore === true;
47
+ this.ingestService = options.dataStore
48
+ ? new ChatDataIngestService(options.dataStore)
49
+ : undefined;
50
+ this.roomService = options.dataStore
51
+ ? new ChatRoomService(options.dataStore)
52
+ : undefined;
53
+ this.agentSummaries = options.agentSummaries
54
+ ? [...options.agentSummaries]
55
+ : undefined;
56
+ }
57
+ async listRooms() {
58
+ this.assertOpen();
59
+ if (this.roomProvider) {
60
+ return ensureDefaultRoomSummary((await this.roomProvider.listRooms()).map(cloneJson));
61
+ }
62
+ if (this.roomService) {
63
+ const defaultRoom = this.roomService.ensureDefaultRoom({
64
+ name: "Shared Chat",
65
+ });
66
+ const rooms = mergeRoomSummaries([
67
+ ...this.roomService.listRooms().map((room) => ({
68
+ id: room.id,
69
+ title: room.name,
70
+ description: room.topic,
71
+ isDefault: room.id === defaultRoom.id || room.metadata.default === true,
72
+ })),
73
+ ...deriveRoomsFromSessions(this.readSessions()),
74
+ ]);
75
+ return ensureDefaultRoomSummary(rooms).map(cloneJson);
76
+ }
77
+ return ensureDefaultRoomSummary(deriveRoomsFromSessions(this.readSessions())).map(cloneJson);
78
+ }
79
+ async listSessions(input = {}) {
80
+ this.assertOpen();
81
+ const defaultRoomId = this.ensureDefaultRoom().id;
82
+ return this.readSessions()
83
+ .filter((session) => input.roomId === undefined ||
84
+ roomIdFromSession(session, defaultRoomId) === input.roomId)
85
+ .map((session) => sessionToSummary(session, defaultRoomId));
86
+ }
87
+ async createSession(input = {}) {
88
+ this.assertOpen();
89
+ const agent = input.agentId ? this.resolveAgent(input.agentId) : undefined;
90
+ const profile = this.resolveProfile(input.profile ??
91
+ agent?.profileName ??
92
+ agent?.id ??
93
+ this.defaultProfileName());
94
+ const room = input.roomId
95
+ ? await this.findRoomSummary(input.roomId)
96
+ : this.ensureDefaultRoom();
97
+ const roomId = input.roomId ?? room?.id;
98
+ const metadata = buildSessionMetadata(roomId, "idle", room?.title);
99
+ const session = this.sessionStore.create({
100
+ channel: "cli-session-ui",
101
+ kind: "chat",
102
+ profile,
103
+ workspace: input.workspace ?? getDefaultPiboWorkspace(),
104
+ title: input.title?.trim() || "New CLI session",
105
+ metadata,
106
+ });
107
+ if (roomId)
108
+ this.upsertSessionNavigation(session, roomId, undefined, "idle");
109
+ this.traceViews.set(session.id, emptyTraceView(session));
110
+ const summary = sessionToSummary(session, this.ensureDefaultRoom().id);
111
+ this.emit(session.id, {
112
+ type: "session",
113
+ session: summary,
114
+ traceView: cloneJson(this.traceViews.get(session.id) ?? null),
115
+ status: await this.getStatus({ sessionId: session.id }),
116
+ });
117
+ return summary;
118
+ }
119
+ async openSession(sessionId) {
120
+ this.assertOpen();
121
+ const session = this.resolveSession(sessionId);
122
+ let handleClosed = false;
123
+ const handleListeners = new Set();
124
+ const removeFromSource = () => {
125
+ const sourceListeners = this.listeners.get(sessionId);
126
+ if (!sourceListeners)
127
+ return;
128
+ for (const listener of handleListeners)
129
+ sourceListeners.delete(listener);
130
+ if (sourceListeners.size === 0)
131
+ this.listeners.delete(sessionId);
132
+ };
133
+ const handle = {
134
+ sessionId,
135
+ close: () => {
136
+ if (handleClosed)
137
+ return;
138
+ handleClosed = true;
139
+ removeFromSource();
140
+ this.openHandles.delete(handle);
141
+ },
142
+ };
143
+ this.openHandles.add(handle);
144
+ const traceView = await this.loadTraceView(session);
145
+ this.traceViews.set(sessionId, traceView);
146
+ return {
147
+ session: sessionToSummary(session, this.ensureDefaultRoom().id),
148
+ traceView: cloneJson(traceView),
149
+ status: await this.getStatus({ sessionId }),
150
+ subscribe: (listener) => {
151
+ if (handleClosed)
152
+ throw new CliSourceError("session_closed", `CLI session handle for "${sessionId}" is closed`);
153
+ handleListeners.add(listener);
154
+ let sourceListeners = this.listeners.get(sessionId);
155
+ if (!sourceListeners) {
156
+ sourceListeners = new Set();
157
+ this.listeners.set(sessionId, sourceListeners);
158
+ }
159
+ sourceListeners.add(listener);
160
+ return () => {
161
+ handleListeners.delete(listener);
162
+ const listeners = this.listeners.get(sessionId);
163
+ listeners?.delete(listener);
164
+ if (listeners?.size === 0)
165
+ this.listeners.delete(sessionId);
166
+ };
167
+ },
168
+ close: handle.close,
169
+ };
170
+ }
171
+ async sendMessage(sessionId, text) {
172
+ this.assertOpen();
173
+ const trimmed = text.trim();
174
+ if (!trimmed)
175
+ throw new CliSourceError("empty_message", "Message text is empty");
176
+ const session = this.resolveSession(sessionId);
177
+ const eventId = randomUUID();
178
+ this.ingestUserMessage(session, eventId, trimmed);
179
+ if (this.router) {
180
+ try {
181
+ await this.router.emit({
182
+ type: "message",
183
+ piboSessionId: sessionId,
184
+ id: eventId,
185
+ text: trimmed,
186
+ source: "ui",
187
+ });
188
+ }
189
+ catch (error) {
190
+ this.recordLocalError(sessionId, eventId, error);
191
+ throw toCliSourceError("send_failed", `Failed to send local CLI message to session "${sessionId}"`, error);
192
+ }
193
+ return;
194
+ }
195
+ this.recordLocalUserMessage(sessionId, eventId, trimmed, "done");
196
+ this.updateSessionStatus(sessionId, "idle");
197
+ }
198
+ async listAgents() {
199
+ this.assertOpen();
200
+ if (this.agentSummaries)
201
+ return this.agentSummaries.map(cloneJson);
202
+ const agents = this.pluginRegistry.getProfileInfos().map((profile) => ({
203
+ id: profile.name,
204
+ name: profile.name,
205
+ description: profile.description,
206
+ profileName: profile.name,
207
+ }));
208
+ return agents.some((agent) => agent.profileName === DEFAULT_PIBO_PROFILE_NAME)
209
+ ? agents
210
+ : [defaultBaseAgentSummary(), ...agents];
211
+ }
212
+ async listSlashCommands() {
213
+ this.assertOpen();
214
+ return this.buildSlashCommands().map(cloneJson);
215
+ }
216
+ async executeSlashCommand(input) {
217
+ this.assertOpen();
218
+ const command = normalizeCommandName(input.command);
219
+ const descriptor = this.findSlashCommand(command);
220
+ const actionName = descriptor.actionName ?? descriptor.id;
221
+ const session = input.sessionId
222
+ ? this.resolveSession(input.sessionId)
223
+ : undefined;
224
+ if (descriptor.support === "browser-only" ||
225
+ descriptor.support === "product-area" ||
226
+ descriptor.support === "deferred") {
227
+ const rawResult = {
228
+ supported: false,
229
+ unsupportedReason: descriptor.unsupportedReason ??
230
+ `${descriptor.slash} is not supported in the terminal.`,
231
+ };
232
+ return {
233
+ command,
234
+ actionName,
235
+ descriptor: normalizeCommandResultDescriptor(command, rawResult),
236
+ rawResult,
237
+ };
238
+ }
239
+ try {
240
+ const rawResult = await this.executeLocalSlashAction({
241
+ command,
242
+ actionName,
243
+ session,
244
+ args: input.args,
245
+ });
246
+ const openSessionId = sessionIdFromActionResult(rawResult);
247
+ const roomId = roomIdFromActionResult(rawResult) ??
248
+ (openSessionId
249
+ ? roomIdFromSession(this.sessionStore.get(openSessionId) ??
250
+ session ??
251
+ {})
252
+ : undefined);
253
+ if (openSessionId)
254
+ this.upsertDerivedSessionNavigation(openSessionId, roomId);
255
+ return {
256
+ command,
257
+ actionName,
258
+ descriptor: normalizeCommandResultDescriptor(command, rawResult),
259
+ rawResult,
260
+ openSessionId,
261
+ roomId,
262
+ };
263
+ }
264
+ catch (error) {
265
+ return {
266
+ command,
267
+ actionName,
268
+ descriptor: normalizeCommandErrorDescriptor(command, error),
269
+ rawResult: {
270
+ error: error instanceof Error ? error.message : String(error),
271
+ },
272
+ };
273
+ }
274
+ }
275
+ async setSessionAgent(sessionId, agentId) {
276
+ this.assertOpen();
277
+ const session = this.resolveSession(sessionId);
278
+ const agent = this.resolveAgent(agentId);
279
+ if (agent.profileName === session.profile || agent.id === session.profile)
280
+ return sessionToSummary(session, this.ensureDefaultRoom().id);
281
+ throw new CliSourceError("unsupported", "Changing an existing local session profile is not supported by the CLI source. Use /new after selecting the desired profile, or start a new session with that profile.");
282
+ }
283
+ async repairLegacyCliSessions(input = {}) {
284
+ this.assertOpen();
285
+ const room = input.roomId
286
+ ? await this.findRoomSummary(input.roomId)
287
+ : this.ensureDefaultRoom();
288
+ const roomId = input.roomId ?? room?.id;
289
+ void input.sessionIds;
290
+ const candidates = [];
291
+ let repaired = 0;
292
+ const repairedIds = [];
293
+ for (const session of candidates) {
294
+ if (!isLegacyCliUnknownSession(session))
295
+ continue;
296
+ const status = statusFromSession(session) === "unknown"
297
+ ? "idle"
298
+ : statusFromSession(session);
299
+ const metadata = {
300
+ ...(session.metadata ?? {}),
301
+ ...buildSessionMetadata(roomId, status, room?.title),
302
+ repairedFromLegacyScope: "user:unknown",
303
+ repairedAt: this.now(),
304
+ };
305
+ const updated = this.sessionStore.update(session.id, { metadata }) ?? {
306
+ ...session,
307
+ metadata,
308
+ updatedAt: this.now(),
309
+ };
310
+ if (this.dataStore && roomId)
311
+ this.dataStore.sessions.upsertSession({
312
+ session: updated,
313
+ roomId,
314
+ status,
315
+ lastActivityAt: updated.updatedAt,
316
+ });
317
+ if (roomId)
318
+ this.upsertSessionNavigation(updated, roomId, undefined, status);
319
+ repaired += 1;
320
+ repairedIds.push(session.id);
321
+ }
322
+ return {
323
+ roomId,
324
+ scanned: candidates.length,
325
+ repaired,
326
+ skipped: candidates.length - repaired,
327
+ sessionIds: repairedIds,
328
+ };
329
+ }
330
+ async getStatus(input = {}) {
331
+ this.assertOpen();
332
+ if (input.sessionId) {
333
+ const session = this.resolveSession(input.sessionId);
334
+ return this.buildStatus(session);
335
+ }
336
+ const sessions = this.readSessions();
337
+ const rooms = this.roomProvider ? "supported" : "supported";
338
+ return {
339
+ source: "local/direct",
340
+ mode: "local",
341
+ connected: true,
342
+ rooms,
343
+ activeRoomId: this.ensureDefaultRoom().id,
344
+ sessions: "supported",
345
+ agents: "supported",
346
+ message: redactCliSecretText(this.statusMessage ??
347
+ `Local CLI source ready; discovered ${sessions.length} session${sessions.length === 1 ? "" : "s"}.`),
348
+ updatedAt: this.now(),
349
+ };
350
+ }
351
+ async close() {
352
+ if (this.closed)
353
+ return;
354
+ this.closed = true;
355
+ for (const handle of [...this.openHandles])
356
+ handle.close();
357
+ this.listeners.clear();
358
+ this.unsubscribeRouter?.();
359
+ if (this.ownsRouter)
360
+ await this.router?.disposeAll?.();
361
+ if (this.ownsSessionStore)
362
+ this.sessionStore.close?.();
363
+ if (this.ownsDataStore)
364
+ this.dataStore?.close();
365
+ }
366
+ listenerCount(sessionId) {
367
+ if (sessionId)
368
+ return this.listeners.get(sessionId)?.size ?? 0;
369
+ let count = 0;
370
+ for (const listeners of this.listeners.values())
371
+ count += listeners.size;
372
+ return count;
373
+ }
374
+ buildSlashCommands() {
375
+ return buildSlashCommandCatalog(this.pluginRegistry.getGatewayActionInfos().map((action) => ({
376
+ name: action.name,
377
+ description: action.description,
378
+ slashCommands: action.slashCommands,
379
+ })));
380
+ }
381
+ findSlashCommand(command) {
382
+ const slash = `/${command}`;
383
+ const descriptor = this.buildSlashCommands().find((candidate) => candidate.slash === slash ||
384
+ candidate.aliases?.includes(slash));
385
+ if (!descriptor)
386
+ throw new CliSourceError("unsupported", `No slash command found for /${command}`);
387
+ return descriptor;
388
+ }
389
+ async executeLocalSlashAction(input) {
390
+ if (input.command === "status") {
391
+ if (input.session && this.router) {
392
+ const event = {
393
+ type: "execution",
394
+ piboSessionId: input.session.id,
395
+ action: input.actionName,
396
+ id: randomUUID(),
397
+ };
398
+ const output = await this.router.emit(event);
399
+ if (output.type === "execution_result")
400
+ return output.result;
401
+ }
402
+ const status = input.session
403
+ ? this.buildStatus(input.session)
404
+ : await this.getStatus();
405
+ return { ...status, activeModel: input.session?.activeModel };
406
+ }
407
+ if (input.command === "session-current") {
408
+ if (!input.session)
409
+ return { supported: false, unsupportedReason: "No session is open." };
410
+ const defaultRoomId = this.ensureDefaultRoom().id;
411
+ const roomId = roomIdFromSession(input.session, defaultRoomId);
412
+ const room = roomId ? await this.findRoomSummary(roomId) : undefined;
413
+ return sessionMetadataResult(input.session, defaultRoomId, room?.title);
414
+ }
415
+ if (input.command === "sessions") {
416
+ const roomId = input.session
417
+ ? roomIdFromSession(input.session, this.ensureDefaultRoom().id)
418
+ : undefined;
419
+ const rooms = new Map((await this.listRooms()).map((room) => [room.id, room]));
420
+ return (await this.listSessions({ roomId })).map((session) => ({
421
+ id: session.id,
422
+ title: session.title,
423
+ sessionTitle: session.title,
424
+ roomId: session.roomId,
425
+ roomTitle: session.roomId
426
+ ? rooms.get(session.roomId)?.title
427
+ : undefined,
428
+ profile: session.profile,
429
+ status: session.status,
430
+ updatedAt: session.updatedAt,
431
+ }));
432
+ }
433
+ if (input.command === "download")
434
+ return terminalDownloadResult(input.args);
435
+ if (input.command === "upload")
436
+ return terminalUploadResult(input.args);
437
+ if (!input.session)
438
+ return {
439
+ supported: false,
440
+ unsupportedReason: `/${input.command} requires an open session.`,
441
+ };
442
+ if (input.command === "login" &&
443
+ loginAuthMethodFromArgs(input.args) === "api_key")
444
+ return terminalApiKeyLoginInstructions(input.args);
445
+ if (!this.router) {
446
+ return {
447
+ supported: false,
448
+ unsupportedReason: `/${input.command} requires a routed local runtime. Open a local routed session or use a debug PTY mocked router.`,
449
+ };
450
+ }
451
+ const action = routedActionNameForSlash(input.command, input.actionName, input.args);
452
+ const params = executionParamsForSlash(input.command, input.args);
453
+ const event = {
454
+ type: "execution",
455
+ piboSessionId: input.session.id,
456
+ action,
457
+ id: randomUUID(),
458
+ ...(params !== undefined ? { params } : {}),
459
+ };
460
+ const output = await this.router.emit(event);
461
+ if (output.type !== "execution_result")
462
+ throw new CliSourceError("action_failed", `Action /${input.command} did not return an execution result.`);
463
+ return output.result;
464
+ }
465
+ upsertDerivedSessionNavigation(sessionId, resultRoomId) {
466
+ const session = this.sessionStore.get(sessionId);
467
+ if (!session)
468
+ return;
469
+ const roomId = resultRoomId ?? roomIdFromSession(session);
470
+ if (!roomId)
471
+ return;
472
+ this.upsertSessionNavigation(session, roomId, undefined, statusFromSession(session) === "unknown"
473
+ ? "idle"
474
+ : statusFromSession(session));
475
+ }
476
+ readSessions() {
477
+ const sessions = this.sessionStore.list
478
+ ? this.sessionStore.list()
479
+ : this.sessionStore.find({});
480
+ return sessions.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
481
+ }
482
+ resolveSession(sessionId) {
483
+ const session = this.sessionStore.get(sessionId);
484
+ if (!session) {
485
+ throw new CliSourceError("session_not_found", `No local Pibo session found for "${sessionId}"`);
486
+ }
487
+ return session;
488
+ }
489
+ resolveAgent(agentId) {
490
+ const summary = this.agentSummaries?.find((candidate) => candidate.id === agentId ||
491
+ candidate.profileName === agentId ||
492
+ candidate.name === agentId);
493
+ if (summary)
494
+ return cloneJson(summary);
495
+ if (agentId === DEFAULT_PIBO_PROFILE_NAME)
496
+ return defaultBaseAgentSummary();
497
+ const agent = this.pluginRegistry
498
+ .getProfileInfos()
499
+ .find((candidate) => candidate.name === agentId || candidate.aliases.includes(agentId));
500
+ if (!agent)
501
+ throw new CliSourceError("agent_not_found", `No local profile found for "${agentId}"`);
502
+ return {
503
+ id: agent.name,
504
+ name: agent.name,
505
+ description: agent.description,
506
+ profileName: agent.name,
507
+ };
508
+ }
509
+ resolveProfile(profile) {
510
+ try {
511
+ return resolvePiboProfileNameFromRegistryOrDefault(this.pluginRegistry, profile);
512
+ }
513
+ catch (error) {
514
+ throw toCliSourceError("agent_not_found", `No local profile found for "${profile}"`, error);
515
+ }
516
+ }
517
+ defaultProfileName() {
518
+ const names = this.pluginRegistry.getProfileNames();
519
+ return names.includes("base") ? "base" : (names[0] ?? "base");
520
+ }
521
+ handleRouterEvent(event) {
522
+ if (this.closed)
523
+ return;
524
+ const session = this.sessionStore.get(event.piboSessionId);
525
+ if (!session)
526
+ return;
527
+ this.ingestOutputEvent(session, event);
528
+ this.recordOutputEvent(event);
529
+ }
530
+ recordOutputEvent(event) {
531
+ const sessionId = event.piboSessionId;
532
+ const eventId = "eventId" in event ? event.eventId : undefined;
533
+ if (event.type === "message_queued" || event.type === "message_started") {
534
+ this.recordLocalUserMessage(sessionId, eventId ?? randomUUID(), event.text, event.type === "message_started" ? "running" : "done");
535
+ this.updateSessionStatus(sessionId, "running");
536
+ return;
537
+ }
538
+ if (event.type === "message_finished") {
539
+ this.updateSessionStatus(sessionId, "idle");
540
+ return;
541
+ }
542
+ if (event.type === "assistant_delta") {
543
+ this.upsertTraceNode(sessionId, {
544
+ id: traceNodeId("assistant", eventId, event.assistantIndex ?? event.contentIndex),
545
+ piboSessionId: sessionId,
546
+ type: "assistant.message",
547
+ title: "Agent Message",
548
+ status: "running",
549
+ startedAt: this.now(),
550
+ output: event.text,
551
+ children: [],
552
+ }, { appendOutput: true, rawEvent: event });
553
+ return;
554
+ }
555
+ if (event.type === "assistant_message") {
556
+ this.upsertTraceNode(sessionId, {
557
+ id: traceNodeId("assistant", eventId, event.assistantIndex ?? event.contentIndex),
558
+ piboSessionId: sessionId,
559
+ type: "assistant.message",
560
+ title: "Agent Message",
561
+ status: "done",
562
+ startedAt: this.now(),
563
+ completedAt: this.now(),
564
+ output: event.text,
565
+ children: [],
566
+ }, { rawEvent: event });
567
+ return;
568
+ }
569
+ if (event.type === "tool_call" ||
570
+ event.type === "tool_execution_started" ||
571
+ event.type === "tool_execution_updated" ||
572
+ event.type === "tool_execution_finished") {
573
+ const finished = event.type === "tool_execution_finished";
574
+ this.upsertTraceNode(sessionId, {
575
+ id: traceNodeId("tool", event.toolCallId),
576
+ piboSessionId: sessionId,
577
+ eventId,
578
+ toolCallId: event.toolCallId,
579
+ type: finished ? "tool.result" : "tool.call",
580
+ title: event.toolName,
581
+ status: finished ? (event.isError ? "error" : "done") : "running",
582
+ startedAt: this.now(),
583
+ completedAt: finished ? this.now() : undefined,
584
+ input: "args" in event ? event.args : undefined,
585
+ output: finished
586
+ ? event.result
587
+ : "partialResult" in event
588
+ ? event.partialResult
589
+ : undefined,
590
+ children: [],
591
+ }, { rawEvent: event });
592
+ return;
593
+ }
594
+ if (event.type === "session_error") {
595
+ this.recordLocalError(sessionId, eventId ?? randomUUID(), event.error);
596
+ return;
597
+ }
598
+ this.appendRawEvent(sessionId, event);
599
+ }
600
+ recordLocalUserMessage(sessionId, eventId, text, status) {
601
+ this.upsertTraceNode(sessionId, {
602
+ id: traceNodeId("user", eventId),
603
+ piboSessionId: sessionId,
604
+ eventId,
605
+ type: "user.message",
606
+ title: "User Message",
607
+ status,
608
+ startedAt: this.now(),
609
+ completedAt: status === "done" ? this.now() : undefined,
610
+ output: text,
611
+ children: [],
612
+ }, {
613
+ rawEvent: {
614
+ type: "message_queued",
615
+ piboSessionId: sessionId,
616
+ eventId,
617
+ queuedMessages: 0,
618
+ text,
619
+ source: "ui",
620
+ },
621
+ });
622
+ }
623
+ recordLocalError(sessionId, eventId, error) {
624
+ this.upsertTraceNode(sessionId, {
625
+ id: traceNodeId("error", eventId),
626
+ piboSessionId: sessionId,
627
+ eventId,
628
+ type: "error",
629
+ title: "CLI source error",
630
+ status: "error",
631
+ startedAt: this.now(),
632
+ completedAt: this.now(),
633
+ error: error instanceof Error ? error.message : String(error),
634
+ children: [],
635
+ }, {
636
+ rawEvent: {
637
+ type: "session_error",
638
+ piboSessionId: sessionId,
639
+ eventId,
640
+ error: error instanceof Error ? error.message : String(error),
641
+ },
642
+ });
643
+ this.updateSessionStatus(sessionId, "error");
644
+ }
645
+ upsertTraceNode(sessionId, node, options = {}) {
646
+ const session = this.resolveSession(sessionId);
647
+ const traceView = cloneJson(this.traceViews.get(sessionId) ?? emptyTraceView(session));
648
+ const index = traceView.nodes.findIndex((candidate) => candidate.id === node.id);
649
+ if (index >= 0) {
650
+ const previous = traceView.nodes[index];
651
+ const output = options.appendOutput &&
652
+ typeof previous.output === "string" &&
653
+ typeof node.output === "string"
654
+ ? previous.output + node.output
655
+ : node.output;
656
+ traceView.nodes[index] = {
657
+ ...previous,
658
+ ...node,
659
+ output,
660
+ children: node.children ?? previous.children,
661
+ };
662
+ }
663
+ else {
664
+ traceView.nodes.push(node);
665
+ }
666
+ if (options.rawEvent)
667
+ traceView.rawEvents.push(storedEvent(options.rawEvent, this.now(), traceView.rawEvents.length + 1));
668
+ traceView.eventCount = traceView.rawEvents.length;
669
+ traceView.version = `local-${traceView.rawEvents.length}-${session.updatedAt}`;
670
+ this.traceViews.set(sessionId, traceView);
671
+ this.emit(sessionId, {
672
+ type: "trace",
673
+ session: sessionToSummary(session, this.ensureDefaultRoom().id),
674
+ traceView: cloneJson(traceView),
675
+ });
676
+ }
677
+ appendRawEvent(sessionId, event) {
678
+ const session = this.resolveSession(sessionId);
679
+ const traceView = cloneJson(this.traceViews.get(sessionId) ?? emptyTraceView(session));
680
+ traceView.rawEvents.push(storedEvent(event, this.now(), traceView.rawEvents.length + 1));
681
+ traceView.eventCount = traceView.rawEvents.length;
682
+ traceView.version = `local-${traceView.rawEvents.length}-${session.updatedAt}`;
683
+ this.traceViews.set(sessionId, traceView);
684
+ this.emit(sessionId, {
685
+ type: "trace",
686
+ session: sessionToSummary(session, this.ensureDefaultRoom().id),
687
+ traceView: cloneJson(traceView),
688
+ });
689
+ }
690
+ updateSessionStatus(sessionId, status) {
691
+ const session = this.resolveSession(sessionId);
692
+ const updated = this.sessionStore.update(sessionId, {
693
+ metadata: { ...(session.metadata ?? {}), status },
694
+ }) ?? session;
695
+ const summary = sessionToSummary(updated, this.ensureDefaultRoom().id);
696
+ this.emit(sessionId, {
697
+ type: "session",
698
+ session: summary,
699
+ status: this.buildStatus(updated),
700
+ });
701
+ }
702
+ async loadTraceView(session) {
703
+ if (!this.dataStore)
704
+ return cloneJson(this.traceViews.get(session.id) ?? emptyTraceView(session));
705
+ const rows = this.dataStore.eventLog.listEvents({
706
+ sessionId: session.id,
707
+ limit: 500,
708
+ });
709
+ const events = rows
710
+ .map((row) => storedPiboEventFromV2Row(eventLogRowToV2MapperRow(row)))
711
+ .filter((event) => event !== undefined)
712
+ .map(normalizeStoredEventForCliTrace);
713
+ return await buildTraceView({
714
+ session,
715
+ sessions: this.readSessions(),
716
+ events,
717
+ status: statusFromSession(session) === "running"
718
+ ? "running"
719
+ : statusFromSession(session) === "error"
720
+ ? "error"
721
+ : "idle",
722
+ cwd: session.workspace ?? getDefaultPiboWorkspace(),
723
+ });
724
+ }
725
+ ingestUserMessage(session, eventId, text) {
726
+ const roomId = roomIdFromSession(session);
727
+ if (!this.ingestService || !roomId)
728
+ return;
729
+ try {
730
+ this.ingestService.ingestUserMessageAccepted({
731
+ session,
732
+ roomId,
733
+ actorId: "cli-session-ui",
734
+ text,
735
+ clientTxnId: eventId,
736
+ legacyEvent: { eventId, createdAt: this.now() },
737
+ });
738
+ }
739
+ catch {
740
+ // Persistence is best-effort; live local rendering still proceeds through router events.
741
+ }
742
+ }
743
+ ingestOutputEvent(session, event) {
744
+ if (!this.ingestService)
745
+ return;
746
+ try {
747
+ this.ingestService.ingestOutputEvent({
748
+ session,
749
+ roomId: roomIdFromSession(session),
750
+ actorId: session.profile,
751
+ event,
752
+ createdAt: this.now(),
753
+ });
754
+ }
755
+ catch {
756
+ // Persistence is best-effort; live local rendering still proceeds through in-memory trace updates.
757
+ }
758
+ }
759
+ buildStatus(session) {
760
+ const runtime = this.router?.getSessionRuntimeStatus?.(session.id);
761
+ return {
762
+ source: "local/direct",
763
+ mode: "local",
764
+ connected: true,
765
+ rooms: "supported",
766
+ sessions: "supported",
767
+ agents: "supported",
768
+ activeRoomId: roomIdFromSession(session) ?? this.ensureDefaultRoom().id,
769
+ activeSessionId: session.id,
770
+ activeAgentId: session.profile,
771
+ activeModel: session.activeModel,
772
+ queuedMessages: runtime?.queuedMessages,
773
+ processing: runtime?.processing,
774
+ streaming: runtime?.streaming,
775
+ cwd: runtime?.cwd,
776
+ thinkingLevel: runtime?.thinkingLevel,
777
+ fastMode: runtime?.fastMode,
778
+ contextUsage: runtime?.contextUsage,
779
+ providerUsage: runtime?.providerUsage,
780
+ warnings: runtime?.warnings,
781
+ errors: runtime?.errors,
782
+ message: redactCliSecretText(runtime
783
+ ? `Runtime ready; queued=${runtime.queuedMessages} processing=${runtime.processing} streaming=${runtime.streaming}`
784
+ : (this.statusMessage ?? "Local CLI source ready.")),
785
+ updatedAt: this.now(),
786
+ };
787
+ }
788
+ async findRoomSummary(roomId) {
789
+ return (await this.listRooms()).find((room) => room.id === roomId);
790
+ }
791
+ ensureDefaultRoom() {
792
+ if (this.roomService) {
793
+ const room = this.roomService.ensureDefaultRoom({ name: "Shared Chat" });
794
+ return {
795
+ id: room.id,
796
+ title: room.name,
797
+ description: room.topic,
798
+ isDefault: true,
799
+ };
800
+ }
801
+ return defaultCliRoomSummary();
802
+ }
803
+ upsertSessionNavigation(session, roomId, lastMessagePreview, status) {
804
+ if (!this.dataStore)
805
+ return;
806
+ const now = this.now();
807
+ this.dataStore.navigation.upsertSession({
808
+ roomId,
809
+ sessionId: session.id,
810
+ rootSessionId: rootSessionIdFromSession(session),
811
+ parentId: session.parentId,
812
+ originId: session.originId,
813
+ title: session.title || lastMessagePreview || "Untitled Session",
814
+ profile: session.profile,
815
+ status,
816
+ lastActivityAt: now,
817
+ lastMessagePreview,
818
+ sortKey: now,
819
+ updatedAt: now,
820
+ });
821
+ }
822
+ emit(sessionId, update) {
823
+ const listeners = [...(this.listeners.get(sessionId) ?? [])];
824
+ for (const listener of listeners)
825
+ listener(update);
826
+ }
827
+ assertOpen() {
828
+ if (this.closed)
829
+ throw new CliSourceError("source_closed", "Local CLI session source is closed");
830
+ }
831
+ }
832
+ export function createLocalCliSessionSource(options = {}) {
833
+ return new LocalCliSessionSource(options);
834
+ }
835
+ export function redactCliSecretText(text) {
836
+ return text
837
+ .replace(/\b([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD)[A-Z0-9_]*)\s*=\s*([^\s]+)/gi, "$1=[redacted]")
838
+ .replace(/\b(api[_-]?key|token|secret|password)\s*[:=]\s*([^\s]+)/gi, "$1=[redacted]")
839
+ .replace(/\b(?:sk|pk|pibo|ghp|github_pat)_[A-Za-z0-9_\-]{8,}\b/g, "[redacted]");
840
+ }
841
+ function sessionToSummary(session, defaultRoomId) {
842
+ return {
843
+ id: session.id,
844
+ title: session.title?.trim() || session.id,
845
+ roomId: roomIdFromSession(session, defaultRoomId),
846
+ profile: session.profile,
847
+ agentId: session.profile,
848
+ workspace: session.workspace,
849
+ status: statusFromSession(session),
850
+ model: session.activeModel,
851
+ createdAt: session.createdAt,
852
+ updatedAt: session.updatedAt,
853
+ };
854
+ }
855
+ function deriveRoomsFromSessions(sessions) {
856
+ const rooms = new Map();
857
+ for (const session of sessions) {
858
+ const roomId = roomIdFromSession(session);
859
+ if (!roomId || rooms.has(roomId))
860
+ continue;
861
+ rooms.set(roomId, {
862
+ id: roomId,
863
+ title: stringMetadata(session, "chatRoomName") ??
864
+ stringMetadata(session, "roomName") ??
865
+ roomId,
866
+ description: "Derived from local session metadata",
867
+ });
868
+ }
869
+ return [...rooms.values()].sort((left, right) => left.title.localeCompare(right.title));
870
+ }
871
+ function roomIdFromSession(session, defaultRoomId) {
872
+ return (stringMetadata(session, "chatRoomId") ??
873
+ stringMetadata(session, "roomId") ??
874
+ defaultRoomId);
875
+ }
876
+ function statusFromSession(session) {
877
+ const status = session.metadata?.status;
878
+ return status === "idle" || status === "running" || status === "error"
879
+ ? status
880
+ : "unknown";
881
+ }
882
+ function stringMetadata(session, key) {
883
+ const value = session.metadata?.[key];
884
+ return typeof value === "string" && value.trim().length > 0
885
+ ? value
886
+ : undefined;
887
+ }
888
+ function buildSessionMetadata(roomId, status, roomName) {
889
+ if (!roomId)
890
+ return { status, source: "pibo tui:sessions" };
891
+ return roomName
892
+ ? {
893
+ chatRoomId: roomId,
894
+ roomId,
895
+ chatRoomName: roomName,
896
+ status,
897
+ source: "pibo tui:sessions",
898
+ }
899
+ : { chatRoomId: roomId, roomId, status, source: "pibo tui:sessions" };
900
+ }
901
+ function rootSessionIdFromSession(session) {
902
+ return session.parentId
903
+ ? typeof session.metadata?.rootSessionId === "string"
904
+ ? session.metadata.rootSessionId
905
+ : session.parentId
906
+ : session.id;
907
+ }
908
+ function isLegacyCliUnknownSession(session) {
909
+ return (session.channel === "cli-session-ui" ||
910
+ session.metadata?.source === "pibo tui:sessions");
911
+ }
912
+ function eventLogRowToV2MapperRow(row) {
913
+ return {
914
+ stream_id: row.streamId,
915
+ session_id: row.sessionId ?? null,
916
+ session_sequence: row.sessionSequence ?? null,
917
+ room_id: row.roomId ?? null,
918
+ type: row.type,
919
+ actor_type: row.actorType ?? null,
920
+ actor_id: row.actorId ?? null,
921
+ event_id: row.eventId ?? null,
922
+ idempotency_key: row.idempotencyKey ?? null,
923
+ retention_class: row.retentionClass,
924
+ preview_text: row.previewText ?? null,
925
+ attributes_json: JSON.stringify(row.attributes ?? {}),
926
+ created_at: row.createdAt,
927
+ };
928
+ }
929
+ function emptyTraceView(session) {
930
+ return {
931
+ piboSessionId: session.id,
932
+ piSessionId: session.piSessionId,
933
+ title: session.title?.trim() || session.id,
934
+ version: `local-empty-${session.updatedAt}`,
935
+ eventCount: 0,
936
+ nodes: [],
937
+ rawEvents: [],
938
+ };
939
+ }
940
+ function normalizeStoredEventForCliTrace(event) {
941
+ const payload = event.payload;
942
+ if (payload?.type !== "user.message.accepted")
943
+ return event;
944
+ return {
945
+ ...event,
946
+ payload: {
947
+ type: "message_queued",
948
+ piboSessionId: event.payload
949
+ .piboSessionId,
950
+ eventId: payload.clientTxnId,
951
+ text: payload.text ?? "",
952
+ source: "ui",
953
+ queuedMessages: 0,
954
+ },
955
+ };
956
+ }
957
+ function storedEvent(event, createdAt, eventSequence) {
958
+ const eventId = "eventId" in event ? event.eventId : undefined;
959
+ return {
960
+ id: eventId ?? `${event.piboSessionId}-${event.type}-${eventSequence}`,
961
+ piboSessionId: event.piboSessionId,
962
+ eventSequence,
963
+ eventId,
964
+ type: event.type,
965
+ createdAt,
966
+ payload: cloneJson(event),
967
+ };
968
+ }
969
+ function traceNodeId(kind, eventId, index) {
970
+ return ["local", kind, eventId ?? "event", index]
971
+ .filter((part) => part !== undefined)
972
+ .join(":");
973
+ }
974
+ function toCliSourceError(code, message, cause) {
975
+ return cause instanceof CliSourceError
976
+ ? cause
977
+ : new CliSourceError(code, message, { cause });
978
+ }
979
+ function mergeRoomSummaries(rooms) {
980
+ const byId = new Map();
981
+ for (const room of rooms) {
982
+ const existing = byId.get(room.id);
983
+ byId.set(room.id, existing
984
+ ? {
985
+ ...room,
986
+ ...existing,
987
+ description: existing.description ?? room.description,
988
+ isDefault: existing.isDefault === true || room.isDefault === true,
989
+ }
990
+ : room);
991
+ }
992
+ return [...byId.values()];
993
+ }
994
+ function ensureDefaultRoomSummary(rooms) {
995
+ const defaultRoom = rooms.find((room) => room.isDefault === true || room.title === "Shared Chat");
996
+ const normalizedRooms = rooms.map((room) => ({
997
+ ...room,
998
+ isDefault: defaultRoom
999
+ ? room.id === defaultRoom.id || room.isDefault === true
1000
+ : room.isDefault === true,
1001
+ }));
1002
+ if (defaultRoom)
1003
+ return normalizedRooms;
1004
+ return [defaultCliRoomSummary(), ...normalizedRooms];
1005
+ }
1006
+ function defaultCliRoomSummary() {
1007
+ return {
1008
+ id: cliDefaultRoomId(),
1009
+ title: "Shared Chat",
1010
+ description: "Shared default chat room",
1011
+ isDefault: true,
1012
+ };
1013
+ }
1014
+ export function cliDefaultRoomId() {
1015
+ return "room_cli_default";
1016
+ }
1017
+ function normalizeCommandName(command) {
1018
+ return command.trim().replace(/^\/+/, "").toLowerCase();
1019
+ }
1020
+ function routedActionNameForSlash(command, actionName, args) {
1021
+ if (command === "fork-candidates" && args?.trim())
1022
+ return "session.fork";
1023
+ if (command === "login" && loginAuthMethodFromArgs(args) === "device_code")
1024
+ return "login.start";
1025
+ return actionName;
1026
+ }
1027
+ function executionParamsForSlash(command, args) {
1028
+ const trimmed = args?.trim();
1029
+ if (command === "compact" && trimmed)
1030
+ return { customInstructions: trimmed };
1031
+ if (command === "thinking" && trimmed)
1032
+ return { level: trimmed };
1033
+ if (command === "model" && trimmed) {
1034
+ const [provider, model] = trimmed.includes("/")
1035
+ ? trimmed.split("/", 2)
1036
+ : [undefined, trimmed];
1037
+ return provider ? { provider, model } : { model };
1038
+ }
1039
+ if (command === "login" && trimmed) {
1040
+ const [provider, method] = parseSlashSelectionArgs(trimmed);
1041
+ if (method === "device_code")
1042
+ return { provider };
1043
+ }
1044
+ if (command === "fork-candidates" && trimmed)
1045
+ return { entryId: trimmed };
1046
+ if (command === "fast" && trimmed)
1047
+ return { mode: trimmed };
1048
+ return undefined;
1049
+ }
1050
+ function loginAuthMethodFromArgs(args) {
1051
+ const trimmed = args?.trim();
1052
+ if (!trimmed)
1053
+ return undefined;
1054
+ return parseSlashSelectionArgs(trimmed)[1];
1055
+ }
1056
+ function parseSlashSelectionArgs(value) {
1057
+ const [left, right] = value.includes("/")
1058
+ ? value.split("/", 2)
1059
+ : value.split(/\s+/, 2);
1060
+ return [left ?? "", right];
1061
+ }
1062
+ function terminalApiKeyLoginInstructions(args) {
1063
+ const [provider] = parseSlashSelectionArgs(args?.trim() ?? "");
1064
+ return {
1065
+ message: `${provider || "Provider"} API-key login requires secret input. The Ink CLI will not echo or collect secrets in this flow; set credentials through provider environment variables or Web Settings, then run /login again.`,
1066
+ supported: true,
1067
+ };
1068
+ }
1069
+ function terminalDownloadResult(args) {
1070
+ const target = args?.trim();
1071
+ if (!target)
1072
+ return {
1073
+ supported: false,
1074
+ unsupportedReason: "Usage: /download <path>. In a terminal, use shell tools such as cat, cp, scp, or rsync for server paths; browser download APIs are Web-only.",
1075
+ };
1076
+ return {
1077
+ message: `Terminal download for ${target}: this path is already on the server. Use shell tools such as cat, cp, scp, or rsync to copy it; browser download APIs are not used by the CLI.`,
1078
+ };
1079
+ }
1080
+ function terminalUploadResult(args) {
1081
+ const target = args?.trim();
1082
+ if (!target)
1083
+ return {
1084
+ supported: false,
1085
+ unsupportedReason: "Usage: /upload <path>. Browser file picker upload is Web-only; from SSH, copy files with scp/rsync or place them under ~/.pibo/uploads.",
1086
+ };
1087
+ return {
1088
+ message: `Terminal upload for ${target}: copy or move the file to ~/.pibo/uploads, or use Web /upload for browser file selection. The CLI did not copy file contents or echo secrets.`,
1089
+ };
1090
+ }
1091
+ function sessionMetadataResult(session, defaultRoomId, roomTitle) {
1092
+ return {
1093
+ piboSessionId: session.id,
1094
+ piSessionId: session.piSessionId,
1095
+ title: session.title,
1096
+ sessionTitle: session.title,
1097
+ profile: session.profile,
1098
+ roomId: roomIdFromSession(session, defaultRoomId),
1099
+ roomTitle,
1100
+ workspace: session.workspace,
1101
+ status: statusFromSession(session),
1102
+ createdAt: session.createdAt,
1103
+ updatedAt: session.updatedAt,
1104
+ };
1105
+ }
1106
+ function sessionIdFromActionResult(value) {
1107
+ const unwrapped = unwrapActionResult(value);
1108
+ if (!unwrapped || typeof unwrapped !== "object" || Array.isArray(unwrapped))
1109
+ return undefined;
1110
+ const record = unwrapped;
1111
+ return typeof record.piboSessionId === "string"
1112
+ ? record.piboSessionId
1113
+ : typeof record.sessionId === "string"
1114
+ ? record.sessionId
1115
+ : undefined;
1116
+ }
1117
+ function roomIdFromActionResult(value) {
1118
+ const unwrapped = unwrapActionResult(value);
1119
+ if (!unwrapped || typeof unwrapped !== "object" || Array.isArray(unwrapped))
1120
+ return undefined;
1121
+ const record = unwrapped;
1122
+ return typeof record.roomId === "string" ? record.roomId : undefined;
1123
+ }
1124
+ function unwrapActionResult(value) {
1125
+ if (!value || typeof value !== "object" || Array.isArray(value))
1126
+ return value;
1127
+ const record = value;
1128
+ if (record.ok === true && "result" in record)
1129
+ return record.result;
1130
+ if (record.success === true && "data" in record)
1131
+ return record.data;
1132
+ return value;
1133
+ }
1134
+ function defaultBaseAgentSummary() {
1135
+ return {
1136
+ id: DEFAULT_PIBO_PROFILE_NAME,
1137
+ name: DEFAULT_PIBO_PROFILE_NAME,
1138
+ description: "Base agent with only the four Pi built-in tools.",
1139
+ profileName: DEFAULT_PIBO_PROFILE_NAME,
1140
+ };
1141
+ }
1142
+ function cloneJson(value) {
1143
+ return value === undefined ? value : JSON.parse(JSON.stringify(value));
1144
+ }