4runr-os 1.0.46 → 1.0.49

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 (91) hide show
  1. package/dist/index.js +6 -34
  2. package/dist/index.js.map +1 -1
  3. package/dist/ui/v3/collectors/resources.d.ts +23 -0
  4. package/dist/ui/v3/collectors/resources.d.ts.map +1 -0
  5. package/dist/ui/v3/collectors/resources.js +117 -0
  6. package/dist/ui/v3/collectors/resources.js.map +1 -0
  7. package/dist/ui/v3/commands/commandResult.d.ts +25 -0
  8. package/dist/ui/v3/commands/commandResult.d.ts.map +1 -0
  9. package/dist/ui/v3/commands/commandResult.js +19 -0
  10. package/dist/ui/v3/commands/commandResult.js.map +1 -0
  11. package/dist/ui/v3/commands/parser.d.ts +14 -0
  12. package/dist/ui/v3/commands/parser.d.ts.map +1 -0
  13. package/dist/ui/v3/commands/parser.js +29 -0
  14. package/dist/ui/v3/commands/parser.js.map +1 -0
  15. package/dist/ui/v3/commands/router.d.ts +13 -0
  16. package/dist/ui/v3/commands/router.d.ts.map +1 -0
  17. package/dist/ui/v3/commands/router.js +69 -0
  18. package/dist/ui/v3/commands/router.js.map +1 -0
  19. package/dist/ui/v3/core/event.d.ts +19 -0
  20. package/dist/ui/v3/core/event.d.ts.map +1 -0
  21. package/dist/ui/v3/core/event.js +7 -0
  22. package/dist/ui/v3/core/event.js.map +1 -0
  23. package/dist/ui/v3/core/eventBus.d.ts +33 -0
  24. package/dist/ui/v3/core/eventBus.d.ts.map +1 -0
  25. package/dist/ui/v3/core/eventBus.js +78 -0
  26. package/dist/ui/v3/core/eventBus.js.map +1 -0
  27. package/dist/ui/v3/index.d.ts +8 -0
  28. package/dist/ui/v3/index.d.ts.map +1 -0
  29. package/dist/ui/v3/index.js +30 -0
  30. package/dist/ui/v3/index.js.map +1 -0
  31. package/dist/ui/v3/state/defaultState.d.ts +9 -0
  32. package/dist/ui/v3/state/defaultState.d.ts.map +1 -0
  33. package/dist/ui/v3/state/defaultState.js +11 -0
  34. package/dist/ui/v3/state/defaultState.js.map +1 -0
  35. package/dist/ui/v3/state/feedModel.d.ts +49 -0
  36. package/dist/ui/v3/state/feedModel.d.ts.map +1 -0
  37. package/dist/ui/v3/state/feedModel.js +84 -0
  38. package/dist/ui/v3/state/feedModel.js.map +1 -0
  39. package/dist/ui/v3/state/resourcesData.d.ts +15 -0
  40. package/dist/ui/v3/state/resourcesData.d.ts.map +1 -0
  41. package/dist/ui/v3/state/resourcesData.js +7 -0
  42. package/dist/ui/v3/state/resourcesData.js.map +1 -0
  43. package/dist/ui/v3/state/uiState.d.ts +12 -0
  44. package/dist/ui/v3/state/uiState.d.ts.map +1 -0
  45. package/dist/ui/v3/state/uiState.js +8 -0
  46. package/dist/ui/v3/state/uiState.js.map +1 -0
  47. package/dist/ui/v3/state/uiStateBuilder.d.ts +16 -0
  48. package/dist/ui/v3/state/uiStateBuilder.d.ts.map +1 -0
  49. package/dist/ui/v3/state/uiStateBuilder.js +35 -0
  50. package/dist/ui/v3/state/uiStateBuilder.js.map +1 -0
  51. package/dist/ui/v3/state/value.d.ts +39 -0
  52. package/dist/ui/v3/state/value.d.ts.map +1 -0
  53. package/dist/ui/v3/state/value.js +31 -0
  54. package/dist/ui/v3/state/value.js.map +1 -0
  55. package/dist/ui/v3/ui/focus.d.ts +28 -0
  56. package/dist/ui/v3/ui/focus.d.ts.map +1 -0
  57. package/dist/ui/v3/ui/focus.js +38 -0
  58. package/dist/ui/v3/ui/focus.js.map +1 -0
  59. package/dist/ui/v3/ui/layout/hubLayout.d.ts +43 -0
  60. package/dist/ui/v3/ui/layout/hubLayout.d.ts.map +1 -0
  61. package/dist/ui/v3/ui/layout/hubLayout.js +170 -0
  62. package/dist/ui/v3/ui/layout/hubLayout.js.map +1 -0
  63. package/dist/ui/v3/ui/layout/phase1Layout.d.ts +34 -0
  64. package/dist/ui/v3/ui/layout/phase1Layout.d.ts.map +1 -0
  65. package/dist/ui/v3/ui/layout/phase1Layout.js +107 -0
  66. package/dist/ui/v3/ui/layout/phase1Layout.js.map +1 -0
  67. package/dist/ui/v3/ui/minimalRuntime.d.ts +14 -0
  68. package/dist/ui/v3/ui/minimalRuntime.d.ts.map +1 -0
  69. package/dist/ui/v3/ui/minimalRuntime.js +111 -0
  70. package/dist/ui/v3/ui/minimalRuntime.js.map +1 -0
  71. package/dist/ui/v3/ui/panels/ResourcesPanel.d.ts +16 -0
  72. package/dist/ui/v3/ui/panels/ResourcesPanel.d.ts.map +1 -0
  73. package/dist/ui/v3/ui/panels/ResourcesPanel.js +46 -0
  74. package/dist/ui/v3/ui/panels/ResourcesPanel.js.map +1 -0
  75. package/dist/ui/v3/ui/phase1Runtime.d.ts +22 -0
  76. package/dist/ui/v3/ui/phase1Runtime.d.ts.map +1 -0
  77. package/dist/ui/v3/ui/phase1Runtime.js +574 -0
  78. package/dist/ui/v3/ui/phase1Runtime.js.map +1 -0
  79. package/dist/ui/v3/ui/primitives/Panel.d.ts +39 -0
  80. package/dist/ui/v3/ui/primitives/Panel.d.ts.map +1 -0
  81. package/dist/ui/v3/ui/primitives/Panel.js +105 -0
  82. package/dist/ui/v3/ui/primitives/Panel.js.map +1 -0
  83. package/dist/ui/v3/ui/theme.d.ts +37 -0
  84. package/dist/ui/v3/ui/theme.d.ts.map +1 -0
  85. package/dist/ui/v3/ui/theme.js +40 -0
  86. package/dist/ui/v3/ui/theme.js.map +1 -0
  87. package/dist/ui/v3/ui/widgets/CommandLine.d.ts +26 -0
  88. package/dist/ui/v3/ui/widgets/CommandLine.d.ts.map +1 -0
  89. package/dist/ui/v3/ui/widgets/CommandLine.js +67 -0
  90. package/dist/ui/v3/ui/widgets/CommandLine.js.map +1 -0
  91. package/package.json +3 -2
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Resources Collector (Phase 4)
3
+ *
4
+ * Collects real system metrics:
5
+ * - CPU load percentage
6
+ * - Memory used/total
7
+ * - Disk used/total
8
+ * - Uptime
9
+ *
10
+ * Rules:
11
+ * - Never fakes values
12
+ * - Returns UNAVAILABLE if metrics cannot be fetched
13
+ * - Uses Node APIs/libs only (no shell commands)
14
+ */
15
+ import si from 'systeminformation';
16
+ import os from 'os';
17
+ import { available, unavailable } from '../state/value.js';
18
+ const COLLECTOR_TIMEOUT = 1500; // ms
19
+ /**
20
+ * Collect system resources
21
+ *
22
+ * Returns Value<ResourcesData> - either AVAILABLE with data or UNAVAILABLE with reason
23
+ */
24
+ export async function collectResources() {
25
+ // Wrap in timeout
26
+ const timeoutPromise = new Promise((resolve) => {
27
+ setTimeout(() => {
28
+ resolve(unavailable('Metrics timeout', 'Check system load or increase timeout'));
29
+ }, COLLECTOR_TIMEOUT);
30
+ });
31
+ const collectionPromise = (async () => {
32
+ try {
33
+ // Collect CPU load
34
+ let cpuPercent;
35
+ try {
36
+ const cpu = await si.currentLoad();
37
+ cpuPercent = cpu.currentLoad;
38
+ }
39
+ catch (error) {
40
+ return unavailable('CPU metrics unavailable', 'Ensure systeminformation can access CPU data');
41
+ }
42
+ // Collect load average (1-minute)
43
+ let load1;
44
+ try {
45
+ const avg = os.loadavg();
46
+ load1 = avg[0]; // 1-minute load average
47
+ }
48
+ catch (error) {
49
+ return unavailable('Load average unavailable', 'Ensure Node.js os module is functional');
50
+ }
51
+ // Collect memory
52
+ let ramUsedMB;
53
+ let ramTotalMB;
54
+ try {
55
+ const mem = await si.mem();
56
+ ramUsedMB = Math.round(mem.used / (1024 * 1024));
57
+ ramTotalMB = Math.round(mem.total / (1024 * 1024));
58
+ }
59
+ catch (error) {
60
+ return unavailable('RAM metrics unavailable', 'Ensure systeminformation can access memory data');
61
+ }
62
+ // Collect disk (primary disk)
63
+ let diskUsedGB;
64
+ let diskTotalGB;
65
+ try {
66
+ const fsSize = await si.fsSize();
67
+ // Find primary disk (prefer root or C:)
68
+ const primaryDisk = fsSize.find((d) => d.mount === '/' || d.mount === 'C:\\');
69
+ if (primaryDisk) {
70
+ diskUsedGB = Math.round(primaryDisk.used / (1024 * 1024 * 1024));
71
+ diskTotalGB = Math.round(primaryDisk.size / (1024 * 1024 * 1024));
72
+ }
73
+ else {
74
+ // Use largest disk as fallback
75
+ const largest = fsSize.reduce((largest, current) => {
76
+ return current.size > largest.size ? current : largest;
77
+ });
78
+ if (largest) {
79
+ diskUsedGB = Math.round(largest.used / (1024 * 1024 * 1024));
80
+ diskTotalGB = Math.round(largest.size / (1024 * 1024 * 1024));
81
+ }
82
+ else {
83
+ return unavailable('Primary disk not found', 'Check disk mounting points');
84
+ }
85
+ }
86
+ }
87
+ catch (error) {
88
+ return unavailable('Disk metrics unavailable', 'Grant filesystem access / run outside restricted container');
89
+ }
90
+ // Collect uptime
91
+ let uptimeSeconds;
92
+ try {
93
+ uptimeSeconds = Math.round(os.uptime());
94
+ }
95
+ catch (error) {
96
+ return unavailable('Uptime unavailable', 'Ensure Node.js os module is functional');
97
+ }
98
+ // All metrics collected successfully
99
+ const data = {
100
+ cpuPercent,
101
+ load1,
102
+ ramUsedMB,
103
+ ramTotalMB,
104
+ diskUsedGB,
105
+ diskTotalGB,
106
+ uptimeSeconds,
107
+ };
108
+ return available(data);
109
+ }
110
+ catch (error) {
111
+ // Unexpected error
112
+ return unavailable('Unexpected error collecting metrics', 'Check system permissions and dependencies');
113
+ }
114
+ })();
115
+ return Promise.race([collectionPromise, timeoutPromise]);
116
+ }
117
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../../src/ui/v3/collectors/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Command Result (Phase 3)
3
+ *
4
+ * Result of executing a command.
5
+ * Commands now emit events through EventBus, so results are simpler.
6
+ */
7
+ export interface CommandResult {
8
+ /**
9
+ * Exit the application
10
+ */
11
+ exitApp?: boolean;
12
+ /**
13
+ * Force rerender (optional, can rerender every tick anyway)
14
+ */
15
+ rerender?: boolean;
16
+ }
17
+ /**
18
+ * Create a result that exits the app
19
+ */
20
+ export declare function exitResult(): CommandResult;
21
+ /**
22
+ * Create a no-op result
23
+ */
24
+ export declare function noOpResult(): CommandResult;
25
+ //# sourceMappingURL=commandResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandResult.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/commands/commandResult.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAE1C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAE1C"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Command Result (Phase 3)
3
+ *
4
+ * Result of executing a command.
5
+ * Commands now emit events through EventBus, so results are simpler.
6
+ */
7
+ /**
8
+ * Create a result that exits the app
9
+ */
10
+ export function exitResult() {
11
+ return { exitApp: true };
12
+ }
13
+ /**
14
+ * Create a no-op result
15
+ */
16
+ export function noOpResult() {
17
+ return {};
18
+ }
19
+ //# sourceMappingURL=commandResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandResult.js","sourceRoot":"","sources":["../../../../src/ui/v3/commands/commandResult.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Command Parser
3
+ *
4
+ * Parses command line input into command and arguments.
5
+ */
6
+ export interface ParsedCommand {
7
+ cmd: string;
8
+ args: string[];
9
+ }
10
+ /**
11
+ * Parse command line input
12
+ */
13
+ export declare function parseCommand(input: string): ParsedCommand | null;
14
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/commands/parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA0BhE"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Command Parser
3
+ *
4
+ * Parses command line input into command and arguments.
5
+ */
6
+ /**
7
+ * Parse command line input
8
+ */
9
+ export function parseCommand(input) {
10
+ const trimmed = input.trim();
11
+ // Empty input
12
+ if (!trimmed) {
13
+ return null;
14
+ }
15
+ // Remove prompt if present
16
+ const withoutPrompt = trimmed.replace(/^4runr>\s*/, '').trim();
17
+ if (!withoutPrompt) {
18
+ return null;
19
+ }
20
+ // Split into tokens
21
+ const tokens = withoutPrompt.split(/\s+/);
22
+ if (tokens.length === 0) {
23
+ return null;
24
+ }
25
+ const cmd = tokens[0].toLowerCase();
26
+ const args = tokens.slice(1);
27
+ return { cmd, args };
28
+ }
29
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../../src/ui/v3/commands/parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,cAAc;IACd,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2BAA2B;IAC3B,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAE/D,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB;IACpB,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Command Router (Phase 3)
3
+ *
4
+ * Routes commands to handlers.
5
+ * All output goes through EventBus (not direct feed manipulation).
6
+ */
7
+ import type { CommandResult } from './commandResult.js';
8
+ /**
9
+ * Route a command
10
+ * Commands emit events through EventBus, not directly to feed
11
+ */
12
+ export declare function routeCommand(cmd: string, args: string[]): CommandResult;
13
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/commands/router.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAoBvE"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Command Router (Phase 3)
3
+ *
4
+ * Routes commands to handlers.
5
+ * All output goes through EventBus (not direct feed manipulation).
6
+ */
7
+ import { eventBus } from '../core/eventBus.js';
8
+ import { feedStore } from '../state/feedModel.js';
9
+ import { exitResult, noOpResult } from './commandResult.js';
10
+ /**
11
+ * Route a command
12
+ * Commands emit events through EventBus, not directly to feed
13
+ */
14
+ export function routeCommand(cmd, args) {
15
+ const command = cmd.toLowerCase().trim();
16
+ switch (command) {
17
+ case 'help':
18
+ return handleHelp();
19
+ case 'clear':
20
+ return handleClear();
21
+ case 'exit':
22
+ case 'quit':
23
+ return handleExit();
24
+ case 'home':
25
+ return handleHome();
26
+ default:
27
+ return handleUnknown(cmd);
28
+ }
29
+ }
30
+ /**
31
+ * Handle help command
32
+ * Emits event through EventBus
33
+ */
34
+ function handleHelp() {
35
+ eventBus.emitTag('SYS', 'COMMANDS: help, clear, exit, home', 'INFO');
36
+ return noOpResult();
37
+ }
38
+ /**
39
+ * Handle clear command
40
+ * Clears feed store, then emits event
41
+ */
42
+ function handleClear() {
43
+ feedStore.clear();
44
+ eventBus.emitTag('SYS', 'FEED CLEARED', 'INFO');
45
+ return noOpResult();
46
+ }
47
+ /**
48
+ * Handle exit command
49
+ */
50
+ function handleExit() {
51
+ return exitResult();
52
+ }
53
+ /**
54
+ * Handle home command
55
+ * Emits event through EventBus
56
+ */
57
+ function handleHome() {
58
+ eventBus.emitTag('SYS', 'HOME', 'INFO');
59
+ return noOpResult();
60
+ }
61
+ /**
62
+ * Handle unknown command
63
+ * Emits error event through EventBus
64
+ */
65
+ function handleUnknown(cmd) {
66
+ eventBus.emitTag('ERR', `UNKNOWN COMMAND: ${cmd} (try: help)`, 'ERROR');
67
+ return noOpResult();
68
+ }
69
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../../src/ui/v3/commands/router.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE5D;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAAc;IACtD,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAEzC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,UAAU,EAAE,CAAC;QAEtB,KAAK,OAAO;YACV,OAAO,WAAW,EAAE,CAAC;QAEvB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,UAAU,EAAE,CAAC;QAEtB,KAAK,MAAM;YACT,OAAO,UAAU,EAAE,CAAC;QAEtB;YACE,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU;IACjB,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,mCAAmC,EAAE,MAAM,CAAC,CAAC;IACrE,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW;IAClB,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAChD,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,SAAS,UAAU;IACjB,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU;IACjB,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,GAAW;IAChC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,cAAc,EAAE,OAAO,CAAC,CAAC;IACxE,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Event Type
3
+ *
4
+ * Minimal event interface for the EventBus system.
5
+ */
6
+ export type EventTag = 'CMD' | 'SYS' | 'ERR' | 'NET' | 'DB' | 'SEC' | 'RUN';
7
+ export type EventLevel = 'INFO' | 'WARN' | 'ERROR';
8
+ export interface Event {
9
+ id: string;
10
+ ts: number;
11
+ tag: EventTag;
12
+ level: EventLevel;
13
+ message: string;
14
+ }
15
+ /**
16
+ * Event input (without id and ts - will be assigned)
17
+ */
18
+ export type EventInput = Omit<Event, 'id' | 'ts'>;
19
+ //# sourceMappingURL=event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/core/event.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;AAE5E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Event Type
3
+ *
4
+ * Minimal event interface for the EventBus system.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.js","sourceRoot":"","sources":["../../../../src/ui/v3/core/event.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * EventBus
3
+ *
4
+ * Central event system for the TUI.
5
+ * All output goes through the EventBus.
6
+ */
7
+ import type { Event, EventInput, EventTag, EventLevel } from './event.js';
8
+ type Subscriber = (event: Event) => void;
9
+ declare class EventBus {
10
+ private subscribers;
11
+ private eventCounter;
12
+ /**
13
+ * Emit an event
14
+ * Normalizes the event (assigns id + ts) and calls all subscribers synchronously
15
+ */
16
+ emit(eventInput: EventInput | Event): void;
17
+ /**
18
+ * Subscribe to events
19
+ * Returns unsubscribe function
20
+ */
21
+ subscribe(fn: Subscriber): () => void;
22
+ /**
23
+ * Helper: emit with tag and message
24
+ */
25
+ emitTag(tag: EventTag, message: string, level?: EventLevel): void;
26
+ /**
27
+ * Get subscriber count (for debugging)
28
+ */
29
+ getSubscriberCount(): number;
30
+ }
31
+ export declare const eventBus: EventBus;
32
+ export {};
33
+ //# sourceMappingURL=eventBus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventBus.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/core/eventBus.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1E,KAAK,UAAU,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAEzC,cAAM,QAAQ;IACZ,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,YAAY,CAAK;IAEzB;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,KAAK,GAAG,IAAI;IA+B1C;;;OAGG;IACH,SAAS,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,IAAI;IASrC;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI;IAejE;;OAEG;IACH,kBAAkB,IAAI,MAAM;CAG7B;AAGD,eAAO,MAAM,QAAQ,UAAiB,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * EventBus
3
+ *
4
+ * Central event system for the TUI.
5
+ * All output goes through the EventBus.
6
+ */
7
+ class EventBus {
8
+ subscribers = new Set();
9
+ eventCounter = 0; // Monotonic counter for IDs
10
+ /**
11
+ * Emit an event
12
+ * Normalizes the event (assigns id + ts) and calls all subscribers synchronously
13
+ */
14
+ emit(eventInput) {
15
+ let event;
16
+ // If already has id and ts, use as-is
17
+ if ('id' in eventInput && 'ts' in eventInput) {
18
+ event = eventInput;
19
+ }
20
+ else {
21
+ // Normalize: assign id and ts
22
+ this.eventCounter++;
23
+ event = {
24
+ id: `evt-${this.eventCounter}`,
25
+ ts: Date.now(),
26
+ ...eventInput,
27
+ };
28
+ }
29
+ // Call all subscribers synchronously
30
+ this.subscribers.forEach(subscriber => {
31
+ try {
32
+ subscriber(event);
33
+ }
34
+ catch (error) {
35
+ // Don't let subscriber errors break the bus
36
+ // In TUI mode, we can't log, so we silently continue
37
+ // In debug mode, we could log to stderr
38
+ if (process.env.DEBUG_NO_TUI === '1') {
39
+ console.error('EventBus subscriber error:', error);
40
+ }
41
+ }
42
+ });
43
+ }
44
+ /**
45
+ * Subscribe to events
46
+ * Returns unsubscribe function
47
+ */
48
+ subscribe(fn) {
49
+ this.subscribers.add(fn);
50
+ // Return unsubscribe function
51
+ return () => {
52
+ this.subscribers.delete(fn);
53
+ };
54
+ }
55
+ /**
56
+ * Helper: emit with tag and message
57
+ */
58
+ emitTag(tag, message, level) {
59
+ // Infer level from tag if not provided
60
+ const inferredLevel = level || (tag === 'ERR' ? 'ERROR' :
61
+ tag === 'SYS' ? 'INFO' :
62
+ 'INFO');
63
+ this.emit({
64
+ tag,
65
+ level: inferredLevel,
66
+ message,
67
+ });
68
+ }
69
+ /**
70
+ * Get subscriber count (for debugging)
71
+ */
72
+ getSubscriberCount() {
73
+ return this.subscribers.size;
74
+ }
75
+ }
76
+ // Singleton instance
77
+ export const eventBus = new EventBus();
78
+ //# sourceMappingURL=eventBus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventBus.js","sourceRoot":"","sources":["../../../../src/ui/v3/core/eventBus.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,QAAQ;IACJ,WAAW,GAAoB,IAAI,GAAG,EAAE,CAAC;IACzC,YAAY,GAAG,CAAC,CAAC,CAAC,4BAA4B;IAEtD;;;OAGG;IACH,IAAI,CAAC,UAA8B;QACjC,IAAI,KAAY,CAAC;QAEjB,sCAAsC;QACtC,IAAI,IAAI,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,EAAE,CAAC;YAC7C,KAAK,GAAG,UAAmB,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,8BAA8B;YAC9B,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,KAAK,GAAG;gBACN,EAAE,EAAE,OAAO,IAAI,CAAC,YAAY,EAAE;gBAC9B,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,GAAG,UAAU;aACd,CAAC;QACJ,CAAC;QAED,qCAAqC;QACrC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YACpC,IAAI,CAAC;gBACH,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,4CAA4C;gBAC5C,qDAAqD;gBACrD,wCAAwC;gBACxC,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,EAAE,CAAC;oBACrC,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,EAAc;QACtB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEzB,8BAA8B;QAC9B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,GAAa,EAAE,OAAe,EAAE,KAAkB;QACxD,uCAAuC;QACvC,MAAM,aAAa,GAAe,KAAK,IAAI,CACzC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACzB,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACxB,MAAM,CACP,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC;YACR,GAAG;YACH,KAAK,EAAE,aAAa;YACpB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IAC/B,CAAC;CACF;AAED,qBAAqB;AACrB,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 4Runr Terminal UI V3 - Main Entry
4
+ *
5
+ * Phase 1: Layout Skeleton + Dedicated Command Line
6
+ */
7
+ export { startPhase1Runtime } from './ui/phase1Runtime.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/v3/index.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 4Runr Terminal UI V3 - Main Entry
4
+ *
5
+ * Phase 1: Layout Skeleton + Dedicated Command Line
6
+ */
7
+ // Export for use as a library
8
+ export { startPhase1Runtime } from './ui/phase1Runtime.js';
9
+ // If run directly (not imported), start the TUI
10
+ const isMainModule = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, '/')}` ||
11
+ process.argv[1]?.endsWith('index.js') ||
12
+ process.argv[1]?.endsWith('index.ts');
13
+ if (isMainModule) {
14
+ // Check for NO_TUI mode
15
+ const noTUI = process.env.NO_TUI === '1' || process.argv.includes('--mode=print');
16
+ if (noTUI) {
17
+ // NO_TUI fallback mode (for CI/SSH)
18
+ console.log('4Runr OS UI v3 (print mode)');
19
+ process.exit(0);
20
+ }
21
+ else {
22
+ // TUI mode (Phase 1)
23
+ const { startPhase1Runtime } = await import('./ui/phase1Runtime.js');
24
+ startPhase1Runtime().catch((error) => {
25
+ console.error('FATAL: TUI failed to start:', error);
26
+ process.exit(1);
27
+ });
28
+ }
29
+ }
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/v3/index.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,8BAA8B;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,gDAAgD;AAChD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE;IACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;AAE3D,IAAI,YAAY,EAAE,CAAC;IACjB,wBAAwB;IACxB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAElF,IAAI,KAAK,EAAE,CAAC;QACV,oCAAoC;QACpC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,qBAAqB;QACrB,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACrE,kBAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACnC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Default UiState (Phase 4)
3
+ *
4
+ * Initial state before collectors run.
5
+ * All fields start as UNAVAILABLE.
6
+ */
7
+ import type { UiState } from './uiState.js';
8
+ export declare const defaultUiState: UiState;
9
+ //# sourceMappingURL=defaultState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultState.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/state/defaultState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,eAAO,MAAM,cAAc,EAAE,OAK5B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Default UiState (Phase 4)
3
+ *
4
+ * Initial state before collectors run.
5
+ * All fields start as UNAVAILABLE.
6
+ */
7
+ import { unavailable } from './value.js';
8
+ export const defaultUiState = {
9
+ resources: unavailable('Not initialized', 'Waiting for first collection cycle'),
10
+ };
11
+ //# sourceMappingURL=defaultState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultState.js","sourceRoot":"","sources":["../../../../src/ui/v3/state/defaultState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,CAAC,MAAM,cAAc,GAAY;IACrC,SAAS,EAAE,WAAW,CACpB,iBAAiB,EACjB,oCAAoC,CACrC;CACF,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Operations Feed Model (Phase 3)
3
+ *
4
+ * Feed store that subscribes to EventBus.
5
+ * All events flow through EventBus → feedStore.
6
+ */
7
+ import type { Event } from '../core/event.js';
8
+ /**
9
+ * Feed store (singleton)
10
+ * Subscribes to EventBus on initialization
11
+ */
12
+ declare class FeedStore {
13
+ private events;
14
+ private maxEvents;
15
+ private unsubscribe;
16
+ constructor();
17
+ /**
18
+ * Add event to feed (called by EventBus subscription)
19
+ */
20
+ private append;
21
+ /**
22
+ * Clear all events
23
+ * Does not break subscription - feed continues receiving new events
24
+ */
25
+ clear(): void;
26
+ /**
27
+ * Get all events
28
+ */
29
+ getAll(): Event[];
30
+ /**
31
+ * Get latest N events
32
+ */
33
+ getLast(count: number): Event[];
34
+ /**
35
+ * Get event count
36
+ */
37
+ getCount(): number;
38
+ /**
39
+ * Cleanup (unsubscribe from EventBus)
40
+ */
41
+ destroy(): void;
42
+ }
43
+ export declare const feedStore: FeedStore;
44
+ /**
45
+ * Format timestamp (number) to HH:MM:SS
46
+ */
47
+ export declare function formatTimestamp(ts: number): string;
48
+ export {};
49
+ //# sourceMappingURL=feedModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedModel.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/state/feedModel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;GAGG;AACH,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,WAAW,CAA6B;;IAShD;;OAEG;IACH,OAAO,CAAC,MAAM;IASd;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,MAAM,IAAI,KAAK,EAAE;IAIjB;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE;IAI/B;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC;AAEzC;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAUlD"}