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.
- package/LICENSE +21 -0
- package/dist/bin.js +27 -3
- package/dist/bin.js.map +1 -1
- package/dist/hub/__tests__/commands.test.d.ts.map +1 -0
- package/dist/hub/__tests__/commands.test.js +72 -0
- package/dist/hub/__tests__/commands.test.js.map +1 -0
- package/dist/hub/__tests__/history.test.d.ts.map +1 -0
- package/dist/hub/__tests__/history.test.js +119 -0
- package/dist/hub/__tests__/history.test.js.map +1 -0
- package/dist/hub/__tests__/parser.test.d.ts.map +1 -0
- package/dist/hub/__tests__/parser.test.js +92 -0
- package/dist/hub/__tests__/parser.test.js.map +1 -0
- package/dist/hub/chat/ChatApp.d.ts +2 -0
- package/dist/hub/chat/ChatApp.d.ts.map +1 -0
- package/dist/hub/chat/ChatApp.js +146 -0
- package/dist/hub/chat/ChatApp.js.map +1 -0
- package/dist/hub/chat/components/ChatInput.d.ts +9 -0
- package/dist/hub/chat/components/ChatInput.d.ts.map +1 -0
- package/dist/hub/chat/components/ChatInput.js +19 -0
- package/dist/hub/chat/components/ChatInput.js.map +1 -0
- package/dist/hub/chat/components/MessageList.d.ts +7 -0
- package/dist/hub/chat/components/MessageList.d.ts.map +1 -0
- package/dist/hub/chat/components/MessageList.js +6 -0
- package/dist/hub/chat/components/MessageList.js.map +1 -0
- package/dist/hub/chat/context.d.ts.map +1 -0
- package/dist/hub/chat/context.js +42 -0
- package/dist/hub/chat/context.js.map +1 -0
- package/dist/hub/chat/hooks/useChatHistory.d.ts +7 -0
- package/dist/hub/chat/hooks/useChatHistory.d.ts.map +1 -0
- package/dist/hub/chat/hooks/useChatHistory.js +31 -0
- package/dist/hub/chat/hooks/useChatHistory.js.map +1 -0
- package/dist/hub/chat/index.d.ts.map +1 -0
- package/dist/hub/chat/index.js +7 -0
- package/dist/hub/chat/index.js.map +1 -0
- package/dist/hub/chat/intent-parser.d.ts.map +1 -0
- package/dist/hub/chat/intent-parser.js +48 -0
- package/dist/hub/chat/intent-parser.js.map +1 -0
- package/dist/hub/chat/types.d.ts.map +1 -0
- package/dist/hub/chat/types.js +2 -0
- package/dist/hub/chat/types.js.map +1 -0
- package/dist/hub/commands/agents.d.ts.map +1 -0
- package/dist/hub/commands/agents.js +36 -0
- package/dist/hub/commands/agents.js.map +1 -0
- package/dist/hub/commands/index.d.ts.map +1 -0
- package/dist/hub/commands/index.js +120 -0
- package/dist/hub/commands/index.js.map +1 -0
- package/dist/hub/commands/logs.d.ts.map +1 -0
- package/dist/hub/commands/logs.js +53 -0
- package/dist/hub/commands/logs.js.map +1 -0
- package/dist/hub/commands/memory.d.ts.map +1 -0
- package/dist/hub/commands/memory.js +40 -0
- package/dist/hub/commands/memory.js.map +1 -0
- package/dist/hub/commands/metrics.d.ts.map +1 -0
- package/dist/hub/commands/metrics.js +35 -0
- package/dist/hub/commands/metrics.js.map +1 -0
- package/dist/hub/commands/providers.d.ts.map +1 -0
- package/dist/hub/commands/providers.js +26 -0
- package/dist/hub/commands/providers.js.map +1 -0
- package/dist/hub/commands/run.d.ts.map +1 -0
- package/dist/hub/commands/run.js +31 -0
- package/dist/hub/commands/run.js.map +1 -0
- package/dist/hub/commands/status.d.ts.map +1 -0
- package/dist/hub/commands/status.js +61 -0
- package/dist/hub/commands/status.js.map +1 -0
- package/dist/hub/commands/workflows.d.ts.map +1 -0
- package/dist/hub/commands/workflows.js +45 -0
- package/dist/hub/commands/workflows.js.map +1 -0
- package/dist/hub/config-loader.d.ts.map +1 -0
- package/dist/hub/config-loader.js +27 -0
- package/dist/hub/config-loader.js.map +1 -0
- package/dist/hub/event-listener.d.ts.map +1 -0
- package/dist/hub/event-listener.js +8 -0
- package/dist/hub/event-listener.js.map +1 -0
- package/dist/hub/history.d.ts.map +1 -0
- package/dist/hub/history.js +59 -0
- package/dist/hub/history.js.map +1 -0
- package/dist/hub/index.d.ts.map +1 -0
- package/dist/hub/index.js +102 -0
- package/dist/hub/index.js.map +1 -0
- package/dist/hub/parser.d.ts.map +1 -0
- package/dist/hub/parser.js +98 -0
- package/dist/hub/parser.js.map +1 -0
- package/dist/hub/styles/borders.d.ts.map +1 -0
- package/dist/hub/styles/borders.js +64 -0
- package/dist/hub/styles/borders.js.map +1 -0
- package/dist/hub/styles/colors.d.ts.map +1 -0
- package/dist/hub/styles/colors.js +115 -0
- package/dist/hub/styles/colors.js.map +1 -0
- package/dist/hub/styles/typography.d.ts.map +1 -0
- package/dist/hub/styles/typography.js +60 -0
- package/dist/hub/styles/typography.js.map +1 -0
- package/dist/hub/tui/App.d.ts +2 -0
- package/dist/hub/tui/App.d.ts.map +1 -0
- package/dist/hub/tui/App.js +53 -0
- package/dist/hub/tui/App.js.map +1 -0
- package/dist/hub/tui/components/AgentQueue.d.ts +6 -0
- package/dist/hub/tui/components/AgentQueue.d.ts.map +1 -0
- package/dist/hub/tui/components/AgentQueue.js +20 -0
- package/dist/hub/tui/components/AgentQueue.js.map +1 -0
- package/dist/hub/tui/components/DAGPanel.d.ts +16 -0
- package/dist/hub/tui/components/DAGPanel.d.ts.map +1 -0
- package/dist/hub/tui/components/DAGPanel.js +51 -0
- package/dist/hub/tui/components/DAGPanel.js.map +1 -0
- package/dist/hub/tui/components/Header.d.ts +7 -0
- package/dist/hub/tui/components/Header.d.ts.map +1 -0
- package/dist/hub/tui/components/Header.js +17 -0
- package/dist/hub/tui/components/Header.js.map +1 -0
- package/dist/hub/tui/components/LogsPanel.d.ts +6 -0
- package/dist/hub/tui/components/LogsPanel.d.ts.map +1 -0
- package/dist/hub/tui/components/LogsPanel.js +26 -0
- package/dist/hub/tui/components/LogsPanel.js.map +1 -0
- package/dist/hub/tui/components/StatusBar.d.ts +8 -0
- package/dist/hub/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/hub/tui/components/StatusBar.js +7 -0
- package/dist/hub/tui/components/StatusBar.js.map +1 -0
- package/dist/hub/tui/hooks/useEvents.d.ts +2 -0
- package/dist/hub/tui/hooks/useEvents.d.ts.map +1 -0
- package/dist/hub/tui/hooks/useEvents.js +13 -0
- package/dist/hub/tui/hooks/useEvents.js.map +1 -0
- package/dist/hub/tui/index.d.ts.map +1 -0
- package/dist/hub/tui/index.js +7 -0
- package/dist/hub/tui/index.js.map +1 -0
- package/dist/hub/tui/types.d.ts.map +1 -0
- package/dist/hub/tui/types.js +2 -0
- package/dist/hub/tui/types.js.map +1 -0
- package/dist/hub/types.d.ts.map +1 -0
- package/dist/hub/types.js +2 -0
- package/dist/hub/types.js.map +1 -0
- package/dist/tui/App.d.ts +2 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +31 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/components/ChatPanel.d.ts +14 -0
- package/dist/tui/components/ChatPanel.d.ts.map +1 -0
- package/dist/tui/components/ChatPanel.js +30 -0
- package/dist/tui/components/ChatPanel.js.map +1 -0
- package/dist/tui/components/Header.d.ts +9 -0
- package/dist/tui/components/Header.d.ts.map +1 -0
- package/dist/tui/components/Header.js +17 -0
- package/dist/tui/components/Header.js.map +1 -0
- package/dist/tui/components/InputBar.d.ts +8 -0
- package/dist/tui/components/InputBar.d.ts.map +1 -0
- package/dist/tui/components/InputBar.js +16 -0
- package/dist/tui/components/InputBar.js.map +1 -0
- package/dist/tui/components/StatusPanel.d.ts +20 -0
- package/dist/tui/components/StatusPanel.d.ts.map +1 -0
- package/dist/tui/components/StatusPanel.js +20 -0
- package/dist/tui/components/StatusPanel.js.map +1 -0
- package/dist/tui/hooks/useAppState.d.ts +38 -0
- package/dist/tui/hooks/useAppState.d.ts.map +1 -0
- package/dist/tui/hooks/useAppState.js +127 -0
- package/dist/tui/hooks/useAppState.js.map +1 -0
- package/dist/tui/index.d.ts +3 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +8 -0
- package/dist/tui/index.js.map +1 -0
- package/package.json +17 -11
- package/src/bin.ts +29 -3
- package/src/hub/__tests__/commands.test.ts +84 -0
- package/src/hub/__tests__/history.test.ts +137 -0
- package/src/hub/__tests__/parser.test.ts +105 -0
- package/src/hub/commands/agents.ts +53 -0
- package/src/hub/commands/index.ts +137 -0
- package/src/hub/commands/logs.ts +70 -0
- package/src/hub/commands/memory.ts +47 -0
- package/src/hub/commands/metrics.ts +49 -0
- package/src/hub/commands/providers.ts +39 -0
- package/src/hub/commands/run.ts +37 -0
- package/src/hub/commands/status.ts +69 -0
- package/src/hub/commands/workflows.ts +64 -0
- package/src/hub/config-loader.ts +37 -0
- package/src/hub/event-listener.ts +13 -0
- package/src/hub/history.ts +66 -0
- package/src/hub/index.ts +120 -0
- package/src/hub/parser.ts +107 -0
- package/src/hub/styles/borders.ts +74 -0
- package/src/hub/styles/colors.ts +129 -0
- package/src/hub/styles/typography.ts +68 -0
- package/src/hub/types.ts +31 -0
- package/src/tui/App.tsx +61 -0
- package/src/tui/components/ChatPanel.tsx +79 -0
- package/src/tui/components/Header.tsx +53 -0
- package/src/tui/components/InputBar.tsx +55 -0
- package/src/tui/components/StatusPanel.tsx +85 -0
- package/src/tui/hooks/useAppState.ts +168 -0
- package/src/tui/index.ts +9 -0
- package/tsconfig.json +19 -3
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/benchmark.d.ts +0 -10
- package/dist/bin.d.ts +0 -3
- package/dist/bootstrap.d.ts +0 -8
- package/dist/bridge-adapter-templates.d.ts +0 -4
- package/dist/bridge-test.d.ts +0 -7
- package/dist/dashboard.d.ts +0 -4
- package/dist/doctor.d.ts +0 -6
- package/dist/evolve.d.ts +0 -7
- package/dist/host-init-templates.d.ts +0 -16
- package/dist/index.d.ts +0 -11
- package/dist/init-host.d.ts +0 -10
- package/dist/install.d.ts +0 -8
- package/dist/run.d.ts +0 -16
- package/dist/styles.d.ts +0 -12
- package/dist/vendor-manifests.d.ts +0 -22
- package/package/dashboard/index.html +0 -420
- package/package/package.json +0 -28
- package/package/src/benchmark.ts +0 -156
- package/package/src/bin.ts +0 -127
- package/package/src/bootstrap.ts +0 -36
- package/package/src/bridge-adapter-templates.ts +0 -181
- package/package/src/bridge-test.ts +0 -107
- package/package/src/dashboard.ts +0 -51
- package/package/src/doctor.ts +0 -92
- package/package/src/evolve.ts +0 -74
- package/package/src/host-init-templates.ts +0 -134
- package/package/src/index.ts +0 -10
- package/package/src/init-host.ts +0 -285
- package/package/src/install.ts +0 -118
- package/package/src/run.ts +0 -317
- package/package/src/styles.ts +0 -12
- package/package/src/vendor-manifests.ts +0 -113
- package/package/src/ws-relay.ts +0 -156
- package/package/tsconfig.json +0 -12
- 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
|
+
}
|
package/src/hub/types.ts
ADDED
|
@@ -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
|
+
}
|
package/src/tui/App.tsx
ADDED
|
@@ -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
|
+
}
|
package/src/tui/index.ts
ADDED
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": [
|
|
11
|
-
|
|
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
|
}
|