@agentuity/runtime 0.0.86 → 0.0.88
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/AGENTS.md +10 -10
- package/README.md +19 -13
- package/dist/_server.d.ts +7 -0
- package/dist/_server.d.ts.map +1 -1
- package/dist/_server.js +50 -0
- package/dist/_server.js.map +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +7 -0
- package/dist/agent.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/otel/otel.d.ts.map +1 -1
- package/dist/otel/otel.js +1 -0
- package/dist/otel/otel.js.map +1 -1
- package/dist/services/local/keyvalue.d.ts.map +1 -1
- package/dist/services/local/keyvalue.js +8 -1
- package/dist/services/local/keyvalue.js.map +1 -1
- package/dist/services/local/vector.d.ts.map +1 -1
- package/dist/services/local/vector.js +9 -2
- package/dist/services/local/vector.js.map +1 -1
- package/dist/session.d.ts +29 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +75 -13
- package/dist/session.js.map +1 -1
- package/package.json +5 -5
- package/src/_server.ts +59 -1
- package/src/agent.ts +9 -1
- package/src/index.ts +1 -2
- package/src/otel/otel.ts +1 -0
- package/src/services/local/keyvalue.ts +7 -1
- package/src/services/local/vector.ts +12 -3
- package/src/session.ts +88 -13
|
@@ -45,7 +45,13 @@ export class LocalKeyValueStorage implements KeyValueStorage {
|
|
|
45
45
|
// Deserialize based on content type
|
|
46
46
|
let data: T;
|
|
47
47
|
if (row.content_type === 'application/json') {
|
|
48
|
-
|
|
48
|
+
try {
|
|
49
|
+
const text = row.value.toString('utf-8');
|
|
50
|
+
data = JSON.parse(text);
|
|
51
|
+
} catch {
|
|
52
|
+
// If JSON parse fails, return the raw buffer as Uint8Array
|
|
53
|
+
data = new Uint8Array(row.value) as T;
|
|
54
|
+
}
|
|
49
55
|
} else if (row.content_type.startsWith('text/')) {
|
|
50
56
|
data = row.value.toString('utf-8') as T;
|
|
51
57
|
} else {
|
|
@@ -173,9 +173,6 @@ export class LocalVectorStorage implements VectorStorage {
|
|
|
173
173
|
throw new Error('Query is required');
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
// Generate query embedding
|
|
177
|
-
const queryEmbedding = simpleEmbedding(params.query);
|
|
178
|
-
|
|
179
176
|
// Fetch all vectors for this name
|
|
180
177
|
const query = this.#db.query(`
|
|
181
178
|
SELECT id, key, embedding, metadata
|
|
@@ -190,6 +187,18 @@ export class LocalVectorStorage implements VectorStorage {
|
|
|
190
187
|
metadata: string | null;
|
|
191
188
|
}>;
|
|
192
189
|
|
|
190
|
+
// If no vectors exist, return empty results
|
|
191
|
+
if (rows.length === 0) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Detect dimensionality from first stored vector
|
|
196
|
+
const firstEmbedding = JSON.parse(rows[0].embedding);
|
|
197
|
+
const dimensions = firstEmbedding.length;
|
|
198
|
+
|
|
199
|
+
// Generate query embedding with matching dimensions
|
|
200
|
+
const queryEmbedding = simpleEmbedding(params.query, dimensions);
|
|
201
|
+
|
|
193
202
|
// Calculate similarities
|
|
194
203
|
const results: Array<VectorSearchResult<T> & { similarity: number }> = [];
|
|
195
204
|
|
package/src/session.ts
CHANGED
|
@@ -615,10 +615,15 @@ export class DefaultSession implements Session {
|
|
|
615
615
|
}
|
|
616
616
|
|
|
617
617
|
/**
|
|
618
|
-
* WebSocket client for thread state persistence
|
|
618
|
+
* WebSocket client for thread state persistence.
|
|
619
|
+
*
|
|
620
|
+
* **WARNING: This class is exported for testing purposes only and is subject to change
|
|
621
|
+
* without notice. Do not use this class directly in production code.**
|
|
622
|
+
*
|
|
619
623
|
* @internal
|
|
624
|
+
* @experimental
|
|
620
625
|
*/
|
|
621
|
-
class ThreadWebSocketClient {
|
|
626
|
+
export class ThreadWebSocketClient {
|
|
622
627
|
private ws: WebSocket | null = null;
|
|
623
628
|
private authenticated = false;
|
|
624
629
|
private pendingRequests = new Map<
|
|
@@ -630,6 +635,10 @@ class ThreadWebSocketClient {
|
|
|
630
635
|
private apiKey: string;
|
|
631
636
|
private wsUrl: string;
|
|
632
637
|
private wsConnecting: Promise<void> | null = null;
|
|
638
|
+
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
|
639
|
+
private isDisposed = false;
|
|
640
|
+
private initialConnectResolve: (() => void) | null = null;
|
|
641
|
+
private initialConnectReject: ((err: Error) => void) | null = null;
|
|
633
642
|
|
|
634
643
|
constructor(apiKey: string, wsUrl: string) {
|
|
635
644
|
this.apiKey = apiKey;
|
|
@@ -638,10 +647,19 @@ class ThreadWebSocketClient {
|
|
|
638
647
|
|
|
639
648
|
async connect(): Promise<void> {
|
|
640
649
|
return new Promise((resolve, reject) => {
|
|
650
|
+
// Store the initial connect promise callbacks if this is the first attempt
|
|
651
|
+
if (this.reconnectAttempts === 0) {
|
|
652
|
+
this.initialConnectResolve = resolve;
|
|
653
|
+
this.initialConnectReject = reject;
|
|
654
|
+
}
|
|
655
|
+
|
|
641
656
|
// Set connection timeout
|
|
642
657
|
const connectionTimeout = setTimeout(() => {
|
|
643
658
|
this.cleanup();
|
|
644
|
-
|
|
659
|
+
const rejectFn = this.initialConnectReject || reject;
|
|
660
|
+
this.initialConnectResolve = null;
|
|
661
|
+
this.initialConnectReject = null;
|
|
662
|
+
rejectFn(new Error('WebSocket connection timeout (10s)'));
|
|
645
663
|
}, 10_000);
|
|
646
664
|
|
|
647
665
|
try {
|
|
@@ -662,13 +680,21 @@ class ThreadWebSocketClient {
|
|
|
662
680
|
if (message.success) {
|
|
663
681
|
this.authenticated = true;
|
|
664
682
|
this.reconnectAttempts = 0;
|
|
665
|
-
|
|
683
|
+
|
|
684
|
+
// Resolve both the current promise and the initial connect promise
|
|
685
|
+
const resolveFn = this.initialConnectResolve || resolve;
|
|
686
|
+
this.initialConnectResolve = null;
|
|
687
|
+
this.initialConnectReject = null;
|
|
688
|
+
resolveFn();
|
|
666
689
|
} else {
|
|
667
690
|
const err = new Error(
|
|
668
691
|
`WebSocket authentication failed: ${message.error || 'Unknown error'}`
|
|
669
692
|
);
|
|
670
693
|
this.cleanup();
|
|
671
|
-
reject
|
|
694
|
+
const rejectFn = this.initialConnectReject || reject;
|
|
695
|
+
this.initialConnectResolve = null;
|
|
696
|
+
this.initialConnectReject = null;
|
|
697
|
+
rejectFn(err);
|
|
672
698
|
}
|
|
673
699
|
return;
|
|
674
700
|
}
|
|
@@ -692,7 +718,13 @@ class ThreadWebSocketClient {
|
|
|
692
718
|
this.ws.on('error', (err: Error) => {
|
|
693
719
|
clearTimeout(connectionTimeout);
|
|
694
720
|
if (!this.authenticated) {
|
|
695
|
-
reject
|
|
721
|
+
// Don't reject immediately if we'll attempt reconnection
|
|
722
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts || this.isDisposed) {
|
|
723
|
+
const rejectFn = this.initialConnectReject || reject;
|
|
724
|
+
this.initialConnectResolve = null;
|
|
725
|
+
this.initialConnectReject = null;
|
|
726
|
+
rejectFn(new Error(`WebSocket error: ${err.message}`));
|
|
727
|
+
}
|
|
696
728
|
}
|
|
697
729
|
});
|
|
698
730
|
|
|
@@ -707,29 +739,59 @@ class ThreadWebSocketClient {
|
|
|
707
739
|
this.pendingRequests.delete(id);
|
|
708
740
|
}
|
|
709
741
|
|
|
710
|
-
//
|
|
711
|
-
if (
|
|
712
|
-
|
|
742
|
+
// Don't attempt reconnection if disposed
|
|
743
|
+
if (this.isDisposed) {
|
|
744
|
+
// Reject initial connect if still pending
|
|
745
|
+
if (!wasAuthenticated && this.initialConnectReject) {
|
|
746
|
+
this.initialConnectReject(new Error('WebSocket closed before authentication'));
|
|
747
|
+
this.initialConnectResolve = null;
|
|
748
|
+
this.initialConnectReject = null;
|
|
749
|
+
}
|
|
750
|
+
return;
|
|
713
751
|
}
|
|
714
752
|
|
|
715
|
-
// Attempt reconnection
|
|
716
|
-
|
|
753
|
+
// Attempt reconnection if within retry limits (even if auth didn't complete)
|
|
754
|
+
// This handles server rollouts where connection closes before auth finishes
|
|
755
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
717
756
|
this.reconnectAttempts++;
|
|
718
757
|
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30_000);
|
|
719
758
|
|
|
759
|
+
internal.info(
|
|
760
|
+
`WebSocket disconnected, attempting reconnection ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`
|
|
761
|
+
);
|
|
762
|
+
|
|
720
763
|
// Schedule reconnection with backoff delay
|
|
721
|
-
setTimeout(() => {
|
|
764
|
+
this.reconnectTimer = setTimeout(() => {
|
|
765
|
+
this.reconnectTimer = null;
|
|
722
766
|
// Create new connection promise for reconnection
|
|
723
767
|
this.wsConnecting = this.connect().catch(() => {
|
|
724
768
|
// Reconnection failed, reset
|
|
725
769
|
this.wsConnecting = null;
|
|
726
770
|
});
|
|
727
771
|
}, delay);
|
|
772
|
+
} else {
|
|
773
|
+
internal.error(
|
|
774
|
+
`WebSocket disconnected after ${this.reconnectAttempts} attempts, giving up`
|
|
775
|
+
);
|
|
776
|
+
|
|
777
|
+
// Reject initial connect if still pending (all attempts exhausted)
|
|
778
|
+
if (!wasAuthenticated && this.initialConnectReject) {
|
|
779
|
+
this.initialConnectReject(
|
|
780
|
+
new Error(
|
|
781
|
+
`WebSocket closed before authentication after ${this.reconnectAttempts} attempts`
|
|
782
|
+
)
|
|
783
|
+
);
|
|
784
|
+
this.initialConnectResolve = null;
|
|
785
|
+
this.initialConnectReject = null;
|
|
786
|
+
}
|
|
728
787
|
}
|
|
729
788
|
});
|
|
730
789
|
} catch (err) {
|
|
731
790
|
clearTimeout(connectionTimeout);
|
|
732
|
-
reject
|
|
791
|
+
const rejectFn = this.initialConnectReject || reject;
|
|
792
|
+
this.initialConnectResolve = null;
|
|
793
|
+
this.initialConnectReject = null;
|
|
794
|
+
rejectFn(err as Error);
|
|
733
795
|
}
|
|
734
796
|
});
|
|
735
797
|
}
|
|
@@ -846,12 +908,25 @@ class ThreadWebSocketClient {
|
|
|
846
908
|
}
|
|
847
909
|
|
|
848
910
|
cleanup(): void {
|
|
911
|
+
// Mark as disposed to prevent new reconnection attempts
|
|
912
|
+
this.isDisposed = true;
|
|
913
|
+
|
|
914
|
+
// Cancel any pending reconnection timer
|
|
915
|
+
if (this.reconnectTimer) {
|
|
916
|
+
clearTimeout(this.reconnectTimer);
|
|
917
|
+
this.reconnectTimer = null;
|
|
918
|
+
}
|
|
919
|
+
|
|
849
920
|
if (this.ws) {
|
|
850
921
|
this.ws.close();
|
|
851
922
|
this.ws = null;
|
|
852
923
|
}
|
|
853
924
|
this.authenticated = false;
|
|
854
925
|
this.pendingRequests.clear();
|
|
926
|
+
this.reconnectAttempts = 0;
|
|
927
|
+
this.wsConnecting = null;
|
|
928
|
+
this.initialConnectResolve = null;
|
|
929
|
+
this.initialConnectReject = null;
|
|
855
930
|
}
|
|
856
931
|
}
|
|
857
932
|
|