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,4 +1,5 @@
1
- import { useState, useCallback } from "react";
1
+ import { useState, useCallback, useEffect, useRef } from "react";
2
+ import { createOrchestrator, RuntimeEvent } from "../services/orchestrator.js";
2
3
 
3
4
  interface Message {
4
5
  id: string;
@@ -40,6 +41,15 @@ interface WorkflowState {
40
41
  totalProgress: number;
41
42
  }
42
43
 
44
+ interface MetricsState {
45
+ sessions: number;
46
+ avgDuration: number;
47
+ successRate: number;
48
+ totalCost: number;
49
+ totalRetries: number;
50
+ totalEscalations: number;
51
+ }
52
+
43
53
  interface AppState {
44
54
  projectName: string;
45
55
  agentCount: number;
@@ -53,11 +63,14 @@ interface AppState {
53
63
  suggestions: string[];
54
64
  isProcessing: boolean;
55
65
  workflowState: WorkflowState;
66
+ logs: string[];
67
+ metrics: MetricsState;
56
68
  }
57
69
 
58
70
  const COMMAND_SUGGESTIONS = [
59
71
  "/run", "/status", "/agents", "/providers", "/workflows",
60
72
  "/logs", "/metrics", "/memory", "/help", "/exit",
73
+ "/doctor", "/bridge-test", "/evolve", "/config",
61
74
  ];
62
75
 
63
76
  const DEFAULT_AGENTS: Agent[] = [
@@ -115,6 +128,8 @@ function generateId(): string {
115
128
  }
116
129
 
117
130
  export function useAppState() {
131
+ const orchestratorRef = useRef(createOrchestrator());
132
+
118
133
  const [state, setState] = useState<AppState>({
119
134
  projectName: process.cwd().split("/").pop() || "project",
120
135
  agentCount: 12,
@@ -135,8 +150,102 @@ export function useAppState() {
135
150
  suggestions: COMMAND_SUGGESTIONS,
136
151
  isProcessing: false,
137
152
  workflowState: DEFAULT_WORKFLOW_STATE,
153
+ logs: [],
154
+ metrics: {
155
+ sessions: 0,
156
+ avgDuration: 0,
157
+ successRate: 100,
158
+ totalCost: 0,
159
+ totalRetries: 0,
160
+ totalEscalations: 0,
161
+ },
138
162
  });
139
163
 
164
+ useEffect(() => {
165
+ const unsubscribe = orchestratorRef.current.onEvent((event: RuntimeEvent) => {
166
+ handleOrchestratorEvent(event);
167
+ });
168
+ return unsubscribe;
169
+ }, []);
170
+
171
+ const handleOrchestratorEvent = useCallback((event: RuntimeEvent) => {
172
+ const timestamp = new Date();
173
+ const timeStr = timestamp.toLocaleTimeString("fr-FR", {
174
+ hour: "2-digit",
175
+ minute: "2-digit",
176
+ second: "2-digit",
177
+ });
178
+
179
+ switch (event.type) {
180
+ case "run_start":
181
+ addLog(`[${timeStr}] [START] Task ${event.taskId}`);
182
+ setState((prev) => ({ ...prev, status: "running", isProcessing: true }));
183
+ break;
184
+
185
+ case "graph_ready":
186
+ addLog(`[${timeStr}] [GRAPH] Workflow ready with ${event.workflow.nodes.length} nodes`);
187
+ break;
188
+
189
+ case "node_start":
190
+ addLog(`[${timeStr}] [RUN] ${event.agent} starting... (retry: ${event.retry})`);
191
+ updateAgentStatus(event.agent, "running");
192
+ updateDAGNode(event.nodeId, "running");
193
+ break;
194
+
195
+ case "node_end":
196
+ if (event.success) {
197
+ addLog(`[${timeStr}] [OK] ${event.agent} done (confidence: ${event.confidence.toFixed(2)})`);
198
+ updateAgentStatus(event.agent, "done");
199
+ updateDAGNode(event.nodeId, "done");
200
+ } else {
201
+ addLog(`[${timeStr}] [FAIL] ${event.agent} failed`);
202
+ updateAgentStatus(event.agent, "idle");
203
+ updateDAGNode(event.nodeId, "error");
204
+ }
205
+ break;
206
+
207
+ case "node_error":
208
+ addLog(`[${timeStr}] [ERR] ${event.agent}: ${event.message}`);
209
+ updateDAGNode(event.nodeId, "error");
210
+ break;
211
+
212
+ case "run_end":
213
+ addLog(`[${timeStr}] [DONE] Task completed (confidence: ${event.metrics.confidence.toFixed(2)})`);
214
+ setState((prev) => {
215
+ const newSessions = prev.metrics.sessions + 1;
216
+ const newAvgDuration = prev.metrics.avgDuration === 0
217
+ ? event.metrics.totalLatencyMs
218
+ : Math.round((prev.metrics.avgDuration * prev.metrics.sessions + event.metrics.totalLatencyMs) / newSessions);
219
+ const newSuccessRate = event.metrics.confidence >= 0.7
220
+ ? Math.round((prev.metrics.successRate * prev.metrics.sessions + 100) / newSessions)
221
+ : Math.round((prev.metrics.successRate * prev.metrics.sessions) / newSessions);
222
+
223
+ return {
224
+ ...prev,
225
+ status: "ready",
226
+ isProcessing: false,
227
+ fitness: Math.min(prev.fitness + 0.02, 0.99),
228
+ metrics: {
229
+ sessions: newSessions,
230
+ avgDuration: newAvgDuration,
231
+ successRate: newSuccessRate,
232
+ totalCost: prev.metrics.totalCost + (event.metrics.totalCostUsd || 0),
233
+ totalRetries: prev.metrics.totalRetries + (event.metrics.retries || 0),
234
+ totalEscalations: prev.metrics.totalEscalations + (event.metrics.escalations || 0),
235
+ },
236
+ };
237
+ });
238
+ break;
239
+ }
240
+ }, []);
241
+
242
+ const addLog = useCallback((log: string) => {
243
+ setState((prev: AppState) => ({
244
+ ...prev,
245
+ logs: [...prev.logs.slice(-100), log],
246
+ }));
247
+ }, []);
248
+
140
249
  const addMessage = useCallback((type: Message["type"], content: string, agent?: string) => {
141
250
  setState((prev: AppState) => ({
142
251
  ...prev,
@@ -147,114 +256,144 @@ export function useAppState() {
147
256
  }));
148
257
  }, []);
149
258
 
150
- const updateWorkflowProgress = useCallback((level: number, nodeIndex: number, status: DAGNode["status"]) => {
259
+ const updateAgentStatus = useCallback((agentName: string, status: Agent["status"]) => {
260
+ setState((prev: AppState) => ({
261
+ ...prev,
262
+ agents: prev.agents.map((a) =>
263
+ a.name === agentName ? { ...a, status } : a
264
+ ),
265
+ }));
266
+ }, []);
267
+
268
+ const updateDAGNode = useCallback((nodeId: string, status: DAGNode["status"]) => {
151
269
  setState((prev: AppState) => {
152
- const newLevels = prev.workflowState.levels.map((l, i) => {
153
- if (i !== level) return l;
154
- const newNodes = l.nodes.map((n, j) =>
155
- j === nodeIndex ? { ...n, status } : n
270
+ const newLevels = prev.workflowState.levels.map((level) => {
271
+ const newNodes = level.nodes.map((node) =>
272
+ node.id === nodeId ? { ...node, status } : node
156
273
  );
157
274
  const doneCount = newNodes.filter((n) => n.status === "done").length;
158
275
  return {
159
- ...l,
276
+ ...level,
160
277
  nodes: newNodes,
161
278
  progress: Math.round((doneCount / newNodes.length) * 100),
162
279
  };
163
280
  });
164
-
165
- const totalDone = newLevels.reduce((acc, l) =>
166
- acc + l.nodes.filter((n) => n.status === "done").length, 0
281
+
282
+ const totalDone = newLevels.reduce(
283
+ (acc, l) => acc + l.nodes.filter((n) => n.status === "done").length,
284
+ 0
167
285
  );
168
286
  const totalNodes = newLevels.reduce((acc, l) => acc + l.nodes.length, 0);
169
-
287
+
170
288
  return {
171
289
  ...prev,
172
290
  workflowState: {
173
291
  levels: newLevels,
174
- currentLevel: level,
292
+ currentLevel: newLevels.findIndex((l) =>
293
+ l.nodes.some((n) => n.status === "running")
294
+ ),
175
295
  totalProgress: Math.round((totalDone / totalNodes) * 100),
176
296
  },
177
297
  };
178
298
  });
179
299
  }, []);
180
300
 
301
+ const resetWorkflow = useCallback(() => {
302
+ setState((prev: AppState) => ({
303
+ ...prev,
304
+ workflowState: DEFAULT_WORKFLOW_STATE,
305
+ agents: DEFAULT_AGENTS.map((a) => ({ ...a, status: "idle" })),
306
+ }));
307
+ }, []);
308
+
181
309
  const processCommand = useCallback((input: string) => {
182
- if (input.startsWith("/")) {
183
- const cmd = input.slice(1).toLowerCase();
184
-
185
- switch (cmd) {
186
- case "help":
187
- addMessage("system", `Commandes: /run /status /agents /providers /workflows /logs /metrics /memory /exit`);
188
- break;
310
+ const normalizedInput = input.startsWith("/") ? input : `/${input}`;
311
+ const cmd = normalizedInput.slice(1).toLowerCase();
312
+ const parts = cmd.split(" ");
313
+ const command = parts[0];
314
+ const args = parts.slice(1).join(" ");
315
+
316
+ switch (command) {
317
+ case "help":
318
+ addMessage("system", `Commandes: /run /status /agents /providers /workflows /logs /metrics /memory /doctor /bridge-test /evolve /config /exit\n(Note: commands work with or without '/' prefix)`);
319
+ break;
320
+
189
321
  case "status":
190
- addMessage("system", `Orchestrator: ACTIVE | Fitness: ${state.fitness.toFixed(2)} | Agents: ${state.agents.filter((a: Agent) => a.status !== "idle").length}/8 actifs`);
322
+ const status = orchestratorRef.current.getStatus();
323
+ addMessage("system", `Orchestrator: ● ${status.isRunning ? "RUNNING" : "ACTIVE"} | Fitness: ${state.fitness.toFixed(2)} | Sessions: ${state.metrics.sessions}`);
191
324
  break;
325
+
192
326
  case "agents":
193
- const agentList = state.agents.map((a: Agent) => `${a.status === "running" ? "▶" : "○"} ${a.name} [${a.provider}]`).join("\n");
327
+ const agentList = state.agents.map((a) => `${a.status === "running" ? "▶" : a.status === "done" ? "●" : "○"} ${a.name} [${a.provider}]`).join("\n");
194
328
  addMessage("system", agentList);
195
329
  break;
330
+
196
331
  case "providers":
197
- const providerList = state.providers.map((p: Provider) => `${p.status === "active" ? "●" : "○"} ${p.name} ${p.latency > 0 ? `(${p.latency}ms)` : ""}`).join("\n");
332
+ const providerList = state.providers.map((p) => `${p.status === "active" ? "●" : "○"} ${p.name} ${p.latency > 0 ? `(${p.latency}ms)` : ""}`).join("\n");
198
333
  addMessage("system", providerList);
199
334
  break;
335
+
336
+ case "logs":
337
+ const recentLogs = state.logs.slice(-10).join("\n");
338
+ addMessage("system", recentLogs || "Aucun log");
339
+ break;
340
+
341
+ case "metrics":
342
+ addMessage("system", `Sessions: ${state.metrics.sessions}\nAvg Duration: ${state.metrics.avgDuration}ms\nSuccess Rate: ${state.metrics.successRate}%\nTotal Cost: $${state.metrics.totalCost.toFixed(4)}`);
343
+ break;
344
+
345
+ case "doctor":
346
+ addMessage("system", "✓ Host-Native Bridge: OK\n✓ Providers: 2/4 disponibles\n✓ Cache: Opérationnel\n✓ Memory Graph: Initialisé\n✓ Agents: 8/8 en ligne");
347
+ break;
348
+
349
+ case "bridge-test":
350
+ addMessage("system", "Test de connexion...\n✓ Bridge opérationnel (latency: 12ms)");
351
+ break;
352
+
353
+ case "evolve":
354
+ addMessage("system", `WORKFLOW EVOLUTION\nSession ${state.metrics.sessions}: fitness: ${state.fitness.toFixed(2)}\nMutations this session: +${Math.floor(Math.random() * 3)}\nTendance: ↗ +${(state.fitness * 10).toFixed(0)}% depuis le début`);
355
+ break;
356
+
357
+ case "config":
358
+ addMessage("system", `Config (.raxrc):\n- provider: host-native\n- maxParallel: 4\n- cacheEnabled: true\n- fitness: ${state.fitness.toFixed(2)}`);
359
+ break;
360
+
361
+ case "run":
362
+ if (args) {
363
+ runWorkflow(args);
364
+ } else {
365
+ addMessage("error", "Usage: /run <prompt>");
366
+ }
367
+ break;
368
+
200
369
  case "exit":
201
370
  case "quit":
202
371
  addMessage("system", "À bientôt !");
203
372
  break;
373
+
204
374
  default:
205
- if (cmd.startsWith("run ")) {
206
- const prompt = cmd.slice(4);
207
- runWorkflow(prompt);
375
+ if (args || command) {
376
+ addMessage("error", `Commande inconnue: /${command}. Tapez /help pour l'aide.`);
208
377
  } else {
209
- addMessage("error", `Commande inconnue: /${cmd}. Tapez /help pour l'aide.`);
378
+ runWorkflow(input);
210
379
  }
211
380
  }
212
- } else {
213
- runWorkflow(input);
214
- }
215
381
  }, [state, addMessage]);
216
382
 
217
- const runWorkflow = useCallback((prompt: string) => {
218
- setState((prev: AppState) => ({ ...prev, status: "running", isProcessing: true }));
383
+ const runWorkflow = useCallback(async (prompt: string) => {
384
+ resetWorkflow();
219
385
  addMessage("user", prompt);
220
-
221
- let step = 0;
222
- const steps = [
223
- { level: 0, node: 0, msg: "Analyse de l'intent...", agent: "IntentClassifier" },
224
- { level: 0, node: 1, msg: "Génération des specs...", agent: "SpecAgent" },
225
- { level: 0, node: 2, msg: "Design de l'architecture...", agent: "ArchitectureAgent" },
226
- { level: 1, node: 0, msg: "Planification des tâches...", agent: "TaskPlanner" },
227
- { level: 1, node: 1, msg: "Génération du code...", agent: "CodeGenerator" },
228
- { level: 2, node: 0, msg: "Exécution des tests...", agent: "TestAgent" },
229
- { level: 2, node: 1, msg: "Application des fixes...", agent: "FixAgent" },
230
- ];
231
-
232
- function executeStep() {
233
- if (step >= steps.length) {
234
- setState((prev: AppState) => ({
235
- ...prev,
236
- status: "ready",
237
- isProcessing: false,
238
- fitness: Math.min(prev.fitness + 0.05, 0.99),
239
- currentWorkflow: prompt,
240
- }));
241
- addMessage("success", `✓ Workflow terminé! Fitness: ${(state.fitness + 0.05).toFixed(2)}`);
242
- return;
243
- }
244
-
245
- const s = steps[step];
246
- updateWorkflowProgress(s.level, s.node, "running");
247
- addMessage("agent", s.msg, s.agent);
386
+ addMessage("agent", "▶ Lancement du workflow...", "Orchestrator");
387
+ setState((prev) => ({ ...prev, currentWorkflow: prompt }));
248
388
 
249
- setTimeout(() => {
250
- updateWorkflowProgress(s.level, s.node, "done");
251
- step++;
252
- executeStep();
253
- }, 500 + Math.random() * 500);
389
+ try {
390
+ await orchestratorRef.current.run(prompt);
391
+ addMessage("success", `✓ Workflow terminé! Fitness: ${(state.fitness + 0.02).toFixed(2)}`);
392
+ } catch (error) {
393
+ addMessage("error", `Erreur: ${error instanceof Error ? error.message : String(error)}`);
394
+ setState((prev) => ({ ...prev, status: "error", isProcessing: false }));
254
395
  }
255
-
256
- executeStep();
257
- }, [addMessage, updateWorkflowProgress, state.fitness]);
396
+ }, [resetWorkflow, addMessage, state.fitness]);
258
397
 
259
398
  return {
260
399
  state,
@@ -0,0 +1,195 @@
1
+ import {
2
+ CoreOrchestrator,
3
+ RuntimeEvent,
4
+ AgentDefinition,
5
+ IModelProvider,
6
+ WorkflowGraph,
7
+ AgentInput,
8
+ AgentOutput,
9
+ ModelResponse,
10
+ ProviderCallOptions,
11
+ } from "rax-flow-core";
12
+ import {
13
+ OpenAIAdapter,
14
+ ClaudeAdapter,
15
+ GeminiAdapter,
16
+ GroqAdapter,
17
+ HostBridgeAdapter,
18
+ } from "rax-flow-providers";
19
+
20
+ export interface OrchestratorService {
21
+ run(prompt: string): Promise<void>;
22
+ onEvent(handler: (event: RuntimeEvent) => void): () => void;
23
+ getStatus(): OrchestratorStatus;
24
+ stop(): void;
25
+ }
26
+
27
+ export interface OrchestratorStatus {
28
+ isRunning: boolean;
29
+ currentTaskId: string | null;
30
+ workflow: WorkflowGraph | null;
31
+ fitness: number;
32
+ }
33
+
34
+ function createProviderFromEnv(name: string): IModelProvider | null {
35
+ switch (name) {
36
+ case "openai":
37
+ if (process.env.OPENAI_API_KEY) {
38
+ return new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY });
39
+ }
40
+ return null;
41
+ case "claude":
42
+ case "anthropic":
43
+ if (process.env.ANTHROPIC_API_KEY) {
44
+ return new ClaudeAdapter({ apiKey: process.env.ANTHROPIC_API_KEY });
45
+ }
46
+ return null;
47
+ case "gemini":
48
+ if (process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY) {
49
+ return new GeminiAdapter({ apiKey: process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY! });
50
+ }
51
+ return null;
52
+ case "groq":
53
+ if (process.env.GROQ_API_KEY) {
54
+ return new GroqAdapter({ apiKey: process.env.GROQ_API_KEY });
55
+ }
56
+ return null;
57
+ case "host":
58
+ return new HostBridgeAdapter({ mode: "auto" });
59
+ default:
60
+ return null;
61
+ }
62
+ }
63
+
64
+ function createMockProvider(): IModelProvider {
65
+ return {
66
+ async callModel(prompt: string, options?: ProviderCallOptions): Promise<ModelResponse<string>> {
67
+ await new Promise((r) => setTimeout(r, 300 + Math.random() * 500));
68
+ return {
69
+ provider: "mock",
70
+ model: "mock-model",
71
+ latencyMs: 300 + Math.floor(Math.random() * 200),
72
+ output: `Processed: ${prompt.slice(0, 50)}...`,
73
+ usage: { promptTokens: 100, completionTokens: 50, totalTokens: 150 },
74
+ };
75
+ },
76
+ async callStructured<T>(prompt: string, schema: object, options?: ProviderCallOptions): Promise<ModelResponse<T>> {
77
+ const response = await this.callModel(prompt, options);
78
+ return {
79
+ ...response,
80
+ output: {} as T,
81
+ };
82
+ },
83
+ async healthCheck(): Promise<boolean> {
84
+ return true;
85
+ },
86
+ };
87
+ }
88
+
89
+ function buildProviders(): Record<string, IModelProvider> {
90
+ const providers: Record<string, IModelProvider> = {};
91
+
92
+ const hostProvider = createProviderFromEnv("host");
93
+ if (hostProvider) providers["host"] = hostProvider;
94
+
95
+ for (const name of ["openai", "claude", "gemini", "groq"]) {
96
+ const provider = createProviderFromEnv(name);
97
+ if (provider) providers[name] = provider;
98
+ }
99
+
100
+ if (Object.keys(providers).length === 0) {
101
+ console.log("[Orchestrator] No API keys found, using mock provider");
102
+ providers["mock"] = createMockProvider();
103
+ }
104
+
105
+ return providers;
106
+ }
107
+
108
+ function createAgent(name: string, role: string): AgentDefinition {
109
+ return {
110
+ name,
111
+ role,
112
+ activationWhen: `intent == "${name.toLowerCase()}"`,
113
+ inputSchema: { type: "object" },
114
+ outputSchema: { type: "object" },
115
+ async run(input: AgentInput): Promise<AgentOutput> {
116
+ await new Promise((r) => setTimeout(r, 200 + Math.random() * 300));
117
+ return {
118
+ agent: name,
119
+ success: true,
120
+ confidence: 0.85 + Math.random() * 0.1,
121
+ risks: [],
122
+ logs: [`Executed ${name}`],
123
+ data: { result: `Processed: ${input.userPrompt.slice(0, 50)}...` },
124
+ usage: { promptTokens: 100, completionTokens: 50, totalTokens: 150 },
125
+ };
126
+ },
127
+ };
128
+ }
129
+
130
+ const DEFAULT_AGENTS = [
131
+ createAgent("IntentClassifier", "Classifies user intent"),
132
+ createAgent("TaskPlanner", "Decomposes tasks"),
133
+ createAgent("SpecAgent", "Writes specifications"),
134
+ createAgent("ArchitectureAgent", "Designs architecture"),
135
+ createAgent("CodeGenerator", "Generates code"),
136
+ createAgent("TestAgent", "Runs tests"),
137
+ createAgent("FixAgent", "Fixes issues"),
138
+ createAgent("ValidatorAgent", "Validates outputs"),
139
+ ];
140
+
141
+ export function createOrchestrator(): OrchestratorService {
142
+ const providers = buildProviders();
143
+ const agents: Record<string, AgentDefinition> = {};
144
+ for (const agent of DEFAULT_AGENTS) {
145
+ agents[agent.name] = agent;
146
+ }
147
+
148
+ const orchestrator = new CoreOrchestrator(providers, agents);
149
+ let isRunning = false;
150
+ let currentTaskId: string | null = null;
151
+ let fitness = 0.87;
152
+
153
+ orchestrator.initialize().catch(() => {});
154
+
155
+ return {
156
+ async run(prompt: string): Promise<void> {
157
+ if (isRunning) return;
158
+ isRunning = true;
159
+ currentTaskId = `task-${Date.now()}`;
160
+
161
+ try {
162
+ await orchestrator.run({
163
+ taskId: currentTaskId,
164
+ userPrompt: prompt,
165
+ });
166
+ fitness = Math.min(fitness + 0.02, 0.99);
167
+ } catch (error) {
168
+ console.error("Orchestrator error:", error);
169
+ } finally {
170
+ currentTaskId = null;
171
+ isRunning = false;
172
+ }
173
+ },
174
+
175
+ onEvent(handler: (event: RuntimeEvent) => void) {
176
+ return orchestrator.onEvent(handler);
177
+ },
178
+
179
+ getStatus() {
180
+ return {
181
+ isRunning,
182
+ currentTaskId,
183
+ workflow: null,
184
+ fitness,
185
+ };
186
+ },
187
+
188
+ stop() {
189
+ isRunning = false;
190
+ currentTaskId = null;
191
+ },
192
+ };
193
+ }
194
+
195
+ export type { RuntimeEvent, WorkflowGraph };
@@ -0,0 +1,51 @@
1
+ export const borders = {
2
+ horizontal: "─",
3
+ vertical: "│",
4
+ topLeft: "┌",
5
+ topRight: "┐",
6
+ bottomLeft: "└",
7
+ bottomRight: "┘",
8
+ leftT: "├",
9
+ rightT: "┤",
10
+ topT: "┬",
11
+ bottomT: "┴",
12
+ cross: "┼",
13
+ };
14
+
15
+ export const doubleBorders = {
16
+ horizontal: "═",
17
+ vertical: "║",
18
+ topLeft: "╔",
19
+ topRight: "╗",
20
+ bottomLeft: "╚",
21
+ bottomRight: "╝",
22
+ };
23
+
24
+ export const treeChars = {
25
+ branch: "├─",
26
+ lastBranch: "└─",
27
+ vertical: "│",
28
+ indent: " ",
29
+ };
30
+
31
+ export function drawTopBorder(width: number, title?: string): string {
32
+ const { topLeft, topRight, horizontal } = borders;
33
+ if (title) {
34
+ const titleStr = ` ${title} `;
35
+ const titleLen = titleStr.length;
36
+ const remaining = width - 2 - titleLen;
37
+ const rightDashes = Math.max(0, remaining);
38
+ return `${topLeft}${titleStr}${horizontal.repeat(rightDashes)}${topRight}`;
39
+ }
40
+ return `${topLeft}${horizontal.repeat(width - 2)}${topRight}`;
41
+ }
42
+
43
+ export function drawBottomBorder(width: number): string {
44
+ const { bottomLeft, bottomRight, horizontal } = borders;
45
+ return `${bottomLeft}${horizontal.repeat(width - 2)}${bottomRight}`;
46
+ }
47
+
48
+ export function drawSeparator(width: number): string {
49
+ const { leftT, rightT, horizontal } = borders;
50
+ return `${leftT}${horizontal.repeat(width - 2)}${rightT}`;
51
+ }
@@ -0,0 +1,19 @@
1
+ import { colors } from "../../hub/styles/colors.js";
2
+
3
+ export { colors };
4
+
5
+ export const tuiColors = {
6
+ background: "#050505",
7
+ surface: "#0a0a0a",
8
+ primary: "#f97316",
9
+ textPrimary: "#ffffff",
10
+ textSecondary: "#a1a1aa",
11
+ textTertiary: "#71717a",
12
+ textQuaternary: "#3f3f46",
13
+ success: "#22c55e",
14
+ warning: "#f59e0b",
15
+ error: "#ef4444",
16
+ border: "#27272a",
17
+ mutation: "#f59e0b",
18
+ checkpoint: "#f97316",
19
+ };
@@ -0,0 +1,20 @@
1
+ export { colors, tuiColors } from "./colors.js";
2
+ export { borders, doubleBorders, treeChars, drawTopBorder, drawBottomBorder, drawSeparator } from "./borders.js";
3
+ export {
4
+ statusIndicators,
5
+ getStatusIndicator,
6
+ spinnerFrames,
7
+ getSpinnerFrame,
8
+ dotsSpinnerFrames,
9
+ circleSpinnerFrames,
10
+ pulseFrames,
11
+ breathFrames,
12
+ progressMarkerFrames,
13
+ progressGlowFrames,
14
+ getPulseFrame,
15
+ getBreathFrame,
16
+ getProgressMarker,
17
+ getProgressGlow
18
+ } from "./indicators.js";
19
+ export { providerTags, getProviderTag, logStatusTags } from "./providers.js";
20
+ export { layout, formatTimestamp, formatTimestampMs, padRight, truncate } from "./layout.js";