@qwickapps/qwickbrain-proxy 1.0.3 → 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/dist/lib/__tests__/connection-manager.test.js +2 -2
- package/dist/lib/__tests__/connection-manager.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/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 +7 -0
- package/dist/lib/proxy-server.d.ts.map +1 -1
- package/dist/lib/proxy-server.js +41 -10
- package/dist/lib/proxy-server.js.map +1 -1
- package/dist/lib/qwickbrain-client.d.ts.map +1 -1
- package/dist/lib/qwickbrain-client.js +26 -16
- package/dist/lib/qwickbrain-client.js.map +1 -1
- package/dist/lib/sse-invalidation-listener.d.ts +5 -1
- package/dist/lib/sse-invalidation-listener.d.ts.map +1 -1
- package/dist/lib/sse-invalidation-listener.js +24 -18
- package/dist/lib/sse-invalidation-listener.js.map +1 -1
- package/dist/lib/tools.d.ts.map +1 -1
- package/dist/lib/tools.js +29 -4
- package/dist/lib/tools.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/__tests__/connection-manager.test.ts +2 -2
- package/src/lib/__tests__/qwickbrain-client.test.ts +3 -1
- package/src/lib/connection-manager.ts +67 -8
- package/src/lib/proxy-server.ts +49 -12
- package/src/lib/qwickbrain-client.ts +29 -15
- package/src/lib/sse-invalidation-listener.ts +32 -18
- package/src/lib/tools.ts +29 -4
- package/.claude/engineering/bugs/BUG-qwickbrain-proxy-cache-and-design.md +0 -840
- package/.github/workflows/publish.yml +0 -105
|
@@ -5,14 +5,18 @@ export declare class SSEInvalidationListener {
|
|
|
5
5
|
private apiKey?;
|
|
6
6
|
private eventSource;
|
|
7
7
|
private reconnectTimeout;
|
|
8
|
-
private reconnectDelay;
|
|
9
8
|
private isActive;
|
|
9
|
+
private reconnectAttempts;
|
|
10
|
+
private readonly initialDelay;
|
|
11
|
+
private readonly maxDelay;
|
|
12
|
+
private readonly multiplier;
|
|
10
13
|
constructor(url: string, cacheManager: CacheManager, apiKey?: string | undefined);
|
|
11
14
|
/**
|
|
12
15
|
* Start listening for SSE invalidation events
|
|
13
16
|
*/
|
|
14
17
|
start(): Promise<void>;
|
|
15
18
|
private connect;
|
|
19
|
+
private scheduleReconnect;
|
|
16
20
|
private handleInvalidationEvent;
|
|
17
21
|
private handleBatchInvalidation;
|
|
18
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse-invalidation-listener.d.ts","sourceRoot":"","sources":["../../src/lib/sse-invalidation-listener.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASvD,qBAAa,uBAAuB;
|
|
1
|
+
{"version":3,"file":"sse-invalidation-listener.d.ts","sourceRoot":"","sources":["../../src/lib/sse-invalidation-listener.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASvD,qBAAa,uBAAuB;IAYhC,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,MAAM,CAAC;IAbjB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,iBAAiB,CAAK;IAG9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;gBAGtB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,YAAY,EAC1B,MAAM,CAAC,EAAE,MAAM,YAAA;IAGzB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B,OAAO,CAAC,OAAO;IA0Df,OAAO,CAAC,iBAAiB;YAmBX,uBAAuB;YAoBvB,uBAAuB;IAqBrC;;OAEG;IACH,IAAI,IAAI,IAAI;IAiBZ;;OAEG;IACH,WAAW,IAAI,OAAO;CAGvB"}
|
|
@@ -5,8 +5,12 @@ export class SSEInvalidationListener {
|
|
|
5
5
|
apiKey;
|
|
6
6
|
eventSource = null;
|
|
7
7
|
reconnectTimeout = null;
|
|
8
|
-
reconnectDelay = 5000; // 5 seconds
|
|
9
8
|
isActive = false;
|
|
9
|
+
reconnectAttempts = 0;
|
|
10
|
+
// Exponential backoff config
|
|
11
|
+
initialDelay = 5000; // 5 seconds
|
|
12
|
+
maxDelay = 300000; // 5 minutes
|
|
13
|
+
multiplier = 2;
|
|
10
14
|
constructor(url, cacheManager, apiKey) {
|
|
11
15
|
this.url = url;
|
|
12
16
|
this.cacheManager = cacheManager;
|
|
@@ -20,6 +24,7 @@ export class SSEInvalidationListener {
|
|
|
20
24
|
return;
|
|
21
25
|
}
|
|
22
26
|
this.isActive = true;
|
|
27
|
+
this.reconnectAttempts = 0;
|
|
23
28
|
this.connect();
|
|
24
29
|
}
|
|
25
30
|
connect() {
|
|
@@ -39,24 +44,18 @@ export class SSEInvalidationListener {
|
|
|
39
44
|
this.eventSource = new EventSource(sseUrl.toString(), eventSourceInitDict);
|
|
40
45
|
this.eventSource.onopen = () => {
|
|
41
46
|
console.error('SSE invalidation listener connected');
|
|
42
|
-
|
|
47
|
+
this.reconnectAttempts = 0; // Reset on successful connection
|
|
43
48
|
if (this.reconnectTimeout) {
|
|
44
49
|
clearTimeout(this.reconnectTimeout);
|
|
45
50
|
this.reconnectTimeout = null;
|
|
46
51
|
}
|
|
47
52
|
};
|
|
48
53
|
this.eventSource.onerror = (error) => {
|
|
49
|
-
console.error('SSE invalidation listener error:', error);
|
|
54
|
+
console.error('SSE invalidation listener error:', error?.message || 'connection failed');
|
|
50
55
|
this.eventSource?.close();
|
|
51
56
|
this.eventSource = null;
|
|
52
|
-
// Schedule reconnection
|
|
53
|
-
|
|
54
|
-
console.error(`SSE reconnecting in ${this.reconnectDelay}ms...`);
|
|
55
|
-
this.reconnectTimeout = setTimeout(() => {
|
|
56
|
-
this.reconnectTimeout = null;
|
|
57
|
-
this.connect();
|
|
58
|
-
}, this.reconnectDelay);
|
|
59
|
-
}
|
|
57
|
+
// Schedule reconnection with exponential backoff
|
|
58
|
+
this.scheduleReconnect();
|
|
60
59
|
};
|
|
61
60
|
// Listen for document invalidation events
|
|
62
61
|
this.eventSource.addEventListener('document:invalidate', (event) => {
|
|
@@ -73,15 +72,21 @@ export class SSEInvalidationListener {
|
|
|
73
72
|
}
|
|
74
73
|
catch (error) {
|
|
75
74
|
console.error('Failed to connect SSE invalidation listener:', error);
|
|
76
|
-
|
|
77
|
-
if (this.isActive && !this.reconnectTimeout) {
|
|
78
|
-
this.reconnectTimeout = setTimeout(() => {
|
|
79
|
-
this.reconnectTimeout = null;
|
|
80
|
-
this.connect();
|
|
81
|
-
}, this.reconnectDelay);
|
|
82
|
-
}
|
|
75
|
+
this.scheduleReconnect();
|
|
83
76
|
}
|
|
84
77
|
}
|
|
78
|
+
scheduleReconnect() {
|
|
79
|
+
if (!this.isActive || this.reconnectTimeout) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const delay = Math.min(this.initialDelay * Math.pow(this.multiplier, this.reconnectAttempts), this.maxDelay);
|
|
83
|
+
this.reconnectAttempts++;
|
|
84
|
+
console.error(`SSE reconnecting in ${Math.round(delay / 1000)}s (attempt ${this.reconnectAttempts})...`);
|
|
85
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
86
|
+
this.reconnectTimeout = null;
|
|
87
|
+
this.connect();
|
|
88
|
+
}, delay);
|
|
89
|
+
}
|
|
85
90
|
async handleInvalidationEvent(data) {
|
|
86
91
|
try {
|
|
87
92
|
const event = JSON.parse(data);
|
|
@@ -125,6 +130,7 @@ export class SSEInvalidationListener {
|
|
|
125
130
|
*/
|
|
126
131
|
stop() {
|
|
127
132
|
this.isActive = false;
|
|
133
|
+
this.reconnectAttempts = 0;
|
|
128
134
|
if (this.reconnectTimeout) {
|
|
129
135
|
clearTimeout(this.reconnectTimeout);
|
|
130
136
|
this.reconnectTimeout = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse-invalidation-listener.js","sourceRoot":"","sources":["../../src/lib/sse-invalidation-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAU1C,MAAM,OAAO,uBAAuB;
|
|
1
|
+
{"version":3,"file":"sse-invalidation-listener.js","sourceRoot":"","sources":["../../src/lib/sse-invalidation-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAU1C,MAAM,OAAO,uBAAuB;IAYxB;IACA;IACA;IAbF,WAAW,GAAuB,IAAI,CAAC;IACvC,gBAAgB,GAA0B,IAAI,CAAC;IAC/C,QAAQ,GAAG,KAAK,CAAC;IACjB,iBAAiB,GAAG,CAAC,CAAC;IAE9B,6BAA6B;IACZ,YAAY,GAAG,IAAI,CAAC,CAAC,YAAY;IACjC,QAAQ,GAAG,MAAM,CAAC,CAAC,YAAY;IAC/B,UAAU,GAAG,CAAC,CAAC;IAEhC,YACU,GAAW,EACX,YAA0B,EAC1B,MAAe;QAFf,QAAG,GAAH,GAAG,CAAQ;QACX,iBAAY,GAAZ,YAAY,CAAc;QAC1B,WAAM,GAAN,MAAM,CAAS;IACtB,CAAC;IAEJ;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,yBAAyB;YACzB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAE5D,mDAAmD;YACnD,MAAM,mBAAmB,GAAQ;gBAC/B,OAAO,EAAE,EAAE;aACZ,CAAC;YAEF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,mBAAmB,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;YACzE,CAAC;YAED,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,mBAAmB,CAAC,CAAC;YAE3E,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE;gBAC7B,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;gBACrD,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,iCAAiC;gBAC7D,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBAC1B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;oBACpC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC/B,CAAC;YACH,CAAC,CAAC;YAEF,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG,CAAC,KAAU,EAAE,EAAE;gBACxC,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,EAAE,OAAO,IAAI,mBAAmB,CAAC,CAAC;gBACzF,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;gBAExB,iDAAiD;gBACjD,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,CAAC,CAAC;YAEF,0CAA0C;YAC1C,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,qBAAqB,EAAE,CAAC,KAAmB,EAAE,EAAE;gBAC/E,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;YAEH,wCAAwC;YACxC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,CAAC,KAAmB,EAAE,EAAE;gBAC7E,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;YAEH,wDAAwD;YACxD,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,wBAAwB,EAAE,CAAC,KAAmB,EAAE,EAAE;gBAClF,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;YACrE,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,EACrE,IAAI,CAAC,QAAQ,CACd,CAAC;QAEF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,cAAc,IAAI,CAAC,iBAAiB,MAAM,CAAC,CAAC;QAEzG,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,IAAY;QAChD,IAAI,CAAC;YACH,MAAM,KAAK,GAAsB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAElD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnB,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;oBACtE,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBACrF,OAAO,CAAC,KAAK,CAAC,8BAA8B,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7E,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnC,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBACpE,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,IAAY;QAChD,IAAI,CAAC;YACH,MAAM,MAAM,GAAwB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAErD,oCAAoC;YACpC,MAAM,OAAO,CAAC,GAAG,CACf,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACzB,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBAC/C,MAAM,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBACvF,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACnC,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC,CAAC,CACH,CAAC;YAEF,OAAO,CAAC,KAAK,CAAC,6BAA6B,MAAM,CAAC,MAAM,QAAQ,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAE3B,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,KAAK,WAAW,CAAC,IAAI,CAAC;IACxG,CAAC;CACF"}
|
package/dist/lib/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA+e5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,aAI1B,CAAC;AAEH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D"}
|
package/dist/lib/tools.js
CHANGED
|
@@ -90,13 +90,13 @@ export const QWICKBRAIN_TOOLS = [
|
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
name: 'search_codebase',
|
|
93
|
-
description: '
|
|
93
|
+
description: 'Search for specific code entities (functions, classes, methods) in the indexed codebase. Returns a list of matching code entities with their locations, signatures, and relevance scores. Use this when you need to FIND specific code elements or get a list of relevant code locations. Uses hybrid search (BM25 keyword matching + semantic embeddings) for accurate results. Output: Structured list of code entities with file paths, line numbers, signatures, and scores.',
|
|
94
94
|
inputSchema: {
|
|
95
95
|
type: 'object',
|
|
96
96
|
properties: {
|
|
97
97
|
query: {
|
|
98
98
|
type: 'string',
|
|
99
|
-
description: '
|
|
99
|
+
description: 'Search query describing what code to find. Examples: "function to parse JSON", "class that handles authentication", "async method for file upload", "error handling utilities"',
|
|
100
100
|
},
|
|
101
101
|
limit: {
|
|
102
102
|
type: 'integer',
|
|
@@ -105,8 +105,33 @@ export const QWICKBRAIN_TOOLS = [
|
|
|
105
105
|
},
|
|
106
106
|
min_score: {
|
|
107
107
|
type: 'number',
|
|
108
|
-
description: 'Minimum
|
|
109
|
-
default: 0.
|
|
108
|
+
description: 'Minimum relevance score threshold (default: 0.3)',
|
|
109
|
+
default: 0.3,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
required: ['query'],
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'ask_qwickai',
|
|
117
|
+
description: 'Ask a question and get an AI-generated natural language answer about the codebase. The AI searches the codebase, analyzes relevant code, and explains it in plain English. Use this when you need to UNDERSTAND how something works or get an explanation. Powered by Llama LLM for intelligent analysis and natural language responses. Output: Natural language explanation with references to specific code locations.',
|
|
118
|
+
inputSchema: {
|
|
119
|
+
type: 'object',
|
|
120
|
+
properties: {
|
|
121
|
+
query: {
|
|
122
|
+
type: 'string',
|
|
123
|
+
description: 'Question about the codebase in natural language. Examples: "How does the authentication system work?", "What happens when a user logs in?", "Explain how database connections are managed", "What files are involved in processing payments?"',
|
|
124
|
+
},
|
|
125
|
+
max_results: {
|
|
126
|
+
type: 'integer',
|
|
127
|
+
description: 'Maximum code entities to analyze (default: 5, max: 10)',
|
|
128
|
+
default: 5,
|
|
129
|
+
},
|
|
130
|
+
model: {
|
|
131
|
+
type: 'string',
|
|
132
|
+
description: 'LLM model to use (default: llama-3.1-8b, options: llama-3.1-8b, qwen-2.5-14b)',
|
|
133
|
+
default: 'llama-3.1-8b',
|
|
134
|
+
enum: ['llama-3.1-8b', 'qwen-2.5-14b'],
|
|
110
135
|
},
|
|
111
136
|
},
|
|
112
137
|
required: ['query'],
|
package/dist/lib/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,MAAM,CAAC,MAAM,gBAAgB,GAAqB;IAChD,sBAAsB;IACtB;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,+KAA+K;QAC5L,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,sCAAsC;iBACpD;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,yEAAyE;iBACvF;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,oLAAoL;QACjM,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kCAAkC;iBAChD;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,mHAAmH;QAChI,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8BAA8B;iBAC5C;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wEAAwE;iBACtF;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,yGAAyG;QACtH,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8BAA8B;iBAC5C;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,qEAAqE;iBACnF;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,yGAAyG;QACtH,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8BAA8B;iBAC5C;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -154,11 +154,11 @@ describe('ConnectionManager', () => {
|
|
|
154
154
|
}
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
-
it('should emit
|
|
157
|
+
it('should emit dormant after max attempts', async () => {
|
|
158
158
|
mockClient.healthCheck = vi.fn().mockRejectedValue(new Error('Failed'));
|
|
159
159
|
|
|
160
160
|
const maxAttemptsListener = vi.fn();
|
|
161
|
-
connectionManager.on('
|
|
161
|
+
connectionManager.on('dormant', maxAttemptsListener);
|
|
162
162
|
|
|
163
163
|
await connectionManager.start();
|
|
164
164
|
|
|
@@ -244,7 +244,9 @@ describe('QwickBrainClient', () => {
|
|
|
244
244
|
const isHealthy = await client.healthCheck();
|
|
245
245
|
|
|
246
246
|
expect(isHealthy).toBe(true);
|
|
247
|
-
expect(global.fetch).toHaveBeenCalledWith('http://api.test.com/health'
|
|
247
|
+
expect(global.fetch).toHaveBeenCalledWith('http://api.test.com/health', expect.objectContaining({
|
|
248
|
+
signal: expect.any(AbortSignal),
|
|
249
|
+
}));
|
|
248
250
|
});
|
|
249
251
|
|
|
250
252
|
it('should return false on health check failure', async () => {
|
|
@@ -3,6 +3,9 @@ import { ConnectionState } from '../types/mcp.js';
|
|
|
3
3
|
import type { Config } from '../types/config.js';
|
|
4
4
|
import type { QwickBrainClient } from './qwickbrain-client.js';
|
|
5
5
|
|
|
6
|
+
// Dormant mode: long interval health check after giving up on reconnection
|
|
7
|
+
const DORMANT_CHECK_INTERVAL = 300000; // 5 minutes
|
|
8
|
+
|
|
6
9
|
export class ConnectionManager extends EventEmitter {
|
|
7
10
|
private state: ConnectionState = 'disconnected';
|
|
8
11
|
private reconnectAttempts = 0;
|
|
@@ -11,6 +14,7 @@ export class ConnectionManager extends EventEmitter {
|
|
|
11
14
|
private qwickbrainClient: QwickBrainClient;
|
|
12
15
|
private config: Config['connection'];
|
|
13
16
|
private isStopped = false;
|
|
17
|
+
private isDormant = false;
|
|
14
18
|
private executionLock: Promise<void> = Promise.resolve();
|
|
15
19
|
|
|
16
20
|
constructor(qwickbrainClient: QwickBrainClient, config: Config['connection']) {
|
|
@@ -34,6 +38,7 @@ export class ConnectionManager extends EventEmitter {
|
|
|
34
38
|
|
|
35
39
|
async start(): Promise<void> {
|
|
36
40
|
this.isStopped = false;
|
|
41
|
+
this.isDormant = false;
|
|
37
42
|
// Start health check in background (don't block server startup)
|
|
38
43
|
this.healthCheck().catch(err => {
|
|
39
44
|
console.error('Initial health check error:', err);
|
|
@@ -43,6 +48,7 @@ export class ConnectionManager extends EventEmitter {
|
|
|
43
48
|
|
|
44
49
|
stop(): void {
|
|
45
50
|
this.isStopped = true;
|
|
51
|
+
this.isDormant = false;
|
|
46
52
|
if (this.healthCheckTimer) {
|
|
47
53
|
clearTimeout(this.healthCheckTimer);
|
|
48
54
|
this.healthCheckTimer = null;
|
|
@@ -62,25 +68,33 @@ export class ConnectionManager extends EventEmitter {
|
|
|
62
68
|
const latencyMs = Date.now() - startTime;
|
|
63
69
|
|
|
64
70
|
if (isHealthy) {
|
|
71
|
+
const wasDormant = this.isDormant;
|
|
72
|
+
this.isDormant = false;
|
|
65
73
|
this.setState('connected');
|
|
66
74
|
this.reconnectAttempts = 0;
|
|
67
75
|
this.clearReconnectTimer();
|
|
68
76
|
this.emit('connected', { latencyMs });
|
|
77
|
+
|
|
78
|
+
// If waking from dormant, switch back to normal health check interval
|
|
79
|
+
if (wasDormant) {
|
|
80
|
+
this.scheduleHealthCheck();
|
|
81
|
+
}
|
|
69
82
|
return true;
|
|
70
83
|
} else {
|
|
71
84
|
throw new Error('Health check failed');
|
|
72
85
|
}
|
|
73
86
|
} catch (error) {
|
|
74
87
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
75
|
-
this.
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
if (!this.isDormant) {
|
|
89
|
+
this.setState('disconnected');
|
|
90
|
+
this.emit('disconnected', { error: errorMessage });
|
|
91
|
+
this.scheduleReconnect();
|
|
92
|
+
}
|
|
78
93
|
return false;
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
|
|
82
97
|
private scheduleHealthCheck(): void {
|
|
83
|
-
// Don't schedule if stopped
|
|
84
98
|
if (this.isStopped) {
|
|
85
99
|
return;
|
|
86
100
|
}
|
|
@@ -89,13 +103,14 @@ export class ConnectionManager extends EventEmitter {
|
|
|
89
103
|
clearTimeout(this.healthCheckTimer);
|
|
90
104
|
}
|
|
91
105
|
|
|
106
|
+
const interval = this.isDormant ? DORMANT_CHECK_INTERVAL : this.config.healthCheckInterval;
|
|
107
|
+
|
|
92
108
|
this.healthCheckTimer = setTimeout(async () => {
|
|
93
109
|
await this.healthCheck();
|
|
94
|
-
// Check again before rescheduling to prevent leak after stop()
|
|
95
110
|
if (!this.isStopped) {
|
|
96
111
|
this.scheduleHealthCheck();
|
|
97
112
|
}
|
|
98
|
-
},
|
|
113
|
+
}, interval);
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
private scheduleReconnect(): void {
|
|
@@ -104,8 +119,7 @@ export class ConnectionManager extends EventEmitter {
|
|
|
104
119
|
}
|
|
105
120
|
|
|
106
121
|
if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
|
|
107
|
-
this.
|
|
108
|
-
this.emit('maxReconnectAttemptsReached');
|
|
122
|
+
this.enterDormantMode();
|
|
109
123
|
return;
|
|
110
124
|
}
|
|
111
125
|
|
|
@@ -126,6 +140,51 @@ export class ConnectionManager extends EventEmitter {
|
|
|
126
140
|
this.emit('reconnecting', { attempt: this.reconnectAttempts, delay });
|
|
127
141
|
}
|
|
128
142
|
|
|
143
|
+
private enterDormantMode(): void {
|
|
144
|
+
this.isDormant = true;
|
|
145
|
+
this.setState('offline');
|
|
146
|
+
this.emit('dormant');
|
|
147
|
+
|
|
148
|
+
// Stop active health check and reconnect timers
|
|
149
|
+
if (this.healthCheckTimer) {
|
|
150
|
+
clearTimeout(this.healthCheckTimer);
|
|
151
|
+
this.healthCheckTimer = null;
|
|
152
|
+
}
|
|
153
|
+
if (this.reconnectTimer) {
|
|
154
|
+
clearTimeout(this.reconnectTimer);
|
|
155
|
+
this.reconnectTimer = null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Schedule dormant-mode health check (5 min interval)
|
|
159
|
+
console.error(`Entering dormant mode. Will retry every ${DORMANT_CHECK_INTERVAL / 1000}s.`);
|
|
160
|
+
this.scheduleHealthCheck();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Wake from dormant mode and attempt immediate reconnection.
|
|
165
|
+
* Called when a tool is invoked and we need to try connecting again.
|
|
166
|
+
*/
|
|
167
|
+
wakeUp(): void {
|
|
168
|
+
if (!this.isDormant || this.isStopped) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
console.error('Waking from dormant mode for tool call...');
|
|
173
|
+
this.isDormant = false;
|
|
174
|
+
this.reconnectAttempts = 0;
|
|
175
|
+
|
|
176
|
+
// Clear dormant timer and do immediate health check
|
|
177
|
+
if (this.healthCheckTimer) {
|
|
178
|
+
clearTimeout(this.healthCheckTimer);
|
|
179
|
+
this.healthCheckTimer = null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.healthCheck().catch(err => {
|
|
183
|
+
console.error('Wake-up health check error:', err);
|
|
184
|
+
});
|
|
185
|
+
this.scheduleHealthCheck();
|
|
186
|
+
}
|
|
187
|
+
|
|
129
188
|
private clearReconnectTimer(): void {
|
|
130
189
|
if (this.reconnectTimer) {
|
|
131
190
|
clearTimeout(this.reconnectTimer);
|
package/src/lib/proxy-server.ts
CHANGED
|
@@ -23,6 +23,7 @@ export class ProxyServer {
|
|
|
23
23
|
private writeQueueManager: WriteQueueManager;
|
|
24
24
|
private sseInvalidationListener: SSEInvalidationListener | null = null;
|
|
25
25
|
private config: Config;
|
|
26
|
+
private connectionInitialized = false;
|
|
26
27
|
|
|
27
28
|
constructor(db: DB, config: Config) {
|
|
28
29
|
this.config = config;
|
|
@@ -61,6 +62,27 @@ export class ProxyServer {
|
|
|
61
62
|
this.setupConnectionListeners();
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Lazy initialization: start connection manager on first tool call
|
|
67
|
+
* instead of eagerly on server startup. Saves CPU when QwickBrain
|
|
68
|
+
* tools are never used in a session.
|
|
69
|
+
*/
|
|
70
|
+
private async ensureConnectionInitialized(): Promise<void> {
|
|
71
|
+
if (this.connectionInitialized) {
|
|
72
|
+
// If dormant, wake up on tool call
|
|
73
|
+
this.connectionManager.wakeUp();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.connectionInitialized = true;
|
|
78
|
+
console.error('First tool call received, initializing connection...');
|
|
79
|
+
|
|
80
|
+
await this.connectionManager.start();
|
|
81
|
+
|
|
82
|
+
// SSE listener starts only when connection is established (see setupConnectionListeners)
|
|
83
|
+
// Not here - avoid starting SSE reconnection loops before we know the server is reachable
|
|
84
|
+
}
|
|
85
|
+
|
|
64
86
|
private setupConnectionListeners(): void {
|
|
65
87
|
this.connectionManager.on('stateChange', ({ from, to }) => {
|
|
66
88
|
console.error(`Connection state: ${from} → ${to}`);
|
|
@@ -72,6 +94,14 @@ export class ProxyServer {
|
|
|
72
94
|
|
|
73
95
|
this.connectionManager.on('connected', ({ latencyMs }) => {
|
|
74
96
|
console.error(`Connected to QwickBrain (latency: ${latencyMs}ms)`);
|
|
97
|
+
|
|
98
|
+
// Start SSE listener when connection is established
|
|
99
|
+
if (this.sseInvalidationListener && !this.sseInvalidationListener.isListening()) {
|
|
100
|
+
this.sseInvalidationListener.start().catch(err => {
|
|
101
|
+
console.error('SSE listener start error:', err);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
75
105
|
// Event-driven: trigger background sync when connection restored
|
|
76
106
|
this.onConnectionRestored().catch(err => {
|
|
77
107
|
console.error('Background sync error:', err);
|
|
@@ -84,6 +114,18 @@ export class ProxyServer {
|
|
|
84
114
|
|
|
85
115
|
this.connectionManager.on('disconnected', ({ error }) => {
|
|
86
116
|
console.error(`Disconnected from QwickBrain: ${error}`);
|
|
117
|
+
// Stop SSE listener when disconnected to avoid independent reconnection loops
|
|
118
|
+
if (this.sseInvalidationListener) {
|
|
119
|
+
this.sseInvalidationListener.stop();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
this.connectionManager.on('dormant', () => {
|
|
124
|
+
console.error('Connection manager entered dormant mode');
|
|
125
|
+
// Stop SSE listener in dormant mode
|
|
126
|
+
if (this.sseInvalidationListener) {
|
|
127
|
+
this.sseInvalidationListener.stop();
|
|
128
|
+
}
|
|
87
129
|
});
|
|
88
130
|
}
|
|
89
131
|
|
|
@@ -129,6 +171,9 @@ export class ProxyServer {
|
|
|
129
171
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
130
172
|
const { name, arguments: args } = request.params;
|
|
131
173
|
|
|
174
|
+
// Lazy init: start connection on first tool call
|
|
175
|
+
await this.ensureConnectionInitialized();
|
|
176
|
+
|
|
132
177
|
try {
|
|
133
178
|
let result: MCPResponse;
|
|
134
179
|
|
|
@@ -483,23 +528,15 @@ export class ProxyServer {
|
|
|
483
528
|
}
|
|
484
529
|
|
|
485
530
|
async start(): Promise<void> {
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
|
|
489
|
-
// Start connection manager (handles connection gracefully, doesn't throw)
|
|
490
|
-
await this.connectionManager.start();
|
|
491
|
-
|
|
492
|
-
// Start SSE invalidation listener if configured
|
|
493
|
-
if (this.sseInvalidationListener) {
|
|
494
|
-
await this.sseInvalidationListener.start();
|
|
495
|
-
console.error('SSE cache invalidation listener started');
|
|
496
|
-
}
|
|
531
|
+
// Lazy init: do NOT start connection manager here.
|
|
532
|
+
// Connection is initialized on first tool call (see ensureConnectionInitialized).
|
|
533
|
+
// This means idle proxy instances use zero network resources.
|
|
497
534
|
|
|
498
535
|
// Start MCP server
|
|
499
536
|
const transport = new StdioServerTransport();
|
|
500
537
|
await this.server.connect(transport);
|
|
501
538
|
|
|
502
|
-
console.error('QwickBrain Proxy started');
|
|
539
|
+
console.error('QwickBrain Proxy started (lazy mode - connection starts on first tool call)');
|
|
503
540
|
}
|
|
504
541
|
|
|
505
542
|
async stop(): Promise<void> {
|
|
@@ -229,28 +229,42 @@ export class QwickBrainClient {
|
|
|
229
229
|
|
|
230
230
|
async healthCheck(): Promise<boolean> {
|
|
231
231
|
try {
|
|
232
|
-
if (this.mode === '
|
|
233
|
-
// For MCP/SSE mode, check if client is connected
|
|
234
|
-
if (!this.client) {
|
|
235
|
-
// Initialize connection on first health check
|
|
236
|
-
await this.connect();
|
|
237
|
-
if (!this.client) {
|
|
238
|
-
return false;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// Try listing tools as health check
|
|
242
|
-
await this.client.listTools();
|
|
243
|
-
return true;
|
|
244
|
-
} else {
|
|
232
|
+
if (this.mode === 'http') {
|
|
245
233
|
// For HTTP mode, ping health endpoint
|
|
246
234
|
if (!this.config.url) {
|
|
247
235
|
return false;
|
|
248
236
|
}
|
|
249
|
-
const response = await fetch(`${this.config.url}/health
|
|
237
|
+
const response = await fetch(`${this.config.url}/health`, {
|
|
238
|
+
signal: AbortSignal.timeout(5000),
|
|
239
|
+
});
|
|
250
240
|
return response.ok;
|
|
251
241
|
}
|
|
242
|
+
|
|
243
|
+
// For MCP/SSE mode: use a lightweight HTTP ping to the base URL
|
|
244
|
+
// instead of creating expensive MCP Client+Transport objects each time
|
|
245
|
+
if (this.config.url) {
|
|
246
|
+
const baseUrl = this.config.url.replace(/\/sse$/, '');
|
|
247
|
+
const response = await fetch(`${baseUrl}/health`, {
|
|
248
|
+
signal: AbortSignal.timeout(5000),
|
|
249
|
+
});
|
|
250
|
+
if (!response.ok) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Server is reachable; ensure MCP client is connected
|
|
256
|
+
if (!this.client) {
|
|
257
|
+
await this.connect();
|
|
258
|
+
if (!this.client) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Verify the MCP connection is alive
|
|
264
|
+
await this.client.listTools();
|
|
265
|
+
return true;
|
|
252
266
|
} catch (error) {
|
|
253
|
-
// Connection dropped - clear client to force reconnection
|
|
267
|
+
// Connection dropped - clear client to force reconnection on next successful health check
|
|
254
268
|
this.client = null;
|
|
255
269
|
this.transport = null;
|
|
256
270
|
return false;
|