@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,661 @@
1
+ import { useCallback, useRef, useState } from 'react';
2
+
3
+ import { LAYOUT_SAVE_DEBOUNCE_MS, ZOOM_MAX, ZOOM_MIN } from '../constants.js';
4
+ import type { ExpandDirection } from '../editor/editorActions.js';
5
+ import {
6
+ canPlaceFurniture,
7
+ expandLayout,
8
+ getWallPlacementRow,
9
+ moveFurniture,
10
+ paintTile,
11
+ placeFurniture,
12
+ removeFurniture,
13
+ rotateFurniture,
14
+ toggleFurnitureState,
15
+ } from '../editor/editorActions.js';
16
+ import type { EditorState } from '../editor/editorState.js';
17
+ import type { OfficeState } from '../engine/officeState.js';
18
+ import {
19
+ getCatalogEntry,
20
+ getRotatedType,
21
+ getToggledType,
22
+ } from '../layout/furnitureCatalog.js';
23
+ import { defaultZoom } from '../toolUtils.js';
24
+ import type {
25
+ EditTool as EditToolType,
26
+ FloorColor,
27
+ OfficeLayout,
28
+ PlacedFurniture,
29
+ TileType as TileTypeVal,
30
+ } from '../types.js';
31
+ import { EditTool } from '../types.js';
32
+ import { TileType } from '../types.js';
33
+
34
+ export interface EditorActions {
35
+ isEditMode: boolean;
36
+ editorTick: number;
37
+ isDirty: boolean;
38
+ zoom: number;
39
+ panRef: React.RefObject<{ x: number; y: number }>;
40
+ saveTimerRef: React.RefObject<ReturnType<typeof setTimeout> | null>;
41
+ setLastSavedLayout: (layout: OfficeLayout) => void;
42
+ handleToggleEditMode: () => void;
43
+ handleToolChange: (tool: EditToolType) => void;
44
+ handleTileTypeChange: (type: TileTypeVal) => void;
45
+ handleFloorColorChange: (color: FloorColor) => void;
46
+ handleWallColorChange: (color: FloorColor) => void;
47
+ handleWallSetChange: (setIndex: number) => void;
48
+ handleSelectedFurnitureColorChange: (color: FloorColor | null) => void;
49
+ handleFurnitureTypeChange: (type: string) => void; // FurnitureType enum or asset ID
50
+ handleDeleteSelected: () => void;
51
+ handleRotateSelected: () => void;
52
+ handleToggleState: () => void;
53
+ handleUndo: () => void;
54
+ handleRedo: () => void;
55
+ handleReset: () => void;
56
+ handleSave: () => void;
57
+ handleZoomChange: (zoom: number) => void;
58
+ handleEditorTileAction: (col: number, row: number) => void;
59
+ handleEditorEraseAction: (col: number, row: number) => void;
60
+ handleEditorSelectionChange: () => void;
61
+ handleDragMove: (uid: string, newCol: number, newRow: number) => void;
62
+ syncDirtyState: () => void;
63
+ }
64
+
65
+ export function useEditorActions(
66
+ getOfficeState: () => OfficeState,
67
+ editorState: EditorState,
68
+ onSaveLayout: (layout: OfficeLayout) => void,
69
+ onSaveLayoutImmediate?: (layout: OfficeLayout) => Promise<boolean>,
70
+ ): EditorActions {
71
+ const [isEditMode, setIsEditMode] = useState(false);
72
+ const [editorTick, setEditorTick] = useState(0);
73
+ const [isDirty, setIsDirty] = useState(false);
74
+ const [zoom, setZoom] = useState(defaultZoom);
75
+ const saveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
76
+ const panRef = useRef({ x: 0, y: 0 });
77
+ const lastSavedLayoutRef = useRef<OfficeLayout | null>(null);
78
+
79
+ // Called by useExtensionMessages on layoutLoaded to set the initial checkpoint
80
+ const setLastSavedLayout = useCallback((layout: OfficeLayout) => {
81
+ lastSavedLayoutRef.current = structuredClone(layout);
82
+ }, []);
83
+
84
+ // Debounced layout save
85
+ const saveLayout = useCallback(
86
+ (layout: OfficeLayout) => {
87
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
88
+ saveTimerRef.current = setTimeout(() => {
89
+ onSaveLayout(layout);
90
+ }, LAYOUT_SAVE_DEBOUNCE_MS);
91
+ },
92
+ [onSaveLayout],
93
+ );
94
+
95
+ // Apply a layout edit: push undo, clear redo, rebuild state, save, mark dirty
96
+ // Optional undoLayout allows pushing a different layout to undo (e.g., pre-expansion)
97
+ const applyEdit = useCallback(
98
+ (newLayout: OfficeLayout, undoLayout?: OfficeLayout) => {
99
+ const os = getOfficeState();
100
+ editorState.pushUndo(undoLayout ?? os.getLayout());
101
+ editorState.clearRedo();
102
+ editorState.isDirty = true;
103
+ setIsDirty(true);
104
+ os.rebuildFromLayout(newLayout);
105
+ saveLayout(newLayout);
106
+ setEditorTick((n) => n + 1);
107
+ },
108
+ [getOfficeState, editorState, saveLayout],
109
+ );
110
+
111
+ const handleToggleEditMode = useCallback(() => {
112
+ setIsEditMode((prev) => {
113
+ const next = !prev;
114
+ editorState.isEditMode = next;
115
+ if (next) {
116
+ // Initialize wallColor from existing wall tiles so new walls match
117
+ const os = getOfficeState();
118
+ const layout = os.getLayout();
119
+ if (layout.tileColors) {
120
+ for (let i = 0; i < layout.tiles.length; i++) {
121
+ if (layout.tiles[i] === TileType.WALL && layout.tileColors[i]) {
122
+ editorState.wallColor = { ...layout.tileColors[i]! };
123
+ break;
124
+ }
125
+ }
126
+ }
127
+ } else {
128
+ editorState.clearSelection();
129
+ editorState.clearGhost();
130
+ editorState.clearDrag();
131
+ wallColorEditActiveRef.current = false;
132
+ }
133
+ return next;
134
+ });
135
+ }, [editorState, getOfficeState]);
136
+
137
+ // Tool toggle: clicking already-active tool deselects it (returns to SELECT)
138
+ const handleToolChange = useCallback(
139
+ (tool: EditToolType) => {
140
+ if (editorState.activeTool === tool) {
141
+ editorState.activeTool = EditTool.SELECT;
142
+ } else {
143
+ editorState.activeTool = tool;
144
+ }
145
+ editorState.clearSelection();
146
+ editorState.clearGhost();
147
+ editorState.clearDrag();
148
+ colorEditUidRef.current = null;
149
+ wallColorEditActiveRef.current = false;
150
+ setEditorTick((n) => n + 1);
151
+ },
152
+ [editorState],
153
+ );
154
+
155
+ const handleTileTypeChange = useCallback(
156
+ (type: TileTypeVal) => {
157
+ editorState.selectedTileType = type;
158
+ setEditorTick((n) => n + 1);
159
+ },
160
+ [editorState],
161
+ );
162
+
163
+ const handleFloorColorChange = useCallback(
164
+ (color: FloorColor) => {
165
+ editorState.floorColor = color;
166
+ setEditorTick((n) => n + 1);
167
+ },
168
+ [editorState],
169
+ );
170
+
171
+ // Track whether we've already pushed undo for the current wall color editing session
172
+ const wallColorEditActiveRef = useRef(false);
173
+
174
+ const handleWallColorChange = useCallback(
175
+ (color: FloorColor) => {
176
+ editorState.wallColor = color;
177
+
178
+ // Update all existing wall tiles to the new color
179
+ const os = getOfficeState();
180
+ const layout = os.getLayout();
181
+ const existingColors = layout.tileColors || new Array(layout.tiles.length).fill(null);
182
+ const newColors = [...existingColors];
183
+ let changed = false;
184
+ for (let i = 0; i < layout.tiles.length; i++) {
185
+ if (layout.tiles[i] === TileType.WALL) {
186
+ newColors[i] = { ...color };
187
+ changed = true;
188
+ }
189
+ }
190
+ if (changed) {
191
+ // Push undo only once per editing session (first slider touch)
192
+ if (!wallColorEditActiveRef.current) {
193
+ editorState.pushUndo(layout);
194
+ editorState.clearRedo();
195
+ wallColorEditActiveRef.current = true;
196
+ }
197
+ const newLayout = { ...layout, tileColors: newColors };
198
+ editorState.isDirty = true;
199
+ setIsDirty(true);
200
+ os.rebuildFromLayout(newLayout);
201
+ saveLayout(newLayout);
202
+ }
203
+ setEditorTick((n) => n + 1);
204
+ },
205
+ [editorState, getOfficeState, saveLayout],
206
+ );
207
+
208
+ const handleWallSetChange = useCallback(
209
+ (setIndex: number) => {
210
+ editorState.selectedWallSet = setIndex;
211
+ setEditorTick((n) => n + 1);
212
+ },
213
+ [editorState],
214
+ );
215
+
216
+ // Track which uid we've already pushed undo for during color editing
217
+ // so dragging sliders doesn't create N undo entries
218
+ const colorEditUidRef = useRef<string | null>(null);
219
+
220
+ const handleSelectedFurnitureColorChange = useCallback(
221
+ (color: FloorColor | null) => {
222
+ const uid = editorState.selectedFurnitureUid;
223
+ if (!uid) return;
224
+ const os = getOfficeState();
225
+ const layout = os.getLayout();
226
+
227
+ // Push undo only once per selection (first slider touch)
228
+ if (colorEditUidRef.current !== uid) {
229
+ editorState.pushUndo(layout);
230
+ editorState.clearRedo();
231
+ colorEditUidRef.current = uid;
232
+ }
233
+
234
+ // Update color on the placed furniture item (null removes color)
235
+ const newFurniture = layout.furniture.map((f) =>
236
+ f.uid === uid ? { ...f, color: color ?? undefined } : f,
237
+ );
238
+ const newLayout = { ...layout, furniture: newFurniture };
239
+
240
+ editorState.isDirty = true;
241
+ setIsDirty(true);
242
+ os.rebuildFromLayout(newLayout);
243
+ saveLayout(newLayout);
244
+ setEditorTick((n) => n + 1);
245
+ },
246
+ [getOfficeState, editorState, saveLayout],
247
+ );
248
+
249
+ const handleFurnitureTypeChange = useCallback(
250
+ (type: string) => {
251
+ // Clicking the same item deselects it (no ghost), stays in furniture mode
252
+ if (editorState.selectedFurnitureType === type) {
253
+ editorState.selectedFurnitureType = '';
254
+ editorState.clearGhost();
255
+ } else {
256
+ editorState.selectedFurnitureType = type;
257
+ }
258
+ setEditorTick((n) => n + 1);
259
+ },
260
+ [editorState],
261
+ );
262
+
263
+ const handleDeleteSelected = useCallback(() => {
264
+ const uid = editorState.selectedFurnitureUid;
265
+ if (!uid) return;
266
+ const os = getOfficeState();
267
+ const newLayout = removeFurniture(os.getLayout(), uid);
268
+ if (newLayout !== os.getLayout()) {
269
+ applyEdit(newLayout);
270
+ editorState.clearSelection();
271
+ colorEditUidRef.current = null;
272
+ }
273
+ }, [getOfficeState, editorState, applyEdit]);
274
+
275
+ const handleRotateSelected = useCallback(() => {
276
+ // If in furniture placement mode, cycle the selected type through the rotation group
277
+ if (editorState.activeTool === EditTool.FURNITURE_PLACE) {
278
+ const rotated = getRotatedType(editorState.selectedFurnitureType, 'cw');
279
+ if (rotated) {
280
+ editorState.selectedFurnitureType = rotated;
281
+ setEditorTick((n) => n + 1);
282
+ }
283
+ return;
284
+ }
285
+ // Otherwise rotate the selected placed furniture
286
+ const uid = editorState.selectedFurnitureUid;
287
+ if (!uid) return;
288
+ const os = getOfficeState();
289
+ const newLayout = rotateFurniture(os.getLayout(), uid, 'cw');
290
+ if (newLayout !== os.getLayout()) {
291
+ applyEdit(newLayout);
292
+ }
293
+ }, [getOfficeState, editorState, applyEdit]);
294
+
295
+ const handleToggleState = useCallback(() => {
296
+ // If in furniture placement mode, toggle the selected type's state
297
+ if (editorState.activeTool === EditTool.FURNITURE_PLACE) {
298
+ const toggled = getToggledType(editorState.selectedFurnitureType);
299
+ if (toggled) {
300
+ editorState.selectedFurnitureType = toggled;
301
+ setEditorTick((n) => n + 1);
302
+ }
303
+ return;
304
+ }
305
+ // Otherwise toggle the selected placed furniture's state
306
+ const uid = editorState.selectedFurnitureUid;
307
+ if (!uid) return;
308
+ const os = getOfficeState();
309
+ const newLayout = toggleFurnitureState(os.getLayout(), uid);
310
+ if (newLayout !== os.getLayout()) {
311
+ applyEdit(newLayout);
312
+ }
313
+ }, [getOfficeState, editorState, applyEdit]);
314
+
315
+ const handleUndo = useCallback(() => {
316
+ const prev = editorState.popUndo();
317
+ if (!prev) return;
318
+ const os = getOfficeState();
319
+ // Push current layout to redo stack before restoring
320
+ editorState.pushRedo(os.getLayout());
321
+ os.rebuildFromLayout(prev);
322
+ saveLayout(prev);
323
+ editorState.isDirty = true;
324
+ setIsDirty(true);
325
+ setEditorTick((n) => n + 1);
326
+ }, [getOfficeState, editorState, saveLayout]);
327
+
328
+ const handleRedo = useCallback(() => {
329
+ const next = editorState.popRedo();
330
+ if (!next) return;
331
+ const os = getOfficeState();
332
+ // Push current layout to undo stack before restoring
333
+ editorState.pushUndo(os.getLayout());
334
+ os.rebuildFromLayout(next);
335
+ saveLayout(next);
336
+ editorState.isDirty = true;
337
+ setIsDirty(true);
338
+ setEditorTick((n) => n + 1);
339
+ }, [getOfficeState, editorState, saveLayout]);
340
+
341
+ const handleReset = useCallback(() => {
342
+ if (!lastSavedLayoutRef.current) return;
343
+ const saved = structuredClone(lastSavedLayoutRef.current);
344
+ applyEdit(saved);
345
+ editorState.reset();
346
+ setIsDirty(false);
347
+ }, [editorState, applyEdit]);
348
+
349
+ const handleSave = useCallback(async () => {
350
+ // Flush any pending debounced save immediately
351
+ if (saveTimerRef.current) {
352
+ clearTimeout(saveTimerRef.current);
353
+ saveTimerRef.current = null;
354
+ }
355
+ const os = getOfficeState();
356
+ const layout = os.getLayout();
357
+ // Use immediate save if available, falling back to debounced save
358
+ if (onSaveLayoutImmediate) {
359
+ const ok = await onSaveLayoutImmediate(layout);
360
+ if (ok) {
361
+ lastSavedLayoutRef.current = structuredClone(layout);
362
+ editorState.isDirty = false;
363
+ setIsDirty(false);
364
+ }
365
+ } else {
366
+ // Debounced save — mark clean optimistically (no async confirmation available)
367
+ onSaveLayout(layout);
368
+ lastSavedLayoutRef.current = structuredClone(layout);
369
+ editorState.isDirty = false;
370
+ setIsDirty(false);
371
+ }
372
+ }, [getOfficeState, editorState, onSaveLayout, onSaveLayoutImmediate]);
373
+
374
+ // Notify React that imperative editor selection changed (e.g., from OfficeCanvas mouseUp)
375
+ const handleEditorSelectionChange = useCallback(() => {
376
+ colorEditUidRef.current = null;
377
+ setEditorTick((n) => n + 1);
378
+ }, []);
379
+
380
+ /** Sync React dirty state after imperative editorState.reset() (e.g., after import) */
381
+ const syncDirtyState = useCallback(() => {
382
+ setIsDirty(editorState.isDirty);
383
+ setEditorTick((n) => n + 1);
384
+ }, [editorState]);
385
+
386
+ const handleZoomChange = useCallback((newZoom: number) => {
387
+ setZoom(Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, newZoom)));
388
+ }, []);
389
+
390
+ const handleDragMove = useCallback(
391
+ (uid: string, newCol: number, newRow: number) => {
392
+ const os = getOfficeState();
393
+ const layout = os.getLayout();
394
+ const newLayout = moveFurniture(layout, uid, newCol, newRow);
395
+ if (newLayout !== layout) {
396
+ applyEdit(newLayout);
397
+ }
398
+ },
399
+ [getOfficeState, applyEdit],
400
+ );
401
+
402
+ /**
403
+ * Expand layout if click is on a ghost border tile (outside current bounds).
404
+ * Returns the expanded layout and adjusted col/row, or null if no expansion needed.
405
+ */
406
+ const maybeExpand = useCallback(
407
+ (
408
+ layout: OfficeLayout,
409
+ col: number,
410
+ row: number,
411
+ ): {
412
+ layout: OfficeLayout;
413
+ col: number;
414
+ row: number;
415
+ shift: { col: number; row: number };
416
+ } | null => {
417
+ if (col >= 0 && col < layout.cols && row >= 0 && row < layout.rows) return null;
418
+
419
+ // Determine which directions to expand
420
+ const directions: ExpandDirection[] = [];
421
+ if (col < 0) directions.push('left');
422
+ if (col >= layout.cols) directions.push('right');
423
+ if (row < 0) directions.push('up');
424
+ if (row >= layout.rows) directions.push('down');
425
+
426
+ let current = layout;
427
+ let totalShiftCol = 0;
428
+ let totalShiftRow = 0;
429
+ for (const dir of directions) {
430
+ const result = expandLayout(current, dir);
431
+ if (!result) return null; // exceeded max
432
+ current = result.layout;
433
+ totalShiftCol += result.shift.col;
434
+ totalShiftRow += result.shift.row;
435
+ }
436
+
437
+ return {
438
+ layout: current,
439
+ col: col + totalShiftCol,
440
+ row: row + totalShiftRow,
441
+ shift: { col: totalShiftCol, row: totalShiftRow },
442
+ };
443
+ },
444
+ [],
445
+ );
446
+
447
+ const handleEditorTileAction = useCallback(
448
+ (col: number, row: number) => {
449
+ const os = getOfficeState();
450
+ // Save the original layout BEFORE any expansion for correct undo
451
+ const originalLayout = os.getLayout();
452
+ let layout = originalLayout;
453
+ let effectiveCol = col;
454
+ let effectiveRow = row;
455
+ let wasExpanded = false;
456
+
457
+ // Handle ghost border expansion for floor/wall tools
458
+ if (
459
+ editorState.activeTool === EditTool.TILE_PAINT ||
460
+ editorState.activeTool === EditTool.WALL_PAINT
461
+ ) {
462
+ const expansion = maybeExpand(layout, col, row);
463
+ if (expansion) {
464
+ layout = expansion.layout;
465
+ effectiveCol = expansion.col;
466
+ effectiveRow = expansion.row;
467
+ wasExpanded = true;
468
+ // Rebuild from expanded layout first, shifting character positions
469
+ os.rebuildFromLayout(layout, expansion.shift);
470
+ }
471
+ }
472
+
473
+ // When expansion happened, undo should restore the pre-expansion layout
474
+ const undoRef = wasExpanded ? originalLayout : undefined;
475
+
476
+ if (editorState.activeTool === EditTool.TILE_PAINT) {
477
+ const newLayout = paintTile(
478
+ layout,
479
+ effectiveCol,
480
+ effectiveRow,
481
+ editorState.selectedTileType,
482
+ editorState.floorColor,
483
+ );
484
+ if (newLayout !== layout) {
485
+ applyEdit(newLayout, undoRef);
486
+ }
487
+ } else if (editorState.activeTool === EditTool.WALL_PAINT) {
488
+ const idx = effectiveRow * layout.cols + effectiveCol;
489
+ const isWall = layout.tiles[idx] === TileType.WALL;
490
+
491
+ // First tile of drag sets direction
492
+ if (editorState.wallDragAdding === null) {
493
+ editorState.wallDragAdding = !isWall;
494
+ }
495
+
496
+ if (editorState.wallDragAdding) {
497
+ // Add wall with color
498
+ const newLayout = paintTile(
499
+ layout,
500
+ effectiveCol,
501
+ effectiveRow,
502
+ TileType.WALL,
503
+ editorState.wallColor,
504
+ );
505
+ if (newLayout !== layout) {
506
+ applyEdit(newLayout, undoRef);
507
+ }
508
+ } else {
509
+ // Remove wall → paint floor with current floor settings
510
+ if (isWall) {
511
+ const newLayout = paintTile(
512
+ layout,
513
+ effectiveCol,
514
+ effectiveRow,
515
+ editorState.selectedTileType,
516
+ editorState.floorColor,
517
+ );
518
+ if (newLayout !== layout) {
519
+ applyEdit(newLayout, undoRef);
520
+ }
521
+ }
522
+ }
523
+ } else if (editorState.activeTool === EditTool.ERASE) {
524
+ if (col < 0 || col >= layout.cols || row < 0 || row >= layout.rows) return;
525
+ const idx = row * layout.cols + col;
526
+ if (layout.tiles[idx] === TileType.VOID) return;
527
+ const newLayout = paintTile(layout, col, row, TileType.VOID);
528
+ if (newLayout !== layout) {
529
+ applyEdit(newLayout);
530
+ }
531
+ } else if (editorState.activeTool === EditTool.FURNITURE_PLACE) {
532
+ const type = editorState.selectedFurnitureType;
533
+ if (type === '') {
534
+ // No item selected — act like SELECT (find furniture hit)
535
+ const hit = layout.furniture.find((f) => {
536
+ const entry = getCatalogEntry(f.type);
537
+ if (!entry) return false;
538
+ return (
539
+ col >= f.col &&
540
+ col < f.col + entry.footprintW &&
541
+ row >= f.row &&
542
+ row < f.row + entry.footprintH
543
+ );
544
+ });
545
+ editorState.selectedFurnitureUid = hit ? hit.uid : null;
546
+ setEditorTick((n) => n + 1);
547
+ } else {
548
+ const placementRow = getWallPlacementRow(type, row);
549
+ if (!canPlaceFurniture(layout, type, col, placementRow)) return;
550
+ const uid = `f-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
551
+ const placed: PlacedFurniture = { uid, type, col, row: placementRow };
552
+ if (editorState.pickedFurnitureColor) {
553
+ placed.color = { ...editorState.pickedFurnitureColor };
554
+ }
555
+ const newLayout = placeFurniture(layout, placed);
556
+ if (newLayout !== layout) {
557
+ applyEdit(newLayout);
558
+ }
559
+ }
560
+ } else if (editorState.activeTool === EditTool.FURNITURE_PICK) {
561
+ // Find furniture at clicked tile, copy its type and color for placement
562
+ const hit = layout.furniture.find((f) => {
563
+ const entry = getCatalogEntry(f.type);
564
+ if (!entry) return false;
565
+ return (
566
+ col >= f.col &&
567
+ col < f.col + entry.footprintW &&
568
+ row >= f.row &&
569
+ row < f.row + entry.footprintH
570
+ );
571
+ });
572
+ if (hit) {
573
+ editorState.selectedFurnitureType = hit.type;
574
+ editorState.pickedFurnitureColor = hit.color ? { ...hit.color } : null;
575
+ editorState.activeTool = EditTool.FURNITURE_PLACE;
576
+ }
577
+ setEditorTick((n) => n + 1);
578
+ } else if (editorState.activeTool === EditTool.EYEDROPPER) {
579
+ const idx = row * layout.cols + col;
580
+ const tile = layout.tiles[idx];
581
+ if (tile !== undefined && tile !== TileType.WALL && tile !== TileType.VOID) {
582
+ editorState.selectedTileType = tile;
583
+ const color = layout.tileColors?.[idx];
584
+ if (color) {
585
+ editorState.floorColor = { ...color };
586
+ }
587
+ editorState.activeTool = EditTool.TILE_PAINT;
588
+ } else if (tile === TileType.WALL) {
589
+ // Pick wall color and switch to wall tool
590
+ const color = layout.tileColors?.[idx];
591
+ if (color) {
592
+ editorState.wallColor = { ...color };
593
+ }
594
+ editorState.activeTool = EditTool.WALL_PAINT;
595
+ }
596
+ setEditorTick((n) => n + 1);
597
+ } else if (editorState.activeTool === EditTool.SELECT) {
598
+ const hit = layout.furniture.find((f) => {
599
+ const entry = getCatalogEntry(f.type);
600
+ if (!entry) return false;
601
+ return (
602
+ col >= f.col &&
603
+ col < f.col + entry.footprintW &&
604
+ row >= f.row &&
605
+ row < f.row + entry.footprintH
606
+ );
607
+ });
608
+ editorState.selectedFurnitureUid = hit ? hit.uid : null;
609
+ setEditorTick((n) => n + 1);
610
+ }
611
+ },
612
+ [getOfficeState, editorState, applyEdit, maybeExpand],
613
+ );
614
+
615
+ const handleEditorEraseAction = useCallback(
616
+ (col: number, row: number) => {
617
+ const os = getOfficeState();
618
+ const layout = os.getLayout();
619
+ if (col < 0 || col >= layout.cols || row < 0 || row >= layout.rows) return;
620
+ const idx = row * layout.cols + col;
621
+ // Only erase non-VOID tiles
622
+ if (layout.tiles[idx] === TileType.VOID) return;
623
+ const newLayout = paintTile(layout, col, row, TileType.VOID);
624
+ if (newLayout !== layout) {
625
+ applyEdit(newLayout);
626
+ }
627
+ },
628
+ [getOfficeState, applyEdit],
629
+ );
630
+
631
+ return {
632
+ isEditMode,
633
+ editorTick,
634
+ isDirty,
635
+ zoom,
636
+ panRef,
637
+ saveTimerRef,
638
+ setLastSavedLayout,
639
+ handleToggleEditMode,
640
+ handleToolChange,
641
+ handleTileTypeChange,
642
+ handleFloorColorChange,
643
+ handleWallColorChange,
644
+ handleWallSetChange,
645
+ handleSelectedFurnitureColorChange,
646
+ handleFurnitureTypeChange,
647
+ handleDeleteSelected,
648
+ handleRotateSelected,
649
+ handleToggleState,
650
+ handleUndo,
651
+ handleRedo,
652
+ handleReset,
653
+ handleSave,
654
+ handleZoomChange,
655
+ handleEditorTileAction,
656
+ handleEditorEraseAction,
657
+ handleEditorSelectionChange,
658
+ handleDragMove,
659
+ syncDirtyState,
660
+ };
661
+ }