@schlessera/brain-ui-react 0.4.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/components/chat/ask-user-card.d.ts +12 -0
- package/dist/components/chat/ask-user-card.d.ts.map +1 -0
- package/dist/components/chat/ask-user-card.js +185 -0
- package/dist/components/chat/ask-user-card.js.map +1 -0
- package/dist/components/chat/brain-markdown.d.ts +35 -0
- package/dist/components/chat/brain-markdown.d.ts.map +1 -0
- package/dist/components/chat/brain-markdown.js +363 -0
- package/dist/components/chat/brain-markdown.js.map +1 -0
- package/dist/components/chat/chat-page.d.ts +2 -0
- package/dist/components/chat/chat-page.d.ts.map +1 -0
- package/dist/components/chat/chat-page.js +442 -0
- package/dist/components/chat/chat-page.js.map +1 -0
- package/dist/components/chat/command-palette.d.ts +5 -0
- package/dist/components/chat/command-palette.d.ts.map +1 -0
- package/dist/components/chat/command-palette.js +18 -0
- package/dist/components/chat/command-palette.js.map +1 -0
- package/dist/components/chat/markdown-content.d.ts +4 -0
- package/dist/components/chat/markdown-content.d.ts.map +1 -0
- package/dist/components/chat/markdown-content.js +6 -0
- package/dist/components/chat/markdown-content.js.map +1 -0
- package/dist/components/chat/message-bubble.d.ts +9 -0
- package/dist/components/chat/message-bubble.d.ts.map +1 -0
- package/dist/components/chat/message-bubble.js +129 -0
- package/dist/components/chat/message-bubble.js.map +1 -0
- package/dist/components/chat/message-share.d.ts +10 -0
- package/dist/components/chat/message-share.d.ts.map +1 -0
- package/dist/components/chat/message-share.js +65 -0
- package/dist/components/chat/message-share.js.map +1 -0
- package/dist/components/chat/renderers/claude-tools.d.ts +3 -0
- package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -0
- package/dist/components/chat/renderers/claude-tools.js +38 -0
- package/dist/components/chat/renderers/claude-tools.js.map +1 -0
- package/dist/components/chat/renderers/generic.d.ts +9 -0
- package/dist/components/chat/renderers/generic.d.ts.map +1 -0
- package/dist/components/chat/renderers/generic.js +68 -0
- package/dist/components/chat/renderers/generic.js.map +1 -0
- package/dist/components/chat/renderers/index.d.ts +5 -0
- package/dist/components/chat/renderers/index.d.ts.map +1 -0
- package/dist/components/chat/renderers/index.js +17 -0
- package/dist/components/chat/renderers/index.js.map +1 -0
- package/dist/components/chat/risk-hints.d.ts +20 -0
- package/dist/components/chat/risk-hints.d.ts.map +1 -0
- package/dist/components/chat/risk-hints.js +81 -0
- package/dist/components/chat/risk-hints.js.map +1 -0
- package/dist/components/chat/session-drawer.d.ts +6 -0
- package/dist/components/chat/session-drawer.d.ts.map +1 -0
- package/dist/components/chat/session-drawer.js +96 -0
- package/dist/components/chat/session-drawer.js.map +1 -0
- package/dist/components/chat/share-block.d.ts +9 -0
- package/dist/components/chat/share-block.d.ts.map +1 -0
- package/dist/components/chat/share-block.js +70 -0
- package/dist/components/chat/share-block.js.map +1 -0
- package/dist/components/chat/tool-call-timeline.d.ts +8 -0
- package/dist/components/chat/tool-call-timeline.d.ts.map +1 -0
- package/dist/components/chat/tool-call-timeline.js +100 -0
- package/dist/components/chat/tool-call-timeline.js.map +1 -0
- package/dist/components/chat/tool-views.d.ts +116 -0
- package/dist/components/chat/tool-views.d.ts.map +1 -0
- package/dist/components/chat/tool-views.js +628 -0
- package/dist/components/chat/tool-views.js.map +1 -0
- package/dist/components/chat/welcome-state.d.ts +4 -0
- package/dist/components/chat/welcome-state.d.ts.map +1 -0
- package/dist/components/chat/welcome-state.js +10 -0
- package/dist/components/chat/welcome-state.js.map +1 -0
- package/dist/components/connectivity/connection-gate.d.ts +5 -0
- package/dist/components/connectivity/connection-gate.d.ts.map +1 -0
- package/dist/components/connectivity/connection-gate.js +42 -0
- package/dist/components/connectivity/connection-gate.js.map +1 -0
- package/dist/components/connectivity/login-screen.d.ts +9 -0
- package/dist/components/connectivity/login-screen.d.ts.map +1 -0
- package/dist/components/connectivity/login-screen.js +99 -0
- package/dist/components/connectivity/login-screen.js.map +1 -0
- package/dist/components/files/file-panel.d.ts +5 -0
- package/dist/components/files/file-panel.d.ts.map +1 -0
- package/dist/components/files/file-panel.js +46 -0
- package/dist/components/files/file-panel.js.map +1 -0
- package/dist/components/files/file-tree.d.ts +2 -0
- package/dist/components/files/file-tree.d.ts.map +1 -0
- package/dist/components/files/file-tree.js +63 -0
- package/dist/components/files/file-tree.js.map +1 -0
- package/dist/components/files/file-viewer-binary.d.ts +5 -0
- package/dist/components/files/file-viewer-binary.d.ts.map +1 -0
- package/dist/components/files/file-viewer-binary.js +20 -0
- package/dist/components/files/file-viewer-binary.js.map +1 -0
- package/dist/components/files/file-viewer-html.d.ts +4 -0
- package/dist/components/files/file-viewer-html.d.ts.map +1 -0
- package/dist/components/files/file-viewer-html.js +5 -0
- package/dist/components/files/file-viewer-html.js.map +1 -0
- package/dist/components/files/file-viewer-markdown.d.ts +4 -0
- package/dist/components/files/file-viewer-markdown.d.ts.map +1 -0
- package/dist/components/files/file-viewer-markdown.js +10 -0
- package/dist/components/files/file-viewer-markdown.js.map +1 -0
- package/dist/components/files/file-viewer-raw.d.ts +5 -0
- package/dist/components/files/file-viewer-raw.d.ts.map +1 -0
- package/dist/components/files/file-viewer-raw.js +15 -0
- package/dist/components/files/file-viewer-raw.js.map +1 -0
- package/dist/components/files/file-viewer.d.ts +2 -0
- package/dist/components/files/file-viewer.d.ts.map +1 -0
- package/dist/components/files/file-viewer.js +175 -0
- package/dist/components/files/file-viewer.js.map +1 -0
- package/dist/components/files/frontmatter-panel.d.ts +5 -0
- package/dist/components/files/frontmatter-panel.d.ts.map +1 -0
- package/dist/components/files/frontmatter-panel.js +12 -0
- package/dist/components/files/frontmatter-panel.js.map +1 -0
- package/dist/components/layout/app-shell.d.ts +5 -0
- package/dist/components/layout/app-shell.d.ts.map +1 -0
- package/dist/components/layout/app-shell.js +10 -0
- package/dist/components/layout/app-shell.js.map +1 -0
- package/dist/components/layout/mobile-tab-bar.d.ts +2 -0
- package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -0
- package/dist/components/layout/mobile-tab-bar.js +16 -0
- package/dist/components/layout/mobile-tab-bar.js.map +1 -0
- package/dist/components/layout/side-rail.d.ts +2 -0
- package/dist/components/layout/side-rail.d.ts.map +1 -0
- package/dist/components/layout/side-rail.js +26 -0
- package/dist/components/layout/side-rail.js.map +1 -0
- package/dist/components/layout/slide-panel.d.ts +9 -0
- package/dist/components/layout/slide-panel.d.ts.map +1 -0
- package/dist/components/layout/slide-panel.js +18 -0
- package/dist/components/layout/slide-panel.js.map +1 -0
- package/dist/components/quick-actions/streaming-modal.d.ts +8 -0
- package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -0
- package/dist/components/quick-actions/streaming-modal.js +92 -0
- package/dist/components/quick-actions/streaming-modal.js.map +1 -0
- package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
- package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -0
- package/dist/components/quick-actions/whatsup-modal.js +82 -0
- package/dist/components/quick-actions/whatsup-modal.js.map +1 -0
- package/dist/components/settings/passkey-panel.d.ts +10 -0
- package/dist/components/settings/passkey-panel.d.ts.map +1 -0
- package/dist/components/settings/passkey-panel.js +118 -0
- package/dist/components/settings/passkey-panel.js.map +1 -0
- package/dist/components/share/share-menu.d.ts +23 -0
- package/dist/components/share/share-menu.d.ts.map +1 -0
- package/dist/components/share/share-menu.js +58 -0
- package/dist/components/share/share-menu.js.map +1 -0
- package/dist/components/voice/dictation-sheet.d.ts +6 -0
- package/dist/components/voice/dictation-sheet.d.ts.map +1 -0
- package/dist/components/voice/dictation-sheet.js +91 -0
- package/dist/components/voice/dictation-sheet.js.map +1 -0
- package/dist/components/voice/mic-button.d.ts +6 -0
- package/dist/components/voice/mic-button.d.ts.map +1 -0
- package/dist/components/voice/mic-button.js +9 -0
- package/dist/components/voice/mic-button.js.map +1 -0
- package/dist/components/voice/review-card.d.ts +8 -0
- package/dist/components/voice/review-card.d.ts.map +1 -0
- package/dist/components/voice/review-card.js +8 -0
- package/dist/components/voice/review-card.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks/use-vpn-status.d.ts +2 -0
- package/dist/hooks/use-vpn-status.d.ts.map +1 -0
- package/dist/hooks/use-vpn-status.js +71 -0
- package/dist/hooks/use-vpn-status.js.map +1 -0
- package/dist/hooks/use-websocket.d.ts +8 -0
- package/dist/hooks/use-websocket.d.ts.map +1 -0
- package/dist/hooks/use-websocket.js +366 -0
- package/dist/hooks/use-websocket.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +115 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +70 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/backend.d.ts +7 -0
- package/dist/lib/backend.d.ts.map +1 -0
- package/dist/lib/backend.js +33 -0
- package/dist/lib/backend.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +21 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +88 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/image-attachments.d.ts +36 -0
- package/dist/lib/image-attachments.d.ts.map +1 -0
- package/dist/lib/image-attachments.js +175 -0
- package/dist/lib/image-attachments.js.map +1 -0
- package/dist/lib/passkeys.d.ts +18 -0
- package/dist/lib/passkeys.d.ts.map +1 -0
- package/dist/lib/passkeys.js +36 -0
- package/dist/lib/passkeys.js.map +1 -0
- package/dist/lib/share.d.ts +53 -0
- package/dist/lib/share.d.ts.map +1 -0
- package/dist/lib/share.js +144 -0
- package/dist/lib/share.js.map +1 -0
- package/dist/lib/strip-markdown.d.ts +10 -0
- package/dist/lib/strip-markdown.d.ts.map +1 -0
- package/dist/lib/strip-markdown.js +37 -0
- package/dist/lib/strip-markdown.js.map +1 -0
- package/dist/lib/tool-names.d.ts +17 -0
- package/dist/lib/tool-names.d.ts.map +1 -0
- package/dist/lib/tool-names.js +23 -0
- package/dist/lib/tool-names.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/ws-client.d.ts +26 -0
- package/dist/lib/ws-client.d.ts.map +1 -0
- package/dist/lib/ws-client.js +93 -0
- package/dist/lib/ws-client.js.map +1 -0
- package/dist/stores/chat-store.d.ts +131 -0
- package/dist/stores/chat-store.d.ts.map +1 -0
- package/dist/stores/chat-store.js +376 -0
- package/dist/stores/chat-store.js.map +1 -0
- package/dist/stores/connection-store.d.ts +11 -0
- package/dist/stores/connection-store.d.ts.map +1 -0
- package/dist/stores/connection-store.js +8 -0
- package/dist/stores/connection-store.js.map +1 -0
- package/dist/stores/file-store.d.ts +53 -0
- package/dist/stores/file-store.d.ts.map +1 -0
- package/dist/stores/file-store.js +284 -0
- package/dist/stores/file-store.js.map +1 -0
- package/dist/stores/provider-store.d.ts +24 -0
- package/dist/stores/provider-store.d.ts.map +1 -0
- package/dist/stores/provider-store.js +56 -0
- package/dist/stores/provider-store.js.map +1 -0
- package/dist/stores/ui-store.d.ts +21 -0
- package/dist/stores/ui-store.d.ts.map +1 -0
- package/dist/stores/ui-store.js +23 -0
- package/dist/stores/ui-store.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/voice/asr-clients.d.ts +2 -0
- package/dist/voice/asr-clients.d.ts.map +1 -0
- package/dist/voice/asr-clients.js +33 -0
- package/dist/voice/asr-clients.js.map +1 -0
- package/dist/voice/asr-deepgram.d.ts +38 -0
- package/dist/voice/asr-deepgram.d.ts.map +1 -0
- package/dist/voice/asr-deepgram.js +307 -0
- package/dist/voice/asr-deepgram.js.map +1 -0
- package/dist/voice/asr-webspeech.d.ts +23 -0
- package/dist/voice/asr-webspeech.d.ts.map +1 -0
- package/dist/voice/asr-webspeech.js +93 -0
- package/dist/voice/asr-webspeech.js.map +1 -0
- package/dist/voice/use-dictation.d.ts +6 -0
- package/dist/voice/use-dictation.d.ts.map +1 -0
- package/dist/voice/use-dictation.js +174 -0
- package/dist/voice/use-dictation.js.map +1 -0
- package/dist/voice/voice-store.d.ts +26 -0
- package/dist/voice/voice-store.d.ts.map +1 -0
- package/dist/voice/voice-store.js +27 -0
- package/dist/voice/voice-store.js.map +1 -0
- package/package.json +71 -0
- package/src/components/chat/ask-user-card.tsx +451 -0
- package/src/components/chat/brain-markdown.tsx +547 -0
- package/src/components/chat/chat-page.tsx +820 -0
- package/src/components/chat/command-palette.tsx +68 -0
- package/src/components/chat/markdown-content.tsx +5 -0
- package/src/components/chat/message-bubble.tsx +362 -0
- package/src/components/chat/message-share.ts +78 -0
- package/src/components/chat/renderers/claude-tools.tsx +53 -0
- package/src/components/chat/renderers/generic.tsx +85 -0
- package/src/components/chat/renderers/index.ts +19 -0
- package/src/components/chat/risk-hints.ts +95 -0
- package/src/components/chat/session-drawer.tsx +213 -0
- package/src/components/chat/share-block.tsx +128 -0
- package/src/components/chat/tool-call-timeline.tsx +322 -0
- package/src/components/chat/tool-views.tsx +898 -0
- package/src/components/chat/welcome-state.tsx +105 -0
- package/src/components/connectivity/connection-gate.tsx +137 -0
- package/src/components/connectivity/login-screen.tsx +169 -0
- package/src/components/files/file-panel.tsx +116 -0
- package/src/components/files/file-tree.tsx +143 -0
- package/src/components/files/file-viewer-binary.tsx +63 -0
- package/src/components/files/file-viewer-html.tsx +10 -0
- package/src/components/files/file-viewer-markdown.tsx +14 -0
- package/src/components/files/file-viewer-raw.tsx +44 -0
- package/src/components/files/file-viewer.tsx +290 -0
- package/src/components/files/frontmatter-panel.tsx +78 -0
- package/src/components/layout/app-shell.tsx +25 -0
- package/src/components/layout/mobile-tab-bar.tsx +54 -0
- package/src/components/layout/side-rail.tsx +128 -0
- package/src/components/layout/slide-panel.tsx +64 -0
- package/src/components/quick-actions/streaming-modal.tsx +168 -0
- package/src/components/quick-actions/whatsup-modal.tsx +149 -0
- package/src/components/settings/passkey-panel.tsx +281 -0
- package/src/components/share/share-menu.tsx +121 -0
- package/src/components/voice/dictation-sheet.tsx +217 -0
- package/src/components/voice/mic-button.tsx +31 -0
- package/src/components/voice/review-card.tsx +66 -0
- package/src/config.ts +27 -0
- package/src/hooks/use-vpn-status.ts +75 -0
- package/src/hooks/use-websocket.ts +403 -0
- package/src/index.ts +46 -0
- package/src/lib/api-client.ts +173 -0
- package/src/lib/backend.ts +35 -0
- package/src/lib/frontmatter.ts +99 -0
- package/src/lib/image-attachments.ts +221 -0
- package/src/lib/passkeys.ts +50 -0
- package/src/lib/share.ts +167 -0
- package/src/lib/strip-markdown.ts +38 -0
- package/src/lib/tool-names.ts +27 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/ws-client.ts +109 -0
- package/src/stores/chat-store.ts +619 -0
- package/src/stores/connection-store.ts +23 -0
- package/src/stores/file-store.ts +344 -0
- package/src/stores/provider-store.ts +85 -0
- package/src/stores/ui-store.ts +48 -0
- package/src/styles.css +4 -0
- package/src/theme.css +425 -0
- package/src/voice/asr-clients.ts +45 -0
- package/src/voice/asr-deepgram.ts +325 -0
- package/src/voice/asr-webspeech.ts +135 -0
- package/src/voice/use-dictation.ts +187 -0
- package/src/voice/voice-store.ts +55 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { useEffect, useRef, useCallback } from "react";
|
|
2
|
+
import { WSClient } from "../lib/ws-client.js";
|
|
3
|
+
import { useConnectionStore } from "../stores/connection-store.js";
|
|
4
|
+
import { useChatStore, activeChat } from "../stores/chat-store.js";
|
|
5
|
+
import { useProviderStore } from "../stores/provider-store.js";
|
|
6
|
+
import { getWsUrl } from "../lib/backend.js";
|
|
7
|
+
import { isAskUserTool } from "../lib/tool-names.js";
|
|
8
|
+
let historyMessageCounter = 0;
|
|
9
|
+
function historyId() {
|
|
10
|
+
return `hist-${++historyMessageCounter}-${Date.now()}`;
|
|
11
|
+
}
|
|
12
|
+
function convertHistoryMessage(msg) {
|
|
13
|
+
// Fallback for history without chronological parts: synthesize the legacy
|
|
14
|
+
// grouped order (thinking, tools, text).
|
|
15
|
+
const parts = msg.parts ??
|
|
16
|
+
[
|
|
17
|
+
...(msg.thinking ? [{ kind: "thinking", text: msg.thinking }] : []),
|
|
18
|
+
...msg.toolCalls.map((_, i) => ({ kind: "tool", toolIndex: i })),
|
|
19
|
+
...(msg.content ? [{ kind: "text", text: msg.content }] : []),
|
|
20
|
+
];
|
|
21
|
+
const askUserExchanges = reconstructAskUserExchanges(msg.toolCalls);
|
|
22
|
+
return {
|
|
23
|
+
id: historyId(),
|
|
24
|
+
role: msg.role,
|
|
25
|
+
content: msg.content,
|
|
26
|
+
thinking: msg.thinking,
|
|
27
|
+
toolCalls: msg.toolCalls.map((tc) => ({
|
|
28
|
+
id: tc.id,
|
|
29
|
+
name: tc.name,
|
|
30
|
+
input: tc.input,
|
|
31
|
+
inputJson: JSON.stringify(tc.input, null, 2),
|
|
32
|
+
output: tc.output,
|
|
33
|
+
isError: tc.isError,
|
|
34
|
+
status: "complete",
|
|
35
|
+
})),
|
|
36
|
+
parts,
|
|
37
|
+
isStreaming: false,
|
|
38
|
+
timestamp: Date.now(),
|
|
39
|
+
...(askUserExchanges ? { askUserExchanges } : {}),
|
|
40
|
+
...(msg.attachmentCount ? { attachmentCount: msg.attachmentCount } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Rebuild ask_user exchanges from a resumed message's tool calls. The ask_user
|
|
45
|
+
* tool's input carries the questions and its output carries the JSON answer
|
|
46
|
+
* payload, so an answered question survives session resume (rendered in its
|
|
47
|
+
* chronological slot, collapsed) instead of vanishing.
|
|
48
|
+
*/
|
|
49
|
+
function reconstructAskUserExchanges(toolCalls) {
|
|
50
|
+
const exchanges = [];
|
|
51
|
+
for (const tc of toolCalls) {
|
|
52
|
+
if (!isAskUserTool(tc.name))
|
|
53
|
+
continue;
|
|
54
|
+
const questions = tc.input?.questions ?? [];
|
|
55
|
+
const exchange = { requestId: tc.id, questions };
|
|
56
|
+
if (tc.output) {
|
|
57
|
+
try {
|
|
58
|
+
const payload = JSON.parse(tc.output);
|
|
59
|
+
exchange.answers = payload.answers;
|
|
60
|
+
exchange.annotations = payload.annotations;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Non-JSON output means the question was dismissed or errored out.
|
|
64
|
+
exchange.cancelled = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (tc.isError && !exchange.answers)
|
|
68
|
+
exchange.cancelled = true;
|
|
69
|
+
exchanges.push(exchange);
|
|
70
|
+
}
|
|
71
|
+
return exchanges.length ? exchanges : undefined;
|
|
72
|
+
}
|
|
73
|
+
/** Map a frame to the run-state its session should show in the session list. */
|
|
74
|
+
export function runStateForFrame(msg) {
|
|
75
|
+
if (msg.type === "result" || msg.type === "error")
|
|
76
|
+
return "idle";
|
|
77
|
+
if (msg.type === "status") {
|
|
78
|
+
if (msg.status === "queued")
|
|
79
|
+
return "queued";
|
|
80
|
+
if (msg.status === "idle" || msg.status === "cancelled")
|
|
81
|
+
return "idle";
|
|
82
|
+
}
|
|
83
|
+
return "streaming";
|
|
84
|
+
}
|
|
85
|
+
export function handleServerMessage(msg) {
|
|
86
|
+
const state = useChatStore.getState();
|
|
87
|
+
// Parallel-session demux (per-session buffers). Every frame is scoped by
|
|
88
|
+
// sessionId; a scoped frame lands in ITS session's buffer, so a background
|
|
89
|
+
// session's transcript keeps accumulating while another one is in view.
|
|
90
|
+
// Frames without a sessionId (legacy single-session servers, or a new
|
|
91
|
+
// session's pre-binding frames) apply to the buffer in view.
|
|
92
|
+
const frameSessionId = msg.sessionId;
|
|
93
|
+
if (frameSessionId) {
|
|
94
|
+
state.setRunState(frameSessionId, runStateForFrame(msg));
|
|
95
|
+
}
|
|
96
|
+
// Resolve the target buffer key for this frame.
|
|
97
|
+
let key;
|
|
98
|
+
if (!frameSessionId) {
|
|
99
|
+
key = state.activeSessionId; // null = the draft view
|
|
100
|
+
}
|
|
101
|
+
else if (state.buffers[frameSessionId]) {
|
|
102
|
+
key = frameSessionId;
|
|
103
|
+
}
|
|
104
|
+
else if (state.draft && (msg.type === "session_info" || msg.type === "result")) {
|
|
105
|
+
// A draft run just got its server identity: adopt the draft buffer.
|
|
106
|
+
state.bindDraftSession(frameSessionId);
|
|
107
|
+
key = frameSessionId;
|
|
108
|
+
}
|
|
109
|
+
else if (msg.type === "session_info" && frameSessionId === state.activeSessionId) {
|
|
110
|
+
// The ACTIVE session announced itself but has no buffer yet — the cold
|
|
111
|
+
// reattach case (PWA relaunch mid-turn; the server may skip the history
|
|
112
|
+
// frame when a first turn has no history yet). Materialize the buffer so
|
|
113
|
+
// this session_info and every following delta land instead of vanishing.
|
|
114
|
+
state.setActiveSession(frameSessionId);
|
|
115
|
+
key = frameSessionId;
|
|
116
|
+
}
|
|
117
|
+
else if (msg.type === "session_history") {
|
|
118
|
+
// History replay may create a buffer (cold resume / reattach).
|
|
119
|
+
key = frameSessionId;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Scoped frame for a session with no buffer (never opened, or evicted):
|
|
123
|
+
// the badge above is all we track. The transcript heals via
|
|
124
|
+
// session_resume when the user opens it.
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const buffer = () => {
|
|
128
|
+
const s = useChatStore.getState();
|
|
129
|
+
return key === null ? s.draft : s.buffers[key];
|
|
130
|
+
};
|
|
131
|
+
switch (msg.type) {
|
|
132
|
+
case "text_delta":
|
|
133
|
+
if (!buffer()?.isStreaming) {
|
|
134
|
+
state.startAssistantMessage(key);
|
|
135
|
+
}
|
|
136
|
+
state.appendText(key, msg.text);
|
|
137
|
+
break;
|
|
138
|
+
case "thinking_delta":
|
|
139
|
+
if (!buffer()?.isStreaming) {
|
|
140
|
+
state.startAssistantMessage(key);
|
|
141
|
+
}
|
|
142
|
+
state.appendThinking(key, msg.text);
|
|
143
|
+
break;
|
|
144
|
+
case "tool_use_start":
|
|
145
|
+
state.startToolCall(key, msg.toolUseId, msg.toolName);
|
|
146
|
+
break;
|
|
147
|
+
case "tool_input_delta":
|
|
148
|
+
state.appendToolInput(key, msg.partialJson);
|
|
149
|
+
break;
|
|
150
|
+
case "tool_use_complete":
|
|
151
|
+
state.completeToolCall(key, msg.toolUseId, msg.toolName, msg.input);
|
|
152
|
+
break;
|
|
153
|
+
case "tool_approval_request":
|
|
154
|
+
state.requestToolApproval(key, msg.toolUseId, msg.toolName, msg.input, msg.description);
|
|
155
|
+
break;
|
|
156
|
+
case "tool_result": {
|
|
157
|
+
state.setToolResult(key, msg.toolUseId, msg.output, msg.isError);
|
|
158
|
+
// Once the agent receives the ask_user tool result, the exchange is
|
|
159
|
+
// complete — drop any leftover ask_user UI state.
|
|
160
|
+
const chat = buffer();
|
|
161
|
+
if (chat?.askUser?.answers || chat?.askUser?.cancelled) {
|
|
162
|
+
state.clearAskUser(key);
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case "ask_user_request":
|
|
167
|
+
state.setAskUserRequest(key, msg.requestId, msg.questions);
|
|
168
|
+
break;
|
|
169
|
+
case "location_request":
|
|
170
|
+
requestBrowserLocation(msg);
|
|
171
|
+
break;
|
|
172
|
+
case "result":
|
|
173
|
+
state.finishAssistantMessage(key);
|
|
174
|
+
resyncIfNeeded(msg.sessionId);
|
|
175
|
+
break;
|
|
176
|
+
case "session_info": {
|
|
177
|
+
// bindDraftSession above handled draft adoption; an info frame may still
|
|
178
|
+
// re-pin the provider picker when it concerns the session in view.
|
|
179
|
+
const current = useChatStore.getState();
|
|
180
|
+
if (frameSessionId && frameSessionId === current.activeSessionId) {
|
|
181
|
+
useProviderStore.getState().setPinned(msg.providerId ?? null);
|
|
182
|
+
// Reattachment on a fresh connection: enter streaming mode so deltas
|
|
183
|
+
// append to a live assistant message instead of vanishing.
|
|
184
|
+
const chat = current.buffers[frameSessionId];
|
|
185
|
+
if (chat && !chat.isStreaming && chat.messages.length === 0) {
|
|
186
|
+
current.startAssistantMessage(frameSessionId);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
case "session_history": {
|
|
192
|
+
const converted = msg.messages.map(convertHistoryMessage);
|
|
193
|
+
if (msg.append) {
|
|
194
|
+
state.appendMessages(key, converted);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
// First (replacing) chunk = fresh authoritative transcript. Cancel any
|
|
198
|
+
// pending reconnect resync so we don't redundantly re-fetch it, and
|
|
199
|
+
// mark this session cold-resumed so idle-status handling doesn't loop.
|
|
200
|
+
state.setMessages(key, converted);
|
|
201
|
+
if (key !== null && key === resyncSessionId)
|
|
202
|
+
resyncSessionId = null;
|
|
203
|
+
coldResumedSessionId = key;
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case "status": {
|
|
208
|
+
// Only finish streaming if this buffer actually started it
|
|
209
|
+
if ((msg.status === "idle" || msg.status === "cancelled") &&
|
|
210
|
+
buffer()?.isStreaming) {
|
|
211
|
+
state.finishAssistantMessage(key);
|
|
212
|
+
}
|
|
213
|
+
// A session that finished while we were offline never delivers its
|
|
214
|
+
// `result` — the idle status on reconnect is the cue to resync. Keyed to
|
|
215
|
+
// THIS frame's session: a background session settling must not consume
|
|
216
|
+
// (or trigger) the active session's pending resync.
|
|
217
|
+
if (msg.status === "idle" || msg.status === "cancelled") {
|
|
218
|
+
const current = useChatStore.getState();
|
|
219
|
+
resyncIfNeeded(frameSessionId ?? current.activeSessionId);
|
|
220
|
+
// Cold load: we hold a stored session id but an empty transcript and
|
|
221
|
+
// the server is idle (so it sent no snapshot). Fetch the history.
|
|
222
|
+
// Only the active session's own (or an unscoped legacy) idle counts.
|
|
223
|
+
if (!frameSessionId || frameSessionId === current.activeSessionId) {
|
|
224
|
+
coldResumeIfNeeded(current.activeSessionId, activeChat(current).messages.length);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case "error":
|
|
230
|
+
if (buffer()?.isStreaming) {
|
|
231
|
+
state.appendText(key, `\n\n**Error:** ${msg.message}`);
|
|
232
|
+
state.finishAssistantMessage(key);
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* The server asked the browser for its location (the agent called
|
|
239
|
+
* `get_current_location`). Read `navigator.geolocation` and reply over the same
|
|
240
|
+
* requestId. The browser shows its own permission prompt on first use; a denial,
|
|
241
|
+
* timeout, or unavailable position comes back as a `location_error` that the
|
|
242
|
+
* server turns into a tool error for the agent.
|
|
243
|
+
*/
|
|
244
|
+
function requestBrowserLocation(msg) {
|
|
245
|
+
const { requestId } = msg;
|
|
246
|
+
if (typeof navigator === "undefined" || !navigator.geolocation) {
|
|
247
|
+
wsClient?.send({
|
|
248
|
+
type: "location_error",
|
|
249
|
+
requestId,
|
|
250
|
+
code: 0,
|
|
251
|
+
message: "Geolocation is not available in this browser.",
|
|
252
|
+
});
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const opts = msg.options ?? {};
|
|
256
|
+
navigator.geolocation.getCurrentPosition((pos) => {
|
|
257
|
+
wsClient?.send({
|
|
258
|
+
type: "location_response",
|
|
259
|
+
requestId,
|
|
260
|
+
coords: {
|
|
261
|
+
latitude: pos.coords.latitude,
|
|
262
|
+
longitude: pos.coords.longitude,
|
|
263
|
+
accuracy: pos.coords.accuracy,
|
|
264
|
+
altitude: pos.coords.altitude,
|
|
265
|
+
altitudeAccuracy: pos.coords.altitudeAccuracy,
|
|
266
|
+
heading: pos.coords.heading,
|
|
267
|
+
speed: pos.coords.speed,
|
|
268
|
+
},
|
|
269
|
+
timestamp: pos.timestamp,
|
|
270
|
+
});
|
|
271
|
+
}, (err) => {
|
|
272
|
+
wsClient?.send({
|
|
273
|
+
type: "location_error",
|
|
274
|
+
requestId,
|
|
275
|
+
code: err.code,
|
|
276
|
+
message: err.message || "Failed to retrieve location.",
|
|
277
|
+
});
|
|
278
|
+
}, {
|
|
279
|
+
enableHighAccuracy: opts.enableHighAccuracy ?? false,
|
|
280
|
+
timeout: opts.timeoutMs ?? 15000,
|
|
281
|
+
maximumAge: opts.maximumAgeMs ?? 60000,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
// Reconnection bookkeeping: after a WS drop, the rendered transcript may have
|
|
285
|
+
// gaps (deltas streamed while offline are lost). We heal by replaying the
|
|
286
|
+
// authoritative session history — immediately if nothing is streaming, or
|
|
287
|
+
// once the in-flight turn settles (result / idle status). The pending resync
|
|
288
|
+
// is keyed to the session that needs healing (the one that was active at the
|
|
289
|
+
// reconnect), so a background session settling first cannot consume it.
|
|
290
|
+
let wasDisconnected = false;
|
|
291
|
+
let resyncSessionId = null;
|
|
292
|
+
function resyncIfNeeded(sessionId) {
|
|
293
|
+
if (!resyncSessionId || !sessionId || sessionId !== resyncSessionId)
|
|
294
|
+
return;
|
|
295
|
+
resyncSessionId = null;
|
|
296
|
+
wsClient?.send({ type: "session_resume", sessionId });
|
|
297
|
+
}
|
|
298
|
+
// A cold page / PWA relaunch restores only the stored session id, not the
|
|
299
|
+
// transcript. The server pushes a snapshot on connect only while a session is
|
|
300
|
+
// actively running; when it's idle (the common "agent finished while the phone
|
|
301
|
+
// slept" case) nothing arrives, so the client must fetch the finished
|
|
302
|
+
// session's history itself. Guarded to fire at most once per session id per
|
|
303
|
+
// connection — an empty session would otherwise re-trigger on every idle
|
|
304
|
+
// status and loop.
|
|
305
|
+
let coldResumedSessionId = null;
|
|
306
|
+
function coldResumeIfNeeded(sessionId, messageCount) {
|
|
307
|
+
if (!sessionId || messageCount > 0)
|
|
308
|
+
return;
|
|
309
|
+
if (coldResumedSessionId === sessionId)
|
|
310
|
+
return;
|
|
311
|
+
coldResumedSessionId = sessionId;
|
|
312
|
+
wsClient?.send({ type: "session_resume", sessionId });
|
|
313
|
+
}
|
|
314
|
+
function handleStatusChange(status) {
|
|
315
|
+
useConnectionStore.getState().setWsStatus(status);
|
|
316
|
+
if (status === "disconnected") {
|
|
317
|
+
wasDisconnected = true;
|
|
318
|
+
// Allow a fresh cold-resume attempt after we reconnect.
|
|
319
|
+
coldResumedSessionId = null;
|
|
320
|
+
}
|
|
321
|
+
else if (status === "connected" && wasDisconnected) {
|
|
322
|
+
wasDisconnected = false;
|
|
323
|
+
const chat = useChatStore.getState();
|
|
324
|
+
const active = activeChat(chat);
|
|
325
|
+
if (chat.activeSessionId && active.messages.length > 0) {
|
|
326
|
+
resyncSessionId = chat.activeSessionId;
|
|
327
|
+
// Not mid-stream: replay right away. Mid-stream: the flag holds until
|
|
328
|
+
// the running turn finishes (result or idle status).
|
|
329
|
+
if (!active.isStreaming) {
|
|
330
|
+
resyncIfNeeded(chat.activeSessionId);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// Singleton client - survives React re-renders
|
|
336
|
+
let wsClient = null;
|
|
337
|
+
export function useWebSocket() {
|
|
338
|
+
const initialized = useRef(false);
|
|
339
|
+
useEffect(() => {
|
|
340
|
+
if (initialized.current)
|
|
341
|
+
return;
|
|
342
|
+
initialized.current = true;
|
|
343
|
+
wsClient = new WSClient(getWsUrl(), handleServerMessage, handleStatusChange);
|
|
344
|
+
wsClient.connect();
|
|
345
|
+
// Skip the exponential backoff when the network demonstrably returns.
|
|
346
|
+
const reconnectNow = () => wsClient?.reconnectNow();
|
|
347
|
+
const onVisible = () => {
|
|
348
|
+
if (document.visibilityState === "visible")
|
|
349
|
+
wsClient?.reconnectNow();
|
|
350
|
+
};
|
|
351
|
+
window.addEventListener("online", reconnectNow);
|
|
352
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
353
|
+
return () => {
|
|
354
|
+
window.removeEventListener("online", reconnectNow);
|
|
355
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
356
|
+
wsClient?.close();
|
|
357
|
+
wsClient = null;
|
|
358
|
+
initialized.current = false;
|
|
359
|
+
};
|
|
360
|
+
}, []);
|
|
361
|
+
const send = useCallback((msg) => {
|
|
362
|
+
wsClient?.send(msg);
|
|
363
|
+
}, []);
|
|
364
|
+
return { send };
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=use-websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-websocket.js","sourceRoot":"","sources":["../../src/hooks/use-websocket.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @schlessera/brain-ui-react — the chat UI as a component library.
|
|
3
|
+
*
|
|
4
|
+
* The deployment shell owns the document: index.html, the mount point, the
|
|
5
|
+
* Vite/PWA build, the service worker, and the theme entry (import ./theme.css
|
|
6
|
+
* into a Tailwind v4 build together with an @source pointing at this package's
|
|
7
|
+
* src, or use the precompiled ./styles.css export). The shell composes the
|
|
8
|
+
* pieces below and calls configureBrainUi() before mounting.
|
|
9
|
+
*/
|
|
10
|
+
export { configureBrainUi, uiConfig, type BrainUiConfig } from "./config.js";
|
|
11
|
+
export { ConnectionGate } from "./components/connectivity/connection-gate.js";
|
|
12
|
+
export { AppShell } from "./components/layout/app-shell.js";
|
|
13
|
+
export { ChatPage } from "./components/chat/chat-page.js";
|
|
14
|
+
export { BrainMarkdown } from "./components/chat/brain-markdown.js";
|
|
15
|
+
export { useChatStore, activeChat, anyStreaming, type ChatKey, type ChatMessage, type SessionChat, type ToolCall, type AskUserExchange, type MessageAttachment, } from "./stores/chat-store.js";
|
|
16
|
+
export { useFileStore } from "./stores/file-store.js";
|
|
17
|
+
export { useUIStore } from "./stores/ui-store.js";
|
|
18
|
+
export { useConnectionStore } from "./stores/connection-store.js";
|
|
19
|
+
export { useProviderStore } from "./stores/provider-store.js";
|
|
20
|
+
export { useVoiceStore } from "./voice/voice-store.js";
|
|
21
|
+
export { useVpnStatus } from "./hooks/use-vpn-status.js";
|
|
22
|
+
export { useWebSocket, handleServerMessage, runStateForFrame } from "./hooks/use-websocket.js";
|
|
23
|
+
export { api } from "./lib/api-client.js";
|
|
24
|
+
export { API_BASE, getWsUrl, getBackendUrl } from "./lib/backend.js";
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAG7E,OAAO,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAGpE,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG/F,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @schlessera/brain-ui-react — the chat UI as a component library.
|
|
3
|
+
*
|
|
4
|
+
* The deployment shell owns the document: index.html, the mount point, the
|
|
5
|
+
* Vite/PWA build, the service worker, and the theme entry (import ./theme.css
|
|
6
|
+
* into a Tailwind v4 build together with an @source pointing at this package's
|
|
7
|
+
* src, or use the precompiled ./styles.css export). The shell composes the
|
|
8
|
+
* pieces below and calls configureBrainUi() before mounting.
|
|
9
|
+
*/
|
|
10
|
+
// Branding / copy configuration (module singleton, set once at boot).
|
|
11
|
+
export { configureBrainUi, uiConfig } from "./config.js";
|
|
12
|
+
// Top-level surfaces the shell composes.
|
|
13
|
+
export { ConnectionGate } from "./components/connectivity/connection-gate.js";
|
|
14
|
+
export { AppShell } from "./components/layout/app-shell.js";
|
|
15
|
+
export { ChatPage } from "./components/chat/chat-page.js";
|
|
16
|
+
// Markdown renderer (also useful standalone, e.g. for a dev kitchen sink).
|
|
17
|
+
export { BrainMarkdown } from "./components/chat/brain-markdown.js";
|
|
18
|
+
// Stores + selectors the shell reads (service-worker busy check, deep links).
|
|
19
|
+
export { useChatStore, activeChat, anyStreaming, } from "./stores/chat-store.js";
|
|
20
|
+
export { useFileStore } from "./stores/file-store.js";
|
|
21
|
+
export { useUIStore } from "./stores/ui-store.js";
|
|
22
|
+
export { useConnectionStore } from "./stores/connection-store.js";
|
|
23
|
+
export { useProviderStore } from "./stores/provider-store.js";
|
|
24
|
+
export { useVoiceStore } from "./voice/voice-store.js";
|
|
25
|
+
// Connectivity probes.
|
|
26
|
+
export { useVpnStatus } from "./hooks/use-vpn-status.js";
|
|
27
|
+
export { useWebSocket, handleServerMessage, runStateForFrame } from "./hooks/use-websocket.js";
|
|
28
|
+
// API surface (typed REST client + backend URL helpers).
|
|
29
|
+
export { api } from "./lib/api-client.js";
|
|
30
|
+
export { API_BASE, getWsUrl, getBackendUrl } from "./lib/backend.js";
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,sEAAsE;AACtE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAE7E,yCAAyC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,8CAA8C,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE1D,2EAA2E;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEpE,8EAA8E;AAC9E,OAAO,EACL,YAAY,EACZ,UAAU,EACV,YAAY,GAOb,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,uBAAuB;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE/F,yDAAyD;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { VoiceKeytermsResponse, VoiceTokenResponse, VoiceSessionResponse, PronunciationOverride, ProviderInfo, PasskeySummary } from "@schlessera/brain-ui-sdk/protocol";
|
|
2
|
+
import type { AuthenticationResponseJSON, RegistrationResponseJSON, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON } from "@simplewebauthn/browser";
|
|
3
|
+
/** Backend id + capability flags the client renders behavior from. */
|
|
4
|
+
export interface BackendInfo {
|
|
5
|
+
id: string;
|
|
6
|
+
capabilities: {
|
|
7
|
+
concurrentSessions: boolean;
|
|
8
|
+
followUp: boolean;
|
|
9
|
+
[key: string]: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare const api: {
|
|
13
|
+
health: () => Promise<{
|
|
14
|
+
status: string;
|
|
15
|
+
uptime: number;
|
|
16
|
+
version: string;
|
|
17
|
+
}>;
|
|
18
|
+
vpnCheck: () => Promise<{
|
|
19
|
+
vpn: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
status: () => Promise<{
|
|
22
|
+
healthy: boolean;
|
|
23
|
+
uptime: number;
|
|
24
|
+
cronJobs: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
lastRunAt: number | null;
|
|
27
|
+
lastStatus: string | null;
|
|
28
|
+
}>;
|
|
29
|
+
activeSession: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
brainSearch: (q: string, opts?: {
|
|
32
|
+
type?: string;
|
|
33
|
+
limit?: number;
|
|
34
|
+
}) => Promise<{
|
|
35
|
+
results: Array<{
|
|
36
|
+
path: string;
|
|
37
|
+
title: string;
|
|
38
|
+
snippet: string;
|
|
39
|
+
score: number;
|
|
40
|
+
}>;
|
|
41
|
+
warnings: string[];
|
|
42
|
+
}>;
|
|
43
|
+
brainBriefing: () => Promise<{
|
|
44
|
+
content: string;
|
|
45
|
+
}>;
|
|
46
|
+
brainStats: () => Promise<{
|
|
47
|
+
documents: number;
|
|
48
|
+
byType: Record<string, number>;
|
|
49
|
+
byStatus: Record<string, number>;
|
|
50
|
+
tags: number;
|
|
51
|
+
links: number;
|
|
52
|
+
}>;
|
|
53
|
+
brainSync: () => Promise<{
|
|
54
|
+
success: boolean;
|
|
55
|
+
message: string;
|
|
56
|
+
}>;
|
|
57
|
+
brainAdd: (content: string, opts?: {
|
|
58
|
+
type?: string;
|
|
59
|
+
title?: string;
|
|
60
|
+
tags?: string[];
|
|
61
|
+
}) => Promise<{
|
|
62
|
+
success: boolean;
|
|
63
|
+
}>;
|
|
64
|
+
sessions: () => Promise<{
|
|
65
|
+
sessions: Array<{
|
|
66
|
+
id: string;
|
|
67
|
+
title: string | null;
|
|
68
|
+
createdAt: number;
|
|
69
|
+
lastActiveAt: number;
|
|
70
|
+
}>;
|
|
71
|
+
}>;
|
|
72
|
+
/** Mint a dictation session for the active speech provider. */
|
|
73
|
+
voiceSession: (signal?: AbortSignal) => Promise<VoiceSessionResponse>;
|
|
74
|
+
/** @deprecated use voiceSession(); kept during client transition. */
|
|
75
|
+
voiceToken: () => Promise<VoiceTokenResponse>;
|
|
76
|
+
voiceKeyterms: () => Promise<VoiceKeytermsResponse>;
|
|
77
|
+
voiceOverrides: (signal?: AbortSignal) => Promise<{
|
|
78
|
+
overrides: PronunciationOverride[];
|
|
79
|
+
}>;
|
|
80
|
+
providers: () => Promise<{
|
|
81
|
+
providers: ProviderInfo[];
|
|
82
|
+
backends?: Record<string, BackendInfo>;
|
|
83
|
+
}>;
|
|
84
|
+
/** Password-mode login. Resolves on success; throws the server error otherwise. */
|
|
85
|
+
login: (password: string) => Promise<{
|
|
86
|
+
ok: true;
|
|
87
|
+
}>;
|
|
88
|
+
logout: () => Promise<{
|
|
89
|
+
ok: true;
|
|
90
|
+
}>;
|
|
91
|
+
/** Which login methods the server offers (public; drives the login screen). */
|
|
92
|
+
authMethods: () => Promise<{
|
|
93
|
+
password: boolean;
|
|
94
|
+
passkey: boolean;
|
|
95
|
+
}>;
|
|
96
|
+
passkeyLoginOptions: () => Promise<PublicKeyCredentialRequestOptionsJSON>;
|
|
97
|
+
passkeyLoginVerify: (response: AuthenticationResponseJSON) => Promise<{
|
|
98
|
+
ok: true;
|
|
99
|
+
}>;
|
|
100
|
+
passkeyRegisterOptions: () => Promise<PublicKeyCredentialCreationOptionsJSON>;
|
|
101
|
+
passkeyRegisterVerify: (response: RegistrationResponseJSON, label?: string) => Promise<{
|
|
102
|
+
ok: true;
|
|
103
|
+
credential: PasskeySummary | null;
|
|
104
|
+
}>;
|
|
105
|
+
passkeyList: () => Promise<{
|
|
106
|
+
credentials: PasskeySummary[];
|
|
107
|
+
}>;
|
|
108
|
+
passkeyRename: (id: string, label: string) => Promise<{
|
|
109
|
+
ok: true;
|
|
110
|
+
}>;
|
|
111
|
+
passkeyDelete: (id: string) => Promise<{
|
|
112
|
+
ok: true;
|
|
113
|
+
}>;
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACf,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,sCAAsC,EACtC,qCAAqC,EACtC,MAAM,yBAAyB,CAAC;AAEjC,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE;QACZ,kBAAkB,EAAE,OAAO,CAAC;QAC5B,QAAQ,EAAE,OAAO,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH;AAiBD,eAAO,MAAM,GAAG;;gBAEQ,MAAM;gBAAU,MAAM;iBAAW,MAAM;;;aAE5B,OAAO;;;iBAI3B,OAAO;gBACR,MAAM;kBACJ,KAAK,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;YACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;SAC3B,CAAC;uBACa,OAAO;;qBAGT,MAAM,SAAS;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;iBAEpD,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;kBACrE,MAAM,EAAE;;;iBAMC,MAAM;;;mBAId,MAAM;gBACT,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;kBACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAC1B,MAAM;eACL,MAAM;;;iBAIM,OAAO;iBAAW,MAAM;;wBAI3B,MAAM,SAAS;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;iBAC9D,OAAO;;;kBAOhB,KAAK,CAAC;YACd,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;YACrB,SAAS,EAAE,MAAM,CAAC;YAClB,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;;IAGN,+DAA+D;4BACvC,WAAW;IAGnC,qEAAqE;;;8BAM3C,WAAW;mBACZ,qBAAqB,EAAE;;;mBAMjC,YAAY,EAAE;mBACd,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;;IAG1C,mFAAmF;sBACjE,MAAM;YACN,IAAI;;;YAMJ,IAAI;;IAEtB,+EAA+E;;kBAEvD,OAAO;iBAAW,OAAO;;;mCAQlB,0BAA0B;YACvC,IAAI;;;sCAWY,wBAAwB,UAAU,MAAM;YACxD,IAAI;oBAAc,cAAc,GAAG,IAAI;;;qBAM9B,cAAc,EAAE;;wBAEvB,MAAM,SAAS,MAAM;YACvB,IAAI;;wBAKF,MAAM;YACR,IAAI;;CAGvB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { API_BASE } from "./backend.js";
|
|
2
|
+
async function fetchJson(path, init) {
|
|
3
|
+
const res = await fetch(`${API_BASE}${path}`, {
|
|
4
|
+
...init,
|
|
5
|
+
headers: {
|
|
6
|
+
"Content-Type": "application/json",
|
|
7
|
+
...init?.headers,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
if (!res.ok) {
|
|
11
|
+
const body = await res.json().catch(() => ({ error: res.statusText }));
|
|
12
|
+
throw new Error(body.error || `HTTP ${res.status}`);
|
|
13
|
+
}
|
|
14
|
+
return res.json();
|
|
15
|
+
}
|
|
16
|
+
export const api = {
|
|
17
|
+
health: () => fetchJson("/health"),
|
|
18
|
+
vpnCheck: () => fetchJson("/vpn-check"),
|
|
19
|
+
status: () => fetchJson("/status"),
|
|
20
|
+
brainSearch: (q, opts) => fetchJson(`/brain/search?q=${encodeURIComponent(q)}${opts?.type ? `&type=${opts.type}` : ""}${opts?.limit ? `&limit=${opts.limit}` : ""}`),
|
|
21
|
+
brainBriefing: () => fetchJson("/brain/briefing"),
|
|
22
|
+
brainStats: () => fetchJson("/brain/stats"),
|
|
23
|
+
brainSync: () => fetchJson("/brain/sync", {
|
|
24
|
+
method: "POST",
|
|
25
|
+
}),
|
|
26
|
+
brainAdd: (content, opts) => fetchJson("/brain/add", {
|
|
27
|
+
method: "POST",
|
|
28
|
+
body: JSON.stringify({ content, ...opts }),
|
|
29
|
+
}),
|
|
30
|
+
sessions: () => fetchJson("/sessions"),
|
|
31
|
+
/** Mint a dictation session for the active speech provider. */
|
|
32
|
+
voiceSession: (signal) => fetchJson("/voice/session", { method: "POST", signal }),
|
|
33
|
+
/** @deprecated use voiceSession(); kept during client transition. */
|
|
34
|
+
voiceToken: () => fetchJson("/voice/token", { method: "POST" }),
|
|
35
|
+
voiceKeyterms: () => fetchJson("/voice/keyterms"),
|
|
36
|
+
voiceOverrides: (signal) => fetchJson("/voice/overrides", {
|
|
37
|
+
signal,
|
|
38
|
+
}),
|
|
39
|
+
providers: () => fetchJson("/providers"),
|
|
40
|
+
/** Password-mode login. Resolves on success; throws the server error otherwise. */
|
|
41
|
+
login: (password) => fetchJson("/auth/login", {
|
|
42
|
+
method: "POST",
|
|
43
|
+
body: JSON.stringify({ password }),
|
|
44
|
+
}),
|
|
45
|
+
logout: () => fetchJson("/auth/logout", { method: "POST" }),
|
|
46
|
+
/** Which login methods the server offers (public; drives the login screen). */
|
|
47
|
+
authMethods: () => fetchJson("/auth/methods"),
|
|
48
|
+
passkeyLoginOptions: () => fetchJson("/auth/passkey/login-options", {
|
|
49
|
+
method: "POST",
|
|
50
|
+
body: "{}",
|
|
51
|
+
}),
|
|
52
|
+
passkeyLoginVerify: (response) => fetchJson("/auth/passkey/login-verify", {
|
|
53
|
+
method: "POST",
|
|
54
|
+
body: JSON.stringify(response),
|
|
55
|
+
}),
|
|
56
|
+
passkeyRegisterOptions: () => fetchJson("/auth/passkey/register-options", {
|
|
57
|
+
method: "POST",
|
|
58
|
+
body: "{}",
|
|
59
|
+
}),
|
|
60
|
+
passkeyRegisterVerify: (response, label) => fetchJson("/auth/passkey/register-verify", { method: "POST", body: JSON.stringify({ response, label }) }),
|
|
61
|
+
passkeyList: () => fetchJson("/auth/passkey/list"),
|
|
62
|
+
passkeyRename: (id, label) => fetchJson(`/auth/passkey/${encodeURIComponent(id)}`, {
|
|
63
|
+
method: "PUT",
|
|
64
|
+
body: JSON.stringify({ label }),
|
|
65
|
+
}),
|
|
66
|
+
passkeyDelete: (id) => fetchJson(`/auth/passkey/${encodeURIComponent(id)}`, {
|
|
67
|
+
method: "DELETE",
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
|