4runr-os 2.1.2 → 2.1.5

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 (566) hide show
  1. package/dist/index.js +16 -1
  2. package/dist/index.js.map +1 -1
  3. package/dist/tui_mk1/kernel.d.ts.map +1 -1
  4. package/dist/tui_mk1/kernel.js +107 -4
  5. package/dist/tui_mk1/kernel.js.map +1 -1
  6. package/dist/tui_mk1/layout/layoutEngine.d.ts +38 -19
  7. package/dist/tui_mk1/layout/layoutEngine.d.ts.map +1 -1
  8. package/dist/tui_mk1/layout/layoutEngine.js +521 -228
  9. package/dist/tui_mk1/layout/layoutEngine.js.map +1 -1
  10. package/dist/tui_mk1/log.d.ts +23 -0
  11. package/dist/tui_mk1/log.d.ts.map +1 -0
  12. package/dist/tui_mk1/log.js +125 -0
  13. package/dist/tui_mk1/log.js.map +1 -0
  14. package/dist/tui_mk1/logger.d.ts.map +1 -1
  15. package/dist/tui_mk1/logger.js +20 -10
  16. package/dist/tui_mk1/logger.js.map +1 -1
  17. package/dist/tui_mk1/mk1App.d.ts +13 -18
  18. package/dist/tui_mk1/mk1App.d.ts.map +1 -1
  19. package/dist/tui_mk1/mk1App.js +334 -157
  20. package/dist/tui_mk1/mk1App.js.map +1 -1
  21. package/dist/tui_mk1/resizeController.d.ts.map +1 -1
  22. package/dist/tui_mk1/resizeController.js +15 -1
  23. package/dist/tui_mk1/resizeController.js.map +1 -1
  24. package/dist/tui_mk1/stdoutGuard.d.ts.map +1 -1
  25. package/dist/tui_mk1/stdoutGuard.js +7 -0
  26. package/dist/tui_mk1/stdoutGuard.js.map +1 -1
  27. package/dist/tui_mk1/terminalRestore.d.ts.map +1 -1
  28. package/dist/tui_mk1/terminalRestore.js +19 -1
  29. package/dist/tui_mk1/terminalRestore.js.map +1 -1
  30. package/dist/tui_mk1/ui/offenderScanner.d.ts +31 -0
  31. package/dist/tui_mk1/ui/offenderScanner.d.ts.map +1 -0
  32. package/dist/tui_mk1/ui/offenderScanner.js +80 -0
  33. package/dist/tui_mk1/ui/offenderScanner.js.map +1 -0
  34. package/dist/tui_mk1/ui/safe.d.ts +9 -0
  35. package/dist/tui_mk1/ui/safe.d.ts.map +1 -0
  36. package/dist/tui_mk1/ui/safe.js +29 -0
  37. package/dist/tui_mk1/ui/safe.js.map +1 -0
  38. package/dist/tui_mk1/ui/safeText.d.ts +22 -0
  39. package/dist/tui_mk1/ui/safeText.d.ts.map +1 -0
  40. package/dist/tui_mk1/ui/safeText.js +50 -0
  41. package/dist/tui_mk1/ui/safeText.js.map +1 -0
  42. package/dist/tui_mk1/ui/uiBuilder.d.ts +44 -0
  43. package/dist/tui_mk1/ui/uiBuilder.d.ts.map +1 -0
  44. package/dist/tui_mk1/ui/uiBuilder.js +467 -0
  45. package/dist/tui_mk1/ui/uiBuilder.js.map +1 -0
  46. package/dist/tui_mk1/viewport/safeViewport.d.ts +10 -1
  47. package/dist/tui_mk1/viewport/safeViewport.d.ts.map +1 -1
  48. package/dist/tui_mk1/viewport/safeViewport.js +47 -15
  49. package/dist/tui_mk1/viewport/safeViewport.js.map +1 -1
  50. package/dist/tui_mk2/kernel.d.ts +28 -0
  51. package/dist/tui_mk2/kernel.d.ts.map +1 -0
  52. package/dist/tui_mk2/kernel.js +86 -0
  53. package/dist/tui_mk2/kernel.js.map +1 -0
  54. package/dist/tui_mk2/mk2App.d.ts +33 -0
  55. package/dist/tui_mk2/mk2App.d.ts.map +1 -0
  56. package/dist/tui_mk2/mk2App.js +93 -0
  57. package/dist/tui_mk2/mk2App.js.map +1 -0
  58. package/package.json +8 -7
  59. package/dist/tui_mk1/ui/panels/createSection.d.ts +0 -18
  60. package/dist/tui_mk1/ui/panels/createSection.d.ts.map +0 -1
  61. package/dist/tui_mk1/ui/panels/createSection.js +0 -42
  62. package/dist/tui_mk1/ui/panels/createSection.js.map +0 -1
  63. package/dist/tui_mk1/ui/panels.d.ts +0 -23
  64. package/dist/tui_mk1/ui/panels.d.ts.map +0 -1
  65. package/dist/tui_mk1/ui/panels.js +0 -108
  66. package/dist/tui_mk1/ui/panels.js.map +0 -1
  67. package/dist/tui_mk1/ui/render/sectionRenderer.d.ts +0 -21
  68. package/dist/tui_mk1/ui/render/sectionRenderer.d.ts.map +0 -1
  69. package/dist/tui_mk1/ui/render/sectionRenderer.js +0 -32
  70. package/dist/tui_mk1/ui/render/sectionRenderer.js.map +0 -1
  71. package/dist/tui_mk1/ui/widgetManager.d.ts +0 -58
  72. package/dist/tui_mk1/ui/widgetManager.d.ts.map +0 -1
  73. package/dist/tui_mk1/ui/widgetManager.js +0 -197
  74. package/dist/tui_mk1/ui/widgetManager.js.map +0 -1
  75. package/dist/ui/boot/sequence.d.ts +0 -10
  76. package/dist/ui/boot/sequence.d.ts.map +0 -1
  77. package/dist/ui/boot/sequence.js +0 -171
  78. package/dist/ui/boot/sequence.js.map +0 -1
  79. package/dist/ui/constraints/layoutSpec.d.ts +0 -47
  80. package/dist/ui/constraints/layoutSpec.d.ts.map +0 -1
  81. package/dist/ui/constraints/layoutSpec.js +0 -60
  82. package/dist/ui/constraints/layoutSpec.js.map +0 -1
  83. package/dist/ui/constraints/unknownHandling.d.ts +0 -29
  84. package/dist/ui/constraints/unknownHandling.d.ts.map +0 -1
  85. package/dist/ui/constraints/unknownHandling.js +0 -60
  86. package/dist/ui/constraints/unknownHandling.js.map +0 -1
  87. package/dist/ui/drilldowns/feed.d.ts +0 -11
  88. package/dist/ui/drilldowns/feed.d.ts.map +0 -1
  89. package/dist/ui/drilldowns/feed.js +0 -68
  90. package/dist/ui/drilldowns/feed.js.map +0 -1
  91. package/dist/ui/drilldowns/index.d.ts +0 -7
  92. package/dist/ui/drilldowns/index.d.ts.map +0 -1
  93. package/dist/ui/drilldowns/index.js +0 -8
  94. package/dist/ui/drilldowns/index.js.map +0 -1
  95. package/dist/ui/drilldowns/posture.d.ts +0 -11
  96. package/dist/ui/drilldowns/posture.d.ts.map +0 -1
  97. package/dist/ui/drilldowns/posture.js +0 -74
  98. package/dist/ui/drilldowns/posture.js.map +0 -1
  99. package/dist/ui/intelligence-posture-view.d.ts +0 -22
  100. package/dist/ui/intelligence-posture-view.d.ts.map +0 -1
  101. package/dist/ui/intelligence-posture-view.js +0 -169
  102. package/dist/ui/intelligence-posture-view.js.map +0 -1
  103. package/dist/ui/navigation/keymaps.d.ts +0 -26
  104. package/dist/ui/navigation/keymaps.d.ts.map +0 -1
  105. package/dist/ui/navigation/keymaps.js +0 -135
  106. package/dist/ui/navigation/keymaps.js.map +0 -1
  107. package/dist/ui/navigation/palette.d.ts +0 -10
  108. package/dist/ui/navigation/palette.d.ts.map +0 -1
  109. package/dist/ui/navigation/palette.js +0 -133
  110. package/dist/ui/navigation/palette.js.map +0 -1
  111. package/dist/ui/navigation/state.d.ts +0 -47
  112. package/dist/ui/navigation/state.d.ts.map +0 -1
  113. package/dist/ui/navigation/state.js +0 -84
  114. package/dist/ui/navigation/state.js.map +0 -1
  115. package/dist/ui/navigation/types.d.ts +0 -38
  116. package/dist/ui/navigation/types.d.ts.map +0 -1
  117. package/dist/ui/navigation/types.js +0 -36
  118. package/dist/ui/navigation/types.js.map +0 -1
  119. package/dist/ui/panels/active-assets.d.ts +0 -12
  120. package/dist/ui/panels/active-assets.d.ts.map +0 -1
  121. package/dist/ui/panels/active-assets.js +0 -83
  122. package/dist/ui/panels/active-assets.js.map +0 -1
  123. package/dist/ui/panels/capability-flags.d.ts +0 -12
  124. package/dist/ui/panels/capability-flags.d.ts.map +0 -1
  125. package/dist/ui/panels/capability-flags.js +0 -59
  126. package/dist/ui/panels/capability-flags.js.map +0 -1
  127. package/dist/ui/panels/command-surface.d.ts +0 -12
  128. package/dist/ui/panels/command-surface.d.ts.map +0 -1
  129. package/dist/ui/panels/command-surface.js +0 -55
  130. package/dist/ui/panels/command-surface.js.map +0 -1
  131. package/dist/ui/panels/network-origin.d.ts +0 -12
  132. package/dist/ui/panels/network-origin.d.ts.map +0 -1
  133. package/dist/ui/panels/network-origin.js +0 -79
  134. package/dist/ui/panels/network-origin.js.map +0 -1
  135. package/dist/ui/panels/operations-feed.d.ts +0 -12
  136. package/dist/ui/panels/operations-feed.d.ts.map +0 -1
  137. package/dist/ui/panels/operations-feed.js +0 -90
  138. package/dist/ui/panels/operations-feed.js.map +0 -1
  139. package/dist/ui/panels/posture.d.ts +0 -12
  140. package/dist/ui/panels/posture.d.ts.map +0 -1
  141. package/dist/ui/panels/posture.js +0 -84
  142. package/dist/ui/panels/posture.js.map +0 -1
  143. package/dist/ui/panels/resources.d.ts +0 -11
  144. package/dist/ui/panels/resources.d.ts.map +0 -1
  145. package/dist/ui/panels/resources.js +0 -88
  146. package/dist/ui/panels/resources.js.map +0 -1
  147. package/dist/ui/primitives/Panel.d.ts +0 -25
  148. package/dist/ui/primitives/Panel.d.ts.map +0 -1
  149. package/dist/ui/primitives/Panel.js +0 -59
  150. package/dist/ui/primitives/Panel.js.map +0 -1
  151. package/dist/ui/rendering/metricRenderer.d.ts +0 -24
  152. package/dist/ui/rendering/metricRenderer.d.ts.map +0 -1
  153. package/dist/ui/rendering/metricRenderer.js +0 -86
  154. package/dist/ui/rendering/metricRenderer.js.map +0 -1
  155. package/dist/ui/runtime/hub.d.ts +0 -12
  156. package/dist/ui/runtime/hub.d.ts.map +0 -1
  157. package/dist/ui/runtime/hub.js +0 -486
  158. package/dist/ui/runtime/hub.js.map +0 -1
  159. package/dist/ui/runtime/hubValidation.d.ts +0 -23
  160. package/dist/ui/runtime/hubValidation.d.ts.map +0 -1
  161. package/dist/ui/runtime/hubValidation.js +0 -90
  162. package/dist/ui/runtime/hubValidation.js.map +0 -1
  163. package/dist/ui/runtime/index.d.ts +0 -29
  164. package/dist/ui/runtime/index.d.ts.map +0 -1
  165. package/dist/ui/runtime/index.js +0 -297
  166. package/dist/ui/runtime/index.js.map +0 -1
  167. package/dist/ui/runtime/no-tui.d.ts +0 -12
  168. package/dist/ui/runtime/no-tui.d.ts.map +0 -1
  169. package/dist/ui/runtime/no-tui.js +0 -77
  170. package/dist/ui/runtime/no-tui.js.map +0 -1
  171. package/dist/ui/runtime/state-builder.d.ts +0 -13
  172. package/dist/ui/runtime/state-builder.d.ts.map +0 -1
  173. package/dist/ui/runtime/state-builder.js +0 -114
  174. package/dist/ui/runtime/state-builder.js.map +0 -1
  175. package/dist/ui/runtime/terminalSizeCheck.d.ts +0 -10
  176. package/dist/ui/runtime/terminalSizeCheck.d.ts.map +0 -1
  177. package/dist/ui/runtime/terminalSizeCheck.js +0 -51
  178. package/dist/ui/runtime/terminalSizeCheck.js.map +0 -1
  179. package/dist/ui/runtime/tuiLogGate.d.ts +0 -22
  180. package/dist/ui/runtime/tuiLogGate.d.ts.map +0 -1
  181. package/dist/ui/runtime/tuiLogGate.js +0 -68
  182. package/dist/ui/runtime/tuiLogGate.js.map +0 -1
  183. package/dist/ui/state/types.d.ts +0 -72
  184. package/dist/ui/state/types.d.ts.map +0 -1
  185. package/dist/ui/state/types.js +0 -6
  186. package/dist/ui/state/types.js.map +0 -1
  187. package/dist/ui/theme/borders.d.ts +0 -20
  188. package/dist/ui/theme/borders.d.ts.map +0 -1
  189. package/dist/ui/theme/borders.js +0 -55
  190. package/dist/ui/theme/borders.js.map +0 -1
  191. package/dist/ui/theme/tokens.d.ts +0 -28
  192. package/dist/ui/theme/tokens.d.ts.map +0 -1
  193. package/dist/ui/theme/tokens.js +0 -50
  194. package/dist/ui/theme/tokens.js.map +0 -1
  195. package/dist/ui/theme/typography.d.ts +0 -14
  196. package/dist/ui/theme/typography.d.ts.map +0 -1
  197. package/dist/ui/theme/typography.js +0 -30
  198. package/dist/ui/theme/typography.js.map +0 -1
  199. package/dist/ui/v3/collectors/assets.collector.d.ts +0 -20
  200. package/dist/ui/v3/collectors/assets.collector.d.ts.map +0 -1
  201. package/dist/ui/v3/collectors/assets.collector.js +0 -80
  202. package/dist/ui/v3/collectors/assets.collector.js.map +0 -1
  203. package/dist/ui/v3/collectors/capabilities.collector.d.ts +0 -18
  204. package/dist/ui/v3/collectors/capabilities.collector.d.ts.map +0 -1
  205. package/dist/ui/v3/collectors/capabilities.collector.js +0 -113
  206. package/dist/ui/v3/collectors/capabilities.collector.js.map +0 -1
  207. package/dist/ui/v3/collectors/network.collector.d.ts +0 -18
  208. package/dist/ui/v3/collectors/network.collector.d.ts.map +0 -1
  209. package/dist/ui/v3/collectors/network.collector.js +0 -37
  210. package/dist/ui/v3/collectors/network.collector.js.map +0 -1
  211. package/dist/ui/v3/collectors/posture.derive.d.ts +0 -24
  212. package/dist/ui/v3/collectors/posture.derive.d.ts.map +0 -1
  213. package/dist/ui/v3/collectors/posture.derive.js +0 -57
  214. package/dist/ui/v3/collectors/posture.derive.js.map +0 -1
  215. package/dist/ui/v3/collectors/resources.d.ts +0 -23
  216. package/dist/ui/v3/collectors/resources.d.ts.map +0 -1
  217. package/dist/ui/v3/collectors/resources.js +0 -136
  218. package/dist/ui/v3/collectors/resources.js.map +0 -1
  219. package/dist/ui/v3/commands/commandEngine.d.ts +0 -77
  220. package/dist/ui/v3/commands/commandEngine.d.ts.map +0 -1
  221. package/dist/ui/v3/commands/commandEngine.js +0 -3289
  222. package/dist/ui/v3/commands/commandEngine.js.map +0 -1
  223. package/dist/ui/v3/commands/commandResult.d.ts +0 -25
  224. package/dist/ui/v3/commands/commandResult.d.ts.map +0 -1
  225. package/dist/ui/v3/commands/commandResult.js +0 -19
  226. package/dist/ui/v3/commands/commandResult.js.map +0 -1
  227. package/dist/ui/v3/commands/diagnose.d.ts +0 -17
  228. package/dist/ui/v3/commands/diagnose.d.ts.map +0 -1
  229. package/dist/ui/v3/commands/diagnose.js +0 -62
  230. package/dist/ui/v3/commands/diagnose.js.map +0 -1
  231. package/dist/ui/v3/commands/errorClassifier.d.ts +0 -23
  232. package/dist/ui/v3/commands/errorClassifier.d.ts.map +0 -1
  233. package/dist/ui/v3/commands/errorClassifier.js +0 -63
  234. package/dist/ui/v3/commands/errorClassifier.js.map +0 -1
  235. package/dist/ui/v3/commands/parser.d.ts +0 -14
  236. package/dist/ui/v3/commands/parser.d.ts.map +0 -1
  237. package/dist/ui/v3/commands/parser.js +0 -29
  238. package/dist/ui/v3/commands/parser.js.map +0 -1
  239. package/dist/ui/v3/commands/router.d.ts +0 -13
  240. package/dist/ui/v3/commands/router.d.ts.map +0 -1
  241. package/dist/ui/v3/commands/router.js +0 -150
  242. package/dist/ui/v3/commands/router.js.map +0 -1
  243. package/dist/ui/v3/config/gateway.d.ts +0 -40
  244. package/dist/ui/v3/config/gateway.d.ts.map +0 -1
  245. package/dist/ui/v3/config/gateway.js +0 -113
  246. package/dist/ui/v3/config/gateway.js.map +0 -1
  247. package/dist/ui/v3/core/event.d.ts +0 -19
  248. package/dist/ui/v3/core/event.d.ts.map +0 -1
  249. package/dist/ui/v3/core/event.js +0 -7
  250. package/dist/ui/v3/core/event.js.map +0 -1
  251. package/dist/ui/v3/core/eventBus.d.ts +0 -39
  252. package/dist/ui/v3/core/eventBus.d.ts.map +0 -1
  253. package/dist/ui/v3/core/eventBus.js +0 -79
  254. package/dist/ui/v3/core/eventBus.js.map +0 -1
  255. package/dist/ui/v3/core/feedStore.d.ts +0 -34
  256. package/dist/ui/v3/core/feedStore.d.ts.map +0 -1
  257. package/dist/ui/v3/core/feedStore.js +0 -46
  258. package/dist/ui/v3/core/feedStore.js.map +0 -1
  259. package/dist/ui/v3/core/logger.d.ts +0 -40
  260. package/dist/ui/v3/core/logger.d.ts.map +0 -1
  261. package/dist/ui/v3/core/logger.js +0 -191
  262. package/dist/ui/v3/core/logger.js.map +0 -1
  263. package/dist/ui/v3/core/opEvent.d.ts +0 -15
  264. package/dist/ui/v3/core/opEvent.d.ts.map +0 -1
  265. package/dist/ui/v3/core/opEvent.js +0 -7
  266. package/dist/ui/v3/core/opEvent.js.map +0 -1
  267. package/dist/ui/v3/index.d.ts +0 -8
  268. package/dist/ui/v3/index.d.ts.map +0 -1
  269. package/dist/ui/v3/index.js +0 -51
  270. package/dist/ui/v3/index.js.map +0 -1
  271. package/dist/ui/v3/runtime/moduleConfig.d.ts +0 -21
  272. package/dist/ui/v3/runtime/moduleConfig.d.ts.map +0 -1
  273. package/dist/ui/v3/runtime/moduleConfig.js +0 -41
  274. package/dist/ui/v3/runtime/moduleConfig.js.map +0 -1
  275. package/dist/ui/v3/section0/index.d.ts +0 -22
  276. package/dist/ui/v3/section0/index.d.ts.map +0 -1
  277. package/dist/ui/v3/section0/index.js +0 -88
  278. package/dist/ui/v3/section0/index.js.map +0 -1
  279. package/dist/ui/v3/section0/runtime/createScreen.d.ts +0 -27
  280. package/dist/ui/v3/section0/runtime/createScreen.d.ts.map +0 -1
  281. package/dist/ui/v3/section0/runtime/createScreen.js +0 -55
  282. package/dist/ui/v3/section0/runtime/createScreen.js.map +0 -1
  283. package/dist/ui/v3/section0/runtime/lifecycle.d.ts +0 -53
  284. package/dist/ui/v3/section0/runtime/lifecycle.d.ts.map +0 -1
  285. package/dist/ui/v3/section0/runtime/lifecycle.js +0 -172
  286. package/dist/ui/v3/section0/runtime/lifecycle.js.map +0 -1
  287. package/dist/ui/v3/section1/index.d.ts +0 -19
  288. package/dist/ui/v3/section1/index.d.ts.map +0 -1
  289. package/dist/ui/v3/section1/index.js +0 -413
  290. package/dist/ui/v3/section1/index.js.map +0 -1
  291. package/dist/ui/v3/section1/runtime/commandLine.d.ts +0 -49
  292. package/dist/ui/v3/section1/runtime/commandLine.d.ts.map +0 -1
  293. package/dist/ui/v3/section1/runtime/commandLine.js +0 -183
  294. package/dist/ui/v3/section1/runtime/commandLine.js.map +0 -1
  295. package/dist/ui/v3/section1/runtime/focusLock.d.ts +0 -24
  296. package/dist/ui/v3/section1/runtime/focusLock.d.ts.map +0 -1
  297. package/dist/ui/v3/section1/runtime/focusLock.js +0 -44
  298. package/dist/ui/v3/section1/runtime/focusLock.js.map +0 -1
  299. package/dist/ui/v3/state/assertUiState.d.ts +0 -27
  300. package/dist/ui/v3/state/assertUiState.d.ts.map +0 -1
  301. package/dist/ui/v3/state/assertUiState.js +0 -89
  302. package/dist/ui/v3/state/assertUiState.js.map +0 -1
  303. package/dist/ui/v3/state/capabilitiesStore.d.ts +0 -54
  304. package/dist/ui/v3/state/capabilitiesStore.d.ts.map +0 -1
  305. package/dist/ui/v3/state/capabilitiesStore.js +0 -76
  306. package/dist/ui/v3/state/capabilitiesStore.js.map +0 -1
  307. package/dist/ui/v3/state/defaultState.d.ts +0 -19
  308. package/dist/ui/v3/state/defaultState.d.ts.map +0 -1
  309. package/dist/ui/v3/state/defaultState.js +0 -28
  310. package/dist/ui/v3/state/defaultState.js.map +0 -1
  311. package/dist/ui/v3/state/gatewayConnectionStore.d.ts +0 -72
  312. package/dist/ui/v3/state/gatewayConnectionStore.d.ts.map +0 -1
  313. package/dist/ui/v3/state/gatewayConnectionStore.js +0 -108
  314. package/dist/ui/v3/state/gatewayConnectionStore.js.map +0 -1
  315. package/dist/ui/v3/state/initializePostureState.d.ts +0 -23
  316. package/dist/ui/v3/state/initializePostureState.d.ts.map +0 -1
  317. package/dist/ui/v3/state/initializePostureState.js +0 -41
  318. package/dist/ui/v3/state/initializePostureState.js.map +0 -1
  319. package/dist/ui/v3/state/panelStore.d.ts +0 -80
  320. package/dist/ui/v3/state/panelStore.d.ts.map +0 -1
  321. package/dist/ui/v3/state/panelStore.js +0 -131
  322. package/dist/ui/v3/state/panelStore.js.map +0 -1
  323. package/dist/ui/v3/state/resourcesData.d.ts +0 -15
  324. package/dist/ui/v3/state/resourcesData.d.ts.map +0 -1
  325. package/dist/ui/v3/state/resourcesData.js +0 -7
  326. package/dist/ui/v3/state/resourcesData.js.map +0 -1
  327. package/dist/ui/v3/state/uiState.d.ts +0 -22
  328. package/dist/ui/v3/state/uiState.d.ts.map +0 -1
  329. package/dist/ui/v3/state/uiState.js +0 -13
  330. package/dist/ui/v3/state/uiState.js.map +0 -1
  331. package/dist/ui/v3/state/uiStateBuilder.d.ts +0 -32
  332. package/dist/ui/v3/state/uiStateBuilder.d.ts.map +0 -1
  333. package/dist/ui/v3/state/uiStateBuilder.js +0 -73
  334. package/dist/ui/v3/state/uiStateBuilder.js.map +0 -1
  335. package/dist/ui/v3/state/uiStateTypes.d.ts +0 -59
  336. package/dist/ui/v3/state/uiStateTypes.d.ts.map +0 -1
  337. package/dist/ui/v3/state/uiStateTypes.js +0 -8
  338. package/dist/ui/v3/state/uiStateTypes.js.map +0 -1
  339. package/dist/ui/v3/state/value.d.ts +0 -80
  340. package/dist/ui/v3/state/value.d.ts.map +0 -1
  341. package/dist/ui/v3/state/value.js +0 -96
  342. package/dist/ui/v3/state/value.js.map +0 -1
  343. package/dist/ui/v3/tui/geometry.d.ts +0 -83
  344. package/dist/ui/v3/tui/geometry.d.ts.map +0 -1
  345. package/dist/ui/v3/tui/geometry.js +0 -201
  346. package/dist/ui/v3/tui/geometry.js.map +0 -1
  347. package/dist/ui/v3/tui/startTui.d.ts +0 -37
  348. package/dist/ui/v3/tui/startTui.d.ts.map +0 -1
  349. package/dist/ui/v3/tui/startTui.js +0 -61
  350. package/dist/ui/v3/tui/startTui.js.map +0 -1
  351. package/dist/ui/v3/tui/terminalMode.d.ts +0 -31
  352. package/dist/ui/v3/tui/terminalMode.d.ts.map +0 -1
  353. package/dist/ui/v3/tui/terminalMode.js +0 -76
  354. package/dist/ui/v3/tui/terminalMode.js.map +0 -1
  355. package/dist/ui/v3/ui/debugUtils.d.ts +0 -67
  356. package/dist/ui/v3/ui/debugUtils.d.ts.map +0 -1
  357. package/dist/ui/v3/ui/debugUtils.js +0 -238
  358. package/dist/ui/v3/ui/debugUtils.js.map +0 -1
  359. package/dist/ui/v3/ui/focus.d.ts +0 -28
  360. package/dist/ui/v3/ui/focus.d.ts.map +0 -1
  361. package/dist/ui/v3/ui/focus.js +0 -38
  362. package/dist/ui/v3/ui/focus.js.map +0 -1
  363. package/dist/ui/v3/ui/layout/hubLayout.d.ts +0 -43
  364. package/dist/ui/v3/ui/layout/hubLayout.d.ts.map +0 -1
  365. package/dist/ui/v3/ui/layout/hubLayout.js +0 -170
  366. package/dist/ui/v3/ui/layout/hubLayout.js.map +0 -1
  367. package/dist/ui/v3/ui/layout/phase1Layout.d.ts +0 -63
  368. package/dist/ui/v3/ui/layout/phase1Layout.d.ts.map +0 -1
  369. package/dist/ui/v3/ui/layout/phase1Layout.js +0 -274
  370. package/dist/ui/v3/ui/layout/phase1Layout.js.map +0 -1
  371. package/dist/ui/v3/ui/layout/phase1Layout.test.d.ts +0 -5
  372. package/dist/ui/v3/ui/layout/phase1Layout.test.d.ts.map +0 -1
  373. package/dist/ui/v3/ui/layout/phase1Layout.test.js +0 -120
  374. package/dist/ui/v3/ui/layout/phase1Layout.test.js.map +0 -1
  375. package/dist/ui/v3/ui/minimalRuntime.d.ts +0 -14
  376. package/dist/ui/v3/ui/minimalRuntime.d.ts.map +0 -1
  377. package/dist/ui/v3/ui/minimalRuntime.js +0 -111
  378. package/dist/ui/v3/ui/minimalRuntime.js.map +0 -1
  379. package/dist/ui/v3/ui/panels/AssetsPanel.d.ts +0 -17
  380. package/dist/ui/v3/ui/panels/AssetsPanel.d.ts.map +0 -1
  381. package/dist/ui/v3/ui/panels/AssetsPanel.js +0 -53
  382. package/dist/ui/v3/ui/panels/AssetsPanel.js.map +0 -1
  383. package/dist/ui/v3/ui/panels/CapabilitiesPanel.d.ts +0 -20
  384. package/dist/ui/v3/ui/panels/CapabilitiesPanel.d.ts.map +0 -1
  385. package/dist/ui/v3/ui/panels/CapabilitiesPanel.js +0 -67
  386. package/dist/ui/v3/ui/panels/CapabilitiesPanel.js.map +0 -1
  387. package/dist/ui/v3/ui/panels/NetworkPanel.d.ts +0 -31
  388. package/dist/ui/v3/ui/panels/NetworkPanel.d.ts.map +0 -1
  389. package/dist/ui/v3/ui/panels/NetworkPanel.js +0 -153
  390. package/dist/ui/v3/ui/panels/NetworkPanel.js.map +0 -1
  391. package/dist/ui/v3/ui/panels/PosturePanel.d.ts +0 -16
  392. package/dist/ui/v3/ui/panels/PosturePanel.d.ts.map +0 -1
  393. package/dist/ui/v3/ui/panels/PosturePanel.js +0 -60
  394. package/dist/ui/v3/ui/panels/PosturePanel.js.map +0 -1
  395. package/dist/ui/v3/ui/panels/ResourcesPanel.d.ts +0 -20
  396. package/dist/ui/v3/ui/panels/ResourcesPanel.d.ts.map +0 -1
  397. package/dist/ui/v3/ui/panels/ResourcesPanel.js +0 -66
  398. package/dist/ui/v3/ui/panels/ResourcesPanel.js.map +0 -1
  399. package/dist/ui/v3/ui/phase1Runtime.d.ts +0 -29
  400. package/dist/ui/v3/ui/phase1Runtime.d.ts.map +0 -1
  401. package/dist/ui/v3/ui/phase1Runtime.js +0 -1648
  402. package/dist/ui/v3/ui/phase1Runtime.js.map +0 -1
  403. package/dist/ui/v3/ui/phase1RuntimeClean.d.ts +0 -34
  404. package/dist/ui/v3/ui/phase1RuntimeClean.d.ts.map +0 -1
  405. package/dist/ui/v3/ui/phase1RuntimeClean.js +0 -1841
  406. package/dist/ui/v3/ui/phase1RuntimeClean.js.map +0 -1
  407. package/dist/ui/v3/ui/primitives/Panel.d.ts +0 -39
  408. package/dist/ui/v3/ui/primitives/Panel.d.ts.map +0 -1
  409. package/dist/ui/v3/ui/primitives/Panel.js +0 -105
  410. package/dist/ui/v3/ui/primitives/Panel.js.map +0 -1
  411. package/dist/ui/v3/ui/theme.d.ts +0 -37
  412. package/dist/ui/v3/ui/theme.d.ts.map +0 -1
  413. package/dist/ui/v3/ui/theme.js +0 -40
  414. package/dist/ui/v3/ui/theme.js.map +0 -1
  415. package/dist/ui/v3/ui/uiRuntime.d.ts +0 -40
  416. package/dist/ui/v3/ui/uiRuntime.d.ts.map +0 -1
  417. package/dist/ui/v3/ui/uiRuntime.js +0 -60
  418. package/dist/ui/v3/ui/uiRuntime.js.map +0 -1
  419. package/dist/ui/v3/ui/widgets/CommandLine.d.ts +0 -26
  420. package/dist/ui/v3/ui/widgets/CommandLine.d.ts.map +0 -1
  421. package/dist/ui/v3/ui/widgets/CommandLine.js +0 -67
  422. package/dist/ui/v3/ui/widgets/CommandLine.js.map +0 -1
  423. package/dist/ui/v3/v1Adapters/agents.d.ts +0 -72
  424. package/dist/ui/v3/v1Adapters/agents.d.ts.map +0 -1
  425. package/dist/ui/v3/v1Adapters/agents.js +0 -182
  426. package/dist/ui/v3/v1Adapters/agents.js.map +0 -1
  427. package/dist/ui/v3/v1Adapters/config.d.ts +0 -67
  428. package/dist/ui/v3/v1Adapters/config.d.ts.map +0 -1
  429. package/dist/ui/v3/v1Adapters/config.js +0 -78
  430. package/dist/ui/v3/v1Adapters/config.js.map +0 -1
  431. package/dist/ui/v3/v1Adapters/connect.d.ts +0 -77
  432. package/dist/ui/v3/v1Adapters/connect.d.ts.map +0 -1
  433. package/dist/ui/v3/v1Adapters/connect.js +0 -576
  434. package/dist/ui/v3/v1Adapters/connect.js.map +0 -1
  435. package/dist/ui/v3/v1Adapters/httpDebug.d.ts +0 -19
  436. package/dist/ui/v3/v1Adapters/httpDebug.d.ts.map +0 -1
  437. package/dist/ui/v3/v1Adapters/httpDebug.js +0 -60
  438. package/dist/ui/v3/v1Adapters/httpDebug.js.map +0 -1
  439. package/dist/ui/v3/v1Adapters/runs.d.ts +0 -77
  440. package/dist/ui/v3/v1Adapters/runs.d.ts.map +0 -1
  441. package/dist/ui/v3/v1Adapters/runs.js +0 -339
  442. package/dist/ui/v3/v1Adapters/runs.js.map +0 -1
  443. package/dist/ui/v4/engine/renderFrame.d.ts +0 -47
  444. package/dist/ui/v4/engine/renderFrame.d.ts.map +0 -1
  445. package/dist/ui/v4/engine/renderFrame.js +0 -653
  446. package/dist/ui/v4/engine/renderFrame.js.map +0 -1
  447. package/dist/ui/v4/engine/resizeController.d.ts +0 -48
  448. package/dist/ui/v4/engine/resizeController.d.ts.map +0 -1
  449. package/dist/ui/v4/engine/resizeController.js +0 -285
  450. package/dist/ui/v4/engine/resizeController.js.map +0 -1
  451. package/dist/ui/v4/engine/safeViewport.d.ts +0 -47
  452. package/dist/ui/v4/engine/safeViewport.d.ts.map +0 -1
  453. package/dist/ui/v4/engine/safeViewport.js +0 -123
  454. package/dist/ui/v4/engine/safeViewport.js.map +0 -1
  455. package/dist/ui/v4/engine/terminalProfile.d.ts +0 -56
  456. package/dist/ui/v4/engine/terminalProfile.d.ts.map +0 -1
  457. package/dist/ui/v4/engine/terminalProfile.js +0 -115
  458. package/dist/ui/v4/engine/terminalProfile.js.map +0 -1
  459. package/dist/ui/v4/index.d.ts +0 -28
  460. package/dist/ui/v4/index.d.ts.map +0 -1
  461. package/dist/ui/v4/index.js +0 -993
  462. package/dist/ui/v4/index.js.map +0 -1
  463. package/dist/ui/v4/layout/layoutEngine.d.ts +0 -62
  464. package/dist/ui/v4/layout/layoutEngine.d.ts.map +0 -1
  465. package/dist/ui/v4/layout/layoutEngine.js +0 -294
  466. package/dist/ui/v4/layout/layoutEngine.js.map +0 -1
  467. package/dist/ui/v4/runtime/keepAlive.d.ts +0 -21
  468. package/dist/ui/v4/runtime/keepAlive.d.ts.map +0 -1
  469. package/dist/ui/v4/runtime/keepAlive.js +0 -149
  470. package/dist/ui/v4/runtime/keepAlive.js.map +0 -1
  471. package/dist/ui/v4/runtime/logger.d.ts +0 -35
  472. package/dist/ui/v4/runtime/logger.d.ts.map +0 -1
  473. package/dist/ui/v4/runtime/logger.js +0 -109
  474. package/dist/ui/v4/runtime/logger.js.map +0 -1
  475. package/dist/ui/v5/debug/assertNoOverflow.d.ts +0 -28
  476. package/dist/ui/v5/debug/assertNoOverflow.d.ts.map +0 -1
  477. package/dist/ui/v5/debug/assertNoOverflow.js +0 -63
  478. package/dist/ui/v5/debug/assertNoOverflow.js.map +0 -1
  479. package/dist/ui/v5/debug/debugCommands.d.ts +0 -20
  480. package/dist/ui/v5/debug/debugCommands.d.ts.map +0 -1
  481. package/dist/ui/v5/debug/debugCommands.js +0 -461
  482. package/dist/ui/v5/debug/debugCommands.js.map +0 -1
  483. package/dist/ui/v5/debugCommands.d.ts +0 -20
  484. package/dist/ui/v5/debugCommands.d.ts.map +0 -1
  485. package/dist/ui/v5/debugCommands.js +0 -81
  486. package/dist/ui/v5/debugCommands.js.map +0 -1
  487. package/dist/ui/v5/guardrails/stdoutGuard.d.ts +0 -23
  488. package/dist/ui/v5/guardrails/stdoutGuard.d.ts.map +0 -1
  489. package/dist/ui/v5/guardrails/stdoutGuard.js +0 -94
  490. package/dist/ui/v5/guardrails/stdoutGuard.js.map +0 -1
  491. package/dist/ui/v5/guardrails/terminalRestore.d.ts +0 -17
  492. package/dist/ui/v5/guardrails/terminalRestore.d.ts.map +0 -1
  493. package/dist/ui/v5/guardrails/terminalRestore.js +0 -47
  494. package/dist/ui/v5/guardrails/terminalRestore.js.map +0 -1
  495. package/dist/ui/v5/index.d.ts +0 -30
  496. package/dist/ui/v5/index.d.ts.map +0 -1
  497. package/dist/ui/v5/index.js +0 -243
  498. package/dist/ui/v5/index.js.map +0 -1
  499. package/dist/ui/v5/kernel/kernel.d.ts +0 -81
  500. package/dist/ui/v5/kernel/kernel.d.ts.map +0 -1
  501. package/dist/ui/v5/kernel/kernel.js +0 -339
  502. package/dist/ui/v5/kernel/kernel.js.map +0 -1
  503. package/dist/ui/v5/kernel.d.ts +0 -75
  504. package/dist/ui/v5/kernel.d.ts.map +0 -1
  505. package/dist/ui/v5/kernel.js +0 -289
  506. package/dist/ui/v5/kernel.js.map +0 -1
  507. package/dist/ui/v5/layout/clampRect.d.ts +0 -28
  508. package/dist/ui/v5/layout/clampRect.d.ts.map +0 -1
  509. package/dist/ui/v5/layout/clampRect.js +0 -45
  510. package/dist/ui/v5/layout/clampRect.js.map +0 -1
  511. package/dist/ui/v5/layout/layoutEngine.d.ts +0 -16
  512. package/dist/ui/v5/layout/layoutEngine.d.ts.map +0 -1
  513. package/dist/ui/v5/layout/layoutEngine.js +0 -99
  514. package/dist/ui/v5/layout/layoutEngine.js.map +0 -1
  515. package/dist/ui/v5/renderGate.d.ts +0 -19
  516. package/dist/ui/v5/renderGate.d.ts.map +0 -1
  517. package/dist/ui/v5/renderGate.js +0 -36
  518. package/dist/ui/v5/renderGate.js.map +0 -1
  519. package/dist/ui/v5/resize/resizeController.d.ts +0 -62
  520. package/dist/ui/v5/resize/resizeController.d.ts.map +0 -1
  521. package/dist/ui/v5/resize/resizeController.js +0 -141
  522. package/dist/ui/v5/resize/resizeController.js.map +0 -1
  523. package/dist/ui/v5/resizeController.d.ts +0 -55
  524. package/dist/ui/v5/resizeController.d.ts.map +0 -1
  525. package/dist/ui/v5/resizeController.js +0 -124
  526. package/dist/ui/v5/resizeController.js.map +0 -1
  527. package/dist/ui/v5/runtime/keepAlive.d.ts +0 -37
  528. package/dist/ui/v5/runtime/keepAlive.d.ts.map +0 -1
  529. package/dist/ui/v5/runtime/keepAlive.js +0 -122
  530. package/dist/ui/v5/runtime/keepAlive.js.map +0 -1
  531. package/dist/ui/v5/runtime/restoreTerminal.d.ts +0 -34
  532. package/dist/ui/v5/runtime/restoreTerminal.d.ts.map +0 -1
  533. package/dist/ui/v5/runtime/restoreTerminal.js +0 -100
  534. package/dist/ui/v5/runtime/restoreTerminal.js.map +0 -1
  535. package/dist/ui/v5/runtime/stdoutGuard.d.ts +0 -42
  536. package/dist/ui/v5/runtime/stdoutGuard.d.ts.map +0 -1
  537. package/dist/ui/v5/runtime/stdoutGuard.js +0 -156
  538. package/dist/ui/v5/runtime/stdoutGuard.js.map +0 -1
  539. package/dist/ui/v5/viewport/getViewport.d.ts +0 -23
  540. package/dist/ui/v5/viewport/getViewport.d.ts.map +0 -1
  541. package/dist/ui/v5/viewport/getViewport.js +0 -117
  542. package/dist/ui/v5/viewport/getViewport.js.map +0 -1
  543. package/dist/ui/v5/viewport.d.ts +0 -41
  544. package/dist/ui/v5/viewport.d.ts.map +0 -1
  545. package/dist/ui/v5/viewport.js +0 -90
  546. package/dist/ui/v5/viewport.js.map +0 -1
  547. package/dist/ui/widgets/flagRow.d.ts +0 -25
  548. package/dist/ui/widgets/flagRow.d.ts.map +0 -1
  549. package/dist/ui/widgets/flagRow.js +0 -57
  550. package/dist/ui/widgets/flagRow.js.map +0 -1
  551. package/dist/ui/widgets/index.d.ts +0 -9
  552. package/dist/ui/widgets/index.d.ts.map +0 -1
  553. package/dist/ui/widgets/index.js +0 -9
  554. package/dist/ui/widgets/index.js.map +0 -1
  555. package/dist/ui/widgets/meter.d.ts +0 -18
  556. package/dist/ui/widgets/meter.d.ts.map +0 -1
  557. package/dist/ui/widgets/meter.js +0 -38
  558. package/dist/ui/widgets/meter.js.map +0 -1
  559. package/dist/ui/widgets/miniMap.d.ts +0 -26
  560. package/dist/ui/widgets/miniMap.d.ts.map +0 -1
  561. package/dist/ui/widgets/miniMap.js +0 -94
  562. package/dist/ui/widgets/miniMap.js.map +0 -1
  563. package/dist/ui/widgets/sparkline.d.ts +0 -17
  564. package/dist/ui/widgets/sparkline.d.ts.map +0 -1
  565. package/dist/ui/widgets/sparkline.js +0 -65
  566. package/dist/ui/widgets/sparkline.js.map +0 -1
@@ -1,3289 +0,0 @@
1
- /**
2
- * Section 3: Command Engine (UI-Agnostic)
3
- *
4
- * Pure command engine that sits between command line and UI state.
5
- *
6
- * Rules:
7
- * - Does not know about blessed
8
- * - Does not render UI
9
- * - Does not contain business logic
10
- * - Only parses input, executes commands, and emits structured results
11
- * - UI layer consumes results and mutates UiState
12
- *
13
- * Architectural Rule (Non-Negotiable):
14
- * - UI-agnostic
15
- * - Side-effect free
16
- * - Deterministic
17
- */
18
- import { available, unavailable } from '../state/value.js';
19
- import { listAgents, getAgent, createAgent as v1CreateAgent } from '../v1Adapters/agents.js';
20
- import { connect as v1Connect } from '../v1Adapters/connect.js';
21
- import { startRun, listRuns } from '../v1Adapters/runs.js';
22
- import { loadConfig } from '../v1Adapters/config.js';
23
- import { diagnoseGateway } from './diagnose.js';
24
- import { classifyError } from './errorClassifier.js';
25
- import { URL } from 'url';
26
- /**
27
- * UI actions that the UI layer interprets
28
- */
29
- export var UiAction;
30
- (function (UiAction) {
31
- UiAction["EXIT"] = "EXIT";
32
- UiAction["CLEAR_FEED"] = "CLEAR_FEED";
33
- UiAction["HOME"] = "HOME";
34
- })(UiAction || (UiAction = {}));
35
- /**
36
- * Parse command line input
37
- *
38
- * Responsibilities:
39
- * - Trim leading/trailing whitespace
40
- * - Support quoted arguments: "quoted value" and 'quoted value'
41
- * - Preserve spaces inside quotes
42
- * - Split unquoted tokens on whitespace
43
- *
44
- * Rules:
45
- * - Empty input → return { name: "", args: [], raw }
46
- * - Parsing never throws
47
- * - Parsing never emits UI output
48
- */
49
- export function parse(line) {
50
- const raw = line;
51
- const trimmed = line.trim();
52
- // Empty input
53
- if (!trimmed) {
54
- return { name: '', args: [], raw };
55
- }
56
- // Remove prompt if present
57
- const withoutPrompt = trimmed.replace(/^4runr>\s*/, '').trim();
58
- if (!withoutPrompt) {
59
- return { name: '', args: [], raw };
60
- }
61
- // Parse with quoted argument support
62
- const tokens = [];
63
- let current = '';
64
- let inDoubleQuote = false;
65
- let inSingleQuote = false;
66
- for (let i = 0; i < withoutPrompt.length; i++) {
67
- const char = withoutPrompt[i];
68
- if (char === '"' && !inSingleQuote) {
69
- if (inDoubleQuote) {
70
- // End of double-quoted string
71
- tokens.push(current);
72
- current = '';
73
- inDoubleQuote = false;
74
- }
75
- else {
76
- // Start of double-quoted string
77
- inDoubleQuote = true;
78
- }
79
- }
80
- else if (char === "'" && !inDoubleQuote) {
81
- if (inSingleQuote) {
82
- // End of single-quoted string
83
- tokens.push(current);
84
- current = '';
85
- inSingleQuote = false;
86
- }
87
- else {
88
- // Start of single-quoted string
89
- inSingleQuote = true;
90
- }
91
- }
92
- else if ((char === ' ' || char === '\t') && !inDoubleQuote && !inSingleQuote) {
93
- // Whitespace outside quotes - end current token
94
- if (current) {
95
- tokens.push(current);
96
- current = '';
97
- }
98
- }
99
- else {
100
- // Regular character - add to current token
101
- current += char;
102
- }
103
- }
104
- // Add final token if any
105
- if (current || inDoubleQuote || inSingleQuote) {
106
- tokens.push(current);
107
- }
108
- if (tokens.length === 0) {
109
- return { name: '', args: [], raw };
110
- }
111
- const name = tokens[0].toLowerCase();
112
- const args = tokens.slice(1);
113
- return { name, args, raw };
114
- }
115
- /**
116
- * Execute a parsed command
117
- *
118
- * Responsibilities:
119
- * - Route to a command handler
120
- * - Return a CommandResult object
121
- * - Never mutate UI directly
122
- *
123
- * Rules:
124
- * - Never emits UI output directly
125
- * - Only side effects via returned data
126
- */
127
- export async function execute(parsed, ctx) {
128
- // Step 2: Normalization in single place (deterministic)
129
- // Normalize the parsed command name and args
130
- const normalizedName = parsed.name ? parsed.name.replace(/\s+/g, ' ').trim().toLowerCase() : '';
131
- const normalizedArgs = parsed.args.map(arg => arg.replace(/\s+/g, ' ').trim()).filter(arg => arg.length > 0);
132
- // Step 1: Debug trace - execute entry
133
- const isDebug = process.env.TUI_DEBUG === '1';
134
- const debugEvents = [];
135
- if (isDebug) {
136
- debugEvents.push({
137
- id: `dbg-execute-${Date.now()}`,
138
- ts: Date.now(),
139
- tag: 'DBG',
140
- level: 'INFO',
141
- msg: `execute cmd="${normalizedName}" argc=${normalizedArgs.length}`,
142
- });
143
- }
144
- // Empty command after normalization
145
- if (!normalizedName) {
146
- return { events: debugEvents };
147
- }
148
- // Step 3: Check for blocked commands (should be none, but verify)
149
- // No filters - all registered commands are allowed
150
- // Step 1: Debug trace - route lookup
151
- const handler = commands[normalizedName];
152
- const exists = !!handler;
153
- if (isDebug) {
154
- debugEvents.push({
155
- id: `dbg-route-${Date.now()}`,
156
- ts: Date.now(),
157
- tag: 'DBG',
158
- level: 'INFO',
159
- msg: `route hit="${normalizedName}" exists=${exists}`,
160
- });
161
- }
162
- if (!handler) {
163
- // Unknown command - return debug events + unknown handler result
164
- const unknownResult = handleUnknown(normalizedName);
165
- return {
166
- events: [...debugEvents, ...unknownResult.events],
167
- uiStateUpdate: unknownResult.uiStateUpdate,
168
- action: unknownResult.action,
169
- };
170
- }
171
- // Step 4: [CMD] event is emitted by handler (connect handler emits it first)
172
- // Step 5: Handler is awaited (Promise.resolve ensures async handlers work)
173
- // Top-level try/catch to prevent swallowed exceptions
174
- try {
175
- const result = handler(ctx, normalizedArgs);
176
- // Handle both sync and async handlers
177
- const finalResult = await Promise.resolve(result);
178
- // Prepend debug events to result events
179
- return {
180
- ...finalResult,
181
- events: [...debugEvents, ...finalResult.events],
182
- };
183
- }
184
- catch (error) {
185
- // Handler error - emit error event (no stack trace, no raw dump)
186
- const errorMsg = error instanceof Error ? error.message : String(error);
187
- const sanitized = errorMsg.substring(0, 50).trim();
188
- const finalMsg = sanitized || 'Internal command error';
189
- return {
190
- events: [
191
- ...debugEvents,
192
- {
193
- id: `err-${Date.now()}`,
194
- ts: Date.now(),
195
- tag: 'ERR',
196
- level: 'ERROR',
197
- msg: finalMsg,
198
- },
199
- ],
200
- uiStateUpdate: (prev) => ({
201
- ...prev,
202
- network: unavailable('Internal error', 'Retry command'),
203
- }),
204
- };
205
- }
206
- }
207
- /**
208
- * Sanitize user input for display in error messages
209
- */
210
- function sanitizeUserInput(input, maxLength = 50) {
211
- // Remove control characters and newlines
212
- let sanitized = input.replace(/[\x00-\x1F\x7F-\x9F\n\r\t]/g, '');
213
- // Truncate to max length
214
- if (sanitized.length > maxLength) {
215
- sanitized = sanitized.substring(0, maxLength) + '...';
216
- }
217
- return sanitized;
218
- }
219
- /**
220
- * Handle unknown command
221
- *
222
- * Rules:
223
- * - Emit exactly one event
224
- * - <command> must be capped (reuse Section 2.5 echo cap)
225
- * - No stack traces
226
- * - No extra lines
227
- * - No duplicate emissions
228
- */
229
- function handleUnknown(cmd) {
230
- const sanitizedCmd = sanitizeUserInput(cmd, 50);
231
- return {
232
- events: [{
233
- id: `err-${Date.now()}`,
234
- ts: Date.now(),
235
- tag: 'ERR',
236
- level: 'ERROR',
237
- msg: `UNKNOWN COMMAND: ${sanitizedCmd} (try: help)`,
238
- }],
239
- };
240
- }
241
- /**
242
- * Network connection attempt ID tracker
243
- * Prevents stale updates from overlapping connection attempts
244
- */
245
- // networkAttemptId removed - using gatewayConnectionStore instead
246
- /**
247
- * Command registration map
248
- *
249
- * Explicit command map - no dynamic loading, no reflection, no plugin system
250
- */
251
- const commands = {
252
- help: handleHelp,
253
- clear: handleClear,
254
- home: handleHome,
255
- exit: handleExit,
256
- // Section 6: Real commands (V1-backed)
257
- 'agents': handleAgents,
258
- 'connect': handleConnect,
259
- 'verify': handleVerify,
260
- 'test': handleTest,
261
- 'status': handleStatus,
262
- 'start': handleStart,
263
- 'runs': handleRuns,
264
- 'system': handleSystem,
265
- 'diagnose': handleDiagnose,
266
- // Debug commands (only available with TUI_DEBUG=1)
267
- 'debug': handleDebug,
268
- };
269
- /**
270
- * Handle help command
271
- *
272
- * Emits help text to Operations Feed
273
- * Text must be static and explicit (no dynamic introspection)
274
- */
275
- function handleHelp(ctx, args) {
276
- return {
277
- events: [
278
- {
279
- id: `help-1-${Date.now()}`,
280
- ts: Date.now(),
281
- tag: 'SYS',
282
- level: 'INFO',
283
- msg: 'AVAILABLE COMMANDS:',
284
- },
285
- {
286
- id: `help-2-${Date.now()}`,
287
- ts: Date.now(),
288
- tag: 'SYS',
289
- level: 'INFO',
290
- msg: ' help',
291
- },
292
- {
293
- id: `help-3-${Date.now()}`,
294
- ts: Date.now(),
295
- tag: 'SYS',
296
- level: 'INFO',
297
- msg: ' clear',
298
- },
299
- {
300
- id: `help-4-${Date.now()}`,
301
- ts: Date.now(),
302
- tag: 'SYS',
303
- level: 'INFO',
304
- msg: ' home',
305
- },
306
- {
307
- id: `help-5-${Date.now()}`,
308
- ts: Date.now(),
309
- tag: 'SYS',
310
- level: 'INFO',
311
- msg: ' exit',
312
- },
313
- {
314
- id: `help-6-${Date.now()}`,
315
- ts: Date.now(),
316
- tag: 'SYS',
317
- level: 'INFO',
318
- msg: ' agents list',
319
- },
320
- {
321
- id: `help-7-${Date.now()}`,
322
- ts: Date.now(),
323
- tag: 'SYS',
324
- level: 'INFO',
325
- msg: ' agents create',
326
- },
327
- {
328
- id: `help-8-${Date.now()}`,
329
- ts: Date.now(),
330
- tag: 'SYS',
331
- level: 'INFO',
332
- msg: ' agents inspect <id>',
333
- },
334
- {
335
- id: `help-9-${Date.now()}`,
336
- ts: Date.now(),
337
- tag: 'SYS',
338
- level: 'INFO',
339
- msg: ' connect — connect to Gateway (uses default target)',
340
- },
341
- {
342
- id: `help-9b-${Date.now()}`,
343
- ts: Date.now(),
344
- tag: 'SYS',
345
- level: 'INFO',
346
- msg: ' connect — connect to Gateway',
347
- },
348
- {
349
- id: `help-test-${Date.now()}`,
350
- ts: Date.now(),
351
- tag: 'SYS',
352
- level: 'INFO',
353
- msg: ' test - Quick connection test (single API call)',
354
- },
355
- {
356
- id: `help-verify-${Date.now()}`,
357
- ts: Date.now(),
358
- tag: 'SYS',
359
- level: 'INFO',
360
- msg: ' verify - Full connection test (multiple endpoints)',
361
- },
362
- {
363
- id: `help-status-${Date.now()}`,
364
- ts: Date.now(),
365
- tag: 'SYS',
366
- level: 'INFO',
367
- msg: ' status - Show connection status and load capabilities',
368
- },
369
- {
370
- id: `help-10-${Date.now()}`,
371
- ts: Date.now(),
372
- tag: 'SYS',
373
- level: 'INFO',
374
- msg: ' start <agentId>',
375
- },
376
- {
377
- id: `help-11-${Date.now()}`,
378
- ts: Date.now(),
379
- tag: 'SYS',
380
- level: 'INFO',
381
- msg: ' runs list',
382
- },
383
- {
384
- id: `help-12-${Date.now()}`,
385
- ts: Date.now(),
386
- tag: 'SYS',
387
- level: 'INFO',
388
- msg: ' system',
389
- },
390
- ],
391
- };
392
- }
393
- /**
394
- * Handle clear command
395
- *
396
- * Does not clear screen
397
- * Does not reset panels
398
- * Emits no output events
399
- * Returns action: CLEAR_FEED
400
- */
401
- function handleClear(ctx, args) {
402
- return {
403
- events: [], // No output events
404
- action: UiAction.CLEAR_FEED,
405
- };
406
- }
407
- /**
408
- * Handle home command
409
- *
410
- * Emits a short status line
411
- * Returns action: HOME
412
- */
413
- function handleHome(ctx, args) {
414
- return {
415
- events: [
416
- {
417
- id: `home-${Date.now()}`,
418
- ts: Date.now(),
419
- tag: 'SYS',
420
- level: 'INFO',
421
- msg: 'HOME VIEW',
422
- },
423
- ],
424
- action: UiAction.HOME,
425
- };
426
- }
427
- /**
428
- * Handle exit command
429
- *
430
- * Emits optional confirmation event (optional but consistent)
431
- * Returns action: EXIT
432
- */
433
- function handleExit(ctx, args) {
434
- return {
435
- events: [
436
- {
437
- id: `exit-${Date.now()}`,
438
- ts: Date.now(),
439
- tag: 'SYS',
440
- level: 'INFO',
441
- msg: 'Exiting...',
442
- },
443
- ],
444
- action: UiAction.EXIT,
445
- };
446
- }
447
- // ============================================================================
448
- // Section 6: Real Commands (V1-Backed)
449
- // ============================================================================
450
- /**
451
- * Handle agents command (list, create, inspect)
452
- */
453
- async function handleAgents(ctx, args) {
454
- const subcommand = args[0]?.toLowerCase() || 'list';
455
- if (subcommand === 'list') {
456
- return handleAgentsList(ctx, args.slice(1));
457
- }
458
- else if (subcommand === 'create') {
459
- return handleAgentsCreate(ctx, args.slice(1));
460
- }
461
- else if (subcommand === 'inspect') {
462
- return handleAgentsInspect(ctx, args.slice(1));
463
- }
464
- else {
465
- return {
466
- events: [{
467
- id: `err-${Date.now()}`,
468
- ts: Date.now(),
469
- tag: 'ERR',
470
- level: 'ERROR',
471
- msg: `Unknown agents subcommand: ${subcommand} (try: list, create, inspect)`,
472
- }],
473
- };
474
- }
475
- }
476
- /**
477
- * 1️⃣ agents list
478
- *
479
- * Calls v1Adapters/agents.listAgents()
480
- * Updates assets → AVAILABLE with real counts
481
- */
482
- async function handleAgentsList(ctx, args) {
483
- const cmdEvent = {
484
- id: `cmd-${Date.now()}`,
485
- ts: Date.now(),
486
- tag: 'CMD',
487
- level: 'INFO',
488
- msg: 'agents list',
489
- };
490
- try {
491
- const result = listAgents();
492
- if (!result.ok) {
493
- // Failure: assets → UNAVAILABLE
494
- const classified = classifyError(result.error, 'list agents');
495
- return {
496
- events: [
497
- cmdEvent,
498
- {
499
- id: `err-${Date.now()}`,
500
- ts: Date.now(),
501
- tag: 'ERR',
502
- level: 'ERROR',
503
- msg: `Failed to list agents: ${classified.message}`,
504
- },
505
- ],
506
- uiStateUpdate: (prev) => ({
507
- ...prev,
508
- assets: unavailable(classified.message, classified.nextAction),
509
- }),
510
- };
511
- }
512
- const agents = result.data;
513
- const count = agents.length;
514
- // Success: assets → AVAILABLE (even if count is 0 - valid empty state)
515
- const assetsState = {
516
- total: count,
517
- active: 0, // TODO: track active agents
518
- idle: count,
519
- error: 0,
520
- };
521
- // Emit exactly one terminal event: [OK] if count > 0, [WARN] if count === 0
522
- const resultEvent = {
523
- id: `result-${Date.now()}`,
524
- ts: Date.now(),
525
- tag: count === 0 ? 'WARN' : 'OK', // [OK] for success, [WARN] for empty
526
- level: count === 0 ? 'WARN' : 'INFO', // WARN for empty, INFO for success
527
- msg: count === 0 ? 'No agents found' : `${count} agent${count === 1 ? '' : 's'} found`,
528
- };
529
- return {
530
- events: [
531
- cmdEvent,
532
- resultEvent,
533
- ],
534
- uiStateUpdate: (prev) => ({
535
- ...prev,
536
- assets: available(assetsState),
537
- }),
538
- };
539
- }
540
- catch (error) {
541
- const classified = classifyError(error, 'list agents');
542
- return {
543
- events: [
544
- cmdEvent,
545
- {
546
- id: `err-${Date.now()}`,
547
- ts: Date.now(),
548
- tag: 'ERR',
549
- level: 'ERROR',
550
- msg: `Failed to list agents: ${classified.message}`,
551
- },
552
- ],
553
- uiStateUpdate: (prev) => ({
554
- ...prev,
555
- assets: unavailable(classified.message, classified.nextAction),
556
- }),
557
- };
558
- }
559
- }
560
- /**
561
- * 2️⃣ agents create
562
- *
563
- * Accepts arguments or minimal defaults
564
- * Calls v1Adapters/agents.createAgent()
565
- */
566
- async function handleAgentsCreate(ctx, args) {
567
- const cmdEvent = {
568
- id: `cmd-${Date.now()}`,
569
- ts: Date.now(),
570
- tag: 'CMD',
571
- level: 'INFO',
572
- msg: 'agents create',
573
- };
574
- try {
575
- // Parse agent name from args (first arg)
576
- const name = args[0]?.trim();
577
- if (!name) {
578
- return {
579
- events: [
580
- cmdEvent,
581
- {
582
- id: `err-${Date.now()}`,
583
- ts: Date.now(),
584
- tag: 'ERR',
585
- level: 'ERROR',
586
- msg: 'Agent name required (usage: agents create <name>)',
587
- },
588
- ],
589
- };
590
- }
591
- // Create minimal agent (can be extended later)
592
- const agent = {
593
- name,
594
- description: args[1] || undefined,
595
- provider: {
596
- type: 'openai',
597
- model: 'gpt-3.5-turbo',
598
- },
599
- };
600
- const result = v1CreateAgent(agent);
601
- if (!result.ok) {
602
- return {
603
- events: [
604
- cmdEvent,
605
- {
606
- id: `err-${Date.now()}`,
607
- ts: Date.now(),
608
- tag: 'ERR',
609
- level: 'ERROR',
610
- msg: `Failed to create agent: ${result.error.message}`,
611
- },
612
- ],
613
- uiStateUpdate: (prev) => ({
614
- ...prev,
615
- assets: unavailable(result.error.message || 'Failed to create agent', result.error.nextAction || 'Check config and retry'),
616
- }),
617
- };
618
- }
619
- // Success: refresh assets list
620
- const listResult = listAgents();
621
- const assetsState = listResult.ok ? {
622
- total: listResult.data.length,
623
- active: 0,
624
- idle: listResult.data.length,
625
- error: 0,
626
- } : {
627
- total: 0,
628
- active: 0,
629
- idle: 0,
630
- error: 0,
631
- };
632
- return {
633
- events: [
634
- cmdEvent,
635
- {
636
- id: `ok-${Date.now()}`,
637
- ts: Date.now(),
638
- tag: 'CMD',
639
- level: 'INFO',
640
- msg: `Agent "${name}" created`,
641
- },
642
- ],
643
- uiStateUpdate: (prev) => ({
644
- ...prev,
645
- assets: available(assetsState),
646
- }),
647
- };
648
- }
649
- catch (error) {
650
- return {
651
- events: [
652
- cmdEvent,
653
- {
654
- id: `err-${Date.now()}`,
655
- ts: Date.now(),
656
- tag: 'ERR',
657
- level: 'ERROR',
658
- msg: `Failed to create agent: ${error.message || 'Unknown error'}`,
659
- },
660
- ],
661
- uiStateUpdate: (prev) => ({
662
- ...prev,
663
- assets: unavailable('Failed to create agent', 'Check config and retry'),
664
- }),
665
- };
666
- }
667
- }
668
- /**
669
- * 3️⃣ agents inspect <id>
670
- *
671
- * Calls v1Adapters/agents.getAgent(id)
672
- * Updates posture → AVAILABLE
673
- */
674
- async function handleAgentsInspect(ctx, args) {
675
- const agentId = args[0]?.trim();
676
- const cmdEvent = {
677
- id: `cmd-${Date.now()}`,
678
- ts: Date.now(),
679
- tag: 'CMD',
680
- level: 'INFO',
681
- msg: `agents inspect ${agentId || ''}`,
682
- };
683
- if (!agentId) {
684
- return {
685
- events: [
686
- cmdEvent,
687
- {
688
- id: `err-${Date.now()}`,
689
- ts: Date.now(),
690
- tag: 'ERR',
691
- level: 'ERROR',
692
- msg: 'Agent ID required (usage: agents inspect <id>)',
693
- },
694
- ],
695
- };
696
- }
697
- try {
698
- const result = getAgent(agentId);
699
- if (!result.ok) {
700
- return {
701
- events: [
702
- cmdEvent,
703
- {
704
- id: `err-${Date.now()}`,
705
- ts: Date.now(),
706
- tag: 'ERR',
707
- level: 'ERROR',
708
- msg: `Agent not found: ${agentId}`,
709
- },
710
- ],
711
- uiStateUpdate: (prev) => ({
712
- ...prev,
713
- posture: unavailable(result.error.message || 'Agent not found', result.error.nextAction || 'Run "agents list"'),
714
- }),
715
- };
716
- }
717
- // Success: posture → AVAILABLE
718
- const agent = result.data;
719
- return {
720
- events: [
721
- cmdEvent,
722
- {
723
- id: `ok-${Date.now()}`,
724
- ts: Date.now(),
725
- tag: 'OK',
726
- level: 'INFO',
727
- msg: `Agent loaded: ${agent.name}`,
728
- },
729
- ],
730
- uiStateUpdate: (prev) => ({
731
- ...prev,
732
- posture: available({
733
- mode: 'HUB',
734
- agentId: agent.name, // Include agent ID per spec
735
- }),
736
- }),
737
- };
738
- }
739
- catch (error) {
740
- return {
741
- events: [
742
- cmdEvent,
743
- {
744
- id: `err-${Date.now()}`,
745
- ts: Date.now(),
746
- tag: 'ERR',
747
- level: 'ERROR',
748
- msg: `Failed to inspect agent: ${error.message || 'Unknown error'}`,
749
- },
750
- ],
751
- uiStateUpdate: (prev) => ({
752
- ...prev,
753
- posture: unavailable('Agent not found', 'Run "agents list"'),
754
- }),
755
- };
756
- }
757
- }
758
- /**
759
- * 4️⃣ connect
760
- *
761
- * Section 6.2: Gateway Connection Enforcement (FINAL, NON-NEGOTIABLE)
762
- *
763
- * Connects to canonical Gateway endpoint.
764
- * - Ignores any arguments (parser may still accept them, but they are ignored)
765
- * - Always calls resolveGatewayUrl()
766
- * - Emits lifecycle events in exact order
767
- * - Uses LOADING state with attemptId to prevent stale updates
768
- * - Guarantees reset in finally block
769
- */
770
- async function handleConnect(ctx, args) {
771
- // Import store and gateway config
772
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
773
- const gatewayConfig = await import('../config/gateway.js');
774
- // Step 1: Resolve target with source tracking
775
- const { url: inputTarget, source } = gatewayConfig.resolveGatewayUrlWithSource();
776
- // Step 2: Emit [CMD] connect
777
- const cmdEvent = {
778
- id: `cmd-${Date.now()}`,
779
- ts: Date.now(),
780
- tag: 'CMD',
781
- level: 'INFO',
782
- msg: 'connect',
783
- };
784
- const events = [cmdEvent];
785
- // Step 3: Log target source
786
- events.push({
787
- id: `sys-source-${Date.now()}`,
788
- ts: Date.now(),
789
- tag: 'SYS',
790
- level: 'INFO',
791
- msg: `gateway target source: ${source}`,
792
- });
793
- // Step 4: Set connecting state in store
794
- gatewayConnectionStore.setConnecting(inputTarget, 5000);
795
- // Step 5: Emit connecting event
796
- events.push({
797
- id: `sys-connecting-${Date.now()}`,
798
- ts: Date.now(),
799
- tag: 'SYS',
800
- level: 'INFO',
801
- msg: 'CONNECTING...',
802
- });
803
- // Step 6: Attempt connection
804
- try {
805
- const result = await v1Connect();
806
- if (!result.ok) {
807
- // Failure: Update store with error
808
- const errorCode = result.error.code || 'UNKNOWN';
809
- const errorMsg = result.error.message || 'Gateway unreachable';
810
- const nextAction = result.error.nextAction || 'Retry "connect"';
811
- gatewayConnectionStore.setError(inputTarget, errorCode, errorMsg, nextAction);
812
- events.push({
813
- id: `err-${Date.now()}`,
814
- ts: Date.now(),
815
- tag: 'ERR',
816
- level: 'ERROR',
817
- msg: errorMsg,
818
- });
819
- // Emit store state for debugging
820
- const storeState = gatewayConnectionStore.getState();
821
- events.push({
822
- id: `sys-network-state-${Date.now()}`,
823
- ts: Date.now(),
824
- tag: 'SYS',
825
- level: 'INFO',
826
- msg: `network_state=${storeState.status}`,
827
- });
828
- return { events };
829
- }
830
- // Success: Update store with connection info
831
- const effectiveTarget = result.data.endpoint; // The endpoint that actually worked (might be different from input)
832
- const healthData = result.data.healthData;
833
- const latency = result.data.latency;
834
- gatewayConnectionStore.setConnected(inputTarget, effectiveTarget, healthData, latency);
835
- // Auto-load capabilities after successful connection
836
- const { capabilitiesStore } = await import('../state/capabilitiesStore.js');
837
- const { GatewayClient } = await import('../../../gateway-client.js');
838
- capabilitiesStore.setLoading();
839
- // Fetch capabilities in background (don't block)
840
- (async () => {
841
- try {
842
- const client = new GatewayClient({ gatewayUrl: effectiveTarget });
843
- const response = await fetch(`${effectiveTarget}/api/capabilities`, {
844
- method: 'GET',
845
- signal: AbortSignal.timeout(5000),
846
- });
847
- if (response.ok) {
848
- const data = await response.json();
849
- const items = data.capabilities || data.items || [];
850
- capabilitiesStore.setLoaded(items);
851
- }
852
- else {
853
- // Endpoint doesn't exist - set empty list
854
- capabilitiesStore.setLoaded([]);
855
- }
856
- }
857
- catch {
858
- // Non-fatal - set empty list
859
- capabilitiesStore.setLoaded([]);
860
- }
861
- })();
862
- // Show input vs effective target if different
863
- if (effectiveTarget !== inputTarget) {
864
- events.push({
865
- id: `sys-targets-${Date.now()}`,
866
- ts: Date.now(),
867
- tag: 'SYS',
868
- level: 'INFO',
869
- msg: `connect: input=${inputTarget} effective=${effectiveTarget}`,
870
- });
871
- }
872
- else {
873
- events.push({
874
- id: `sys-target-${Date.now()}`,
875
- ts: Date.now(),
876
- tag: 'SYS',
877
- level: 'INFO',
878
- msg: `connect: target=${inputTarget}`,
879
- });
880
- }
881
- // Show clean connection message
882
- const endpointUrl = new URL(effectiveTarget);
883
- const displayHost = endpointUrl.hostname === '127.0.0.1' ? 'localhost' : endpointUrl.hostname;
884
- const displayPort = endpointUrl.port || (endpointUrl.protocol === 'https:' ? '443' : '80');
885
- events.push({
886
- id: `ok-${Date.now()}`,
887
- ts: Date.now(),
888
- tag: 'OK',
889
- level: 'INFO',
890
- msg: `Connected to ${displayHost}:${displayPort}`,
891
- });
892
- // Show gateway verification info
893
- if (healthData) {
894
- const status = healthData.status || 'alive';
895
- const persistence = healthData.persistence || 'unknown';
896
- events.push({
897
- id: `sys-verify-${Date.now()}`,
898
- ts: Date.now(),
899
- tag: 'SYS',
900
- level: 'INFO',
901
- msg: `Gateway: ${status} | Persistence: ${persistence}${latency ? ` | Latency: ${latency}ms` : ''}`,
902
- });
903
- }
904
- // Emit store state for debugging
905
- const storeState = gatewayConnectionStore.getState();
906
- events.push({
907
- id: `sys-network-state-${Date.now()}`,
908
- ts: Date.now(),
909
- tag: 'SYS',
910
- level: 'INFO',
911
- msg: `network_state=${storeState.status}`,
912
- });
913
- return { events };
914
- }
915
- catch (error) {
916
- // Step 7: Catch-all error handler
917
- const errorMsg = error?.message || 'Connection failed';
918
- const errorCode = error?.code || 'UNKNOWN';
919
- gatewayConnectionStore.setError(inputTarget, errorCode, errorMsg, 'Retry "connect"');
920
- events.push({
921
- id: `err-${Date.now()}`,
922
- ts: Date.now(),
923
- tag: 'ERR',
924
- level: 'ERROR',
925
- msg: errorMsg,
926
- });
927
- // Emit store state for debugging
928
- const storeState = gatewayConnectionStore.getState();
929
- events.push({
930
- id: `sys-network-state-${Date.now()}`,
931
- ts: Date.now(),
932
- tag: 'SYS',
933
- level: 'INFO',
934
- msg: `network_state=${storeState.status}`,
935
- });
936
- return { events };
937
- }
938
- }
939
- /**
940
- * 4.5️⃣ test
941
- *
942
- * Simple test - makes ONE API call to prove connection works
943
- * Just calls /health and shows the result
944
- */
945
- async function handleTest(ctx, args) {
946
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
947
- const gatewayConfig = await import('../config/gateway.js');
948
- const { GatewayClient } = await import('../../../gateway-client.js');
949
- const cmdEvent = {
950
- id: `cmd-${Date.now()}`,
951
- ts: Date.now(),
952
- tag: 'CMD',
953
- level: 'INFO',
954
- msg: 'test',
955
- };
956
- const events = [cmdEvent];
957
- // Check store state first
958
- const storeState = gatewayConnectionStore.getState();
959
- if (storeState.status !== 'connected') {
960
- events.push({
961
- id: `err-${Date.now()}`,
962
- ts: Date.now(),
963
- tag: 'ERR',
964
- level: 'ERROR',
965
- msg: `Not connected (status: ${storeState.status}). Run "connect" first.`,
966
- });
967
- return { events };
968
- }
969
- // Type guard: ensure we have resolvedTo
970
- if (!('resolvedTo' in storeState) || !storeState.resolvedTo) {
971
- events.push({
972
- id: `err-${Date.now()}`,
973
- ts: Date.now(),
974
- tag: 'ERR',
975
- level: 'ERROR',
976
- msg: `Connection state missing resolvedTo. Run "connect" again.`,
977
- });
978
- return { events };
979
- }
980
- // Use the resolved endpoint from the store (the one that actually worked)
981
- const gatewayUrl = storeState.resolvedTo;
982
- // Debug: log what URL we're using
983
- events.push({
984
- id: `sys-test-debug-${Date.now()}`,
985
- ts: Date.now(),
986
- tag: 'SYS',
987
- level: 'INFO',
988
- msg: `Using gateway URL: ${gatewayUrl}`,
989
- });
990
- const client = new GatewayClient({ gatewayUrl });
991
- events.push({
992
- id: `sys-test-start-${Date.now()}`,
993
- ts: Date.now(),
994
- tag: 'SYS',
995
- level: 'INFO',
996
- msg: `Testing connection to ${storeState.resolvedTo}...`,
997
- });
998
- // Make a single API call to /health
999
- try {
1000
- const startTime = Date.now();
1001
- const healthResponse = await client.health();
1002
- const latency = Date.now() - startTime;
1003
- // Show clear success message
1004
- events.push({
1005
- id: `ok-test-${Date.now()}`,
1006
- ts: Date.now(),
1007
- tag: 'OK',
1008
- level: 'INFO',
1009
- msg: `✓ Connection verified! Gateway responded in ${latency}ms`,
1010
- });
1011
- // Show response details
1012
- events.push({
1013
- id: `sys-test-details-${Date.now()}`,
1014
- ts: Date.now(),
1015
- tag: 'SYS',
1016
- level: 'INFO',
1017
- msg: ` Status: ${healthResponse.status || 'ok'}`,
1018
- });
1019
- if (healthResponse.persistence) {
1020
- events.push({
1021
- id: `sys-test-persistence-${Date.now()}`,
1022
- ts: Date.now(),
1023
- tag: 'SYS',
1024
- level: 'INFO',
1025
- msg: ` Persistence: ${healthResponse.persistence}`,
1026
- });
1027
- }
1028
- if (healthResponse.version) {
1029
- events.push({
1030
- id: `sys-test-version-${Date.now()}`,
1031
- ts: Date.now(),
1032
- tag: 'SYS',
1033
- level: 'INFO',
1034
- msg: ` Version: ${healthResponse.version}`,
1035
- });
1036
- }
1037
- // Show the full response for debugging
1038
- events.push({
1039
- id: `sys-test-response-${Date.now()}`,
1040
- ts: Date.now(),
1041
- tag: 'SYS',
1042
- level: 'INFO',
1043
- msg: ` Response: ${JSON.stringify(healthResponse).substring(0, 100)}...`,
1044
- });
1045
- }
1046
- catch (error) {
1047
- events.push({
1048
- id: `err-test-${Date.now()}`,
1049
- ts: Date.now(),
1050
- tag: 'ERR',
1051
- level: 'ERROR',
1052
- msg: `✗ Connection test failed: ${error.message || 'Unknown error'}`,
1053
- });
1054
- if (error.code) {
1055
- events.push({
1056
- id: `err-test-code-${Date.now()}`,
1057
- ts: Date.now(),
1058
- tag: 'ERR',
1059
- level: 'ERROR',
1060
- msg: ` Error code: ${error.code}`,
1061
- });
1062
- }
1063
- }
1064
- return { events };
1065
- }
1066
- /**
1067
- * 4.6️⃣ verify
1068
- *
1069
- * Makes real API calls to prove the connection works
1070
- * Tests: /health, /ready, /api/runs, /metrics
1071
- */
1072
- async function handleVerify(ctx, args) {
1073
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
1074
- const gatewayConfig = await import('../config/gateway.js');
1075
- const { GatewayClient } = await import('../../../gateway-client.js');
1076
- const cmdEvent = {
1077
- id: `cmd-${Date.now()}`,
1078
- ts: Date.now(),
1079
- tag: 'CMD',
1080
- level: 'INFO',
1081
- msg: 'verify',
1082
- };
1083
- const events = [cmdEvent];
1084
- // Check store state first
1085
- const storeState = gatewayConnectionStore.getState();
1086
- if (storeState.status !== 'connected') {
1087
- events.push({
1088
- id: `err-${Date.now()}`,
1089
- ts: Date.now(),
1090
- tag: 'ERR',
1091
- level: 'ERROR',
1092
- msg: `Not connected (status: ${storeState.status}). Run "connect" first.`,
1093
- });
1094
- return { events };
1095
- }
1096
- // Use the resolved endpoint from the store (the one that actually worked)
1097
- const gatewayUrl = storeState.resolvedTo;
1098
- const client = new GatewayClient({ gatewayUrl });
1099
- events.push({
1100
- id: `sys-verify-start-${Date.now()}`,
1101
- ts: Date.now(),
1102
- tag: 'SYS',
1103
- level: 'INFO',
1104
- msg: `Verifying connection to ${storeState.resolvedTo}...`,
1105
- });
1106
- // Test 1: Health check
1107
- try {
1108
- const startTime = Date.now();
1109
- const healthResponse = await client.health();
1110
- const latency = Date.now() - startTime;
1111
- events.push({
1112
- id: `ok-health-${Date.now()}`,
1113
- ts: Date.now(),
1114
- tag: 'OK',
1115
- level: 'INFO',
1116
- msg: `✓ /health: ${healthResponse.status || 'ok'} (${latency}ms)`,
1117
- });
1118
- if (healthResponse.persistence) {
1119
- events.push({
1120
- id: `sys-persistence-${Date.now()}`,
1121
- ts: Date.now(),
1122
- tag: 'SYS',
1123
- level: 'INFO',
1124
- msg: ` Persistence: ${healthResponse.persistence}`,
1125
- });
1126
- }
1127
- }
1128
- catch (error) {
1129
- events.push({
1130
- id: `err-health-${Date.now()}`,
1131
- ts: Date.now(),
1132
- tag: 'ERR',
1133
- level: 'ERROR',
1134
- msg: `✗ /health failed: ${error.message || 'Unknown error'}`,
1135
- });
1136
- }
1137
- // Test 2: Ready check
1138
- try {
1139
- const startTime = Date.now();
1140
- const readyResponse = await fetch(`${gatewayUrl}/ready`, {
1141
- method: 'GET',
1142
- signal: AbortSignal.timeout(5000),
1143
- });
1144
- const latency = Date.now() - startTime;
1145
- const data = await readyResponse.json();
1146
- events.push({
1147
- id: `ok-ready-${Date.now()}`,
1148
- ts: Date.now(),
1149
- tag: 'OK',
1150
- level: 'INFO',
1151
- msg: `✓ /ready: ${data.status || readyResponse.status} (${latency}ms)`,
1152
- });
1153
- }
1154
- catch (error) {
1155
- events.push({
1156
- id: `err-ready-${Date.now()}`,
1157
- ts: Date.now(),
1158
- tag: 'ERR',
1159
- level: 'ERROR',
1160
- msg: `✗ /ready failed: ${error.message || 'Unknown error'}`,
1161
- });
1162
- }
1163
- // Test 3: List runs (requires auth, but tests API endpoint)
1164
- try {
1165
- const startTime = Date.now();
1166
- const runsResponse = await fetch(`${gatewayUrl}/api/runs?limit=1`, {
1167
- method: 'GET',
1168
- headers: {
1169
- 'Authorization': `Bearer ${process.env.GATEWAY_TOKEN || ''}`,
1170
- },
1171
- signal: AbortSignal.timeout(5000),
1172
- });
1173
- const latency = Date.now() - startTime;
1174
- if (runsResponse.ok) {
1175
- const data = await runsResponse.json();
1176
- events.push({
1177
- id: `ok-runs-${Date.now()}`,
1178
- ts: Date.now(),
1179
- tag: 'OK',
1180
- level: 'INFO',
1181
- msg: `✓ /api/runs: ${runsResponse.status} (${latency}ms) - ${data.runs?.length || 0} runs`,
1182
- });
1183
- }
1184
- else {
1185
- events.push({
1186
- id: `warn-runs-${Date.now()}`,
1187
- ts: Date.now(),
1188
- tag: 'SYS',
1189
- level: 'WARN',
1190
- msg: `⚠ /api/runs: ${runsResponse.status} (${latency}ms) - ${runsResponse.status === 401 ? 'Auth required' : 'Error'}`,
1191
- });
1192
- }
1193
- }
1194
- catch (error) {
1195
- events.push({
1196
- id: `err-runs-${Date.now()}`,
1197
- ts: Date.now(),
1198
- tag: 'ERR',
1199
- level: 'ERROR',
1200
- msg: `✗ /api/runs failed: ${error.message || 'Unknown error'}`,
1201
- });
1202
- }
1203
- // Test 4: Metrics endpoint (optional - longer timeout, warn on failure)
1204
- try {
1205
- const startTime = Date.now();
1206
- const metricsResponse = await fetch(`${gatewayUrl}/metrics`, {
1207
- method: 'GET',
1208
- signal: AbortSignal.timeout(15000), // 15s timeout for metrics
1209
- });
1210
- const latency = Date.now() - startTime;
1211
- const text = await metricsResponse.text();
1212
- const lines = text.split('\n').filter(l => l.trim() && !l.startsWith('#')).length;
1213
- events.push({
1214
- id: `ok-metrics-${Date.now()}`,
1215
- ts: Date.now(),
1216
- tag: 'OK',
1217
- level: 'INFO',
1218
- msg: `✓ /metrics: ${metricsResponse.status} (${latency}ms) - ${lines} metrics`,
1219
- });
1220
- }
1221
- catch (error) {
1222
- // Metrics is optional - show WARN not ERR
1223
- const errorMsg = error.message || 'Unknown error';
1224
- const isTimeout = errorMsg.includes('timeout') || errorMsg.includes('aborted');
1225
- events.push({
1226
- id: `warn-metrics-${Date.now()}`,
1227
- ts: Date.now(),
1228
- tag: 'SYS',
1229
- level: 'WARN',
1230
- msg: `⚠ /metrics unavailable (${isTimeout ? 'timeout' : errorMsg.substring(0, 30)})`,
1231
- });
1232
- }
1233
- // Summary
1234
- events.push({
1235
- id: `sys-verify-done-${Date.now()}`,
1236
- ts: Date.now(),
1237
- tag: 'SYS',
1238
- level: 'INFO',
1239
- msg: 'Verification complete. Connection is working.',
1240
- });
1241
- return { events };
1242
- }
1243
- /**
1244
- * 4.7️⃣ status
1245
- *
1246
- * Prints connection summary and fetches capabilities
1247
- */
1248
- async function handleStatus(ctx, args) {
1249
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
1250
- const { capabilitiesStore } = await import('../state/capabilitiesStore.js');
1251
- const { GatewayClient } = await import('../../../gateway-client.js');
1252
- const cmdEvent = {
1253
- id: `cmd-${Date.now()}`,
1254
- ts: Date.now(),
1255
- tag: 'CMD',
1256
- level: 'INFO',
1257
- msg: 'status',
1258
- };
1259
- const events = [cmdEvent];
1260
- // Get connection state
1261
- const connState = gatewayConnectionStore.getState();
1262
- // Print connection summary
1263
- if (connState.status === 'connected') {
1264
- events.push({
1265
- id: `sys-status-conn-${Date.now()}`,
1266
- ts: Date.now(),
1267
- tag: 'SYS',
1268
- level: 'INFO',
1269
- msg: `Connection: CONNECTED`,
1270
- });
1271
- if (connState.target !== connState.resolvedTo) {
1272
- events.push({
1273
- id: `sys-status-targets-${Date.now()}`,
1274
- ts: Date.now(),
1275
- tag: 'SYS',
1276
- level: 'INFO',
1277
- msg: ` Target: ${connState.target} → ${connState.resolvedTo}`,
1278
- });
1279
- }
1280
- else {
1281
- events.push({
1282
- id: `sys-status-target-${Date.now()}`,
1283
- ts: Date.now(),
1284
- tag: 'SYS',
1285
- level: 'INFO',
1286
- msg: ` Target: ${connState.resolvedTo}`,
1287
- });
1288
- }
1289
- if (connState.latencyMs !== undefined) {
1290
- events.push({
1291
- id: `sys-status-latency-${Date.now()}`,
1292
- ts: Date.now(),
1293
- tag: 'SYS',
1294
- level: 'INFO',
1295
- msg: ` Latency: ${connState.latencyMs}ms`,
1296
- });
1297
- }
1298
- // PROOF: Make a real API call right now to verify connection works
1299
- events.push({
1300
- id: `sys-status-verify-${Date.now()}`,
1301
- ts: Date.now(),
1302
- tag: 'SYS',
1303
- level: 'INFO',
1304
- msg: `Verifying connection with live API call...`,
1305
- });
1306
- try {
1307
- const verifyStartTime = Date.now();
1308
- const verifyClient = new GatewayClient({ gatewayUrl: connState.resolvedTo });
1309
- const verifyHealth = await verifyClient.health();
1310
- const verifyLatency = Date.now() - verifyStartTime;
1311
- // Show actual response data to prove it's real
1312
- events.push({
1313
- id: `ok-status-verify-${Date.now()}`,
1314
- ts: Date.now(),
1315
- tag: 'OK',
1316
- level: 'INFO',
1317
- msg: `✓ Verified: Gateway responded in ${verifyLatency}ms`,
1318
- });
1319
- if (verifyHealth.status) {
1320
- events.push({
1321
- id: `sys-status-health-${Date.now()}`,
1322
- ts: Date.now(),
1323
- tag: 'SYS',
1324
- level: 'INFO',
1325
- msg: ` Health: ${verifyHealth.status}`,
1326
- });
1327
- }
1328
- if (verifyHealth.persistence) {
1329
- events.push({
1330
- id: `sys-status-persistence-${Date.now()}`,
1331
- ts: Date.now(),
1332
- tag: 'SYS',
1333
- level: 'INFO',
1334
- msg: ` Persistence: ${verifyHealth.persistence}`,
1335
- });
1336
- }
1337
- // Show timestamp from server to prove it's real
1338
- if (verifyHealth.time) {
1339
- events.push({
1340
- id: `sys-status-time-${Date.now()}`,
1341
- ts: Date.now(),
1342
- tag: 'SYS',
1343
- level: 'INFO',
1344
- msg: ` Server time: ${verifyHealth.time}`,
1345
- });
1346
- }
1347
- }
1348
- catch (error) {
1349
- // If verification fails, connection is NOT real
1350
- events.push({
1351
- id: `err-status-verify-${Date.now()}`,
1352
- ts: Date.now(),
1353
- tag: 'ERR',
1354
- level: 'ERROR',
1355
- msg: `✗ Verification FAILED: ${error.message || 'Connection not working'}`,
1356
- });
1357
- // Update store to reflect reality
1358
- gatewayConnectionStore.setError(connState.resolvedTo, error.code || 'VERIFY_FAILED', 'Connection verification failed', 'Run "connect" again');
1359
- return { events };
1360
- }
1361
- // Fetch capabilities (endpoint may not exist - that's OK)
1362
- capabilitiesStore.setLoading();
1363
- try {
1364
- // Try /api/capabilities endpoint (may not exist on all Gateway versions)
1365
- const response = await fetch(`${connState.resolvedTo}/api/capabilities`, {
1366
- method: 'GET',
1367
- signal: AbortSignal.timeout(5000),
1368
- });
1369
- if (response.ok) {
1370
- const data = await response.json();
1371
- const items = data.capabilities || data.items || [];
1372
- capabilitiesStore.setLoaded(items);
1373
- events.push({
1374
- id: `ok-capabilities-${Date.now()}`,
1375
- ts: Date.now(),
1376
- tag: 'OK',
1377
- level: 'INFO',
1378
- msg: `Capabilities: ${items.length} items loaded`,
1379
- });
1380
- }
1381
- else if (response.status === 404) {
1382
- // 404 is expected - endpoint doesn't exist yet (not an error)
1383
- capabilitiesStore.setLoaded([]);
1384
- events.push({
1385
- id: `sys-capabilities-${Date.now()}`,
1386
- ts: Date.now(),
1387
- tag: 'SYS',
1388
- level: 'INFO',
1389
- msg: `Capabilities: endpoint not implemented (404) - this is normal`,
1390
- });
1391
- }
1392
- else {
1393
- // Other error status
1394
- capabilitiesStore.setLoaded([]);
1395
- events.push({
1396
- id: `sys-capabilities-${Date.now()}`,
1397
- ts: Date.now(),
1398
- tag: 'SYS',
1399
- level: 'INFO',
1400
- msg: `Capabilities: endpoint returned ${response.status}`,
1401
- });
1402
- }
1403
- }
1404
- catch (error) {
1405
- // Network error - non-fatal
1406
- capabilitiesStore.setLoaded([]);
1407
- const errorMsg = error.message?.substring(0, 40) || 'unavailable';
1408
- events.push({
1409
- id: `sys-capabilities-${Date.now()}`,
1410
- ts: Date.now(),
1411
- tag: 'SYS',
1412
- level: 'INFO',
1413
- msg: `Capabilities: ${errorMsg}`,
1414
- });
1415
- }
1416
- }
1417
- else {
1418
- events.push({
1419
- id: `sys-status-conn-${Date.now()}`,
1420
- ts: Date.now(),
1421
- tag: 'SYS',
1422
- level: 'WARN',
1423
- msg: `Connection: ${connState.status.toUpperCase()}`,
1424
- });
1425
- if (connState.status === 'error' && 'message' in connState) {
1426
- events.push({
1427
- id: `sys-status-error-${Date.now()}`,
1428
- ts: Date.now(),
1429
- tag: 'SYS',
1430
- level: 'WARN',
1431
- msg: ` Error: ${connState.message}`,
1432
- });
1433
- }
1434
- }
1435
- return { events };
1436
- }
1437
- /**
1438
- * 5️⃣ start <agentId>
1439
- *
1440
- * Calls v1Adapters/runs.startRun(agentId)
1441
- * Updates posture → AVAILABLE (mode: RUNNING)
1442
- */
1443
- async function handleStart(ctx, args) {
1444
- const agentId = args[0]?.trim();
1445
- const cmdEvent = {
1446
- id: `cmd-${Date.now()}`,
1447
- ts: Date.now(),
1448
- tag: 'CMD',
1449
- level: 'INFO',
1450
- msg: `start ${agentId || ''}`,
1451
- };
1452
- if (!agentId) {
1453
- return {
1454
- events: [
1455
- cmdEvent,
1456
- {
1457
- id: `err-${Date.now()}`,
1458
- ts: Date.now(),
1459
- tag: 'ERR',
1460
- level: 'ERROR',
1461
- msg: 'Agent ID required (usage: start <agentId>)',
1462
- },
1463
- ],
1464
- };
1465
- }
1466
- // Get connection state - REQUIREMENT A: use effective gateway URL from store
1467
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
1468
- const connState = gatewayConnectionStore.getState();
1469
- // REQUIREMENT A: Check if connected and have effective URL
1470
- if (connState.status !== 'connected' || !connState.resolvedTo) {
1471
- return {
1472
- events: [
1473
- cmdEvent,
1474
- {
1475
- id: `err-${Date.now()}`,
1476
- ts: Date.now(),
1477
- tag: 'ERR',
1478
- level: 'ERROR',
1479
- msg: 'Not connected. Run "connect" first.',
1480
- },
1481
- ],
1482
- uiStateUpdate: (prev) => ({
1483
- ...prev,
1484
- network: unavailable('Not connected', 'Run "connect" first'),
1485
- posture: unavailable('Cannot start run - not connected', 'Run "connect" first'),
1486
- }),
1487
- };
1488
- }
1489
- // REQUIREMENT B: Use effective gateway URL from store (single source of truth)
1490
- const effectiveGatewayUrl = connState.resolvedTo;
1491
- // REQUIREMENT C: Add debug output to prove routing is correct
1492
- const events = [
1493
- cmdEvent,
1494
- {
1495
- id: `sys-start-gateway-${Date.now()}`,
1496
- ts: Date.now(),
1497
- tag: 'SYS',
1498
- level: 'INFO',
1499
- msg: `Using gateway URL: ${effectiveGatewayUrl}`,
1500
- },
1501
- ];
1502
- try {
1503
- const result = await startRun(agentId, undefined, effectiveGatewayUrl);
1504
- // Add debug logs to events if present
1505
- if (result.ok && result.debugLogs) {
1506
- result.debugLogs.forEach((log) => {
1507
- events.push({
1508
- id: `sys-debug-${Date.now()}-${Math.random()}`,
1509
- ts: Date.now(),
1510
- tag: 'SYS',
1511
- level: 'INFO',
1512
- msg: log.replace(/^\[SYS\]\s*/, ''), // Remove duplicate [SYS] tag
1513
- });
1514
- });
1515
- }
1516
- if (!result.ok) {
1517
- const error = result.error;
1518
- const httpStatus = error.httpStatus;
1519
- const responseBody = error.responseBody;
1520
- // Add debug logs to events if present
1521
- if (error.debugLogs) {
1522
- error.debugLogs.forEach((log) => {
1523
- events.push({
1524
- id: `sys-debug-${Date.now()}-${Math.random()}`,
1525
- ts: Date.now(),
1526
- tag: 'SYS',
1527
- level: 'INFO',
1528
- msg: log.replace(/^\[SYS\]\s*/, ''), // Remove duplicate [SYS] tag
1529
- });
1530
- });
1531
- }
1532
- // Build detailed error message
1533
- let errorMsg = `Failed to start run: ${error.message}`;
1534
- if (httpStatus) {
1535
- errorMsg = `${httpStatus} ${httpStatus === 400 ? 'Bad Request' : httpStatus === 404 ? 'Not Found' : httpStatus === 401 ? 'Unauthorized' : 'Error'}: ${error.message}`;
1536
- }
1537
- // Include response body if available
1538
- if (responseBody) {
1539
- try {
1540
- const bodyStr = typeof responseBody === 'string' ? responseBody : JSON.stringify(responseBody);
1541
- errorMsg += `\n Response: ${bodyStr}`;
1542
- }
1543
- catch {
1544
- // Ignore serialization errors
1545
- }
1546
- }
1547
- events.push({
1548
- id: `err-${Date.now()}`,
1549
- ts: Date.now(),
1550
- tag: 'ERR',
1551
- level: 'ERROR',
1552
- msg: errorMsg,
1553
- });
1554
- return {
1555
- events,
1556
- uiStateUpdate: (prev) => ({
1557
- ...prev,
1558
- posture: unavailable(error.message, error.nextAction || 'Check gateway connection and agent ID'),
1559
- }),
1560
- };
1561
- }
1562
- // Success: posture → AVAILABLE (mode: RUNNING)
1563
- events.push({
1564
- id: `ok-${Date.now()}`,
1565
- ts: Date.now(),
1566
- tag: 'OK',
1567
- level: 'INFO',
1568
- msg: `Run started: ${result.data.id}`,
1569
- });
1570
- return {
1571
- events,
1572
- uiStateUpdate: (prev) => ({
1573
- ...prev,
1574
- posture: available({
1575
- mode: 'RUNNING',
1576
- }),
1577
- }),
1578
- };
1579
- }
1580
- catch (error) {
1581
- const classified = classifyError(error, 'start run');
1582
- events.push({
1583
- id: `err-${Date.now()}`,
1584
- ts: Date.now(),
1585
- tag: 'ERR',
1586
- level: 'ERROR',
1587
- msg: `Failed to start run: ${classified.message}`,
1588
- });
1589
- return {
1590
- events,
1591
- uiStateUpdate: (prev) => ({
1592
- ...prev,
1593
- posture: unavailable(classified.message, classified.nextAction),
1594
- }),
1595
- };
1596
- }
1597
- }
1598
- /**
1599
- * 6️⃣ runs list
1600
- *
1601
- * Calls v1Adapters/runs (needs listRuns function - TODO)
1602
- * Updates posture → AVAILABLE
1603
- */
1604
- async function handleRuns(ctx, args) {
1605
- const subcommand = args[0]?.toLowerCase() || 'list';
1606
- if (subcommand === 'list') {
1607
- return handleRunsList(ctx, args.slice(1));
1608
- }
1609
- else {
1610
- return {
1611
- events: [{
1612
- id: `err-${Date.now()}`,
1613
- ts: Date.now(),
1614
- tag: 'ERR',
1615
- level: 'ERROR',
1616
- msg: `Unknown runs subcommand: ${subcommand} (try: list)`,
1617
- }],
1618
- };
1619
- }
1620
- }
1621
- async function handleRunsList(ctx, args) {
1622
- const cmdEvent = {
1623
- id: `cmd-${Date.now()}`,
1624
- ts: Date.now(),
1625
- tag: 'CMD',
1626
- level: 'INFO',
1627
- msg: 'runs list',
1628
- };
1629
- // Check connection first
1630
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
1631
- const connState = gatewayConnectionStore.getState();
1632
- if (connState.status !== 'connected') {
1633
- const classified = classifyError({ code: 'NOT_CONNECTED', message: 'Not connected' }, 'list runs');
1634
- return {
1635
- events: [
1636
- cmdEvent,
1637
- {
1638
- id: `err-${Date.now()}`,
1639
- ts: Date.now(),
1640
- tag: 'ERR',
1641
- level: 'ERROR',
1642
- msg: `Failed to list runs: ${classified.message}`,
1643
- },
1644
- ],
1645
- uiStateUpdate: (prev) => ({
1646
- ...prev,
1647
- network: unavailable(classified.message, classified.nextAction),
1648
- assets: unavailable('Cannot fetch runs - not connected', 'Run "connect" first'),
1649
- }),
1650
- };
1651
- }
1652
- // Add debug output
1653
- const events = [
1654
- cmdEvent,
1655
- {
1656
- id: `sys-runs-gateway-${Date.now()}`,
1657
- ts: Date.now(),
1658
- tag: 'SYS',
1659
- level: 'INFO',
1660
- msg: `Fetching runs from: ${connState.resolvedTo}`,
1661
- },
1662
- ];
1663
- try {
1664
- // Use resolved endpoint from store (same as start command)
1665
- const result = await listRuns({ limit: 50 }, connState.resolvedTo);
1666
- // Add debug logs to events if present
1667
- if (result.ok && result.debugLogs) {
1668
- result.debugLogs.forEach((log) => {
1669
- events.push({
1670
- id: `sys-debug-${Date.now()}-${Math.random()}`,
1671
- ts: Date.now(),
1672
- tag: 'SYS',
1673
- level: 'INFO',
1674
- msg: log.replace(/^\[SYS\]\s*/, ''), // Remove duplicate [SYS] tag
1675
- });
1676
- });
1677
- }
1678
- if (!result.ok) {
1679
- const error = result.error;
1680
- const httpStatus = error.httpStatus;
1681
- const responseBody = error.responseBody;
1682
- // Build detailed error message
1683
- let errorMsg = `Failed to list runs: ${error.message}`;
1684
- if (httpStatus) {
1685
- errorMsg = `${httpStatus} ${httpStatus === 400 ? 'Bad Request' : httpStatus === 401 ? 'Unauthorized' : httpStatus === 403 ? 'Forbidden' : httpStatus === 404 ? 'Not Found' : 'Error'}: ${error.message}`;
1686
- }
1687
- // Include response body if available
1688
- if (responseBody) {
1689
- try {
1690
- const bodyStr = typeof responseBody === 'string' ? responseBody : JSON.stringify(responseBody);
1691
- errorMsg += `\n Response: ${bodyStr}`;
1692
- }
1693
- catch {
1694
- // Ignore serialization errors
1695
- }
1696
- }
1697
- // Add debug logs to events if present
1698
- if (error.debugLogs) {
1699
- error.debugLogs.forEach((log) => {
1700
- events.push({
1701
- id: `sys-debug-${Date.now()}-${Math.random()}`,
1702
- ts: Date.now(),
1703
- tag: 'SYS',
1704
- level: 'INFO',
1705
- msg: log.replace(/^\[SYS\]\s*/, ''), // Remove duplicate [SYS] tag
1706
- });
1707
- });
1708
- }
1709
- events.push({
1710
- id: `err-${Date.now()}`,
1711
- ts: Date.now(),
1712
- tag: 'ERR',
1713
- level: 'ERROR',
1714
- msg: errorMsg,
1715
- });
1716
- return {
1717
- events,
1718
- uiStateUpdate: (prev) => ({
1719
- ...prev,
1720
- assets: unavailable(error.message, error.nextAction || 'Check gateway connection'),
1721
- }),
1722
- };
1723
- }
1724
- const runs = result.data;
1725
- const count = runs.length;
1726
- const activeCount = runs.filter(r => r.status === 'running' || r.status === 'queued').length;
1727
- const completedCount = runs.filter(r => r.status === 'completed').length;
1728
- const errorCount = runs.filter(r => r.status === 'failed' || r.status === 'cancelled').length;
1729
- // Debug: Show what we got
1730
- events.push({
1731
- id: `sys-runs-count-${Date.now()}`,
1732
- ts: Date.now(),
1733
- tag: 'SYS',
1734
- level: 'INFO',
1735
- msg: `Found ${count} run${count === 1 ? '' : 's'}: ${activeCount} active, ${completedCount} completed, ${errorCount} failed`,
1736
- });
1737
- // Show run IDs for debugging
1738
- if (count > 0 && count <= 10) {
1739
- runs.forEach((run, idx) => {
1740
- events.push({
1741
- id: `sys-run-${idx}-${Date.now()}`,
1742
- ts: Date.now(),
1743
- tag: 'SYS',
1744
- level: 'INFO',
1745
- msg: ` ${idx + 1}. ${run.id} (${run.status}) - ${run.name}`,
1746
- });
1747
- });
1748
- }
1749
- // Update Assets panel with run summary
1750
- const assetsState = {
1751
- total: count,
1752
- active: activeCount,
1753
- idle: completedCount,
1754
- error: errorCount,
1755
- };
1756
- // Emit exactly one terminal event
1757
- const resultEvent = {
1758
- id: `result-${Date.now()}`,
1759
- ts: Date.now(),
1760
- tag: count === 0 ? 'WARN' : 'OK',
1761
- level: count === 0 ? 'WARN' : 'INFO',
1762
- msg: count === 0 ? 'No runs found' : `${count} run${count === 1 ? '' : 's'} found (${activeCount} active, ${completedCount} completed, ${errorCount} failed)`,
1763
- };
1764
- events.push(resultEvent);
1765
- return {
1766
- events,
1767
- uiStateUpdate: (prev) => ({
1768
- ...prev,
1769
- assets: available(assetsState),
1770
- }),
1771
- };
1772
- }
1773
- catch (error) {
1774
- const classified = classifyError(error, 'list runs');
1775
- events.push({
1776
- id: `err-${Date.now()}`,
1777
- ts: Date.now(),
1778
- tag: 'ERR',
1779
- level: 'ERROR',
1780
- msg: `Failed to list runs: ${classified.message}`,
1781
- });
1782
- return {
1783
- events,
1784
- uiStateUpdate: (prev) => ({
1785
- ...prev,
1786
- assets: unavailable(classified.message, classified.nextAction),
1787
- }),
1788
- };
1789
- }
1790
- }
1791
- /**
1792
- * 7️⃣ diagnose
1793
- *
1794
- * Diagnoses Gateway connection issues
1795
- * Shows detailed information about why connect is failing
1796
- */
1797
- async function handleDiagnose(ctx, args) {
1798
- const events = [
1799
- {
1800
- id: `cmd-diagnose-${Date.now()}`,
1801
- ts: Date.now(),
1802
- tag: 'CMD',
1803
- level: 'INFO',
1804
- msg: 'diagnose',
1805
- },
1806
- {
1807
- id: `sys-diagnose-${Date.now()}`,
1808
- ts: Date.now(),
1809
- tag: 'SYS',
1810
- level: 'INFO',
1811
- msg: 'Diagnosing Gateway connection...',
1812
- },
1813
- ];
1814
- try {
1815
- const result = await diagnoseGateway();
1816
- // Show endpoint being tested
1817
- events.push({
1818
- id: `diag-endpoint-${Date.now()}`,
1819
- ts: Date.now(),
1820
- tag: 'SYS',
1821
- level: 'INFO',
1822
- msg: `Testing: ${result.endpoint}`,
1823
- });
1824
- if (result.healthReachable && result.healthResponse) {
1825
- // Success!
1826
- events.push({
1827
- id: `diag-success-${Date.now()}`,
1828
- ts: Date.now(),
1829
- tag: 'OK',
1830
- level: 'INFO',
1831
- msg: `✅ Gateway is reachable`,
1832
- });
1833
- const healthStr = JSON.stringify(result.healthResponse).substring(0, 150);
1834
- events.push({
1835
- id: `diag-health-${Date.now()}`,
1836
- ts: Date.now(),
1837
- tag: 'SYS',
1838
- level: 'INFO',
1839
- msg: `Health: ${healthStr}...`,
1840
- });
1841
- }
1842
- else {
1843
- // Failure - show detailed error
1844
- events.push({
1845
- id: `diag-error-${Date.now()}`,
1846
- ts: Date.now(),
1847
- tag: 'ERR',
1848
- level: 'ERROR',
1849
- msg: `❌ ${result.error || 'Connection failed'}`,
1850
- });
1851
- if (result.errorCode) {
1852
- events.push({
1853
- id: `diag-code-${Date.now()}`,
1854
- ts: Date.now(),
1855
- tag: 'SYS',
1856
- level: 'INFO',
1857
- msg: `Error code: ${result.errorCode}`,
1858
- });
1859
- }
1860
- // Provide specific guidance based on error
1861
- if (result.errorCode === 'ECONNREFUSED') {
1862
- events.push({
1863
- id: `diag-help-${Date.now()}`,
1864
- ts: Date.now(),
1865
- tag: 'SYS',
1866
- level: 'INFO',
1867
- msg: 'Gateway is not running. Start it with: docker-compose up -d gateway',
1868
- });
1869
- }
1870
- else if (result.errorCode === 'ETIMEDOUT' || result.errorCode === 'ECONNABORTED') {
1871
- events.push({
1872
- id: `diag-help-${Date.now()}`,
1873
- ts: Date.now(),
1874
- tag: 'SYS',
1875
- level: 'INFO',
1876
- msg: 'Connection timeout. Check firewall or network connectivity.',
1877
- });
1878
- }
1879
- else if (result.errorCode?.startsWith('HTTP_404')) {
1880
- events.push({
1881
- id: `diag-help-${Date.now()}`,
1882
- ts: Date.now(),
1883
- tag: 'SYS',
1884
- level: 'INFO',
1885
- msg: 'Health endpoint not found. Gateway may be running but misconfigured.',
1886
- });
1887
- }
1888
- }
1889
- return { events };
1890
- }
1891
- catch (error) {
1892
- events.push({
1893
- id: `diag-exception-${Date.now()}`,
1894
- ts: Date.now(),
1895
- tag: 'ERR',
1896
- level: 'ERROR',
1897
- msg: `Diagnostic failed: ${error?.message || 'Unknown error'}`,
1898
- });
1899
- return { events };
1900
- }
1901
- }
1902
- /**
1903
- * 8️⃣ system
1904
- *
1905
- * Aggregates network state, config, agent count, run count
1906
- * Updates statusStrip → AVAILABLE
1907
- */
1908
- async function handleSystem(ctx, args) {
1909
- const cmdEvent = {
1910
- id: `cmd-${Date.now()}`,
1911
- ts: Date.now(),
1912
- tag: 'CMD',
1913
- level: 'INFO',
1914
- msg: 'system',
1915
- };
1916
- const events = [cmdEvent];
1917
- try {
1918
- // Get connection state
1919
- const { gatewayConnectionStore } = await import('../state/gatewayConnectionStore.js');
1920
- const connState = gatewayConnectionStore.getState();
1921
- // Aggregate system state
1922
- const agentsResult = listAgents();
1923
- const configResult = loadConfig();
1924
- const agentCount = agentsResult.ok ? agentsResult.data.length : 0;
1925
- const connected = connState.status === 'connected';
1926
- // Build status summary
1927
- const statusLeft = connected ? 'ONLINE' : 'OFFLINE';
1928
- const statusRight = `Agents: ${agentCount}`;
1929
- // Show system health summary
1930
- events.push({
1931
- id: `sys-health-${Date.now()}`,
1932
- ts: Date.now(),
1933
- tag: 'SYS',
1934
- level: 'INFO',
1935
- msg: `System Health Snapshot`,
1936
- });
1937
- events.push({
1938
- id: `sys-conn-${Date.now()}`,
1939
- ts: Date.now(),
1940
- tag: 'SYS',
1941
- level: connected ? 'INFO' : 'WARN',
1942
- msg: ` Gateway: ${connected ? 'CONNECTED' : connState.status.toUpperCase()}`,
1943
- });
1944
- if (connected && connState.resolvedTo) {
1945
- events.push({
1946
- id: `sys-endpoint-${Date.now()}`,
1947
- ts: Date.now(),
1948
- tag: 'SYS',
1949
- level: 'INFO',
1950
- msg: ` Endpoint: ${connState.resolvedTo}`,
1951
- });
1952
- }
1953
- events.push({
1954
- id: `sys-agents-${Date.now()}`,
1955
- ts: Date.now(),
1956
- tag: 'SYS',
1957
- level: 'INFO',
1958
- msg: ` Agents: ${agentCount}`,
1959
- });
1960
- // Refresh resources (trigger collector update)
1961
- const { collectResources } = await import('../collectors/resources.js');
1962
- const resources = await collectResources();
1963
- // Determine overall health
1964
- const isHealthy = connected && agentCount >= 0; // Basic health check
1965
- events.push({
1966
- id: isHealthy ? `ok-${Date.now()}` : `warn-${Date.now()}`,
1967
- ts: Date.now(),
1968
- tag: isHealthy ? 'OK' : 'WARN',
1969
- level: isHealthy ? 'INFO' : 'WARN',
1970
- msg: isHealthy ? 'System healthy' : 'Partial connectivity',
1971
- });
1972
- return {
1973
- events,
1974
- uiStateUpdate: (prev) => ({
1975
- ...prev,
1976
- resources, // Refresh resources
1977
- statusStrip: available({
1978
- left: statusLeft,
1979
- right: statusRight,
1980
- }),
1981
- // Refresh network timestamp if connected (preserve state, just update)
1982
- network: connected && connState.status === 'connected' ? prev.network : prev.network,
1983
- }),
1984
- };
1985
- }
1986
- catch (error) {
1987
- const classified = classifyError(error, 'system check');
1988
- return {
1989
- events: [
1990
- cmdEvent,
1991
- {
1992
- id: `err-${Date.now()}`,
1993
- ts: Date.now(),
1994
- tag: 'ERR',
1995
- level: 'ERROR',
1996
- msg: `System check failed: ${classified.message}`,
1997
- },
1998
- ],
1999
- uiStateUpdate: (prev) => ({
2000
- ...prev,
2001
- statusStrip: unavailable(classified.message, classified.nextAction),
2002
- }),
2003
- };
2004
- }
2005
- }
2006
- /**
2007
- * 9️⃣ debug <subcommand>
2008
- *
2009
- * Debug commands for TUI lifecycle investigation
2010
- * Only available with TUI_DEBUG=1
2011
- */
2012
- async function handleDebug(ctx, args) {
2013
- // Check if debug mode is enabled (some commands require it, but geo is always available)
2014
- const isDebugMode = process.env.TUI_DEBUG === '1';
2015
- const subcommand = args[0]?.toLowerCase();
2016
- if (!subcommand) {
2017
- return {
2018
- events: [{
2019
- id: `err-${Date.now()}`,
2020
- ts: Date.now(),
2021
- tag: 'ERR',
2022
- level: 'ERROR',
2023
- msg: 'Usage: debug <ui|geo|resize|resize-test|resize-torture|resize-trace|layout|tree|dump-layout|fullscreen|size|listeners|stdout>',
2024
- }],
2025
- };
2026
- }
2027
- // Allow geo and layout dump commands without debug mode (diagnostic tools)
2028
- const alwaysAllowed = ['geo', 'geometry', 'dump-layout', 'layout', 'layout-detail'];
2029
- const requiresDebug = !alwaysAllowed.includes(subcommand);
2030
- if (requiresDebug && !isDebugMode) {
2031
- return {
2032
- events: [{
2033
- id: `err-${Date.now()}`,
2034
- ts: Date.now(),
2035
- tag: 'ERR',
2036
- level: 'ERROR',
2037
- msg: 'Debug commands require TUI_DEBUG=1 environment variable (except: geo, dump-layout, layout)',
2038
- }],
2039
- };
2040
- }
2041
- const cmdEvent = {
2042
- id: `cmd-${Date.now()}`,
2043
- ts: Date.now(),
2044
- tag: 'CMD',
2045
- level: 'INFO',
2046
- msg: `debug ${subcommand}`,
2047
- };
2048
- // Import debug utils (lazy load)
2049
- try {
2050
- const debugUtils = await import('../ui/debugUtils.js');
2051
- if (subcommand === 'ui') {
2052
- // Step 1B: UI inventory dump
2053
- // Get the screen from UIRuntime
2054
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2055
- const runtime = getUIRuntime();
2056
- debugUtils.dumpUIInventory(runtime.screen);
2057
- return {
2058
- events: [cmdEvent, {
2059
- id: `dbg-${Date.now()}`,
2060
- ts: Date.now(),
2061
- tag: 'DBG',
2062
- level: 'INFO',
2063
- msg: 'UI inventory dumped to Operations (check above)',
2064
- }],
2065
- };
2066
- }
2067
- else if (subcommand === 'geo' || subcommand === 'geometry') {
2068
- // Step 1: Enhanced geometry debug (prove which values change on fullscreen)
2069
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2070
- const { getTerminalGeometry, formatGeometry } = await import('../tui/geometry.js');
2071
- const runtime = getUIRuntime();
2072
- const geo = getTerminalGeometry(runtime.screen);
2073
- // Get all geometry sources
2074
- const screenCols = runtime.screen.cols ?? 'N/A';
2075
- const screenRows = runtime.screen.rows ?? 'N/A';
2076
- const screenWidth = runtime.screen.width ?? 'N/A';
2077
- const screenHeight = runtime.screen.height ?? 'N/A';
2078
- const stdoutCols = process.stdout.columns ?? 'N/A';
2079
- const stdoutRows = process.stdout.rows ?? 'N/A';
2080
- return {
2081
- events: [
2082
- cmdEvent,
2083
- {
2084
- id: `dbg-geo-${Date.now()}`,
2085
- ts: Date.now(),
2086
- tag: 'DBG',
2087
- level: 'INFO',
2088
- msg: `=== GEOMETRY SOURCES ===`,
2089
- },
2090
- {
2091
- id: `dbg-geo-screen-${Date.now()}`,
2092
- ts: Date.now(),
2093
- tag: 'DBG',
2094
- level: 'INFO',
2095
- msg: `screen.cols=${screenCols} screen.rows=${screenRows}`,
2096
- },
2097
- {
2098
- id: `dbg-geo-screen-wh-${Date.now()}`,
2099
- ts: Date.now(),
2100
- tag: 'DBG',
2101
- level: 'INFO',
2102
- msg: `screen.width=${screenWidth} screen.height=${screenHeight}`,
2103
- },
2104
- {
2105
- id: `dbg-geo-stdout-${Date.now()}`,
2106
- ts: Date.now(),
2107
- tag: 'DBG',
2108
- level: 'INFO',
2109
- msg: `stdout.columns=${stdoutCols} stdout.rows=${stdoutRows}`,
2110
- },
2111
- {
2112
- id: `dbg-geo-final-${Date.now()}`,
2113
- ts: Date.now(),
2114
- tag: 'DBG',
2115
- level: 'INFO',
2116
- msg: `Final: ${formatGeometry(geo)}`,
2117
- },
2118
- {
2119
- id: `dbg-geo-layout-${Date.now()}`,
2120
- ts: Date.now(),
2121
- tag: 'DBG',
2122
- level: 'INFO',
2123
- msg: `Layout using: cols=${geo.cols} rows=${geo.rows} safeCols=${geo.safeCols} safeRows=${geo.safeRows}`,
2124
- },
2125
- ],
2126
- };
2127
- }
2128
- else if (subcommand === 'resize') {
2129
- // Phase C1: Resize stats
2130
- const resizeStats = debugUtils.getResizeStats();
2131
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2132
- const runtime = getUIRuntime();
2133
- const childrenCount = (runtime.screen.children || []).length;
2134
- return {
2135
- events: [
2136
- cmdEvent,
2137
- {
2138
- id: `dbg-resize-${Date.now()}`,
2139
- ts: Date.now(),
2140
- tag: 'DBG',
2141
- level: 'INFO',
2142
- msg: `=== RESIZE STATS ===`,
2143
- },
2144
- {
2145
- id: `dbg-resize2-${Date.now()}`,
2146
- ts: Date.now(),
2147
- tag: 'DBG',
2148
- level: 'INFO',
2149
- msg: `Events: ${resizeStats.eventCount}`,
2150
- },
2151
- {
2152
- id: `dbg-resize3-${Date.now()}`,
2153
- ts: Date.now(),
2154
- tag: 'DBG',
2155
- level: 'INFO',
2156
- msg: `Applies: ${resizeStats.applyCount}`,
2157
- },
2158
- {
2159
- id: `dbg-resize4-${Date.now()}`,
2160
- ts: Date.now(),
2161
- tag: 'DBG',
2162
- level: 'INFO',
2163
- msg: `Handler bound: ${resizeStats.handlerBound ? 'yes' : 'no'}`,
2164
- },
2165
- {
2166
- id: `dbg-resize5-${Date.now()}`,
2167
- ts: Date.now(),
2168
- tag: 'DBG',
2169
- level: 'INFO',
2170
- msg: `Screen children: ${childrenCount} (should be constant)`,
2171
- },
2172
- {
2173
- id: `dbg-resize6-${Date.now()}`,
2174
- ts: Date.now(),
2175
- tag: 'DBG',
2176
- level: 'INFO',
2177
- msg: `Debounce: 100ms`,
2178
- },
2179
- {
2180
- id: `dbg-resize7-${Date.now()}`,
2181
- ts: Date.now(),
2182
- tag: 'DBG',
2183
- level: 'INFO',
2184
- msg: `=== END RESIZE STATS ===`,
2185
- },
2186
- ],
2187
- };
2188
- }
2189
- else if (subcommand === 'resize-test') {
2190
- // Comprehensive resize diagnostics (must pass all checks)
2191
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2192
- const { getTerminalGeometry, formatGeometry } = await import('../tui/geometry.js');
2193
- const runtime = getUIRuntime();
2194
- const geo = getTerminalGeometry(runtime.screen);
2195
- const resizeStats = debugUtils.getResizeStats();
2196
- // Get all dimension sources
2197
- const screenCols = runtime.screen.cols ?? 'N/A';
2198
- const screenRows = runtime.screen.rows ?? 'N/A';
2199
- const screenWidth = runtime.screen.width ?? 'N/A';
2200
- const screenHeight = runtime.screen.height ?? 'N/A';
2201
- const stdoutCols = process.stdout.columns ?? 'N/A';
2202
- const stdoutRows = process.stdout.rows ?? 'N/A';
2203
- // Get screen children count (must be constant)
2204
- const childrenCount = (runtime.screen.children || []).length;
2205
- // Check for duplicates
2206
- const commandLineCount = (runtime.screen.children || []).filter((w) => w.type === 'textbox' || w.type === 'box').length;
2207
- const events = [
2208
- cmdEvent,
2209
- {
2210
- id: `dbg-test-${Date.now()}`,
2211
- ts: Date.now(),
2212
- tag: 'DBG',
2213
- level: 'INFO',
2214
- msg: `=== RESIZE TEST DIAGNOSTICS ===`,
2215
- },
2216
- {
2217
- id: `dbg-test-1-${Date.now()}`,
2218
- ts: Date.now(),
2219
- tag: 'DBG',
2220
- level: 'INFO',
2221
- msg: `--- Terminal Dimensions ---`,
2222
- },
2223
- {
2224
- id: `dbg-test-2-${Date.now()}`,
2225
- ts: Date.now(),
2226
- tag: 'DBG',
2227
- level: 'INFO',
2228
- msg: `process.stdout: columns=${stdoutCols} rows=${stdoutRows}`,
2229
- },
2230
- {
2231
- id: `dbg-test-3-${Date.now()}`,
2232
- ts: Date.now(),
2233
- tag: 'DBG',
2234
- level: 'INFO',
2235
- msg: `screen.cols=${screenCols} screen.rows=${screenRows}`,
2236
- },
2237
- {
2238
- id: `dbg-test-4-${Date.now()}`,
2239
- ts: Date.now(),
2240
- tag: 'DBG',
2241
- level: 'INFO',
2242
- msg: `screen.width=${screenWidth} screen.height=${screenHeight}`,
2243
- },
2244
- {
2245
- id: `dbg-test-5-${Date.now()}`,
2246
- ts: Date.now(),
2247
- tag: 'DBG',
2248
- level: 'INFO',
2249
- msg: `Final geometry: ${formatGeometry(geo)}`,
2250
- },
2251
- {
2252
- id: `dbg-test-6-${Date.now()}`,
2253
- ts: Date.now(),
2254
- tag: 'DBG',
2255
- level: 'INFO',
2256
- msg: `--- Resize Stats ---`,
2257
- },
2258
- {
2259
- id: `dbg-test-7-${Date.now()}`,
2260
- ts: Date.now(),
2261
- tag: 'DBG',
2262
- level: 'INFO',
2263
- msg: `Events: ${resizeStats.eventCount}`,
2264
- },
2265
- {
2266
- id: `dbg-test-8-${Date.now()}`,
2267
- ts: Date.now(),
2268
- tag: 'DBG',
2269
- level: 'INFO',
2270
- msg: `Applies: ${resizeStats.applyCount}`,
2271
- },
2272
- {
2273
- id: `dbg-test-9-${Date.now()}`,
2274
- ts: Date.now(),
2275
- tag: 'DBG',
2276
- level: 'INFO',
2277
- msg: `Handler bound: ${resizeStats.handlerBound ? 'yes' : 'no'}`,
2278
- },
2279
- {
2280
- id: `dbg-test-10-${Date.now()}`,
2281
- ts: Date.now(),
2282
- tag: 'DBG',
2283
- level: 'INFO',
2284
- msg: `Resize listeners: ${resizeStats.listenerCount || 0} (expected: 1-2)`,
2285
- },
2286
- {
2287
- id: `dbg-test-11-${Date.now()}`,
2288
- ts: Date.now(),
2289
- tag: 'DBG',
2290
- level: 'INFO',
2291
- msg: `--- UI State ---`,
2292
- },
2293
- {
2294
- id: `dbg-test-12-${Date.now()}`,
2295
- ts: Date.now(),
2296
- tag: 'DBG',
2297
- level: 'INFO',
2298
- msg: `Screen children: ${childrenCount} (should be constant ~8)`,
2299
- },
2300
- {
2301
- id: `dbg-test-13-${Date.now()}`,
2302
- ts: Date.now(),
2303
- tag: 'DBG',
2304
- level: 'INFO',
2305
- msg: `UI rebuilds: ${resizeStats.uiRebuildCount || 0} (must be 0)`,
2306
- },
2307
- {
2308
- id: `dbg-test-14-${Date.now()}`,
2309
- ts: Date.now(),
2310
- tag: 'DBG',
2311
- level: childrenCount > 10 ? 'ERROR' : 'INFO',
2312
- msg: `${childrenCount > 10 ? '⚠ FAIL' : '✓ PASS'}: Children count check (${childrenCount} <= 10)`,
2313
- },
2314
- {
2315
- id: `dbg-test-15-${Date.now()}`,
2316
- ts: Date.now(),
2317
- tag: 'DBG',
2318
- level: (resizeStats.uiRebuildCount || 0) > 0 ? 'ERROR' : 'INFO',
2319
- msg: `${(resizeStats.uiRebuildCount || 0) > 0 ? '⚠ FAIL' : '✓ PASS'}: No UI rebuilds (${resizeStats.uiRebuildCount || 0} === 0)`,
2320
- },
2321
- {
2322
- id: `dbg-test-16-${Date.now()}`,
2323
- ts: Date.now(),
2324
- tag: 'DBG',
2325
- level: (resizeStats.listenerCount || 0) > 2 ? 'ERROR' : 'INFO',
2326
- msg: `${(resizeStats.listenerCount || 0) > 2 ? '⚠ FAIL' : '✓ PASS'}: Listener count check (${resizeStats.listenerCount || 0} <= 2)`,
2327
- },
2328
- {
2329
- id: `dbg-test-17-${Date.now()}`,
2330
- ts: Date.now(),
2331
- tag: 'DBG',
2332
- level: 'INFO',
2333
- msg: `--- Layout Bounds ---`,
2334
- },
2335
- {
2336
- id: `dbg-test-18-${Date.now()}`,
2337
- ts: Date.now(),
2338
- tag: 'DBG',
2339
- level: 'INFO',
2340
- msg: `safeCols: ${geo.safeCols}, safeRows: ${geo.safeRows}`,
2341
- },
2342
- {
2343
- id: `dbg-test-19-${Date.now()}`,
2344
- ts: Date.now(),
2345
- tag: 'DBG',
2346
- level: 'INFO',
2347
- msg: `Max right edge allowed: ${geo.safeCols - 1}`,
2348
- },
2349
- {
2350
- id: `dbg-test-20-${Date.now()}`,
2351
- ts: Date.now(),
2352
- tag: 'DBG',
2353
- level: 'INFO',
2354
- msg: `=== END RESIZE TEST ===`,
2355
- },
2356
- {
2357
- id: `dbg-test-21-${Date.now()}`,
2358
- ts: Date.now(),
2359
- tag: 'DBG',
2360
- level: 'INFO',
2361
- msg: `Toggle fullscreen and run again to verify stats update correctly.`,
2362
- },
2363
- ];
2364
- return { events };
2365
- }
2366
- else if (subcommand === 'resize-torture' || subcommand === 'torture') {
2367
- // Resize torture test - comprehensive widget duplication detection
2368
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2369
- const runtime = getUIRuntime();
2370
- const screen = runtime.screen;
2371
- const widgets = runtime.widgets;
2372
- // Get current dimensions
2373
- const { getTerminalGeometry } = await import('../tui/geometry.js');
2374
- const geo = getTerminalGeometry(screen);
2375
- // Count all widgets recursively
2376
- function countWidgets(node, depth = 0) {
2377
- const result = { total: 0, byType: {}, byId: {} };
2378
- if (!node)
2379
- return result;
2380
- result.total = 1;
2381
- // Track by type
2382
- const type = node.type || 'unknown';
2383
- result.byType[type] = (result.byType[type] || 0) + 1;
2384
- // Track by ID (if available)
2385
- const id = node.options?.id || node._id || 'no-id';
2386
- result.byId[id] = (result.byId[id] || 0) + 1;
2387
- // Recursively count children
2388
- if (node.children && Array.isArray(node.children)) {
2389
- for (const child of node.children) {
2390
- const childResult = countWidgets(child, depth + 1);
2391
- result.total += childResult.total;
2392
- // Merge byType
2393
- for (const [t, count] of Object.entries(childResult.byType)) {
2394
- result.byType[t] = (result.byType[t] || 0) + count;
2395
- }
2396
- // Merge byId
2397
- for (const [i, count] of Object.entries(childResult.byId)) {
2398
- result.byId[i] = (result.byId[i] || 0) + count;
2399
- }
2400
- }
2401
- }
2402
- return result;
2403
- }
2404
- const widgetStats = countWidgets(screen);
2405
- // Check for duplicates
2406
- const duplicateTypes = [];
2407
- for (const [type, count] of Object.entries(widgetStats.byType)) {
2408
- if (count > 1 && type !== 'box' && type !== 'text' && type !== 'line') {
2409
- duplicateTypes.push(`${type}=${count}`);
2410
- }
2411
- }
2412
- const duplicateIds = [];
2413
- for (const [id, count] of Object.entries(widgetStats.byId)) {
2414
- if (count > 1 && id !== 'no-id') {
2415
- duplicateIds.push(`${id}=${count}`);
2416
- }
2417
- }
2418
- // Count specific widgets
2419
- const postureCount = widgetStats.byType['box'] || 0; // Approximate
2420
- const commandLineCount = screen.children.filter((w) => w === widgets.commandLine).length;
2421
- // Get resize stats
2422
- const resizeStats = debugUtils.getResizeStats();
2423
- const events = [
2424
- cmdEvent,
2425
- {
2426
- id: `dbg-torture-1-${Date.now()}`,
2427
- ts: Date.now(),
2428
- tag: 'DBG',
2429
- level: 'INFO',
2430
- msg: `=== RESIZE TORTURE TEST ===`,
2431
- },
2432
- {
2433
- id: `dbg-torture-2-${Date.now()}`,
2434
- ts: Date.now(),
2435
- tag: 'DBG',
2436
- level: 'INFO',
2437
- msg: `Instructions: Toggle fullscreen ↔ windowed 10 times, then run this again.`,
2438
- },
2439
- {
2440
- id: `dbg-torture-3-${Date.now()}`,
2441
- ts: Date.now(),
2442
- tag: 'DBG',
2443
- level: 'INFO',
2444
- msg: ``,
2445
- },
2446
- {
2447
- id: `dbg-torture-4-${Date.now()}`,
2448
- ts: Date.now(),
2449
- tag: 'DBG',
2450
- level: 'INFO',
2451
- msg: `Current terminal: ${geo.cols}x${geo.rows} (source: ${geo.source})`,
2452
- },
2453
- {
2454
- id: `dbg-torture-5-${Date.now()}`,
2455
- ts: Date.now(),
2456
- tag: 'DBG',
2457
- level: 'INFO',
2458
- msg: ``,
2459
- },
2460
- {
2461
- id: `dbg-torture-6-${Date.now()}`,
2462
- ts: Date.now(),
2463
- tag: 'DBG',
2464
- level: 'INFO',
2465
- msg: `--- Widget Counts ---`,
2466
- },
2467
- {
2468
- id: `dbg-torture-7-${Date.now()}`,
2469
- ts: Date.now(),
2470
- tag: 'DBG',
2471
- level: 'INFO',
2472
- msg: `Total widgets: ${widgetStats.total} (should be stable ~8-15)`,
2473
- },
2474
- {
2475
- id: `dbg-torture-8-${Date.now()}`,
2476
- ts: Date.now(),
2477
- tag: 'DBG',
2478
- level: 'INFO',
2479
- msg: `Screen.children: ${screen.children.length}`,
2480
- },
2481
- {
2482
- id: `dbg-torture-9-${Date.now()}`,
2483
- ts: Date.now(),
2484
- tag: 'DBG',
2485
- level: 'INFO',
2486
- msg: `Command line instances: ${commandLineCount} (must be 1)`,
2487
- },
2488
- {
2489
- id: `dbg-torture-10-${Date.now()}`,
2490
- ts: Date.now(),
2491
- tag: 'DBG',
2492
- level: 'INFO',
2493
- msg: ``,
2494
- },
2495
- {
2496
- id: `dbg-torture-11-${Date.now()}`,
2497
- ts: Date.now(),
2498
- tag: 'DBG',
2499
- level: 'INFO',
2500
- msg: `--- Widget Types ---`,
2501
- },
2502
- ];
2503
- // Add widget type counts
2504
- for (const [type, count] of Object.entries(widgetStats.byType)) {
2505
- events.push({
2506
- id: `dbg-torture-type-${type}-${Date.now()}`,
2507
- ts: Date.now(),
2508
- tag: 'DBG',
2509
- level: 'INFO',
2510
- msg: ` ${type}: ${count}`,
2511
- });
2512
- }
2513
- events.push({
2514
- id: `dbg-torture-12-${Date.now()}`,
2515
- ts: Date.now(),
2516
- tag: 'DBG',
2517
- level: 'INFO',
2518
- msg: ``,
2519
- });
2520
- events.push({
2521
- id: `dbg-torture-13-${Date.now()}`,
2522
- ts: Date.now(),
2523
- tag: 'DBG',
2524
- level: 'INFO',
2525
- msg: `--- Resize Stats ---`,
2526
- });
2527
- events.push({
2528
- id: `dbg-torture-14-${Date.now()}`,
2529
- ts: Date.now(),
2530
- tag: 'DBG',
2531
- level: 'INFO',
2532
- msg: `Resize events: ${resizeStats.eventCount}`,
2533
- });
2534
- events.push({
2535
- id: `dbg-torture-15-${Date.now()}`,
2536
- ts: Date.now(),
2537
- tag: 'DBG',
2538
- level: 'INFO',
2539
- msg: `Resize applies: ${resizeStats.applyCount}`,
2540
- });
2541
- events.push({
2542
- id: `dbg-torture-16-${Date.now()}`,
2543
- ts: Date.now(),
2544
- tag: 'DBG',
2545
- level: 'INFO',
2546
- msg: `UI rebuilds: ${resizeStats.uiRebuildCount || 0} (must be 0)`,
2547
- });
2548
- events.push({
2549
- id: `dbg-torture-17-${Date.now()}`,
2550
- ts: Date.now(),
2551
- tag: 'DBG',
2552
- level: 'INFO',
2553
- msg: ``,
2554
- });
2555
- events.push({
2556
- id: `dbg-torture-18-${Date.now()}`,
2557
- ts: Date.now(),
2558
- tag: 'DBG',
2559
- level: duplicateTypes.length > 0 ? 'ERROR' : 'INFO',
2560
- msg: `--- Duplication Check ---`,
2561
- });
2562
- if (duplicateTypes.length > 0) {
2563
- events.push({
2564
- id: `dbg-torture-19-${Date.now()}`,
2565
- ts: Date.now(),
2566
- tag: 'DBG',
2567
- level: 'ERROR',
2568
- msg: `⚠ FAIL: Duplicate widget types detected: ${duplicateTypes.join(', ')}`,
2569
- });
2570
- }
2571
- else {
2572
- events.push({
2573
- id: `dbg-torture-19-${Date.now()}`,
2574
- ts: Date.now(),
2575
- tag: 'DBG',
2576
- level: 'INFO',
2577
- msg: `✓ PASS: No duplicate widget types`,
2578
- });
2579
- }
2580
- if (commandLineCount > 1) {
2581
- events.push({
2582
- id: `dbg-torture-20-${Date.now()}`,
2583
- ts: Date.now(),
2584
- tag: 'DBG',
2585
- level: 'ERROR',
2586
- msg: `⚠ FAIL: Multiple command lines (${commandLineCount})`,
2587
- });
2588
- }
2589
- else {
2590
- events.push({
2591
- id: `dbg-torture-20-${Date.now()}`,
2592
- ts: Date.now(),
2593
- tag: 'DBG',
2594
- level: 'INFO',
2595
- msg: `✓ PASS: Single command line`,
2596
- });
2597
- }
2598
- if ((resizeStats.uiRebuildCount || 0) > 0) {
2599
- events.push({
2600
- id: `dbg-torture-21-${Date.now()}`,
2601
- ts: Date.now(),
2602
- tag: 'DBG',
2603
- level: 'ERROR',
2604
- msg: `⚠ FAIL: UI was rebuilt ${resizeStats.uiRebuildCount} times (should be 0)`,
2605
- });
2606
- }
2607
- else {
2608
- events.push({
2609
- id: `dbg-torture-21-${Date.now()}`,
2610
- ts: Date.now(),
2611
- tag: 'DBG',
2612
- level: 'INFO',
2613
- msg: `✓ PASS: No UI rebuilds`,
2614
- });
2615
- }
2616
- events.push({
2617
- id: `dbg-torture-22-${Date.now()}`,
2618
- ts: Date.now(),
2619
- tag: 'DBG',
2620
- level: 'INFO',
2621
- msg: ``,
2622
- });
2623
- events.push({
2624
- id: `dbg-torture-23-${Date.now()}`,
2625
- ts: Date.now(),
2626
- tag: 'DBG',
2627
- level: 'INFO',
2628
- msg: `=== END TORTURE TEST ===`,
2629
- });
2630
- return { events };
2631
- }
2632
- else if (subcommand === 'size') {
2633
- // dbg:size - Show terminal sizing and environment info (works in V3 and V4)
2634
- const { handleSizeCommandWithScreen } = await import('../../../core/commands/size.js');
2635
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2636
- const runtime = getUIRuntime();
2637
- const screen = runtime.screen;
2638
- // Pass screen object to get actual dimensions
2639
- return handleSizeCommandWithScreen(ctx, args, {
2640
- width: screen.width,
2641
- height: screen.height,
2642
- cols: screen.cols,
2643
- rows: screen.rows,
2644
- });
2645
- }
2646
- else if (subcommand === 'tree') {
2647
- // Widget tree diagnostic - shows widget counts to detect duplication
2648
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2649
- const runtime = getUIRuntime();
2650
- const screen = runtime.screen;
2651
- const widgets = runtime.widgets;
2652
- // Count widgets recursively
2653
- function countWidgets(node, depth = 0) {
2654
- const result = { total: 0, byName: {} };
2655
- if (!node)
2656
- return result;
2657
- result.total = 1;
2658
- // Try to identify widget by title or type
2659
- const name = node.options?.title || node.options?.content || node.type || 'unknown';
2660
- const shortName = name.substring(0, 30).replace(/\s+/g, '_');
2661
- result.byName[shortName] = (result.byName[shortName] || 0) + 1;
2662
- // Recursively count children
2663
- if (node.children && Array.isArray(node.children)) {
2664
- for (const child of node.children) {
2665
- const childResult = countWidgets(child, depth + 1);
2666
- result.total += childResult.total;
2667
- // Merge byName
2668
- for (const [n, count] of Object.entries(childResult.byName)) {
2669
- result.byName[n] = (result.byName[n] || 0) + count;
2670
- }
2671
- }
2672
- }
2673
- return result;
2674
- }
2675
- // Count specific widgets
2676
- const screenChildren = screen.children || [];
2677
- const postureCount = screenChildren.filter((w) => w === widgets.posture).length;
2678
- const resourcesCount = screenChildren.filter((w) => w === widgets.resources).length;
2679
- const assetsCount = screenChildren.filter((w) => w === widgets.assets).length;
2680
- const operationsCount = screenChildren.filter((w) => w === widgets.operations).length;
2681
- const networkCount = screenChildren.filter((w) => w === widgets.network).length;
2682
- const capabilitiesCount = screenChildren.filter((w) => w === widgets.capabilities).length;
2683
- const commandLineCount = screenChildren.filter((w) => w === widgets.commandLine).length;
2684
- const statusStripCount = screenChildren.filter((w) => w === widgets.statusStrip).length;
2685
- const treeStats = countWidgets(screen);
2686
- const events = [
2687
- cmdEvent,
2688
- {
2689
- id: `dbg-tree-1-${Date.now()}`,
2690
- ts: Date.now(),
2691
- tag: 'DBG',
2692
- level: 'INFO',
2693
- msg: `=== WIDGET TREE DIAGNOSTIC ===`,
2694
- },
2695
- {
2696
- id: `dbg-tree-2-${Date.now()}`,
2697
- ts: Date.now(),
2698
- tag: 'DBG',
2699
- level: 'INFO',
2700
- msg: ``,
2701
- },
2702
- {
2703
- id: `dbg-tree-3-${Date.now()}`,
2704
- ts: Date.now(),
2705
- tag: 'DBG',
2706
- level: 'INFO',
2707
- msg: `screen.children.length: ${screenChildren.length} (expected: 8)`,
2708
- },
2709
- {
2710
- id: `dbg-tree-4-${Date.now()}`,
2711
- ts: Date.now(),
2712
- tag: 'DBG',
2713
- level: 'INFO',
2714
- msg: `Total recursive nodes: ${treeStats.total}`,
2715
- },
2716
- {
2717
- id: `dbg-tree-5-${Date.now()}`,
2718
- ts: Date.now(),
2719
- tag: 'DBG',
2720
- level: 'INFO',
2721
- msg: ``,
2722
- },
2723
- {
2724
- id: `dbg-tree-6-${Date.now()}`,
2725
- ts: Date.now(),
2726
- tag: 'DBG',
2727
- level: 'INFO',
2728
- msg: `--- Panel Counts (must be 1 each) ---`,
2729
- },
2730
- {
2731
- id: `dbg-tree-7-${Date.now()}`,
2732
- ts: Date.now(),
2733
- tag: 'DBG',
2734
- level: postureCount === 1 ? 'INFO' : 'ERROR',
2735
- msg: `POSTURE: ${postureCount} ${postureCount === 1 ? '✓' : '⚠ FAIL'}`,
2736
- },
2737
- {
2738
- id: `dbg-tree-8-${Date.now()}`,
2739
- ts: Date.now(),
2740
- tag: 'DBG',
2741
- level: resourcesCount === 1 ? 'INFO' : 'ERROR',
2742
- msg: `RESOURCES: ${resourcesCount} ${resourcesCount === 1 ? '✓' : '⚠ FAIL'}`,
2743
- },
2744
- {
2745
- id: `dbg-tree-9-${Date.now()}`,
2746
- ts: Date.now(),
2747
- tag: 'DBG',
2748
- level: assetsCount === 1 ? 'INFO' : 'ERROR',
2749
- msg: `ASSETS: ${assetsCount} ${assetsCount === 1 ? '✓' : '⚠ FAIL'}`,
2750
- },
2751
- {
2752
- id: `dbg-tree-10-${Date.now()}`,
2753
- ts: Date.now(),
2754
- tag: 'DBG',
2755
- level: operationsCount === 1 ? 'INFO' : 'ERROR',
2756
- msg: `OPERATIONS: ${operationsCount} ${operationsCount === 1 ? '✓' : '⚠ FAIL'}`,
2757
- },
2758
- {
2759
- id: `dbg-tree-11-${Date.now()}`,
2760
- ts: Date.now(),
2761
- tag: 'DBG',
2762
- level: networkCount === 1 ? 'INFO' : 'ERROR',
2763
- msg: `NETWORK: ${networkCount} ${networkCount === 1 ? '✓' : '⚠ FAIL'}`,
2764
- },
2765
- {
2766
- id: `dbg-tree-12-${Date.now()}`,
2767
- ts: Date.now(),
2768
- tag: 'DBG',
2769
- level: capabilitiesCount === 1 ? 'INFO' : 'ERROR',
2770
- msg: `CAPABILITIES: ${capabilitiesCount} ${capabilitiesCount === 1 ? '✓' : '⚠ FAIL'}`,
2771
- },
2772
- {
2773
- id: `dbg-tree-13-${Date.now()}`,
2774
- ts: Date.now(),
2775
- tag: 'DBG',
2776
- level: commandLineCount === 1 ? 'INFO' : 'ERROR',
2777
- msg: `COMMAND_LINE: ${commandLineCount} ${commandLineCount === 1 ? '✓' : '⚠ FAIL'}`,
2778
- },
2779
- {
2780
- id: `dbg-tree-14-${Date.now()}`,
2781
- ts: Date.now(),
2782
- tag: 'DBG',
2783
- level: statusStripCount === 1 ? 'INFO' : 'ERROR',
2784
- msg: `STATUS_STRIP: ${statusStripCount} ${statusStripCount === 1 ? '✓' : '⚠ FAIL'}`,
2785
- },
2786
- {
2787
- id: `dbg-tree-15-${Date.now()}`,
2788
- ts: Date.now(),
2789
- tag: 'DBG',
2790
- level: 'INFO',
2791
- msg: ``,
2792
- },
2793
- {
2794
- id: `dbg-tree-16-${Date.now()}`,
2795
- ts: Date.now(),
2796
- tag: 'DBG',
2797
- level: screenChildren.length === 8 ? 'INFO' : 'ERROR',
2798
- msg: `${screenChildren.length === 8 ? '✓ PASS' : '⚠ FAIL'}: Total children count (${screenChildren.length} === 8)`,
2799
- },
2800
- {
2801
- id: `dbg-tree-17-${Date.now()}`,
2802
- ts: Date.now(),
2803
- tag: 'DBG',
2804
- level: 'INFO',
2805
- msg: ``,
2806
- },
2807
- {
2808
- id: `dbg-tree-18-${Date.now()}`,
2809
- ts: Date.now(),
2810
- tag: 'DBG',
2811
- level: 'INFO',
2812
- msg: `=== END TREE DIAGNOSTIC ===`,
2813
- },
2814
- {
2815
- id: `dbg-tree-19-${Date.now()}`,
2816
- ts: Date.now(),
2817
- tag: 'DBG',
2818
- level: 'INFO',
2819
- msg: `Toggle fullscreen and run again to verify counts stay stable.`,
2820
- },
2821
- ];
2822
- return { events };
2823
- }
2824
- else if (subcommand === 'layout') {
2825
- // Layout overlay toggle - shows live layout instrumentation
2826
- const { setLayoutOverlayEnabled, getLayoutOverlayEnabled } = await import('../ui/phase1RuntimeClean.js');
2827
- if (args[1]?.toLowerCase() === 'on' || args[1]?.toLowerCase() === 'enable') {
2828
- setLayoutOverlayEnabled(true);
2829
- return {
2830
- events: [
2831
- cmdEvent,
2832
- {
2833
- id: `dbg-layout-${Date.now()}`,
2834
- ts: Date.now(),
2835
- tag: 'DBG',
2836
- level: 'INFO',
2837
- msg: 'Layout overlay ENABLED - live layout stats will show in Operations panel',
2838
- },
2839
- ],
2840
- };
2841
- }
2842
- else if (args[1]?.toLowerCase() === 'off' || args[1]?.toLowerCase() === 'disable') {
2843
- setLayoutOverlayEnabled(false);
2844
- return {
2845
- events: [
2846
- cmdEvent,
2847
- {
2848
- id: `dbg-layout-${Date.now()}`,
2849
- ts: Date.now(),
2850
- tag: 'DBG',
2851
- level: 'INFO',
2852
- msg: 'Layout overlay DISABLED',
2853
- },
2854
- ],
2855
- };
2856
- }
2857
- else {
2858
- // Show current status
2859
- const enabled = getLayoutOverlayEnabled();
2860
- return {
2861
- events: [
2862
- cmdEvent,
2863
- {
2864
- id: `dbg-layout-status-${Date.now()}`,
2865
- ts: Date.now(),
2866
- tag: 'DBG',
2867
- level: 'INFO',
2868
- msg: `Layout overlay: ${enabled ? 'ENABLED' : 'DISABLED'}`,
2869
- },
2870
- {
2871
- id: `dbg-layout-usage-${Date.now()}`,
2872
- ts: Date.now(),
2873
- tag: 'DBG',
2874
- level: 'INFO',
2875
- msg: `Usage: debug layout <on|off>`,
2876
- },
2877
- ],
2878
- };
2879
- }
2880
- }
2881
- else if (subcommand === 'resize-trace' || subcommand === 'trace-resize') {
2882
- // Resize trace mode toggle
2883
- const { setResizeTraceEnabled, getResizeTraceEnabled } = await import('../ui/phase1RuntimeClean.js');
2884
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2885
- if (args[1]?.toLowerCase() === 'on' || args[1]?.toLowerCase() === 'enable') {
2886
- setResizeTraceEnabled(true);
2887
- return {
2888
- events: [
2889
- cmdEvent,
2890
- {
2891
- id: `dbg-trace-${Date.now()}`,
2892
- ts: Date.now(),
2893
- tag: 'DBG',
2894
- level: 'INFO',
2895
- msg: 'Resize trace ENABLED - all resize events will be logged',
2896
- },
2897
- ],
2898
- };
2899
- }
2900
- else if (args[1]?.toLowerCase() === 'off' || args[1]?.toLowerCase() === 'disable') {
2901
- setResizeTraceEnabled(false);
2902
- return {
2903
- events: [
2904
- cmdEvent,
2905
- {
2906
- id: `dbg-trace-${Date.now()}`,
2907
- ts: Date.now(),
2908
- tag: 'DBG',
2909
- level: 'INFO',
2910
- msg: 'Resize trace DISABLED',
2911
- },
2912
- ],
2913
- };
2914
- }
2915
- else {
2916
- // Show current status
2917
- const enabled = getResizeTraceEnabled();
2918
- const runtime = getUIRuntime();
2919
- const childrenCount = (runtime.screen.children || []).length;
2920
- const resizeStats = debugUtils.getResizeStats();
2921
- return {
2922
- events: [
2923
- cmdEvent,
2924
- {
2925
- id: `dbg-trace-status-${Date.now()}`,
2926
- ts: Date.now(),
2927
- tag: 'DBG',
2928
- level: 'INFO',
2929
- msg: `Resize trace: ${enabled ? 'ENABLED' : 'DISABLED'}`,
2930
- },
2931
- {
2932
- id: `dbg-trace-status2-${Date.now()}`,
2933
- ts: Date.now(),
2934
- tag: 'DBG',
2935
- level: 'INFO',
2936
- msg: `Usage: debug resize-trace <on|off>`,
2937
- },
2938
- {
2939
- id: `dbg-trace-status3-${Date.now()}`,
2940
- ts: Date.now(),
2941
- tag: 'DBG',
2942
- level: 'INFO',
2943
- msg: `Current: Events=${resizeStats.eventCount}, Applies=${resizeStats.applyCount}, Children=${childrenCount}`,
2944
- },
2945
- ],
2946
- };
2947
- }
2948
- }
2949
- else if (subcommand === 'dump-layout' || subcommand === 'layout' || subcommand === 'layout-detail') {
2950
- // Phase D: Layout dump - comprehensive debugging
2951
- // Pure snapshot: compute once, print once, return immediately (no async operations)
2952
- const { dumpLayout } = await import('../ui/phase1RuntimeClean.js');
2953
- const layoutLines = dumpLayout();
2954
- // Limit output to prevent spam (max 30 lines)
2955
- const MAX_OUTPUT_LINES = 30;
2956
- const linesToShow = layoutLines.slice(0, MAX_OUTPUT_LINES);
2957
- const events = [cmdEvent];
2958
- for (const line of linesToShow) {
2959
- events.push({
2960
- id: `dbg-layout-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`,
2961
- ts: Date.now(),
2962
- tag: 'DBG',
2963
- level: 'INFO',
2964
- msg: line,
2965
- });
2966
- }
2967
- // Add truncation notice if needed
2968
- if (layoutLines.length > MAX_OUTPUT_LINES) {
2969
- events.push({
2970
- id: `dbg-layout-trunc-${Date.now()}`,
2971
- ts: Date.now(),
2972
- tag: 'DBG',
2973
- level: 'INFO',
2974
- msg: `... (output truncated, ${layoutLines.length - MAX_OUTPUT_LINES} more lines)`,
2975
- });
2976
- }
2977
- // Return immediately - no async operations, no render calls, no resize triggers
2978
- return { events };
2979
- }
2980
- else if (subcommand === 'fullscreen') {
2981
- // Fullscreen diagnostic - shows 12 critical values for fullscreen debugging
2982
- const { getUIRuntime } = await import('../ui/uiRuntime.js');
2983
- const { computePhase1Layout } = await import('../ui/layout/phase1Layout.js');
2984
- const runtime = getUIRuntime();
2985
- const screen = runtime.screen;
2986
- // Get all dimension sources
2987
- const screenWidth = screen.width ?? 'N/A';
2988
- const screenHeight = screen.height ?? 'N/A';
2989
- const programCols = screen.program?.cols ?? 'N/A';
2990
- const programRows = screen.program?.rows ?? 'N/A';
2991
- const stdoutCols = process.stdout.columns ?? 'N/A';
2992
- const stdoutRows = process.stdout.rows ?? 'N/A';
2993
- const stderrCols = process.stderr.columns ?? 'N/A';
2994
- const stderrRows = process.stderr.rows ?? 'N/A';
2995
- // Get actual geometry being used (authoritative source)
2996
- const { getTerminalGeometry, getTerminalSize } = await import('../tui/geometry.js');
2997
- const actualSize = getTerminalSize(screen);
2998
- const actualGeo = getTerminalGeometry(screen);
2999
- // Compute layout to get metadata (pass fresh screen to use current geometry)
3000
- const layoutResult = computePhase1Layout(screen.width ?? 80, screen.height ?? 24, screen);
3001
- const events = [
3002
- cmdEvent,
3003
- {
3004
- id: `dbg-fullscreen-1-${Date.now()}`,
3005
- ts: Date.now(),
3006
- tag: 'DBG',
3007
- level: 'INFO',
3008
- msg: `=== FULLSCREEN DIAGNOSTIC ===`,
3009
- },
3010
- {
3011
- id: `dbg-fullscreen-2-${Date.now()}`,
3012
- ts: Date.now(),
3013
- tag: 'DBG',
3014
- level: 'INFO',
3015
- msg: `A. TERMINAL DIMENSIONS (all sources):`,
3016
- },
3017
- {
3018
- id: `dbg-fullscreen-3-${Date.now()}`,
3019
- ts: Date.now(),
3020
- tag: 'DBG',
3021
- level: 'INFO',
3022
- msg: ` screen.width: ${screenWidth}`,
3023
- },
3024
- {
3025
- id: `dbg-fullscreen-4-${Date.now()}`,
3026
- ts: Date.now(),
3027
- tag: 'DBG',
3028
- level: 'INFO',
3029
- msg: ` screen.height: ${screenHeight}`,
3030
- },
3031
- {
3032
- id: `dbg-fullscreen-5-${Date.now()}`,
3033
- ts: Date.now(),
3034
- tag: 'DBG',
3035
- level: 'INFO',
3036
- msg: ` screen.program.cols: ${programCols}`,
3037
- },
3038
- {
3039
- id: `dbg-fullscreen-6-${Date.now()}`,
3040
- ts: Date.now(),
3041
- tag: 'DBG',
3042
- level: 'INFO',
3043
- msg: ` screen.program.rows: ${programRows}`,
3044
- },
3045
- {
3046
- id: `dbg-fullscreen-7-${Date.now()}`,
3047
- ts: Date.now(),
3048
- tag: 'DBG',
3049
- level: 'INFO',
3050
- msg: ` process.stdout.columns: ${stdoutCols}`,
3051
- },
3052
- {
3053
- id: `dbg-fullscreen-8-${Date.now()}`,
3054
- ts: Date.now(),
3055
- tag: 'DBG',
3056
- level: 'INFO',
3057
- msg: ` process.stdout.rows: ${stdoutRows}`,
3058
- },
3059
- {
3060
- id: `dbg-fullscreen-9-${Date.now()}`,
3061
- ts: Date.now(),
3062
- tag: 'DBG',
3063
- level: 'INFO',
3064
- msg: ` process.stderr.columns: ${stderrCols}`,
3065
- },
3066
- {
3067
- id: `dbg-fullscreen-10-${Date.now()}`,
3068
- ts: Date.now(),
3069
- tag: 'DBG',
3070
- level: 'INFO',
3071
- msg: ` process.stderr.rows: ${stderrRows}`,
3072
- },
3073
- {
3074
- id: `dbg-fullscreen-11-${Date.now()}`,
3075
- ts: Date.now(),
3076
- tag: 'DBG',
3077
- level: 'INFO',
3078
- msg: ``,
3079
- },
3080
- {
3081
- id: `dbg-fullscreen-12-${Date.now()}`,
3082
- ts: Date.now(),
3083
- tag: 'DBG',
3084
- level: 'INFO',
3085
- msg: `C. GEOMETRY USED (authoritative):`,
3086
- },
3087
- {
3088
- id: `dbg-fullscreen-13-${Date.now()}`,
3089
- ts: Date.now(),
3090
- tag: 'DBG',
3091
- level: 'INFO',
3092
- msg: ` getTerminalSize() source: ${actualSize.source}`,
3093
- },
3094
- {
3095
- id: `dbg-fullscreen-14-${Date.now()}`,
3096
- ts: Date.now(),
3097
- tag: 'DBG',
3098
- level: 'INFO',
3099
- msg: ` getTerminalSize() cols: ${actualSize.cols}`,
3100
- },
3101
- {
3102
- id: `dbg-fullscreen-15-${Date.now()}`,
3103
- ts: Date.now(),
3104
- tag: 'DBG',
3105
- level: 'INFO',
3106
- msg: ` getTerminalSize() rows: ${actualSize.rows}`,
3107
- },
3108
- {
3109
- id: `dbg-fullscreen-16-${Date.now()}`,
3110
- ts: Date.now(),
3111
- tag: 'DBG',
3112
- level: 'INFO',
3113
- msg: ` getTerminalGeometry() safeCols: ${actualGeo.safeCols}`,
3114
- },
3115
- {
3116
- id: `dbg-fullscreen-17-${Date.now()}`,
3117
- ts: Date.now(),
3118
- tag: 'DBG',
3119
- level: 'INFO',
3120
- msg: ` getTerminalGeometry() safeRows: ${actualGeo.safeRows}`,
3121
- },
3122
- {
3123
- id: `dbg-fullscreen-18-${Date.now()}`,
3124
- ts: Date.now(),
3125
- tag: 'DBG',
3126
- level: 'INFO',
3127
- msg: ` Terminal mode: ${actualGeo.mode}`,
3128
- },
3129
- ];
3130
- // Add layout metadata if available
3131
- if (layoutResult.ok && layoutResult.metadata) {
3132
- const m = layoutResult.metadata;
3133
- events.push({
3134
- id: `dbg-fullscreen-19-${Date.now()}`,
3135
- ts: Date.now(),
3136
- tag: 'DBG',
3137
- level: 'INFO',
3138
- msg: ``,
3139
- }, {
3140
- id: `dbg-fullscreen-20-${Date.now()}`,
3141
- ts: Date.now(),
3142
- tag: 'DBG',
3143
- level: 'INFO',
3144
- msg: `B. LAYOUT METADATA (what layout is using):`,
3145
- }, {
3146
- id: `dbg-fullscreen-21-${Date.now()}`,
3147
- ts: Date.now(),
3148
- tag: 'DBG',
3149
- level: 'INFO',
3150
- msg: ` layout.colsUsed: ${m.colsUsed} (should match safeCols or be close)`,
3151
- }, {
3152
- id: `dbg-fullscreen-22-${Date.now()}`,
3153
- ts: Date.now(),
3154
- tag: 'DBG',
3155
- level: 'INFO',
3156
- msg: ` layout.rowsUsed: ${m.rowsUsed} (should match safeRows or be close)`,
3157
- }, {
3158
- id: `dbg-fullscreen-23-${Date.now()}`,
3159
- ts: Date.now(),
3160
- tag: 'DBG',
3161
- level: 'INFO',
3162
- msg: ` layout.availableWidth: ${m.availableWidth}`,
3163
- }, {
3164
- id: `dbg-fullscreen-24-${Date.now()}`,
3165
- ts: Date.now(),
3166
- tag: 'DBG',
3167
- level: 'INFO',
3168
- msg: ` layout.availableHeight: ${m.availableHeight}`,
3169
- }, {
3170
- id: `dbg-fullscreen-25-${Date.now()}`,
3171
- ts: Date.now(),
3172
- tag: 'DBG',
3173
- level: 'INFO',
3174
- msg: ` layout.gutters: ${m.gutters}`,
3175
- }, {
3176
- id: `dbg-fullscreen-26-${Date.now()}`,
3177
- ts: Date.now(),
3178
- tag: 'DBG',
3179
- level: 'INFO',
3180
- msg: ` layout.margins: ${m.margins} (browser=${actualGeo.mode === 'browser' ? 'yes' : 'no'})`,
3181
- }, {
3182
- id: `dbg-fullscreen-27-${Date.now()}`,
3183
- ts: Date.now(),
3184
- tag: 'DBG',
3185
- level: 'INFO',
3186
- msg: ` layout.minCols: ${m.minCols}`,
3187
- }, {
3188
- id: `dbg-fullscreen-28-${Date.now()}`,
3189
- ts: Date.now(),
3190
- tag: 'DBG',
3191
- level: 'INFO',
3192
- msg: ` layout.maxCols: ${m.maxCols ?? 'none (no max)'}`,
3193
- });
3194
- }
3195
- else {
3196
- events.push({
3197
- id: `dbg-fullscreen-19-${Date.now()}`,
3198
- ts: Date.now(),
3199
- tag: 'ERR',
3200
- level: 'ERROR',
3201
- msg: ``,
3202
- }, {
3203
- id: `dbg-fullscreen-20-${Date.now()}`,
3204
- ts: Date.now(),
3205
- tag: 'ERR',
3206
- level: 'ERROR',
3207
- msg: `B. LAYOUT ERROR: ${layoutResult.errorMessage || 'Layout computation failed'}`,
3208
- });
3209
- }
3210
- // Add diagnostic summary
3211
- events.push({
3212
- id: `dbg-fullscreen-summary-${Date.now()}`,
3213
- ts: Date.now(),
3214
- tag: 'DBG',
3215
- level: 'INFO',
3216
- msg: ``,
3217
- }, {
3218
- id: `dbg-fullscreen-summary2-${Date.now()}`,
3219
- ts: Date.now(),
3220
- tag: 'DBG',
3221
- level: 'INFO',
3222
- msg: `DIAGNOSTIC: If cols/rows DON'T change in fullscreen → Windows Terminal settings (font/padding).`,
3223
- }, {
3224
- id: `dbg-fullscreen-summary3-${Date.now()}`,
3225
- ts: Date.now(),
3226
- tag: 'DBG',
3227
- level: 'INFO',
3228
- msg: `If cols/rows DO change but colsUsed stays small → layout clamping bug (check code).`,
3229
- });
3230
- events.push({
3231
- id: `dbg-fullscreen-end-${Date.now()}`,
3232
- ts: Date.now(),
3233
- tag: 'DBG',
3234
- level: 'INFO',
3235
- msg: `=== END FULLSCREEN DIAGNOSTIC ===`,
3236
- });
3237
- return { events };
3238
- }
3239
- else if (subcommand === 'listeners') {
3240
- // Step 2B: Listener bindings dump
3241
- debugUtils.dumpListenerBindings();
3242
- return {
3243
- events: [cmdEvent, {
3244
- id: `dbg-${Date.now()}`,
3245
- ts: Date.now(),
3246
- tag: 'DBG',
3247
- level: 'INFO',
3248
- msg: 'Listener bindings dumped to Operations (check above)',
3249
- }],
3250
- };
3251
- }
3252
- else if (subcommand === 'stdout') {
3253
- // Step 3B: Blocked writes dump
3254
- debugUtils.dumpBlockedWrites();
3255
- return {
3256
- events: [cmdEvent, {
3257
- id: `dbg-${Date.now()}`,
3258
- ts: Date.now(),
3259
- tag: 'DBG',
3260
- level: 'INFO',
3261
- msg: 'Blocked stdout/stderr writes dumped to Operations (check above)',
3262
- }],
3263
- };
3264
- }
3265
- else {
3266
- return {
3267
- events: [cmdEvent, {
3268
- id: `err-${Date.now()}`,
3269
- ts: Date.now(),
3270
- tag: 'ERR',
3271
- level: 'ERROR',
3272
- msg: `Unknown debug subcommand: ${subcommand} (try: ui, geo, resize, resize-test, resize-torture, resize-trace, layout, tree, dump-layout, fullscreen, size, listeners, stdout)`,
3273
- }],
3274
- };
3275
- }
3276
- }
3277
- catch (error) {
3278
- return {
3279
- events: [cmdEvent, {
3280
- id: `err-${Date.now()}`,
3281
- ts: Date.now(),
3282
- tag: 'ERR',
3283
- level: 'ERROR',
3284
- msg: `Debug command failed: ${error.message || 'Unknown error'}`,
3285
- }],
3286
- };
3287
- }
3288
- }
3289
- //# sourceMappingURL=commandEngine.js.map