@dtoolkit/dbrain 0.3.1 → 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.
Files changed (82) hide show
  1. package/README.md +39 -7
  2. package/dist/cli/compact.d.ts +10 -0
  3. package/dist/cli/compact.d.ts.map +1 -0
  4. package/dist/cli/compact.js +44 -0
  5. package/dist/cli/compact.js.map +1 -0
  6. package/dist/cli/configure.d.ts +2 -0
  7. package/dist/cli/configure.d.ts.map +1 -0
  8. package/dist/cli/configure.js +126 -0
  9. package/dist/cli/configure.js.map +1 -0
  10. package/dist/cli/index.js +63 -0
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/init.d.ts.map +1 -1
  13. package/dist/cli/init.js +18 -0
  14. package/dist/cli/init.js.map +1 -1
  15. package/dist/cli/keys.d.ts +11 -0
  16. package/dist/cli/keys.d.ts.map +1 -0
  17. package/dist/cli/keys.js +85 -0
  18. package/dist/cli/keys.js.map +1 -0
  19. package/dist/cli/link.d.ts +12 -0
  20. package/dist/cli/link.d.ts.map +1 -0
  21. package/dist/cli/link.js +118 -0
  22. package/dist/cli/link.js.map +1 -0
  23. package/dist/cli/start.d.ts.map +1 -1
  24. package/dist/cli/start.js +31 -1
  25. package/dist/cli/start.js.map +1 -1
  26. package/dist/cli/status.d.ts.map +1 -1
  27. package/dist/cli/status.js +23 -1
  28. package/dist/cli/status.js.map +1 -1
  29. package/dist/core/compact.d.ts +18 -0
  30. package/dist/core/compact.d.ts.map +1 -0
  31. package/dist/core/compact.js +117 -0
  32. package/dist/core/compact.js.map +1 -0
  33. package/dist/core/config.d.ts +23 -0
  34. package/dist/core/config.d.ts.map +1 -1
  35. package/dist/core/config.js +31 -1
  36. package/dist/core/config.js.map +1 -1
  37. package/dist/core/connections.d.ts +9 -0
  38. package/dist/core/connections.d.ts.map +1 -0
  39. package/dist/core/connections.js +25 -0
  40. package/dist/core/connections.js.map +1 -0
  41. package/dist/core/db.d.ts.map +1 -1
  42. package/dist/core/db.js +36 -0
  43. package/dist/core/db.js.map +1 -1
  44. package/dist/dashboard/index.html +250 -26
  45. package/dist/mcp/server.d.ts.map +1 -1
  46. package/dist/mcp/server.js +216 -15
  47. package/dist/mcp/server.js.map +1 -1
  48. package/dist/server/index.d.ts.map +1 -1
  49. package/dist/server/index.js +30 -2
  50. package/dist/server/index.js.map +1 -1
  51. package/dist/server/routes/compact.d.ts +3 -0
  52. package/dist/server/routes/compact.d.ts.map +1 -0
  53. package/dist/server/routes/compact.js +29 -0
  54. package/dist/server/routes/compact.js.map +1 -0
  55. package/dist/server/routes/entities.d.ts.map +1 -1
  56. package/dist/server/routes/entities.js +6 -1
  57. package/dist/server/routes/entities.js.map +1 -1
  58. package/dist/server/routes/facts.d.ts.map +1 -1
  59. package/dist/server/routes/facts.js +55 -2
  60. package/dist/server/routes/facts.js.map +1 -1
  61. package/dist/server/routes/health.d.ts.map +1 -1
  62. package/dist/server/routes/health.js +46 -2
  63. package/dist/server/routes/health.js.map +1 -1
  64. package/dist/server/routes/keys.d.ts +3 -0
  65. package/dist/server/routes/keys.d.ts.map +1 -0
  66. package/dist/server/routes/keys.js +73 -0
  67. package/dist/server/routes/keys.js.map +1 -0
  68. package/dist/server/routes/permissions.d.ts +3 -0
  69. package/dist/server/routes/permissions.d.ts.map +1 -0
  70. package/dist/server/routes/permissions.js +9 -0
  71. package/dist/server/routes/permissions.js.map +1 -0
  72. package/dist/server/routes/proxy.d.ts +3 -0
  73. package/dist/server/routes/proxy.d.ts.map +1 -0
  74. package/dist/server/routes/proxy.js +37 -0
  75. package/dist/server/routes/proxy.js.map +1 -0
  76. package/dist/server/routes/search.d.ts.map +1 -1
  77. package/dist/server/routes/search.js +113 -41
  78. package/dist/server/routes/search.js.map +1 -1
  79. package/dist/server/routes/workspace.d.ts.map +1 -1
  80. package/dist/server/routes/workspace.js +5 -0
  81. package/dist/server/routes/workspace.js.map +1 -1
  82. package/package.json +4 -2
@@ -0,0 +1,118 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join, resolve } from 'node:path';
4
+ import * as p from '@clack/prompts';
5
+ import pc from 'picocolors';
6
+ import { loadConfig } from '../core/config.js';
7
+ function configPath(dataPath) {
8
+ return join(dataPath, 'config.json');
9
+ }
10
+ function saveConnections(dataPath, connections) {
11
+ const raw = JSON.parse(readFileSync(configPath(dataPath), 'utf-8'));
12
+ raw.connections = connections;
13
+ writeFileSync(configPath(dataPath), JSON.stringify(raw, null, 2) + '\n');
14
+ }
15
+ export async function link(url, opts) {
16
+ const dataPath = resolve(opts.path || join(homedir(), '.dbrain'));
17
+ let config;
18
+ try {
19
+ config = loadConfig(dataPath);
20
+ }
21
+ catch {
22
+ p.log.error(`${pc.red('No brain found.')} Run ${pc.bold('dbrain init')} first.`);
23
+ process.exit(1);
24
+ }
25
+ if (config.brainType === 'shared') {
26
+ p.log.error(`${pc.red('Shared brains cannot connect to other brains.')}`);
27
+ process.exit(1);
28
+ }
29
+ const token = opts.token;
30
+ if (!token) {
31
+ p.log.error(`${pc.red('--token is required')}`);
32
+ process.exit(1);
33
+ }
34
+ p.log.step(`Connecting to ${pc.blue(url)}...`);
35
+ let health;
36
+ try {
37
+ const res = await fetch(`${url}/health`, {
38
+ headers: { Authorization: `Bearer ${token}` },
39
+ });
40
+ if (!res.ok)
41
+ throw new Error(`HTTP ${res.status}`);
42
+ health = (await res.json());
43
+ }
44
+ catch (err) {
45
+ p.log.error(`${pc.red('Cannot reach brain:')} ${err.message}`);
46
+ process.exit(1);
47
+ }
48
+ if (health.brainType !== 'shared') {
49
+ p.log.error(`${pc.red('Target brain is not shared.')} Only personal → shared connections are allowed.`);
50
+ process.exit(1);
51
+ }
52
+ const name = opts.name || health.name || new URL(url).hostname;
53
+ const existing = config.connections.find((c) => c.url === url);
54
+ if (existing) {
55
+ p.log.warn(`${pc.yellow('Already linked to')} ${pc.bold(existing.name)} at ${url}`);
56
+ process.exit(0);
57
+ }
58
+ const connections = [...config.connections, { name, url, token }];
59
+ saveConnections(dataPath, connections);
60
+ p.log.success(`${pc.green('Linked to')} ${pc.bold(name)}`);
61
+ p.note([`Name: ${pc.green(name)}`, `URL: ${pc.dim(url)}`, `Type: ${pc.green('shared')}`].join('\n'), 'Connection');
62
+ }
63
+ export async function unlink(name, opts) {
64
+ const dataPath = resolve(opts.path || join(homedir(), '.dbrain'));
65
+ let config;
66
+ try {
67
+ config = loadConfig(dataPath);
68
+ }
69
+ catch {
70
+ p.log.error(`${pc.red('No brain found.')} Run ${pc.bold('dbrain init')} first.`);
71
+ process.exit(1);
72
+ }
73
+ const idx = config.connections.findIndex((c) => c.name === name);
74
+ if (idx === -1) {
75
+ p.log.error(`${pc.red(`Connection "${name}" not found.`)}`);
76
+ process.exit(1);
77
+ }
78
+ const connections = config.connections.filter((_, i) => i !== idx);
79
+ saveConnections(dataPath, connections);
80
+ p.log.success(`${pc.green('Unlinked')} ${pc.bold(name)}`);
81
+ }
82
+ export async function connections(opts) {
83
+ const dataPath = resolve(opts.path || join(homedir(), '.dbrain'));
84
+ let config;
85
+ try {
86
+ config = loadConfig(dataPath);
87
+ }
88
+ catch {
89
+ p.log.error(`${pc.red('No brain found.')} Run ${pc.bold('dbrain init')} first.`);
90
+ process.exit(1);
91
+ }
92
+ if (config.connections.length === 0) {
93
+ p.log.info('No connections. Use `dbrain link` to connect to a shared brain.');
94
+ return;
95
+ }
96
+ p.log.info(`${pc.bold(`${config.connections.length} connection(s)`)}\n`);
97
+ for (const conn of config.connections) {
98
+ let status = pc.dim('checking...');
99
+ try {
100
+ const res = await fetch(`${conn.url}/health`, {
101
+ headers: { Authorization: `Bearer ${conn.token}` },
102
+ signal: AbortSignal.timeout(3000),
103
+ });
104
+ if (res.ok) {
105
+ const h = (await res.json());
106
+ status = `${pc.green('online')} ${h.entities} entities, ${h.facts} facts`;
107
+ }
108
+ else {
109
+ status = pc.red(`error (${res.status})`);
110
+ }
111
+ }
112
+ catch {
113
+ status = pc.red('offline');
114
+ }
115
+ console.log(` ${pc.bold(conn.name)} ${pc.dim(conn.url)} ${status}`);
116
+ }
117
+ }
118
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/cli/link.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAeA,wBAAsB,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,iBAyB3C"}
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAiBA,wBAAsB,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,iBA4D3C"}
package/dist/cli/start.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { homedir } from 'node:os';
2
2
  import { resolve } from 'node:path';
3
+ import { Cron } from 'croner';
3
4
  import pc from 'picocolors';
5
+ import { compact } from '../core/compact.js';
4
6
  import { loadConfig } from '../core/config.js';
5
7
  import { createDatabase } from '../core/db.js';
6
8
  import { startDashboard } from '../dashboard/server.js';
@@ -20,6 +22,34 @@ export async function start(pathArg) {
20
22
  startDashboard(dashboardPort);
21
23
  const identity = db.prepare("SELECT content FROM documents WHERE key = 'identity'").get();
22
24
  const name = identity?.content?.match(/\*\*Name:\*\* (.+)/)?.[1] || 'dbrain';
25
+ let compactLine = '';
26
+ if (config.compact.schedule) {
27
+ const job = new Cron(config.compact.schedule, () => {
28
+ console.log(`\n${pc.dim('[compact]')} Starting scheduled compaction...`);
29
+ try {
30
+ const result = compact({
31
+ db,
32
+ tiers: config.tiers,
33
+ threshold: config.compact.threshold,
34
+ limit: config.compact.limit,
35
+ steps: ['dedup', 'tiers'],
36
+ onProgress: (msg) => console.log(` ${pc.dim('[compact]')} ${msg}`),
37
+ });
38
+ const now = new Date().toISOString();
39
+ const payload = JSON.stringify({ ...result, at: now });
40
+ db.prepare(`INSERT INTO documents (key, title, content, updated_at)
41
+ VALUES ('compact_last_run', 'Last Compact Run', ?, ?)
42
+ ON CONFLICT(key) DO UPDATE SET content = excluded.content, updated_at = excluded.updated_at`).run(payload, now);
43
+ console.log(`${pc.dim('[compact]')} Done — ` +
44
+ `${result.factsDeduped} deduped, ${result.tiersUpdated} tiers updated`);
45
+ }
46
+ catch (err) {
47
+ console.error(`${pc.red('[compact]')} Error: ${err.message}`);
48
+ }
49
+ });
50
+ const next = job.nextRun();
51
+ compactLine = `\n ${pc.green('Compact')}: ${config.compact.schedule} (next: ${next?.toLocaleString() ?? 'unknown'})`;
52
+ }
23
53
  console.log(`
24
54
  ${pc.cyan(name)} is awake
25
55
 
@@ -27,7 +57,7 @@ ${pc.cyan(name)} is awake
27
57
  ${pc.green('MCP')}: ${address}/mcp
28
58
  ${pc.green('Dashboard')}: http://localhost:${dashboardPort}
29
59
  ${pc.green('Brain')}: ${config.dataPath}
30
- ${pc.green('Token')}: ${config.token.slice(0, 16)}...
60
+ ${pc.green('Token')}: ${config.token.slice(0, 16)}...${compactLine}
31
61
  `);
32
62
  }
33
63
  //# sourceMappingURL=start.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,SAAS,eAAe,CAAC,OAAgB;IACvC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAgB;IAC1C,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACrD,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAE3E,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IACtC,cAAc,CAAC,aAAa,CAAC,CAAC;IAE9B,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,sDAAsD,CAAC,CAAC,GAAG,EAE1E,CAAC;IACd,MAAM,IAAI,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;IAE7E,OAAO,CAAC,GAAG,CAAC;EACZ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;;IAEX,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,OAAO;IACjC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,OAAO;IACjC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,sBAAsB,aAAa;IACxD,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,MAAM,CAAC,QAAQ;IACzC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;CACtD,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAaA,wBAAsB,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,iBAqB5C"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAeA,wBAAsB,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,iBA4C5C"}
@@ -3,6 +3,7 @@ import { homedir } from 'node:os';
3
3
  import { resolve, join } from 'node:path';
4
4
  import pc from 'picocolors';
5
5
  import { loadConfig } from '../core/config.js';
6
+ import { createDatabase } from '../core/db.js';
6
7
  function resolveDataPath(pathArg) {
7
8
  if (pathArg)
8
9
  return resolve(pathArg.replace('~', homedir()));
@@ -18,13 +19,34 @@ export async function status(pathArg) {
18
19
  const dbPath = join(dataPath, 'dbrain.db');
19
20
  const dbExists = existsSync(dbPath);
20
21
  const dbSize = dbExists ? statSync(dbPath).size : 0;
22
+ let compactLines = '';
23
+ if (config.compact.schedule) {
24
+ compactLines += `\n ${pc.green('Compact')}: ${config.compact.schedule}`;
25
+ }
26
+ if (dbExists) {
27
+ try {
28
+ const db = createDatabase(config);
29
+ const row = db
30
+ .prepare("SELECT content FROM documents WHERE key = 'compact_last_run'")
31
+ .get();
32
+ db.close();
33
+ if (row) {
34
+ const last = JSON.parse(row.content);
35
+ const date = new Date(last.at).toLocaleString();
36
+ compactLines += `\n ${pc.green('Last run')}: ${date} — ${last.factsDeduped} deduped, ${last.tiersUpdated} tiers updated`;
37
+ }
38
+ }
39
+ catch {
40
+ // db read failed, skip compact info
41
+ }
42
+ }
21
43
  console.log(`
22
44
  ${pc.cyan('dbrain')} status
23
45
 
24
46
  ${pc.green('Data')}: ${config.dataPath}
25
47
  ${pc.green('Port')}: ${config.port}
26
48
  ${pc.green('Host')}: ${config.host}
27
- ${pc.green('Database')}: ${dbExists ? `${(dbSize / 1024).toFixed(1)} KB` : 'not created'}
49
+ ${pc.green('Database')}: ${dbExists ? `${(dbSize / 1024).toFixed(1)} KB` : 'not created'}${compactLines}
28
50
  `);
29
51
  }
30
52
  //# sourceMappingURL=status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,SAAS,eAAe,CAAC,OAAgB;IACvC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAgB;IAC3C,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAE1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpD,OAAO,CAAC,GAAG,CAAC;EACZ,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;;IAEf,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,MAAM,CAAC,QAAQ;IACxC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,MAAM,CAAC,IAAI;IACpC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,MAAM,CAAC,IAAI;IACpC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa;CACzF,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { TierConfig } from '@dtoolkit/core';
2
+ import type Database from 'better-sqlite3';
3
+ export interface CompactOptions {
4
+ db: Database.Database;
5
+ tiers: TierConfig;
6
+ threshold?: number;
7
+ limit?: number;
8
+ dryRun?: boolean;
9
+ steps?: ('dedup' | 'tiers')[];
10
+ onProgress?: (msg: string) => void;
11
+ }
12
+ export interface CompactResult {
13
+ factsDeduped: number;
14
+ factsProcessed: number;
15
+ tiersUpdated: number;
16
+ }
17
+ export declare function compact(opts: CompactOptions): CompactResult;
18
+ //# sourceMappingURL=compact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../src/core/compact.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;IAC9B,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAYD,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAwB3D"}
@@ -0,0 +1,117 @@
1
+ import { computeTier, diceCoefficient } from '@dtoolkit/core';
2
+ export function compact(opts) {
3
+ const { db, tiers, threshold = 0.85, limit = 1000, dryRun = false, steps = ['dedup', 'tiers'], onProgress, } = opts;
4
+ const result = { factsDeduped: 0, factsProcessed: 0, tiersUpdated: 0 };
5
+ if (steps.includes('dedup')) {
6
+ const dedup = deduplicateFacts(db, threshold, limit, dryRun, onProgress);
7
+ result.factsDeduped = dedup.archived;
8
+ result.factsProcessed = dedup.processed;
9
+ }
10
+ if (steps.includes('tiers')) {
11
+ result.tiersUpdated = recalculateTiers(db, tiers, dryRun, onProgress);
12
+ }
13
+ return result;
14
+ }
15
+ function deduplicateFacts(db, threshold, limit, dryRun, onProgress) {
16
+ const facts = db
17
+ .prepare(`SELECT id, entity_id, fact, last_accessed, access_count, tier, compacted_at
18
+ FROM facts
19
+ WHERE status = 'active' AND tier = 'cold' AND compacted_at IS NULL
20
+ ORDER BY last_accessed ASC
21
+ LIMIT ?`)
22
+ .all(limit);
23
+ onProgress?.(`Found ${facts.length} uncompacted cold facts`);
24
+ if (facts.length === 0)
25
+ return { archived: 0, processed: 0 };
26
+ const byEntity = new Map();
27
+ for (const f of facts) {
28
+ const group = byEntity.get(f.entity_id) ?? [];
29
+ group.push(f);
30
+ byEntity.set(f.entity_id, group);
31
+ }
32
+ const toArchive = [];
33
+ const toMark = [];
34
+ const now = new Date().toISOString();
35
+ for (const [entityId, group] of byEntity) {
36
+ if (group.length < 2) {
37
+ toMark.push(group[0].id);
38
+ continue;
39
+ }
40
+ const dominated = new Set();
41
+ for (let i = 0; i < group.length; i++) {
42
+ const fi = group[i];
43
+ if (dominated.has(fi.id))
44
+ continue;
45
+ for (let j = i + 1; j < group.length; j++) {
46
+ const fj = group[j];
47
+ if (dominated.has(fj.id))
48
+ continue;
49
+ const score = diceCoefficient(fi.fact, fj.fact);
50
+ if (score >= threshold) {
51
+ const [keep, drop] = pickWinner(fi, fj);
52
+ dominated.add(drop.id);
53
+ onProgress?.(`[${entityId}] ${(score * 100).toFixed(0)}% match:\n` +
54
+ ` keep: "${keep.fact}"\n` +
55
+ ` drop: "${drop.fact}"`);
56
+ toArchive.push(drop.id);
57
+ }
58
+ }
59
+ }
60
+ for (const f of group) {
61
+ if (!dominated.has(f.id))
62
+ toMark.push(f.id);
63
+ }
64
+ }
65
+ if (!dryRun && (toArchive.length > 0 || toMark.length > 0)) {
66
+ const tx = db.transaction(() => {
67
+ const archiveStmt = db.prepare("UPDATE facts SET status = 'archived' WHERE id = ?");
68
+ for (const id of toArchive)
69
+ archiveStmt.run(id);
70
+ const markStmt = db.prepare('UPDATE facts SET compacted_at = ? WHERE id = ?');
71
+ for (const id of toMark)
72
+ markStmt.run(now, id);
73
+ });
74
+ tx();
75
+ }
76
+ onProgress?.(dryRun
77
+ ? `Dry run: would archive ${toArchive.length} duplicates, mark ${toMark.length} as compacted`
78
+ : `Archived ${toArchive.length} duplicates, marked ${toMark.length} as compacted`);
79
+ return { archived: toArchive.length, processed: toMark.length };
80
+ }
81
+ function pickWinner(a, b) {
82
+ if (a.access_count !== b.access_count) {
83
+ return a.access_count > b.access_count ? [a, b] : [b, a];
84
+ }
85
+ return a.last_accessed >= b.last_accessed ? [a, b] : [b, a];
86
+ }
87
+ function recalculateTiers(db, tiers, dryRun, onProgress) {
88
+ const facts = db
89
+ .prepare("SELECT id, last_accessed, access_count, tier, compacted_at FROM facts WHERE status = 'active'")
90
+ .all();
91
+ const updates = [];
92
+ for (const f of facts) {
93
+ const newTier = computeTier(f.last_accessed, f.access_count, tiers);
94
+ if (newTier !== f.tier) {
95
+ const resetCompacted = newTier === 'cold' && f.tier !== 'cold';
96
+ updates.push({ id: f.id, newTier, resetCompacted });
97
+ }
98
+ }
99
+ if (!dryRun && updates.length > 0) {
100
+ const tx = db.transaction(() => {
101
+ const resetStmt = db.prepare('UPDATE facts SET tier = ?, compacted_at = NULL WHERE id = ?');
102
+ const keepStmt = db.prepare('UPDATE facts SET tier = ? WHERE id = ?');
103
+ for (const u of updates) {
104
+ if (u.resetCompacted)
105
+ resetStmt.run(u.newTier, u.id);
106
+ else
107
+ keepStmt.run(u.newTier, u.id);
108
+ }
109
+ });
110
+ tx();
111
+ }
112
+ onProgress?.(dryRun
113
+ ? `Dry run: would update ${updates.length} tier assignments`
114
+ : `Updated ${updates.length} tier assignments`);
115
+ return updates.length;
116
+ }
117
+ //# sourceMappingURL=compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/core/compact.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,38 @@
1
1
  import { z } from 'zod';
2
+ export declare const ConnectionSchema: z.ZodObject<{
3
+ name: z.ZodString;
4
+ url: z.ZodString;
5
+ token: z.ZodString;
6
+ }, z.core.$strip>;
7
+ export type Connection = z.infer<typeof ConnectionSchema>;
2
8
  export declare const ConfigSchema: z.ZodObject<{
3
9
  dataPath: z.ZodString;
4
10
  port: z.ZodDefault<z.ZodNumber>;
5
11
  host: z.ZodDefault<z.ZodString>;
6
12
  token: z.ZodString;
13
+ brainName: z.ZodOptional<z.ZodString>;
14
+ brainType: z.ZodDefault<z.ZodEnum<{
15
+ personal: "personal";
16
+ shared: "shared";
17
+ }>>;
18
+ connections: z.ZodDefault<z.ZodArray<z.ZodObject<{
19
+ name: z.ZodString;
20
+ url: z.ZodString;
21
+ token: z.ZodString;
22
+ }, z.core.$strip>>>;
7
23
  tiers: z.ZodDefault<z.ZodObject<{
8
24
  hotDays: z.ZodDefault<z.ZodNumber>;
9
25
  hotMinAccess: z.ZodDefault<z.ZodNumber>;
10
26
  warmDays: z.ZodDefault<z.ZodNumber>;
11
27
  }, z.core.$strip>>;
28
+ compact: z.ZodDefault<z.ZodObject<{
29
+ threshold: z.ZodDefault<z.ZodNumber>;
30
+ limit: z.ZodDefault<z.ZodNumber>;
31
+ schedule: z.ZodOptional<z.ZodString>;
32
+ provider: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strip>>;
12
34
  }, z.core.$strip>;
13
35
  export type Config = z.infer<typeof ConfigSchema>;
14
36
  export declare function loadConfig(dataPath: string): Config;
37
+ export declare function loadConnections(dataPath: string): Connection[];
15
38
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;;;;;;;iBAYvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMnD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,gBAAgB;;;;iBAI3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuBvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUnD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAK9D"}
@@ -1,11 +1,20 @@
1
1
  import { readFileSync, existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { z } from 'zod';
4
+ // Connections only go personal → shared. No chaining.
5
+ export const ConnectionSchema = z.object({
6
+ name: z.string(),
7
+ url: z.string(),
8
+ token: z.string(),
9
+ });
4
10
  export const ConfigSchema = z.object({
5
11
  dataPath: z.string(),
6
12
  port: z.number().default(7878),
7
13
  host: z.string().default('0.0.0.0'),
8
14
  token: z.string(),
15
+ brainName: z.string().optional(),
16
+ brainType: z.enum(['personal', 'shared']).default('personal'),
17
+ connections: z.array(ConnectionSchema).default([]),
9
18
  tiers: z
10
19
  .object({
11
20
  hotDays: z.number().default(7),
@@ -13,12 +22,33 @@ export const ConfigSchema = z.object({
13
22
  warmDays: z.number().default(30),
14
23
  })
15
24
  .default({ hotDays: 7, hotMinAccess: 10, warmDays: 30 }),
25
+ compact: z
26
+ .object({
27
+ threshold: z.number().min(0).max(1).default(0.85),
28
+ limit: z.number().min(1).default(1000),
29
+ schedule: z.string().optional(),
30
+ provider: z.string().optional(),
31
+ })
32
+ .default({ threshold: 0.85, limit: 1000 }),
16
33
  });
17
34
  export function loadConfig(dataPath) {
18
35
  const configPath = join(dataPath, 'config.json');
19
36
  if (!existsSync(configPath)) {
20
37
  throw new Error(`Config not found at ${configPath}. Run 'dbrain init' first.`);
21
38
  }
22
- return ConfigSchema.parse(JSON.parse(readFileSync(configPath, 'utf-8')));
39
+ const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
40
+ raw.dataPath = dataPath;
41
+ if (process.env.DBRAIN_BRAIN_NAME)
42
+ raw.brainName = process.env.DBRAIN_BRAIN_NAME;
43
+ if (process.env.DBRAIN_BRAIN_TYPE)
44
+ raw.brainType = process.env.DBRAIN_BRAIN_TYPE;
45
+ return ConfigSchema.parse(raw);
46
+ }
47
+ export function loadConnections(dataPath) {
48
+ const configPath = join(dataPath, 'config.json');
49
+ if (!existsSync(configPath))
50
+ return [];
51
+ const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
52
+ return ConfigSchema.parse(raw).connections;
23
53
  }
24
54
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KACjC,CAAC;SACD,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;CAC3D,CAAC,CAAC;AAIH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,4BAA4B,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;CAClB,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAC7D,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAClD,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KACjC,CAAC;SACD,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1D,OAAO,EAAE,CAAC;SACP,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QACjD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QACtC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAChC,CAAC;SACD,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;CAC7C,CAAC,CAAC;AAIH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,4BAA4B,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACxB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACjF,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACjF,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { DBrainClient } from '@dtoolkit/sdk';
2
+ import type { Connection } from './config.js';
3
+ export declare function getConnection(connections: Connection[], name?: string): DBrainClient | null;
4
+ export declare function getAllConnections(connections: Connection[]): Array<{
5
+ name: string;
6
+ client: DBrainClient;
7
+ }>;
8
+ export declare function clearCache(): void;
9
+ //# sourceMappingURL=connections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/core/connections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,wBAAgB,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAW3F;AAED,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,UAAU,EAAE,GACxB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC,CAK/C;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
@@ -0,0 +1,25 @@
1
+ import { DBrainClient } from '@dtoolkit/sdk';
2
+ const TIMEOUT_MS = 5000;
3
+ const cache = new Map();
4
+ export function getConnection(connections, name) {
5
+ const conn = name ? connections.find((c) => c.name === name) : connections[0];
6
+ if (!conn)
7
+ return null;
8
+ const key = conn.url;
9
+ let client = cache.get(key);
10
+ if (!client) {
11
+ client = new DBrainClient({ baseUrl: conn.url, token: conn.token, timeoutMs: TIMEOUT_MS });
12
+ cache.set(key, client);
13
+ }
14
+ return client;
15
+ }
16
+ export function getAllConnections(connections) {
17
+ return connections.map((c) => ({
18
+ name: c.name,
19
+ client: getConnection(connections, c.name),
20
+ }));
21
+ }
22
+ export function clearCache() {
23
+ cache.clear();
24
+ }
25
+ //# sourceMappingURL=connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/core/connections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAI7C,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;AAE9C,MAAM,UAAU,aAAa,CAAC,WAAyB,EAAE,IAAa;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9E,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QAC3F,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,WAAyB;IAEzB,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAiB;KAC3D,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAkF1C,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAOhE"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAgI1C,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAQhE"}
package/dist/core/db.js CHANGED
@@ -79,12 +79,48 @@ CREATE TRIGGER IF NOT EXISTS facts_au AFTER UPDATE ON facts BEGIN
79
79
  VALUES (new.rowid, new.fact, new.entity_id, new.category);
80
80
  END;
81
81
  `;
82
+ function migrate(db) {
83
+ db.exec('CREATE TABLE IF NOT EXISTS schema_version (version INTEGER PRIMARY KEY)');
84
+ const row = db.prepare('SELECT MAX(version) as v FROM schema_version').get();
85
+ const current = row?.v ?? 0;
86
+ if (current < 1) {
87
+ const columns = db.pragma('table_info(facts)').map((c) => c.name);
88
+ if (!columns.includes('author_id')) {
89
+ db.exec('ALTER TABLE facts ADD COLUMN author_id TEXT');
90
+ }
91
+ if (!columns.includes('origin_brain')) {
92
+ db.exec('ALTER TABLE facts ADD COLUMN origin_brain TEXT');
93
+ }
94
+ db.exec(`
95
+ CREATE TABLE IF NOT EXISTS api_keys (
96
+ id TEXT PRIMARY KEY,
97
+ token TEXT NOT NULL UNIQUE,
98
+ user_id TEXT NOT NULL,
99
+ user_name TEXT NOT NULL,
100
+ permissions TEXT NOT NULL DEFAULT 'read+write',
101
+ created_at TEXT NOT NULL,
102
+ last_used TEXT,
103
+ status TEXT DEFAULT 'active'
104
+ );
105
+ CREATE INDEX IF NOT EXISTS idx_api_keys_token ON api_keys(token);
106
+ `);
107
+ db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(1);
108
+ }
109
+ if (current < 2) {
110
+ const columns = db.pragma('table_info(facts)').map((c) => c.name);
111
+ if (!columns.includes('compacted_at')) {
112
+ db.exec('ALTER TABLE facts ADD COLUMN compacted_at TEXT');
113
+ }
114
+ db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(2);
115
+ }
116
+ }
82
117
  export function createDatabase(config) {
83
118
  const dbPath = join(config.dataPath, 'dbrain.db');
84
119
  const db = new Database(dbPath);
85
120
  db.pragma('journal_mode = WAL');
86
121
  db.pragma('foreign_keys = ON');
87
122
  db.exec(SCHEMA);
123
+ migrate(db);
88
124
  return db;
89
125
  }
90
126
  //# sourceMappingURL=db.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Ed,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,OAAO,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Ed,CAAC;AAEF,SAAS,OAAO,CAAC,EAAqB;IACpC,EAAE,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;IAEnF,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,EAE7D,CAAC;IACd,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAE5B,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,OAAO,GAAI,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAE1F,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACnC,EAAE,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACtC,EAAE,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC5D,CAAC;QAED,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;KAYP,CAAC,CAAC;QAEH,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,OAAO,GAAI,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAE1F,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACtC,EAAE,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC5D,CAAC;QAED,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,EAAE,CAAC;AACZ,CAAC"}