@mecha.im/cli 0.3.4

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 (691) hide show
  1. package/Dockerfile +103 -0
  2. package/README.md +173 -0
  3. package/agent/activity.ts +31 -0
  4. package/agent/costs.ts +93 -0
  5. package/agent/dashboard/dist/assets/addon-fit-YJmn1quW.js +12 -0
  6. package/agent/dashboard/dist/assets/addon-web-links-BWjmmSgS.js +12 -0
  7. package/agent/dashboard/dist/assets/index-B4OKDQ7e.css +32 -0
  8. package/agent/dashboard/dist/assets/index-fZ_N6Wsi.js +193 -0
  9. package/agent/dashboard/dist/assets/xterm-BqvuqXEL.js +27 -0
  10. package/agent/dashboard/dist/index.html +19 -0
  11. package/agent/dashboard/dist/pixel-engine/characters/char_0.png +0 -0
  12. package/agent/dashboard/dist/pixel-engine/characters/char_1.png +0 -0
  13. package/agent/dashboard/dist/pixel-engine/characters/char_2.png +0 -0
  14. package/agent/dashboard/dist/pixel-engine/characters/char_3.png +0 -0
  15. package/agent/dashboard/dist/pixel-engine/characters/char_4.png +0 -0
  16. package/agent/dashboard/dist/pixel-engine/characters/char_5.png +0 -0
  17. package/agent/dashboard/dist/pixel-engine/default-layout.json +4320 -0
  18. package/agent/dashboard/dist/pixel-engine/floors/floor_0.png +0 -0
  19. package/agent/dashboard/dist/pixel-engine/floors/floor_1.png +0 -0
  20. package/agent/dashboard/dist/pixel-engine/floors/floor_2.png +0 -0
  21. package/agent/dashboard/dist/pixel-engine/floors/floor_3.png +0 -0
  22. package/agent/dashboard/dist/pixel-engine/floors/floor_4.png +0 -0
  23. package/agent/dashboard/dist/pixel-engine/floors/floor_5.png +0 -0
  24. package/agent/dashboard/dist/pixel-engine/floors/floor_6.png +0 -0
  25. package/agent/dashboard/dist/pixel-engine/floors/floor_7.png +0 -0
  26. package/agent/dashboard/dist/pixel-engine/floors/floor_8.png +0 -0
  27. package/agent/dashboard/dist/pixel-engine/fonts/FSPixelSansUnicode-Regular.ttf +0 -0
  28. package/agent/dashboard/dist/pixel-engine/furniture/BIN/BIN.png +0 -0
  29. package/agent/dashboard/dist/pixel-engine/furniture/BIN/manifest.json +13 -0
  30. package/agent/dashboard/dist/pixel-engine/furniture/BLACKBOARD/BLACKBOARD.png +0 -0
  31. package/agent/dashboard/dist/pixel-engine/furniture/BLACKBOARD/manifest.json +16 -0
  32. package/agent/dashboard/dist/pixel-engine/furniture/BOOKSHELF/BOOKSHELF.png +0 -0
  33. package/agent/dashboard/dist/pixel-engine/furniture/BOOKSHELF/manifest.json +16 -0
  34. package/agent/dashboard/dist/pixel-engine/furniture/CACTUS/CACTUS.png +0 -0
  35. package/agent/dashboard/dist/pixel-engine/furniture/CACTUS/manifest.json +13 -0
  36. package/agent/dashboard/dist/pixel-engine/furniture/CLOCK/CLOCK.png +0 -0
  37. package/agent/dashboard/dist/pixel-engine/furniture/CLOCK/manifest.json +13 -0
  38. package/agent/dashboard/dist/pixel-engine/furniture/COFFEE/COFFEE.png +0 -0
  39. package/agent/dashboard/dist/pixel-engine/furniture/COFFEE/manifest.json +13 -0
  40. package/agent/dashboard/dist/pixel-engine/furniture/COFFEE_TABLE/COFFEE_TABLE.png +0 -0
  41. package/agent/dashboard/dist/pixel-engine/furniture/COFFEE_TABLE/manifest.json +13 -0
  42. package/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_BENCH/CUSHIONED_BENCH.png +0 -0
  43. package/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_BENCH/manifest.json +13 -0
  44. package/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_BACK.png +0 -0
  45. package/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_FRONT.png +0 -0
  46. package/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_SIDE.png +0 -0
  47. package/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/manifest.json +44 -0
  48. package/agent/dashboard/dist/pixel-engine/furniture/DESK/DESK_FRONT.png +0 -0
  49. package/agent/dashboard/dist/pixel-engine/furniture/DESK/DESK_SIDE.png +0 -0
  50. package/agent/dashboard/dist/pixel-engine/furniture/DESK/manifest.json +33 -0
  51. package/agent/dashboard/dist/pixel-engine/furniture/DOUBLE_BOOKSHELF/DOUBLE_BOOKSHELF.png +0 -0
  52. package/agent/dashboard/dist/pixel-engine/furniture/DOUBLE_BOOKSHELF/manifest.json +16 -0
  53. package/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_1/FILE_BOXES_1.png +0 -0
  54. package/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_1/manifest.json +13 -0
  55. package/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_2/FILE_BOXES_2.png +0 -0
  56. package/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_2/manifest.json +13 -0
  57. package/agent/dashboard/dist/pixel-engine/furniture/HANGING_PLANT/HANGING_PLANT.png +0 -0
  58. package/agent/dashboard/dist/pixel-engine/furniture/HANGING_PLANT/manifest.json +13 -0
  59. package/agent/dashboard/dist/pixel-engine/furniture/LARGE_PAINTING/LARGE_PAINTING.png +0 -0
  60. package/agent/dashboard/dist/pixel-engine/furniture/LARGE_PAINTING/manifest.json +13 -0
  61. package/agent/dashboard/dist/pixel-engine/furniture/LARGE_PLANT/LARGE_PLANT.png +0 -0
  62. package/agent/dashboard/dist/pixel-engine/furniture/LARGE_PLANT/manifest.json +13 -0
  63. package/agent/dashboard/dist/pixel-engine/furniture/PC/PC_BACK.png +0 -0
  64. package/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_OFF.png +0 -0
  65. package/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_ON_1.png +0 -0
  66. package/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_ON_2.png +0 -0
  67. package/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_ON_3.png +0 -0
  68. package/agent/dashboard/dist/pixel-engine/furniture/PC/PC_SIDE.png +0 -0
  69. package/agent/dashboard/dist/pixel-engine/furniture/PC/manifest.json +88 -0
  70. package/agent/dashboard/dist/pixel-engine/furniture/PLANT/PLANT.png +0 -0
  71. package/agent/dashboard/dist/pixel-engine/furniture/PLANT/manifest.json +13 -0
  72. package/agent/dashboard/dist/pixel-engine/furniture/PLANT_2/PLANT_2.png +0 -0
  73. package/agent/dashboard/dist/pixel-engine/furniture/PLANT_2/manifest.json +13 -0
  74. package/agent/dashboard/dist/pixel-engine/furniture/POT/POT.png +0 -0
  75. package/agent/dashboard/dist/pixel-engine/furniture/POT/manifest.json +13 -0
  76. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING/SMALL_PAINTING.png +0 -0
  77. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING/manifest.json +13 -0
  78. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING_2/SMALL_PAINTING_2.png +0 -0
  79. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING_2/manifest.json +13 -0
  80. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_TABLE/SMALL_TABLE_FRONT.png +0 -0
  81. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_TABLE/SMALL_TABLE_SIDE.png +0 -0
  82. package/agent/dashboard/dist/pixel-engine/furniture/SMALL_TABLE/manifest.json +33 -0
  83. package/agent/dashboard/dist/pixel-engine/furniture/SOFA/SOFA_BACK.png +0 -0
  84. package/agent/dashboard/dist/pixel-engine/furniture/SOFA/SOFA_FRONT.png +0 -0
  85. package/agent/dashboard/dist/pixel-engine/furniture/SOFA/SOFA_SIDE.png +0 -0
  86. package/agent/dashboard/dist/pixel-engine/furniture/SOFA/manifest.json +44 -0
  87. package/agent/dashboard/dist/pixel-engine/furniture/TABLE_FRONT/TABLE_FRONT.png +0 -0
  88. package/agent/dashboard/dist/pixel-engine/furniture/TABLE_FRONT/manifest.json +13 -0
  89. package/agent/dashboard/dist/pixel-engine/furniture/VENDER_MACHINE/VENDER_MACHINE.png +0 -0
  90. package/agent/dashboard/dist/pixel-engine/furniture/VENDER_MACHINE/manifest.json +16 -0
  91. package/agent/dashboard/dist/pixel-engine/furniture/WATER_MACHINE/WATER_MACHINE.png +0 -0
  92. package/agent/dashboard/dist/pixel-engine/furniture/WATER_MACHINE/manifest.json +16 -0
  93. package/agent/dashboard/dist/pixel-engine/furniture/WHITEBOARD/WHITEBOARD.png +0 -0
  94. package/agent/dashboard/dist/pixel-engine/furniture/WHITEBOARD/manifest.json +16 -0
  95. package/agent/dashboard/dist/pixel-engine/furniture/WOODEN_BENCH/WOODEN_BENCH.png +0 -0
  96. package/agent/dashboard/dist/pixel-engine/furniture/WOODEN_BENCH/manifest.json +13 -0
  97. package/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_BACK.png +0 -0
  98. package/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_FRONT.png +0 -0
  99. package/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_SIDE.png +0 -0
  100. package/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/manifest.json +44 -0
  101. package/agent/dashboard/dist/pixel-engine/furniture/index.json +32 -0
  102. package/agent/dashboard/dist/pixel-engine/walls/wall_0.png +0 -0
  103. package/agent/dashboard/index.html +18 -0
  104. package/agent/dashboard/package.json +41 -0
  105. package/agent/dashboard/public/pixel-engine/CREDITS.md +17 -0
  106. package/agent/dashboard/public/pixel-engine/characters/char_0.png +0 -0
  107. package/agent/dashboard/public/pixel-engine/characters/char_1.png +0 -0
  108. package/agent/dashboard/public/pixel-engine/characters/char_2.png +0 -0
  109. package/agent/dashboard/public/pixel-engine/characters/char_3.png +0 -0
  110. package/agent/dashboard/public/pixel-engine/characters/char_4.png +0 -0
  111. package/agent/dashboard/public/pixel-engine/characters/char_5.png +0 -0
  112. package/agent/dashboard/public/pixel-engine/default-layout.json +4320 -0
  113. package/agent/dashboard/public/pixel-engine/floors/floor_0.png +0 -0
  114. package/agent/dashboard/public/pixel-engine/floors/floor_1.png +0 -0
  115. package/agent/dashboard/public/pixel-engine/floors/floor_2.png +0 -0
  116. package/agent/dashboard/public/pixel-engine/floors/floor_3.png +0 -0
  117. package/agent/dashboard/public/pixel-engine/floors/floor_4.png +0 -0
  118. package/agent/dashboard/public/pixel-engine/floors/floor_5.png +0 -0
  119. package/agent/dashboard/public/pixel-engine/floors/floor_6.png +0 -0
  120. package/agent/dashboard/public/pixel-engine/floors/floor_7.png +0 -0
  121. package/agent/dashboard/public/pixel-engine/floors/floor_8.png +0 -0
  122. package/agent/dashboard/public/pixel-engine/fonts/FSPixelSansUnicode-Regular.ttf +0 -0
  123. package/agent/dashboard/public/pixel-engine/furniture/BIN/BIN.png +0 -0
  124. package/agent/dashboard/public/pixel-engine/furniture/BIN/manifest.json +13 -0
  125. package/agent/dashboard/public/pixel-engine/furniture/BLACKBOARD/BLACKBOARD.png +0 -0
  126. package/agent/dashboard/public/pixel-engine/furniture/BLACKBOARD/manifest.json +16 -0
  127. package/agent/dashboard/public/pixel-engine/furniture/BOOKSHELF/BOOKSHELF.png +0 -0
  128. package/agent/dashboard/public/pixel-engine/furniture/BOOKSHELF/manifest.json +16 -0
  129. package/agent/dashboard/public/pixel-engine/furniture/CACTUS/CACTUS.png +0 -0
  130. package/agent/dashboard/public/pixel-engine/furniture/CACTUS/manifest.json +13 -0
  131. package/agent/dashboard/public/pixel-engine/furniture/CLOCK/CLOCK.png +0 -0
  132. package/agent/dashboard/public/pixel-engine/furniture/CLOCK/manifest.json +13 -0
  133. package/agent/dashboard/public/pixel-engine/furniture/COFFEE/COFFEE.png +0 -0
  134. package/agent/dashboard/public/pixel-engine/furniture/COFFEE/manifest.json +13 -0
  135. package/agent/dashboard/public/pixel-engine/furniture/COFFEE_TABLE/COFFEE_TABLE.png +0 -0
  136. package/agent/dashboard/public/pixel-engine/furniture/COFFEE_TABLE/manifest.json +13 -0
  137. package/agent/dashboard/public/pixel-engine/furniture/CUSHIONED_BENCH/CUSHIONED_BENCH.png +0 -0
  138. package/agent/dashboard/public/pixel-engine/furniture/CUSHIONED_BENCH/manifest.json +13 -0
  139. package/agent/dashboard/public/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_BACK.png +0 -0
  140. package/agent/dashboard/public/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_FRONT.png +0 -0
  141. package/agent/dashboard/public/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_SIDE.png +0 -0
  142. package/agent/dashboard/public/pixel-engine/furniture/CUSHIONED_CHAIR/manifest.json +44 -0
  143. package/agent/dashboard/public/pixel-engine/furniture/DESK/DESK_FRONT.png +0 -0
  144. package/agent/dashboard/public/pixel-engine/furniture/DESK/DESK_SIDE.png +0 -0
  145. package/agent/dashboard/public/pixel-engine/furniture/DESK/manifest.json +33 -0
  146. package/agent/dashboard/public/pixel-engine/furniture/DOUBLE_BOOKSHELF/DOUBLE_BOOKSHELF.png +0 -0
  147. package/agent/dashboard/public/pixel-engine/furniture/DOUBLE_BOOKSHELF/manifest.json +16 -0
  148. package/agent/dashboard/public/pixel-engine/furniture/FILE_BOXES_1/FILE_BOXES_1.png +0 -0
  149. package/agent/dashboard/public/pixel-engine/furniture/FILE_BOXES_1/manifest.json +13 -0
  150. package/agent/dashboard/public/pixel-engine/furniture/FILE_BOXES_2/FILE_BOXES_2.png +0 -0
  151. package/agent/dashboard/public/pixel-engine/furniture/FILE_BOXES_2/manifest.json +13 -0
  152. package/agent/dashboard/public/pixel-engine/furniture/HANGING_PLANT/HANGING_PLANT.png +0 -0
  153. package/agent/dashboard/public/pixel-engine/furniture/HANGING_PLANT/manifest.json +13 -0
  154. package/agent/dashboard/public/pixel-engine/furniture/LARGE_PAINTING/LARGE_PAINTING.png +0 -0
  155. package/agent/dashboard/public/pixel-engine/furniture/LARGE_PAINTING/manifest.json +13 -0
  156. package/agent/dashboard/public/pixel-engine/furniture/LARGE_PLANT/LARGE_PLANT.png +0 -0
  157. package/agent/dashboard/public/pixel-engine/furniture/LARGE_PLANT/manifest.json +13 -0
  158. package/agent/dashboard/public/pixel-engine/furniture/PC/PC_BACK.png +0 -0
  159. package/agent/dashboard/public/pixel-engine/furniture/PC/PC_FRONT_OFF.png +0 -0
  160. package/agent/dashboard/public/pixel-engine/furniture/PC/PC_FRONT_ON_1.png +0 -0
  161. package/agent/dashboard/public/pixel-engine/furniture/PC/PC_FRONT_ON_2.png +0 -0
  162. package/agent/dashboard/public/pixel-engine/furniture/PC/PC_FRONT_ON_3.png +0 -0
  163. package/agent/dashboard/public/pixel-engine/furniture/PC/PC_SIDE.png +0 -0
  164. package/agent/dashboard/public/pixel-engine/furniture/PC/manifest.json +88 -0
  165. package/agent/dashboard/public/pixel-engine/furniture/PLANT/PLANT.png +0 -0
  166. package/agent/dashboard/public/pixel-engine/furniture/PLANT/manifest.json +13 -0
  167. package/agent/dashboard/public/pixel-engine/furniture/PLANT_2/PLANT_2.png +0 -0
  168. package/agent/dashboard/public/pixel-engine/furniture/PLANT_2/manifest.json +13 -0
  169. package/agent/dashboard/public/pixel-engine/furniture/POT/POT.png +0 -0
  170. package/agent/dashboard/public/pixel-engine/furniture/POT/manifest.json +13 -0
  171. package/agent/dashboard/public/pixel-engine/furniture/SMALL_PAINTING/SMALL_PAINTING.png +0 -0
  172. package/agent/dashboard/public/pixel-engine/furniture/SMALL_PAINTING/manifest.json +13 -0
  173. package/agent/dashboard/public/pixel-engine/furniture/SMALL_PAINTING_2/SMALL_PAINTING_2.png +0 -0
  174. package/agent/dashboard/public/pixel-engine/furniture/SMALL_PAINTING_2/manifest.json +13 -0
  175. package/agent/dashboard/public/pixel-engine/furniture/SMALL_TABLE/SMALL_TABLE_FRONT.png +0 -0
  176. package/agent/dashboard/public/pixel-engine/furniture/SMALL_TABLE/SMALL_TABLE_SIDE.png +0 -0
  177. package/agent/dashboard/public/pixel-engine/furniture/SMALL_TABLE/manifest.json +33 -0
  178. package/agent/dashboard/public/pixel-engine/furniture/SOFA/SOFA_BACK.png +0 -0
  179. package/agent/dashboard/public/pixel-engine/furniture/SOFA/SOFA_FRONT.png +0 -0
  180. package/agent/dashboard/public/pixel-engine/furniture/SOFA/SOFA_SIDE.png +0 -0
  181. package/agent/dashboard/public/pixel-engine/furniture/SOFA/manifest.json +44 -0
  182. package/agent/dashboard/public/pixel-engine/furniture/TABLE_FRONT/TABLE_FRONT.png +0 -0
  183. package/agent/dashboard/public/pixel-engine/furniture/TABLE_FRONT/manifest.json +13 -0
  184. package/agent/dashboard/public/pixel-engine/furniture/VENDER_MACHINE/VENDER_MACHINE.png +0 -0
  185. package/agent/dashboard/public/pixel-engine/furniture/VENDER_MACHINE/manifest.json +16 -0
  186. package/agent/dashboard/public/pixel-engine/furniture/WATER_MACHINE/WATER_MACHINE.png +0 -0
  187. package/agent/dashboard/public/pixel-engine/furniture/WATER_MACHINE/manifest.json +16 -0
  188. package/agent/dashboard/public/pixel-engine/furniture/WHITEBOARD/WHITEBOARD.png +0 -0
  189. package/agent/dashboard/public/pixel-engine/furniture/WHITEBOARD/manifest.json +16 -0
  190. package/agent/dashboard/public/pixel-engine/furniture/WOODEN_BENCH/WOODEN_BENCH.png +0 -0
  191. package/agent/dashboard/public/pixel-engine/furniture/WOODEN_BENCH/manifest.json +13 -0
  192. package/agent/dashboard/public/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_BACK.png +0 -0
  193. package/agent/dashboard/public/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_FRONT.png +0 -0
  194. package/agent/dashboard/public/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_SIDE.png +0 -0
  195. package/agent/dashboard/public/pixel-engine/furniture/WOODEN_CHAIR/manifest.json +44 -0
  196. package/agent/dashboard/public/pixel-engine/furniture/index.json +32 -0
  197. package/agent/dashboard/public/pixel-engine/walls/wall_0.png +0 -0
  198. package/agent/dashboard/src/app.tsx +223 -0
  199. package/agent/dashboard/src/components/alert.tsx +24 -0
  200. package/agent/dashboard/src/components/badge.tsx +41 -0
  201. package/agent/dashboard/src/components/button.tsx +44 -0
  202. package/agent/dashboard/src/components/card.tsx +21 -0
  203. package/agent/dashboard/src/components/dialog.tsx +28 -0
  204. package/agent/dashboard/src/components/index.ts +7 -0
  205. package/agent/dashboard/src/components/input.tsx +45 -0
  206. package/agent/dashboard/src/components/status-dot.tsx +31 -0
  207. package/agent/dashboard/src/index.css +126 -0
  208. package/agent/dashboard/src/lib/api.test.ts +41 -0
  209. package/agent/dashboard/src/lib/api.ts +53 -0
  210. package/agent/dashboard/src/lib/fleet-context.tsx +92 -0
  211. package/agent/dashboard/src/lib/format.test.ts +119 -0
  212. package/agent/dashboard/src/lib/format.ts +41 -0
  213. package/agent/dashboard/src/lib/login-gate.tsx +117 -0
  214. package/agent/dashboard/src/lib/sanitize.test.ts +86 -0
  215. package/agent/dashboard/src/lib/sanitize.ts +13 -0
  216. package/agent/dashboard/src/lib/snippet.test.ts +50 -0
  217. package/agent/dashboard/src/lib/snippet.ts +15 -0
  218. package/agent/dashboard/src/lib/ws-parse.test.ts +72 -0
  219. package/agent/dashboard/src/lib/ws-parse.ts +46 -0
  220. package/agent/dashboard/src/main.tsx +25 -0
  221. package/agent/dashboard/src/pixel-engine/colorize.ts +230 -0
  222. package/agent/dashboard/src/pixel-engine/components/BottomToolbar.tsx +83 -0
  223. package/agent/dashboard/src/pixel-engine/components/DebugView.tsx +175 -0
  224. package/agent/dashboard/src/pixel-engine/components/OfficeCanvas.tsx +838 -0
  225. package/agent/dashboard/src/pixel-engine/components/PixelOffice.tsx +646 -0
  226. package/agent/dashboard/src/pixel-engine/components/SettingsModal.tsx +213 -0
  227. package/agent/dashboard/src/pixel-engine/components/ToolOverlay.tsx +203 -0
  228. package/agent/dashboard/src/pixel-engine/components/ZoomControls.tsx +177 -0
  229. package/agent/dashboard/src/pixel-engine/constants.ts +132 -0
  230. package/agent/dashboard/src/pixel-engine/editor/EditorToolbar.tsx +737 -0
  231. package/agent/dashboard/src/pixel-engine/editor/editorActions.ts +291 -0
  232. package/agent/dashboard/src/pixel-engine/editor/editorState.ts +123 -0
  233. package/agent/dashboard/src/pixel-engine/engine/characters.ts +595 -0
  234. package/agent/dashboard/src/pixel-engine/engine/gameLoop.ts +50 -0
  235. package/agent/dashboard/src/pixel-engine/engine/interactionScheduler.ts +442 -0
  236. package/agent/dashboard/src/pixel-engine/engine/matrixEffect.ts +139 -0
  237. package/agent/dashboard/src/pixel-engine/engine/officeState.ts +748 -0
  238. package/agent/dashboard/src/pixel-engine/engine/renderer.ts +693 -0
  239. package/agent/dashboard/src/pixel-engine/floorTiles.ts +74 -0
  240. package/agent/dashboard/src/pixel-engine/hooks/useAssetLoader.ts +488 -0
  241. package/agent/dashboard/src/pixel-engine/hooks/useEditorActions.ts +661 -0
  242. package/agent/dashboard/src/pixel-engine/hooks/useEditorKeyboard.ts +83 -0
  243. package/agent/dashboard/src/pixel-engine/hooks/useLayoutPersistence.ts +162 -0
  244. package/agent/dashboard/src/pixel-engine/hooks/useOfficeStream.ts +353 -0
  245. package/agent/dashboard/src/pixel-engine/layout/furnitureCatalog.ts +417 -0
  246. package/agent/dashboard/src/pixel-engine/layout/layoutSerializer.ts +416 -0
  247. package/agent/dashboard/src/pixel-engine/layout/tileMap.ts +109 -0
  248. package/agent/dashboard/src/pixel-engine/notificationSound.ts +69 -0
  249. package/agent/dashboard/src/pixel-engine/pixel-office.css +55 -0
  250. package/agent/dashboard/src/pixel-engine/sprites/bubble-permission.json +27 -0
  251. package/agent/dashboard/src/pixel-engine/sprites/bubble-waiting.json +27 -0
  252. package/agent/dashboard/src/pixel-engine/sprites/spriteCache.ts +82 -0
  253. package/agent/dashboard/src/pixel-engine/sprites/spriteData.ts +176 -0
  254. package/agent/dashboard/src/pixel-engine/toolUtils.ts +28 -0
  255. package/agent/dashboard/src/pixel-engine/types.ts +232 -0
  256. package/agent/dashboard/src/pixel-engine/wallTiles.ts +203 -0
  257. package/agent/dashboard/src/views/auth.tsx +249 -0
  258. package/agent/dashboard/src/views/fleet.tsx +263 -0
  259. package/agent/dashboard/src/views/network.tsx +106 -0
  260. package/agent/dashboard/src/views/schedule-types.ts +12 -0
  261. package/agent/dashboard/src/views/schedule-utils.ts +49 -0
  262. package/agent/dashboard/src/views/schedule.tsx +326 -0
  263. package/agent/dashboard/src/views/sessions/conversation-viewer.tsx +279 -0
  264. package/agent/dashboard/src/views/sessions/session-detail.tsx +48 -0
  265. package/agent/dashboard/src/views/sessions/session-list.tsx +265 -0
  266. package/agent/dashboard/src/views/sessions/terminal-pane.tsx +270 -0
  267. package/agent/dashboard/src/views/sessions.tsx +55 -0
  268. package/agent/dashboard/src/views/settings-config.tsx +265 -0
  269. package/agent/dashboard/src/views/settings-logs.tsx +99 -0
  270. package/agent/dashboard/src/views/settings-status.tsx +215 -0
  271. package/agent/dashboard/src/views/settings.tsx +324 -0
  272. package/agent/dashboard/src/views/webhooks.tsx +230 -0
  273. package/agent/dashboard/src/vite-env.d.ts +3 -0
  274. package/agent/dashboard/tsconfig.json +13 -0
  275. package/agent/entry.ts +168 -0
  276. package/agent/event-log.ts +103 -0
  277. package/agent/node-pty-adapter.ts +39 -0
  278. package/agent/paths.ts +12 -0
  279. package/agent/pty-manager.ts +265 -0
  280. package/agent/pty-types.ts +25 -0
  281. package/agent/routes/api.ts +149 -0
  282. package/agent/routes/config.ts +116 -0
  283. package/agent/routes/dashboard.ts +101 -0
  284. package/agent/routes/schedule.ts +84 -0
  285. package/agent/routes/sessions.ts +43 -0
  286. package/agent/routes/webhooks.ts +113 -0
  287. package/agent/scheduler.ts +373 -0
  288. package/agent/server-schema.ts +25 -0
  289. package/agent/server-utils.ts +163 -0
  290. package/agent/server.ts +218 -0
  291. package/agent/server.types.ts +39 -0
  292. package/agent/session-history-types.ts +78 -0
  293. package/agent/session-history-utils.ts +96 -0
  294. package/agent/session-history.ts +318 -0
  295. package/agent/session.ts +152 -0
  296. package/agent/tools/mecha-call.ts +106 -0
  297. package/agent/tools/mecha-fleet.ts +176 -0
  298. package/agent/tools/mecha-list.ts +56 -0
  299. package/agent/tools/mecha-server.ts +70 -0
  300. package/agent/types.ts +35 -0
  301. package/agent/webhook.ts +127 -0
  302. package/agent/ws-terminal.ts +174 -0
  303. package/dist/agent/activity.d.ts +14 -0
  304. package/dist/agent/activity.d.ts.map +1 -0
  305. package/dist/agent/activity.js +25 -0
  306. package/dist/agent/activity.js.map +1 -0
  307. package/dist/agent/character-config.test.d.ts +2 -0
  308. package/dist/agent/character-config.test.d.ts.map +1 -0
  309. package/dist/agent/character-config.test.js +51 -0
  310. package/dist/agent/character-config.test.js.map +1 -0
  311. package/dist/agent/costs.d.ts +16 -0
  312. package/dist/agent/costs.d.ts.map +1 -0
  313. package/dist/agent/costs.js +82 -0
  314. package/dist/agent/costs.js.map +1 -0
  315. package/dist/agent/dashboard/dist/assets/addon-fit-YJmn1quW.js +12 -0
  316. package/dist/agent/dashboard/dist/assets/addon-web-links-BWjmmSgS.js +12 -0
  317. package/dist/agent/dashboard/dist/assets/index-B4OKDQ7e.css +32 -0
  318. package/dist/agent/dashboard/dist/assets/index-fZ_N6Wsi.js +193 -0
  319. package/dist/agent/dashboard/dist/assets/xterm-BqvuqXEL.js +27 -0
  320. package/dist/agent/dashboard/dist/index.html +19 -0
  321. package/dist/agent/dashboard/dist/pixel-engine/characters/char_0.png +0 -0
  322. package/dist/agent/dashboard/dist/pixel-engine/characters/char_1.png +0 -0
  323. package/dist/agent/dashboard/dist/pixel-engine/characters/char_2.png +0 -0
  324. package/dist/agent/dashboard/dist/pixel-engine/characters/char_3.png +0 -0
  325. package/dist/agent/dashboard/dist/pixel-engine/characters/char_4.png +0 -0
  326. package/dist/agent/dashboard/dist/pixel-engine/characters/char_5.png +0 -0
  327. package/dist/agent/dashboard/dist/pixel-engine/default-layout.json +4320 -0
  328. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_0.png +0 -0
  329. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_1.png +0 -0
  330. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_2.png +0 -0
  331. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_3.png +0 -0
  332. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_4.png +0 -0
  333. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_5.png +0 -0
  334. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_6.png +0 -0
  335. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_7.png +0 -0
  336. package/dist/agent/dashboard/dist/pixel-engine/floors/floor_8.png +0 -0
  337. package/dist/agent/dashboard/dist/pixel-engine/fonts/FSPixelSansUnicode-Regular.ttf +0 -0
  338. package/dist/agent/dashboard/dist/pixel-engine/furniture/BIN/BIN.png +0 -0
  339. package/dist/agent/dashboard/dist/pixel-engine/furniture/BIN/manifest.json +13 -0
  340. package/dist/agent/dashboard/dist/pixel-engine/furniture/BLACKBOARD/BLACKBOARD.png +0 -0
  341. package/dist/agent/dashboard/dist/pixel-engine/furniture/BLACKBOARD/manifest.json +16 -0
  342. package/dist/agent/dashboard/dist/pixel-engine/furniture/BOOKSHELF/BOOKSHELF.png +0 -0
  343. package/dist/agent/dashboard/dist/pixel-engine/furniture/BOOKSHELF/manifest.json +16 -0
  344. package/dist/agent/dashboard/dist/pixel-engine/furniture/CACTUS/CACTUS.png +0 -0
  345. package/dist/agent/dashboard/dist/pixel-engine/furniture/CACTUS/manifest.json +13 -0
  346. package/dist/agent/dashboard/dist/pixel-engine/furniture/CLOCK/CLOCK.png +0 -0
  347. package/dist/agent/dashboard/dist/pixel-engine/furniture/CLOCK/manifest.json +13 -0
  348. package/dist/agent/dashboard/dist/pixel-engine/furniture/COFFEE/COFFEE.png +0 -0
  349. package/dist/agent/dashboard/dist/pixel-engine/furniture/COFFEE/manifest.json +13 -0
  350. package/dist/agent/dashboard/dist/pixel-engine/furniture/COFFEE_TABLE/COFFEE_TABLE.png +0 -0
  351. package/dist/agent/dashboard/dist/pixel-engine/furniture/COFFEE_TABLE/manifest.json +13 -0
  352. package/dist/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_BENCH/CUSHIONED_BENCH.png +0 -0
  353. package/dist/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_BENCH/manifest.json +13 -0
  354. package/dist/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_BACK.png +0 -0
  355. package/dist/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_FRONT.png +0 -0
  356. package/dist/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/CUSHIONED_CHAIR_SIDE.png +0 -0
  357. package/dist/agent/dashboard/dist/pixel-engine/furniture/CUSHIONED_CHAIR/manifest.json +44 -0
  358. package/dist/agent/dashboard/dist/pixel-engine/furniture/DESK/DESK_FRONT.png +0 -0
  359. package/dist/agent/dashboard/dist/pixel-engine/furniture/DESK/DESK_SIDE.png +0 -0
  360. package/dist/agent/dashboard/dist/pixel-engine/furniture/DESK/manifest.json +33 -0
  361. package/dist/agent/dashboard/dist/pixel-engine/furniture/DOUBLE_BOOKSHELF/DOUBLE_BOOKSHELF.png +0 -0
  362. package/dist/agent/dashboard/dist/pixel-engine/furniture/DOUBLE_BOOKSHELF/manifest.json +16 -0
  363. package/dist/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_1/FILE_BOXES_1.png +0 -0
  364. package/dist/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_1/manifest.json +13 -0
  365. package/dist/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_2/FILE_BOXES_2.png +0 -0
  366. package/dist/agent/dashboard/dist/pixel-engine/furniture/FILE_BOXES_2/manifest.json +13 -0
  367. package/dist/agent/dashboard/dist/pixel-engine/furniture/HANGING_PLANT/HANGING_PLANT.png +0 -0
  368. package/dist/agent/dashboard/dist/pixel-engine/furniture/HANGING_PLANT/manifest.json +13 -0
  369. package/dist/agent/dashboard/dist/pixel-engine/furniture/LARGE_PAINTING/LARGE_PAINTING.png +0 -0
  370. package/dist/agent/dashboard/dist/pixel-engine/furniture/LARGE_PAINTING/manifest.json +13 -0
  371. package/dist/agent/dashboard/dist/pixel-engine/furniture/LARGE_PLANT/LARGE_PLANT.png +0 -0
  372. package/dist/agent/dashboard/dist/pixel-engine/furniture/LARGE_PLANT/manifest.json +13 -0
  373. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/PC_BACK.png +0 -0
  374. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_OFF.png +0 -0
  375. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_ON_1.png +0 -0
  376. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_ON_2.png +0 -0
  377. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/PC_FRONT_ON_3.png +0 -0
  378. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/PC_SIDE.png +0 -0
  379. package/dist/agent/dashboard/dist/pixel-engine/furniture/PC/manifest.json +88 -0
  380. package/dist/agent/dashboard/dist/pixel-engine/furniture/PLANT/PLANT.png +0 -0
  381. package/dist/agent/dashboard/dist/pixel-engine/furniture/PLANT/manifest.json +13 -0
  382. package/dist/agent/dashboard/dist/pixel-engine/furniture/PLANT_2/PLANT_2.png +0 -0
  383. package/dist/agent/dashboard/dist/pixel-engine/furniture/PLANT_2/manifest.json +13 -0
  384. package/dist/agent/dashboard/dist/pixel-engine/furniture/POT/POT.png +0 -0
  385. package/dist/agent/dashboard/dist/pixel-engine/furniture/POT/manifest.json +13 -0
  386. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING/SMALL_PAINTING.png +0 -0
  387. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING/manifest.json +13 -0
  388. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING_2/SMALL_PAINTING_2.png +0 -0
  389. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_PAINTING_2/manifest.json +13 -0
  390. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_TABLE/SMALL_TABLE_FRONT.png +0 -0
  391. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_TABLE/SMALL_TABLE_SIDE.png +0 -0
  392. package/dist/agent/dashboard/dist/pixel-engine/furniture/SMALL_TABLE/manifest.json +33 -0
  393. package/dist/agent/dashboard/dist/pixel-engine/furniture/SOFA/SOFA_BACK.png +0 -0
  394. package/dist/agent/dashboard/dist/pixel-engine/furniture/SOFA/SOFA_FRONT.png +0 -0
  395. package/dist/agent/dashboard/dist/pixel-engine/furniture/SOFA/SOFA_SIDE.png +0 -0
  396. package/dist/agent/dashboard/dist/pixel-engine/furniture/SOFA/manifest.json +44 -0
  397. package/dist/agent/dashboard/dist/pixel-engine/furniture/TABLE_FRONT/TABLE_FRONT.png +0 -0
  398. package/dist/agent/dashboard/dist/pixel-engine/furniture/TABLE_FRONT/manifest.json +13 -0
  399. package/dist/agent/dashboard/dist/pixel-engine/furniture/VENDER_MACHINE/VENDER_MACHINE.png +0 -0
  400. package/dist/agent/dashboard/dist/pixel-engine/furniture/VENDER_MACHINE/manifest.json +16 -0
  401. package/dist/agent/dashboard/dist/pixel-engine/furniture/WATER_MACHINE/WATER_MACHINE.png +0 -0
  402. package/dist/agent/dashboard/dist/pixel-engine/furniture/WATER_MACHINE/manifest.json +16 -0
  403. package/dist/agent/dashboard/dist/pixel-engine/furniture/WHITEBOARD/WHITEBOARD.png +0 -0
  404. package/dist/agent/dashboard/dist/pixel-engine/furniture/WHITEBOARD/manifest.json +16 -0
  405. package/dist/agent/dashboard/dist/pixel-engine/furniture/WOODEN_BENCH/WOODEN_BENCH.png +0 -0
  406. package/dist/agent/dashboard/dist/pixel-engine/furniture/WOODEN_BENCH/manifest.json +13 -0
  407. package/dist/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_BACK.png +0 -0
  408. package/dist/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_FRONT.png +0 -0
  409. package/dist/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/WOODEN_CHAIR_SIDE.png +0 -0
  410. package/dist/agent/dashboard/dist/pixel-engine/furniture/WOODEN_CHAIR/manifest.json +44 -0
  411. package/dist/agent/dashboard/dist/pixel-engine/furniture/index.json +32 -0
  412. package/dist/agent/dashboard/dist/pixel-engine/walls/wall_0.png +0 -0
  413. package/dist/agent/entry.d.ts +2 -0
  414. package/dist/agent/entry.d.ts.map +1 -0
  415. package/dist/agent/entry.js +157 -0
  416. package/dist/agent/entry.js.map +1 -0
  417. package/dist/agent/event-log.d.ts +11 -0
  418. package/dist/agent/event-log.d.ts.map +1 -0
  419. package/dist/agent/event-log.js +102 -0
  420. package/dist/agent/event-log.js.map +1 -0
  421. package/dist/agent/node-pty-adapter.d.ts +4 -0
  422. package/dist/agent/node-pty-adapter.d.ts.map +1 -0
  423. package/dist/agent/node-pty-adapter.js +35 -0
  424. package/dist/agent/node-pty-adapter.js.map +1 -0
  425. package/dist/agent/paths.d.ts +11 -0
  426. package/dist/agent/paths.d.ts.map +1 -0
  427. package/dist/agent/paths.js +12 -0
  428. package/dist/agent/paths.js.map +1 -0
  429. package/dist/agent/pty-manager.d.ts +34 -0
  430. package/dist/agent/pty-manager.d.ts.map +1 -0
  431. package/dist/agent/pty-manager.js +210 -0
  432. package/dist/agent/pty-manager.js.map +1 -0
  433. package/dist/agent/pty-types.d.ts +26 -0
  434. package/dist/agent/pty-types.d.ts.map +1 -0
  435. package/dist/agent/pty-types.js +2 -0
  436. package/dist/agent/pty-types.js.map +1 -0
  437. package/dist/agent/routes/api.d.ts +17 -0
  438. package/dist/agent/routes/api.d.ts.map +1 -0
  439. package/dist/agent/routes/api.js +125 -0
  440. package/dist/agent/routes/api.js.map +1 -0
  441. package/dist/agent/routes/config.d.ts +6 -0
  442. package/dist/agent/routes/config.d.ts.map +1 -0
  443. package/dist/agent/routes/config.js +116 -0
  444. package/dist/agent/routes/config.js.map +1 -0
  445. package/dist/agent/routes/dashboard.d.ts +4 -0
  446. package/dist/agent/routes/dashboard.d.ts.map +1 -0
  447. package/dist/agent/routes/dashboard.js +97 -0
  448. package/dist/agent/routes/dashboard.js.map +1 -0
  449. package/dist/agent/routes/schedule.d.ts +4 -0
  450. package/dist/agent/routes/schedule.d.ts.map +1 -0
  451. package/dist/agent/routes/schedule.js +98 -0
  452. package/dist/agent/routes/schedule.js.map +1 -0
  453. package/dist/agent/routes/sessions.d.ts +4 -0
  454. package/dist/agent/routes/sessions.d.ts.map +1 -0
  455. package/dist/agent/routes/sessions.js +43 -0
  456. package/dist/agent/routes/sessions.js.map +1 -0
  457. package/dist/agent/routes/webhooks.d.ts +5 -0
  458. package/dist/agent/routes/webhooks.d.ts.map +1 -0
  459. package/dist/agent/routes/webhooks.js +102 -0
  460. package/dist/agent/routes/webhooks.js.map +1 -0
  461. package/dist/agent/scheduler.d.ts +50 -0
  462. package/dist/agent/scheduler.d.ts.map +1 -0
  463. package/dist/agent/scheduler.js +332 -0
  464. package/dist/agent/scheduler.js.map +1 -0
  465. package/dist/agent/server-schema.d.ts +20 -0
  466. package/dist/agent/server-schema.d.ts.map +1 -0
  467. package/dist/agent/server-schema.js +20 -0
  468. package/dist/agent/server-schema.js.map +1 -0
  469. package/dist/agent/server-utils.d.ts +18 -0
  470. package/dist/agent/server-utils.d.ts.map +1 -0
  471. package/dist/agent/server-utils.js +132 -0
  472. package/dist/agent/server-utils.js.map +1 -0
  473. package/dist/agent/server.d.ts +17 -0
  474. package/dist/agent/server.d.ts.map +1 -0
  475. package/dist/agent/server.js +196 -0
  476. package/dist/agent/server.js.map +1 -0
  477. package/dist/agent/server.types.d.ts +38 -0
  478. package/dist/agent/server.types.d.ts.map +1 -0
  479. package/dist/agent/server.types.js +2 -0
  480. package/dist/agent/server.types.js.map +1 -0
  481. package/dist/agent/session-history-types.d.ts +74 -0
  482. package/dist/agent/session-history-types.d.ts.map +1 -0
  483. package/dist/agent/session-history-types.js +2 -0
  484. package/dist/agent/session-history-types.js.map +1 -0
  485. package/dist/agent/session-history-utils.d.ts +13 -0
  486. package/dist/agent/session-history-utils.d.ts.map +1 -0
  487. package/dist/agent/session-history-utils.js +102 -0
  488. package/dist/agent/session-history-utils.js.map +1 -0
  489. package/dist/agent/session-history.d.ts +20 -0
  490. package/dist/agent/session-history.d.ts.map +1 -0
  491. package/dist/agent/session-history.js +282 -0
  492. package/dist/agent/session-history.js.map +1 -0
  493. package/dist/agent/session.d.ts +51 -0
  494. package/dist/agent/session.d.ts.map +1 -0
  495. package/dist/agent/session.js +135 -0
  496. package/dist/agent/session.js.map +1 -0
  497. package/dist/agent/tools/mecha-call.d.ts +2 -0
  498. package/dist/agent/tools/mecha-call.d.ts.map +1 -0
  499. package/dist/agent/tools/mecha-call.js +101 -0
  500. package/dist/agent/tools/mecha-call.js.map +1 -0
  501. package/dist/agent/tools/mecha-fleet.d.ts +25 -0
  502. package/dist/agent/tools/mecha-fleet.d.ts.map +1 -0
  503. package/dist/agent/tools/mecha-fleet.js +144 -0
  504. package/dist/agent/tools/mecha-fleet.js.map +1 -0
  505. package/dist/agent/tools/mecha-list.d.ts +6 -0
  506. package/dist/agent/tools/mecha-list.d.ts.map +1 -0
  507. package/dist/agent/tools/mecha-list.js +46 -0
  508. package/dist/agent/tools/mecha-list.js.map +1 -0
  509. package/dist/agent/tools/mecha-server.d.ts +4 -0
  510. package/dist/agent/tools/mecha-server.d.ts.map +1 -0
  511. package/dist/agent/tools/mecha-server.js +49 -0
  512. package/dist/agent/tools/mecha-server.js.map +1 -0
  513. package/dist/agent/types.d.ts +38 -0
  514. package/dist/agent/types.d.ts.map +1 -0
  515. package/dist/agent/types.js +32 -0
  516. package/dist/agent/types.js.map +1 -0
  517. package/dist/agent/webhook.d.ts +12 -0
  518. package/dist/agent/webhook.d.ts.map +1 -0
  519. package/dist/agent/webhook.js +105 -0
  520. package/dist/agent/webhook.js.map +1 -0
  521. package/dist/agent/ws-terminal.d.ts +4 -0
  522. package/dist/agent/ws-terminal.d.ts.map +1 -0
  523. package/dist/agent/ws-terminal.js +160 -0
  524. package/dist/agent/ws-terminal.js.map +1 -0
  525. package/dist/shared/atomic-write.d.ts +5 -0
  526. package/dist/shared/atomic-write.d.ts.map +1 -0
  527. package/dist/shared/atomic-write.js +63 -0
  528. package/dist/shared/atomic-write.js.map +1 -0
  529. package/dist/shared/errors.d.ts +71 -0
  530. package/dist/shared/errors.d.ts.map +1 -0
  531. package/dist/shared/errors.js +52 -0
  532. package/dist/shared/errors.js.map +1 -0
  533. package/dist/shared/logger.d.ts +7 -0
  534. package/dist/shared/logger.d.ts.map +1 -0
  535. package/dist/shared/logger.js +52 -0
  536. package/dist/shared/logger.js.map +1 -0
  537. package/dist/shared/mutex.d.ts +12 -0
  538. package/dist/shared/mutex.d.ts.map +1 -0
  539. package/dist/shared/mutex.js +73 -0
  540. package/dist/shared/mutex.js.map +1 -0
  541. package/dist/shared/safe-read.d.ts +12 -0
  542. package/dist/shared/safe-read.d.ts.map +1 -0
  543. package/dist/shared/safe-read.js +33 -0
  544. package/dist/shared/safe-read.js.map +1 -0
  545. package/dist/shared/totp.d.ts +7 -0
  546. package/dist/shared/totp.d.ts.map +1 -0
  547. package/dist/shared/totp.js +75 -0
  548. package/dist/shared/totp.js.map +1 -0
  549. package/dist/shared/validation.d.ts +7 -0
  550. package/dist/shared/validation.d.ts.map +1 -0
  551. package/dist/shared/validation.js +30 -0
  552. package/dist/shared/validation.js.map +1 -0
  553. package/dist/src/auth.d.ts +48 -0
  554. package/dist/src/auth.d.ts.map +1 -0
  555. package/dist/src/auth.js +160 -0
  556. package/dist/src/auth.js.map +1 -0
  557. package/dist/src/cli-output.d.ts +14 -0
  558. package/dist/src/cli-output.d.ts.map +1 -0
  559. package/dist/src/cli-output.js +47 -0
  560. package/dist/src/cli-output.js.map +1 -0
  561. package/dist/src/cli-utils.d.ts +15 -0
  562. package/dist/src/cli-utils.d.ts.map +1 -0
  563. package/dist/src/cli-utils.js +241 -0
  564. package/dist/src/cli-utils.js.map +1 -0
  565. package/dist/src/cli.d.ts +3 -0
  566. package/dist/src/cli.d.ts.map +1 -0
  567. package/dist/src/cli.js +535 -0
  568. package/dist/src/cli.js.map +1 -0
  569. package/dist/src/cli.utils.d.ts +10 -0
  570. package/dist/src/cli.utils.d.ts.map +1 -0
  571. package/dist/src/cli.utils.js +127 -0
  572. package/dist/src/cli.utils.js.map +1 -0
  573. package/dist/src/commands/auth.d.ts +3 -0
  574. package/dist/src/commands/auth.d.ts.map +1 -0
  575. package/dist/src/commands/auth.js +139 -0
  576. package/dist/src/commands/auth.js.map +1 -0
  577. package/dist/src/commands/bot-api.d.ts +15 -0
  578. package/dist/src/commands/bot-api.d.ts.map +1 -0
  579. package/dist/src/commands/bot-api.js +40 -0
  580. package/dist/src/commands/bot-api.js.map +1 -0
  581. package/dist/src/commands/completion.d.ts +3 -0
  582. package/dist/src/commands/completion.d.ts.map +1 -0
  583. package/dist/src/commands/completion.js +108 -0
  584. package/dist/src/commands/completion.js.map +1 -0
  585. package/dist/src/commands/config.d.ts +3 -0
  586. package/dist/src/commands/config.d.ts.map +1 -0
  587. package/dist/src/commands/config.js +110 -0
  588. package/dist/src/commands/config.js.map +1 -0
  589. package/dist/src/commands/costs.d.ts +3 -0
  590. package/dist/src/commands/costs.d.ts.map +1 -0
  591. package/dist/src/commands/costs.js +88 -0
  592. package/dist/src/commands/costs.js.map +1 -0
  593. package/dist/src/commands/daemon.d.ts +3 -0
  594. package/dist/src/commands/daemon.d.ts.map +1 -0
  595. package/dist/src/commands/daemon.js +86 -0
  596. package/dist/src/commands/daemon.js.map +1 -0
  597. package/dist/src/commands/push-dashboard.d.ts +3 -0
  598. package/dist/src/commands/push-dashboard.d.ts.map +1 -0
  599. package/dist/src/commands/push-dashboard.js +48 -0
  600. package/dist/src/commands/push-dashboard.js.map +1 -0
  601. package/dist/src/commands/schedule.d.ts +3 -0
  602. package/dist/src/commands/schedule.d.ts.map +1 -0
  603. package/dist/src/commands/schedule.js +70 -0
  604. package/dist/src/commands/schedule.js.map +1 -0
  605. package/dist/src/commands/sessions.d.ts +3 -0
  606. package/dist/src/commands/sessions.d.ts.map +1 -0
  607. package/dist/src/commands/sessions.js +62 -0
  608. package/dist/src/commands/sessions.js.map +1 -0
  609. package/dist/src/commands/webhooks.d.ts +3 -0
  610. package/dist/src/commands/webhooks.d.ts.map +1 -0
  611. package/dist/src/commands/webhooks.js +44 -0
  612. package/dist/src/commands/webhooks.js.map +1 -0
  613. package/dist/src/config.d.ts +9 -0
  614. package/dist/src/config.d.ts.map +1 -0
  615. package/dist/src/config.js +56 -0
  616. package/dist/src/config.js.map +1 -0
  617. package/dist/src/daemon-audit.d.ts +13 -0
  618. package/dist/src/daemon-audit.d.ts.map +1 -0
  619. package/dist/src/daemon-audit.js +33 -0
  620. package/dist/src/daemon-audit.js.map +1 -0
  621. package/dist/src/daemon.d.ts +25 -0
  622. package/dist/src/daemon.d.ts.map +1 -0
  623. package/dist/src/daemon.js +344 -0
  624. package/dist/src/daemon.js.map +1 -0
  625. package/dist/src/dashboard-server-schema.d.ts +23 -0
  626. package/dist/src/dashboard-server-schema.d.ts.map +1 -0
  627. package/dist/src/dashboard-server-schema.js +45 -0
  628. package/dist/src/dashboard-server-schema.js.map +1 -0
  629. package/dist/src/dashboard-server-utils.d.ts +18 -0
  630. package/dist/src/dashboard-server-utils.d.ts.map +1 -0
  631. package/dist/src/dashboard-server-utils.js +107 -0
  632. package/dist/src/dashboard-server-utils.js.map +1 -0
  633. package/dist/src/dashboard-server.d.ts +2 -0
  634. package/dist/src/dashboard-server.d.ts.map +1 -0
  635. package/dist/src/dashboard-server.js +777 -0
  636. package/dist/src/dashboard-server.js.map +1 -0
  637. package/dist/src/docker.constants.d.ts +5 -0
  638. package/dist/src/docker.constants.d.ts.map +1 -0
  639. package/dist/src/docker.constants.js +7 -0
  640. package/dist/src/docker.constants.js.map +1 -0
  641. package/dist/src/docker.d.ts +16 -0
  642. package/dist/src/docker.d.ts.map +1 -0
  643. package/dist/src/docker.js +437 -0
  644. package/dist/src/docker.js.map +1 -0
  645. package/dist/src/docker.types.d.ts +13 -0
  646. package/dist/src/docker.types.d.ts.map +1 -0
  647. package/dist/src/docker.types.js +2 -0
  648. package/dist/src/docker.types.js.map +1 -0
  649. package/dist/src/docker.utils.d.ts +24 -0
  650. package/dist/src/docker.utils.d.ts.map +1 -0
  651. package/dist/src/docker.utils.js +239 -0
  652. package/dist/src/docker.utils.js.map +1 -0
  653. package/dist/src/doctor.d.ts +3 -0
  654. package/dist/src/doctor.d.ts.map +1 -0
  655. package/dist/src/doctor.js +80 -0
  656. package/dist/src/doctor.js.map +1 -0
  657. package/dist/src/doctor.utils.d.ts +30 -0
  658. package/dist/src/doctor.utils.d.ts.map +1 -0
  659. package/dist/src/doctor.utils.js +192 -0
  660. package/dist/src/doctor.utils.js.map +1 -0
  661. package/dist/src/mcp-proxy.d.ts +2 -0
  662. package/dist/src/mcp-proxy.d.ts.map +1 -0
  663. package/dist/src/mcp-proxy.js +177 -0
  664. package/dist/src/mcp-proxy.js.map +1 -0
  665. package/dist/src/resolve-endpoint.d.ts +13 -0
  666. package/dist/src/resolve-endpoint.d.ts.map +1 -0
  667. package/dist/src/resolve-endpoint.js +112 -0
  668. package/dist/src/resolve-endpoint.js.map +1 -0
  669. package/dist/src/store.d.ts +41 -0
  670. package/dist/src/store.d.ts.map +1 -0
  671. package/dist/src/store.js +263 -0
  672. package/dist/src/store.js.map +1 -0
  673. package/package.json +84 -0
  674. package/s6/mecha-agent/dependencies.d/tailscale-up +0 -0
  675. package/s6/mecha-agent/finish +4 -0
  676. package/s6/mecha-agent/run +39 -0
  677. package/s6/mecha-agent/type +1 -0
  678. package/s6/tailscale-up/dependencies.d/tailscaled +0 -0
  679. package/s6/tailscale-up/type +1 -0
  680. package/s6/tailscale-up/up +39 -0
  681. package/s6/tailscaled/run +14 -0
  682. package/s6/tailscaled/type +1 -0
  683. package/shared/atomic-write.ts +58 -0
  684. package/shared/errors.ts +137 -0
  685. package/shared/logger.ts +50 -0
  686. package/shared/mutex.ts +73 -0
  687. package/shared/safe-read.ts +52 -0
  688. package/shared/totp.ts +83 -0
  689. package/shared/validation.ts +29 -0
  690. package/tsconfig.agent.json +10 -0
  691. package/tsconfig.json +22 -0
@@ -0,0 +1,326 @@
1
+ import { useState, useEffect, useCallback, useRef } from "react";
2
+ import { botFetch } from "../lib/api";
3
+ import type { ScheduleEntry } from "./schedule-types";
4
+ import { CRON_PRESETS, cronToHuman, timeUntil } from "./schedule-utils";
5
+ import { Alert, Button, Card, Dialog, DialogFooter, Input, StatusBadge, Textarea } from "../components";
6
+
7
+ export default function Schedule() {
8
+ const [entries, setEntries] = useState<ScheduleEntry[]>([]);
9
+ const [error, setError] = useState<string | null>(null);
10
+ const [showAdd, setShowAdd] = useState(false);
11
+ const [editingId, setEditingId] = useState<string | null>(null);
12
+ const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null);
13
+ const [, setTick] = useState(0);
14
+
15
+ // Form state
16
+ const [formCron, setFormCron] = useState("");
17
+ const [formPrompt, setFormPrompt] = useState("");
18
+ const [formBusy, setFormBusy] = useState(false);
19
+ const [formError, setFormError] = useState<string | null>(null);
20
+
21
+ const pollRef = useRef<ReturnType<typeof setInterval>>(undefined);
22
+
23
+ const refresh = useCallback(() => {
24
+ botFetch("/api/schedule")
25
+ .then((r) => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.json(); })
26
+ .then((data) => { setEntries(data as ScheduleEntry[]); setError(null); })
27
+ .catch((err) => setError(err instanceof Error ? err.message : "Failed to load schedule"));
28
+ }, []);
29
+
30
+ useEffect(() => {
31
+ refresh();
32
+ pollRef.current = setInterval(refresh, 10_000);
33
+ return () => clearInterval(pollRef.current);
34
+ }, [refresh]);
35
+
36
+ // Countdown ticker
37
+ useEffect(() => {
38
+ const timer = setInterval(() => setTick((t) => t + 1), 1000);
39
+ return () => clearInterval(timer);
40
+ }, []);
41
+
42
+ function resetForm() {
43
+ setFormCron("");
44
+ setFormPrompt("");
45
+ setFormError(null);
46
+ setShowAdd(false);
47
+ setEditingId(null);
48
+ }
49
+
50
+ async function handleAdd() {
51
+ if (!formCron.trim() || !formPrompt.trim()) { setFormError("Cron and prompt are required"); return; }
52
+ setFormBusy(true);
53
+ setFormError(null);
54
+ try {
55
+ const resp = await botFetch("/api/schedule", {
56
+ method: "POST",
57
+ headers: { "Content-Type": "application/json" },
58
+ body: JSON.stringify({ cron: formCron.trim(), prompt: formPrompt.trim() }),
59
+ });
60
+ const data = await resp.json() as Record<string, unknown>;
61
+ if (!resp.ok) { setFormError(String(data.error ?? "Failed to create")); return; }
62
+ resetForm();
63
+ refresh();
64
+ } catch { setFormError("Network error"); }
65
+ finally { setFormBusy(false); }
66
+ }
67
+
68
+ async function handleUpdate(id: string) {
69
+ if (!formCron.trim() || !formPrompt.trim()) { setFormError("Cron and prompt are required"); return; }
70
+ setFormBusy(true);
71
+ setFormError(null);
72
+ try {
73
+ const resp = await botFetch(`/api/schedule/${encodeURIComponent(id)}`, {
74
+ method: "PUT",
75
+ headers: { "Content-Type": "application/json" },
76
+ body: JSON.stringify({ cron: formCron.trim(), prompt: formPrompt.trim() }),
77
+ });
78
+ const data = await resp.json() as Record<string, unknown>;
79
+ if (!resp.ok) { setFormError(String(data.error ?? "Failed to update")); return; }
80
+ resetForm();
81
+ refresh();
82
+ } catch { setFormError("Network error"); }
83
+ finally { setFormBusy(false); }
84
+ }
85
+
86
+ async function handleDelete(id: string) {
87
+ try {
88
+ const resp = await botFetch(`/api/schedule/${encodeURIComponent(id)}`, { method: "DELETE" });
89
+ if (!resp.ok) {
90
+ const data = await resp.json() as Record<string, unknown>;
91
+ setError(String(data.error ?? "Delete failed"));
92
+ return;
93
+ }
94
+ setDeleteConfirm(null);
95
+ refresh();
96
+ } catch { setError("Network error"); }
97
+ }
98
+
99
+ async function handleToggle(entry: ScheduleEntry) {
100
+ const action = entry.status === "active" ? "pause" : "resume";
101
+ try {
102
+ const resp = await botFetch(`/api/schedule/${encodeURIComponent(entry.id)}/${action}`, { method: "POST" });
103
+ if (!resp.ok) {
104
+ const data = await resp.json() as Record<string, unknown>;
105
+ setError(String(data.error ?? `${action} failed`));
106
+ return;
107
+ }
108
+ refresh();
109
+ } catch { setError("Network error"); }
110
+ }
111
+
112
+ async function handleTrigger(id: string) {
113
+ try {
114
+ const resp = await botFetch(`/api/schedule/trigger/${encodeURIComponent(id)}`, { method: "POST" });
115
+ if (!resp.ok) {
116
+ const data = await resp.json() as Record<string, unknown>;
117
+ setError(String(data.error ?? "Trigger failed"));
118
+ return;
119
+ }
120
+ refresh();
121
+ } catch { setError("Network error"); }
122
+ }
123
+
124
+ function startEdit(entry: ScheduleEntry) {
125
+ setEditingId(entry.id);
126
+ setFormCron(entry.cron);
127
+ setFormPrompt(entry.prompt);
128
+ setFormError(null);
129
+ setShowAdd(false);
130
+ }
131
+
132
+ function startAdd() {
133
+ setShowAdd(true);
134
+ setEditingId(null);
135
+ setFormCron("");
136
+ setFormPrompt("");
137
+ setFormError(null);
138
+ }
139
+
140
+ const isEditing = editingId !== null;
141
+
142
+ return (
143
+ <div className="p-6 space-y-4 max-w-4xl mx-auto h-full overflow-y-auto">
144
+ <div className="flex items-center justify-between mb-2">
145
+ <h2 className="text-lg font-semibold text-foreground">Schedule</h2>
146
+ <Button onClick={startAdd} disabled={showAdd || isEditing}>
147
+ + Add Task
148
+ </Button>
149
+ </div>
150
+
151
+ {error && (
152
+ <Alert variant="error" onDismiss={() => setError(null)}>
153
+ {error}
154
+ </Alert>
155
+ )}
156
+
157
+ {/* Add / Edit form */}
158
+ {(showAdd || isEditing) && (
159
+ <Card spacing={3}>
160
+ <h3 className="text-sm font-medium text-foreground">
161
+ {isEditing ? "Edit Schedule Entry" : "New Schedule Entry"}
162
+ </h3>
163
+
164
+ {/* Cron presets */}
165
+ <div className="flex flex-wrap gap-1.5">
166
+ {CRON_PRESETS.map((p) => (
167
+ <button
168
+ key={p.cron}
169
+ onClick={() => setFormCron(p.cron)}
170
+ className={`text-xs px-2 py-1 rounded-md border transition-colors ${
171
+ formCron === p.cron
172
+ ? "border-primary bg-primary/10 text-primary"
173
+ : "border-border text-muted-foreground hover:border-primary/50"
174
+ }`}
175
+ >
176
+ {p.label}
177
+ </button>
178
+ ))}
179
+ </div>
180
+
181
+ <div>
182
+ <label className="text-xs text-muted-foreground block mb-1">Cron Expression (5 fields)</label>
183
+ <Input
184
+ mono
185
+ value={formCron}
186
+ onChange={(e) => setFormCron(e.target.value)}
187
+ placeholder="*/15 * * * *"
188
+ className="w-full"
189
+ />
190
+ {formCron && (
191
+ <div className="text-xs text-muted-foreground mt-1">{cronToHuman(formCron)}</div>
192
+ )}
193
+ </div>
194
+
195
+ <div>
196
+ <label className="text-xs text-muted-foreground block mb-1">Prompt</label>
197
+ <Textarea
198
+ value={formPrompt}
199
+ onChange={(e) => setFormPrompt(e.target.value)}
200
+ placeholder="What should the bot do on this schedule?"
201
+ rows={3}
202
+ className="w-full"
203
+ />
204
+ </div>
205
+
206
+ {formError && (
207
+ <Alert variant="error">{formError}</Alert>
208
+ )}
209
+
210
+ <div className="flex gap-2 justify-end">
211
+ <Button variant="secondary" onClick={resetForm}>
212
+ Cancel
213
+ </Button>
214
+ <Button
215
+ onClick={() => isEditing ? handleUpdate(editingId!) : handleAdd()}
216
+ disabled={formBusy || !formCron.trim() || !formPrompt.trim()}
217
+ >
218
+ {formBusy ? "Saving..." : isEditing ? "Update" : "Create"}
219
+ </Button>
220
+ </div>
221
+ </Card>
222
+ )}
223
+
224
+ {/* Entry list */}
225
+ {entries.length === 0 && !showAdd && (
226
+ <p className="text-muted-foreground text-sm">No scheduled tasks. Click "Add Task" to create one.</p>
227
+ )}
228
+
229
+ {entries.map((e) => (
230
+ <Card key={e.id}>
231
+ {/* Header row */}
232
+ <div className="flex items-center justify-between mb-2">
233
+ <div className="flex items-center gap-2">
234
+ <code className="text-primary text-sm">{e.cron}</code>
235
+ <span className="text-xs text-muted-foreground">{cronToHuman(e.cron)}</span>
236
+ <StatusBadge variant={e.status === "active" ? "success" : "warning"}>
237
+ {e.status}
238
+ </StatusBadge>
239
+ {e.consecutiveErrors >= 5 && (
240
+ <StatusBadge variant="error">
241
+ auto-paused
242
+ </StatusBadge>
243
+ )}
244
+ </div>
245
+
246
+ {/* Action buttons */}
247
+ <div className="flex items-center gap-1.5">
248
+ <Button
249
+ variant="ghost"
250
+ size="xs"
251
+ onClick={() => handleToggle(e)}
252
+ title={e.status === "active" ? "Pause" : "Resume"}
253
+ >
254
+ {e.status === "active" ? "Pause" : "Resume"}
255
+ </Button>
256
+ <Button
257
+ variant="ghost"
258
+ size="xs"
259
+ onClick={() => handleTrigger(e.id)}
260
+ title="Run now"
261
+ >
262
+ Trigger
263
+ </Button>
264
+ <Button
265
+ variant="ghost"
266
+ size="xs"
267
+ onClick={() => startEdit(e)}
268
+ title="Edit"
269
+ >
270
+ Edit
271
+ </Button>
272
+ <Button
273
+ variant="ghost-destructive"
274
+ size="xs"
275
+ onClick={() => setDeleteConfirm(e.id)}
276
+ title="Delete"
277
+ >
278
+ Delete
279
+ </Button>
280
+ </div>
281
+ </div>
282
+
283
+ {/* Prompt */}
284
+ <p className="text-sm text-foreground mb-2 whitespace-pre-wrap break-words">
285
+ {e.prompt.length > 200 ? e.prompt.slice(0, 200) + "..." : e.prompt}
286
+ </p>
287
+
288
+ {/* Stats row */}
289
+ <div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
290
+ {e.nextRunAt && e.status === "active" && (
291
+ <span>Next: <span className="text-foreground">{timeUntil(e.nextRunAt)}</span></span>
292
+ )}
293
+ {e.lastRunAt && (
294
+ <span>Last: {new Date(e.lastRunAt).toLocaleString()}</span>
295
+ )}
296
+ <span>Runs: {e.runCount} (today: {e.runsToday})</span>
297
+ {e.lastResult && (
298
+ <span className={e.lastResult === "error" ? "text-destructive" : e.lastResult === "success" ? "text-green-600 dark:text-green-400" : ""}>
299
+ Last result: {e.lastResult}
300
+ </span>
301
+ )}
302
+ {e.consecutiveErrors > 0 && (
303
+ <span className="text-destructive">Consecutive errors: {e.consecutiveErrors}</span>
304
+ )}
305
+ </div>
306
+ </Card>
307
+ ))}
308
+
309
+ {/* Delete confirmation dialog */}
310
+ <Dialog
311
+ open={deleteConfirm !== null}
312
+ title="Delete Schedule Entry"
313
+ description="This will permanently remove this scheduled task. Are you sure?"
314
+ >
315
+ <DialogFooter>
316
+ <Button variant="secondary" size="lg" onClick={() => setDeleteConfirm(null)}>
317
+ Cancel
318
+ </Button>
319
+ <Button variant="destructive" size="lg" onClick={() => handleDelete(deleteConfirm!)}>
320
+ Delete
321
+ </Button>
322
+ </DialogFooter>
323
+ </Dialog>
324
+ </div>
325
+ );
326
+ }
@@ -0,0 +1,279 @@
1
+ import { useState, useEffect, useRef, useMemo, useCallback } from "react";
2
+ import { botFetch } from "../../lib/api";
3
+ import { sanitizeMarkdown } from "../../lib/sanitize";
4
+ import { formatToolLabel } from "../../lib/format";
5
+
6
+ // --- Copy button ---
7
+
8
+ function CopyButton({ text }: { text: string }) {
9
+ const [copied, setCopied] = useState(false);
10
+
11
+ const handleCopy = useCallback(() => {
12
+ navigator.clipboard.writeText(text).then(() => {
13
+ setCopied(true);
14
+ setTimeout(() => setCopied(false), 1500);
15
+ }).catch(() => {
16
+ // Clipboard API may fail in non-HTTPS or unfocused contexts — ignore silently
17
+ });
18
+ }, [text]);
19
+
20
+ return (
21
+ <button
22
+ onClick={handleCopy}
23
+ className="opacity-0 group-hover:opacity-100 p-1 rounded transition-opacity text-muted-foreground hover:text-foreground"
24
+ title="Copy to clipboard"
25
+ >
26
+ {copied ? (
27
+ <svg className="w-4 h-4 text-success" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
28
+ <path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
29
+ </svg>
30
+ ) : (
31
+ <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
32
+ <path strokeLinecap="round" strokeLinejoin="round" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
33
+ </svg>
34
+ )}
35
+ </button>
36
+ );
37
+ }
38
+
39
+ interface ConversationMessage {
40
+ role: "user" | "assistant" | "tool_use" | "tool_result";
41
+ content: string;
42
+ timestamp: string;
43
+ toolName?: string;
44
+ toolInput?: unknown;
45
+ toolUseId?: string;
46
+ toolResultContent?: string;
47
+ model?: string;
48
+ thinkingContent?: string;
49
+ tokensIn?: number;
50
+ tokensOut?: number;
51
+ }
52
+
53
+ interface SessionDetail {
54
+ id: string;
55
+ messages: ConversationMessage[];
56
+ totalCostUsd: number;
57
+ model: string;
58
+ }
59
+
60
+ // --- Markdown renderer with DOMPurify sanitization ---
61
+
62
+ function MarkdownContent({ text, variant }: { text: string; variant?: "user" | "assistant" }) {
63
+ const html = useMemo(() => sanitizeMarkdown(text), [text]);
64
+ return (
65
+ <div
66
+ className={`prose prose-sm max-w-none
67
+ ${variant === "user" ? "prose-headings:text-msg-user-foreground prose-p:text-msg-user-foreground prose-li:text-msg-user-foreground prose-strong:text-msg-user-foreground prose-a:text-msg-user-foreground" : "dark:prose-invert prose-headings:text-foreground"}
68
+ prose-pre:bg-code-bg prose-pre:border prose-pre:border-code-border prose-pre:text-xs
69
+ prose-code:bg-code-bg prose-code:text-code-text prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:text-xs prose-code:before:content-none prose-code:after:content-none
70
+ prose-table:border-collapse prose-th:border prose-th:border-border prose-th:px-2 prose-th:py-1
71
+ prose-td:border prose-td:border-border prose-td:px-2 prose-td:py-1
72
+ prose-a:text-primary prose-blockquote:border-l-border prose-blockquote:text-muted-foreground
73
+ prose-hr:border-border`}
74
+ dangerouslySetInnerHTML={{ __html: html }}
75
+ />
76
+ );
77
+ }
78
+
79
+ // --- Tool card ---
80
+
81
+ function ToolCard({ msg, result }: { msg: ConversationMessage; result?: ConversationMessage }) {
82
+ const [expanded, setExpanded] = useState(false);
83
+
84
+ const toolLabel = formatToolLabel(msg.toolName ?? "tool", msg.toolInput);
85
+
86
+ const copyText = typeof msg.toolInput === "string"
87
+ ? msg.toolInput
88
+ : JSON.stringify(msg.toolInput, null, 2);
89
+
90
+ return (
91
+ <div className="my-1.5 border border-msg-tool-border rounded-md bg-msg-tool group">
92
+ <div className="flex items-center">
93
+ <button
94
+ onClick={() => setExpanded(!expanded)}
95
+ className="flex-1 text-left px-3 py-2 flex items-center gap-2 text-xs hover:bg-accent/50 transition-colors rounded-md"
96
+ >
97
+ <span className="text-muted-foreground">{expanded ? "▼" : "▶"}</span>
98
+ <span className="text-primary font-mono">{msg.toolName}</span>
99
+ <span className="text-muted-foreground truncate flex-1">{toolLabel}</span>
100
+ </button>
101
+ <div className="pr-2">
102
+ <CopyButton text={copyText} />
103
+ </div>
104
+ </div>
105
+ {expanded && (
106
+ <div className="px-3 pb-2 space-y-2">
107
+ <div>
108
+ <div className="text-xs text-muted-foreground mb-1">Input:</div>
109
+ <pre className="text-xs bg-code-bg text-code-text border border-code-border rounded-md p-2 overflow-x-auto max-h-60 overflow-y-auto">
110
+ {typeof msg.toolInput === "string"
111
+ ? msg.toolInput
112
+ : JSON.stringify(msg.toolInput, null, 2)}
113
+ </pre>
114
+ </div>
115
+ {result && result.content && (
116
+ <div>
117
+ <div className="text-xs text-muted-foreground mb-1">Output:</div>
118
+ <pre className="text-xs bg-code-bg text-code-text border border-code-border rounded-md p-2 overflow-x-auto max-h-60 overflow-y-auto">
119
+ {result.content}
120
+ </pre>
121
+ </div>
122
+ )}
123
+ </div>
124
+ )}
125
+ </div>
126
+ );
127
+ }
128
+
129
+ // --- Thinking block ---
130
+
131
+ function ThinkingBlock({ content }: { content: string }) {
132
+ const [expanded, setExpanded] = useState(false);
133
+
134
+ return (
135
+ <div className="my-1">
136
+ <button
137
+ onClick={() => setExpanded(!expanded)}
138
+ className="text-xs text-muted-foreground hover:text-foreground flex items-center gap-1 transition-colors"
139
+ >
140
+ <span>{expanded ? "▼" : "▶"}</span>
141
+ <span className="italic">thinking...</span>
142
+ </button>
143
+ {expanded && (
144
+ <pre className="text-xs text-muted-foreground bg-muted rounded-md p-2 mt-1 whitespace-pre-wrap max-h-40 overflow-y-auto">
145
+ {content}
146
+ </pre>
147
+ )}
148
+ </div>
149
+ );
150
+ }
151
+
152
+ // --- Main component ---
153
+
154
+ interface Props {
155
+ sessionId: string;
156
+ className?: string;
157
+ }
158
+
159
+ export default function ConversationViewer({ sessionId, className }: Props) {
160
+ const [detail, setDetail] = useState<SessionDetail | null>(null);
161
+ const [loading, setLoading] = useState(true);
162
+ const [error, setError] = useState<string | null>(null);
163
+ const bottomRef = useRef<HTMLDivElement>(null);
164
+
165
+ useEffect(() => {
166
+ setLoading(true);
167
+ setError(null);
168
+ const controller = new AbortController();
169
+ botFetch(`/api/sessions/${sessionId}`, { signal: controller.signal })
170
+ .then((r) => {
171
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
172
+ return r.json();
173
+ })
174
+ .then((data) => {
175
+ if (controller.signal.aborted) return;
176
+ if (!data || !Array.isArray(data.messages)) throw new Error("Invalid session data");
177
+ setDetail(data as SessionDetail);
178
+ setLoading(false);
179
+ })
180
+ .catch((err) => {
181
+ if (controller.signal.aborted) return;
182
+ setError(err instanceof Error ? err.message : "Failed to load");
183
+ setLoading(false);
184
+ });
185
+ return () => controller.abort();
186
+ }, [sessionId]);
187
+
188
+ useEffect(() => {
189
+ if (!loading) {
190
+ bottomRef.current?.scrollIntoView({ behavior: "smooth" });
191
+ }
192
+ }, [detail, loading]);
193
+
194
+ if (loading) {
195
+ return (
196
+ <div className={`flex items-center justify-center text-muted-foreground ${className ?? ""}`}>
197
+ Loading conversation...
198
+ </div>
199
+ );
200
+ }
201
+
202
+ if (error) {
203
+ return (
204
+ <div className={`flex items-center justify-center text-destructive ${className ?? ""}`}>
205
+ Error: {error}
206
+ </div>
207
+ );
208
+ }
209
+
210
+ if (!detail || detail.messages.length === 0) {
211
+ return (
212
+ <div className={`flex items-center justify-center text-muted-foreground ${className ?? ""}`}>
213
+ No messages in this session
214
+ </div>
215
+ );
216
+ }
217
+
218
+ // Build tool result lookup: toolUseId → message
219
+ const toolResults = new Map<string, ConversationMessage>();
220
+ for (const msg of detail.messages) {
221
+ if (msg.role === "tool_result" && msg.toolUseId) {
222
+ toolResults.set(msg.toolUseId, msg);
223
+ }
224
+ }
225
+
226
+ return (
227
+ <div className={`overflow-y-auto overflow-x-hidden scrollbar-thin ${className ?? ""}`}>
228
+ {/* Messages */}
229
+ <div className="p-4 space-y-3">
230
+ {detail.messages.map((msg, i) => {
231
+ // Skip tool_result — shown inside ToolCard
232
+ if (msg.role === "tool_result") return null;
233
+
234
+ const key = msg.toolUseId ?? `${msg.role}-${msg.timestamp}-${i}`;
235
+
236
+ if (msg.role === "user") {
237
+ return (
238
+ <div key={key} className="mr-12">
239
+ <div className="group relative bg-msg-user text-msg-user-foreground rounded-lg px-3 py-[1.2em] text-sm">
240
+ <MarkdownContent text={msg.content} variant="user" />
241
+ <div className="absolute bottom-1.5 right-1.5">
242
+ <CopyButton text={msg.content} />
243
+ </div>
244
+ </div>
245
+ </div>
246
+ );
247
+ }
248
+
249
+ if (msg.role === "tool_use") {
250
+ const result = msg.toolUseId ? toolResults.get(msg.toolUseId) : undefined;
251
+ return <ToolCard key={key} msg={msg} result={result} />;
252
+ }
253
+
254
+ if (msg.role === "assistant") {
255
+ return (
256
+ <div key={key} className="ml-12">
257
+ {msg.thinkingContent && <ThinkingBlock content={msg.thinkingContent} />}
258
+ <div className="group relative bg-msg-assistant text-msg-assistant-foreground rounded-lg px-3 py-[1.2em] text-sm">
259
+ <MarkdownContent text={msg.content} variant="assistant" />
260
+ <div className="absolute bottom-1.5 right-1.5">
261
+ <CopyButton text={msg.content} />
262
+ </div>
263
+ </div>
264
+ {msg.tokensIn != null && (
265
+ <div className="text-xs text-muted-foreground mt-1">
266
+ {msg.tokensIn?.toLocaleString()} in / {msg.tokensOut?.toLocaleString()} out
267
+ </div>
268
+ )}
269
+ </div>
270
+ );
271
+ }
272
+
273
+ return null;
274
+ })}
275
+ <div ref={bottomRef} />
276
+ </div>
277
+ </div>
278
+ );
279
+ }
@@ -0,0 +1,48 @@
1
+ import { useState } from "react";
2
+ import { FileType, FileTerminal } from "lucide-react";
3
+ import ConversationViewer from "./conversation-viewer";
4
+ import TerminalPane from "./terminal-pane";
5
+
6
+ interface Props {
7
+ sessionId: string;
8
+ hasPty: boolean;
9
+ className?: string;
10
+ }
11
+
12
+ export default function SessionDetail({ sessionId, hasPty, className }: Props) {
13
+ const [showTerminal, setShowTerminal] = useState(false);
14
+
15
+ return (
16
+ <div className={`flex flex-col ${className ?? ""}`}>
17
+ {/* Action bar */}
18
+ <div className="flex items-center justify-end gap-1 px-4 py-2 bg-card">
19
+ <button
20
+ onClick={() => setShowTerminal(false)}
21
+ className={`p-1.5 transition-colors ${
22
+ !showTerminal ? "text-foreground" : "text-muted-foreground hover:text-foreground"
23
+ }`}
24
+ title="History"
25
+ >
26
+ <FileType className="w-4 h-4" />
27
+ </button>
28
+ <button
29
+ onClick={() => hasPty && setShowTerminal(true)}
30
+ className={`p-1.5 transition-colors ${
31
+ showTerminal ? "text-foreground" : hasPty ? "text-muted-foreground hover:text-foreground" : "text-muted-foreground/40 cursor-not-allowed"
32
+ }`}
33
+ title={hasPty ? "Terminal" : "No terminal for this session"}
34
+ disabled={!hasPty}
35
+ >
36
+ <FileTerminal className="w-4 h-4" />
37
+ </button>
38
+ </div>
39
+
40
+ {/* Content */}
41
+ {!showTerminal ? (
42
+ <ConversationViewer sessionId={sessionId} className="flex-1 min-h-0" />
43
+ ) : (
44
+ <TerminalPane sessionId={sessionId} className="flex-1 min-h-0" />
45
+ )}
46
+ </div>
47
+ );
48
+ }