fluxy-bot 0.3.2 → 0.3.3
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/dist-fluxy/fluxy.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
|
|
6
6
|
<title>Fluxy Chat</title>
|
|
7
|
-
<script type="module" crossorigin src="/fluxy/assets/fluxy-
|
|
7
|
+
<script type="module" crossorigin src="/fluxy/assets/fluxy-C6-vL18Q.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/fluxy/assets/globals-Bu5tVsgN.js">
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/fluxy/assets/globals-DYOj4b0m.css">
|
|
10
10
|
</head>
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ import { WsClient } from './src/lib/ws-client';
|
|
|
5
5
|
import { useFluxyChat } from './src/hooks/useFluxyChat';
|
|
6
6
|
import OnboardWizard from './OnboardWizard';
|
|
7
7
|
import LoginScreen from './src/components/LoginScreen';
|
|
8
|
-
import { getAuthToken, setAuthToken, clearAuthToken, authFetch } from './src/lib/auth';
|
|
8
|
+
import { getAuthToken, setAuthToken, clearAuthToken, authFetch, onAuthFailure } from './src/lib/auth';
|
|
9
9
|
import MessageList from './src/components/Chat/MessageList';
|
|
10
10
|
import InputBar from './src/components/Chat/InputBar';
|
|
11
11
|
import './src/styles/globals.css';
|
|
@@ -74,6 +74,14 @@ function FluxyApp() {
|
|
|
74
74
|
setAuthenticated(true);
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
+
// Handle mid-session token expiry (authFetch gets 401)
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
onAuthFailure(() => {
|
|
80
|
+
setAuthenticated(false);
|
|
81
|
+
setAuthRequired(true);
|
|
82
|
+
});
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
77
85
|
// Connect WebSocket only when authenticated
|
|
78
86
|
useEffect(() => {
|
|
79
87
|
if (!authenticated) return;
|
|
@@ -145,7 +153,7 @@ function FluxyApp() {
|
|
|
145
153
|
}, [menuOpen]);
|
|
146
154
|
|
|
147
155
|
const { messages, streaming, streamBuffer, tools, sendMessage, stopStreaming, clearContext } =
|
|
148
|
-
useFluxyChat(clientRef.current, reloadTrigger);
|
|
156
|
+
useFluxyChat(clientRef.current, reloadTrigger, authenticated);
|
|
149
157
|
|
|
150
158
|
// Auth gate: show spinner while checking, login screen if needed
|
|
151
159
|
if (!authChecked) {
|
|
@@ -8,7 +8,7 @@ import { authFetch } from '../lib/auth';
|
|
|
8
8
|
* Loads/persists messages via the DB (worker API).
|
|
9
9
|
* Supports cross-device sync via chat:sync WS events.
|
|
10
10
|
*/
|
|
11
|
-
export function useFluxyChat(ws: WsClient | null, triggerReload?: number) {
|
|
11
|
+
export function useFluxyChat(ws: WsClient | null, triggerReload?: number, enabled = true) {
|
|
12
12
|
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
|
13
13
|
const [conversationId, setConversationId] = useState<string | null>(null);
|
|
14
14
|
const [streaming, setStreaming] = useState(false);
|
|
@@ -62,19 +62,19 @@ export function useFluxyChat(ws: WsClient | null, triggerReload?: number) {
|
|
|
62
62
|
} catch { /* worker not ready yet */ }
|
|
63
63
|
}, []);
|
|
64
64
|
|
|
65
|
-
// Load on mount
|
|
65
|
+
// Load on mount (only when enabled/authenticated)
|
|
66
66
|
useEffect(() => {
|
|
67
|
-
if (loaded.current) return;
|
|
67
|
+
if (!enabled || loaded.current) return;
|
|
68
68
|
loaded.current = true;
|
|
69
69
|
loadFromDb();
|
|
70
|
-
}, [loadFromDb]);
|
|
70
|
+
}, [enabled, loadFromDb]);
|
|
71
71
|
|
|
72
72
|
// Reload on reconnect (triggerReload changes)
|
|
73
73
|
useEffect(() => {
|
|
74
|
-
if (triggerReload && triggerReload > 0) {
|
|
74
|
+
if (enabled && triggerReload && triggerReload > 0) {
|
|
75
75
|
loadFromDb();
|
|
76
76
|
}
|
|
77
|
-
}, [triggerReload, loadFromDb]);
|
|
77
|
+
}, [enabled, triggerReload, loadFromDb]);
|
|
78
78
|
|
|
79
79
|
useEffect(() => {
|
|
80
80
|
if (!ws) return;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const TOKEN_KEY = 'fluxy_token';
|
|
2
2
|
|
|
3
|
+
let authFailureCallback: (() => void) | null = null;
|
|
4
|
+
|
|
3
5
|
export function getAuthToken(): string | null {
|
|
4
6
|
return localStorage.getItem(TOKEN_KEY);
|
|
5
7
|
}
|
|
@@ -12,6 +14,11 @@ export function clearAuthToken(): void {
|
|
|
12
14
|
localStorage.removeItem(TOKEN_KEY);
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
/** Register a callback for when a 401 is received (token expired mid-session) */
|
|
18
|
+
export function onAuthFailure(cb: () => void): void {
|
|
19
|
+
authFailureCallback = cb;
|
|
20
|
+
}
|
|
21
|
+
|
|
15
22
|
export async function authFetch(url: string, options: RequestInit = {}): Promise<Response> {
|
|
16
23
|
const token = getAuthToken();
|
|
17
24
|
const headers = new Headers(options.headers);
|
|
@@ -21,9 +28,10 @@ export async function authFetch(url: string, options: RequestInit = {}): Promise
|
|
|
21
28
|
|
|
22
29
|
const res = await fetch(url, { ...options, headers });
|
|
23
30
|
|
|
24
|
-
if (res.status === 401) {
|
|
31
|
+
if (res.status === 401 && token) {
|
|
32
|
+
// Token was present but rejected — it expired
|
|
25
33
|
clearAuthToken();
|
|
26
|
-
|
|
34
|
+
authFailureCallback?.();
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
return res;
|