rax-flow 0.1.5 → 0.1.7

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 (223) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.js +27 -3
  3. package/dist/bin.js.map +1 -1
  4. package/dist/hub/__tests__/commands.test.d.ts.map +1 -0
  5. package/dist/hub/__tests__/commands.test.js +72 -0
  6. package/dist/hub/__tests__/commands.test.js.map +1 -0
  7. package/dist/hub/__tests__/history.test.d.ts.map +1 -0
  8. package/dist/hub/__tests__/history.test.js +119 -0
  9. package/dist/hub/__tests__/history.test.js.map +1 -0
  10. package/dist/hub/__tests__/parser.test.d.ts.map +1 -0
  11. package/dist/hub/__tests__/parser.test.js +92 -0
  12. package/dist/hub/__tests__/parser.test.js.map +1 -0
  13. package/dist/hub/chat/ChatApp.d.ts +2 -0
  14. package/dist/hub/chat/ChatApp.d.ts.map +1 -0
  15. package/dist/hub/chat/ChatApp.js +146 -0
  16. package/dist/hub/chat/ChatApp.js.map +1 -0
  17. package/dist/hub/chat/components/ChatInput.d.ts +9 -0
  18. package/dist/hub/chat/components/ChatInput.d.ts.map +1 -0
  19. package/dist/hub/chat/components/ChatInput.js +19 -0
  20. package/dist/hub/chat/components/ChatInput.js.map +1 -0
  21. package/dist/hub/chat/components/MessageList.d.ts +7 -0
  22. package/dist/hub/chat/components/MessageList.d.ts.map +1 -0
  23. package/dist/hub/chat/components/MessageList.js +6 -0
  24. package/dist/hub/chat/components/MessageList.js.map +1 -0
  25. package/dist/hub/chat/context.d.ts.map +1 -0
  26. package/dist/hub/chat/context.js +42 -0
  27. package/dist/hub/chat/context.js.map +1 -0
  28. package/dist/hub/chat/hooks/useChatHistory.d.ts +7 -0
  29. package/dist/hub/chat/hooks/useChatHistory.d.ts.map +1 -0
  30. package/dist/hub/chat/hooks/useChatHistory.js +31 -0
  31. package/dist/hub/chat/hooks/useChatHistory.js.map +1 -0
  32. package/dist/hub/chat/index.d.ts.map +1 -0
  33. package/dist/hub/chat/index.js +7 -0
  34. package/dist/hub/chat/index.js.map +1 -0
  35. package/dist/hub/chat/intent-parser.d.ts.map +1 -0
  36. package/dist/hub/chat/intent-parser.js +48 -0
  37. package/dist/hub/chat/intent-parser.js.map +1 -0
  38. package/dist/hub/chat/types.d.ts.map +1 -0
  39. package/dist/hub/chat/types.js +2 -0
  40. package/dist/hub/chat/types.js.map +1 -0
  41. package/dist/hub/commands/agents.d.ts.map +1 -0
  42. package/dist/hub/commands/agents.js +36 -0
  43. package/dist/hub/commands/agents.js.map +1 -0
  44. package/dist/hub/commands/index.d.ts.map +1 -0
  45. package/dist/hub/commands/index.js +120 -0
  46. package/dist/hub/commands/index.js.map +1 -0
  47. package/dist/hub/commands/logs.d.ts.map +1 -0
  48. package/dist/hub/commands/logs.js +53 -0
  49. package/dist/hub/commands/logs.js.map +1 -0
  50. package/dist/hub/commands/memory.d.ts.map +1 -0
  51. package/dist/hub/commands/memory.js +40 -0
  52. package/dist/hub/commands/memory.js.map +1 -0
  53. package/dist/hub/commands/metrics.d.ts.map +1 -0
  54. package/dist/hub/commands/metrics.js +35 -0
  55. package/dist/hub/commands/metrics.js.map +1 -0
  56. package/dist/hub/commands/providers.d.ts.map +1 -0
  57. package/dist/hub/commands/providers.js +26 -0
  58. package/dist/hub/commands/providers.js.map +1 -0
  59. package/dist/hub/commands/run.d.ts.map +1 -0
  60. package/dist/hub/commands/run.js +31 -0
  61. package/dist/hub/commands/run.js.map +1 -0
  62. package/dist/hub/commands/status.d.ts.map +1 -0
  63. package/dist/hub/commands/status.js +61 -0
  64. package/dist/hub/commands/status.js.map +1 -0
  65. package/dist/hub/commands/workflows.d.ts.map +1 -0
  66. package/dist/hub/commands/workflows.js +45 -0
  67. package/dist/hub/commands/workflows.js.map +1 -0
  68. package/dist/hub/config-loader.d.ts.map +1 -0
  69. package/dist/hub/config-loader.js +27 -0
  70. package/dist/hub/config-loader.js.map +1 -0
  71. package/dist/hub/event-listener.d.ts.map +1 -0
  72. package/dist/hub/event-listener.js +8 -0
  73. package/dist/hub/event-listener.js.map +1 -0
  74. package/dist/hub/history.d.ts.map +1 -0
  75. package/dist/hub/history.js +59 -0
  76. package/dist/hub/history.js.map +1 -0
  77. package/dist/hub/index.d.ts.map +1 -0
  78. package/dist/hub/index.js +102 -0
  79. package/dist/hub/index.js.map +1 -0
  80. package/dist/hub/parser.d.ts.map +1 -0
  81. package/dist/hub/parser.js +98 -0
  82. package/dist/hub/parser.js.map +1 -0
  83. package/dist/hub/styles/borders.d.ts.map +1 -0
  84. package/dist/hub/styles/borders.js +64 -0
  85. package/dist/hub/styles/borders.js.map +1 -0
  86. package/dist/hub/styles/colors.d.ts.map +1 -0
  87. package/dist/hub/styles/colors.js +115 -0
  88. package/dist/hub/styles/colors.js.map +1 -0
  89. package/dist/hub/styles/typography.d.ts.map +1 -0
  90. package/dist/hub/styles/typography.js +60 -0
  91. package/dist/hub/styles/typography.js.map +1 -0
  92. package/dist/hub/tui/App.d.ts +2 -0
  93. package/dist/hub/tui/App.d.ts.map +1 -0
  94. package/dist/hub/tui/App.js +53 -0
  95. package/dist/hub/tui/App.js.map +1 -0
  96. package/dist/hub/tui/components/AgentQueue.d.ts +6 -0
  97. package/dist/hub/tui/components/AgentQueue.d.ts.map +1 -0
  98. package/dist/hub/tui/components/AgentQueue.js +20 -0
  99. package/dist/hub/tui/components/AgentQueue.js.map +1 -0
  100. package/dist/hub/tui/components/DAGPanel.d.ts +16 -0
  101. package/dist/hub/tui/components/DAGPanel.d.ts.map +1 -0
  102. package/dist/hub/tui/components/DAGPanel.js +51 -0
  103. package/dist/hub/tui/components/DAGPanel.js.map +1 -0
  104. package/dist/hub/tui/components/Header.d.ts +7 -0
  105. package/dist/hub/tui/components/Header.d.ts.map +1 -0
  106. package/dist/hub/tui/components/Header.js +17 -0
  107. package/dist/hub/tui/components/Header.js.map +1 -0
  108. package/dist/hub/tui/components/LogsPanel.d.ts +6 -0
  109. package/dist/hub/tui/components/LogsPanel.d.ts.map +1 -0
  110. package/dist/hub/tui/components/LogsPanel.js +26 -0
  111. package/dist/hub/tui/components/LogsPanel.js.map +1 -0
  112. package/dist/hub/tui/components/StatusBar.d.ts +8 -0
  113. package/dist/hub/tui/components/StatusBar.d.ts.map +1 -0
  114. package/dist/hub/tui/components/StatusBar.js +7 -0
  115. package/dist/hub/tui/components/StatusBar.js.map +1 -0
  116. package/dist/hub/tui/hooks/useEvents.d.ts +2 -0
  117. package/dist/hub/tui/hooks/useEvents.d.ts.map +1 -0
  118. package/dist/hub/tui/hooks/useEvents.js +13 -0
  119. package/dist/hub/tui/hooks/useEvents.js.map +1 -0
  120. package/dist/hub/tui/index.d.ts.map +1 -0
  121. package/dist/hub/tui/index.js +7 -0
  122. package/dist/hub/tui/index.js.map +1 -0
  123. package/dist/hub/tui/types.d.ts.map +1 -0
  124. package/dist/hub/tui/types.js +2 -0
  125. package/dist/hub/tui/types.js.map +1 -0
  126. package/dist/hub/types.d.ts.map +1 -0
  127. package/dist/hub/types.js +2 -0
  128. package/dist/hub/types.js.map +1 -0
  129. package/dist/tui/App.d.ts +2 -0
  130. package/dist/tui/App.d.ts.map +1 -0
  131. package/dist/tui/App.js +31 -0
  132. package/dist/tui/App.js.map +1 -0
  133. package/dist/tui/components/ChatPanel.d.ts +14 -0
  134. package/dist/tui/components/ChatPanel.d.ts.map +1 -0
  135. package/dist/tui/components/ChatPanel.js +30 -0
  136. package/dist/tui/components/ChatPanel.js.map +1 -0
  137. package/dist/tui/components/Header.d.ts +9 -0
  138. package/dist/tui/components/Header.d.ts.map +1 -0
  139. package/dist/tui/components/Header.js +17 -0
  140. package/dist/tui/components/Header.js.map +1 -0
  141. package/dist/tui/components/InputBar.d.ts +8 -0
  142. package/dist/tui/components/InputBar.d.ts.map +1 -0
  143. package/dist/tui/components/InputBar.js +16 -0
  144. package/dist/tui/components/InputBar.js.map +1 -0
  145. package/dist/tui/components/StatusPanel.d.ts +20 -0
  146. package/dist/tui/components/StatusPanel.d.ts.map +1 -0
  147. package/dist/tui/components/StatusPanel.js +20 -0
  148. package/dist/tui/components/StatusPanel.js.map +1 -0
  149. package/dist/tui/hooks/useAppState.d.ts +38 -0
  150. package/dist/tui/hooks/useAppState.d.ts.map +1 -0
  151. package/dist/tui/hooks/useAppState.js +127 -0
  152. package/dist/tui/hooks/useAppState.js.map +1 -0
  153. package/dist/tui/index.d.ts +3 -0
  154. package/dist/tui/index.d.ts.map +1 -0
  155. package/dist/tui/index.js +8 -0
  156. package/dist/tui/index.js.map +1 -0
  157. package/package.json +17 -11
  158. package/src/bin.ts +29 -3
  159. package/src/hub/__tests__/commands.test.ts +84 -0
  160. package/src/hub/__tests__/history.test.ts +137 -0
  161. package/src/hub/__tests__/parser.test.ts +105 -0
  162. package/src/hub/commands/agents.ts +53 -0
  163. package/src/hub/commands/index.ts +137 -0
  164. package/src/hub/commands/logs.ts +70 -0
  165. package/src/hub/commands/memory.ts +47 -0
  166. package/src/hub/commands/metrics.ts +49 -0
  167. package/src/hub/commands/providers.ts +39 -0
  168. package/src/hub/commands/run.ts +37 -0
  169. package/src/hub/commands/status.ts +69 -0
  170. package/src/hub/commands/workflows.ts +64 -0
  171. package/src/hub/config-loader.ts +37 -0
  172. package/src/hub/event-listener.ts +13 -0
  173. package/src/hub/history.ts +66 -0
  174. package/src/hub/index.ts +120 -0
  175. package/src/hub/parser.ts +107 -0
  176. package/src/hub/styles/borders.ts +74 -0
  177. package/src/hub/styles/colors.ts +129 -0
  178. package/src/hub/styles/typography.ts +68 -0
  179. package/src/hub/types.ts +31 -0
  180. package/src/tui/App.tsx +61 -0
  181. package/src/tui/components/ChatPanel.tsx +79 -0
  182. package/src/tui/components/Header.tsx +53 -0
  183. package/src/tui/components/InputBar.tsx +55 -0
  184. package/src/tui/components/StatusPanel.tsx +85 -0
  185. package/src/tui/hooks/useAppState.ts +168 -0
  186. package/src/tui/index.ts +9 -0
  187. package/tsconfig.json +19 -3
  188. package/tsconfig.tsbuildinfo +1 -0
  189. package/dist/benchmark.d.ts +0 -10
  190. package/dist/bin.d.ts +0 -3
  191. package/dist/bootstrap.d.ts +0 -8
  192. package/dist/bridge-adapter-templates.d.ts +0 -4
  193. package/dist/bridge-test.d.ts +0 -7
  194. package/dist/dashboard.d.ts +0 -4
  195. package/dist/doctor.d.ts +0 -6
  196. package/dist/evolve.d.ts +0 -7
  197. package/dist/host-init-templates.d.ts +0 -16
  198. package/dist/index.d.ts +0 -11
  199. package/dist/init-host.d.ts +0 -10
  200. package/dist/install.d.ts +0 -8
  201. package/dist/run.d.ts +0 -16
  202. package/dist/styles.d.ts +0 -12
  203. package/dist/vendor-manifests.d.ts +0 -22
  204. package/package/dashboard/index.html +0 -420
  205. package/package/package.json +0 -28
  206. package/package/src/benchmark.ts +0 -156
  207. package/package/src/bin.ts +0 -127
  208. package/package/src/bootstrap.ts +0 -36
  209. package/package/src/bridge-adapter-templates.ts +0 -181
  210. package/package/src/bridge-test.ts +0 -107
  211. package/package/src/dashboard.ts +0 -51
  212. package/package/src/doctor.ts +0 -92
  213. package/package/src/evolve.ts +0 -74
  214. package/package/src/host-init-templates.ts +0 -134
  215. package/package/src/index.ts +0 -10
  216. package/package/src/init-host.ts +0 -285
  217. package/package/src/install.ts +0 -118
  218. package/package/src/run.ts +0 -317
  219. package/package/src/styles.ts +0 -12
  220. package/package/src/vendor-manifests.ts +0 -113
  221. package/package/src/ws-relay.ts +0 -156
  222. package/package/tsconfig.json +0 -12
  223. package/rax-flow-0.1.1.tgz +0 -0
@@ -0,0 +1,68 @@
1
+ // RAX-FLOW Design System - Typography
2
+ // Space Grotesk for titles, Space Mono for system text
3
+
4
+ export const typography = {
5
+ // Font families
6
+ primary: "Space Grotesk",
7
+ monospace: "Space Mono",
8
+
9
+ // Font weights
10
+ weights: {
11
+ light: 300,
12
+ regular: 400,
13
+ medium: 500,
14
+ bold: 700,
15
+ },
16
+
17
+ // Sizes (in terminal columns roughly)
18
+ sizes: {
19
+ hero: 4, // text-4xl
20
+ section: 2, // text-2xl
21
+ label: 0, // text-[10px]
22
+ body: 1, // text-sm
23
+ code: 0, // text-xs
24
+ status: -1, // text-[9px]
25
+ agent: 0, // text-xs
26
+ provider: -1, // text-[9px]
27
+ },
28
+
29
+ // Tracking (letter-spacing)
30
+ tracking: {
31
+ none: "",
32
+ tight: "",
33
+ normal: "",
34
+ wide: " ",
35
+ label: " ", // 0.15em equivalent in monospace
36
+ },
37
+ };
38
+
39
+ // Text formatting utilities for terminal
40
+ export function upperCase(text: string): string {
41
+ return text.toUpperCase();
42
+ }
43
+
44
+ export function padCenter(text: string, width: number): string {
45
+ const padding = Math.max(0, width - text.length);
46
+ const leftPad = Math.floor(padding / 2);
47
+ const rightPad = padding - leftPad;
48
+ return " ".repeat(leftPad) + text + " ".repeat(rightPad);
49
+ }
50
+
51
+ export function padRight(text: string, width: number): string {
52
+ const padding = Math.max(0, width - text.length);
53
+ return text + " ".repeat(padding);
54
+ }
55
+
56
+ export function padLeft(text: string, width: number): string {
57
+ const padding = Math.max(0, width - text.length);
58
+ return " ".repeat(padding) + text;
59
+ }
60
+
61
+ export function truncate(text: string, maxLength: number): string {
62
+ if (text.length <= maxLength) return text;
63
+ return text.slice(0, maxLength - 3) + "...";
64
+ }
65
+
66
+ export function formatLabel(text: string): string {
67
+ return upperCase(text).split("").join(" ");
68
+ }
@@ -0,0 +1,31 @@
1
+ export interface HubOptions {
2
+ cwd: string;
3
+ config?: HubConfig;
4
+ }
5
+
6
+ export interface HubConfig {
7
+ project?: string;
8
+ providers?: string[];
9
+ theme?: 'industrial' | 'minimal' | 'high-contrast';
10
+ }
11
+
12
+ export interface Command {
13
+ name: string;
14
+ args: string[];
15
+ flags: Record<string, string | boolean>;
16
+ }
17
+
18
+ export interface HubContext {
19
+ currentWorkflow?: string;
20
+ currentRun?: string;
21
+ config: HubConfig;
22
+ }
23
+
24
+ export type CommandHandler = (args: string[], flags: Record<string, string | boolean>, context: HubContext) => Promise<void>;
25
+
26
+ export interface CommandDefinition {
27
+ name: string;
28
+ description: string;
29
+ handler: CommandHandler;
30
+ aliases?: string[];
31
+ }
@@ -0,0 +1,61 @@
1
+ import React from "react";
2
+ import { Box, Text, useApp, useInput } from "ink";
3
+ import { Header } from "./components/Header.js";
4
+ import { ChatPanel } from "./components/ChatPanel.js";
5
+ import { StatusPanel } from "./components/StatusPanel.js";
6
+ import { InputBar } from "./components/InputBar.js";
7
+ import { useAppState } from "./hooks/useAppState.js";
8
+
9
+ export function App() {
10
+ const { exit } = useApp();
11
+ const { state, dispatch, processCommand } = useAppState();
12
+
13
+ useInput((input, key) => {
14
+ if (key.ctrl && input === "c") {
15
+ exit();
16
+ }
17
+ if (key.ctrl && input === "d") {
18
+ exit();
19
+ }
20
+ });
21
+
22
+ const handleSubmit = (input: string) => {
23
+ const trimmed = input.trim();
24
+ if (!trimmed) return;
25
+
26
+ if (trimmed === "exit" || trimmed === "quit") {
27
+ exit();
28
+ return;
29
+ }
30
+
31
+ processCommand(trimmed);
32
+ };
33
+
34
+ return (
35
+ <Box flexDirection="column" height="100%" width="100%">
36
+ <Header
37
+ projectName={state.projectName}
38
+ agentCount={state.agentCount}
39
+ provider={state.provider}
40
+ status={state.status}
41
+ />
42
+ <Box flexGrow={1} flexDirection="row" width="100%">
43
+ <ChatPanel
44
+ messages={state.messages}
45
+ isProcessing={state.isProcessing}
46
+ />
47
+ <StatusPanel
48
+ agents={state.agents}
49
+ providers={state.providers}
50
+ fitness={state.fitness}
51
+ currentWorkflow={state.currentWorkflow}
52
+ />
53
+ </Box>
54
+ <InputBar
55
+ onSubmit={handleSubmit}
56
+ suggestions={state.suggestions}
57
+ isProcessing={state.isProcessing}
58
+ />
59
+ </Box>
60
+ );
61
+ }
@@ -0,0 +1,79 @@
1
+ import React from "react";
2
+ import { Box, Text, useInput } from "ink";
3
+
4
+ interface Message {
5
+ id: string;
6
+ type: "user" | "system" | "agent" | "error" | "success";
7
+ content: string;
8
+ timestamp: Date;
9
+ agent?: string;
10
+ }
11
+
12
+ interface ChatPanelProps {
13
+ messages: Message[];
14
+ isProcessing: boolean;
15
+ }
16
+
17
+ function formatTime(date: Date): string {
18
+ return date.toLocaleTimeString("fr-FR", {
19
+ hour: "2-digit",
20
+ minute: "2-digit",
21
+ second: "2-digit",
22
+ });
23
+ }
24
+
25
+ function MessageItem({ message }: { message: Message; key?: string }) {
26
+ const typeColors: Record<string, string> = {
27
+ user: "cyan",
28
+ system: "gray",
29
+ agent: "#f97316",
30
+ error: "red",
31
+ success: "green",
32
+ };
33
+
34
+ const typeLabels: Record<string, string> = {
35
+ user: "YOU",
36
+ system: "SYS",
37
+ agent: message.agent || "AGENT",
38
+ error: "ERR",
39
+ success: "OK",
40
+ };
41
+
42
+ return (
43
+ <Box flexDirection="column" marginBottom={1}>
44
+ <Box flexDirection="row">
45
+ <Text color="gray" dimColor>[{formatTime(message.timestamp)}]</Text>
46
+ <Text color={typeColors[message.type]} bold> [{typeLabels[message.type]}]</Text>
47
+ {message.agent && <Text color="gray"> [{message.agent}]</Text>}
48
+ </Box>
49
+ <Text color="white">{message.content}</Text>
50
+ </Box>
51
+ );
52
+ }
53
+
54
+ export function ChatPanel({ messages, isProcessing }: ChatPanelProps) {
55
+ return (
56
+ <Box
57
+ flexDirection="column"
58
+ flexGrow={2}
59
+ borderStyle="single"
60
+ borderColor="gray"
61
+ paddingX={1}
62
+ >
63
+ <Box borderStyle="single" borderColor="#f97316" marginBottom={1}>
64
+ <Text color="#f97316" bold>CHAT</Text>
65
+ <Text color="gray"> — Tapez /help pour les commandes</Text>
66
+ </Box>
67
+ <Box flexDirection="column" flexGrow={1} overflow="hidden">
68
+ {messages.slice(-15).map((msg) => (
69
+ <MessageItem key={msg.id} message={msg} />
70
+ ))}
71
+ {isProcessing && (
72
+ <Box>
73
+ <Text color="yellow">● Processing...</Text>
74
+ </Box>
75
+ )}
76
+ </Box>
77
+ </Box>
78
+ );
79
+ }
@@ -0,0 +1,53 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+
4
+ interface HeaderProps {
5
+ projectName: string;
6
+ agentCount: number;
7
+ provider: string;
8
+ status: "ready" | "running" | "error";
9
+ }
10
+
11
+ export function Header({ projectName, agentCount, provider, status }: HeaderProps) {
12
+ const statusColors = {
13
+ ready: "green",
14
+ running: "yellow",
15
+ error: "red",
16
+ };
17
+
18
+ const statusText = {
19
+ ready: "READY",
20
+ running: "RUNNING",
21
+ error: "ERROR",
22
+ };
23
+
24
+ const statusIcon = status === "running" ? "▶" : status === "error" ? "✗" : "●";
25
+
26
+ return (
27
+ <Box
28
+ flexDirection="row"
29
+ justifyContent="space-between"
30
+ alignItems="center"
31
+ paddingX={1}
32
+ borderStyle="single"
33
+ borderColor="gray"
34
+ width="100%"
35
+ >
36
+ <Box flexDirection="row" alignItems="center">
37
+ <Text color="#f97316" bold>■</Text>
38
+ <Text color="white" bold> RAX-FLOW</Text>
39
+ <Text color="gray"> HUB</Text>
40
+ </Box>
41
+ <Box flexDirection="row" alignItems="center" gap={2}>
42
+ <Text color="gray">Project:</Text>
43
+ <Text color="cyan">{projectName}</Text>
44
+ <Text color="gray">│</Text>
45
+ <Text color="gray">Agents:</Text>
46
+ <Text color="green">{agentCount}/12</Text>
47
+ <Text color="gray">│</Text>
48
+ <Text color="gray">[{provider}]</Text>
49
+ <Text color={statusColors[status]}> {statusIcon} {statusText[status]}</Text>
50
+ </Box>
51
+ </Box>
52
+ );
53
+ }
@@ -0,0 +1,55 @@
1
+ import React, { useState } from "react";
2
+ import { Box, Text, useInput } from "ink";
3
+ import TextInput from "ink-text-input";
4
+
5
+ interface InputBarProps {
6
+ onSubmit: (input: string) => void;
7
+ suggestions: string[];
8
+ isProcessing: boolean;
9
+ }
10
+
11
+ export function InputBar({ onSubmit, suggestions, isProcessing }: InputBarProps) {
12
+ const [input, setInput] = useState("");
13
+
14
+ const handleSubmit = (value: string) => {
15
+ if (value.trim()) {
16
+ onSubmit(value);
17
+ setInput("");
18
+ }
19
+ };
20
+
21
+ const filteredSuggestions = suggestions.filter((s) =>
22
+ s.toLowerCase().startsWith(input.toLowerCase())
23
+ ).slice(0, 5);
24
+
25
+ return (
26
+ <Box flexDirection="column" borderStyle="single" borderColor="gray" paddingX={1}>
27
+ {input.startsWith("/") && filteredSuggestions.length > 0 && (
28
+ <Box flexDirection="row" marginBottom={1}>
29
+ {filteredSuggestions.map((s) => (
30
+ <Box key={s} marginRight={2}>
31
+ <Text color="cyan">{s}</Text>
32
+ </Box>
33
+ ))}
34
+ </Box>
35
+ )}
36
+ <Box flexDirection="row" alignItems="center">
37
+ <Text color="#f97316" bold>▶</Text>
38
+ <Box marginLeft={1} flexGrow={1}>
39
+ <TextInput
40
+ value={input}
41
+ onChange={setInput}
42
+ onSubmit={handleSubmit}
43
+ placeholder="Tapez /help ou votre prompt..."
44
+ showCursor={true}
45
+ />
46
+ </Box>
47
+ {isProcessing && <Text color="yellow"> ●</Text>}
48
+ </Box>
49
+ <Box flexDirection="row" marginTop={1}>
50
+ <Text color="gray" dimColor>[Ctrl+C] Quitter</Text>
51
+ <Text color="gray" dimColor> │ [/cmd] Commandes</Text>
52
+ </Box>
53
+ </Box>
54
+ );
55
+ }
@@ -0,0 +1,85 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+
4
+ interface Agent {
5
+ name: string;
6
+ role: string;
7
+ status: "idle" | "running" | "queued" | "done";
8
+ provider: string;
9
+ }
10
+
11
+ interface Provider {
12
+ name: string;
13
+ status: "active" | "idle";
14
+ latency: number;
15
+ }
16
+
17
+ interface StatusPanelProps {
18
+ agents: Agent[];
19
+ providers: Provider[];
20
+ fitness: number;
21
+ currentWorkflow: string | null;
22
+ }
23
+
24
+ const statusIcons: Record<string, { icon: string; color: string }> = {
25
+ idle: { icon: "○", color: "gray" },
26
+ running: { icon: "▶", color: "yellow" },
27
+ queued: { icon: "◐", color: "cyan" },
28
+ done: { icon: "●", color: "green" },
29
+ };
30
+
31
+ function AgentRow({ agent, key }: { agent: Agent; key?: string }) {
32
+ const { icon, color } = statusIcons[agent.status];
33
+ return (
34
+ <Box key={key} flexDirection="row" justifyContent="space-between">
35
+ <Text color={color}>{icon}</Text>
36
+ <Text color="white">{agent.name.slice(0, 12).padEnd(12)}</Text>
37
+ <Text color="gray">[{agent.provider}]</Text>
38
+ </Box>
39
+ );
40
+ }
41
+
42
+ function ProviderRow({ provider, key }: { provider: Provider; key?: string }) {
43
+ return (
44
+ <Box key={key} flexDirection="row" justifyContent="space-between">
45
+ <Text color={provider.status === "active" ? "green" : "gray"}>
46
+ {provider.status === "active" ? "●" : "○"}
47
+ </Text>
48
+ <Text color="white">{provider.name}</Text>
49
+ <Text color="gray">{provider.latency > 0 ? `${provider.latency}ms` : "--"}</Text>
50
+ </Box>
51
+ );
52
+ }
53
+
54
+ export function StatusPanel({ agents, providers, fitness, currentWorkflow }: StatusPanelProps) {
55
+ const fitnessColor = fitness >= 0.9 ? "green" : fitness >= 0.7 ? "yellow" : "red";
56
+
57
+ return (
58
+ <Box flexDirection="column" width={35} borderStyle="single" borderColor="gray">
59
+ <Box borderStyle="single" borderColor="#f97316" marginBottom={1}>
60
+ <Text color="#f97316" bold>STATUS</Text>
61
+ </Box>
62
+
63
+ <Box flexDirection="column" paddingX={1}>
64
+ <Text color="gray" bold>WORKFLOW</Text>
65
+ <Text color="white">{currentWorkflow || "Aucun"}</Text>
66
+ <Text color="gray">Fitness: </Text>
67
+ <Text color={fitnessColor} bold>{fitness.toFixed(2)}</Text>
68
+ </Box>
69
+
70
+ <Box flexDirection="column" paddingX={1} marginTop={1}>
71
+ <Text color="gray" bold>AGENTS</Text>
72
+ {agents.slice(0, 6).map((agent) => (
73
+ <AgentRow key={agent.name} agent={agent} />
74
+ ))}
75
+ </Box>
76
+
77
+ <Box flexDirection="column" paddingX={1} marginTop={1}>
78
+ <Text color="gray" bold>PROVIDERS</Text>
79
+ {providers.map((provider) => (
80
+ <ProviderRow key={provider.name} provider={provider} />
81
+ ))}
82
+ </Box>
83
+ </Box>
84
+ );
85
+ }
@@ -0,0 +1,168 @@
1
+ import { useState, useCallback } from "react";
2
+
3
+ interface Message {
4
+ id: string;
5
+ type: "user" | "system" | "agent" | "error" | "success";
6
+ content: string;
7
+ timestamp: Date;
8
+ agent?: string;
9
+ }
10
+
11
+ interface Agent {
12
+ name: string;
13
+ role: string;
14
+ status: "idle" | "running" | "queued" | "done";
15
+ provider: string;
16
+ }
17
+
18
+ interface Provider {
19
+ name: string;
20
+ status: "active" | "idle";
21
+ latency: number;
22
+ }
23
+
24
+ interface AppState {
25
+ projectName: string;
26
+ agentCount: number;
27
+ provider: string;
28
+ status: "ready" | "running" | "error";
29
+ messages: Message[];
30
+ agents: Agent[];
31
+ providers: Provider[];
32
+ fitness: number;
33
+ currentWorkflow: string | null;
34
+ suggestions: string[];
35
+ isProcessing: boolean;
36
+ }
37
+
38
+ const COMMAND_SUGGESTIONS = [
39
+ "/run", "/status", "/agents", "/providers", "/workflows",
40
+ "/logs", "/metrics", "/memory", "/help", "/exit",
41
+ ];
42
+
43
+ const DEFAULT_AGENTS: Agent[] = [
44
+ { name: "IntentClassifier", role: "Classify intent", status: "idle", provider: "H" },
45
+ { name: "TaskPlanner", role: "Decompose tasks", status: "idle", provider: "H" },
46
+ { name: "SpecAgent", role: "Write specs", status: "idle", provider: "H" },
47
+ { name: "CodeGenerator", role: "Generate code", status: "idle", provider: "H" },
48
+ { name: "TestAgent", role: "Run tests", status: "idle", provider: "H" },
49
+ { name: "FixAgent", role: "Fix issues", status: "idle", provider: "H" },
50
+ { name: "MutationAgent", role: "Evolve workflow", status: "idle", provider: "H" },
51
+ { name: "ValidatorAgent", role: "Validate outputs", status: "idle", provider: "H" },
52
+ ];
53
+
54
+ const DEFAULT_PROVIDERS: Provider[] = [
55
+ { name: "Host-Native", status: "active", latency: 12 },
56
+ { name: "Claude Code", status: "active", latency: 8 },
57
+ { name: "OpenCode", status: "idle", latency: 0 },
58
+ { name: "Anthropic", status: "idle", latency: 0 },
59
+ ];
60
+
61
+ function generateId(): string {
62
+ return Math.random().toString(36).slice(2, 9);
63
+ }
64
+
65
+ export function useAppState() {
66
+ const [state, setState] = useState<AppState>({
67
+ projectName: process.cwd().split("/").pop() || "project",
68
+ agentCount: 12,
69
+ provider: "HOST-NATIVE",
70
+ status: "ready",
71
+ messages: [
72
+ {
73
+ id: generateId(),
74
+ type: "system",
75
+ content: "■ RAX-FLOW HUB prêt. Tapez votre prompt ou /help pour les commandes.",
76
+ timestamp: new Date(),
77
+ },
78
+ ],
79
+ agents: DEFAULT_AGENTS,
80
+ providers: DEFAULT_PROVIDERS,
81
+ fitness: 0.87,
82
+ currentWorkflow: null,
83
+ suggestions: COMMAND_SUGGESTIONS,
84
+ isProcessing: false,
85
+ });
86
+
87
+ const addMessage = useCallback((type: Message["type"], content: string, agent?: string) => {
88
+ setState((prev: AppState) => ({
89
+ ...prev,
90
+ messages: [
91
+ ...prev.messages,
92
+ { id: generateId(), type, content, timestamp: new Date(), agent },
93
+ ],
94
+ }));
95
+ }, []);
96
+
97
+ const processCommand = useCallback((input: string) => {
98
+ if (input.startsWith("/")) {
99
+ const cmd = input.slice(1).toLowerCase();
100
+
101
+ switch (cmd) {
102
+ case "help":
103
+ addMessage("system", `Commandes: /run /status /agents /providers /workflows /logs /metrics /memory /exit`);
104
+ break;
105
+ case "status":
106
+ addMessage("system", `Orchestrator: ● ACTIVE | Fitness: ${state.fitness.toFixed(2)} | Agents: ${state.agents.filter((a: Agent) => a.status !== "idle").length}/8 actifs`);
107
+ break;
108
+ case "agents":
109
+ const agentList = state.agents.map((a: Agent) => `${a.status === "running" ? "▶" : "○"} ${a.name} [${a.provider}]`).join("\n");
110
+ addMessage("system", agentList);
111
+ break;
112
+ case "providers":
113
+ const providerList = state.providers.map((p: Provider) => `${p.status === "active" ? "●" : "○"} ${p.name} ${p.latency > 0 ? `(${p.latency}ms)` : ""}`).join("\n");
114
+ addMessage("system", providerList);
115
+ break;
116
+ case "exit":
117
+ case "quit":
118
+ addMessage("system", "À bientôt !");
119
+ break;
120
+ default:
121
+ if (cmd.startsWith("run ")) {
122
+ const prompt = cmd.slice(4);
123
+ setState((prev: AppState) => ({ ...prev, status: "running", isProcessing: true }));
124
+ addMessage("user", prompt);
125
+ addMessage("agent", "Analyse de l'intent...", "IntentClassifier");
126
+ setTimeout(() => {
127
+ addMessage("agent", `Intent détecté: code_generation`, "IntentClassifier");
128
+ addMessage("agent", "Décomposition en tâches...", "TaskPlanner");
129
+ setState((prev: AppState) => ({
130
+ ...prev,
131
+ status: "ready",
132
+ isProcessing: false,
133
+ fitness: Math.min(prev.fitness + 0.02, 0.99),
134
+ currentWorkflow: prompt,
135
+ agents: prev.agents.map((a: Agent, i: number) => ({
136
+ ...a,
137
+ status: i === 0 ? "done" as const : i === 1 ? "running" as const : "idle" as const,
138
+ })),
139
+ }));
140
+ }, 1500);
141
+ } else {
142
+ addMessage("error", `Commande inconnue: /${cmd}. Tapez /help pour l'aide.`);
143
+ }
144
+ }
145
+ } else {
146
+ setState((prev: AppState) => ({ ...prev, status: "running", isProcessing: true }));
147
+ addMessage("user", input);
148
+ addMessage("agent", "Analyse de l'intent...", "IntentClassifier");
149
+ setTimeout(() => {
150
+ addMessage("agent", `Intent détecté: code_generation`, "IntentClassifier");
151
+ addMessage("agent", "Exécution du workflow...", "Orchestrator");
152
+ setState((prev: AppState) => ({
153
+ ...prev,
154
+ status: "ready",
155
+ isProcessing: false,
156
+ fitness: Math.min(prev.fitness + 0.01, 0.99),
157
+ currentWorkflow: input,
158
+ }));
159
+ }, 2000);
160
+ }
161
+ }, [state, addMessage]);
162
+
163
+ return {
164
+ state,
165
+ dispatch: setState,
166
+ processCommand,
167
+ };
168
+ }
@@ -0,0 +1,9 @@
1
+ import { render } from "ink";
2
+ import React from "react";
3
+ import { App } from "./App.js";
4
+
5
+ export function startTUI() {
6
+ return render(React.createElement(App));
7
+ }
8
+
9
+ export { App } from "./App.js";
package/tsconfig.json CHANGED
@@ -5,8 +5,24 @@
5
5
  "outDir": "dist",
6
6
  "composite": true,
7
7
  "declaration": true,
8
- "declarationMap": true
8
+ "declarationMap": true,
9
+ "jsx": "react-jsx",
10
+ "jsxImportSource": "react",
11
+ "esModuleInterop": true
9
12
  },
10
- "include": ["src/**/*.ts"],
11
- "references": [{ "path": "../core" }, { "path": "../agents" }, { "path": "../providers" }]
13
+ "include": [
14
+ "src/**/*.ts",
15
+ "src/**/*.tsx"
16
+ ],
17
+ "references": [
18
+ {
19
+ "path": "../core"
20
+ },
21
+ {
22
+ "path": "../agents"
23
+ },
24
+ {
25
+ "path": "../providers"
26
+ }
27
+ ]
12
28
  }