@qwickapps/qwickbrain-proxy 1.0.2 → 1.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/CHANGELOG.md +17 -0
- package/dist/db/schema.d.ts +63 -6
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +17 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/lib/__tests__/cache-manager.test.js +146 -83
- package/dist/lib/__tests__/cache-manager.test.js.map +1 -1
- package/dist/lib/__tests__/connection-manager.test.js +2 -2
- package/dist/lib/__tests__/connection-manager.test.js.map +1 -1
- package/dist/lib/__tests__/proxy-server.test.js +16 -44
- package/dist/lib/__tests__/proxy-server.test.js.map +1 -1
- package/dist/lib/__tests__/qwickbrain-client.test.js +3 -1
- package/dist/lib/__tests__/qwickbrain-client.test.js.map +1 -1
- package/dist/lib/__tests__/sse-invalidation-listener.test.d.ts +2 -0
- package/dist/lib/__tests__/sse-invalidation-listener.test.d.ts.map +1 -0
- package/dist/lib/__tests__/sse-invalidation-listener.test.js +245 -0
- package/dist/lib/__tests__/sse-invalidation-listener.test.js.map +1 -0
- package/dist/lib/__tests__/write-queue-manager.test.d.ts +2 -0
- package/dist/lib/__tests__/write-queue-manager.test.d.ts.map +1 -0
- package/dist/lib/__tests__/write-queue-manager.test.js +291 -0
- package/dist/lib/__tests__/write-queue-manager.test.js.map +1 -0
- package/dist/lib/cache-manager.d.ts +35 -6
- package/dist/lib/cache-manager.d.ts.map +1 -1
- package/dist/lib/cache-manager.js +154 -41
- package/dist/lib/cache-manager.js.map +1 -1
- package/dist/lib/connection-manager.d.ts +7 -0
- package/dist/lib/connection-manager.d.ts.map +1 -1
- package/dist/lib/connection-manager.js +57 -8
- package/dist/lib/connection-manager.js.map +1 -1
- package/dist/lib/proxy-server.d.ts +12 -0
- package/dist/lib/proxy-server.d.ts.map +1 -1
- package/dist/lib/proxy-server.js +184 -87
- package/dist/lib/proxy-server.js.map +1 -1
- package/dist/lib/qwickbrain-client.d.ts +4 -0
- package/dist/lib/qwickbrain-client.d.ts.map +1 -1
- package/dist/lib/qwickbrain-client.js +152 -13
- package/dist/lib/qwickbrain-client.js.map +1 -1
- package/dist/lib/sse-invalidation-listener.d.ts +31 -0
- package/dist/lib/sse-invalidation-listener.d.ts.map +1 -0
- package/dist/lib/sse-invalidation-listener.js +151 -0
- package/dist/lib/sse-invalidation-listener.js.map +1 -0
- package/dist/lib/tools.d.ts +21 -0
- package/dist/lib/tools.d.ts.map +1 -0
- package/dist/lib/tools.js +513 -0
- package/dist/lib/tools.js.map +1 -0
- package/dist/lib/write-queue-manager.d.ts +88 -0
- package/dist/lib/write-queue-manager.d.ts.map +1 -0
- package/dist/lib/write-queue-manager.js +191 -0
- package/dist/lib/write-queue-manager.js.map +1 -0
- package/dist/types/config.d.ts +7 -42
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +1 -6
- package/dist/types/config.js.map +1 -1
- package/drizzle/0002_lru_cache_migration.sql +94 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +6 -2
- package/scripts/rebuild-sqlite.sh +26 -0
- package/src/db/schema.ts +17 -2
- package/src/lib/__tests__/cache-manager.test.ts +180 -90
- package/src/lib/__tests__/connection-manager.test.ts +2 -2
- package/src/lib/__tests__/proxy-server.test.ts +16 -51
- package/src/lib/__tests__/qwickbrain-client.test.ts +3 -1
- package/src/lib/__tests__/sse-invalidation-listener.test.ts +326 -0
- package/src/lib/__tests__/write-queue-manager.test.ts +383 -0
- package/src/lib/cache-manager.ts +198 -46
- package/src/lib/connection-manager.ts +67 -8
- package/src/lib/proxy-server.ts +231 -90
- package/src/lib/qwickbrain-client.ts +166 -12
- package/src/lib/sse-invalidation-listener.ts +185 -0
- package/src/lib/tools.ts +525 -0
- package/src/lib/write-queue-manager.ts +271 -0
- package/src/types/config.ts +1 -6
- package/.github/workflows/publish.yml +0 -92
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { eq } from 'drizzle-orm';
|
|
2
|
+
import { syncQueue } from '../db/schema.js';
|
|
3
|
+
export class WriteQueueManager {
|
|
4
|
+
db;
|
|
5
|
+
qwickbrainClient;
|
|
6
|
+
maxAttempts = 3;
|
|
7
|
+
isSyncing = false;
|
|
8
|
+
constructor(db, qwickbrainClient) {
|
|
9
|
+
this.db = db;
|
|
10
|
+
this.qwickbrainClient = qwickbrainClient;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Queue a write operation for later sync
|
|
14
|
+
*/
|
|
15
|
+
async queueOperation(operation, payload) {
|
|
16
|
+
await this.db.insert(syncQueue).values({
|
|
17
|
+
operation,
|
|
18
|
+
payload: JSON.stringify(payload),
|
|
19
|
+
status: 'pending',
|
|
20
|
+
attempts: 0,
|
|
21
|
+
});
|
|
22
|
+
console.error(`Queued operation: ${operation}`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get count of pending operations
|
|
26
|
+
*/
|
|
27
|
+
async getPendingCount() {
|
|
28
|
+
const result = await this.db
|
|
29
|
+
.select()
|
|
30
|
+
.from(syncQueue)
|
|
31
|
+
.where(eq(syncQueue.status, 'pending'));
|
|
32
|
+
return result.length;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sync all pending operations
|
|
36
|
+
* Returns number of operations synced successfully
|
|
37
|
+
*/
|
|
38
|
+
async syncPendingOperations() {
|
|
39
|
+
if (this.isSyncing) {
|
|
40
|
+
console.error('Sync already in progress, skipping');
|
|
41
|
+
return { synced: 0, failed: 0 };
|
|
42
|
+
}
|
|
43
|
+
this.isSyncing = true;
|
|
44
|
+
let synced = 0;
|
|
45
|
+
let failed = 0;
|
|
46
|
+
try {
|
|
47
|
+
// Get all pending operations, ordered by creation time (FIFO)
|
|
48
|
+
const pending = await this.db
|
|
49
|
+
.select()
|
|
50
|
+
.from(syncQueue)
|
|
51
|
+
.where(eq(syncQueue.status, 'pending'))
|
|
52
|
+
.orderBy(syncQueue.createdAt);
|
|
53
|
+
console.error(`Syncing ${pending.length} pending operations...`);
|
|
54
|
+
for (const item of pending) {
|
|
55
|
+
try {
|
|
56
|
+
await this.executeOperation(item);
|
|
57
|
+
// Mark as completed
|
|
58
|
+
await this.db
|
|
59
|
+
.update(syncQueue)
|
|
60
|
+
.set({ status: 'completed' })
|
|
61
|
+
.where(eq(syncQueue.id, item.id));
|
|
62
|
+
synced++;
|
|
63
|
+
console.error(`Synced operation ${item.id}: ${item.operation}`);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
67
|
+
const newAttempts = item.attempts + 1;
|
|
68
|
+
if (newAttempts >= this.maxAttempts) {
|
|
69
|
+
// Max attempts reached, mark as failed
|
|
70
|
+
await this.db
|
|
71
|
+
.update(syncQueue)
|
|
72
|
+
.set({
|
|
73
|
+
status: 'failed',
|
|
74
|
+
error: errorMessage,
|
|
75
|
+
attempts: newAttempts,
|
|
76
|
+
lastAttemptAt: new Date(),
|
|
77
|
+
})
|
|
78
|
+
.where(eq(syncQueue.id, item.id));
|
|
79
|
+
failed++;
|
|
80
|
+
console.error(`Operation ${item.id} failed after ${newAttempts} attempts: ${errorMessage}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Increment attempts, keep as pending
|
|
84
|
+
await this.db
|
|
85
|
+
.update(syncQueue)
|
|
86
|
+
.set({
|
|
87
|
+
attempts: newAttempts,
|
|
88
|
+
lastAttemptAt: new Date(),
|
|
89
|
+
error: errorMessage,
|
|
90
|
+
})
|
|
91
|
+
.where(eq(syncQueue.id, item.id));
|
|
92
|
+
console.error(`Operation ${item.id} failed (attempt ${newAttempts}/${this.maxAttempts}): ${errorMessage}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Clean up completed operations (keep failed ones for inspection)
|
|
97
|
+
await this.cleanupCompleted();
|
|
98
|
+
console.error(`Sync complete: ${synced} synced, ${failed} failed`);
|
|
99
|
+
return { synced, failed };
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
this.isSyncing = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Execute a single queued operation
|
|
107
|
+
*/
|
|
108
|
+
async executeOperation(item) {
|
|
109
|
+
const payload = JSON.parse(item.payload);
|
|
110
|
+
switch (item.operation) {
|
|
111
|
+
case 'create_document':
|
|
112
|
+
case 'update_document': {
|
|
113
|
+
const p = payload;
|
|
114
|
+
await this.qwickbrainClient.createDocument(p.docType, p.name, p.content, p.project, p.metadata);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
case 'set_memory':
|
|
118
|
+
case 'update_memory': {
|
|
119
|
+
const p = payload;
|
|
120
|
+
await this.qwickbrainClient.setMemory(p.name, p.content, p.project, p.metadata);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
case 'delete_document': {
|
|
124
|
+
const p = payload;
|
|
125
|
+
await this.qwickbrainClient.deleteDocument(p.docType, p.name, p.project);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case 'delete_memory': {
|
|
129
|
+
const p = payload;
|
|
130
|
+
await this.qwickbrainClient.deleteMemory(p.name, p.project);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`Unknown operation: ${item.operation}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clean up completed operations
|
|
139
|
+
*/
|
|
140
|
+
async cleanupCompleted() {
|
|
141
|
+
await this.db.delete(syncQueue).where(eq(syncQueue.status, 'completed'));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get failed operations for inspection
|
|
145
|
+
*/
|
|
146
|
+
async getFailedOperations() {
|
|
147
|
+
return await this.db
|
|
148
|
+
.select()
|
|
149
|
+
.from(syncQueue)
|
|
150
|
+
.where(eq(syncQueue.status, 'failed'))
|
|
151
|
+
.orderBy(syncQueue.createdAt);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Retry a specific failed operation
|
|
155
|
+
*/
|
|
156
|
+
async retryOperation(id) {
|
|
157
|
+
await this.db
|
|
158
|
+
.update(syncQueue)
|
|
159
|
+
.set({
|
|
160
|
+
status: 'pending',
|
|
161
|
+
attempts: 0,
|
|
162
|
+
error: null,
|
|
163
|
+
lastAttemptAt: null,
|
|
164
|
+
})
|
|
165
|
+
.where(eq(syncQueue.id, id));
|
|
166
|
+
console.error(`Operation ${id} reset to pending for retry`);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Clear all failed operations
|
|
170
|
+
*/
|
|
171
|
+
async clearFailed() {
|
|
172
|
+
const failed = await this.getFailedOperations();
|
|
173
|
+
await this.db.delete(syncQueue).where(eq(syncQueue.status, 'failed'));
|
|
174
|
+
console.error(`Cleared ${failed.length} failed operations`);
|
|
175
|
+
return failed.length;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get queue statistics
|
|
179
|
+
*/
|
|
180
|
+
async getQueueStats() {
|
|
181
|
+
const all = await this.db.select().from(syncQueue);
|
|
182
|
+
const pending = all.filter(item => item.status === 'pending').length;
|
|
183
|
+
const failed = all.filter(item => item.status === 'failed').length;
|
|
184
|
+
return {
|
|
185
|
+
pending,
|
|
186
|
+
failed,
|
|
187
|
+
total: all.length,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=write-queue-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-queue-manager.js","sourceRoot":"","sources":["../../src/lib/write-queue-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -21,40 +21,15 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
21
21
|
}>>;
|
|
22
22
|
cache: z.ZodDefault<z.ZodObject<{
|
|
23
23
|
dir: z.ZodOptional<z.ZodString>;
|
|
24
|
-
|
|
25
|
-
workflows: z.ZodDefault<z.ZodNumber>;
|
|
26
|
-
rules: z.ZodDefault<z.ZodNumber>;
|
|
27
|
-
documents: z.ZodDefault<z.ZodNumber>;
|
|
28
|
-
memories: z.ZodDefault<z.ZodNumber>;
|
|
29
|
-
}, "strip", z.ZodTypeAny, {
|
|
30
|
-
workflows: number;
|
|
31
|
-
rules: number;
|
|
32
|
-
documents: number;
|
|
33
|
-
memories: number;
|
|
34
|
-
}, {
|
|
35
|
-
workflows?: number | undefined;
|
|
36
|
-
rules?: number | undefined;
|
|
37
|
-
documents?: number | undefined;
|
|
38
|
-
memories?: number | undefined;
|
|
39
|
-
}>>;
|
|
24
|
+
maxCacheSizeBytes: z.ZodDefault<z.ZodNumber>;
|
|
40
25
|
preload: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
41
26
|
}, "strip", z.ZodTypeAny, {
|
|
42
|
-
|
|
43
|
-
workflows: number;
|
|
44
|
-
rules: number;
|
|
45
|
-
documents: number;
|
|
46
|
-
memories: number;
|
|
47
|
-
};
|
|
27
|
+
maxCacheSizeBytes: number;
|
|
48
28
|
preload: string[];
|
|
49
29
|
dir?: string | undefined;
|
|
50
30
|
}, {
|
|
51
31
|
dir?: string | undefined;
|
|
52
|
-
|
|
53
|
-
workflows?: number | undefined;
|
|
54
|
-
rules?: number | undefined;
|
|
55
|
-
documents?: number | undefined;
|
|
56
|
-
memories?: number | undefined;
|
|
57
|
-
} | undefined;
|
|
32
|
+
maxCacheSizeBytes?: number | undefined;
|
|
58
33
|
preload?: string[] | undefined;
|
|
59
34
|
}>>;
|
|
60
35
|
connection: z.ZodDefault<z.ZodObject<{
|
|
@@ -105,12 +80,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
105
80
|
}>>;
|
|
106
81
|
}, "strip", z.ZodTypeAny, {
|
|
107
82
|
cache: {
|
|
108
|
-
|
|
109
|
-
workflows: number;
|
|
110
|
-
rules: number;
|
|
111
|
-
documents: number;
|
|
112
|
-
memories: number;
|
|
113
|
-
};
|
|
83
|
+
maxCacheSizeBytes: number;
|
|
114
84
|
preload: string[];
|
|
115
85
|
dir?: string | undefined;
|
|
116
86
|
};
|
|
@@ -138,12 +108,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
138
108
|
}, {
|
|
139
109
|
cache?: {
|
|
140
110
|
dir?: string | undefined;
|
|
141
|
-
|
|
142
|
-
workflows?: number | undefined;
|
|
143
|
-
rules?: number | undefined;
|
|
144
|
-
documents?: number | undefined;
|
|
145
|
-
memories?: number | undefined;
|
|
146
|
-
} | undefined;
|
|
111
|
+
maxCacheSizeBytes?: number | undefined;
|
|
147
112
|
preload?: string[] | undefined;
|
|
148
113
|
} | undefined;
|
|
149
114
|
qwickbrain?: {
|
|
@@ -175,12 +140,12 @@ export declare const CacheConfigSchema: z.ZodObject<{
|
|
|
175
140
|
preload: z.ZodBoolean;
|
|
176
141
|
}, "strip", z.ZodTypeAny, {
|
|
177
142
|
offline: boolean;
|
|
178
|
-
ttl: number;
|
|
179
143
|
preload: boolean;
|
|
144
|
+
ttl: number;
|
|
180
145
|
}, {
|
|
181
146
|
offline: boolean;
|
|
182
|
-
ttl: number;
|
|
183
147
|
preload: boolean;
|
|
148
|
+
ttl: number;
|
|
184
149
|
}>;
|
|
185
150
|
export type CacheConfig = z.infer<typeof CacheConfigSchema>;
|
|
186
151
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;EAI5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
package/dist/types/config.js
CHANGED
|
@@ -11,12 +11,7 @@ export const ConfigSchema = z.object({
|
|
|
11
11
|
}).default({}),
|
|
12
12
|
cache: z.object({
|
|
13
13
|
dir: z.string().optional(),
|
|
14
|
-
|
|
15
|
-
workflows: z.number().default(86400), // 24 hours
|
|
16
|
-
rules: z.number().default(86400), // 24 hours
|
|
17
|
-
documents: z.number().default(21600), // 6 hours
|
|
18
|
-
memories: z.number().default(3600), // 1 hour
|
|
19
|
-
}).default({}),
|
|
14
|
+
maxCacheSizeBytes: z.number().default(100 * 1024 * 1024), // 100MB default for dynamic tier
|
|
20
15
|
preload: z.array(z.string()).default(['workflows', 'rules']),
|
|
21
16
|
}).default({}),
|
|
22
17
|
connection: z.object({
|
package/dist/types/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACnD,6BAA6B;QAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC9B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACpC,2CAA2C;QAC3C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC9B,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC1B,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACnD,6BAA6B;QAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC9B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACpC,2CAA2C;QAC3C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC9B,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC1B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,EAAE,iCAAiC;QAC3F,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;KAC7D,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACd,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,aAAa;QAC7D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,YAAY;QAC/C,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC;YACzB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW;YAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,aAAa;YAC7C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;SAClC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;KACf,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY;QAClD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KAClC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACf,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;CACrB,CAAC,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
-- Migration: Remove TTL, add LRU fields (two-tier storage)
|
|
2
|
+
-- Phase 2: LRU Cache Implementation
|
|
3
|
+
|
|
4
|
+
-- Create new documents table with LRU fields
|
|
5
|
+
CREATE TABLE `documents_new` (
|
|
6
|
+
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
7
|
+
`doc_type` text NOT NULL,
|
|
8
|
+
`name` text NOT NULL,
|
|
9
|
+
`project` text,
|
|
10
|
+
`content` text NOT NULL,
|
|
11
|
+
`metadata` text,
|
|
12
|
+
`cached_at` integer DEFAULT (unixepoch()) NOT NULL,
|
|
13
|
+
`last_accessed_at` integer DEFAULT (unixepoch()) NOT NULL,
|
|
14
|
+
`is_critical` integer DEFAULT false NOT NULL,
|
|
15
|
+
`size_bytes` integer DEFAULT 0 NOT NULL,
|
|
16
|
+
`synced` integer DEFAULT true NOT NULL
|
|
17
|
+
);
|
|
18
|
+
--> statement-breakpoint
|
|
19
|
+
|
|
20
|
+
-- Copy data from old table, calculating size and critical flag
|
|
21
|
+
INSERT INTO `documents_new` (
|
|
22
|
+
id, doc_type, name, project, content, metadata, cached_at, last_accessed_at, is_critical, size_bytes, synced
|
|
23
|
+
)
|
|
24
|
+
SELECT
|
|
25
|
+
id,
|
|
26
|
+
doc_type,
|
|
27
|
+
name,
|
|
28
|
+
project,
|
|
29
|
+
content,
|
|
30
|
+
metadata,
|
|
31
|
+
cached_at,
|
|
32
|
+
cached_at as last_accessed_at, -- Initialize with cached_at
|
|
33
|
+
CASE
|
|
34
|
+
WHEN doc_type IN ('workflow', 'rule', 'agent', 'template') THEN true
|
|
35
|
+
ELSE false
|
|
36
|
+
END as is_critical,
|
|
37
|
+
length(content) as size_bytes, -- Calculate size in bytes
|
|
38
|
+
synced
|
|
39
|
+
FROM `documents`;
|
|
40
|
+
--> statement-breakpoint
|
|
41
|
+
|
|
42
|
+
-- Drop old table
|
|
43
|
+
DROP TABLE `documents`;
|
|
44
|
+
--> statement-breakpoint
|
|
45
|
+
|
|
46
|
+
-- Rename new table
|
|
47
|
+
ALTER TABLE `documents_new` RENAME TO `documents`;
|
|
48
|
+
--> statement-breakpoint
|
|
49
|
+
|
|
50
|
+
-- Recreate unique index
|
|
51
|
+
CREATE UNIQUE INDEX `documents_doc_type_name_project_unique` ON `documents` (`doc_type`,`name`,`project`);
|
|
52
|
+
--> statement-breakpoint
|
|
53
|
+
|
|
54
|
+
-- Create new memories table with LRU fields
|
|
55
|
+
CREATE TABLE `memories_new` (
|
|
56
|
+
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
57
|
+
`name` text NOT NULL,
|
|
58
|
+
`project` text,
|
|
59
|
+
`content` text NOT NULL,
|
|
60
|
+
`metadata` text,
|
|
61
|
+
`cached_at` integer DEFAULT (unixepoch()) NOT NULL,
|
|
62
|
+
`last_accessed_at` integer DEFAULT (unixepoch()) NOT NULL,
|
|
63
|
+
`size_bytes` integer DEFAULT 0 NOT NULL,
|
|
64
|
+
`synced` integer DEFAULT true NOT NULL
|
|
65
|
+
);
|
|
66
|
+
--> statement-breakpoint
|
|
67
|
+
|
|
68
|
+
-- Copy data from old table, calculating size
|
|
69
|
+
INSERT INTO `memories_new` (
|
|
70
|
+
id, name, project, content, metadata, cached_at, last_accessed_at, size_bytes, synced
|
|
71
|
+
)
|
|
72
|
+
SELECT
|
|
73
|
+
id,
|
|
74
|
+
name,
|
|
75
|
+
project,
|
|
76
|
+
content,
|
|
77
|
+
metadata,
|
|
78
|
+
cached_at,
|
|
79
|
+
cached_at as last_accessed_at, -- Initialize with cached_at
|
|
80
|
+
length(content) as size_bytes, -- Calculate size in bytes
|
|
81
|
+
synced
|
|
82
|
+
FROM `memories`;
|
|
83
|
+
--> statement-breakpoint
|
|
84
|
+
|
|
85
|
+
-- Drop old table
|
|
86
|
+
DROP TABLE `memories`;
|
|
87
|
+
--> statement-breakpoint
|
|
88
|
+
|
|
89
|
+
-- Rename new table
|
|
90
|
+
ALTER TABLE `memories_new` RENAME TO `memories`;
|
|
91
|
+
--> statement-breakpoint
|
|
92
|
+
|
|
93
|
+
-- Recreate unique index
|
|
94
|
+
CREATE UNIQUE INDEX `memories_name_project_unique` ON `memories` (`name`,`project`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwickapps/qwickbrain-proxy",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Local MCP proxy for QwickBrain with caching and resilience",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
"typecheck": "tsc --noEmit",
|
|
19
19
|
"db:generate": "drizzle-kit generate",
|
|
20
20
|
"db:migrate": "drizzle-kit migrate",
|
|
21
|
-
"db:studio": "drizzle-kit studio"
|
|
21
|
+
"db:studio": "drizzle-kit studio",
|
|
22
|
+
"rebuild-sqlite": "bash scripts/rebuild-sqlite.sh",
|
|
23
|
+
"postinstall": "bash scripts/rebuild-sqlite.sh || true"
|
|
22
24
|
},
|
|
23
25
|
"keywords": [
|
|
24
26
|
"mcp",
|
|
@@ -52,11 +54,13 @@
|
|
|
52
54
|
},
|
|
53
55
|
"devDependencies": {
|
|
54
56
|
"@types/better-sqlite3": "^7.6.0",
|
|
57
|
+
"@types/eventsource": "^3.0.0",
|
|
55
58
|
"@types/node": "^20.0.0",
|
|
56
59
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
57
60
|
"@typescript-eslint/parser": "^7.0.0",
|
|
58
61
|
"drizzle-kit": "^0.31.8",
|
|
59
62
|
"eslint": "^8.57.0",
|
|
63
|
+
"eventsource": "^4.0.0",
|
|
60
64
|
"prettier": "^3.0.0",
|
|
61
65
|
"tsx": "^4.0.0",
|
|
62
66
|
"typescript": "^5.3.0",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
echo "Rebuilding better-sqlite3 native bindings..."
|
|
5
|
+
|
|
6
|
+
# Ensure Python has setuptools (needed for node-gyp with Python 3.13+)
|
|
7
|
+
python3 -m pip install --quiet setuptools --break-system-packages 2>/dev/null || true
|
|
8
|
+
|
|
9
|
+
# Navigate to monorepo root and rebuild better-sqlite3
|
|
10
|
+
cd "$(dirname "$0")/../../.."
|
|
11
|
+
|
|
12
|
+
# Rebuild better-sqlite3 for the entire monorepo
|
|
13
|
+
pnpm exec node-gyp rebuild --directory node_modules/.pnpm/better-sqlite3@*/node_modules/better-sqlite3 --release 2>/dev/null || {
|
|
14
|
+
# Fallback: find and rebuild better-sqlite3 directly
|
|
15
|
+
SQLITE_DIR=$(find node_modules/.pnpm -type d -path "*/better-sqlite3@*/node_modules/better-sqlite3" -print -quit)
|
|
16
|
+
if [ -n "$SQLITE_DIR" ]; then
|
|
17
|
+
echo "Building in: $SQLITE_DIR"
|
|
18
|
+
cd "$SQLITE_DIR"
|
|
19
|
+
npm run build-release
|
|
20
|
+
else
|
|
21
|
+
echo "Warning: Could not find better-sqlite3 to rebuild"
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
echo "✓ better-sqlite3 rebuilt successfully"
|
package/src/db/schema.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { integer, sqliteTable, text, unique } from 'drizzle-orm/sqlite-core';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Cached documents (workflows, rules, FRDs, designs, etc.)
|
|
6
|
+
*
|
|
7
|
+
* Two-tier storage:
|
|
8
|
+
* - Critical tier (isCritical=true): workflows, rules, agents, templates - never evicted, not counted toward limit
|
|
9
|
+
* - Dynamic tier (isCritical=false): other documents - LRU eviction when storage limit reached
|
|
6
10
|
*/
|
|
7
11
|
export const documents = sqliteTable('documents', {
|
|
8
12
|
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
@@ -14,7 +18,13 @@ export const documents = sqliteTable('documents', {
|
|
|
14
18
|
cachedAt: integer('cached_at', { mode: 'timestamp' })
|
|
15
19
|
.notNull()
|
|
16
20
|
.default(sql`(unixepoch())`),
|
|
17
|
-
|
|
21
|
+
lastAccessedAt: integer('last_accessed_at', { mode: 'timestamp' })
|
|
22
|
+
.notNull()
|
|
23
|
+
.default(sql`(unixepoch())`),
|
|
24
|
+
isCritical: integer('is_critical', { mode: 'boolean' })
|
|
25
|
+
.notNull()
|
|
26
|
+
.default(false),
|
|
27
|
+
sizeBytes: integer('size_bytes').notNull().default(0),
|
|
18
28
|
synced: integer('synced', { mode: 'boolean' }).notNull().default(true),
|
|
19
29
|
}, (table) => ({
|
|
20
30
|
uniqueDocument: unique().on(table.docType, table.name, table.project),
|
|
@@ -22,6 +32,8 @@ export const documents = sqliteTable('documents', {
|
|
|
22
32
|
|
|
23
33
|
/**
|
|
24
34
|
* Cached memories (project context, patterns, decisions)
|
|
35
|
+
*
|
|
36
|
+
* Memories are always dynamic tier - LRU eviction applies
|
|
25
37
|
*/
|
|
26
38
|
export const memories = sqliteTable('memories', {
|
|
27
39
|
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
@@ -32,7 +44,10 @@ export const memories = sqliteTable('memories', {
|
|
|
32
44
|
cachedAt: integer('cached_at', { mode: 'timestamp' })
|
|
33
45
|
.notNull()
|
|
34
46
|
.default(sql`(unixepoch())`),
|
|
35
|
-
|
|
47
|
+
lastAccessedAt: integer('last_accessed_at', { mode: 'timestamp' })
|
|
48
|
+
.notNull()
|
|
49
|
+
.default(sql`(unixepoch())`),
|
|
50
|
+
sizeBytes: integer('size_bytes').notNull().default(0),
|
|
36
51
|
synced: integer('synced', { mode: 'boolean' }).notNull().default(true),
|
|
37
52
|
}, (table) => ({
|
|
38
53
|
uniqueMemory: unique().on(table.name, table.project),
|