4runr-os 1.0.23 → 1.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/dist/collectors/collector_assets.d.ts +19 -0
  2. package/dist/collectors/collector_assets.d.ts.map +1 -0
  3. package/dist/collectors/collector_assets.js +72 -0
  4. package/dist/collectors/collector_assets.js.map +1 -0
  5. package/dist/collectors/collector_capabilities.d.ts +19 -0
  6. package/dist/collectors/collector_capabilities.d.ts.map +1 -0
  7. package/dist/collectors/collector_capabilities.js +61 -0
  8. package/dist/collectors/collector_capabilities.js.map +1 -0
  9. package/dist/collectors/collector_feed.d.ts +30 -0
  10. package/dist/collectors/collector_feed.d.ts.map +1 -0
  11. package/dist/collectors/collector_feed.js +78 -0
  12. package/dist/collectors/collector_feed.js.map +1 -0
  13. package/dist/collectors/collector_geo.d.ts +12 -0
  14. package/dist/collectors/collector_geo.d.ts.map +1 -0
  15. package/dist/collectors/collector_geo.js +248 -0
  16. package/dist/collectors/collector_geo.js.map +1 -0
  17. package/dist/collectors/collector_network.d.ts +22 -0
  18. package/dist/collectors/collector_network.d.ts.map +1 -0
  19. package/dist/collectors/collector_network.js +83 -0
  20. package/dist/collectors/collector_network.js.map +1 -0
  21. package/dist/collectors/collector_posture.d.ts +25 -0
  22. package/dist/collectors/collector_posture.d.ts.map +1 -0
  23. package/dist/collectors/collector_posture.js +207 -0
  24. package/dist/collectors/collector_posture.js.map +1 -0
  25. package/dist/collectors/collector_resources.d.ts +21 -0
  26. package/dist/collectors/collector_resources.d.ts.map +1 -0
  27. package/dist/collectors/collector_resources.js +87 -0
  28. package/dist/collectors/collector_resources.js.map +1 -0
  29. package/dist/collectors/helpers.d.ts +21 -0
  30. package/dist/collectors/helpers.d.ts.map +1 -0
  31. package/dist/collectors/helpers.js +49 -0
  32. package/dist/collectors/helpers.js.map +1 -0
  33. package/dist/core/collectorRegistry.d.ts +43 -0
  34. package/dist/core/collectorRegistry.d.ts.map +1 -0
  35. package/dist/core/collectorRegistry.js +76 -0
  36. package/dist/core/collectorRegistry.js.map +1 -0
  37. package/dist/core/constants.d.ts +25 -0
  38. package/dist/core/constants.d.ts.map +1 -0
  39. package/dist/core/constants.js +33 -0
  40. package/dist/core/constants.js.map +1 -0
  41. package/dist/core/eventBus.d.ts +36 -0
  42. package/dist/core/eventBus.d.ts.map +1 -0
  43. package/dist/core/eventBus.js +52 -0
  44. package/dist/core/eventBus.js.map +1 -0
  45. package/dist/core/types.d.ts +128 -0
  46. package/dist/core/types.d.ts.map +1 -0
  47. package/dist/core/types.js +6 -0
  48. package/dist/core/types.js.map +1 -0
  49. package/dist/events.d.ts +35 -0
  50. package/dist/events.d.ts.map +1 -0
  51. package/dist/events.js +89 -0
  52. package/dist/events.js.map +1 -0
  53. package/dist/index.js +301 -36
  54. package/dist/index.js.map +1 -1
  55. package/dist/models.d.ts +74 -0
  56. package/dist/models.d.ts.map +1 -0
  57. package/dist/models.js +7 -0
  58. package/dist/models.js.map +1 -0
  59. package/dist/state/getCollectorResults.d.ts +18 -0
  60. package/dist/state/getCollectorResults.d.ts.map +1 -0
  61. package/dist/state/getCollectorResults.js +25 -0
  62. package/dist/state/getCollectorResults.js.map +1 -0
  63. package/dist/state/historyStore.d.ts +35 -0
  64. package/dist/state/historyStore.d.ts.map +1 -0
  65. package/dist/state/historyStore.js +58 -0
  66. package/dist/state/historyStore.js.map +1 -0
  67. package/dist/state/uiStateBuilder.d.ts +12 -0
  68. package/dist/state/uiStateBuilder.d.ts.map +1 -0
  69. package/dist/state/uiStateBuilder.js +169 -0
  70. package/dist/state/uiStateBuilder.js.map +1 -0
  71. package/dist/state/uiStateScheduler.d.ts +43 -0
  72. package/dist/state/uiStateScheduler.d.ts.map +1 -0
  73. package/dist/state/uiStateScheduler.js +118 -0
  74. package/dist/state/uiStateScheduler.js.map +1 -0
  75. package/dist/store.d.ts +3 -1
  76. package/dist/store.d.ts.map +1 -1
  77. package/dist/store.js +2 -0
  78. package/dist/store.js.map +1 -1
  79. package/dist/system-state.d.ts +96 -0
  80. package/dist/system-state.d.ts.map +1 -0
  81. package/dist/system-state.js +273 -0
  82. package/dist/system-state.js.map +1 -0
  83. package/dist/ui/boot/sequence.d.ts +10 -0
  84. package/dist/ui/boot/sequence.d.ts.map +1 -0
  85. package/dist/ui/boot/sequence.js +173 -0
  86. package/dist/ui/boot/sequence.js.map +1 -0
  87. package/dist/ui/constraints/layoutSpec.d.ts +47 -0
  88. package/dist/ui/constraints/layoutSpec.d.ts.map +1 -0
  89. package/dist/ui/constraints/layoutSpec.js +60 -0
  90. package/dist/ui/constraints/layoutSpec.js.map +1 -0
  91. package/dist/ui/constraints/unknownHandling.d.ts +29 -0
  92. package/dist/ui/constraints/unknownHandling.d.ts.map +1 -0
  93. package/dist/ui/constraints/unknownHandling.js +60 -0
  94. package/dist/ui/constraints/unknownHandling.js.map +1 -0
  95. package/dist/ui/drilldowns/feed.d.ts +11 -0
  96. package/dist/ui/drilldowns/feed.d.ts.map +1 -0
  97. package/dist/ui/drilldowns/feed.js +68 -0
  98. package/dist/ui/drilldowns/feed.js.map +1 -0
  99. package/dist/ui/drilldowns/index.d.ts +7 -0
  100. package/dist/ui/drilldowns/index.d.ts.map +1 -0
  101. package/dist/ui/drilldowns/index.js +8 -0
  102. package/dist/ui/drilldowns/index.js.map +1 -0
  103. package/dist/ui/drilldowns/posture.d.ts +11 -0
  104. package/dist/ui/drilldowns/posture.d.ts.map +1 -0
  105. package/dist/ui/drilldowns/posture.js +74 -0
  106. package/dist/ui/drilldowns/posture.js.map +1 -0
  107. package/dist/ui/intelligence-posture-view.d.ts +22 -0
  108. package/dist/ui/intelligence-posture-view.d.ts.map +1 -0
  109. package/dist/ui/intelligence-posture-view.js +169 -0
  110. package/dist/ui/intelligence-posture-view.js.map +1 -0
  111. package/dist/ui/navigation/keymaps.d.ts +26 -0
  112. package/dist/ui/navigation/keymaps.d.ts.map +1 -0
  113. package/dist/ui/navigation/keymaps.js +135 -0
  114. package/dist/ui/navigation/keymaps.js.map +1 -0
  115. package/dist/ui/navigation/palette.d.ts +10 -0
  116. package/dist/ui/navigation/palette.d.ts.map +1 -0
  117. package/dist/ui/navigation/palette.js +133 -0
  118. package/dist/ui/navigation/palette.js.map +1 -0
  119. package/dist/ui/navigation/state.d.ts +47 -0
  120. package/dist/ui/navigation/state.d.ts.map +1 -0
  121. package/dist/ui/navigation/state.js +84 -0
  122. package/dist/ui/navigation/state.js.map +1 -0
  123. package/dist/ui/navigation/types.d.ts +38 -0
  124. package/dist/ui/navigation/types.d.ts.map +1 -0
  125. package/dist/ui/navigation/types.js +36 -0
  126. package/dist/ui/navigation/types.js.map +1 -0
  127. package/dist/ui/panels/active-assets.d.ts +12 -0
  128. package/dist/ui/panels/active-assets.d.ts.map +1 -0
  129. package/dist/ui/panels/active-assets.js +83 -0
  130. package/dist/ui/panels/active-assets.js.map +1 -0
  131. package/dist/ui/panels/capability-flags.d.ts +12 -0
  132. package/dist/ui/panels/capability-flags.d.ts.map +1 -0
  133. package/dist/ui/panels/capability-flags.js +59 -0
  134. package/dist/ui/panels/capability-flags.js.map +1 -0
  135. package/dist/ui/panels/command-surface.d.ts +12 -0
  136. package/dist/ui/panels/command-surface.d.ts.map +1 -0
  137. package/dist/ui/panels/command-surface.js +55 -0
  138. package/dist/ui/panels/command-surface.js.map +1 -0
  139. package/dist/ui/panels/network-origin.d.ts +12 -0
  140. package/dist/ui/panels/network-origin.d.ts.map +1 -0
  141. package/dist/ui/panels/network-origin.js +79 -0
  142. package/dist/ui/panels/network-origin.js.map +1 -0
  143. package/dist/ui/panels/operations-feed.d.ts +12 -0
  144. package/dist/ui/panels/operations-feed.d.ts.map +1 -0
  145. package/dist/ui/panels/operations-feed.js +90 -0
  146. package/dist/ui/panels/operations-feed.js.map +1 -0
  147. package/dist/ui/panels/posture.d.ts +12 -0
  148. package/dist/ui/panels/posture.d.ts.map +1 -0
  149. package/dist/ui/panels/posture.js +84 -0
  150. package/dist/ui/panels/posture.js.map +1 -0
  151. package/dist/ui/panels/resources.d.ts +11 -0
  152. package/dist/ui/panels/resources.d.ts.map +1 -0
  153. package/dist/ui/panels/resources.js +88 -0
  154. package/dist/ui/panels/resources.js.map +1 -0
  155. package/dist/ui/primitives/Panel.d.ts +25 -0
  156. package/dist/ui/primitives/Panel.d.ts.map +1 -0
  157. package/dist/ui/primitives/Panel.js +59 -0
  158. package/dist/ui/primitives/Panel.js.map +1 -0
  159. package/dist/ui/rendering/metricRenderer.d.ts +24 -0
  160. package/dist/ui/rendering/metricRenderer.d.ts.map +1 -0
  161. package/dist/ui/rendering/metricRenderer.js +86 -0
  162. package/dist/ui/rendering/metricRenderer.js.map +1 -0
  163. package/dist/ui/runtime/hub.d.ts +12 -0
  164. package/dist/ui/runtime/hub.d.ts.map +1 -0
  165. package/dist/ui/runtime/hub.js +468 -0
  166. package/dist/ui/runtime/hub.js.map +1 -0
  167. package/dist/ui/runtime/hubValidation.d.ts +23 -0
  168. package/dist/ui/runtime/hubValidation.d.ts.map +1 -0
  169. package/dist/ui/runtime/hubValidation.js +90 -0
  170. package/dist/ui/runtime/hubValidation.js.map +1 -0
  171. package/dist/ui/runtime/index.d.ts +29 -0
  172. package/dist/ui/runtime/index.d.ts.map +1 -0
  173. package/dist/ui/runtime/index.js +299 -0
  174. package/dist/ui/runtime/index.js.map +1 -0
  175. package/dist/ui/runtime/no-tui.d.ts +12 -0
  176. package/dist/ui/runtime/no-tui.d.ts.map +1 -0
  177. package/dist/ui/runtime/no-tui.js +77 -0
  178. package/dist/ui/runtime/no-tui.js.map +1 -0
  179. package/dist/ui/runtime/state-builder.d.ts +13 -0
  180. package/dist/ui/runtime/state-builder.d.ts.map +1 -0
  181. package/dist/ui/runtime/state-builder.js +114 -0
  182. package/dist/ui/runtime/state-builder.js.map +1 -0
  183. package/dist/ui/runtime/terminalSizeCheck.d.ts +10 -0
  184. package/dist/ui/runtime/terminalSizeCheck.d.ts.map +1 -0
  185. package/dist/ui/runtime/terminalSizeCheck.js +51 -0
  186. package/dist/ui/runtime/terminalSizeCheck.js.map +1 -0
  187. package/dist/ui/runtime/tuiLogGate.d.ts +22 -0
  188. package/dist/ui/runtime/tuiLogGate.d.ts.map +1 -0
  189. package/dist/ui/runtime/tuiLogGate.js +68 -0
  190. package/dist/ui/runtime/tuiLogGate.js.map +1 -0
  191. package/dist/ui/state/types.d.ts +72 -0
  192. package/dist/ui/state/types.d.ts.map +1 -0
  193. package/dist/ui/state/types.js +6 -0
  194. package/dist/ui/state/types.js.map +1 -0
  195. package/dist/ui/theme/borders.d.ts +20 -0
  196. package/dist/ui/theme/borders.d.ts.map +1 -0
  197. package/dist/ui/theme/borders.js +55 -0
  198. package/dist/ui/theme/borders.js.map +1 -0
  199. package/dist/ui/theme/tokens.d.ts +28 -0
  200. package/dist/ui/theme/tokens.d.ts.map +1 -0
  201. package/dist/ui/theme/tokens.js +50 -0
  202. package/dist/ui/theme/tokens.js.map +1 -0
  203. package/dist/ui/theme/typography.d.ts +14 -0
  204. package/dist/ui/theme/typography.d.ts.map +1 -0
  205. package/dist/ui/theme/typography.js +30 -0
  206. package/dist/ui/theme/typography.js.map +1 -0
  207. package/dist/ui/widgets/flagRow.d.ts +25 -0
  208. package/dist/ui/widgets/flagRow.d.ts.map +1 -0
  209. package/dist/ui/widgets/flagRow.js +57 -0
  210. package/dist/ui/widgets/flagRow.js.map +1 -0
  211. package/dist/ui/widgets/index.d.ts +9 -0
  212. package/dist/ui/widgets/index.d.ts.map +1 -0
  213. package/dist/ui/widgets/index.js +9 -0
  214. package/dist/ui/widgets/index.js.map +1 -0
  215. package/dist/ui/widgets/meter.d.ts +18 -0
  216. package/dist/ui/widgets/meter.d.ts.map +1 -0
  217. package/dist/ui/widgets/meter.js +38 -0
  218. package/dist/ui/widgets/meter.js.map +1 -0
  219. package/dist/ui/widgets/miniMap.d.ts +26 -0
  220. package/dist/ui/widgets/miniMap.d.ts.map +1 -0
  221. package/dist/ui/widgets/miniMap.js +94 -0
  222. package/dist/ui/widgets/miniMap.js.map +1 -0
  223. package/dist/ui/widgets/sparkline.d.ts +17 -0
  224. package/dist/ui/widgets/sparkline.d.ts.map +1 -0
  225. package/dist/ui/widgets/sparkline.js +63 -0
  226. package/dist/ui/widgets/sparkline.js.map +1 -0
  227. package/dist/ui-primitives.d.ts +5 -2
  228. package/dist/ui-primitives.d.ts.map +1 -1
  229. package/dist/ui-primitives.js +22 -9
  230. package/dist/ui-primitives.js.map +1 -1
  231. package/package.json +5 -4
  232. package/dist/ui/home-view.d.ts +0 -27
  233. package/dist/ui/home-view.d.ts.map +0 -1
  234. package/dist/ui/home-view.js +0 -127
  235. package/dist/ui/home-view.js.map +0 -1
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Panel 6: CAPABILITY FLAGS
3
+ * Location: Right column (bottom)
4
+ * Purpose: Silent credibility. No explanation.
5
+ */
6
+ import { getSystemState } from '../../system-state.js';
7
+ import { createPanel } from '../primitives/Panel.js';
8
+ import { getBlessedColor } from '../theme/tokens.js';
9
+ /**
10
+ * Render CAPABILITY FLAGS panel
11
+ */
12
+ export function renderCapabilityFlagsPanel(screen, top, left, width, height, appState) {
13
+ let systemState;
14
+ try {
15
+ systemState = getSystemState(appState, false);
16
+ }
17
+ catch {
18
+ systemState = null;
19
+ }
20
+ const content = [];
21
+ if (systemState) {
22
+ const flags = systemState.capabilityFlags;
23
+ // GATEWAY
24
+ const gatewayColor = flags.gateway === 'READY'
25
+ ? getBlessedColor('successGreen')
26
+ : getBlessedColor('warnAmber');
27
+ content.push(`GATEWAY: {${gatewayColor}-fg}${flags.gateway}{/}`);
28
+ // DATABASE
29
+ const dbColor = flags.database === 'READY'
30
+ ? getBlessedColor('successGreen')
31
+ : getBlessedColor('warnAmber');
32
+ content.push(`DATABASE: {${dbColor}-fg}${flags.database}{/}`);
33
+ // MEMORY
34
+ content.push(`MEMORY: {${getBlessedColor('accentCyan')}-fg}${flags.memoryLayer}{/}`);
35
+ // SECURITY
36
+ content.push(`SECURITY: {${getBlessedColor('accentCyan')}-fg}${flags.security}{/}`);
37
+ // RATE LIMIT
38
+ const rateLimitColor = flags.rateLimiting === 'ENABLED'
39
+ ? getBlessedColor('successGreen')
40
+ : getBlessedColor('mutedGrey');
41
+ content.push(`RATE LIMIT: {${rateLimitColor}-fg}${flags.rateLimiting}{/}`);
42
+ }
43
+ else {
44
+ content.push('GATEWAY: UNKNOWN');
45
+ content.push('DATABASE: UNKNOWN');
46
+ content.push('MEMORY: UNKNOWN');
47
+ content.push('SECURITY: UNKNOWN');
48
+ content.push('RATE LIMIT: UNKNOWN');
49
+ }
50
+ return createPanel(screen, {
51
+ title: 'CAPABILITY FLAGS',
52
+ top,
53
+ left,
54
+ width,
55
+ height,
56
+ content,
57
+ });
58
+ }
59
+ //# sourceMappingURL=capability-flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-flags.js","sourceRoot":"","sources":["../../../src/ui/panels/capability-flags.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAsB,EACtB,GAAW,EACX,IAAY,EACZ,KAAa,EACb,MAAc,EACd,QAAkB;IAElB,IAAI,WAAW,CAAC;IAChB,IAAI,CAAC;QACH,WAAW,GAAG,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,WAAW,CAAC,eAAe,CAAC;QAE1C,UAAU;QACV,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,KAAK,OAAO;YAC5C,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC;YACjC,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,aAAa,YAAY,OAAO,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;QAEjE,WAAW;QACX,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,KAAK,OAAO;YACxC,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC;YACjC,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,cAAc,OAAO,OAAO,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC;QAE9D,SAAS;QACT,OAAO,CAAC,IAAI,CAAC,YAAY,eAAe,CAAC,YAAY,CAAC,OAAO,KAAK,CAAC,WAAW,KAAK,CAAC,CAAC;QAErF,WAAW;QACX,OAAO,CAAC,IAAI,CAAC,cAAc,eAAe,CAAC,YAAY,CAAC,OAAO,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC;QAEpF,aAAa;QACb,MAAM,cAAc,GAAG,KAAK,CAAC,YAAY,KAAK,SAAS;YACrD,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC;YACjC,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,gBAAgB,cAAc,OAAO,KAAK,CAAC,YAAY,KAAK,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,WAAW,CAAC,MAAM,EAAE;QACzB,KAAK,EAAE,kBAAkB;QACzB,GAAG;QACH,IAAI;QACJ,KAAK;QACL,MAAM;QACN,OAAO;KACR,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Panel 7: COMMAND SURFACE + STATUS STRIP
3
+ * Location: Bottom bar
4
+ * Purpose: Authority and orientation
5
+ */
6
+ import type { Widgets } from 'neo-blessed';
7
+ import type { AppState } from '../../store.js';
8
+ /**
9
+ * Render COMMAND SURFACE + STATUS STRIP
10
+ */
11
+ export declare function renderCommandSurface(screen: Widgets.Screen, top: number, left: number, width: number, height: number, appState: AppState): Widgets.Box;
12
+ //# sourceMappingURL=command-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-surface.d.ts","sourceRoot":"","sources":["../../../src/ui/panels/command-surface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM/C;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,GAAG,CAgDb"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Panel 7: COMMAND SURFACE + STATUS STRIP
3
+ * Location: Bottom bar
4
+ * Purpose: Authority and orientation
5
+ */
6
+ import blessed from 'neo-blessed';
7
+ import { getSystemState } from '../../system-state.js';
8
+ import { getBlessedColor } from '../theme/tokens.js';
9
+ const blessedLib = blessed;
10
+ /**
11
+ * Render COMMAND SURFACE + STATUS STRIP
12
+ */
13
+ export function renderCommandSurface(screen, top, left, width, height, appState) {
14
+ let systemState;
15
+ try {
16
+ systemState = getSystemState(appState, false);
17
+ }
18
+ catch {
19
+ systemState = null;
20
+ }
21
+ // Command Surface (left side)
22
+ const commands = 'start deploy inspect metrics system';
23
+ const commandText = `{${getBlessedColor('accentCyan')}-fg}${commands}{/}`;
24
+ // Status Strip (right side)
25
+ const mode = appState.localMode ? 'LOCAL' : (appState.gatewayConnected ? 'REMOTE' : 'OFFLINE');
26
+ const connect = appState.gatewayConnected ? 'CONNECTED' : 'DISCONNECTED';
27
+ const posture = systemState?.systemPosture.overallPosture || 'UNKNOWN';
28
+ // Count active runs
29
+ const activeRuns = appState.runHistory.filter(r => r.status === 'RUNNING').length;
30
+ // Last command (simplified - would track actual last command)
31
+ const lastCmd = 'posture';
32
+ const statusParts = [
33
+ mode,
34
+ connect,
35
+ posture,
36
+ `${activeRuns}`,
37
+ lastCmd,
38
+ ];
39
+ const statusText = statusParts.join(' | ');
40
+ // Combine command surface and status strip
41
+ const fullText = `${commandText} | {${getBlessedColor('mutedGrey')}-fg}${statusText}{/}`;
42
+ const statusBar = blessedLib.box({
43
+ top,
44
+ left,
45
+ width,
46
+ height,
47
+ content: fullText,
48
+ tags: true,
49
+ style: {
50
+ fg: getBlessedColor('standardWhite'),
51
+ },
52
+ });
53
+ return statusBar;
54
+ }
55
+ //# sourceMappingURL=command-surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-surface.js","sourceRoot":"","sources":["../../../src/ui/panels/command-surface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,OAAO,MAAM,aAAa,CAAC;AAGlC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,UAAU,GAAQ,OAAO,CAAC;AAEhC;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAsB,EACtB,GAAW,EACX,IAAY,EACZ,KAAa,EACb,MAAc,EACd,QAAkB;IAElB,IAAI,WAAW,CAAC;IAChB,IAAI,CAAC;QACH,WAAW,GAAG,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,6CAA6C,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,YAAY,CAAC,OAAO,QAAQ,KAAK,CAAC;IAE1E,4BAA4B;IAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/F,MAAM,OAAO,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC;IACzE,MAAM,OAAO,GAAG,WAAW,EAAE,aAAa,CAAC,cAAc,IAAI,SAAS,CAAC;IAEvE,oBAAoB;IACpB,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IAElF,8DAA8D;IAC9D,MAAM,OAAO,GAAG,SAAS,CAAC;IAE1B,MAAM,WAAW,GAAG;QAClB,IAAI;QACJ,OAAO;QACP,OAAO;QACP,GAAG,UAAU,EAAE;QACf,OAAO;KACR,CAAC;IACF,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE3C,2CAA2C;IAC3C,MAAM,QAAQ,GAAG,GAAG,WAAW,SAAS,eAAe,CAAC,WAAW,CAAC,OAAO,UAAU,KAAK,CAAC;IAE3F,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC;QAC/B,GAAG;QACH,IAAI;QACJ,KAAK;QACL,MAAM;QACN,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE;YACL,EAAE,EAAE,eAAe,CAAC,eAAe,CAAC;SACrC;KACF,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Panel 5: NETWORK / ORIGIN
3
+ * Location: Right column (top)
4
+ * Purpose: Situational and geographic awareness
5
+ */
6
+ import type { Widgets } from 'neo-blessed';
7
+ import type { AppState } from '../../store.js';
8
+ /**
9
+ * Render NETWORK / ORIGIN panel
10
+ */
11
+ export declare function renderNetworkOriginPanel(screen: Widgets.Screen, top: number, left: number, width: number, height: number, appState: AppState): Widgets.Box;
12
+ //# sourceMappingURL=network-origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-origin.d.ts","sourceRoot":"","sources":["../../../src/ui/panels/network-origin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAwB/C;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,GAAG,CAoDb"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Panel 5: NETWORK / ORIGIN
3
+ * Location: Right column (top)
4
+ * Purpose: Situational and geographic awareness
5
+ */
6
+ import { getSystemState } from '../../system-state.js';
7
+ import { createPanel } from '../primitives/Panel.js';
8
+ import { getBlessedColor } from '../theme/tokens.js';
9
+ /**
10
+ * Mask IP address (e.g., 44.222.xxx.xxx)
11
+ */
12
+ function maskIP(ip) {
13
+ const parts = ip.split('.');
14
+ if (parts.length === 4) {
15
+ return `${parts[0]}.${parts[1]}.xxx.xxx`;
16
+ }
17
+ return 'HIDDEN';
18
+ }
19
+ /**
20
+ * Get public IP (simplified - would need actual IP detection)
21
+ */
22
+ function getPublicIP() {
23
+ // For v1, return HIDDEN (would need external API call)
24
+ return 'HIDDEN';
25
+ }
26
+ /**
27
+ * Render NETWORK / ORIGIN panel
28
+ */
29
+ export function renderNetworkOriginPanel(screen, top, left, width, height, appState) {
30
+ let systemState;
31
+ try {
32
+ systemState = getSystemState(appState, false);
33
+ }
34
+ catch {
35
+ systemState = null;
36
+ }
37
+ const content = [];
38
+ if (systemState) {
39
+ const network = systemState.networkContext;
40
+ // ORIGIN
41
+ const origin = `${network.operatorOrigin.region} (${network.operatorOrigin.networkType})`;
42
+ content.push(`ORIGIN: {${getBlessedColor('accentCyan')}-fg}${origin}{/}`);
43
+ // GATEWAY
44
+ const gateway = network.targetInfrastructure.gatewayRegion || 'UNKNOWN';
45
+ content.push(`GATEWAY: {${getBlessedColor('accentCyan')}-fg}${gateway}{/}`);
46
+ // DATABASE
47
+ const database = network.targetInfrastructure.databaseRegion || 'NONE';
48
+ content.push(`DATABASE: {${getBlessedColor('accentCyan')}-fg}${database}{/}`);
49
+ // LATENCY
50
+ const latency = network.targetInfrastructure.latencyClass;
51
+ let latencyColor = getBlessedColor('mutedGrey');
52
+ if (latency === 'LOW')
53
+ latencyColor = getBlessedColor('successGreen');
54
+ else if (latency === 'MEDIUM')
55
+ latencyColor = getBlessedColor('warnAmber');
56
+ else if (latency === 'HIGH')
57
+ latencyColor = getBlessedColor('criticalRed');
58
+ content.push(`LATENCY: {${latencyColor}-fg}${latency}{/}`);
59
+ // PUBLIC IP
60
+ const publicIP = getPublicIP();
61
+ content.push(`PUBLIC IP: {${getBlessedColor('mutedGrey')}-fg}${publicIP}{/}`);
62
+ }
63
+ else {
64
+ content.push('ORIGIN: UNKNOWN');
65
+ content.push('GATEWAY: UNKNOWN');
66
+ content.push('DATABASE: UNKNOWN');
67
+ content.push('LATENCY: UNKNOWN');
68
+ content.push('PUBLIC IP: UNKNOWN');
69
+ }
70
+ return createPanel(screen, {
71
+ title: 'NETWORK / ORIGIN',
72
+ top,
73
+ left,
74
+ width,
75
+ height,
76
+ content,
77
+ });
78
+ }
79
+ //# sourceMappingURL=network-origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-origin.js","sourceRoot":"","sources":["../../../src/ui/panels/network-origin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Panel 4: OPERATIONS FEED
3
+ * Location: Center column (main)
4
+ * Purpose: Make the system feel alive and responsive
5
+ */
6
+ import type { Widgets } from 'neo-blessed';
7
+ import type { AppState } from '../../store.js';
8
+ /**
9
+ * Render OPERATIONS FEED panel
10
+ */
11
+ export declare function renderOperationsFeedPanel(screen: Widgets.Screen, top: number, left: number, width: number, height: number, appState: AppState): Widgets.Box;
12
+ //# sourceMappingURL=operations-feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations-feed.d.ts","sourceRoot":"","sources":["../../../src/ui/panels/operations-feed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA4D/C;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,GAAG,CA8Bb"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Panel 4: OPERATIONS FEED
3
+ * Location: Center column (main)
4
+ * Purpose: Make the system feel alive and responsive
5
+ */
6
+ import { getSystemState } from '../../system-state.js';
7
+ import { createPanel } from '../primitives/Panel.js';
8
+ import { getBlessedColor } from '../theme/tokens.js';
9
+ /**
10
+ * Format timestamp as HH:MM:SS
11
+ */
12
+ function formatTime(timestamp) {
13
+ const date = new Date(timestamp);
14
+ const hours = date.getHours().toString().padStart(2, '0');
15
+ const minutes = date.getMinutes().toString().padStart(2, '0');
16
+ const seconds = date.getSeconds().toString().padStart(2, '0');
17
+ return `${hours}:${minutes}:${seconds}`;
18
+ }
19
+ /**
20
+ * Get event tag from event type
21
+ */
22
+ function getEventTag(eventType) {
23
+ if (eventType.includes('RUN'))
24
+ return 'RUN';
25
+ if (eventType.includes('CONNECTION'))
26
+ return 'NET';
27
+ if (eventType.includes('ERROR'))
28
+ return 'SEC';
29
+ if (eventType.includes('DATABASE') || eventType.includes('DB'))
30
+ return 'DB';
31
+ if (eventType.includes('GATEWAY'))
32
+ return 'GATEWAY';
33
+ return 'SYSTEM';
34
+ }
35
+ /**
36
+ * Format event for display
37
+ * Format: [HH:MM:SS] [TAG] message
38
+ */
39
+ function formatEvent(event) {
40
+ const time = formatTime(event.timestamp);
41
+ const tag = getEventTag(event.type);
42
+ // Extract message from description (remove prefix if present)
43
+ let message = event.description;
44
+ if (message.includes(':')) {
45
+ const parts = message.split(':');
46
+ if (parts.length > 1) {
47
+ message = parts.slice(1).join(':').trim();
48
+ }
49
+ }
50
+ const color = event.severity === 'critical'
51
+ ? getBlessedColor('criticalRed')
52
+ : event.severity === 'warning'
53
+ ? getBlessedColor('warnAmber')
54
+ : getBlessedColor('accentCyan');
55
+ // Format: [HH:MM:SS] [TAG] message
56
+ return `{${color}-fg}[${time}] [${tag}] ${message}{/}`;
57
+ }
58
+ /**
59
+ * Render OPERATIONS FEED panel
60
+ */
61
+ export function renderOperationsFeedPanel(screen, top, left, width, height, appState) {
62
+ let systemState;
63
+ try {
64
+ systemState = getSystemState(appState, false);
65
+ }
66
+ catch {
67
+ systemState = null;
68
+ }
69
+ const content = [];
70
+ if (systemState && systemState.operationFeed.length > 0) {
71
+ // Show last 10-12 events (newest first)
72
+ const events = systemState.operationFeed
73
+ .slice(-12)
74
+ .reverse()
75
+ .map(formatEvent);
76
+ content.push(...events);
77
+ }
78
+ else {
79
+ content.push(`{${getBlessedColor('mutedGrey')}-fg}NO RECENT OPERATIONS{/}`);
80
+ }
81
+ return createPanel(screen, {
82
+ title: 'OPERATIONS FEED',
83
+ top,
84
+ left,
85
+ width,
86
+ height,
87
+ content,
88
+ });
89
+ }
90
+ //# sourceMappingURL=operations-feed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations-feed.js","sourceRoot":"","sources":["../../../src/ui/panels/operations-feed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Panel 1: POSTURE
3
+ * Location: Left column (top)
4
+ * Purpose: Answer "Am I safe to operate?"
5
+ */
6
+ import type { Widgets } from 'neo-blessed';
7
+ import type { AppState } from '../../store.js';
8
+ /**
9
+ * Render POSTURE panel
10
+ */
11
+ export declare function renderPosturePanel(screen: Widgets.Screen, top: number, left: number, width: number, height: number, appState: AppState): Widgets.Box;
12
+ //# sourceMappingURL=posture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posture.d.ts","sourceRoot":"","sources":["../../../src/ui/panels/posture.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM/C;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,GAAG,CAsEb"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Panel 1: POSTURE
3
+ * Location: Left column (top)
4
+ * Purpose: Answer "Am I safe to operate?"
5
+ */
6
+ import { getSystemState } from '../../system-state.js';
7
+ import { createPanel } from '../primitives/Panel.js';
8
+ import { getBlessedColor } from '../theme/tokens.js';
9
+ import { formatRelativeTime } from '../../utils.js';
10
+ /**
11
+ * Render POSTURE panel
12
+ */
13
+ export function renderPosturePanel(screen, top, left, width, height, appState) {
14
+ let systemState;
15
+ try {
16
+ systemState = getSystemState(appState, false);
17
+ }
18
+ catch {
19
+ systemState = null;
20
+ }
21
+ const content = [];
22
+ // POSTURE
23
+ const posture = systemState?.systemPosture.overallPosture || 'UNKNOWN';
24
+ let postureColor = 'white';
25
+ if (posture === 'OPERATIONAL')
26
+ postureColor = getBlessedColor('successGreen');
27
+ else if (posture === 'DEGRADED')
28
+ postureColor = getBlessedColor('warnAmber');
29
+ else if (posture === 'CRITICAL')
30
+ postureColor = getBlessedColor('criticalRed');
31
+ content.push(`POSTURE: {${postureColor}-fg}${posture}{/}`);
32
+ // RISK
33
+ const risk = systemState?.systemPosture.riskLevel || 'UNKNOWN';
34
+ let riskColor = 'white';
35
+ if (risk === 'LOW')
36
+ riskColor = getBlessedColor('successGreen');
37
+ else if (risk === 'ELEVATED')
38
+ riskColor = getBlessedColor('warnAmber');
39
+ else if (risk === 'HIGH')
40
+ riskColor = getBlessedColor('criticalRed');
41
+ content.push(`RISK: {${riskColor}-fg}${risk}{/}`);
42
+ // CONNECTED
43
+ const connected = appState.gatewayConnected ? 'YES' : 'NO';
44
+ const target = appState.gatewayUrl
45
+ ? appState.gatewayUrl.replace(/^https?:\/\//, '').substring(0, 20)
46
+ : '';
47
+ const connectedText = connected === 'YES' && target
48
+ ? `${connected} (${target})`
49
+ : connected;
50
+ const connectedColor = connected === 'YES'
51
+ ? getBlessedColor('successGreen')
52
+ : getBlessedColor('warnAmber');
53
+ content.push(`CONNECTED: {${connectedColor}-fg}${connectedText}{/}`);
54
+ // LAST CHANGE
55
+ const lastChange = systemState?.systemPosture.lastStateChange
56
+ ? formatRelativeTime(systemState.systemPosture.lastStateChange)
57
+ : 'UNKNOWN';
58
+ content.push(`LAST CHANGE: ${lastChange}`);
59
+ // CAUSE (only if not OPERATIONAL)
60
+ if (posture !== 'OPERATIONAL' && posture !== 'UNKNOWN') {
61
+ let cause = '';
62
+ if (posture === 'CRITICAL') {
63
+ cause = 'System initialization failed';
64
+ }
65
+ else if (posture === 'DEGRADED') {
66
+ cause = 'No gateway connection';
67
+ }
68
+ else if (posture === 'OFFLINE') {
69
+ cause = 'Offline mode';
70
+ }
71
+ if (cause) {
72
+ content.push(`CAUSE: {${getBlessedColor('warnAmber')}-fg}${cause}{/}`);
73
+ }
74
+ }
75
+ return createPanel(screen, {
76
+ title: 'POSTURE',
77
+ top,
78
+ left,
79
+ width,
80
+ height,
81
+ content,
82
+ });
83
+ }
84
+ //# sourceMappingURL=posture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posture.js","sourceRoot":"","sources":["../../../src/ui/panels/posture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Panel 2: RESOURCES
3
+ * Location: Left column (middle)
4
+ * Purpose: Give devs confidence the system is under control
5
+ */
6
+ import type { Widgets } from 'neo-blessed';
7
+ /**
8
+ * Render RESOURCES panel
9
+ */
10
+ export declare function renderResourcesPanel(screen: Widgets.Screen, top: number, left: number, width: number, height: number, appState?: any): Widgets.Box;
11
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/ui/panels/resources.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAqD3C;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,GAAG,GACb,OAAO,CAAC,GAAG,CAsCb"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Panel 2: RESOURCES
3
+ * Location: Left column (middle)
4
+ * Purpose: Give devs confidence the system is under control
5
+ */
6
+ import * as os from 'os';
7
+ import { createPanel } from '../primitives/Panel.js';
8
+ // Uptime formatting done inline
9
+ /**
10
+ * Get CPU usage (simplified - would need actual monitoring in production)
11
+ */
12
+ function getCpuUsage() {
13
+ // For v1, return UNKNOWN (would need os-utils or similar)
14
+ // In production, would track CPU over time
15
+ return 'UNKNOWN';
16
+ }
17
+ /**
18
+ * Get load average (1 minute)
19
+ */
20
+ function getLoadAverage() {
21
+ const load = os.loadavg();
22
+ if (load && load.length > 0) {
23
+ return load[0].toFixed(2);
24
+ }
25
+ return 'UNKNOWN';
26
+ }
27
+ /**
28
+ * Get RAM usage
29
+ */
30
+ function getRamUsage() {
31
+ const total = os.totalmem();
32
+ const free = os.freemem();
33
+ const used = total - free;
34
+ const usedGB = (used / 1024 / 1024 / 1024).toFixed(1);
35
+ const totalGB = (total / 1024 / 1024 / 1024).toFixed(1);
36
+ return `${usedGB}G / ${totalGB}G`;
37
+ }
38
+ /**
39
+ * Get disk usage (simplified - would need actual disk monitoring)
40
+ */
41
+ function getDiskUsage() {
42
+ // For v1, return UNKNOWN (would need statvfs or similar)
43
+ return 'UNKNOWN';
44
+ }
45
+ /**
46
+ * Get process count
47
+ */
48
+ function getProcessCount() {
49
+ // Simplified - would count actual processes
50
+ return 'UNKNOWN';
51
+ }
52
+ /**
53
+ * Render RESOURCES panel
54
+ */
55
+ export function renderResourcesPanel(screen, top, left, width, height, appState // Not used but kept for consistency
56
+ ) {
57
+ const content = [];
58
+ // CPU
59
+ const cpu = getCpuUsage();
60
+ content.push(`CPU: ${cpu}`);
61
+ // LOAD
62
+ const load = getLoadAverage();
63
+ content.push(`LOAD: ${load}`);
64
+ // RAM
65
+ const ram = getRamUsage();
66
+ content.push(`RAM: ${ram}`);
67
+ // DISK
68
+ const disk = getDiskUsage();
69
+ content.push(`DISK: ${disk}`);
70
+ // UPTIME
71
+ const uptimeSeconds = os.uptime();
72
+ const hours = Math.floor(uptimeSeconds / 3600);
73
+ const minutes = Math.floor((uptimeSeconds % 3600) / 60);
74
+ const uptime = hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
75
+ content.push(`UPTIME: ${uptime}`);
76
+ // PROCS
77
+ const procs = getProcessCount();
78
+ content.push(`PROCS: ${procs}`);
79
+ return createPanel(screen, {
80
+ title: 'RESOURCES',
81
+ top,
82
+ left,
83
+ width,
84
+ height,
85
+ content,
86
+ });
87
+ }
88
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../src/ui/panels/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Panel Primitive
3
+ * Phase 1: Reusable panel component with consistent styling
4
+ */
5
+ import type { Widgets } from 'neo-blessed';
6
+ import type { PanelId } from '../navigation/types.js';
7
+ /**
8
+ * Panel Options
9
+ */
10
+ export interface PanelOptions {
11
+ title: string;
12
+ top: number;
13
+ left: number;
14
+ width: number;
15
+ height: number;
16
+ content?: string[];
17
+ focused?: boolean;
18
+ panelId?: PanelId;
19
+ severity?: 'OK' | 'WARNING' | 'CRITICAL' | 'NEUTRAL';
20
+ }
21
+ /**
22
+ * Create a consistent panel widget
23
+ */
24
+ export declare function createPanel(screen: Widgets.Screen, options: PanelOptions): Widgets.Box;
25
+ //# sourceMappingURL=Panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../src/ui/primitives/Panel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAKtD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;CACtD;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,GAAG,CAkEb"}