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.
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/tui_mk1/kernel.d.ts.map +1 -1
- package/dist/tui_mk1/kernel.js +107 -4
- package/dist/tui_mk1/kernel.js.map +1 -1
- package/dist/tui_mk1/layout/layoutEngine.d.ts +38 -19
- package/dist/tui_mk1/layout/layoutEngine.d.ts.map +1 -1
- package/dist/tui_mk1/layout/layoutEngine.js +521 -228
- package/dist/tui_mk1/layout/layoutEngine.js.map +1 -1
- package/dist/tui_mk1/log.d.ts +23 -0
- package/dist/tui_mk1/log.d.ts.map +1 -0
- package/dist/tui_mk1/log.js +125 -0
- package/dist/tui_mk1/log.js.map +1 -0
- package/dist/tui_mk1/logger.d.ts.map +1 -1
- package/dist/tui_mk1/logger.js +20 -10
- package/dist/tui_mk1/logger.js.map +1 -1
- package/dist/tui_mk1/mk1App.d.ts +13 -18
- package/dist/tui_mk1/mk1App.d.ts.map +1 -1
- package/dist/tui_mk1/mk1App.js +334 -157
- package/dist/tui_mk1/mk1App.js.map +1 -1
- package/dist/tui_mk1/resizeController.d.ts.map +1 -1
- package/dist/tui_mk1/resizeController.js +15 -1
- package/dist/tui_mk1/resizeController.js.map +1 -1
- package/dist/tui_mk1/stdoutGuard.d.ts.map +1 -1
- package/dist/tui_mk1/stdoutGuard.js +7 -0
- package/dist/tui_mk1/stdoutGuard.js.map +1 -1
- package/dist/tui_mk1/terminalRestore.d.ts.map +1 -1
- package/dist/tui_mk1/terminalRestore.js +19 -1
- package/dist/tui_mk1/terminalRestore.js.map +1 -1
- package/dist/tui_mk1/ui/offenderScanner.d.ts +31 -0
- package/dist/tui_mk1/ui/offenderScanner.d.ts.map +1 -0
- package/dist/tui_mk1/ui/offenderScanner.js +80 -0
- package/dist/tui_mk1/ui/offenderScanner.js.map +1 -0
- package/dist/tui_mk1/ui/safe.d.ts +9 -0
- package/dist/tui_mk1/ui/safe.d.ts.map +1 -0
- package/dist/tui_mk1/ui/safe.js +29 -0
- package/dist/tui_mk1/ui/safe.js.map +1 -0
- package/dist/tui_mk1/ui/safeText.d.ts +22 -0
- package/dist/tui_mk1/ui/safeText.d.ts.map +1 -0
- package/dist/tui_mk1/ui/safeText.js +50 -0
- package/dist/tui_mk1/ui/safeText.js.map +1 -0
- package/dist/tui_mk1/ui/uiBuilder.d.ts +44 -0
- package/dist/tui_mk1/ui/uiBuilder.d.ts.map +1 -0
- package/dist/tui_mk1/ui/uiBuilder.js +467 -0
- package/dist/tui_mk1/ui/uiBuilder.js.map +1 -0
- package/dist/tui_mk1/viewport/safeViewport.d.ts +10 -1
- package/dist/tui_mk1/viewport/safeViewport.d.ts.map +1 -1
- package/dist/tui_mk1/viewport/safeViewport.js +47 -15
- package/dist/tui_mk1/viewport/safeViewport.js.map +1 -1
- package/dist/tui_mk2/kernel.d.ts +28 -0
- package/dist/tui_mk2/kernel.d.ts.map +1 -0
- package/dist/tui_mk2/kernel.js +86 -0
- package/dist/tui_mk2/kernel.js.map +1 -0
- package/dist/tui_mk2/mk2App.d.ts +33 -0
- package/dist/tui_mk2/mk2App.d.ts.map +1 -0
- package/dist/tui_mk2/mk2App.js +93 -0
- package/dist/tui_mk2/mk2App.js.map +1 -0
- package/package.json +8 -7
- package/dist/tui_mk1/ui/panels/createSection.d.ts +0 -18
- package/dist/tui_mk1/ui/panels/createSection.d.ts.map +0 -1
- package/dist/tui_mk1/ui/panels/createSection.js +0 -42
- package/dist/tui_mk1/ui/panels/createSection.js.map +0 -1
- package/dist/tui_mk1/ui/panels.d.ts +0 -23
- package/dist/tui_mk1/ui/panels.d.ts.map +0 -1
- package/dist/tui_mk1/ui/panels.js +0 -108
- package/dist/tui_mk1/ui/panels.js.map +0 -1
- package/dist/tui_mk1/ui/render/sectionRenderer.d.ts +0 -21
- package/dist/tui_mk1/ui/render/sectionRenderer.d.ts.map +0 -1
- package/dist/tui_mk1/ui/render/sectionRenderer.js +0 -32
- package/dist/tui_mk1/ui/render/sectionRenderer.js.map +0 -1
- package/dist/tui_mk1/ui/widgetManager.d.ts +0 -58
- package/dist/tui_mk1/ui/widgetManager.d.ts.map +0 -1
- package/dist/tui_mk1/ui/widgetManager.js +0 -197
- package/dist/tui_mk1/ui/widgetManager.js.map +0 -1
- package/dist/ui/boot/sequence.d.ts +0 -10
- package/dist/ui/boot/sequence.d.ts.map +0 -1
- package/dist/ui/boot/sequence.js +0 -171
- package/dist/ui/boot/sequence.js.map +0 -1
- package/dist/ui/constraints/layoutSpec.d.ts +0 -47
- package/dist/ui/constraints/layoutSpec.d.ts.map +0 -1
- package/dist/ui/constraints/layoutSpec.js +0 -60
- package/dist/ui/constraints/layoutSpec.js.map +0 -1
- package/dist/ui/constraints/unknownHandling.d.ts +0 -29
- package/dist/ui/constraints/unknownHandling.d.ts.map +0 -1
- package/dist/ui/constraints/unknownHandling.js +0 -60
- package/dist/ui/constraints/unknownHandling.js.map +0 -1
- package/dist/ui/drilldowns/feed.d.ts +0 -11
- package/dist/ui/drilldowns/feed.d.ts.map +0 -1
- package/dist/ui/drilldowns/feed.js +0 -68
- package/dist/ui/drilldowns/feed.js.map +0 -1
- package/dist/ui/drilldowns/index.d.ts +0 -7
- package/dist/ui/drilldowns/index.d.ts.map +0 -1
- package/dist/ui/drilldowns/index.js +0 -8
- package/dist/ui/drilldowns/index.js.map +0 -1
- package/dist/ui/drilldowns/posture.d.ts +0 -11
- package/dist/ui/drilldowns/posture.d.ts.map +0 -1
- package/dist/ui/drilldowns/posture.js +0 -74
- package/dist/ui/drilldowns/posture.js.map +0 -1
- package/dist/ui/intelligence-posture-view.d.ts +0 -22
- package/dist/ui/intelligence-posture-view.d.ts.map +0 -1
- package/dist/ui/intelligence-posture-view.js +0 -169
- package/dist/ui/intelligence-posture-view.js.map +0 -1
- package/dist/ui/navigation/keymaps.d.ts +0 -26
- package/dist/ui/navigation/keymaps.d.ts.map +0 -1
- package/dist/ui/navigation/keymaps.js +0 -135
- package/dist/ui/navigation/keymaps.js.map +0 -1
- package/dist/ui/navigation/palette.d.ts +0 -10
- package/dist/ui/navigation/palette.d.ts.map +0 -1
- package/dist/ui/navigation/palette.js +0 -133
- package/dist/ui/navigation/palette.js.map +0 -1
- package/dist/ui/navigation/state.d.ts +0 -47
- package/dist/ui/navigation/state.d.ts.map +0 -1
- package/dist/ui/navigation/state.js +0 -84
- package/dist/ui/navigation/state.js.map +0 -1
- package/dist/ui/navigation/types.d.ts +0 -38
- package/dist/ui/navigation/types.d.ts.map +0 -1
- package/dist/ui/navigation/types.js +0 -36
- package/dist/ui/navigation/types.js.map +0 -1
- package/dist/ui/panels/active-assets.d.ts +0 -12
- package/dist/ui/panels/active-assets.d.ts.map +0 -1
- package/dist/ui/panels/active-assets.js +0 -83
- package/dist/ui/panels/active-assets.js.map +0 -1
- package/dist/ui/panels/capability-flags.d.ts +0 -12
- package/dist/ui/panels/capability-flags.d.ts.map +0 -1
- package/dist/ui/panels/capability-flags.js +0 -59
- package/dist/ui/panels/capability-flags.js.map +0 -1
- package/dist/ui/panels/command-surface.d.ts +0 -12
- package/dist/ui/panels/command-surface.d.ts.map +0 -1
- package/dist/ui/panels/command-surface.js +0 -55
- package/dist/ui/panels/command-surface.js.map +0 -1
- package/dist/ui/panels/network-origin.d.ts +0 -12
- package/dist/ui/panels/network-origin.d.ts.map +0 -1
- package/dist/ui/panels/network-origin.js +0 -79
- package/dist/ui/panels/network-origin.js.map +0 -1
- package/dist/ui/panels/operations-feed.d.ts +0 -12
- package/dist/ui/panels/operations-feed.d.ts.map +0 -1
- package/dist/ui/panels/operations-feed.js +0 -90
- package/dist/ui/panels/operations-feed.js.map +0 -1
- package/dist/ui/panels/posture.d.ts +0 -12
- package/dist/ui/panels/posture.d.ts.map +0 -1
- package/dist/ui/panels/posture.js +0 -84
- package/dist/ui/panels/posture.js.map +0 -1
- package/dist/ui/panels/resources.d.ts +0 -11
- package/dist/ui/panels/resources.d.ts.map +0 -1
- package/dist/ui/panels/resources.js +0 -88
- package/dist/ui/panels/resources.js.map +0 -1
- package/dist/ui/primitives/Panel.d.ts +0 -25
- package/dist/ui/primitives/Panel.d.ts.map +0 -1
- package/dist/ui/primitives/Panel.js +0 -59
- package/dist/ui/primitives/Panel.js.map +0 -1
- package/dist/ui/rendering/metricRenderer.d.ts +0 -24
- package/dist/ui/rendering/metricRenderer.d.ts.map +0 -1
- package/dist/ui/rendering/metricRenderer.js +0 -86
- package/dist/ui/rendering/metricRenderer.js.map +0 -1
- package/dist/ui/runtime/hub.d.ts +0 -12
- package/dist/ui/runtime/hub.d.ts.map +0 -1
- package/dist/ui/runtime/hub.js +0 -486
- package/dist/ui/runtime/hub.js.map +0 -1
- package/dist/ui/runtime/hubValidation.d.ts +0 -23
- package/dist/ui/runtime/hubValidation.d.ts.map +0 -1
- package/dist/ui/runtime/hubValidation.js +0 -90
- package/dist/ui/runtime/hubValidation.js.map +0 -1
- package/dist/ui/runtime/index.d.ts +0 -29
- package/dist/ui/runtime/index.d.ts.map +0 -1
- package/dist/ui/runtime/index.js +0 -297
- package/dist/ui/runtime/index.js.map +0 -1
- package/dist/ui/runtime/no-tui.d.ts +0 -12
- package/dist/ui/runtime/no-tui.d.ts.map +0 -1
- package/dist/ui/runtime/no-tui.js +0 -77
- package/dist/ui/runtime/no-tui.js.map +0 -1
- package/dist/ui/runtime/state-builder.d.ts +0 -13
- package/dist/ui/runtime/state-builder.d.ts.map +0 -1
- package/dist/ui/runtime/state-builder.js +0 -114
- package/dist/ui/runtime/state-builder.js.map +0 -1
- package/dist/ui/runtime/terminalSizeCheck.d.ts +0 -10
- package/dist/ui/runtime/terminalSizeCheck.d.ts.map +0 -1
- package/dist/ui/runtime/terminalSizeCheck.js +0 -51
- package/dist/ui/runtime/terminalSizeCheck.js.map +0 -1
- package/dist/ui/runtime/tuiLogGate.d.ts +0 -22
- package/dist/ui/runtime/tuiLogGate.d.ts.map +0 -1
- package/dist/ui/runtime/tuiLogGate.js +0 -68
- package/dist/ui/runtime/tuiLogGate.js.map +0 -1
- package/dist/ui/state/types.d.ts +0 -72
- package/dist/ui/state/types.d.ts.map +0 -1
- package/dist/ui/state/types.js +0 -6
- package/dist/ui/state/types.js.map +0 -1
- package/dist/ui/theme/borders.d.ts +0 -20
- package/dist/ui/theme/borders.d.ts.map +0 -1
- package/dist/ui/theme/borders.js +0 -55
- package/dist/ui/theme/borders.js.map +0 -1
- package/dist/ui/theme/tokens.d.ts +0 -28
- package/dist/ui/theme/tokens.d.ts.map +0 -1
- package/dist/ui/theme/tokens.js +0 -50
- package/dist/ui/theme/tokens.js.map +0 -1
- package/dist/ui/theme/typography.d.ts +0 -14
- package/dist/ui/theme/typography.d.ts.map +0 -1
- package/dist/ui/theme/typography.js +0 -30
- package/dist/ui/theme/typography.js.map +0 -1
- package/dist/ui/v3/collectors/assets.collector.d.ts +0 -20
- package/dist/ui/v3/collectors/assets.collector.d.ts.map +0 -1
- package/dist/ui/v3/collectors/assets.collector.js +0 -80
- package/dist/ui/v3/collectors/assets.collector.js.map +0 -1
- package/dist/ui/v3/collectors/capabilities.collector.d.ts +0 -18
- package/dist/ui/v3/collectors/capabilities.collector.d.ts.map +0 -1
- package/dist/ui/v3/collectors/capabilities.collector.js +0 -113
- package/dist/ui/v3/collectors/capabilities.collector.js.map +0 -1
- package/dist/ui/v3/collectors/network.collector.d.ts +0 -18
- package/dist/ui/v3/collectors/network.collector.d.ts.map +0 -1
- package/dist/ui/v3/collectors/network.collector.js +0 -37
- package/dist/ui/v3/collectors/network.collector.js.map +0 -1
- package/dist/ui/v3/collectors/posture.derive.d.ts +0 -24
- package/dist/ui/v3/collectors/posture.derive.d.ts.map +0 -1
- package/dist/ui/v3/collectors/posture.derive.js +0 -57
- package/dist/ui/v3/collectors/posture.derive.js.map +0 -1
- package/dist/ui/v3/collectors/resources.d.ts +0 -23
- package/dist/ui/v3/collectors/resources.d.ts.map +0 -1
- package/dist/ui/v3/collectors/resources.js +0 -136
- package/dist/ui/v3/collectors/resources.js.map +0 -1
- package/dist/ui/v3/commands/commandEngine.d.ts +0 -77
- package/dist/ui/v3/commands/commandEngine.d.ts.map +0 -1
- package/dist/ui/v3/commands/commandEngine.js +0 -3289
- package/dist/ui/v3/commands/commandEngine.js.map +0 -1
- package/dist/ui/v3/commands/commandResult.d.ts +0 -25
- package/dist/ui/v3/commands/commandResult.d.ts.map +0 -1
- package/dist/ui/v3/commands/commandResult.js +0 -19
- package/dist/ui/v3/commands/commandResult.js.map +0 -1
- package/dist/ui/v3/commands/diagnose.d.ts +0 -17
- package/dist/ui/v3/commands/diagnose.d.ts.map +0 -1
- package/dist/ui/v3/commands/diagnose.js +0 -62
- package/dist/ui/v3/commands/diagnose.js.map +0 -1
- package/dist/ui/v3/commands/errorClassifier.d.ts +0 -23
- package/dist/ui/v3/commands/errorClassifier.d.ts.map +0 -1
- package/dist/ui/v3/commands/errorClassifier.js +0 -63
- package/dist/ui/v3/commands/errorClassifier.js.map +0 -1
- package/dist/ui/v3/commands/parser.d.ts +0 -14
- package/dist/ui/v3/commands/parser.d.ts.map +0 -1
- package/dist/ui/v3/commands/parser.js +0 -29
- package/dist/ui/v3/commands/parser.js.map +0 -1
- package/dist/ui/v3/commands/router.d.ts +0 -13
- package/dist/ui/v3/commands/router.d.ts.map +0 -1
- package/dist/ui/v3/commands/router.js +0 -150
- package/dist/ui/v3/commands/router.js.map +0 -1
- package/dist/ui/v3/config/gateway.d.ts +0 -40
- package/dist/ui/v3/config/gateway.d.ts.map +0 -1
- package/dist/ui/v3/config/gateway.js +0 -113
- package/dist/ui/v3/config/gateway.js.map +0 -1
- package/dist/ui/v3/core/event.d.ts +0 -19
- package/dist/ui/v3/core/event.d.ts.map +0 -1
- package/dist/ui/v3/core/event.js +0 -7
- package/dist/ui/v3/core/event.js.map +0 -1
- package/dist/ui/v3/core/eventBus.d.ts +0 -39
- package/dist/ui/v3/core/eventBus.d.ts.map +0 -1
- package/dist/ui/v3/core/eventBus.js +0 -79
- package/dist/ui/v3/core/eventBus.js.map +0 -1
- package/dist/ui/v3/core/feedStore.d.ts +0 -34
- package/dist/ui/v3/core/feedStore.d.ts.map +0 -1
- package/dist/ui/v3/core/feedStore.js +0 -46
- package/dist/ui/v3/core/feedStore.js.map +0 -1
- package/dist/ui/v3/core/logger.d.ts +0 -40
- package/dist/ui/v3/core/logger.d.ts.map +0 -1
- package/dist/ui/v3/core/logger.js +0 -191
- package/dist/ui/v3/core/logger.js.map +0 -1
- package/dist/ui/v3/core/opEvent.d.ts +0 -15
- package/dist/ui/v3/core/opEvent.d.ts.map +0 -1
- package/dist/ui/v3/core/opEvent.js +0 -7
- package/dist/ui/v3/core/opEvent.js.map +0 -1
- package/dist/ui/v3/index.d.ts +0 -8
- package/dist/ui/v3/index.d.ts.map +0 -1
- package/dist/ui/v3/index.js +0 -51
- package/dist/ui/v3/index.js.map +0 -1
- package/dist/ui/v3/runtime/moduleConfig.d.ts +0 -21
- package/dist/ui/v3/runtime/moduleConfig.d.ts.map +0 -1
- package/dist/ui/v3/runtime/moduleConfig.js +0 -41
- package/dist/ui/v3/runtime/moduleConfig.js.map +0 -1
- package/dist/ui/v3/section0/index.d.ts +0 -22
- package/dist/ui/v3/section0/index.d.ts.map +0 -1
- package/dist/ui/v3/section0/index.js +0 -88
- package/dist/ui/v3/section0/index.js.map +0 -1
- package/dist/ui/v3/section0/runtime/createScreen.d.ts +0 -27
- package/dist/ui/v3/section0/runtime/createScreen.d.ts.map +0 -1
- package/dist/ui/v3/section0/runtime/createScreen.js +0 -55
- package/dist/ui/v3/section0/runtime/createScreen.js.map +0 -1
- package/dist/ui/v3/section0/runtime/lifecycle.d.ts +0 -53
- package/dist/ui/v3/section0/runtime/lifecycle.d.ts.map +0 -1
- package/dist/ui/v3/section0/runtime/lifecycle.js +0 -172
- package/dist/ui/v3/section0/runtime/lifecycle.js.map +0 -1
- package/dist/ui/v3/section1/index.d.ts +0 -19
- package/dist/ui/v3/section1/index.d.ts.map +0 -1
- package/dist/ui/v3/section1/index.js +0 -413
- package/dist/ui/v3/section1/index.js.map +0 -1
- package/dist/ui/v3/section1/runtime/commandLine.d.ts +0 -49
- package/dist/ui/v3/section1/runtime/commandLine.d.ts.map +0 -1
- package/dist/ui/v3/section1/runtime/commandLine.js +0 -183
- package/dist/ui/v3/section1/runtime/commandLine.js.map +0 -1
- package/dist/ui/v3/section1/runtime/focusLock.d.ts +0 -24
- package/dist/ui/v3/section1/runtime/focusLock.d.ts.map +0 -1
- package/dist/ui/v3/section1/runtime/focusLock.js +0 -44
- package/dist/ui/v3/section1/runtime/focusLock.js.map +0 -1
- package/dist/ui/v3/state/assertUiState.d.ts +0 -27
- package/dist/ui/v3/state/assertUiState.d.ts.map +0 -1
- package/dist/ui/v3/state/assertUiState.js +0 -89
- package/dist/ui/v3/state/assertUiState.js.map +0 -1
- package/dist/ui/v3/state/capabilitiesStore.d.ts +0 -54
- package/dist/ui/v3/state/capabilitiesStore.d.ts.map +0 -1
- package/dist/ui/v3/state/capabilitiesStore.js +0 -76
- package/dist/ui/v3/state/capabilitiesStore.js.map +0 -1
- package/dist/ui/v3/state/defaultState.d.ts +0 -19
- package/dist/ui/v3/state/defaultState.d.ts.map +0 -1
- package/dist/ui/v3/state/defaultState.js +0 -28
- package/dist/ui/v3/state/defaultState.js.map +0 -1
- package/dist/ui/v3/state/gatewayConnectionStore.d.ts +0 -72
- package/dist/ui/v3/state/gatewayConnectionStore.d.ts.map +0 -1
- package/dist/ui/v3/state/gatewayConnectionStore.js +0 -108
- package/dist/ui/v3/state/gatewayConnectionStore.js.map +0 -1
- package/dist/ui/v3/state/initializePostureState.d.ts +0 -23
- package/dist/ui/v3/state/initializePostureState.d.ts.map +0 -1
- package/dist/ui/v3/state/initializePostureState.js +0 -41
- package/dist/ui/v3/state/initializePostureState.js.map +0 -1
- package/dist/ui/v3/state/panelStore.d.ts +0 -80
- package/dist/ui/v3/state/panelStore.d.ts.map +0 -1
- package/dist/ui/v3/state/panelStore.js +0 -131
- package/dist/ui/v3/state/panelStore.js.map +0 -1
- package/dist/ui/v3/state/resourcesData.d.ts +0 -15
- package/dist/ui/v3/state/resourcesData.d.ts.map +0 -1
- package/dist/ui/v3/state/resourcesData.js +0 -7
- package/dist/ui/v3/state/resourcesData.js.map +0 -1
- package/dist/ui/v3/state/uiState.d.ts +0 -22
- package/dist/ui/v3/state/uiState.d.ts.map +0 -1
- package/dist/ui/v3/state/uiState.js +0 -13
- package/dist/ui/v3/state/uiState.js.map +0 -1
- package/dist/ui/v3/state/uiStateBuilder.d.ts +0 -32
- package/dist/ui/v3/state/uiStateBuilder.d.ts.map +0 -1
- package/dist/ui/v3/state/uiStateBuilder.js +0 -73
- package/dist/ui/v3/state/uiStateBuilder.js.map +0 -1
- package/dist/ui/v3/state/uiStateTypes.d.ts +0 -59
- package/dist/ui/v3/state/uiStateTypes.d.ts.map +0 -1
- package/dist/ui/v3/state/uiStateTypes.js +0 -8
- package/dist/ui/v3/state/uiStateTypes.js.map +0 -1
- package/dist/ui/v3/state/value.d.ts +0 -80
- package/dist/ui/v3/state/value.d.ts.map +0 -1
- package/dist/ui/v3/state/value.js +0 -96
- package/dist/ui/v3/state/value.js.map +0 -1
- package/dist/ui/v3/tui/geometry.d.ts +0 -83
- package/dist/ui/v3/tui/geometry.d.ts.map +0 -1
- package/dist/ui/v3/tui/geometry.js +0 -201
- package/dist/ui/v3/tui/geometry.js.map +0 -1
- package/dist/ui/v3/tui/startTui.d.ts +0 -37
- package/dist/ui/v3/tui/startTui.d.ts.map +0 -1
- package/dist/ui/v3/tui/startTui.js +0 -61
- package/dist/ui/v3/tui/startTui.js.map +0 -1
- package/dist/ui/v3/tui/terminalMode.d.ts +0 -31
- package/dist/ui/v3/tui/terminalMode.d.ts.map +0 -1
- package/dist/ui/v3/tui/terminalMode.js +0 -76
- package/dist/ui/v3/tui/terminalMode.js.map +0 -1
- package/dist/ui/v3/ui/debugUtils.d.ts +0 -67
- package/dist/ui/v3/ui/debugUtils.d.ts.map +0 -1
- package/dist/ui/v3/ui/debugUtils.js +0 -238
- package/dist/ui/v3/ui/debugUtils.js.map +0 -1
- package/dist/ui/v3/ui/focus.d.ts +0 -28
- package/dist/ui/v3/ui/focus.d.ts.map +0 -1
- package/dist/ui/v3/ui/focus.js +0 -38
- package/dist/ui/v3/ui/focus.js.map +0 -1
- package/dist/ui/v3/ui/layout/hubLayout.d.ts +0 -43
- package/dist/ui/v3/ui/layout/hubLayout.d.ts.map +0 -1
- package/dist/ui/v3/ui/layout/hubLayout.js +0 -170
- package/dist/ui/v3/ui/layout/hubLayout.js.map +0 -1
- package/dist/ui/v3/ui/layout/phase1Layout.d.ts +0 -63
- package/dist/ui/v3/ui/layout/phase1Layout.d.ts.map +0 -1
- package/dist/ui/v3/ui/layout/phase1Layout.js +0 -274
- package/dist/ui/v3/ui/layout/phase1Layout.js.map +0 -1
- package/dist/ui/v3/ui/layout/phase1Layout.test.d.ts +0 -5
- package/dist/ui/v3/ui/layout/phase1Layout.test.d.ts.map +0 -1
- package/dist/ui/v3/ui/layout/phase1Layout.test.js +0 -120
- package/dist/ui/v3/ui/layout/phase1Layout.test.js.map +0 -1
- package/dist/ui/v3/ui/minimalRuntime.d.ts +0 -14
- package/dist/ui/v3/ui/minimalRuntime.d.ts.map +0 -1
- package/dist/ui/v3/ui/minimalRuntime.js +0 -111
- package/dist/ui/v3/ui/minimalRuntime.js.map +0 -1
- package/dist/ui/v3/ui/panels/AssetsPanel.d.ts +0 -17
- package/dist/ui/v3/ui/panels/AssetsPanel.d.ts.map +0 -1
- package/dist/ui/v3/ui/panels/AssetsPanel.js +0 -53
- package/dist/ui/v3/ui/panels/AssetsPanel.js.map +0 -1
- package/dist/ui/v3/ui/panels/CapabilitiesPanel.d.ts +0 -20
- package/dist/ui/v3/ui/panels/CapabilitiesPanel.d.ts.map +0 -1
- package/dist/ui/v3/ui/panels/CapabilitiesPanel.js +0 -67
- package/dist/ui/v3/ui/panels/CapabilitiesPanel.js.map +0 -1
- package/dist/ui/v3/ui/panels/NetworkPanel.d.ts +0 -31
- package/dist/ui/v3/ui/panels/NetworkPanel.d.ts.map +0 -1
- package/dist/ui/v3/ui/panels/NetworkPanel.js +0 -153
- package/dist/ui/v3/ui/panels/NetworkPanel.js.map +0 -1
- package/dist/ui/v3/ui/panels/PosturePanel.d.ts +0 -16
- package/dist/ui/v3/ui/panels/PosturePanel.d.ts.map +0 -1
- package/dist/ui/v3/ui/panels/PosturePanel.js +0 -60
- package/dist/ui/v3/ui/panels/PosturePanel.js.map +0 -1
- package/dist/ui/v3/ui/panels/ResourcesPanel.d.ts +0 -20
- package/dist/ui/v3/ui/panels/ResourcesPanel.d.ts.map +0 -1
- package/dist/ui/v3/ui/panels/ResourcesPanel.js +0 -66
- package/dist/ui/v3/ui/panels/ResourcesPanel.js.map +0 -1
- package/dist/ui/v3/ui/phase1Runtime.d.ts +0 -29
- package/dist/ui/v3/ui/phase1Runtime.d.ts.map +0 -1
- package/dist/ui/v3/ui/phase1Runtime.js +0 -1648
- package/dist/ui/v3/ui/phase1Runtime.js.map +0 -1
- package/dist/ui/v3/ui/phase1RuntimeClean.d.ts +0 -34
- package/dist/ui/v3/ui/phase1RuntimeClean.d.ts.map +0 -1
- package/dist/ui/v3/ui/phase1RuntimeClean.js +0 -1841
- package/dist/ui/v3/ui/phase1RuntimeClean.js.map +0 -1
- package/dist/ui/v3/ui/primitives/Panel.d.ts +0 -39
- package/dist/ui/v3/ui/primitives/Panel.d.ts.map +0 -1
- package/dist/ui/v3/ui/primitives/Panel.js +0 -105
- package/dist/ui/v3/ui/primitives/Panel.js.map +0 -1
- package/dist/ui/v3/ui/theme.d.ts +0 -37
- package/dist/ui/v3/ui/theme.d.ts.map +0 -1
- package/dist/ui/v3/ui/theme.js +0 -40
- package/dist/ui/v3/ui/theme.js.map +0 -1
- package/dist/ui/v3/ui/uiRuntime.d.ts +0 -40
- package/dist/ui/v3/ui/uiRuntime.d.ts.map +0 -1
- package/dist/ui/v3/ui/uiRuntime.js +0 -60
- package/dist/ui/v3/ui/uiRuntime.js.map +0 -1
- package/dist/ui/v3/ui/widgets/CommandLine.d.ts +0 -26
- package/dist/ui/v3/ui/widgets/CommandLine.d.ts.map +0 -1
- package/dist/ui/v3/ui/widgets/CommandLine.js +0 -67
- package/dist/ui/v3/ui/widgets/CommandLine.js.map +0 -1
- package/dist/ui/v3/v1Adapters/agents.d.ts +0 -72
- package/dist/ui/v3/v1Adapters/agents.d.ts.map +0 -1
- package/dist/ui/v3/v1Adapters/agents.js +0 -182
- package/dist/ui/v3/v1Adapters/agents.js.map +0 -1
- package/dist/ui/v3/v1Adapters/config.d.ts +0 -67
- package/dist/ui/v3/v1Adapters/config.d.ts.map +0 -1
- package/dist/ui/v3/v1Adapters/config.js +0 -78
- package/dist/ui/v3/v1Adapters/config.js.map +0 -1
- package/dist/ui/v3/v1Adapters/connect.d.ts +0 -77
- package/dist/ui/v3/v1Adapters/connect.d.ts.map +0 -1
- package/dist/ui/v3/v1Adapters/connect.js +0 -576
- package/dist/ui/v3/v1Adapters/connect.js.map +0 -1
- package/dist/ui/v3/v1Adapters/httpDebug.d.ts +0 -19
- package/dist/ui/v3/v1Adapters/httpDebug.d.ts.map +0 -1
- package/dist/ui/v3/v1Adapters/httpDebug.js +0 -60
- package/dist/ui/v3/v1Adapters/httpDebug.js.map +0 -1
- package/dist/ui/v3/v1Adapters/runs.d.ts +0 -77
- package/dist/ui/v3/v1Adapters/runs.d.ts.map +0 -1
- package/dist/ui/v3/v1Adapters/runs.js +0 -339
- package/dist/ui/v3/v1Adapters/runs.js.map +0 -1
- package/dist/ui/v4/engine/renderFrame.d.ts +0 -47
- package/dist/ui/v4/engine/renderFrame.d.ts.map +0 -1
- package/dist/ui/v4/engine/renderFrame.js +0 -653
- package/dist/ui/v4/engine/renderFrame.js.map +0 -1
- package/dist/ui/v4/engine/resizeController.d.ts +0 -48
- package/dist/ui/v4/engine/resizeController.d.ts.map +0 -1
- package/dist/ui/v4/engine/resizeController.js +0 -285
- package/dist/ui/v4/engine/resizeController.js.map +0 -1
- package/dist/ui/v4/engine/safeViewport.d.ts +0 -47
- package/dist/ui/v4/engine/safeViewport.d.ts.map +0 -1
- package/dist/ui/v4/engine/safeViewport.js +0 -123
- package/dist/ui/v4/engine/safeViewport.js.map +0 -1
- package/dist/ui/v4/engine/terminalProfile.d.ts +0 -56
- package/dist/ui/v4/engine/terminalProfile.d.ts.map +0 -1
- package/dist/ui/v4/engine/terminalProfile.js +0 -115
- package/dist/ui/v4/engine/terminalProfile.js.map +0 -1
- package/dist/ui/v4/index.d.ts +0 -28
- package/dist/ui/v4/index.d.ts.map +0 -1
- package/dist/ui/v4/index.js +0 -993
- package/dist/ui/v4/index.js.map +0 -1
- package/dist/ui/v4/layout/layoutEngine.d.ts +0 -62
- package/dist/ui/v4/layout/layoutEngine.d.ts.map +0 -1
- package/dist/ui/v4/layout/layoutEngine.js +0 -294
- package/dist/ui/v4/layout/layoutEngine.js.map +0 -1
- package/dist/ui/v4/runtime/keepAlive.d.ts +0 -21
- package/dist/ui/v4/runtime/keepAlive.d.ts.map +0 -1
- package/dist/ui/v4/runtime/keepAlive.js +0 -149
- package/dist/ui/v4/runtime/keepAlive.js.map +0 -1
- package/dist/ui/v4/runtime/logger.d.ts +0 -35
- package/dist/ui/v4/runtime/logger.d.ts.map +0 -1
- package/dist/ui/v4/runtime/logger.js +0 -109
- package/dist/ui/v4/runtime/logger.js.map +0 -1
- package/dist/ui/v5/debug/assertNoOverflow.d.ts +0 -28
- package/dist/ui/v5/debug/assertNoOverflow.d.ts.map +0 -1
- package/dist/ui/v5/debug/assertNoOverflow.js +0 -63
- package/dist/ui/v5/debug/assertNoOverflow.js.map +0 -1
- package/dist/ui/v5/debug/debugCommands.d.ts +0 -20
- package/dist/ui/v5/debug/debugCommands.d.ts.map +0 -1
- package/dist/ui/v5/debug/debugCommands.js +0 -461
- package/dist/ui/v5/debug/debugCommands.js.map +0 -1
- package/dist/ui/v5/debugCommands.d.ts +0 -20
- package/dist/ui/v5/debugCommands.d.ts.map +0 -1
- package/dist/ui/v5/debugCommands.js +0 -81
- package/dist/ui/v5/debugCommands.js.map +0 -1
- package/dist/ui/v5/guardrails/stdoutGuard.d.ts +0 -23
- package/dist/ui/v5/guardrails/stdoutGuard.d.ts.map +0 -1
- package/dist/ui/v5/guardrails/stdoutGuard.js +0 -94
- package/dist/ui/v5/guardrails/stdoutGuard.js.map +0 -1
- package/dist/ui/v5/guardrails/terminalRestore.d.ts +0 -17
- package/dist/ui/v5/guardrails/terminalRestore.d.ts.map +0 -1
- package/dist/ui/v5/guardrails/terminalRestore.js +0 -47
- package/dist/ui/v5/guardrails/terminalRestore.js.map +0 -1
- package/dist/ui/v5/index.d.ts +0 -30
- package/dist/ui/v5/index.d.ts.map +0 -1
- package/dist/ui/v5/index.js +0 -243
- package/dist/ui/v5/index.js.map +0 -1
- package/dist/ui/v5/kernel/kernel.d.ts +0 -81
- package/dist/ui/v5/kernel/kernel.d.ts.map +0 -1
- package/dist/ui/v5/kernel/kernel.js +0 -339
- package/dist/ui/v5/kernel/kernel.js.map +0 -1
- package/dist/ui/v5/kernel.d.ts +0 -75
- package/dist/ui/v5/kernel.d.ts.map +0 -1
- package/dist/ui/v5/kernel.js +0 -289
- package/dist/ui/v5/kernel.js.map +0 -1
- package/dist/ui/v5/layout/clampRect.d.ts +0 -28
- package/dist/ui/v5/layout/clampRect.d.ts.map +0 -1
- package/dist/ui/v5/layout/clampRect.js +0 -45
- package/dist/ui/v5/layout/clampRect.js.map +0 -1
- package/dist/ui/v5/layout/layoutEngine.d.ts +0 -16
- package/dist/ui/v5/layout/layoutEngine.d.ts.map +0 -1
- package/dist/ui/v5/layout/layoutEngine.js +0 -99
- package/dist/ui/v5/layout/layoutEngine.js.map +0 -1
- package/dist/ui/v5/renderGate.d.ts +0 -19
- package/dist/ui/v5/renderGate.d.ts.map +0 -1
- package/dist/ui/v5/renderGate.js +0 -36
- package/dist/ui/v5/renderGate.js.map +0 -1
- package/dist/ui/v5/resize/resizeController.d.ts +0 -62
- package/dist/ui/v5/resize/resizeController.d.ts.map +0 -1
- package/dist/ui/v5/resize/resizeController.js +0 -141
- package/dist/ui/v5/resize/resizeController.js.map +0 -1
- package/dist/ui/v5/resizeController.d.ts +0 -55
- package/dist/ui/v5/resizeController.d.ts.map +0 -1
- package/dist/ui/v5/resizeController.js +0 -124
- package/dist/ui/v5/resizeController.js.map +0 -1
- package/dist/ui/v5/runtime/keepAlive.d.ts +0 -37
- package/dist/ui/v5/runtime/keepAlive.d.ts.map +0 -1
- package/dist/ui/v5/runtime/keepAlive.js +0 -122
- package/dist/ui/v5/runtime/keepAlive.js.map +0 -1
- package/dist/ui/v5/runtime/restoreTerminal.d.ts +0 -34
- package/dist/ui/v5/runtime/restoreTerminal.d.ts.map +0 -1
- package/dist/ui/v5/runtime/restoreTerminal.js +0 -100
- package/dist/ui/v5/runtime/restoreTerminal.js.map +0 -1
- package/dist/ui/v5/runtime/stdoutGuard.d.ts +0 -42
- package/dist/ui/v5/runtime/stdoutGuard.d.ts.map +0 -1
- package/dist/ui/v5/runtime/stdoutGuard.js +0 -156
- package/dist/ui/v5/runtime/stdoutGuard.js.map +0 -1
- package/dist/ui/v5/viewport/getViewport.d.ts +0 -23
- package/dist/ui/v5/viewport/getViewport.d.ts.map +0 -1
- package/dist/ui/v5/viewport/getViewport.js +0 -117
- package/dist/ui/v5/viewport/getViewport.js.map +0 -1
- package/dist/ui/v5/viewport.d.ts +0 -41
- package/dist/ui/v5/viewport.d.ts.map +0 -1
- package/dist/ui/v5/viewport.js +0 -90
- package/dist/ui/v5/viewport.js.map +0 -1
- package/dist/ui/widgets/flagRow.d.ts +0 -25
- package/dist/ui/widgets/flagRow.d.ts.map +0 -1
- package/dist/ui/widgets/flagRow.js +0 -57
- package/dist/ui/widgets/flagRow.js.map +0 -1
- package/dist/ui/widgets/index.d.ts +0 -9
- package/dist/ui/widgets/index.d.ts.map +0 -1
- package/dist/ui/widgets/index.js +0 -9
- package/dist/ui/widgets/index.js.map +0 -1
- package/dist/ui/widgets/meter.d.ts +0 -18
- package/dist/ui/widgets/meter.d.ts.map +0 -1
- package/dist/ui/widgets/meter.js +0 -38
- package/dist/ui/widgets/meter.js.map +0 -1
- package/dist/ui/widgets/miniMap.d.ts +0 -26
- package/dist/ui/widgets/miniMap.d.ts.map +0 -1
- package/dist/ui/widgets/miniMap.js +0 -94
- package/dist/ui/widgets/miniMap.js.map +0 -1
- package/dist/ui/widgets/sparkline.d.ts +0 -17
- package/dist/ui/widgets/sparkline.d.ts.map +0 -1
- package/dist/ui/widgets/sparkline.js +0 -65
- 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
|