rax-flow 0.1.8 → 0.2.0

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 (224) hide show
  1. package/dist/bin.js +8 -6
  2. package/dist/bin.js.map +1 -1
  3. package/dist/hub/commands/index.d.ts.map +1 -1
  4. package/dist/hub/commands/index.js +7 -4
  5. package/dist/hub/commands/index.js.map +1 -1
  6. package/dist/hub/event-listener.d.ts +6 -0
  7. package/dist/hub/event-listener.d.ts.map +1 -1
  8. package/dist/hub/event-listener.js +10 -6
  9. package/dist/hub/event-listener.js.map +1 -1
  10. package/dist/hub/index.d.ts.map +1 -1
  11. package/dist/hub/index.js +12 -0
  12. package/dist/hub/index.js.map +1 -1
  13. package/dist/setup/components/ApiKeyInput.d.ts +25 -0
  14. package/dist/setup/components/ApiKeyInput.d.ts.map +1 -0
  15. package/dist/setup/components/ApiKeyInput.js +54 -0
  16. package/dist/setup/components/ApiKeyInput.js.map +1 -0
  17. package/dist/setup/components/AsciiBanner.d.ts +22 -0
  18. package/dist/setup/components/AsciiBanner.d.ts.map +1 -0
  19. package/dist/setup/components/AsciiBanner.js +55 -0
  20. package/dist/setup/components/AsciiBanner.js.map +1 -0
  21. package/dist/setup/components/CliDetector.d.ts +17 -0
  22. package/dist/setup/components/CliDetector.d.ts.map +1 -0
  23. package/dist/setup/components/CliDetector.js +79 -0
  24. package/dist/setup/components/CliDetector.js.map +1 -0
  25. package/dist/setup/components/ModeSelector.d.ts +8 -0
  26. package/dist/setup/components/ModeSelector.d.ts.map +1 -0
  27. package/dist/setup/components/ModeSelector.js +76 -0
  28. package/dist/setup/components/ModeSelector.js.map +1 -0
  29. package/dist/setup/components/ProviderSelector.d.ts +18 -0
  30. package/dist/setup/components/ProviderSelector.d.ts.map +1 -0
  31. package/dist/setup/components/ProviderSelector.js +97 -0
  32. package/dist/setup/components/ProviderSelector.js.map +1 -0
  33. package/dist/setup/components/SetupWizard.d.ts +2 -0
  34. package/dist/setup/components/SetupWizard.d.ts.map +1 -0
  35. package/dist/setup/components/SetupWizard.js +212 -0
  36. package/dist/setup/components/SetupWizard.js.map +1 -0
  37. package/dist/setup/components/StepIndicator.d.ts +13 -0
  38. package/dist/setup/components/StepIndicator.d.ts.map +1 -0
  39. package/dist/setup/components/StepIndicator.js +18 -0
  40. package/dist/setup/components/StepIndicator.js.map +1 -0
  41. package/dist/setup/components/SuccessScreen.d.ts +18 -0
  42. package/dist/setup/components/SuccessScreen.d.ts.map +1 -0
  43. package/dist/setup/components/SuccessScreen.js +38 -0
  44. package/dist/setup/components/SuccessScreen.js.map +1 -0
  45. package/dist/setup/index.d.ts +12 -0
  46. package/dist/setup/index.d.ts.map +1 -0
  47. package/dist/setup/index.js +29 -0
  48. package/dist/setup/index.js.map +1 -0
  49. package/dist/setup/utils/cli-detection.d.ts +12 -0
  50. package/dist/setup/utils/cli-detection.d.ts.map +1 -0
  51. package/dist/setup/utils/cli-detection.js +83 -0
  52. package/dist/setup/utils/cli-detection.js.map +1 -0
  53. package/dist/setup/utils/config-writer.d.ts +43 -0
  54. package/dist/setup/utils/config-writer.d.ts.map +1 -0
  55. package/dist/setup/utils/config-writer.js +180 -0
  56. package/dist/setup/utils/config-writer.js.map +1 -0
  57. package/dist/tui/App.d.ts +2 -1
  58. package/dist/tui/App.d.ts.map +1 -1
  59. package/dist/tui/App.js +88 -20
  60. package/dist/tui/App.js.map +1 -1
  61. package/dist/tui/components/AgentStateIcon.d.ts +18 -0
  62. package/dist/tui/components/AgentStateIcon.d.ts.map +1 -0
  63. package/dist/tui/components/AgentStateIcon.js +57 -0
  64. package/dist/tui/components/AgentStateIcon.js.map +1 -0
  65. package/dist/tui/components/AnimatedBranch.d.ts +39 -0
  66. package/dist/tui/components/AnimatedBranch.d.ts.map +1 -0
  67. package/dist/tui/components/AnimatedBranch.js +64 -0
  68. package/dist/tui/components/AnimatedBranch.js.map +1 -0
  69. package/dist/tui/components/ChatPanel.d.ts +2 -1
  70. package/dist/tui/components/ChatPanel.d.ts.map +1 -1
  71. package/dist/tui/components/ChatPanel.js +47 -28
  72. package/dist/tui/components/ChatPanel.js.map +1 -1
  73. package/dist/tui/components/DAGPanel.d.ts +14 -2
  74. package/dist/tui/components/DAGPanel.d.ts.map +1 -1
  75. package/dist/tui/components/DAGPanel.js +48 -27
  76. package/dist/tui/components/DAGPanel.js.map +1 -1
  77. package/dist/tui/components/ExecutionTimeline.d.ts +34 -0
  78. package/dist/tui/components/ExecutionTimeline.d.ts.map +1 -0
  79. package/dist/tui/components/ExecutionTimeline.js +67 -0
  80. package/dist/tui/components/ExecutionTimeline.js.map +1 -0
  81. package/dist/tui/components/Header.d.ts +2 -1
  82. package/dist/tui/components/Header.d.ts.map +1 -1
  83. package/dist/tui/components/Header.js +26 -19
  84. package/dist/tui/components/Header.js.map +1 -1
  85. package/dist/tui/components/HelpOverlay.d.ts +2 -1
  86. package/dist/tui/components/HelpOverlay.d.ts.map +1 -1
  87. package/dist/tui/components/HelpOverlay.js +59 -41
  88. package/dist/tui/components/HelpOverlay.js.map +1 -1
  89. package/dist/tui/components/InputBar.d.ts +3 -1
  90. package/dist/tui/components/InputBar.d.ts.map +1 -1
  91. package/dist/tui/components/InputBar.js +12 -7
  92. package/dist/tui/components/InputBar.js.map +1 -1
  93. package/dist/tui/components/LogsPanel.d.ts +9 -0
  94. package/dist/tui/components/LogsPanel.d.ts.map +1 -0
  95. package/dist/tui/components/LogsPanel.js +56 -0
  96. package/dist/tui/components/LogsPanel.js.map +1 -0
  97. package/dist/tui/components/MemoryPanel.d.ts +21 -0
  98. package/dist/tui/components/MemoryPanel.d.ts.map +1 -0
  99. package/dist/tui/components/MemoryPanel.js +51 -0
  100. package/dist/tui/components/MemoryPanel.js.map +1 -0
  101. package/dist/tui/components/MetricsPanel.d.ts +18 -0
  102. package/dist/tui/components/MetricsPanel.d.ts.map +1 -0
  103. package/dist/tui/components/MetricsPanel.js +27 -0
  104. package/dist/tui/components/MetricsPanel.js.map +1 -0
  105. package/dist/tui/components/StatusPanel.d.ts +3 -1
  106. package/dist/tui/components/StatusPanel.d.ts.map +1 -1
  107. package/dist/tui/components/StatusPanel.js +20 -18
  108. package/dist/tui/components/StatusPanel.js.map +1 -1
  109. package/dist/tui/components/TaskTree.d.ts +28 -0
  110. package/dist/tui/components/TaskTree.d.ts.map +1 -0
  111. package/dist/tui/components/TaskTree.js +29 -0
  112. package/dist/tui/components/TaskTree.js.map +1 -0
  113. package/dist/tui/components/animations/ProgressBar.d.ts +39 -0
  114. package/dist/tui/components/animations/ProgressBar.d.ts.map +1 -0
  115. package/dist/tui/components/animations/ProgressBar.js +39 -0
  116. package/dist/tui/components/animations/ProgressBar.js.map +1 -0
  117. package/dist/tui/components/animations/Pulse.d.ts +17 -0
  118. package/dist/tui/components/animations/Pulse.d.ts.map +1 -0
  119. package/dist/tui/components/animations/Pulse.js +47 -0
  120. package/dist/tui/components/animations/Pulse.js.map +1 -0
  121. package/dist/tui/components/animations/Spinner.d.ts +13 -0
  122. package/dist/tui/components/animations/Spinner.d.ts.map +1 -0
  123. package/dist/tui/components/animations/Spinner.js +36 -0
  124. package/dist/tui/components/animations/Spinner.js.map +1 -0
  125. package/dist/tui/components/animations/StatusAnimator.d.ts +27 -0
  126. package/dist/tui/components/animations/StatusAnimator.d.ts.map +1 -0
  127. package/dist/tui/components/animations/StatusAnimator.js +85 -0
  128. package/dist/tui/components/animations/StatusAnimator.js.map +1 -0
  129. package/dist/tui/components/animations/TypingEffect.d.ts +26 -0
  130. package/dist/tui/components/animations/TypingEffect.d.ts.map +1 -0
  131. package/dist/tui/components/animations/TypingEffect.js +59 -0
  132. package/dist/tui/components/animations/TypingEffect.js.map +1 -0
  133. package/dist/tui/components/animations/index.d.ts +8 -0
  134. package/dist/tui/components/animations/index.d.ts.map +1 -0
  135. package/dist/tui/components/animations/index.js +6 -0
  136. package/dist/tui/components/animations/index.js.map +1 -0
  137. package/dist/tui/hooks/useAnimation.d.ts +42 -0
  138. package/dist/tui/hooks/useAnimation.d.ts.map +1 -0
  139. package/dist/tui/hooks/useAnimation.js +212 -0
  140. package/dist/tui/hooks/useAnimation.js.map +1 -0
  141. package/dist/tui/hooks/useAppState.d.ts +10 -0
  142. package/dist/tui/hooks/useAppState.d.ts.map +1 -1
  143. package/dist/tui/hooks/useAppState.js +178 -75
  144. package/dist/tui/hooks/useAppState.js.map +1 -1
  145. package/dist/tui/services/orchestrator.d.ts +16 -0
  146. package/dist/tui/services/orchestrator.d.ts.map +1 -0
  147. package/dist/tui/services/orchestrator.js +152 -0
  148. package/dist/tui/services/orchestrator.js.map +1 -0
  149. package/dist/tui/styles/borders.d.ts +31 -0
  150. package/dist/tui/styles/borders.d.ts.map +1 -0
  151. package/dist/tui/styles/borders.js +47 -0
  152. package/dist/tui/styles/borders.js.map +1 -0
  153. package/dist/tui/styles/colors.d.ts +18 -0
  154. package/dist/tui/styles/colors.d.ts.map +1 -0
  155. package/dist/tui/styles/colors.js +18 -0
  156. package/dist/tui/styles/colors.js.map +1 -0
  157. package/dist/tui/styles/index.d.ts +6 -0
  158. package/dist/tui/styles/index.d.ts.map +1 -0
  159. package/dist/tui/styles/index.js +6 -0
  160. package/dist/tui/styles/index.js.map +1 -0
  161. package/dist/tui/styles/indicators.d.ts +67 -0
  162. package/dist/tui/styles/indicators.d.ts.map +1 -0
  163. package/dist/tui/styles/indicators.js +42 -0
  164. package/dist/tui/styles/indicators.js.map +1 -0
  165. package/dist/tui/styles/layout.d.ts +21 -0
  166. package/dist/tui/styles/layout.d.ts.map +1 -0
  167. package/dist/tui/styles/layout.js +42 -0
  168. package/dist/tui/styles/layout.js.map +1 -0
  169. package/dist/tui/styles/providers.d.ts +77 -0
  170. package/dist/tui/styles/providers.d.ts.map +1 -0
  171. package/dist/tui/styles/providers.js +31 -0
  172. package/dist/tui/styles/providers.js.map +1 -0
  173. package/dist/tui/utils/animation.d.ts +44 -0
  174. package/dist/tui/utils/animation.d.ts.map +1 -0
  175. package/dist/tui/utils/animation.js +107 -0
  176. package/dist/tui/utils/animation.js.map +1 -0
  177. package/package.json +8 -8
  178. package/src/bin.ts +8 -5
  179. package/src/hub/commands/index.ts +7 -4
  180. package/src/hub/event-listener.ts +14 -10
  181. package/src/hub/index.ts +14 -2
  182. package/src/setup/components/ApiKeyInput.tsx +158 -0
  183. package/src/setup/components/AsciiBanner.tsx +125 -0
  184. package/src/setup/components/CliDetector.tsx +230 -0
  185. package/src/setup/components/ModeSelector.tsx +137 -0
  186. package/src/setup/components/ProviderSelector.tsx +174 -0
  187. package/src/setup/components/SetupWizard.tsx +368 -0
  188. package/src/setup/components/StepIndicator.tsx +74 -0
  189. package/src/setup/components/SuccessScreen.tsx +229 -0
  190. package/src/setup/index.ts +34 -0
  191. package/src/setup/utils/cli-detection.ts +99 -0
  192. package/src/setup/utils/config-writer.ts +249 -0
  193. package/src/tui/App.tsx +117 -53
  194. package/src/tui/components/AgentStateIcon.tsx +84 -0
  195. package/src/tui/components/AnimatedBranch.tsx +134 -0
  196. package/src/tui/components/ChatPanel.tsx +85 -43
  197. package/src/tui/components/DAGPanel.tsx +150 -58
  198. package/src/tui/components/ExecutionTimeline.tsx +225 -0
  199. package/src/tui/components/Header.tsx +76 -43
  200. package/src/tui/components/HelpOverlay.tsx +118 -61
  201. package/src/tui/components/InputBar.tsx +33 -19
  202. package/src/tui/components/LogsPanel.tsx +129 -0
  203. package/src/tui/components/MemoryPanel.tsx +163 -0
  204. package/src/tui/components/MetricsPanel.tsx +149 -0
  205. package/src/tui/components/StatusPanel.tsx +84 -37
  206. package/src/tui/components/TaskTree.tsx +159 -0
  207. package/src/tui/components/animations/ProgressBar.tsx +160 -0
  208. package/src/tui/components/animations/Pulse.tsx +73 -0
  209. package/src/tui/components/animations/Spinner.tsx +54 -0
  210. package/src/tui/components/animations/StatusAnimator.tsx +153 -0
  211. package/src/tui/components/animations/TypingEffect.tsx +119 -0
  212. package/src/tui/components/animations/index.ts +16 -0
  213. package/src/tui/hooks/useAnimation.ts +290 -0
  214. package/src/tui/hooks/useAppState.ts +206 -67
  215. package/src/tui/services/orchestrator.ts +195 -0
  216. package/src/tui/styles/borders.ts +51 -0
  217. package/src/tui/styles/colors.ts +19 -0
  218. package/src/tui/styles/index.ts +20 -0
  219. package/src/tui/styles/indicators.ts +54 -0
  220. package/src/tui/styles/layout.ts +44 -0
  221. package/src/tui/styles/providers.ts +32 -0
  222. package/src/tui/utils/animation.ts +124 -0
  223. package/LICENSE +0 -21
  224. package/tsconfig.tsbuildinfo +0 -1
@@ -1,83 +1,140 @@
1
- import React from "react";
2
- import { Box, Text, useInput } from "ink";
1
+ import React, { memo, useMemo } from "react";
2
+ import { Box, Text } from "ink";
3
+ import { tuiColors } from "../styles/index.js";
3
4
 
4
5
  interface HelpOverlayProps {
5
6
  onDismiss: () => void;
6
7
  }
7
8
 
8
- export function HelpOverlay({ onDismiss }: HelpOverlayProps) {
9
- useInput((input, key) => {
10
- if (key.escape || input === "q") {
11
- onDismiss();
12
- }
13
- });
9
+ const COMMAND_SECTIONS = [
10
+ {
11
+ title: "EXECUTION",
12
+ items: [
13
+ ["run <prompt>", "Execute workflow"],
14
+ ["run -w <file>", "With blueprint"],
15
+ ["run -p <n>", "Max parallel agents"],
16
+ ["retry", "Relaunch last workflow"],
17
+ ["stop / pause", "Control execution"],
18
+ ],
19
+ },
20
+ {
21
+ title: "NAVIGATION",
22
+ items: [
23
+ ["status", "System overview"],
24
+ ["agents", "Agent list & status"],
25
+ ["providers", "Provider status"],
26
+ ["workflows", "Available blueprints"],
27
+ ["memory", "QSGM graph view"],
28
+ ],
29
+ },
30
+ {
31
+ title: "MONITORING",
32
+ items: [
33
+ ["logs", "Real-time logs"],
34
+ ["logs -f", "Follow mode"],
35
+ ["metrics", "Performance stats"],
36
+ ["evolve", "Evolution history"],
37
+ ["doctor", "System diagnostic"],
38
+ ],
39
+ },
40
+ ];
14
41
 
15
- const sections = [
16
- {
17
- title: "COMMANDES",
18
- items: [
19
- ["/run <prompt>", "Exécuter un workflow"],
20
- ["/status", "État du système"],
21
- ["/agents", "Liste des agents"],
22
- ["/providers", "Liste des providers"],
23
- ["/workflows", "Blueprints disponibles"],
24
- ["/help, ?", "Cette aide"],
25
- ["/exit", "Quitter"],
26
- ],
27
- },
28
- {
29
- title: "NAVIGATION",
30
- items: [
31
- ["Tab", "Changer de panel actif"],
32
- ["F1-F8", "Aller au panel spécifique"],
33
- ["Ctrl+C", "Quitter"],
34
- ["Esc", "Fermer l'aide"],
35
- ],
36
- },
37
- {
38
- title: "PANELS",
39
- items: [
40
- ["CHAT", "Messages et interaction"],
41
- ["DAG", "Visualisation du workflow"],
42
- ["STATUS", "Agents et providers"],
43
- ],
44
- },
45
- ];
42
+ const KEYBOARD_SHORTCUTS = [
43
+ ["Tab", "Cycle panels"],
44
+ ["F1-F8", "Jump to panel"],
45
+ ["Ctrl+C", "Quit"],
46
+ ["Esc", "Close overlay"],
47
+ ["?", "Toggle help"],
48
+ ];
49
+
50
+ const FUNCTION_KEYS = [
51
+ { key: "F1", label: "Help" },
52
+ { key: "F2", label: "Agents" },
53
+ { key: "F3", label: "Providers" },
54
+ { key: "F4", label: "Workflows" },
55
+ { key: "F5", label: "Logs" },
56
+ { key: "F6", label: "Metrics" },
57
+ { key: "F7", label: "Memory" },
58
+ { key: "F8", label: "Dashboard" },
59
+ ];
60
+
61
+ export const HelpOverlay = memo(function HelpOverlay({ onDismiss }: HelpOverlayProps) {
62
+ const functionKeyElements = useMemo(() =>
63
+ FUNCTION_KEYS.map((fn) => (
64
+ <Box key={fn.key} marginRight={2}>
65
+ <Text color={tuiColors.primary}>[{fn.key}]</Text>
66
+ <Text color={tuiColors.textSecondary}> {fn.label}</Text>
67
+ </Box>
68
+ )),
69
+ []
70
+ );
71
+
72
+ const sectionElements = useMemo(() =>
73
+ COMMAND_SECTIONS.map((section) => (
74
+ <Box key={section.title} flexDirection="column" width={28} marginRight={2}>
75
+ <Text color={tuiColors.primary} bold>┌─ {section.title} ──────────────</Text>
76
+ <Box flexDirection="column" marginTop={1}>
77
+ {section.items.map(([cmd, desc]) => (
78
+ <Box key={cmd} flexDirection="row" marginBottom={1}>
79
+ <Text color={tuiColors.textPrimary}>{cmd.padEnd(14)}</Text>
80
+ <Text color={tuiColors.textTertiary}>{desc}</Text>
81
+ </Box>
82
+ ))}
83
+ </Box>
84
+ </Box>
85
+ )),
86
+ []
87
+ );
88
+
89
+ const shortcutElements = useMemo(() =>
90
+ KEYBOARD_SHORTCUTS.map(([key, action]) => (
91
+ <Box key={key} marginRight={3}>
92
+ <Text color={tuiColors.textPrimary}>[{key.padEnd(6)}]</Text>
93
+ <Text color={tuiColors.textTertiary}> {action}</Text>
94
+ </Box>
95
+ )),
96
+ []
97
+ );
46
98
 
47
99
  return (
48
100
  <Box
49
101
  flexDirection="column"
50
102
  flexGrow={1}
51
- borderStyle="double"
52
- borderColor="#f97316"
103
+ borderStyle="single"
104
+ borderColor={tuiColors.primary}
53
105
  paddingX={2}
54
106
  >
55
107
  <Box marginBottom={1}>
56
- <Text color="#f97316" bold>■ RAX-FLOW HELP</Text>
57
- <Text color="gray"> [Esc] pour fermer</Text>
108
+ <Text color={tuiColors.primary} bold>■ RAX-FLOW HELP</Text>
109
+ <Text color={tuiColors.textTertiary}> ── Press [Esc] or [q] to close</Text>
110
+ </Box>
111
+
112
+ <Box borderStyle="single" borderColor={tuiColors.border} marginBottom={1}>
113
+ <Text color={tuiColors.textTertiary}>
114
+ Orchestrator that Evolves with Your Host Tools
115
+ </Text>
116
+ </Box>
117
+
118
+ <Box flexDirection="row" marginBottom={1}>
119
+ {functionKeyElements}
58
120
  </Box>
59
121
 
60
122
  <Box flexDirection="row" flexGrow={1}>
61
- {sections.map((section) => (
62
- <Box key={section.title} flexDirection="column" width={30}>
63
- <Text color="gray" bold underline>
64
- {section.title}
65
- </Text>
66
- <Box flexDirection="column" marginTop={1}>
67
- {section.items.map(([cmd, desc]) => (
68
- <Box key={cmd} flexDirection="row" marginBottom={1}>
69
- <Text color="cyan">{cmd.padEnd(16)}</Text>
70
- <Text color="white">{desc}</Text>
71
- </Box>
72
- ))}
73
- </Box>
74
- </Box>
75
- ))}
123
+ {sectionElements}
76
124
  </Box>
77
125
 
78
- <Box borderStyle="single" borderColor="gray" marginTop={1}>
79
- <Text color="gray">Pour exécuter un workflow, tapez simplement votre prompt ou /run "..."</Text>
126
+ <Box marginTop={1}>
127
+ <Text color={tuiColors.primary} bold>┌─ KEYBOARD ─────────────────────────────────────</Text>
128
+ </Box>
129
+ <Box flexDirection="row">
130
+ {shortcutElements}
131
+ </Box>
132
+
133
+ <Box borderStyle="single" borderColor={tuiColors.border} marginTop={1}>
134
+ <Text color={tuiColors.textTertiary}>
135
+ Type your prompt to execute a workflow, or use /run "..." for explicit execution
136
+ </Text>
80
137
  </Box>
81
138
  </Box>
82
139
  );
83
- }
140
+ });
@@ -1,55 +1,69 @@
1
- import React, { useState } from "react";
2
- import { Box, Text, useInput } from "ink";
1
+ import React, { useState, memo, useMemo, useCallback } from "react";
2
+ import { Box, Text } from "ink";
3
3
  import TextInput from "ink-text-input";
4
+ import { tuiColors } from "../styles/index.js";
4
5
 
5
6
  interface InputBarProps {
6
7
  onSubmit: (input: string) => void;
7
8
  suggestions: string[];
8
9
  isProcessing: boolean;
10
+ projectName: string;
9
11
  }
10
12
 
11
- export function InputBar({ onSubmit, suggestions, isProcessing }: InputBarProps) {
13
+ export const InputBar = memo(function InputBar({ onSubmit, suggestions, isProcessing, projectName }: InputBarProps) {
12
14
  const [input, setInput] = useState("");
13
15
 
14
- const handleSubmit = (value: string) => {
16
+ const handleSubmit = useCallback((value: string) => {
15
17
  if (value.trim()) {
16
18
  onSubmit(value);
17
19
  setInput("");
18
20
  }
19
- };
21
+ }, [onSubmit]);
20
22
 
21
- const filteredSuggestions = suggestions.filter((s) =>
22
- s.toLowerCase().startsWith(input.toLowerCase())
23
- ).slice(0, 5);
23
+ const handleChange = useCallback((value: string) => {
24
+ setInput(value);
25
+ }, []);
26
+
27
+ const filteredSuggestions = useMemo(() =>
28
+ suggestions.filter((s) =>
29
+ s.toLowerCase().startsWith(input.toLowerCase())
30
+ ).slice(0, 5),
31
+ [suggestions, input]
32
+ );
33
+
34
+ const showSuggestions = input.startsWith("/") && filteredSuggestions.length > 0;
24
35
 
25
36
  return (
26
- <Box flexDirection="column" borderStyle="single" borderColor="gray" paddingX={1}>
27
- {input.startsWith("/") && filteredSuggestions.length > 0 && (
37
+ <Box flexDirection="column" borderStyle="single" borderColor={tuiColors.border} paddingX={1}>
38
+ {showSuggestions && (
28
39
  <Box flexDirection="row" marginBottom={1}>
29
40
  {filteredSuggestions.map((s) => (
30
41
  <Box key={s} marginRight={2}>
31
- <Text color="cyan">{s}</Text>
42
+ <Text color={tuiColors.primary}>{s}</Text>
32
43
  </Box>
33
44
  ))}
34
45
  </Box>
35
46
  )}
36
47
  <Box flexDirection="row" alignItems="center">
37
- <Text color="#f97316" bold>▶</Text>
38
- <Box marginLeft={1} flexGrow={1}>
48
+ <Text color={tuiColors.primary} bold>rax-flow://</Text>
49
+ <Text color={tuiColors.textSecondary}>{projectName}</Text>
50
+ <Text color={tuiColors.textPrimary}> &gt; </Text>
51
+ <Box flexGrow={1}>
39
52
  <TextInput
40
53
  value={input}
41
- onChange={setInput}
54
+ onChange={handleChange}
42
55
  onSubmit={handleSubmit}
43
- placeholder="Tapez /help ou votre prompt..."
56
+ placeholder="Enter prompt or /help..."
44
57
  showCursor={true}
45
58
  />
46
59
  </Box>
47
- {isProcessing && <Text color="yellow"> ●</Text>}
60
+ {isProcessing && <Text color={tuiColors.warning}> ●</Text>}
48
61
  </Box>
49
62
  <Box flexDirection="row" marginTop={1}>
50
- <Text color="gray" dimColor>[Ctrl+C] Quitter</Text>
51
- <Text color="gray" dimColor> │ [/cmd] Commandes</Text>
63
+ <Text color={tuiColors.textQuaternary}>[Ctrl+C] Quit</Text>
64
+ <Text color={tuiColors.textQuaternary}> │ [/cmd] Commands</Text>
65
+ <Text color={tuiColors.textQuaternary}> │ [?] Help</Text>
52
66
  </Box>
53
67
  </Box>
54
68
  );
55
- }
69
+ });
@@ -0,0 +1,129 @@
1
+ import React, { useState, useEffect, memo, useRef, useMemo } from "react";
2
+ import { Box, Text } from "ink";
3
+ import { tuiColors, logStatusTags } from "../styles/index.js";
4
+ import { Spinner } from "./animations/index.js";
5
+
6
+ interface LogsPanelProps {
7
+ logs: string[];
8
+ isActive: boolean;
9
+ isStreaming?: boolean;
10
+ }
11
+
12
+ const MAX_DISPLAYED_LOGS = 12;
13
+ const HIGHLIGHT_DURATION = 2000;
14
+
15
+ interface ParsedLog {
16
+ time: string;
17
+ tag: string;
18
+ message: string;
19
+ color: string;
20
+ }
21
+
22
+ function parseLogLine(log: string): ParsedLog | null {
23
+ const timeMatch = log.match(/\[(\d{2}:\d{2}:\d{2}(?:\.\d+)?)\]/);
24
+ const tagMatch = log.match(/\[(\w+)\]/g);
25
+
26
+ if (!timeMatch || !tagMatch || tagMatch.length < 2) {
27
+ return null;
28
+ }
29
+
30
+ const time = timeMatch[1];
31
+ const tag = tagMatch[1].replace(/[\[\]]/g, "").toUpperCase();
32
+
33
+ const tagConfig = Object.values(logStatusTags).find(t => t.tag.toUpperCase().includes(tag));
34
+ const color = tagConfig?.color || tuiColors.textTertiary;
35
+
36
+ const messageStart = log.indexOf(tagMatch[1]) + tagMatch[1].length;
37
+ const message = log.slice(messageStart).trim();
38
+
39
+ return { time, tag, message, color };
40
+ }
41
+
42
+ interface LogLineProps {
43
+ log: string;
44
+ isNew?: boolean;
45
+ }
46
+
47
+ const LogLine = memo(function LogLine({ log, isNew }: LogLineProps) {
48
+ const parsed = useMemo(() => parseLogLine(log), [log]);
49
+
50
+ if (!parsed) {
51
+ return <Text color={tuiColors.textPrimary}>{log}</Text>;
52
+ }
53
+
54
+ const paddedTag = useMemo(() => parsed.tag.padEnd(7), [parsed.tag]);
55
+
56
+ return (
57
+ <Box flexDirection="row">
58
+ <Text color={tuiColors.textTertiary}>[{parsed.time}]</Text>
59
+ <Text color={parsed.color} bold> [{paddedTag}]</Text>
60
+ <Text color={isNew ? tuiColors.textPrimary : tuiColors.textSecondary}> {parsed.message}</Text>
61
+ </Box>
62
+ );
63
+ });
64
+
65
+ export const LogsPanel = memo(function LogsPanel({ logs, isActive, isStreaming = false }: LogsPanelProps) {
66
+ const borderColor = isActive ? tuiColors.primary : tuiColors.border;
67
+ const [highlightedIndex, setHighlightedIndex] = useState<number | null>(null);
68
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
69
+
70
+ const displayLogs = useMemo(() => logs.slice(-MAX_DISPLAYED_LOGS), [logs]);
71
+
72
+ useEffect(() => {
73
+ if (logs.length === 0) return;
74
+
75
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
76
+
77
+ setHighlightedIndex(logs.length - 1);
78
+ timeoutRef.current = setTimeout(() => {
79
+ setHighlightedIndex(null);
80
+ }, HIGHLIGHT_DURATION);
81
+
82
+ return () => {
83
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
84
+ };
85
+ }, [logs.length]);
86
+
87
+ const logElements = useMemo(() =>
88
+ displayLogs.map((log, index) => {
89
+ const logIndex = logs.length - MAX_DISPLAYED_LOGS + index;
90
+ const isNew = logIndex === highlightedIndex;
91
+ return <LogLine key={`${logIndex}-${index}`} log={log} isNew={isNew} />;
92
+ }),
93
+ [displayLogs, logs.length, highlightedIndex]
94
+ );
95
+
96
+ return (
97
+ <Box
98
+ flexDirection="column"
99
+ flexGrow={1}
100
+ borderStyle="single"
101
+ borderColor={borderColor}
102
+ paddingX={1}
103
+ >
104
+ <Box marginBottom={1}>
105
+ <Text color={tuiColors.primary} bold>┌─</Text>
106
+ <Text color={tuiColors.primary} bold> LOGS_STREAM </Text>
107
+ <Text color={tuiColors.textTertiary}>────────────────────────────</Text>
108
+ {isStreaming && (
109
+ <Box flexDirection="row">
110
+ <Text color={tuiColors.warning}> </Text>
111
+ <Spinner type="dots" color={tuiColors.warning} />
112
+ </Box>
113
+ )}
114
+ </Box>
115
+ <Box flexDirection="column" flexGrow={1} overflow="hidden">
116
+ {logElements}
117
+ {logs.length === 0 && (
118
+ <Text color={tuiColors.textTertiary}>No logs. Start a workflow to see logs.</Text>
119
+ )}
120
+ {isStreaming && logs.length === 0 && (
121
+ <Box flexDirection="row">
122
+ <Spinner type="dots" color={tuiColors.warning} />
123
+ <Text color={tuiColors.textTertiary}> Waiting for logs...</Text>
124
+ </Box>
125
+ )}
126
+ </Box>
127
+ </Box>
128
+ );
129
+ });
@@ -0,0 +1,163 @@
1
+ import React, { memo, useMemo } from "react";
2
+ import { Box, Text } from "ink";
3
+ import { tuiColors, treeChars } from "../styles/index.js";
4
+ import { Pulse } from "./animations/index.js";
5
+
6
+ interface MemoryNode {
7
+ id: string;
8
+ type: string;
9
+ label: string;
10
+ }
11
+
12
+ interface MemoryEdge {
13
+ from: string;
14
+ to: string;
15
+ }
16
+
17
+ interface MemoryPanelProps {
18
+ nodes?: MemoryNode[];
19
+ edges?: MemoryEdge[];
20
+ nodeCount?: number;
21
+ cacheHitRate?: number;
22
+ isActive?: boolean;
23
+ tick?: number;
24
+ }
25
+
26
+ const DEFAULT_NODES: MemoryNode[] = [
27
+ { id: "1", type: "action", label: "code_gen" },
28
+ { id: "2", type: "file", label: "auth.ts" },
29
+ { id: "3", type: "task", label: "login" },
30
+ { id: "4", type: "test", label: "auth.test" },
31
+ { id: "5", type: "fix", label: "patch_001" },
32
+ ];
33
+
34
+ const DEFAULT_EDGES: MemoryEdge[] = [
35
+ { from: "1", to: "2" },
36
+ { from: "2", to: "3" },
37
+ { from: "3", to: "4" },
38
+ { from: "4", to: "5" },
39
+ { from: "2", to: "5" },
40
+ ];
41
+
42
+ const NODE_TYPE_COLORS: Record<string, string> = {
43
+ action: tuiColors.primary,
44
+ file: tuiColors.success,
45
+ task: tuiColors.warning,
46
+ test: tuiColors.textSecondary,
47
+ fix: tuiColors.error,
48
+ };
49
+
50
+ interface NodeTypeBadgeProps {
51
+ type: string;
52
+ isActive?: boolean;
53
+ }
54
+
55
+ const NodeTypeBadge = memo(function NodeTypeBadge({ type, isActive }: NodeTypeBadgeProps) {
56
+ const color = NODE_TYPE_COLORS[type] || tuiColors.textTertiary;
57
+ return (
58
+ <Box flexDirection="row">
59
+ {isActive && <Pulse interval={400} color={color} type="pulse" />}
60
+ <Text color={color}>[{type}]</Text>
61
+ </Box>
62
+ );
63
+ });
64
+
65
+ export const MemoryPanel = memo(function MemoryPanel({
66
+ nodes,
67
+ edges,
68
+ nodeCount = 0,
69
+ cacheHitRate = 0,
70
+ isActive = false,
71
+ tick = 0
72
+ }: MemoryPanelProps) {
73
+ const borderColor = isActive ? tuiColors.primary : tuiColors.border;
74
+
75
+ const displayNodes = (nodes && nodes.length > 0) ? nodes : DEFAULT_NODES;
76
+ const displayEdges = (edges && edges.length > 0) ? edges : DEFAULT_EDGES;
77
+ const displayNodeCount = nodeCount > 0 ? nodeCount : 247;
78
+ const displayCacheHitRate = cacheHitRate > 0 ? cacheHitRate : 94;
79
+
80
+ const activeNodeIndex = isActive ? tick % 4 : -1;
81
+
82
+ const nodeElements = useMemo(() =>
83
+ displayNodes.slice(0, 4).map((node, idx) => {
84
+ const isLast = idx === Math.min(3, displayNodes.length - 1);
85
+ const isNodeActive = idx === activeNodeIndex;
86
+ return (
87
+ <Box key={node.id} flexDirection="row">
88
+ <Text color={tuiColors.textTertiary}>{treeChars.vertical} </Text>
89
+ <NodeTypeBadge type={node.type} isActive={isNodeActive} />
90
+ <Text color={tuiColors.textPrimary}> {node.label}</Text>
91
+ {!isLast && (
92
+ <Text color={tuiColors.primary}> ──▶</Text>
93
+ )}
94
+ </Box>
95
+ );
96
+ }),
97
+ [displayNodes, activeNodeIndex]
98
+ );
99
+
100
+ const edgeElements = useMemo(() =>
101
+ displayEdges.slice(0, 3).map((edge, i) => {
102
+ const fromNode = displayNodes.find((n) => n.id === edge.from);
103
+ const toNode = displayNodes.find((n) => n.id === edge.to);
104
+ return (
105
+ <Box key={i} flexDirection="row">
106
+ <Text color={tuiColors.textSecondary}>{treeChars.branch}</Text>
107
+ <Text color={tuiColors.textPrimary}> {fromNode?.label || "?"}</Text>
108
+ <Text color={tuiColors.primary}> ──▶ </Text>
109
+ <Text color={tuiColors.textPrimary}>{toNode?.label || "?"}</Text>
110
+ </Box>
111
+ );
112
+ }),
113
+ [displayEdges, displayNodes]
114
+ );
115
+
116
+ const mutationCount = useMemo(() => Math.floor(Math.random() * 4) + 1, [tick]);
117
+
118
+ return (
119
+ <Box
120
+ flexDirection="column"
121
+ flexGrow={1}
122
+ borderStyle="single"
123
+ borderColor={borderColor}
124
+ paddingX={1}
125
+ >
126
+ <Box marginBottom={1}>
127
+ <Text color={tuiColors.primary} bold>┌─</Text>
128
+ <Text color={tuiColors.primary} bold> QSGM </Text>
129
+ <Text color={tuiColors.textTertiary}>── nodes: {displayNodeCount} ──</Text>
130
+ {isActive && <Pulse interval={500} color={tuiColors.primary} type="pulse" />}
131
+ </Box>
132
+
133
+ <Box flexDirection="column">
134
+ <Text color={tuiColors.textTertiary} bold>QUANTUM_SEMANTIC_GRAPH_MEMORY</Text>
135
+ </Box>
136
+
137
+ <Box flexDirection="column" marginTop={1}>
138
+ <Text color={tuiColors.textTertiary} bold>GRAPH VISUALIZATION</Text>
139
+ <Box flexDirection="column" marginTop={1}>
140
+ {nodeElements}
141
+ </Box>
142
+ </Box>
143
+
144
+ <Box flexDirection="column" marginTop={1}>
145
+ <Text color={tuiColors.textTertiary} bold>CONNECTIONS</Text>
146
+ <Box flexDirection="column" marginTop={1}>
147
+ {edgeElements}
148
+ </Box>
149
+ </Box>
150
+
151
+ <Box marginTop={1}>
152
+ <Text color={tuiColors.textTertiary}>├─ STATS ───────────────────</Text>
153
+ </Box>
154
+ <Box flexDirection="row">
155
+ <Text color={tuiColors.textSecondary}>Cache Hit:</Text>
156
+ <Text color={tuiColors.success}> </Text>
157
+ <Pulse interval={800} color={tuiColors.success} type="breath" />
158
+ <Text color={tuiColors.success}> {displayCacheHitRate}%</Text>
159
+ <Text color={tuiColors.textTertiary}> │ Mutations: +{mutationCount}</Text>
160
+ </Box>
161
+ </Box>
162
+ );
163
+ });