@ai-devkit/memory 0.1.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/README.md +149 -0
- package/dist/api.d.ts +20 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +46 -0
- package/dist/api.js.map +1 -0
- package/dist/database/connection.d.ts +27 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +107 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/index.d.ts +4 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +37 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/migrations/001_initial.sql +50 -0
- package/dist/database/schema.d.ts +6 -0
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/database/schema.js +89 -0
- package/dist/database/schema.js.map +1 -0
- package/dist/handlers/search.d.ts +3 -0
- package/dist/handlers/search.d.ts.map +1 -0
- package/dist/handlers/search.js +78 -0
- package/dist/handlers/search.js.map +1 -0
- package/dist/handlers/store.d.ts +3 -0
- package/dist/handlers/store.d.ts.map +1 -0
- package/dist/handlers/store.js +71 -0
- package/dist/handlers/store.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +172 -0
- package/dist/server.js.map +1 -0
- package/dist/services/normalizer.d.ts +21 -0
- package/dist/services/normalizer.d.ts.map +1 -0
- package/dist/services/normalizer.js +52 -0
- package/dist/services/normalizer.js.map +1 -0
- package/dist/services/ranker.d.ts +21 -0
- package/dist/services/ranker.d.ts.map +1 -0
- package/dist/services/ranker.js +70 -0
- package/dist/services/ranker.js.map +1 -0
- package/dist/services/search.d.ts +29 -0
- package/dist/services/search.d.ts.map +1 -0
- package/dist/services/search.js +92 -0
- package/dist/services/search.js.map +1 -0
- package/dist/services/validator.d.ts +11 -0
- package/dist/services/validator.d.ts.map +1 -0
- package/dist/services/validator.js +144 -0
- package/dist/services/validator.js.map +1 -0
- package/dist/types/index.d.ts +58 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/errors.d.ts +21 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +76 -0
- package/dist/utils/errors.js.map +1 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @ai-devkit/memory
|
|
2
|
+
|
|
3
|
+
A lightweight MCP-based memory service for AI agents. Store and retrieve actionable knowledge using SQLite with FTS5 full-text search.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔍 **Full-Text Search** - FTS5 with BM25 ranking
|
|
8
|
+
- 🏷️ **Tag-Based Filtering** - Boost results by contextTags
|
|
9
|
+
- 📁 **Scoped Knowledge** - global, project, or repo-specific rules
|
|
10
|
+
- 🔄 **Deduplication** - Prevents duplicate content
|
|
11
|
+
- ⚡ **Fast** - SQLite with WAL mode, <50ms search latency
|
|
12
|
+
- 📦 **Portable** - Single database file, no external dependencies
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @ai-devkit/memory
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### As MCP Server
|
|
23
|
+
|
|
24
|
+
Add to your MCP client configuration:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"memory": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["@ai-devkit/memory"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Using the Tools
|
|
38
|
+
|
|
39
|
+
#### Store Knowledge
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"tool": "memory.storeKnowledge",
|
|
44
|
+
"arguments": {
|
|
45
|
+
"title": "Always use Response DTOs for API endpoints",
|
|
46
|
+
"content": "When building REST APIs, always use Response DTOs instead of returning domain entities directly. This provides better API versioning, security, and decoupling.",
|
|
47
|
+
"tags": ["api", "backend", "dto"],
|
|
48
|
+
"scope": "global"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Search Knowledge
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"tool": "memory.searchKnowledge",
|
|
58
|
+
"arguments": {
|
|
59
|
+
"query": "building an API endpoint",
|
|
60
|
+
"contextTags": ["api"],
|
|
61
|
+
"limit": 5
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### CLI Commands
|
|
67
|
+
|
|
68
|
+
You can also use the CLI directly:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Store knowledge
|
|
72
|
+
ai-devkit-memory store \
|
|
73
|
+
-t "Always use Response DTOs for API endpoints" \
|
|
74
|
+
-c "When building REST APIs, always use Response DTOs..." \
|
|
75
|
+
--tags "api,backend,dto" \
|
|
76
|
+
-s global
|
|
77
|
+
|
|
78
|
+
# Search knowledge
|
|
79
|
+
ai-devkit-memory search -q "API best practices" --tags "api" -l 5
|
|
80
|
+
|
|
81
|
+
# Start MCP server (default)
|
|
82
|
+
ai-devkit-memory serve
|
|
83
|
+
# or just:
|
|
84
|
+
ai-devkit-memory
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API Reference
|
|
88
|
+
|
|
89
|
+
### `memory.storeKnowledge`
|
|
90
|
+
|
|
91
|
+
Store a new knowledge item.
|
|
92
|
+
|
|
93
|
+
| Parameter | Type | Required | Description |
|
|
94
|
+
|-----------|------|----------|-------------|
|
|
95
|
+
| `title` | string | ✅ | Short description (10-100 chars) |
|
|
96
|
+
| `content` | string | ✅ | Detailed explanation in markdown (50-5000 chars) |
|
|
97
|
+
| `tags` | string[] | ❌ | Domain keywords (max 10) |
|
|
98
|
+
| `scope` | string | ❌ | `global`, `project:<name>`, or `repo:<name>` |
|
|
99
|
+
|
|
100
|
+
### `memory.searchKnowledge`
|
|
101
|
+
|
|
102
|
+
Search for relevant knowledge.
|
|
103
|
+
|
|
104
|
+
| Parameter | Type | Required | Description |
|
|
105
|
+
|-----------|------|----------|-------------|
|
|
106
|
+
| `query` | string | ✅ | Natural language task description (3-500 chars) |
|
|
107
|
+
| `contextTags` | string[] | ❌ | Tags to boost matching results |
|
|
108
|
+
| `scope` | string | ❌ | Scope filter (project results prioritized) |
|
|
109
|
+
| `limit` | number | ❌ | Max results (1-20, default: 5) |
|
|
110
|
+
|
|
111
|
+
## Ranking Algorithm
|
|
112
|
+
|
|
113
|
+
Results are ranked using:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
final_score = bm25_score × tag_boost + scope_boost
|
|
117
|
+
|
|
118
|
+
Where:
|
|
119
|
+
bm25_score = FTS5 bm25() with column weights (title=10, content=5, tags=1)
|
|
120
|
+
tag_boost = 1 + (matching_tags × 0.1)
|
|
121
|
+
scope_boost = +0.5 if scope matches, +0.2 if global
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Database Location
|
|
125
|
+
|
|
126
|
+
Default: `~/.ai-devkit/memory.db`
|
|
127
|
+
|
|
128
|
+
## Development
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Install dependencies
|
|
132
|
+
npm install
|
|
133
|
+
|
|
134
|
+
# Build
|
|
135
|
+
npm run build
|
|
136
|
+
|
|
137
|
+
# Run tests
|
|
138
|
+
npm test
|
|
139
|
+
|
|
140
|
+
# Run with MCP Inspector
|
|
141
|
+
npm run inspect
|
|
142
|
+
|
|
143
|
+
# Start server
|
|
144
|
+
npm run start
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { storeKnowledge } from './handlers/store';
|
|
2
|
+
import { searchKnowledge } from './handlers/search';
|
|
3
|
+
import type { StoreKnowledgeInput, SearchKnowledgeInput, StoreKnowledgeResult, SearchKnowledgeResult } from './types';
|
|
4
|
+
export { storeKnowledge, searchKnowledge };
|
|
5
|
+
export type { StoreKnowledgeInput, SearchKnowledgeInput, StoreKnowledgeResult, SearchKnowledgeResult };
|
|
6
|
+
export interface MemoryStoreOptions {
|
|
7
|
+
title: string;
|
|
8
|
+
content: string;
|
|
9
|
+
tags?: string;
|
|
10
|
+
scope?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MemorySearchOptions {
|
|
13
|
+
query: string;
|
|
14
|
+
tags?: string;
|
|
15
|
+
scope?: string;
|
|
16
|
+
limit?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function memoryStoreCommand(options: MemoryStoreOptions): StoreKnowledgeResult;
|
|
19
|
+
export declare function memorySearchCommand(options: MemorySearchOptions): SearchKnowledgeResult;
|
|
20
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEtH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,CAAC;AAGvG,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,oBAAoB,CASpF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,qBAAqB,CASvF"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get memorySearchCommand () {
|
|
13
|
+
return memorySearchCommand;
|
|
14
|
+
},
|
|
15
|
+
get memoryStoreCommand () {
|
|
16
|
+
return memoryStoreCommand;
|
|
17
|
+
},
|
|
18
|
+
get searchKnowledge () {
|
|
19
|
+
return _search.searchKnowledge;
|
|
20
|
+
},
|
|
21
|
+
get storeKnowledge () {
|
|
22
|
+
return _store.storeKnowledge;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const _store = require("./handlers/store");
|
|
26
|
+
const _search = require("./handlers/search");
|
|
27
|
+
function memoryStoreCommand(options) {
|
|
28
|
+
const input = {
|
|
29
|
+
title: options.title,
|
|
30
|
+
content: options.content,
|
|
31
|
+
tags: options.tags ? options.tags.split(',').map((t)=>t.trim()) : undefined,
|
|
32
|
+
scope: options.scope
|
|
33
|
+
};
|
|
34
|
+
return (0, _store.storeKnowledge)(input);
|
|
35
|
+
}
|
|
36
|
+
function memorySearchCommand(options) {
|
|
37
|
+
const input = {
|
|
38
|
+
query: options.query,
|
|
39
|
+
contextTags: options.tags ? options.tags.split(',').map((t)=>t.trim()) : undefined,
|
|
40
|
+
scope: options.scope,
|
|
41
|
+
limit: options.limit
|
|
42
|
+
};
|
|
43
|
+
return (0, _search.searchKnowledge)(input);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api.ts"],"sourcesContent":["import { storeKnowledge } from './handlers/store';\nimport { searchKnowledge } from './handlers/search';\nimport type { StoreKnowledgeInput, SearchKnowledgeInput, StoreKnowledgeResult, SearchKnowledgeResult } from './types';\n\nexport { storeKnowledge, searchKnowledge };\nexport type { StoreKnowledgeInput, SearchKnowledgeInput, StoreKnowledgeResult, SearchKnowledgeResult };\n\n// CLI command handlers for integration with main ai-devkit CLI\nexport interface MemoryStoreOptions {\n title: string;\n content: string;\n tags?: string;\n scope?: string;\n}\n\nexport interface MemorySearchOptions {\n query: string;\n tags?: string;\n scope?: string;\n limit?: number;\n}\n\nexport function memoryStoreCommand(options: MemoryStoreOptions): StoreKnowledgeResult {\n const input: StoreKnowledgeInput = {\n title: options.title,\n content: options.content,\n tags: options.tags ? options.tags.split(',').map(t => t.trim()) : undefined,\n scope: options.scope,\n };\n\n return storeKnowledge(input);\n}\n\nexport function memorySearchCommand(options: MemorySearchOptions): SearchKnowledgeResult {\n const input: SearchKnowledgeInput = {\n query: options.query,\n contextTags: options.tags ? options.tags.split(',').map(t => t.trim()) : undefined,\n scope: options.scope,\n limit: options.limit,\n };\n\n return searchKnowledge(input);\n}\n"],"names":["memorySearchCommand","memoryStoreCommand","searchKnowledge","storeKnowledge","options","input","title","content","tags","split","map","t","trim","undefined","scope","query","contextTags","limit"],"mappings":";;;;;;;;;;;QAiCgBA;eAAAA;;QAXAC;eAAAA;;QAlBSC;eAAAA,uBAAe;;QAA/BC;eAAAA,qBAAc;;;uBAJQ;wBACC;AAqBzB,SAASF,mBAAmBG,OAA2B;IAC1D,MAAMC,QAA6B;QAC/BC,OAAOF,QAAQE,KAAK;QACpBC,SAASH,QAAQG,OAAO;QACxBC,MAAMJ,QAAQI,IAAI,GAAGJ,QAAQI,IAAI,CAACC,KAAK,CAAC,KAAKC,GAAG,CAACC,CAAAA,IAAKA,EAAEC,IAAI,MAAMC;QAClEC,OAAOV,QAAQU,KAAK;IACxB;IAEA,OAAOX,IAAAA,qBAAc,EAACE;AAC1B;AAEO,SAASL,oBAAoBI,OAA4B;IAC5D,MAAMC,QAA8B;QAChCU,OAAOX,QAAQW,KAAK;QACpBC,aAAaZ,QAAQI,IAAI,GAAGJ,QAAQI,IAAI,CAACC,KAAK,CAAC,KAAKC,GAAG,CAACC,CAAAA,IAAKA,EAAEC,IAAI,MAAMC;QACzEC,OAAOV,QAAQU,KAAK;QACpBG,OAAOb,QAAQa,KAAK;IACxB;IAEA,OAAOf,IAAAA,uBAAe,EAACG;AAC3B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
/**
|
|
3
|
+
* Default database path: ~/.ai-devkit/memory.db
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_DB_PATH: string;
|
|
6
|
+
export interface DatabaseOptions {
|
|
7
|
+
dbPath?: string;
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
readonly?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class DatabaseConnection {
|
|
12
|
+
private db;
|
|
13
|
+
private readonly dbPath;
|
|
14
|
+
constructor(options?: DatabaseOptions);
|
|
15
|
+
private configure;
|
|
16
|
+
get instance(): Database.Database;
|
|
17
|
+
get path(): string;
|
|
18
|
+
get isOpen(): boolean;
|
|
19
|
+
query<T>(sql: string, params?: unknown[]): T[];
|
|
20
|
+
queryOne<T>(sql: string, params?: unknown[]): T | undefined;
|
|
21
|
+
execute(sql: string, params?: unknown[]): Database.RunResult;
|
|
22
|
+
transaction<T>(fn: () => T): T;
|
|
23
|
+
close(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare function getDatabase(options?: DatabaseOptions): DatabaseConnection;
|
|
26
|
+
export declare function closeDatabase(): void;
|
|
27
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/database/connection.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAKtC;;GAEG;AACH,eAAO,MAAM,eAAe,QAA6C,CAAC;AAE1E,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,OAAO,GAAE,eAAoB;IAczC,OAAO,CAAC,SAAS;IAQjB,IAAI,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAEhC;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,CAAC,EAAE;IAIlD,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,CAAC,GAAG,SAAS;IAI/D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,QAAQ,CAAC,SAAS;IAGhE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAI9B,KAAK,IAAI,IAAI;CAKhB;AAKD,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,kBAAkB,CAczE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAMpC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get DEFAULT_DB_PATH () {
|
|
13
|
+
return DEFAULT_DB_PATH;
|
|
14
|
+
},
|
|
15
|
+
get DatabaseConnection () {
|
|
16
|
+
return DatabaseConnection;
|
|
17
|
+
},
|
|
18
|
+
get closeDatabase () {
|
|
19
|
+
return closeDatabase;
|
|
20
|
+
},
|
|
21
|
+
get getDatabase () {
|
|
22
|
+
return getDatabase;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const _bettersqlite3 = /*#__PURE__*/ _interop_require_default(require("better-sqlite3"));
|
|
26
|
+
const _fs = require("fs");
|
|
27
|
+
const _path = require("path");
|
|
28
|
+
const _os = require("os");
|
|
29
|
+
function _interop_require_default(obj) {
|
|
30
|
+
return obj && obj.__esModule ? obj : {
|
|
31
|
+
default: obj
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const DEFAULT_DB_PATH = (0, _path.join)((0, _os.homedir)(), '.ai-devkit', 'memory.db');
|
|
35
|
+
let DatabaseConnection = class DatabaseConnection {
|
|
36
|
+
db;
|
|
37
|
+
dbPath;
|
|
38
|
+
constructor(options = {}){
|
|
39
|
+
this.dbPath = options.dbPath ?? DEFAULT_DB_PATH;
|
|
40
|
+
const dir = (0, _path.dirname)(this.dbPath);
|
|
41
|
+
(0, _fs.mkdirSync)(dir, {
|
|
42
|
+
recursive: true
|
|
43
|
+
});
|
|
44
|
+
this.db = new _bettersqlite3.default(this.dbPath, {
|
|
45
|
+
readonly: options.readonly ?? false,
|
|
46
|
+
verbose: options.verbose ? console.log : undefined
|
|
47
|
+
});
|
|
48
|
+
this.configure();
|
|
49
|
+
}
|
|
50
|
+
configure() {
|
|
51
|
+
this.db.pragma('journal_mode = WAL');
|
|
52
|
+
this.db.pragma('foreign_keys = ON');
|
|
53
|
+
this.db.pragma('synchronous = NORMAL');
|
|
54
|
+
this.db.pragma('busy_timeout = 5000');
|
|
55
|
+
this.db.pragma('mmap_size = 268435456');
|
|
56
|
+
}
|
|
57
|
+
get instance() {
|
|
58
|
+
return this.db;
|
|
59
|
+
}
|
|
60
|
+
get path() {
|
|
61
|
+
return this.dbPath;
|
|
62
|
+
}
|
|
63
|
+
get isOpen() {
|
|
64
|
+
return this.db.open;
|
|
65
|
+
}
|
|
66
|
+
query(sql, params = []) {
|
|
67
|
+
return this.db.prepare(sql).all(...params);
|
|
68
|
+
}
|
|
69
|
+
queryOne(sql, params = []) {
|
|
70
|
+
return this.db.prepare(sql).get(...params);
|
|
71
|
+
}
|
|
72
|
+
execute(sql, params = []) {
|
|
73
|
+
return this.db.prepare(sql).run(...params);
|
|
74
|
+
}
|
|
75
|
+
transaction(fn) {
|
|
76
|
+
return this.db.transaction(fn)();
|
|
77
|
+
}
|
|
78
|
+
close() {
|
|
79
|
+
if (this.db.open) {
|
|
80
|
+
this.db.close();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
let instance = null;
|
|
85
|
+
let schemaInitialized = false;
|
|
86
|
+
function getDatabase(options) {
|
|
87
|
+
if (!instance) {
|
|
88
|
+
instance = new DatabaseConnection(options);
|
|
89
|
+
}
|
|
90
|
+
// Auto-run migrations on first access
|
|
91
|
+
if (!schemaInitialized) {
|
|
92
|
+
// Lazy import to avoid circular dependency
|
|
93
|
+
const { initializeSchema } = require('./schema');
|
|
94
|
+
initializeSchema(instance);
|
|
95
|
+
schemaInitialized = true;
|
|
96
|
+
}
|
|
97
|
+
return instance;
|
|
98
|
+
}
|
|
99
|
+
function closeDatabase() {
|
|
100
|
+
if (instance) {
|
|
101
|
+
instance.close();
|
|
102
|
+
instance = null;
|
|
103
|
+
schemaInitialized = false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/database/connection.ts"],"sourcesContent":["import Database from 'better-sqlite3';\nimport { mkdirSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { homedir } from 'os';\n\n/**\n * Default database path: ~/.ai-devkit/memory.db\n */\nexport const DEFAULT_DB_PATH = join(homedir(), '.ai-devkit', 'memory.db');\n\nexport interface DatabaseOptions {\n dbPath?: string;\n verbose?: boolean;\n readonly?: boolean;\n}\n\nexport class DatabaseConnection {\n private db: Database.Database;\n private readonly dbPath: string;\n\n constructor(options: DatabaseOptions = {}) {\n this.dbPath = options.dbPath ?? DEFAULT_DB_PATH;\n\n const dir = dirname(this.dbPath);\n mkdirSync(dir, { recursive: true });\n\n this.db = new Database(this.dbPath, {\n readonly: options.readonly ?? false,\n verbose: options.verbose ? console.log : undefined,\n });\n\n this.configure();\n }\n\n private configure(): void {\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.db.pragma('synchronous = NORMAL');\n this.db.pragma('busy_timeout = 5000');\n this.db.pragma('mmap_size = 268435456');\n }\n\n get instance(): Database.Database {\n return this.db;\n }\n\n get path(): string {\n return this.dbPath;\n }\n\n get isOpen(): boolean {\n return this.db.open;\n }\n\n query<T>(sql: string, params: unknown[] = []): T[] {\n return this.db.prepare(sql).all(...params) as T[];\n }\n\n queryOne<T>(sql: string, params: unknown[] = []): T | undefined {\n return this.db.prepare(sql).get(...params) as T | undefined;\n }\n\n execute(sql: string, params: unknown[] = []): Database.RunResult {\n return this.db.prepare(sql).run(...params);\n }\n transaction<T>(fn: () => T): T {\n return this.db.transaction(fn)();\n }\n\n close(): void {\n if (this.db.open) {\n this.db.close();\n }\n }\n}\n\nlet instance: DatabaseConnection | null = null;\nlet schemaInitialized = false;\n\nexport function getDatabase(options?: DatabaseOptions): DatabaseConnection {\n if (!instance) {\n instance = new DatabaseConnection(options);\n }\n\n // Auto-run migrations on first access\n if (!schemaInitialized) {\n // Lazy import to avoid circular dependency\n const { initializeSchema } = require('./schema');\n initializeSchema(instance);\n schemaInitialized = true;\n }\n\n return instance;\n}\n\nexport function closeDatabase(): void {\n if (instance) {\n instance.close();\n instance = null;\n schemaInitialized = false;\n }\n}"],"names":["DEFAULT_DB_PATH","DatabaseConnection","closeDatabase","getDatabase","join","homedir","db","dbPath","options","dir","dirname","mkdirSync","recursive","Database","readonly","verbose","console","log","undefined","configure","pragma","instance","path","isOpen","open","query","sql","params","prepare","all","queryOne","get","execute","run","transaction","fn","close","schemaInitialized","initializeSchema","require"],"mappings":";;;;;;;;;;;QAQaA;eAAAA;;QAQAC;eAAAA;;QA+EGC;eAAAA;;QAhBAC;eAAAA;;;sEA/EK;oBACK;sBACI;oBACN;;;;;;AAKjB,MAAMH,kBAAkBI,IAAAA,UAAI,EAACC,IAAAA,WAAO,KAAI,cAAc;AAQtD,IAAA,AAAMJ,qBAAN,MAAMA;IACDK,GAAsB;IACbC,OAAe;IAEhC,YAAYC,UAA2B,CAAC,CAAC,CAAE;QACvC,IAAI,CAACD,MAAM,GAAGC,QAAQD,MAAM,IAAIP;QAEhC,MAAMS,MAAMC,IAAAA,aAAO,EAAC,IAAI,CAACH,MAAM;QAC/BI,IAAAA,aAAS,EAACF,KAAK;YAAEG,WAAW;QAAK;QAEjC,IAAI,CAACN,EAAE,GAAG,IAAIO,sBAAQ,CAAC,IAAI,CAACN,MAAM,EAAE;YAChCO,UAAUN,QAAQM,QAAQ,IAAI;YAC9BC,SAASP,QAAQO,OAAO,GAAGC,QAAQC,GAAG,GAAGC;QAC7C;QAEA,IAAI,CAACC,SAAS;IAClB;IAEQA,YAAkB;QACtB,IAAI,CAACb,EAAE,CAACc,MAAM,CAAC;QACf,IAAI,CAACd,EAAE,CAACc,MAAM,CAAC;QACf,IAAI,CAACd,EAAE,CAACc,MAAM,CAAC;QACf,IAAI,CAACd,EAAE,CAACc,MAAM,CAAC;QACf,IAAI,CAACd,EAAE,CAACc,MAAM,CAAC;IACnB;IAEA,IAAIC,WAA8B;QAC9B,OAAO,IAAI,CAACf,EAAE;IAClB;IAEA,IAAIgB,OAAe;QACf,OAAO,IAAI,CAACf,MAAM;IACtB;IAEA,IAAIgB,SAAkB;QAClB,OAAO,IAAI,CAACjB,EAAE,CAACkB,IAAI;IACvB;IAEAC,MAASC,GAAW,EAAEC,SAAoB,EAAE,EAAO;QAC/C,OAAO,IAAI,CAACrB,EAAE,CAACsB,OAAO,CAACF,KAAKG,GAAG,IAAIF;IACvC;IAEAG,SAAYJ,GAAW,EAAEC,SAAoB,EAAE,EAAiB;QAC5D,OAAO,IAAI,CAACrB,EAAE,CAACsB,OAAO,CAACF,KAAKK,GAAG,IAAIJ;IACvC;IAEAK,QAAQN,GAAW,EAAEC,SAAoB,EAAE,EAAsB;QAC7D,OAAO,IAAI,CAACrB,EAAE,CAACsB,OAAO,CAACF,KAAKO,GAAG,IAAIN;IACvC;IACAO,YAAeC,EAAW,EAAK;QAC3B,OAAO,IAAI,CAAC7B,EAAE,CAAC4B,WAAW,CAACC;IAC/B;IAEAC,QAAc;QACV,IAAI,IAAI,CAAC9B,EAAE,CAACkB,IAAI,EAAE;YACd,IAAI,CAAClB,EAAE,CAAC8B,KAAK;QACjB;IACJ;AACJ;AAEA,IAAIf,WAAsC;AAC1C,IAAIgB,oBAAoB;AAEjB,SAASlC,YAAYK,OAAyB;IACjD,IAAI,CAACa,UAAU;QACXA,WAAW,IAAIpB,mBAAmBO;IACtC;IAEA,sCAAsC;IACtC,IAAI,CAAC6B,mBAAmB;QACpB,2CAA2C;QAC3C,MAAM,EAAEC,gBAAgB,EAAE,GAAGC,QAAQ;QACrCD,iBAAiBjB;QACjBgB,oBAAoB;IACxB;IAEA,OAAOhB;AACX;AAEO,SAASnB;IACZ,IAAImB,UAAU;QACVA,SAASe,KAAK;QACdf,WAAW;QACXgB,oBAAoB;IACxB;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/database/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/F,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get DEFAULT_DB_PATH () {
|
|
13
|
+
return _connection.DEFAULT_DB_PATH;
|
|
14
|
+
},
|
|
15
|
+
get DatabaseConnection () {
|
|
16
|
+
return _connection.DatabaseConnection;
|
|
17
|
+
},
|
|
18
|
+
get closeDatabase () {
|
|
19
|
+
return _connection.closeDatabase;
|
|
20
|
+
},
|
|
21
|
+
get getDatabase () {
|
|
22
|
+
return _connection.getDatabase;
|
|
23
|
+
},
|
|
24
|
+
get getSchemaVersion () {
|
|
25
|
+
return _schema.getSchemaVersion;
|
|
26
|
+
},
|
|
27
|
+
get initializeSchema () {
|
|
28
|
+
return _schema.initializeSchema;
|
|
29
|
+
},
|
|
30
|
+
get resetSchema () {
|
|
31
|
+
return _schema.resetSchema;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const _connection = require("./connection");
|
|
35
|
+
const _schema = require("./schema");
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/database/index.ts"],"sourcesContent":["export { DatabaseConnection, getDatabase, closeDatabase, DEFAULT_DB_PATH } from './connection';\nexport type { DatabaseOptions } from './connection';\nexport { initializeSchema, getSchemaVersion, resetSchema } from './schema';\n"],"names":["DEFAULT_DB_PATH","DatabaseConnection","closeDatabase","getDatabase","getSchemaVersion","initializeSchema","resetSchema"],"mappings":";;;;;;;;;;;QAAyDA;eAAAA,2BAAe;;QAA/DC;eAAAA,8BAAkB;;QAAeC;eAAAA,yBAAa;;QAA1BC;eAAAA,uBAAW;;QAEbC;eAAAA,wBAAgB;;QAAlCC;eAAAA,wBAAgB;;QAAoBC;eAAAA,mBAAW;;;4BAFwB;wBAEhB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
-- Migration 001: Initial schema
|
|
2
|
+
-- Creates the core knowledge table and FTS5 index
|
|
3
|
+
|
|
4
|
+
-- Main knowledge table (simplified: 9 fields)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS knowledge (
|
|
6
|
+
id TEXT PRIMARY KEY,
|
|
7
|
+
title TEXT NOT NULL CHECK (length(title) <= 100),
|
|
8
|
+
content TEXT NOT NULL CHECK (length(content) <= 5000),
|
|
9
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
10
|
+
scope TEXT NOT NULL DEFAULT 'global',
|
|
11
|
+
normalized_title TEXT NOT NULL,
|
|
12
|
+
content_hash TEXT NOT NULL,
|
|
13
|
+
created_at TEXT NOT NULL,
|
|
14
|
+
updated_at TEXT NOT NULL,
|
|
15
|
+
|
|
16
|
+
UNIQUE (normalized_title, scope),
|
|
17
|
+
UNIQUE (content_hash, scope)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
-- FTS5 virtual table for full-text search
|
|
21
|
+
-- Column weights for bm25(): title=10, content=5, tags=1
|
|
22
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_fts USING fts5(
|
|
23
|
+
title,
|
|
24
|
+
content,
|
|
25
|
+
tags,
|
|
26
|
+
content='knowledge',
|
|
27
|
+
content_rowid='rowid',
|
|
28
|
+
tokenize='porter unicode61'
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
-- Triggers to keep FTS in sync
|
|
32
|
+
CREATE TRIGGER IF NOT EXISTS knowledge_ai AFTER INSERT ON knowledge BEGIN
|
|
33
|
+
INSERT INTO knowledge_fts(rowid, title, content, tags)
|
|
34
|
+
VALUES (NEW.rowid, NEW.title, NEW.content, NEW.tags);
|
|
35
|
+
END;
|
|
36
|
+
|
|
37
|
+
CREATE TRIGGER IF NOT EXISTS knowledge_ad AFTER DELETE ON knowledge BEGIN
|
|
38
|
+
INSERT INTO knowledge_fts(knowledge_fts, rowid, title, content, tags)
|
|
39
|
+
VALUES ('delete', OLD.rowid, OLD.title, OLD.content, OLD.tags);
|
|
40
|
+
END;
|
|
41
|
+
|
|
42
|
+
CREATE TRIGGER IF NOT EXISTS knowledge_au AFTER UPDATE ON knowledge BEGIN
|
|
43
|
+
INSERT INTO knowledge_fts(knowledge_fts, rowid, title, content, tags)
|
|
44
|
+
VALUES ('delete', OLD.rowid, OLD.title, OLD.content, OLD.tags);
|
|
45
|
+
INSERT INTO knowledge_fts(rowid, title, content, tags)
|
|
46
|
+
VALUES (NEW.rowid, NEW.title, NEW.content, NEW.tags);
|
|
47
|
+
END;
|
|
48
|
+
|
|
49
|
+
-- Index for fast scope filtering
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_knowledge_scope ON knowledge(scope);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DatabaseConnection } from './connection';
|
|
2
|
+
export declare function getSchemaVersion(db: DatabaseConnection): number;
|
|
3
|
+
export declare function initializeSchema(db: DatabaseConnection): void;
|
|
4
|
+
export declare function resetSchema(db: DatabaseConnection): void;
|
|
5
|
+
export declare function getPendingMigrations(db: DatabaseConnection): string[];
|
|
6
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/database/schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,kBAAkB,GAAG,MAAM,CAG/D;AAsCD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI,CAkB7D;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI,CAQxD;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAMrE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get getPendingMigrations () {
|
|
13
|
+
return getPendingMigrations;
|
|
14
|
+
},
|
|
15
|
+
get getSchemaVersion () {
|
|
16
|
+
return getSchemaVersion;
|
|
17
|
+
},
|
|
18
|
+
get initializeSchema () {
|
|
19
|
+
return initializeSchema;
|
|
20
|
+
},
|
|
21
|
+
get resetSchema () {
|
|
22
|
+
return resetSchema;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const _fs = require("fs");
|
|
26
|
+
const _path = require("path");
|
|
27
|
+
function getSchemaVersion(db) {
|
|
28
|
+
const result = db.instance.pragma('user_version');
|
|
29
|
+
return result[0]?.user_version ?? 0;
|
|
30
|
+
}
|
|
31
|
+
function setSchemaVersion(db, version) {
|
|
32
|
+
db.instance.pragma(`user_version = ${version}`);
|
|
33
|
+
}
|
|
34
|
+
function getMigrationsDir() {
|
|
35
|
+
// In production, migrations are in dist/database/migrations
|
|
36
|
+
// In development/testing, they are in src/database/migrations
|
|
37
|
+
const distPath = (0, _path.join)(__dirname, 'migrations');
|
|
38
|
+
return distPath;
|
|
39
|
+
}
|
|
40
|
+
function getMigrationFiles() {
|
|
41
|
+
const migrationsDir = getMigrationsDir();
|
|
42
|
+
let files;
|
|
43
|
+
try {
|
|
44
|
+
files = (0, _fs.readdirSync)(migrationsDir).filter((f)=>f.endsWith('.sql')).sort();
|
|
45
|
+
} catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return files.map((file)=>{
|
|
49
|
+
const match = file.match(/^(\d+)_(.+)\.sql$/);
|
|
50
|
+
if (!match || !match[1] || !match[2]) {
|
|
51
|
+
throw new Error(`Invalid migration filename: ${file}. Expected format: 001_name.sql`);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
version: parseInt(match[1], 10),
|
|
55
|
+
name: match[2],
|
|
56
|
+
path: (0, _path.join)(migrationsDir, file)
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function initializeSchema(db) {
|
|
61
|
+
const currentVersion = getSchemaVersion(db);
|
|
62
|
+
const migrations = getMigrationFiles();
|
|
63
|
+
const pendingMigrations = migrations.filter((m)=>m.version > currentVersion);
|
|
64
|
+
if (pendingMigrations.length === 0) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
for (const migration of pendingMigrations){
|
|
68
|
+
const sql = (0, _fs.readFileSync)(migration.path, 'utf-8');
|
|
69
|
+
db.transaction(()=>{
|
|
70
|
+
db.instance.exec(sql);
|
|
71
|
+
setSchemaVersion(db, migration.version);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function resetSchema(db) {
|
|
76
|
+
db.transaction(()=>{
|
|
77
|
+
db.execute('DROP TABLE IF EXISTS knowledge_fts');
|
|
78
|
+
db.execute('DROP TABLE IF EXISTS knowledge');
|
|
79
|
+
setSchemaVersion(db, 0);
|
|
80
|
+
});
|
|
81
|
+
initializeSchema(db);
|
|
82
|
+
}
|
|
83
|
+
function getPendingMigrations(db) {
|
|
84
|
+
const currentVersion = getSchemaVersion(db);
|
|
85
|
+
const migrations = getMigrationFiles();
|
|
86
|
+
return migrations.filter((m)=>m.version > currentVersion).map((m)=>`${m.version}_${m.name}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/database/schema.ts"],"sourcesContent":["import { readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport type { DatabaseConnection } from './connection';\n\nexport function getSchemaVersion(db: DatabaseConnection): number {\n const result = db.instance.pragma('user_version') as { user_version: number }[];\n return result[0]?.user_version ?? 0;\n}\n\nfunction setSchemaVersion(db: DatabaseConnection, version: number): void {\n db.instance.pragma(`user_version = ${version}`);\n}\n\nfunction getMigrationsDir(): string {\n // In production, migrations are in dist/database/migrations\n // In development/testing, they are in src/database/migrations\n const distPath = join(__dirname, 'migrations');\n return distPath;\n}\n\nfunction getMigrationFiles(): { version: number; path: string; name: string }[] {\n const migrationsDir = getMigrationsDir();\n\n let files: string[];\n try {\n files = readdirSync(migrationsDir)\n .filter(f => f.endsWith('.sql'))\n .sort();\n } catch {\n return [];\n }\n\n return files.map(file => {\n const match = file.match(/^(\\d+)_(.+)\\.sql$/);\n if (!match || !match[1] || !match[2]) {\n throw new Error(`Invalid migration filename: ${file}. Expected format: 001_name.sql`);\n }\n return {\n version: parseInt(match[1], 10),\n name: match[2],\n path: join(migrationsDir, file),\n };\n });\n}\n\nexport function initializeSchema(db: DatabaseConnection): void {\n const currentVersion = getSchemaVersion(db);\n const migrations = getMigrationFiles();\n\n const pendingMigrations = migrations.filter(m => m.version > currentVersion);\n\n if (pendingMigrations.length === 0) {\n return;\n }\n\n for (const migration of pendingMigrations) {\n const sql = readFileSync(migration.path, 'utf-8');\n\n db.transaction(() => {\n db.instance.exec(sql);\n setSchemaVersion(db, migration.version);\n });\n }\n}\n\nexport function resetSchema(db: DatabaseConnection): void {\n db.transaction(() => {\n db.execute('DROP TABLE IF EXISTS knowledge_fts');\n db.execute('DROP TABLE IF EXISTS knowledge');\n setSchemaVersion(db, 0);\n });\n\n initializeSchema(db);\n}\n\nexport function getPendingMigrations(db: DatabaseConnection): string[] {\n const currentVersion = getSchemaVersion(db);\n const migrations = getMigrationFiles();\n return migrations\n .filter(m => m.version > currentVersion)\n .map(m => `${m.version}_${m.name}`);\n}\n"],"names":["getPendingMigrations","getSchemaVersion","initializeSchema","resetSchema","db","result","instance","pragma","user_version","setSchemaVersion","version","getMigrationsDir","distPath","join","__dirname","getMigrationFiles","migrationsDir","files","readdirSync","filter","f","endsWith","sort","map","file","match","Error","parseInt","name","path","currentVersion","migrations","pendingMigrations","m","length","migration","sql","readFileSync","transaction","exec","execute"],"mappings":";;;;;;;;;;;QA2EgBA;eAAAA;;QAvEAC;eAAAA;;QAyCAC;eAAAA;;QAoBAC;eAAAA;;;oBAjE0B;sBACrB;AAGd,SAASF,iBAAiBG,EAAsB;IACnD,MAAMC,SAASD,GAAGE,QAAQ,CAACC,MAAM,CAAC;IAClC,OAAOF,MAAM,CAAC,EAAE,EAAEG,gBAAgB;AACtC;AAEA,SAASC,iBAAiBL,EAAsB,EAAEM,OAAe;IAC7DN,GAAGE,QAAQ,CAACC,MAAM,CAAC,CAAC,eAAe,EAAEG,SAAS;AAClD;AAEA,SAASC;IACL,4DAA4D;IAC5D,8DAA8D;IAC9D,MAAMC,WAAWC,IAAAA,UAAI,EAACC,WAAW;IACjC,OAAOF;AACX;AAEA,SAASG;IACL,MAAMC,gBAAgBL;IAEtB,IAAIM;IACJ,IAAI;QACAA,QAAQC,IAAAA,eAAW,EAACF,eACfG,MAAM,CAACC,CAAAA,IAAKA,EAAEC,QAAQ,CAAC,SACvBC,IAAI;IACb,EAAE,OAAM;QACJ,OAAO,EAAE;IACb;IAEA,OAAOL,MAAMM,GAAG,CAACC,CAAAA;QACb,MAAMC,QAAQD,KAAKC,KAAK,CAAC;QACzB,IAAI,CAACA,SAAS,CAACA,KAAK,CAAC,EAAE,IAAI,CAACA,KAAK,CAAC,EAAE,EAAE;YAClC,MAAM,IAAIC,MAAM,CAAC,4BAA4B,EAAEF,KAAK,+BAA+B,CAAC;QACxF;QACA,OAAO;YACHd,SAASiB,SAASF,KAAK,CAAC,EAAE,EAAE;YAC5BG,MAAMH,KAAK,CAAC,EAAE;YACdI,MAAMhB,IAAAA,UAAI,EAACG,eAAeQ;QAC9B;IACJ;AACJ;AAEO,SAAStB,iBAAiBE,EAAsB;IACnD,MAAM0B,iBAAiB7B,iBAAiBG;IACxC,MAAM2B,aAAahB;IAEnB,MAAMiB,oBAAoBD,WAAWZ,MAAM,CAACc,CAAAA,IAAKA,EAAEvB,OAAO,GAAGoB;IAE7D,IAAIE,kBAAkBE,MAAM,KAAK,GAAG;QAChC;IACJ;IAEA,KAAK,MAAMC,aAAaH,kBAAmB;QACvC,MAAMI,MAAMC,IAAAA,gBAAY,EAACF,UAAUN,IAAI,EAAE;QAEzCzB,GAAGkC,WAAW,CAAC;YACXlC,GAAGE,QAAQ,CAACiC,IAAI,CAACH;YACjB3B,iBAAiBL,IAAI+B,UAAUzB,OAAO;QAC1C;IACJ;AACJ;AAEO,SAASP,YAAYC,EAAsB;IAC9CA,GAAGkC,WAAW,CAAC;QACXlC,GAAGoC,OAAO,CAAC;QACXpC,GAAGoC,OAAO,CAAC;QACX/B,iBAAiBL,IAAI;IACzB;IAEAF,iBAAiBE;AACrB;AAEO,SAASJ,qBAAqBI,EAAsB;IACvD,MAAM0B,iBAAiB7B,iBAAiBG;IACxC,MAAM2B,aAAahB;IACnB,OAAOgB,WACFZ,MAAM,CAACc,CAAAA,IAAKA,EAAEvB,OAAO,GAAGoB,gBACxBP,GAAG,CAACU,CAAAA,IAAK,GAAGA,EAAEvB,OAAO,CAAC,CAAC,EAAEuB,EAAEL,IAAI,EAAE;AAC1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/handlers/search.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAgB5E,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAwClF"}
|