@andespindola/brainlink 0.1.0-beta.27 → 0.1.0-beta.29

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.
@@ -25,6 +25,13 @@ body {
25
25
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
26
26
  }
27
27
 
28
+ body {
29
+ display: flex;
30
+ flex-direction: column;
31
+ min-height: 100vh;
32
+ min-height: 100dvh;
33
+ }
34
+
28
35
  button,
29
36
  input,
30
37
  select {
@@ -32,8 +39,9 @@ select {
32
39
  }
33
40
 
34
41
  .shell {
42
+ flex: 1 1 auto;
35
43
  width: 100%;
36
- height: calc(100svh - 28px);
44
+ min-height: 0;
37
45
  overflow: hidden;
38
46
  }
39
47
 
@@ -346,6 +354,7 @@ li small {
346
354
  }
347
355
 
348
356
  .app-footer {
357
+ flex: 0 0 28px;
349
358
  height: 28px;
350
359
  display: flex;
351
360
  align-items: center;
@@ -1,6 +1,7 @@
1
1
  import { execFile } from 'node:child_process';
2
2
  import { access } from 'node:fs/promises';
3
3
  import { basename, extname, join, relative, resolve } from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
4
5
  import { promisify } from 'node:util';
5
6
  import { extractTags, extractWikiLinks } from '../domain/markdown.js';
6
7
  import { sanitizeAgentId, sharedAgentId } from '../domain/agents.js';
@@ -42,9 +43,13 @@ const parseDelimitedRows = (rawOutput) => {
42
43
  .map((row) => row.split(fieldSeparator));
43
44
  };
44
45
  const runSqliteQuery = async (databasePath, sql) => {
45
- try {
46
- const { stdout } = await execFileAsync('sqlite3', ['--readonly', '-noheader', '-separator', fieldSeparator, '-newline', rowSeparator, databasePath, sql], { maxBuffer: 1024 * 1024 * 64 });
46
+ const baseArgs = ['-noheader', '-separator', fieldSeparator, '-newline', rowSeparator, '-cmd', '.timeout 5000'];
47
+ const runQuery = async (args) => {
48
+ const { stdout } = await execFileAsync('sqlite3', [...args, sql], { maxBuffer: 1024 * 1024 * 64 });
47
49
  return parseDelimitedRows(stdout);
50
+ };
51
+ try {
52
+ return await runQuery(['--readonly', ...baseArgs, databasePath]);
48
53
  }
49
54
  catch (error) {
50
55
  const message = error instanceof Error ? error.message : String(error);
@@ -52,6 +57,17 @@ const runSqliteQuery = async (databasePath, sql) => {
52
57
  if (lower.includes('enoent') || lower.includes('not found')) {
53
58
  throw new Error('sqlite3 CLI was not found. Install sqlite3 to use db-import.');
54
59
  }
60
+ if (lower.includes('database is locked') || lower.includes('(5)')) {
61
+ try {
62
+ const uri = pathToFileURL(databasePath);
63
+ uri.search = 'mode=ro&immutable=1';
64
+ return await runQuery(['-uri', ...baseArgs, uri.toString()]);
65
+ }
66
+ catch (fallbackError) {
67
+ const fallbackMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
68
+ throw new Error(`Unable to read SQLite database (locked). Close writers (server/watch/mcp) or rerun with DB idle. Details: ${fallbackMessage}`);
69
+ }
70
+ }
55
71
  throw new Error(`Unable to read SQLite database: ${message}`);
56
72
  }
57
73
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.27",
3
+ "version": "0.1.0-beta.29",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",