@schlessera/brain-ui-server 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 +65 -0
- package/dist/agent/backend.d.ts +30 -0
- package/dist/agent/backend.d.ts.map +1 -0
- package/dist/agent/backend.js +226 -0
- package/dist/agent/backend.js.map +1 -0
- package/dist/app.d.ts +27 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +116 -0
- package/dist/app.js.map +1 -0
- package/dist/brain/client.d.ts +43 -0
- package/dist/brain/client.d.ts.map +1 -0
- package/dist/brain/client.js +154 -0
- package/dist/brain/client.js.map +1 -0
- package/dist/brain/types.d.ts +41 -0
- package/dist/brain/types.d.ts.map +1 -0
- package/dist/brain/types.js +2 -0
- package/dist/brain/types.js.map +1 -0
- package/dist/cron/scheduler.d.ts +9 -0
- package/dist/cron/scheduler.d.ts.map +1 -0
- package/dist/cron/scheduler.js +58 -0
- package/dist/cron/scheduler.js.map +1 -0
- package/dist/db/client.d.ts +10 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +73 -0
- package/dist/db/client.js.map +1 -0
- package/dist/files/walker.d.ts +63 -0
- package/dist/files/walker.d.ts.map +1 -0
- package/dist/files/walker.js +416 -0
- package/dist/files/walker.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +59 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +246 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/passkeys.d.ts +36 -0
- package/dist/middleware/passkeys.d.ts.map +1 -0
- package/dist/middleware/passkeys.js +427 -0
- package/dist/middleware/passkeys.js.map +1 -0
- package/dist/middleware/tailscale.d.ts +31 -0
- package/dist/middleware/tailscale.d.ts.map +1 -0
- package/dist/middleware/tailscale.js +64 -0
- package/dist/middleware/tailscale.js.map +1 -0
- package/dist/render/template.d.ts +7 -0
- package/dist/render/template.d.ts.map +1 -0
- package/dist/render/template.js +112 -0
- package/dist/render/template.js.map +1 -0
- package/dist/routes/brain.d.ts +155 -0
- package/dist/routes/brain.d.ts.map +1 -0
- package/dist/routes/brain.js +250 -0
- package/dist/routes/brain.js.map +1 -0
- package/dist/routes/files.d.ts +89 -0
- package/dist/routes/files.d.ts.map +1 -0
- package/dist/routes/files.js +91 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/health.d.ts +37 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +27 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/providers.d.ts +33 -0
- package/dist/routes/providers.d.ts.map +1 -0
- package/dist/routes/providers.js +9 -0
- package/dist/routes/providers.js.map +1 -0
- package/dist/routes/render.d.ts +25 -0
- package/dist/routes/render.d.ts.map +1 -0
- package/dist/routes/render.js +47 -0
- package/dist/routes/render.js.map +1 -0
- package/dist/routes/sessions.d.ts +79 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +37 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/voice.d.ts +92 -0
- package/dist/routes/voice.d.ts.map +1 -0
- package/dist/routes/voice.js +64 -0
- package/dist/routes/voice.js.map +1 -0
- package/dist/voice/deepgram-token.d.ts +5 -0
- package/dist/voice/deepgram-token.d.ts.map +1 -0
- package/dist/voice/deepgram-token.js +63 -0
- package/dist/voice/deepgram-token.js.map +1 -0
- package/dist/voice/keyterm-builder.d.ts +18 -0
- package/dist/voice/keyterm-builder.d.ts.map +1 -0
- package/dist/voice/keyterm-builder.js +391 -0
- package/dist/voice/keyterm-builder.js.map +1 -0
- package/dist/voice/speech-providers.d.ts +25 -0
- package/dist/voice/speech-providers.d.ts.map +1 -0
- package/dist/voice/speech-providers.js +104 -0
- package/dist/voice/speech-providers.js.map +1 -0
- package/dist/ws/attachments.d.ts +10 -0
- package/dist/ws/attachments.d.ts.map +1 -0
- package/dist/ws/attachments.js +63 -0
- package/dist/ws/attachments.js.map +1 -0
- package/dist/ws/bridge.d.ts +7 -0
- package/dist/ws/bridge.d.ts.map +1 -0
- package/dist/ws/bridge.js +86 -0
- package/dist/ws/bridge.js.map +1 -0
- package/dist/ws/clients.d.ts +20 -0
- package/dist/ws/clients.d.ts.map +1 -0
- package/dist/ws/clients.js +48 -0
- package/dist/ws/clients.js.map +1 -0
- package/dist/ws/connection.d.ts +8 -0
- package/dist/ws/connection.d.ts.map +1 -0
- package/dist/ws/connection.js +116 -0
- package/dist/ws/connection.js.map +1 -0
- package/dist/ws/dispatch.d.ts +5 -0
- package/dist/ws/dispatch.d.ts.map +1 -0
- package/dist/ws/dispatch.js +139 -0
- package/dist/ws/dispatch.js.map +1 -0
- package/dist/ws/frames.d.ts +17 -0
- package/dist/ws/frames.d.ts.map +1 -0
- package/dist/ws/frames.js +37 -0
- package/dist/ws/frames.js.map +1 -0
- package/dist/ws/handler.d.ts +34 -0
- package/dist/ws/handler.d.ts.map +1 -0
- package/dist/ws/handler.js +33 -0
- package/dist/ws/handler.js.map +1 -0
- package/dist/ws/history.d.ts +17 -0
- package/dist/ws/history.d.ts.map +1 -0
- package/dist/ws/history.js +45 -0
- package/dist/ws/history.js.map +1 -0
- package/dist/ws/host.d.ts +40 -0
- package/dist/ws/host.d.ts.map +1 -0
- package/dist/ws/host.js +49 -0
- package/dist/ws/host.js.map +1 -0
- package/dist/ws/routing.d.ts +12 -0
- package/dist/ws/routing.d.ts.map +1 -0
- package/dist/ws/routing.js +31 -0
- package/dist/ws/routing.js.map +1 -0
- package/dist/ws/run-session.d.ts +17 -0
- package/dist/ws/run-session.d.ts.map +1 -0
- package/dist/ws/run-session.js +160 -0
- package/dist/ws/run-session.js.map +1 -0
- package/dist/ws/session-catalog.d.ts +25 -0
- package/dist/ws/session-catalog.d.ts.map +1 -0
- package/dist/ws/session-catalog.js +45 -0
- package/dist/ws/session-catalog.js.map +1 -0
- package/dist/ws/shrink.d.ts +34 -0
- package/dist/ws/shrink.d.ts.map +1 -0
- package/dist/ws/shrink.js +91 -0
- package/dist/ws/shrink.js.map +1 -0
- package/dist/ws/turns.d.ts +77 -0
- package/dist/ws/turns.d.ts.map +1 -0
- package/dist/ws/turns.js +89 -0
- package/dist/ws/turns.js.map +1 -0
- package/migrations/001_initial.sql +29 -0
- package/migrations/002_session_provider.sql +1 -0
- package/migrations/003_session_backend.sql +5 -0
- package/migrations/004_drop_gemini_backend.sql +20 -0
- package/migrations/005_passkey_credentials.sql +18 -0
- package/package.json +72 -0
- package/src/agent/backend.ts +308 -0
- package/src/app.ts +159 -0
- package/src/brain/client.ts +186 -0
- package/src/brain/types.ts +44 -0
- package/src/cron/scheduler.ts +80 -0
- package/src/db/client.ts +85 -0
- package/src/files/walker.ts +418 -0
- package/src/index.ts +39 -0
- package/src/middleware/auth.ts +321 -0
- package/src/middleware/passkeys.ts +510 -0
- package/src/middleware/tailscale.ts +81 -0
- package/src/render/template.ts +124 -0
- package/src/routes/brain.ts +305 -0
- package/src/routes/files.ts +99 -0
- package/src/routes/health.ts +29 -0
- package/src/routes/providers.ts +9 -0
- package/src/routes/render.ts +68 -0
- package/src/routes/sessions.ts +49 -0
- package/src/routes/voice.ts +80 -0
- package/src/voice/deepgram-token.ts +80 -0
- package/src/voice/keyterm-builder.ts +426 -0
- package/src/voice/speech-providers.ts +111 -0
- package/src/ws/attachments.ts +86 -0
- package/src/ws/bridge.ts +139 -0
- package/src/ws/clients.ts +57 -0
- package/src/ws/connection.ts +132 -0
- package/src/ws/dispatch.ts +162 -0
- package/src/ws/frames.ts +42 -0
- package/src/ws/handler.ts +50 -0
- package/src/ws/history.ts +51 -0
- package/src/ws/host.ts +69 -0
- package/src/ws/routing.ts +43 -0
- package/src/ws/run-session.ts +192 -0
- package/src/ws/session-catalog.ts +97 -0
- package/src/ws/shrink.ts +95 -0
- package/src/ws/turns.ts +151 -0
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { readdir, readFile, stat, realpath } from "node:fs/promises";
|
|
2
|
+
import { join, resolve, sep, posix, dirname } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import ignore from "ignore";
|
|
5
|
+
import { FILE_SIZE_CAP_BYTES } from "@schlessera/brain-ui-sdk/protocol";
|
|
6
|
+
const HARD_EXCLUDE_DIRS = new Set([".git", "node_modules"]);
|
|
7
|
+
const HARD_EXCLUDE_FILE_PATTERNS = [
|
|
8
|
+
/\.db$/i,
|
|
9
|
+
/\.db-wal$/i,
|
|
10
|
+
/\.db-shm$/i,
|
|
11
|
+
];
|
|
12
|
+
// Build / dependency manifests that aren't browseable content. Matched by
|
|
13
|
+
// exact name (case-insensitive) at any depth.
|
|
14
|
+
const HARD_EXCLUDE_FILE_NAMES = new Set([
|
|
15
|
+
"package.json",
|
|
16
|
+
"package-lock.json",
|
|
17
|
+
"bun.lock",
|
|
18
|
+
"bun.lockb",
|
|
19
|
+
"yarn.lock",
|
|
20
|
+
"pnpm-lock.yaml",
|
|
21
|
+
"skills-lock.json",
|
|
22
|
+
].map((n) => n.toLowerCase()));
|
|
23
|
+
export function getBrainRoot() {
|
|
24
|
+
return process.env.BRAIN_PATH || join(process.env.HOME || "/root", "brain");
|
|
25
|
+
}
|
|
26
|
+
export class PathEscapeError extends Error {
|
|
27
|
+
constructor(rel) {
|
|
28
|
+
super(`path_escape: ${rel}`);
|
|
29
|
+
this.name = "PathEscapeError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class NotFoundError extends Error {
|
|
33
|
+
constructor(rel) {
|
|
34
|
+
super(`not_found: ${rel}`);
|
|
35
|
+
this.name = "NotFoundError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class TooLargeError extends Error {
|
|
39
|
+
size;
|
|
40
|
+
constructor(size) {
|
|
41
|
+
super(`file_too_large: ${size}`);
|
|
42
|
+
this.size = size;
|
|
43
|
+
this.name = "TooLargeError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve a repo-relative path to an absolute path, rejecting any escape
|
|
48
|
+
* outside the brain root (including via symlinks).
|
|
49
|
+
*/
|
|
50
|
+
export async function safeResolve(rel, root = getBrainRoot()) {
|
|
51
|
+
if (typeof rel !== "string")
|
|
52
|
+
throw new PathEscapeError(String(rel));
|
|
53
|
+
// Reject absolute paths and null bytes
|
|
54
|
+
if (rel.startsWith("/") || rel.startsWith("\\") || rel.includes("\0")) {
|
|
55
|
+
throw new PathEscapeError(rel);
|
|
56
|
+
}
|
|
57
|
+
// Normalize separators; reject ".." segments anywhere
|
|
58
|
+
const normalized = rel.replace(/\\/g, "/");
|
|
59
|
+
for (const seg of normalized.split("/")) {
|
|
60
|
+
if (seg === "..")
|
|
61
|
+
throw new PathEscapeError(rel);
|
|
62
|
+
}
|
|
63
|
+
const absRoot = resolve(root);
|
|
64
|
+
const abs = resolve(absRoot, normalized);
|
|
65
|
+
if (abs !== absRoot && !abs.startsWith(absRoot + sep)) {
|
|
66
|
+
throw new PathEscapeError(rel);
|
|
67
|
+
}
|
|
68
|
+
// Check for symlink escape via realpath when the path exists
|
|
69
|
+
if (existsSync(abs)) {
|
|
70
|
+
const real = await realpath(abs);
|
|
71
|
+
if (real !== absRoot && !real.startsWith(absRoot + sep)) {
|
|
72
|
+
throw new PathEscapeError(rel);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return abs;
|
|
76
|
+
}
|
|
77
|
+
const ignoreCache = new Map();
|
|
78
|
+
async function loadIgnore(root) {
|
|
79
|
+
const gitignore = join(root, ".gitignore");
|
|
80
|
+
let mtime = 0;
|
|
81
|
+
try {
|
|
82
|
+
const s = await stat(gitignore);
|
|
83
|
+
mtime = s.mtimeMs;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// no .gitignore — empty matcher
|
|
87
|
+
}
|
|
88
|
+
const cached = ignoreCache.get(root);
|
|
89
|
+
if (cached && cached.mtime === mtime)
|
|
90
|
+
return cached.matcher;
|
|
91
|
+
const matcher = ignore();
|
|
92
|
+
if (mtime > 0) {
|
|
93
|
+
try {
|
|
94
|
+
const text = await readFile(gitignore, "utf8");
|
|
95
|
+
matcher.add(text);
|
|
96
|
+
}
|
|
97
|
+
catch { }
|
|
98
|
+
}
|
|
99
|
+
ignoreCache.set(root, { matcher, mtime });
|
|
100
|
+
return matcher;
|
|
101
|
+
}
|
|
102
|
+
function isHardExcluded(name, isDir) {
|
|
103
|
+
// Hide all dotfiles and dot-directories — they are tooling/config noise
|
|
104
|
+
// (.git, .gitignore, .agents, .claude, .brain-ui, etc.) that the user
|
|
105
|
+
// doesn't want to navigate as content.
|
|
106
|
+
if (name.startsWith("."))
|
|
107
|
+
return true;
|
|
108
|
+
if (isDir)
|
|
109
|
+
return HARD_EXCLUDE_DIRS.has(name);
|
|
110
|
+
if (HARD_EXCLUDE_FILE_NAMES.has(name.toLowerCase()))
|
|
111
|
+
return true;
|
|
112
|
+
return HARD_EXCLUDE_FILE_PATTERNS.some((re) => re.test(name));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* List entries of a directory, applying ignore rules.
|
|
116
|
+
* Always excludes: .git, node_modules, *.db*. Then applies .gitignore.
|
|
117
|
+
*/
|
|
118
|
+
export async function listDirectory(rel, root = getBrainRoot()) {
|
|
119
|
+
const abs = await safeResolve(rel, root);
|
|
120
|
+
let s;
|
|
121
|
+
try {
|
|
122
|
+
s = await stat(abs);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
throw new NotFoundError(rel);
|
|
126
|
+
}
|
|
127
|
+
if (!s.isDirectory())
|
|
128
|
+
throw new NotFoundError(rel);
|
|
129
|
+
const matcher = await loadIgnore(root);
|
|
130
|
+
const dirents = await readdir(abs, { withFileTypes: true });
|
|
131
|
+
const entries = [];
|
|
132
|
+
for (const d of dirents) {
|
|
133
|
+
const isDir = d.isDirectory();
|
|
134
|
+
const isFile = d.isFile();
|
|
135
|
+
const isSymlink = d.isSymbolicLink();
|
|
136
|
+
if (!isDir && !isFile && !isSymlink)
|
|
137
|
+
continue;
|
|
138
|
+
if (isHardExcluded(d.name, isDir))
|
|
139
|
+
continue;
|
|
140
|
+
const relChild = rel ? posix.join(rel, d.name) : d.name;
|
|
141
|
+
// ignore expects trailing slash on dirs to match dir-only rules
|
|
142
|
+
const matchPath = isDir ? `${relChild}/` : relChild;
|
|
143
|
+
if (matcher.ignores(matchPath))
|
|
144
|
+
continue;
|
|
145
|
+
let childStat;
|
|
146
|
+
try {
|
|
147
|
+
childStat = await stat(join(abs, d.name));
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
continue; // broken symlink
|
|
151
|
+
}
|
|
152
|
+
// Resolve symlinks: drop ones that escape the root
|
|
153
|
+
if (isSymlink) {
|
|
154
|
+
try {
|
|
155
|
+
const real = await realpath(join(abs, d.name));
|
|
156
|
+
const absRoot = resolve(root);
|
|
157
|
+
if (real !== absRoot && !real.startsWith(absRoot + sep))
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
entries.push({
|
|
165
|
+
name: d.name,
|
|
166
|
+
path: relChild,
|
|
167
|
+
type: childStat.isDirectory() ? "dir" : "file",
|
|
168
|
+
size: childStat.isFile() ? childStat.size : undefined,
|
|
169
|
+
mtime: Math.floor(childStat.mtimeMs),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
entries.sort((a, b) => {
|
|
173
|
+
if (a.type !== b.type)
|
|
174
|
+
return a.type === "dir" ? -1 : 1;
|
|
175
|
+
return a.name.localeCompare(b.name, undefined, { sensitivity: "base" });
|
|
176
|
+
});
|
|
177
|
+
return entries;
|
|
178
|
+
}
|
|
179
|
+
const MARKDOWN_EXT = new Set([".md", ".markdown", ".mdx"]);
|
|
180
|
+
const HTML_EXT = new Set([".html", ".htm"]);
|
|
181
|
+
const KNOWN_TEXT_EXT = new Set([
|
|
182
|
+
".txt", ".text", ".log",
|
|
183
|
+
".json", ".jsonc", ".yaml", ".yml", ".toml", ".xml", ".csv", ".tsv",
|
|
184
|
+
".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs",
|
|
185
|
+
".py", ".rb", ".go", ".rs", ".java", ".kt", ".swift", ".c", ".h",
|
|
186
|
+
".cpp", ".hpp", ".cc", ".cs", ".php", ".sh", ".bash", ".zsh", ".fish",
|
|
187
|
+
".css", ".scss", ".sass", ".less",
|
|
188
|
+
".sql", ".env", ".ini", ".conf", ".cfg",
|
|
189
|
+
".gitignore", ".gitattributes", ".editorconfig", ".prettierrc",
|
|
190
|
+
".dockerfile", ".lock",
|
|
191
|
+
]);
|
|
192
|
+
function extOf(name) {
|
|
193
|
+
const i = name.lastIndexOf(".");
|
|
194
|
+
if (i < 0)
|
|
195
|
+
return "";
|
|
196
|
+
return name.slice(i).toLowerCase();
|
|
197
|
+
}
|
|
198
|
+
export function classifyKind(name, bytes) {
|
|
199
|
+
const ext = extOf(name);
|
|
200
|
+
if (MARKDOWN_EXT.has(ext))
|
|
201
|
+
return "markdown";
|
|
202
|
+
if (HTML_EXT.has(ext))
|
|
203
|
+
return "html";
|
|
204
|
+
if (KNOWN_TEXT_EXT.has(ext))
|
|
205
|
+
return "text";
|
|
206
|
+
// Bare names like "Dockerfile", "Makefile", "LICENSE", "README"
|
|
207
|
+
const base = name.toLowerCase();
|
|
208
|
+
if (["dockerfile", "makefile", "license", "licence", "readme", "changelog", "authors", "contributors", "notice"].includes(base)) {
|
|
209
|
+
return "text";
|
|
210
|
+
}
|
|
211
|
+
// Fall back to byte sniff: a buffer is "text" if no NUL byte in first 4KB and decodes as UTF-8.
|
|
212
|
+
if (bytes) {
|
|
213
|
+
const slice = bytes.subarray(0, Math.min(bytes.length, 4096));
|
|
214
|
+
if (slice.includes(0))
|
|
215
|
+
return "binary";
|
|
216
|
+
try {
|
|
217
|
+
new TextDecoder("utf-8", { fatal: true }).decode(slice);
|
|
218
|
+
return "text";
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return "binary";
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return "binary";
|
|
225
|
+
}
|
|
226
|
+
const MIME_BY_EXT = {
|
|
227
|
+
".png": "image/png",
|
|
228
|
+
".jpg": "image/jpeg",
|
|
229
|
+
".jpeg": "image/jpeg",
|
|
230
|
+
".gif": "image/gif",
|
|
231
|
+
".webp": "image/webp",
|
|
232
|
+
".svg": "image/svg+xml",
|
|
233
|
+
".avif": "image/avif",
|
|
234
|
+
".bmp": "image/bmp",
|
|
235
|
+
".ico": "image/x-icon",
|
|
236
|
+
".pdf": "application/pdf",
|
|
237
|
+
".mp3": "audio/mpeg",
|
|
238
|
+
".wav": "audio/wav",
|
|
239
|
+
".mp4": "video/mp4",
|
|
240
|
+
".webm": "video/webm",
|
|
241
|
+
};
|
|
242
|
+
export function mimeFor(name, kind) {
|
|
243
|
+
const ext = extOf(name);
|
|
244
|
+
if (MIME_BY_EXT[ext])
|
|
245
|
+
return MIME_BY_EXT[ext];
|
|
246
|
+
if (kind === "markdown")
|
|
247
|
+
return "text/markdown; charset=utf-8";
|
|
248
|
+
if (kind === "html")
|
|
249
|
+
return "text/html; charset=utf-8";
|
|
250
|
+
if (kind === "text")
|
|
251
|
+
return "text/plain; charset=utf-8";
|
|
252
|
+
return "application/octet-stream";
|
|
253
|
+
}
|
|
254
|
+
export async function readFileContent(rel, root = getBrainRoot()) {
|
|
255
|
+
const abs = await safeResolve(rel, root);
|
|
256
|
+
let s;
|
|
257
|
+
try {
|
|
258
|
+
s = await stat(abs);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
throw new NotFoundError(rel);
|
|
262
|
+
}
|
|
263
|
+
if (!s.isFile())
|
|
264
|
+
throw new NotFoundError(rel);
|
|
265
|
+
if (s.size > FILE_SIZE_CAP_BYTES)
|
|
266
|
+
throw new TooLargeError(s.size);
|
|
267
|
+
const ext = extOf(abs);
|
|
268
|
+
const presumed = MARKDOWN_EXT.has(ext)
|
|
269
|
+
? "markdown"
|
|
270
|
+
: HTML_EXT.has(ext)
|
|
271
|
+
? "html"
|
|
272
|
+
: KNOWN_TEXT_EXT.has(ext)
|
|
273
|
+
? "text"
|
|
274
|
+
: null;
|
|
275
|
+
if (presumed) {
|
|
276
|
+
const content = await readFile(abs, "utf8");
|
|
277
|
+
return {
|
|
278
|
+
kind: presumed,
|
|
279
|
+
size: s.size,
|
|
280
|
+
mtime: Math.floor(s.mtimeMs),
|
|
281
|
+
mime: mimeFor(rel, presumed),
|
|
282
|
+
content,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const buf = await readFile(abs);
|
|
286
|
+
const kind = classifyKind(abs, buf);
|
|
287
|
+
if (kind === "text" || kind === "markdown" || kind === "html") {
|
|
288
|
+
return {
|
|
289
|
+
kind,
|
|
290
|
+
size: s.size,
|
|
291
|
+
mtime: Math.floor(s.mtimeMs),
|
|
292
|
+
mime: mimeFor(rel, kind),
|
|
293
|
+
content: buf.toString("utf8"),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
kind: "binary",
|
|
298
|
+
size: s.size,
|
|
299
|
+
mtime: Math.floor(s.mtimeMs),
|
|
300
|
+
mime: mimeFor(rel, "binary"),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Stream raw bytes of a file (for image/binary preview).
|
|
305
|
+
* Returns the absolute path; caller uses Bun.file() to stream.
|
|
306
|
+
*/
|
|
307
|
+
export async function resolveForRaw(rel, root = getBrainRoot()) {
|
|
308
|
+
const abs = await safeResolve(rel, root);
|
|
309
|
+
let s;
|
|
310
|
+
try {
|
|
311
|
+
s = await stat(abs);
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
throw new NotFoundError(rel);
|
|
315
|
+
}
|
|
316
|
+
if (!s.isFile())
|
|
317
|
+
throw new NotFoundError(rel);
|
|
318
|
+
if (s.size > FILE_SIZE_CAP_BYTES)
|
|
319
|
+
throw new TooLargeError(s.size);
|
|
320
|
+
const kind = classifyKind(abs);
|
|
321
|
+
return { abs, size: s.size, mime: mimeFor(rel, kind), kind };
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Walk the brain repo and build a slug -> repo-relative-path map for all
|
|
325
|
+
* markdown files (.md / .markdown / .mdx), respecting the same ignore
|
|
326
|
+
* rules as listDirectory. Slug = basename without extension, lowercase.
|
|
327
|
+
*
|
|
328
|
+
* If two files share a slug (rare), the first one encountered wins —
|
|
329
|
+
* deterministic given the sorted directory traversal.
|
|
330
|
+
*/
|
|
331
|
+
export async function buildWikilinkMap(root = getBrainRoot()) {
|
|
332
|
+
const matcher = await loadIgnore(root);
|
|
333
|
+
const out = {};
|
|
334
|
+
async function walk(rel) {
|
|
335
|
+
const abs = await safeResolve(rel, root);
|
|
336
|
+
let dirents;
|
|
337
|
+
try {
|
|
338
|
+
dirents = await readdir(abs, { withFileTypes: true });
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
// Sort for deterministic precedence
|
|
344
|
+
dirents.sort((a, b) => a.name.localeCompare(b.name));
|
|
345
|
+
for (const d of dirents) {
|
|
346
|
+
const isDir = d.isDirectory();
|
|
347
|
+
const isFile = d.isFile();
|
|
348
|
+
const isSymlink = d.isSymbolicLink();
|
|
349
|
+
if (!isDir && !isFile && !isSymlink)
|
|
350
|
+
continue;
|
|
351
|
+
if (isHardExcluded(d.name, isDir))
|
|
352
|
+
continue;
|
|
353
|
+
const relChild = rel ? posix.join(rel, d.name) : d.name;
|
|
354
|
+
const matchPath = isDir ? `${relChild}/` : relChild;
|
|
355
|
+
if (matcher.ignores(matchPath))
|
|
356
|
+
continue;
|
|
357
|
+
let childStat;
|
|
358
|
+
try {
|
|
359
|
+
childStat = await stat(join(abs, d.name));
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (isSymlink) {
|
|
365
|
+
try {
|
|
366
|
+
const real = await realpath(join(abs, d.name));
|
|
367
|
+
const absRoot = resolve(root);
|
|
368
|
+
if (real !== absRoot && !real.startsWith(absRoot + sep))
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (childStat.isDirectory()) {
|
|
376
|
+
await walk(relChild);
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const lower = d.name.toLowerCase();
|
|
380
|
+
const dot = lower.lastIndexOf(".");
|
|
381
|
+
const ext = dot >= 0 ? lower.slice(dot) : "";
|
|
382
|
+
if (ext !== ".md" && ext !== ".markdown" && ext !== ".mdx")
|
|
383
|
+
continue;
|
|
384
|
+
const slug = lower.slice(0, dot);
|
|
385
|
+
if (slug && !out[slug])
|
|
386
|
+
out[slug] = relChild;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
await walk("");
|
|
390
|
+
return out;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Return ancestor directories of a path, root-first (excluding root and the path itself).
|
|
394
|
+
* resolve("a/b/c.md") -> { ancestors: ["a", "a/b"], exists, type }
|
|
395
|
+
*/
|
|
396
|
+
export async function resolveAncestors(rel, root = getBrainRoot()) {
|
|
397
|
+
const normalized = rel.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
398
|
+
if (!normalized)
|
|
399
|
+
return { ancestors: [], exists: true, type: "dir" };
|
|
400
|
+
const parts = normalized.split("/");
|
|
401
|
+
const ancestors = [];
|
|
402
|
+
for (let i = 1; i < parts.length; i++) {
|
|
403
|
+
ancestors.push(parts.slice(0, i).join("/"));
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const abs = await safeResolve(normalized, root);
|
|
407
|
+
const s = await stat(abs);
|
|
408
|
+
return { ancestors, exists: true, type: s.isDirectory() ? "dir" : "file" };
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
return { ancestors, exists: false };
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Re-export for callers
|
|
415
|
+
export { dirname };
|
|
416
|
+
//# sourceMappingURL=walker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/files/walker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @schlessera/brain-ui-server — the chat-UI backend as a library.
|
|
3
|
+
*
|
|
4
|
+
* The deployment shell owns the process: it builds the Bun.serve() object,
|
|
5
|
+
* decides the port/idleTimeout, wires SIGTERM, and injects deployment-only
|
|
6
|
+
* pieces (static client build, PNG/PDF renderer). Everything else — routes,
|
|
7
|
+
* auth, passkeys, the WebSocket turn coordinator, the session catalog — lives
|
|
8
|
+
* behind createApp().
|
|
9
|
+
*/
|
|
10
|
+
export { createApp, type CreateAppOptions, type AppRenderer } from "./app.js";
|
|
11
|
+
export { websocket, cancelActiveTurn, isTurnActive } from "./ws/handler.js";
|
|
12
|
+
export { getDb, closeDb, configureDb } from "./db/client.js";
|
|
13
|
+
export { getBackends, getBackendsInfo } from "./agent/backend.js";
|
|
14
|
+
export { resolveAuthMode, type AuthMode } from "./middleware/auth.js";
|
|
15
|
+
export { WsHost, type WsHostOptions, defaultWsHost, configureWsHost, handleClientMessage, resetForTests, resolveTurnTarget, createSessionCatalog, type SessionCatalog, } from "./ws/handler.js";
|
|
16
|
+
export * as brainClient from "./brain/client.js";
|
|
17
|
+
export { buildKeyterms, writeCache } from "./voice/keyterm-builder.js";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAG9E,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,EACL,MAAM,EACN,KAAK,aAAa,EAClB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @schlessera/brain-ui-server — the chat-UI backend as a library.
|
|
3
|
+
*
|
|
4
|
+
* The deployment shell owns the process: it builds the Bun.serve() object,
|
|
5
|
+
* decides the port/idleTimeout, wires SIGTERM, and injects deployment-only
|
|
6
|
+
* pieces (static client build, PNG/PDF renderer). Everything else — routes,
|
|
7
|
+
* auth, passkeys, the WebSocket turn coordinator, the session catalog — lives
|
|
8
|
+
* behind createApp().
|
|
9
|
+
*/
|
|
10
|
+
export { createApp } from "./app.js";
|
|
11
|
+
// Process lifecycle helpers for the bin entry.
|
|
12
|
+
export { websocket, cancelActiveTurn, isTurnActive } from "./ws/handler.js";
|
|
13
|
+
export { getDb, closeDb, configureDb } from "./db/client.js";
|
|
14
|
+
// Boot-time diagnostics (fail fast on a bad AGENT_BACKEND / profile config,
|
|
15
|
+
// log the resolved auth mode).
|
|
16
|
+
export { getBackends, getBackendsInfo } from "./agent/backend.js";
|
|
17
|
+
export { resolveAuthMode } from "./middleware/auth.js";
|
|
18
|
+
// WebSocket internals for embedders and tests.
|
|
19
|
+
export { WsHost, defaultWsHost, configureWsHost, handleClientMessage, resetForTests, resolveTurnTarget, createSessionCatalog, } from "./ws/handler.js";
|
|
20
|
+
// Brain repo access (spawned CLI wrapper) — useful for embedders that add
|
|
21
|
+
// their own routes on top.
|
|
22
|
+
export * as brainClient from "./brain/client.js";
|
|
23
|
+
// Voice keyterm cache rebuild (used by deployments after `brain sync`).
|
|
24
|
+
export { buildKeyterms, writeCache } from "./voice/keyterm-builder.js";
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAA2C,MAAM,UAAU,CAAC;AAE9E,+CAA+C;AAC/C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7D,4EAA4E;AAC5E,+BAA+B;AAC/B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAiB,MAAM,sBAAsB,CAAC;AAEtE,+CAA+C;AAC/C,OAAO,EACL,MAAM,EAEN,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,GAErB,MAAM,iBAAiB,CAAC;AAEzB,0EAA0E;AAC1E,2BAA2B;AAC3B,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAEjD,wEAAwE;AACxE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { Context, MiddlewareHandler } from "hono";
|
|
3
|
+
/**
|
|
4
|
+
* Authentication for a remote surface to an agent with write access to the
|
|
5
|
+
* user's files. Modes (AUTH_MODE):
|
|
6
|
+
*
|
|
7
|
+
* - `password` — a single shared password (Bun.password argon2id hash in
|
|
8
|
+
* BRAIN_UI_PASSWORD_HASH), a signed HttpOnly SameSite=Strict
|
|
9
|
+
* session cookie (COOKIE_SECRET), a rate-limited login route.
|
|
10
|
+
* The only mode where `docker compose up` on a bare VPS is safe.
|
|
11
|
+
* - `tailscale` — Tailscale IP allowlist (today's model). Header trust is gated
|
|
12
|
+
* behind TRUST_PROXY=1; otherwise the socket address is used.
|
|
13
|
+
* - `proxy` — trust an upstream auth header (PROXY_AUTH_HEADER) set by
|
|
14
|
+
* Authelia / oauth2-proxy / Caddy basic_auth, etc.
|
|
15
|
+
* - `none` — no auth. REFUSES to start unless HOST is loopback (fail
|
|
16
|
+
* closed), regardless of NODE_ENV; the only override is the
|
|
17
|
+
* explicit BRAIN_UI_DANGEROUSLY_DISABLE_AUTH=1 escape hatch.
|
|
18
|
+
*
|
|
19
|
+
* Default: `password` when BRAIN_UI_PASSWORD_HASH is set, else `tailscale`.
|
|
20
|
+
*/
|
|
21
|
+
export type AuthMode = "password" | "tailscale" | "proxy" | "none";
|
|
22
|
+
export declare const LOGIN_RATE_LIMIT = 5;
|
|
23
|
+
export declare const GLOBAL_LOGIN_RATE_LIMIT = 20;
|
|
24
|
+
export declare function resolveAuthMode(): AuthMode;
|
|
25
|
+
/**
|
|
26
|
+
* Validate the auth configuration at startup. Throws (refusing to boot) on an
|
|
27
|
+
* unsafe or unusable configuration.
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertAuthConfig(mode: AuthMode): void;
|
|
30
|
+
/** Middleware guarding /api/* according to the resolved mode. */
|
|
31
|
+
export declare function authGuard(mode: AuthMode): MiddlewareHandler;
|
|
32
|
+
/**
|
|
33
|
+
* Authorize a WebSocket upgrade. The upgrade handler must call this itself —
|
|
34
|
+
* browsers can't set headers on the WS handshake, so the session cookie (sent
|
|
35
|
+
* automatically same-origin) is the credential, and no header-modifying
|
|
36
|
+
* middleware may sit on the WS route (immutable-header errors). Mirrors
|
|
37
|
+
* {@link authGuard} without emitting a response.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isWsAuthorized(c: Context, mode: AuthMode): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Mint the session cookie. The single place a session comes into existence —
|
|
42
|
+
* both password login and passkey login (middleware/passkeys.ts) call this, so
|
|
43
|
+
* authGuard / isWsAuthorized / TTL semantics stay identical across methods.
|
|
44
|
+
*/
|
|
45
|
+
export declare function issueSessionCookie(c: Context): Promise<void>;
|
|
46
|
+
/** Test-only: clear all rate-limit buckets (they are module-global state). */
|
|
47
|
+
export declare function resetLoginRateLimiter(): void;
|
|
48
|
+
export declare function consumeLoginToken(key: string, limit: number): boolean;
|
|
49
|
+
/** Login/logout routes. Only functional in `password` mode. */
|
|
50
|
+
export declare function authRoutes(mode: AuthMode, deps?: {
|
|
51
|
+
/**
|
|
52
|
+
* When provided and returning true, password login is refused (the app
|
|
53
|
+
* injects passkeys' passwordLoginDisabled so the shared password dies
|
|
54
|
+
* once a passkey exists for the RP). Injected to keep this module free
|
|
55
|
+
* of WebAuthn concerns.
|
|
56
|
+
*/
|
|
57
|
+
passwordDisabled?: (c: Context) => boolean;
|
|
58
|
+
}): Hono;
|
|
59
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAIvD;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAInE,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAQlC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAG1C,wBAAgB,eAAe,IAAI,QAAQ,CAe1C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAwDrD;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,iBAAiB,CAqC3D;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAWjF;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAYlE;AA4CD,8EAA8E;AAC9E,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAUrE;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CACxB,IAAI,EAAE,QAAQ,EACd,IAAI,GAAE;IACJ;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;CACvC,GACL,IAAI,CAkDN"}
|