@andespindola/brainlink 0.1.0-beta.1 → 0.1.0-beta.11

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +241 -10
  3. package/dist/application/add-note.js +62 -13
  4. package/dist/application/analyze-vault.js +104 -9
  5. package/dist/application/frontend/client-css.js +154 -71
  6. package/dist/application/frontend/client-html.js +42 -33
  7. package/dist/application/frontend/client-js.js +316 -84
  8. package/dist/application/get-graph-layout.js +22 -7
  9. package/dist/application/get-graph-node.js +12 -0
  10. package/dist/application/get-graph-summary.js +12 -0
  11. package/dist/application/index-vault.js +7 -0
  12. package/dist/application/migrate-vault.js +91 -0
  13. package/dist/application/search-graph-node-ids.js +12 -0
  14. package/dist/application/search-knowledge.js +74 -4
  15. package/dist/application/server/routes.js +27 -1
  16. package/dist/cli/commands/agent-commands.js +412 -0
  17. package/dist/cli/commands/config-commands.js +167 -0
  18. package/dist/cli/commands/read-commands.js +25 -8
  19. package/dist/cli/commands/write-commands.js +173 -4
  20. package/dist/cli/main.js +4 -0
  21. package/dist/cli/runtime.js +5 -2
  22. package/dist/domain/embeddings.js +2 -1
  23. package/dist/domain/graph-layout.js +20 -14
  24. package/dist/domain/markdown.js +36 -4
  25. package/dist/infrastructure/config.js +94 -8
  26. package/dist/infrastructure/file-system-vault.js +15 -0
  27. package/dist/infrastructure/paths.js +9 -1
  28. package/dist/infrastructure/search-packs.js +151 -0
  29. package/dist/infrastructure/session-state.js +172 -0
  30. package/dist/infrastructure/sqlite/graph-reader.js +252 -105
  31. package/dist/infrastructure/sqlite/recovery.js +83 -0
  32. package/dist/infrastructure/sqlite/schema.js +4 -1
  33. package/dist/infrastructure/sqlite/search-reader.js +104 -72
  34. package/dist/infrastructure/sqlite-index.js +16 -3
  35. package/dist/mcp/main.js +11 -3
  36. package/dist/mcp/server.js +17 -2
  37. package/dist/mcp/startup.js +35 -0
  38. package/dist/mcp/tools.js +571 -19
  39. package/docs/AGENT_USAGE.md +87 -3
  40. package/docs/ARCHITECTURE.md +16 -1
  41. package/docs/QUICKSTART.md +104 -0
  42. package/docs/RELEASE.md +3 -3
  43. package/package.json +1 -1
@@ -1,23 +1,36 @@
1
- import Database from 'better-sqlite3';
2
1
  import { chmodSync } from 'node:fs';
3
2
  import { join } from 'node:path';
4
3
  import { createIndexWriter } from './sqlite/document-writer.js';
5
4
  import { createGraphReader } from './sqlite/graph-reader.js';
5
+ import { createRecoverySnapshot, openDatabaseWithRecovery } from './sqlite/recovery.js';
6
6
  import { createSchema } from './sqlite/schema.js';
7
7
  import { createSearchReader } from './sqlite/search-reader.js';
8
8
  export const openSqliteIndex = (vaultPath) => {
9
9
  const databasePath = join(vaultPath, '.brainlink', 'brainlink.db');
10
- const database = new Database(databasePath);
10
+ const backupPath = join(vaultPath, '.brainlink', 'brainlink.db.backup');
11
+ const database = openDatabaseWithRecovery(databasePath, backupPath);
12
+ const indexWriter = createIndexWriter(database);
11
13
  chmodSync(databasePath, 0o600);
12
14
  database.exec(`
13
15
  PRAGMA foreign_keys = ON;
14
16
  PRAGMA journal_mode = WAL;
15
17
  PRAGMA synchronous = NORMAL;
16
18
  PRAGMA temp_store = MEMORY;
19
+ PRAGMA busy_timeout = 5000;
20
+ PRAGMA cache_size = -20000;
17
21
  `);
18
22
  createSchema(database);
19
23
  return {
20
- ...createIndexWriter(database),
24
+ reset: () => indexWriter.reset(),
25
+ saveDocuments: (documents) => {
26
+ indexWriter.saveDocuments(documents);
27
+ try {
28
+ createRecoverySnapshot(database, backupPath);
29
+ }
30
+ catch {
31
+ // Snapshot creation is best-effort. Indexing success should not fail because of backup I/O.
32
+ }
33
+ },
21
34
  ...createSearchReader(database),
22
35
  ...createGraphReader(database),
23
36
  close: () => database.close()
package/dist/mcp/main.js CHANGED
@@ -1,9 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { createBrainlinkMcpServer } from './server.js';
4
- const server = createBrainlinkMcpServer();
5
- const transport = new StdioServerTransport();
6
- server.connect(transport).catch((error) => {
4
+ import { runStartupBootstrap } from './startup.js';
5
+ const start = async () => {
6
+ const startup = await runStartupBootstrap();
7
+ if (startup.error) {
8
+ console.error(`Brainlink MCP startup bootstrap warning: ${startup.error}`);
9
+ }
10
+ const server = createBrainlinkMcpServer();
11
+ const transport = new StdioServerTransport();
12
+ await server.connect(transport);
13
+ };
14
+ start().catch((error) => {
7
15
  const message = error instanceof Error ? error.message : String(error);
8
16
  console.error(message);
9
17
  process.exitCode = 1;
@@ -2,7 +2,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { addNoteInputSchema, addFileInputSchema, addFileTool, addNoteTool, brokenLinksInputSchema, brokenLinksTool, contextInputSchema, contextTool, graphInputSchema, graphTool, indexInputSchema, indexTool, orphansInputSchema, orphansTool, searchInputSchema, searchTool, statsInputSchema, statsTool, syncInputSchema, syncTool, validateInputSchema, validateTool } from './tools.js';
5
+ import { addNoteInputSchema, addFileInputSchema, addFileTool, addNoteTool, brokenLinksInputSchema, brokenLinksTool, bootstrapInputSchema, bootstrapTool, contextInputSchema, contextTool, graphInputSchema, graphTool, indexInputSchema, indexTool, orphansInputSchema, orphansTool, policyInputSchema, policyTool, recommendationsInputSchema, recommendationsTool, searchInputSchema, searchTool, statsInputSchema, statsTool, syncInputSchema, syncTool, validateInputSchema, validateTool } from './tools.js';
6
6
  const readPackageVersion = () => {
7
7
  const packagePath = join(dirname(fileURLToPath(import.meta.url)), '../../package.json');
8
8
  const metadata = JSON.parse(readFileSync(packagePath, 'utf8'));
@@ -15,9 +15,24 @@ export const createBrainlinkMcpServer = () => {
15
15
  version: readPackageVersion(),
16
16
  description: 'Local-first Markdown memory tools for AI agents.'
17
17
  });
18
+ server.registerTool('brainlink_bootstrap', {
19
+ title: 'Bootstrap Brainlink For A Task (Default Entrypoint)',
20
+ description: 'Default entrypoint for agents. Run this first to index/check memory state, then optionally retrieve context for the current task query.',
21
+ inputSchema: bootstrapInputSchema
22
+ }, bootstrapTool);
23
+ server.registerTool('brainlink_policy', {
24
+ title: 'Brainlink Bootstrap Policy',
25
+ description: 'Read or update bootstrap enforcement policy and inspect bootstrap readiness for the current vault/agent.',
26
+ inputSchema: policyInputSchema
27
+ }, policyTool);
28
+ server.registerTool('brainlink_recommendations', {
29
+ title: 'Brainlink Recommended MCP Workflow',
30
+ description: 'Return a plug-and-play action plan for this vault/agent, including policy, bootstrap, context retrieval and durable write guidance.',
31
+ inputSchema: recommendationsInputSchema
32
+ }, recommendationsTool);
18
33
  server.registerTool('brainlink_context', {
19
34
  title: 'Build Brainlink Context',
20
- description: 'Read indexed Brainlink memory for a task or question. This is read-only and does not create graph links.',
35
+ description: 'Read indexed Brainlink memory for a task or question. Usually called after brainlink_bootstrap. This is read-only and does not create graph links.',
21
36
  inputSchema: contextInputSchema
22
37
  }, contextTool);
23
38
  server.registerTool('brainlink_search', {
@@ -0,0 +1,35 @@
1
+ import { indexVault } from '../application/index-vault.js';
2
+ import { loadBrainlinkConfig } from '../infrastructure/config.js';
3
+ import { assertVaultAllowed } from '../infrastructure/file-system-vault.js';
4
+ import { getBootstrapPolicy, touchBootstrapSession } from '../infrastructure/session-state.js';
5
+ export const runStartupBootstrap = async () => {
6
+ try {
7
+ const policy = await getBootstrapPolicy();
8
+ if (!policy.autoBootstrapOnStartup) {
9
+ return {
10
+ attempted: false,
11
+ skipped: true,
12
+ reason: 'autoBootstrapOnStartup=false'
13
+ };
14
+ }
15
+ const config = await loadBrainlinkConfig();
16
+ const vault = assertVaultAllowed(config.vault, config.allowedVaults);
17
+ const agent = config.defaultAgent;
18
+ const index = await indexVault(vault);
19
+ await touchBootstrapSession(vault, agent);
20
+ return {
21
+ attempted: true,
22
+ skipped: false,
23
+ vault,
24
+ agent: agent ?? '*',
25
+ index
26
+ };
27
+ }
28
+ catch (error) {
29
+ return {
30
+ attempted: true,
31
+ skipped: false,
32
+ error: error instanceof Error ? error.message : String(error)
33
+ };
34
+ }
35
+ };