fluxy-bot 0.1.45 → 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.
- package/bin/cli.js +1 -3
- package/client/src/App.tsx +0 -3
- package/client/src/components/Layout/DashboardLayout.tsx +1 -1
- package/client/src/hooks/useChat.ts +51 -62
- package/client/src/lib/ws-client.ts +1 -1
- package/dist/assets/{index-BAUWfBMW.js → index-D8wa5QyC.js} +21 -21
- package/dist/assets/index-Dpj8titN.css +1 -0
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/package.json +10 -8
- package/scripts/postinstall.js +10 -26
- package/shared/paths.ts +1 -11
- package/supervisor/fluxy.html +94 -0
- package/supervisor/index.ts +66 -191
- package/supervisor/worker.ts +3 -16
- package/tsconfig.json +2 -3
- package/vite.config.ts +4 -1
- package/{supervisor → worker}/claude-agent.ts +43 -50
- package/{shared → worker}/db.ts +1 -9
- package/{shared → worker}/file-storage.ts +1 -1
- package/worker/index.ts +133 -31
- package/worker/prompts/fluxy-system-prompt.txt +8 -0
- package/client/src/components/BuildOverlay.tsx +0 -75
- package/dist/assets/index-CiN0-4-O.css +0 -1
- package/shared/workspace.ts +0 -196
- package/supervisor/prompts/fluxy-system-prompt.txt +0 -35
- package/supervisor/vite-dev.ts +0 -73
package/bin/cli.js
CHANGED
|
@@ -8,10 +8,8 @@ import { fileURLToPath } from 'url';
|
|
|
8
8
|
|
|
9
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
|
|
11
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
11
12
|
const DATA_DIR = path.join(os.homedir(), '.fluxy');
|
|
12
|
-
const APP_DIR = path.join(DATA_DIR, 'app');
|
|
13
|
-
// Use ~/.fluxy/app/ if it exists (editable copy), otherwise fall back to npm install location
|
|
14
|
-
const ROOT = fs.existsSync(APP_DIR) ? APP_DIR : path.resolve(__dirname, '..');
|
|
15
13
|
const CONFIG_PATH = path.join(DATA_DIR, 'config.json');
|
|
16
14
|
const BIN_DIR = path.join(DATA_DIR, 'bin');
|
|
17
15
|
const CF_PATH = path.join(BIN_DIR, 'cloudflared');
|
package/client/src/App.tsx
CHANGED
|
@@ -6,8 +6,6 @@ import DashboardLayout from './components/Layout/DashboardLayout';
|
|
|
6
6
|
import DashboardPage from './components/Dashboard/DashboardPage';
|
|
7
7
|
import ChatView from './components/Chat/ChatView';
|
|
8
8
|
import FluxyFab from './components/FluxyFab';
|
|
9
|
-
import BuildOverlay from './components/BuildOverlay';
|
|
10
|
-
|
|
11
9
|
import OnboardWizard from './components/Onboard/OnboardWizard';
|
|
12
10
|
import {
|
|
13
11
|
Sheet,
|
|
@@ -72,7 +70,6 @@ export default function App() {
|
|
|
72
70
|
<>
|
|
73
71
|
<ErrorBoundary fallback={<DashboardError />}>
|
|
74
72
|
<DashboardLayout onOpenOnboard={() => setShowOnboard(true)}>
|
|
75
|
-
<BuildOverlay ws={ws} />
|
|
76
73
|
<DashboardPage />
|
|
77
74
|
</DashboardLayout>
|
|
78
75
|
</ErrorBoundary>
|
|
@@ -17,7 +17,7 @@ export default function DashboardLayout({ children, onOpenOnboard }: Props) {
|
|
|
17
17
|
<Sidebar />
|
|
18
18
|
</div>
|
|
19
19
|
{/* Main content */}
|
|
20
|
-
<main className="
|
|
20
|
+
<main className="flex-1 overflow-y-auto p-4 md:p-6">{children}</main>
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
23
|
);
|
|
@@ -52,67 +52,58 @@ export function useChat(ws: WsClient | null) {
|
|
|
52
52
|
.catch(() => {});
|
|
53
53
|
}, []);
|
|
54
54
|
|
|
55
|
-
// Load messages when conversationId is set
|
|
55
|
+
// Load messages when conversationId is set
|
|
56
56
|
useEffect(() => {
|
|
57
57
|
if (!conversationId) return;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
} else if (m.audio_data.includes('/')) {
|
|
79
|
-
audioData = `/api/files/${m.audio_data}`;
|
|
80
|
-
} else {
|
|
81
|
-
audioData = `data:audio/webm;base64,${m.audio_data}`;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
let attachments: StoredAttachment[] | undefined;
|
|
86
|
-
if (m.attachments) {
|
|
87
|
-
try {
|
|
88
|
-
attachments = JSON.parse(m.attachments);
|
|
89
|
-
} catch { /* ignore malformed */ }
|
|
58
|
+
fetch(`/api/conversations/${conversationId}`)
|
|
59
|
+
.then((r) => {
|
|
60
|
+
if (!r.ok) throw new Error('not found');
|
|
61
|
+
return r.json();
|
|
62
|
+
})
|
|
63
|
+
.then((data) => {
|
|
64
|
+
if (data.messages?.length) {
|
|
65
|
+
setMessages(
|
|
66
|
+
data.messages
|
|
67
|
+
.filter((m: any) => m.role === 'user' || m.role === 'assistant')
|
|
68
|
+
.map((m: any) => {
|
|
69
|
+
// Backward compat for audio_data: file path → URL, data: prefix → legacy, else → prepend data URL
|
|
70
|
+
let audioData: string | undefined;
|
|
71
|
+
if (m.audio_data) {
|
|
72
|
+
if (m.audio_data.startsWith('data:')) {
|
|
73
|
+
audioData = m.audio_data; // legacy data URL
|
|
74
|
+
} else if (m.audio_data.includes('/')) {
|
|
75
|
+
audioData = `/api/files/${m.audio_data}`; // file path → HTTP URL
|
|
76
|
+
} else {
|
|
77
|
+
audioData = `data:audio/webm;base64,${m.audio_data}`; // raw base64
|
|
90
78
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Parse stored attachments
|
|
82
|
+
let attachments: StoredAttachment[] | undefined;
|
|
83
|
+
if (m.attachments) {
|
|
84
|
+
try {
|
|
85
|
+
attachments = JSON.parse(m.attachments);
|
|
86
|
+
} catch { /* ignore malformed */ }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
id: m.id,
|
|
91
|
+
role: m.role,
|
|
92
|
+
content: m.content,
|
|
93
|
+
timestamp: m.created_at,
|
|
94
|
+
audioData,
|
|
95
|
+
hasAttachments: !!(attachments && attachments.length > 0),
|
|
96
|
+
attachments,
|
|
97
|
+
};
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.catch(() => {
|
|
103
|
+
// Conversation gone — clear
|
|
104
|
+
setConversationId(null);
|
|
105
|
+
fetch('/api/context/clear', { method: 'POST' }).catch(() => {});
|
|
106
|
+
});
|
|
116
107
|
}, [conversationId]);
|
|
117
108
|
|
|
118
109
|
// Persist conversationId to DB when it changes
|
|
@@ -132,8 +123,7 @@ export function useChat(ws: WsClient | null) {
|
|
|
132
123
|
if (!ws) return;
|
|
133
124
|
|
|
134
125
|
const unsubs = [
|
|
135
|
-
ws.on('bot:typing', (
|
|
136
|
-
if (data.conversationId) setConversationId(data.conversationId);
|
|
126
|
+
ws.on('bot:typing', () => {
|
|
137
127
|
setStreaming(true);
|
|
138
128
|
setTools([]);
|
|
139
129
|
}),
|
|
@@ -233,14 +223,13 @@ export function useChat(ws: WsClient | null) {
|
|
|
233
223
|
}, [ws, conversationId]);
|
|
234
224
|
|
|
235
225
|
const clearContext = useCallback(() => {
|
|
236
|
-
// Clear UI state only — starts a fresh conversation on next message.
|
|
237
|
-
// Old messages stay in DB (used as context for the agent).
|
|
238
226
|
setMessages([]);
|
|
239
227
|
setConversationId(null);
|
|
240
228
|
setStreamBuffer('');
|
|
241
229
|
setStreaming(false);
|
|
242
230
|
setTools([]);
|
|
243
231
|
prevConvId.current = null;
|
|
232
|
+
loaded.current = false;
|
|
244
233
|
fetch('/api/context/clear', { method: 'POST' }).catch(() => {});
|
|
245
234
|
}, []);
|
|
246
235
|
|
|
@@ -20,7 +20,7 @@ export class WsClient {
|
|
|
20
20
|
|
|
21
21
|
constructor(url?: string) {
|
|
22
22
|
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
23
|
-
const host = location.host;
|
|
23
|
+
const host = import.meta.env.DEV ? 'localhost:3000' : location.host;
|
|
24
24
|
this.url = url ?? `${proto}//${host}/ws`;
|
|
25
25
|
}
|
|
26
26
|
|