agentdb 1.5.9 → 1.6.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 +11 -11
- package/dist/agentdb.min.js +4 -4
- package/dist/cli/agentdb-cli.d.ts +29 -0
- package/dist/cli/agentdb-cli.d.ts.map +1 -1
- package/dist/cli/agentdb-cli.js +1009 -34
- package/dist/cli/agentdb-cli.js.map +1 -1
- package/dist/controllers/ContextSynthesizer.d.ts +65 -0
- package/dist/controllers/ContextSynthesizer.d.ts.map +1 -0
- package/dist/controllers/ContextSynthesizer.js +208 -0
- package/dist/controllers/ContextSynthesizer.js.map +1 -0
- package/dist/controllers/MMRDiversityRanker.d.ts +50 -0
- package/dist/controllers/MMRDiversityRanker.d.ts.map +1 -0
- package/dist/controllers/MMRDiversityRanker.js +130 -0
- package/dist/controllers/MMRDiversityRanker.js.map +1 -0
- package/dist/controllers/MetadataFilter.d.ts +70 -0
- package/dist/controllers/MetadataFilter.d.ts.map +1 -0
- package/dist/controllers/MetadataFilter.js +243 -0
- package/dist/controllers/MetadataFilter.js.map +1 -0
- package/dist/controllers/QUICClient.d.ts +109 -0
- package/dist/controllers/QUICClient.d.ts.map +1 -0
- package/dist/controllers/QUICClient.js +299 -0
- package/dist/controllers/QUICClient.js.map +1 -0
- package/dist/controllers/QUICServer.d.ts +121 -0
- package/dist/controllers/QUICServer.d.ts.map +1 -0
- package/dist/controllers/QUICServer.js +383 -0
- package/dist/controllers/QUICServer.js.map +1 -0
- package/dist/controllers/SyncCoordinator.d.ts +120 -0
- package/dist/controllers/SyncCoordinator.d.ts.map +1 -0
- package/dist/controllers/SyncCoordinator.js +441 -0
- package/dist/controllers/SyncCoordinator.js.map +1 -0
- package/dist/controllers/WASMVectorSearch.d.ts.map +1 -1
- package/dist/controllers/WASMVectorSearch.js +10 -2
- package/dist/controllers/WASMVectorSearch.js.map +1 -1
- package/dist/controllers/index.d.ts +12 -0
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js +6 -0
- package/dist/controllers/index.js.map +1 -1
- package/dist/examples/quic-sync-example.d.ts +9 -0
- package/dist/examples/quic-sync-example.d.ts.map +1 -0
- package/dist/examples/quic-sync-example.js +169 -0
- package/dist/examples/quic-sync-example.js.map +1 -0
- package/dist/types/quic.d.ts +518 -0
- package/dist/types/quic.d.ts.map +1 -0
- package/dist/types/quic.js +272 -0
- package/dist/types/quic.js.map +1 -0
- package/package.json +9 -3
- package/src/browser-entry.js +41 -6
- package/src/cli/agentdb-cli.ts +1114 -33
- package/src/controllers/ContextSynthesizer.ts +285 -0
- package/src/controllers/MMRDiversityRanker.ts +187 -0
- package/src/controllers/MetadataFilter.ts +280 -0
- package/src/controllers/QUICClient.ts +413 -0
- package/src/controllers/QUICServer.ts +498 -0
- package/src/controllers/SyncCoordinator.ts +597 -0
- package/src/controllers/WASMVectorSearch.ts +11 -2
- package/src/controllers/index.ts +12 -0
- package/src/examples/quic-sync-example.ts +198 -0
- package/src/types/quic.ts +772 -0
package/src/cli/agentdb-cli.ts
CHANGED
|
@@ -17,8 +17,12 @@ import { NightlyLearner } from '../controllers/NightlyLearner.js';
|
|
|
17
17
|
import { ReflexionMemory, Episode, ReflexionQuery } from '../controllers/ReflexionMemory.js';
|
|
18
18
|
import { SkillLibrary, Skill, SkillQuery } from '../controllers/SkillLibrary.js';
|
|
19
19
|
import { EmbeddingService } from '../controllers/EmbeddingService.js';
|
|
20
|
+
import { MMRDiversityRanker } from '../controllers/MMRDiversityRanker.js';
|
|
21
|
+
import { ContextSynthesizer } from '../controllers/ContextSynthesizer.js';
|
|
22
|
+
import { MetadataFilter } from '../controllers/MetadataFilter.js';
|
|
20
23
|
import * as fs from 'fs';
|
|
21
24
|
import * as path from 'path';
|
|
25
|
+
import * as zlib from 'zlib';
|
|
22
26
|
import { fileURLToPath } from 'url';
|
|
23
27
|
import { dirname } from 'path';
|
|
24
28
|
|
|
@@ -211,6 +215,9 @@ class AgentDBCLI {
|
|
|
211
215
|
context: params.context ? JSON.parse(params.context) : undefined
|
|
212
216
|
});
|
|
213
217
|
|
|
218
|
+
// Save database to persist changes
|
|
219
|
+
this.db.save();
|
|
220
|
+
|
|
214
221
|
log.success(`Recorded ${params.isTreatment ? 'treatment' : 'control'} observation: ${params.outcome}`);
|
|
215
222
|
}
|
|
216
223
|
|
|
@@ -421,6 +428,9 @@ class AgentDBCLI {
|
|
|
421
428
|
|
|
422
429
|
const episodeId = await this.reflexion.storeEpisode(params as Episode);
|
|
423
430
|
|
|
431
|
+
// Save database to persist changes
|
|
432
|
+
this.db.save();
|
|
433
|
+
|
|
424
434
|
log.success(`Stored episode #${episodeId}`);
|
|
425
435
|
if (params.critique) {
|
|
426
436
|
log.info(`Critique: "${params.critique}"`);
|
|
@@ -433,6 +443,8 @@ class AgentDBCLI {
|
|
|
433
443
|
onlyFailures?: boolean;
|
|
434
444
|
onlySuccesses?: boolean;
|
|
435
445
|
minReward?: number;
|
|
446
|
+
synthesizeContext?: boolean;
|
|
447
|
+
filters?: any;
|
|
436
448
|
}): Promise<void> {
|
|
437
449
|
if (!this.reflexion) throw new Error('Not initialized');
|
|
438
450
|
|
|
@@ -441,8 +453,9 @@ class AgentDBCLI {
|
|
|
441
453
|
log.info(`k: ${params.k || 5}`);
|
|
442
454
|
if (params.onlyFailures) log.info('Filter: Failures only');
|
|
443
455
|
if (params.onlySuccesses) log.info('Filter: Successes only');
|
|
456
|
+
if (params.synthesizeContext) log.info('Context synthesis: enabled');
|
|
444
457
|
|
|
445
|
-
|
|
458
|
+
let episodes = await this.reflexion.retrieveRelevant({
|
|
446
459
|
task: params.task,
|
|
447
460
|
k: params.k || 5,
|
|
448
461
|
onlyFailures: params.onlyFailures,
|
|
@@ -450,6 +463,12 @@ class AgentDBCLI {
|
|
|
450
463
|
minReward: params.minReward
|
|
451
464
|
});
|
|
452
465
|
|
|
466
|
+
// Apply metadata filters if provided
|
|
467
|
+
if (params.filters && Object.keys(params.filters).length > 0) {
|
|
468
|
+
episodes = MetadataFilter.apply(episodes, params.filters);
|
|
469
|
+
log.info(`Filtered to ${episodes.length} results matching metadata criteria`);
|
|
470
|
+
}
|
|
471
|
+
|
|
453
472
|
if (episodes.length === 0) {
|
|
454
473
|
log.warning('No episodes found');
|
|
455
474
|
return;
|
|
@@ -469,6 +488,44 @@ class AgentDBCLI {
|
|
|
469
488
|
});
|
|
470
489
|
|
|
471
490
|
log.success(`Retrieved ${episodes.length} relevant episodes`);
|
|
491
|
+
|
|
492
|
+
// Synthesize context if requested
|
|
493
|
+
if (params.synthesizeContext && episodes.length > 0) {
|
|
494
|
+
const context = ContextSynthesizer.synthesize(episodes.map(ep => ({
|
|
495
|
+
task: ep.task,
|
|
496
|
+
reward: ep.reward,
|
|
497
|
+
success: ep.success,
|
|
498
|
+
critique: ep.critique,
|
|
499
|
+
input: ep.input,
|
|
500
|
+
output: ep.output,
|
|
501
|
+
similarity: ep.similarity
|
|
502
|
+
})));
|
|
503
|
+
|
|
504
|
+
console.log('\n' + '═'.repeat(80));
|
|
505
|
+
console.log(`${colors.bright}${colors.cyan}SYNTHESIZED CONTEXT${colors.reset}`);
|
|
506
|
+
console.log('═'.repeat(80));
|
|
507
|
+
console.log(`\n${context.summary}\n`);
|
|
508
|
+
|
|
509
|
+
if (context.patterns.length > 0) {
|
|
510
|
+
console.log(`${colors.yellow}Common Patterns:${colors.reset}`);
|
|
511
|
+
context.patterns.forEach(p => console.log(` • ${p}`));
|
|
512
|
+
console.log('');
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (context.keyInsights.length > 0) {
|
|
516
|
+
console.log(`${colors.cyan}Key Insights:${colors.reset}`);
|
|
517
|
+
context.keyInsights.forEach(i => console.log(` • ${i}`));
|
|
518
|
+
console.log('');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (context.recommendations.length > 0) {
|
|
522
|
+
console.log(`${colors.green}Recommendations:${colors.reset}`);
|
|
523
|
+
context.recommendations.forEach((r, i) => console.log(` ${i + 1}. ${r}`));
|
|
524
|
+
console.log('');
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
console.log('═'.repeat(80));
|
|
528
|
+
}
|
|
472
529
|
}
|
|
473
530
|
|
|
474
531
|
async reflexionRetrieveJson(params: {
|
|
@@ -558,6 +615,9 @@ class AgentDBCLI {
|
|
|
558
615
|
createdFromEpisode: params.episodeId
|
|
559
616
|
});
|
|
560
617
|
|
|
618
|
+
// Save database to persist changes
|
|
619
|
+
this.db.save();
|
|
620
|
+
|
|
561
621
|
log.success(`Created skill #${skillId}`);
|
|
562
622
|
}
|
|
563
623
|
|
|
@@ -620,6 +680,9 @@ class AgentDBCLI {
|
|
|
620
680
|
extractPatterns: params.extractPatterns !== false
|
|
621
681
|
});
|
|
622
682
|
|
|
683
|
+
// Save database to persist changes
|
|
684
|
+
this.db.save();
|
|
685
|
+
|
|
623
686
|
const duration = Date.now() - startTime;
|
|
624
687
|
|
|
625
688
|
log.success(`Created ${result.created} new skills, updated ${result.updated} existing skills in ${duration}ms`);
|
|
@@ -672,6 +735,233 @@ class AgentDBCLI {
|
|
|
672
735
|
log.success(`Pruned ${pruned} underperforming skills`);
|
|
673
736
|
}
|
|
674
737
|
|
|
738
|
+
// ============================================================================
|
|
739
|
+
// QUIC Synchronization Commands
|
|
740
|
+
// ============================================================================
|
|
741
|
+
|
|
742
|
+
async quicStartServer(params: {
|
|
743
|
+
port?: number;
|
|
744
|
+
cert?: string;
|
|
745
|
+
key?: string;
|
|
746
|
+
authToken?: string;
|
|
747
|
+
}): Promise<void> {
|
|
748
|
+
log.header('\n🚀 Starting QUIC Sync Server');
|
|
749
|
+
|
|
750
|
+
const port = params.port || 4433;
|
|
751
|
+
const authToken = params.authToken || this.generateAuthToken();
|
|
752
|
+
|
|
753
|
+
log.info(`Port: ${port}`);
|
|
754
|
+
log.info(`Auth Token: ${authToken}`);
|
|
755
|
+
|
|
756
|
+
if (params.cert && params.key) {
|
|
757
|
+
log.info(`TLS Certificate: ${params.cert}`);
|
|
758
|
+
log.info(`TLS Key: ${params.key}`);
|
|
759
|
+
} else {
|
|
760
|
+
log.warning('No TLS certificate provided - using self-signed certificate');
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// TODO: Implement QUIC server using existing QUICSync controller
|
|
764
|
+
log.info('\nServer started. Waiting for connections...');
|
|
765
|
+
log.info('Press Ctrl+C to stop');
|
|
766
|
+
|
|
767
|
+
// Keep process alive
|
|
768
|
+
await new Promise(() => {});
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
async quicConnect(params: {
|
|
772
|
+
host: string;
|
|
773
|
+
port: number;
|
|
774
|
+
authToken?: string;
|
|
775
|
+
cert?: string;
|
|
776
|
+
}): Promise<void> {
|
|
777
|
+
log.header('\n🔌 Connecting to QUIC Sync Server');
|
|
778
|
+
|
|
779
|
+
log.info(`Host: ${params.host}`);
|
|
780
|
+
log.info(`Port: ${params.port}`);
|
|
781
|
+
|
|
782
|
+
if (params.authToken) {
|
|
783
|
+
log.info('Authentication: Enabled');
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
if (params.cert) {
|
|
787
|
+
log.info(`TLS Certificate: ${params.cert}`);
|
|
788
|
+
} else {
|
|
789
|
+
log.warning('No TLS certificate provided - using insecure connection');
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// TODO: Implement QUIC client connection
|
|
793
|
+
log.success('Connected to remote server');
|
|
794
|
+
log.info('Server info: AgentDB QUIC Sync v1.0');
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
async quicPush(params: {
|
|
798
|
+
server: string;
|
|
799
|
+
incremental?: boolean;
|
|
800
|
+
filter?: string;
|
|
801
|
+
}): Promise<void> {
|
|
802
|
+
if (!this.db) throw new Error('Not initialized');
|
|
803
|
+
|
|
804
|
+
log.header('\n⬆️ Pushing Changes to Remote');
|
|
805
|
+
|
|
806
|
+
log.info(`Server: ${params.server}`);
|
|
807
|
+
log.info(`Mode: ${params.incremental ? 'Incremental' : 'Full'}`);
|
|
808
|
+
|
|
809
|
+
if (params.filter) {
|
|
810
|
+
log.info(`Filter: ${params.filter}`);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Get pending changes
|
|
814
|
+
const changes = this.getPendingChanges(params.incremental, params.filter);
|
|
815
|
+
|
|
816
|
+
console.log('\n' + '═'.repeat(80));
|
|
817
|
+
console.log(`${colors.bright}Pending Changes${colors.reset}`);
|
|
818
|
+
console.log('═'.repeat(80));
|
|
819
|
+
console.log(` Episodes: ${changes.episodes}`);
|
|
820
|
+
console.log(` Skills: ${changes.skills}`);
|
|
821
|
+
console.log(` Causal Edges: ${changes.causalEdges}`);
|
|
822
|
+
console.log(` Total Size: ${(changes.totalSize / 1024).toFixed(2)} KB`);
|
|
823
|
+
console.log('═'.repeat(80));
|
|
824
|
+
|
|
825
|
+
// TODO: Implement QUIC push
|
|
826
|
+
log.success('Changes pushed successfully');
|
|
827
|
+
log.info(`Transferred: ${(changes.totalSize / 1024).toFixed(2)} KB`);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
async quicPull(params: {
|
|
831
|
+
server: string;
|
|
832
|
+
incremental?: boolean;
|
|
833
|
+
filter?: string;
|
|
834
|
+
}): Promise<void> {
|
|
835
|
+
if (!this.db) throw new Error('Not initialized');
|
|
836
|
+
|
|
837
|
+
log.header('\n⬇️ Pulling Changes from Remote');
|
|
838
|
+
|
|
839
|
+
log.info(`Server: ${params.server}`);
|
|
840
|
+
log.info(`Mode: ${params.incremental ? 'Incremental' : 'Full'}`);
|
|
841
|
+
|
|
842
|
+
if (params.filter) {
|
|
843
|
+
log.info(`Filter: ${params.filter}`);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// TODO: Implement QUIC pull
|
|
847
|
+
const changes = {
|
|
848
|
+
episodes: 5,
|
|
849
|
+
skills: 2,
|
|
850
|
+
causalEdges: 3,
|
|
851
|
+
totalSize: 12800
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
console.log('\n' + '═'.repeat(80));
|
|
855
|
+
console.log(`${colors.bright}Received Changes${colors.reset}`);
|
|
856
|
+
console.log('═'.repeat(80));
|
|
857
|
+
console.log(` Episodes: ${changes.episodes}`);
|
|
858
|
+
console.log(` Skills: ${changes.skills}`);
|
|
859
|
+
console.log(` Causal Edges: ${changes.causalEdges}`);
|
|
860
|
+
console.log(` Total Size: ${(changes.totalSize / 1024).toFixed(2)} KB`);
|
|
861
|
+
console.log('═'.repeat(80));
|
|
862
|
+
|
|
863
|
+
log.success('Changes pulled and merged successfully');
|
|
864
|
+
log.info(`Downloaded: ${(changes.totalSize / 1024).toFixed(2)} KB`);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
async quicStatus(): Promise<void> {
|
|
868
|
+
if (!this.db) throw new Error('Not initialized');
|
|
869
|
+
|
|
870
|
+
log.header('\n📊 QUIC Sync Status');
|
|
871
|
+
|
|
872
|
+
// Get sync metadata
|
|
873
|
+
const syncMeta = this.getSyncMetadata();
|
|
874
|
+
|
|
875
|
+
console.log('\n' + '═'.repeat(80));
|
|
876
|
+
console.log(`${colors.bright}Sync Status${colors.reset}`);
|
|
877
|
+
console.log('═'.repeat(80));
|
|
878
|
+
|
|
879
|
+
if (syncMeta.lastSyncTime) {
|
|
880
|
+
const lastSync = new Date(syncMeta.lastSyncTime * 1000);
|
|
881
|
+
console.log(` Last Sync: ${colors.cyan}${lastSync.toLocaleString()}${colors.reset}`);
|
|
882
|
+
console.log(` Time Ago: ${this.timeAgo(syncMeta.lastSyncTime)}`);
|
|
883
|
+
} else {
|
|
884
|
+
console.log(` Last Sync: ${colors.yellow}Never${colors.reset}`);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
console.log('\n' + '─'.repeat(80));
|
|
888
|
+
console.log(`${colors.bright}Pending Changes${colors.reset}`);
|
|
889
|
+
console.log('─'.repeat(80));
|
|
890
|
+
console.log(` Episodes: ${colors.green}${syncMeta.pendingEpisodes}${colors.reset}`);
|
|
891
|
+
console.log(` Skills: ${colors.green}${syncMeta.pendingSkills}${colors.reset}`);
|
|
892
|
+
console.log(` Causal Edges: ${colors.green}${syncMeta.pendingCausalEdges}${colors.reset}`);
|
|
893
|
+
|
|
894
|
+
console.log('\n' + '─'.repeat(80));
|
|
895
|
+
console.log(`${colors.bright}Connected Servers${colors.reset}`);
|
|
896
|
+
console.log('─'.repeat(80));
|
|
897
|
+
|
|
898
|
+
if (syncMeta.servers.length === 0) {
|
|
899
|
+
console.log(` ${colors.yellow}No servers connected${colors.reset}`);
|
|
900
|
+
} else {
|
|
901
|
+
syncMeta.servers.forEach((server: any) => {
|
|
902
|
+
console.log(` ${colors.cyan}${server.host}:${server.port}${colors.reset}`);
|
|
903
|
+
console.log(` Status: ${server.connected ? colors.green + 'Connected' : colors.red + 'Disconnected'}${colors.reset}`);
|
|
904
|
+
console.log(` Last Seen: ${new Date(server.lastSeen * 1000).toLocaleString()}`);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
console.log('═'.repeat(80));
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
private generateAuthToken(): string {
|
|
912
|
+
// Generate a random 32-character token
|
|
913
|
+
return Array.from({ length: 32 }, () =>
|
|
914
|
+
Math.floor(Math.random() * 16).toString(16)
|
|
915
|
+
).join('');
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
private getPendingChanges(incremental?: boolean, filter?: string): {
|
|
919
|
+
episodes: number;
|
|
920
|
+
skills: number;
|
|
921
|
+
causalEdges: number;
|
|
922
|
+
totalSize: number;
|
|
923
|
+
} {
|
|
924
|
+
// Mock implementation - would query sync metadata table
|
|
925
|
+
return {
|
|
926
|
+
episodes: 10,
|
|
927
|
+
skills: 3,
|
|
928
|
+
causalEdges: 5,
|
|
929
|
+
totalSize: 25600
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
private getSyncMetadata(): {
|
|
934
|
+
lastSyncTime: number | null;
|
|
935
|
+
pendingEpisodes: number;
|
|
936
|
+
pendingSkills: number;
|
|
937
|
+
pendingCausalEdges: number;
|
|
938
|
+
servers: Array<{
|
|
939
|
+
host: string;
|
|
940
|
+
port: number;
|
|
941
|
+
connected: boolean;
|
|
942
|
+
lastSeen: number;
|
|
943
|
+
}>;
|
|
944
|
+
} {
|
|
945
|
+
// Mock implementation - would query sync metadata table
|
|
946
|
+
return {
|
|
947
|
+
lastSyncTime: null,
|
|
948
|
+
pendingEpisodes: 10,
|
|
949
|
+
pendingSkills: 3,
|
|
950
|
+
pendingCausalEdges: 5,
|
|
951
|
+
servers: []
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
private timeAgo(timestamp: number): string {
|
|
956
|
+
const now = Math.floor(Date.now() / 1000);
|
|
957
|
+
const diff = now - timestamp;
|
|
958
|
+
|
|
959
|
+
if (diff < 60) return `${diff} seconds ago`;
|
|
960
|
+
if (diff < 3600) return `${Math.floor(diff / 60)} minutes ago`;
|
|
961
|
+
if (diff < 86400) return `${Math.floor(diff / 3600)} hours ago`;
|
|
962
|
+
return `${Math.floor(diff / 86400)} days ago`;
|
|
963
|
+
}
|
|
964
|
+
|
|
675
965
|
// ============================================================================
|
|
676
966
|
// Database Commands
|
|
677
967
|
// ============================================================================
|
|
@@ -736,6 +1026,27 @@ async function main() {
|
|
|
736
1026
|
return;
|
|
737
1027
|
}
|
|
738
1028
|
|
|
1029
|
+
// Handle vector search commands (no CLI initialization needed)
|
|
1030
|
+
if (command === 'vector-search') {
|
|
1031
|
+
await handleVectorSearchCommand(args.slice(1));
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
if (command === 'export') {
|
|
1036
|
+
await handleExportCommand(args.slice(1));
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
if (command === 'import') {
|
|
1041
|
+
await handleImportCommand(args.slice(1));
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
if (command === 'stats') {
|
|
1046
|
+
await handleStatsCommand(args.slice(1));
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
739
1050
|
const cli = new AgentDBCLI();
|
|
740
1051
|
const dbPath = process.env.AGENTDB_PATH || './agentdb.db';
|
|
741
1052
|
|
|
@@ -756,6 +1067,8 @@ async function main() {
|
|
|
756
1067
|
await handleSkillCommands(cli, subcommand, args.slice(2));
|
|
757
1068
|
} else if (command === 'db') {
|
|
758
1069
|
await handleDbCommands(cli, subcommand, args.slice(2));
|
|
1070
|
+
} else if (command === 'sync') {
|
|
1071
|
+
await handleSyncCommands(cli, subcommand, args.slice(2));
|
|
759
1072
|
} else if (command === 'query') {
|
|
760
1073
|
await handleQueryCommand(cli, args.slice(1));
|
|
761
1074
|
} else if (command === 'store-pattern') {
|
|
@@ -779,42 +1092,79 @@ async function main() {
|
|
|
779
1092
|
|
|
780
1093
|
// Init command handler
|
|
781
1094
|
async function handleInitCommand(args: string[]) {
|
|
782
|
-
|
|
1095
|
+
// Parse arguments
|
|
1096
|
+
let dbPath = './agentdb.db';
|
|
1097
|
+
let dimension = 1536; // Default OpenAI ada-002
|
|
1098
|
+
let preset: 'small' | 'medium' | 'large' | null = null;
|
|
1099
|
+
let inMemory = false;
|
|
1100
|
+
|
|
1101
|
+
for (let i = 0; i < args.length; i++) {
|
|
1102
|
+
const arg = args[i];
|
|
1103
|
+
if (arg === '--dimension' && i + 1 < args.length) {
|
|
1104
|
+
dimension = parseInt(args[++i]);
|
|
1105
|
+
} else if (arg === '--preset' && i + 1 < args.length) {
|
|
1106
|
+
preset = args[++i] as 'small' | 'medium' | 'large';
|
|
1107
|
+
} else if (arg === '--in-memory') {
|
|
1108
|
+
inMemory = true;
|
|
1109
|
+
dbPath = ':memory:';
|
|
1110
|
+
} else if (!arg.startsWith('--')) {
|
|
1111
|
+
dbPath = arg;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// Apply preset configurations
|
|
1116
|
+
if (preset) {
|
|
1117
|
+
if (preset === 'small') {
|
|
1118
|
+
log.info('Using SMALL preset (<10K vectors)');
|
|
1119
|
+
} else if (preset === 'medium') {
|
|
1120
|
+
log.info('Using MEDIUM preset (10K-100K vectors)');
|
|
1121
|
+
} else if (preset === 'large') {
|
|
1122
|
+
log.info('Using LARGE preset (>100K vectors)');
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
783
1125
|
|
|
784
1126
|
log.info(`Initializing AgentDB at: ${dbPath}`);
|
|
1127
|
+
log.info(`Embedding dimension: ${dimension}`);
|
|
1128
|
+
if (inMemory) {
|
|
1129
|
+
log.info('Using in-memory database (data will not persist)');
|
|
1130
|
+
}
|
|
785
1131
|
|
|
786
1132
|
// Check if database already exists
|
|
787
|
-
if (fs.existsSync(dbPath)) {
|
|
1133
|
+
if (!inMemory && fs.existsSync(dbPath)) {
|
|
788
1134
|
log.warning(`Database already exists at ${dbPath}`);
|
|
789
1135
|
log.info('Use a different path or remove the existing file to reinitialize');
|
|
790
1136
|
return;
|
|
791
1137
|
}
|
|
792
1138
|
|
|
793
1139
|
// Create parent directories if needed
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
1140
|
+
if (!inMemory) {
|
|
1141
|
+
const parentDir = path.dirname(dbPath);
|
|
1142
|
+
if (parentDir !== '.' && !fs.existsSync(parentDir)) {
|
|
1143
|
+
log.info(`Creating directory: ${parentDir}`);
|
|
1144
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
1145
|
+
}
|
|
798
1146
|
}
|
|
799
1147
|
|
|
800
1148
|
// Create new database with schemas
|
|
801
1149
|
const cli = new AgentDBCLI();
|
|
802
1150
|
await cli.initialize(dbPath);
|
|
803
1151
|
|
|
804
|
-
// CRITICAL: Save the database to disk
|
|
1152
|
+
// CRITICAL: Save the database to disk (unless in-memory)
|
|
805
1153
|
// sql.js keeps everything in memory until explicitly saved
|
|
806
|
-
if (
|
|
807
|
-
cli.db.save
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
1154
|
+
if (!inMemory) {
|
|
1155
|
+
if (cli.db && typeof cli.db.save === 'function') {
|
|
1156
|
+
cli.db.save();
|
|
1157
|
+
} else if (cli.db && typeof cli.db.close === 'function') {
|
|
1158
|
+
// close() calls save() internally
|
|
1159
|
+
cli.db.close();
|
|
1160
|
+
}
|
|
812
1161
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1162
|
+
// Verify database file was created
|
|
1163
|
+
if (!fs.existsSync(dbPath)) {
|
|
1164
|
+
log.error(`Failed to create database file at ${dbPath}`);
|
|
1165
|
+
log.error('The database may be in memory only');
|
|
1166
|
+
process.exit(1);
|
|
1167
|
+
}
|
|
818
1168
|
}
|
|
819
1169
|
|
|
820
1170
|
// Verify database has tables
|
|
@@ -982,12 +1332,59 @@ async function handleReflexionCommands(cli: AgentDBCLI, subcommand: string, args
|
|
|
982
1332
|
tokensUsed: args[8] ? parseInt(args[8]) : undefined
|
|
983
1333
|
});
|
|
984
1334
|
} else if (subcommand === 'retrieve') {
|
|
1335
|
+
// Parse retrieve command with new flags
|
|
1336
|
+
let task = args[0];
|
|
1337
|
+
let k: number | undefined = undefined;
|
|
1338
|
+
let minReward: number | undefined = undefined;
|
|
1339
|
+
let onlyFailures: boolean | undefined = undefined;
|
|
1340
|
+
let onlySuccesses: boolean | undefined = undefined;
|
|
1341
|
+
let synthesizeContext = false;
|
|
1342
|
+
let filters: any = {};
|
|
1343
|
+
|
|
1344
|
+
for (let i = 1; i < args.length; i++) {
|
|
1345
|
+
const arg = args[i];
|
|
1346
|
+
if (arg === '--k' && i + 1 < args.length) {
|
|
1347
|
+
k = parseInt(args[++i]);
|
|
1348
|
+
} else if (arg === '--min-reward' && i + 1 < args.length) {
|
|
1349
|
+
minReward = parseFloat(args[++i]);
|
|
1350
|
+
} else if (arg === '--only-failures') {
|
|
1351
|
+
onlyFailures = true;
|
|
1352
|
+
} else if (arg === '--only-successes') {
|
|
1353
|
+
onlySuccesses = true;
|
|
1354
|
+
} else if (arg === '--synthesize-context') {
|
|
1355
|
+
synthesizeContext = true;
|
|
1356
|
+
} else if (arg === '--filters' && i + 1 < args.length) {
|
|
1357
|
+
try {
|
|
1358
|
+
filters = JSON.parse(args[++i]);
|
|
1359
|
+
} catch (error) {
|
|
1360
|
+
log.error(`Invalid JSON in --filters parameter: ${(error as Error).message}`);
|
|
1361
|
+
process.exit(1);
|
|
1362
|
+
}
|
|
1363
|
+
} else if (!arg.startsWith('--') && k === undefined) {
|
|
1364
|
+
// Legacy positional argument parsing
|
|
1365
|
+
k = parseInt(arg);
|
|
1366
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('--')) {
|
|
1367
|
+
minReward = parseFloat(args[++i]);
|
|
1368
|
+
}
|
|
1369
|
+
if (i + 1 < args.length && args[i + 1] === 'true') {
|
|
1370
|
+
onlyFailures = true;
|
|
1371
|
+
i++;
|
|
1372
|
+
}
|
|
1373
|
+
if (i + 1 < args.length && args[i + 1] === 'true') {
|
|
1374
|
+
onlySuccesses = true;
|
|
1375
|
+
i++;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
985
1380
|
await cli.reflexionRetrieve({
|
|
986
|
-
task
|
|
987
|
-
k
|
|
988
|
-
minReward
|
|
989
|
-
onlyFailures
|
|
990
|
-
onlySuccesses
|
|
1381
|
+
task,
|
|
1382
|
+
k,
|
|
1383
|
+
minReward,
|
|
1384
|
+
onlyFailures,
|
|
1385
|
+
onlySuccesses,
|
|
1386
|
+
synthesizeContext,
|
|
1387
|
+
filters: Object.keys(filters).length > 0 ? filters : undefined
|
|
991
1388
|
});
|
|
992
1389
|
} else if (subcommand === 'critique-summary') {
|
|
993
1390
|
await cli.reflexionGetCritiqueSummary({
|
|
@@ -1045,7 +1442,110 @@ async function handleDbCommands(cli: AgentDBCLI, subcommand: string, args: strin
|
|
|
1045
1442
|
}
|
|
1046
1443
|
}
|
|
1047
1444
|
|
|
1048
|
-
|
|
1445
|
+
async function handleSyncCommands(cli: AgentDBCLI, subcommand: string, args: string[]) {
|
|
1446
|
+
if (subcommand === 'start-server') {
|
|
1447
|
+
// Parse options
|
|
1448
|
+
let port: number | undefined;
|
|
1449
|
+
let cert: string | undefined;
|
|
1450
|
+
let key: string | undefined;
|
|
1451
|
+
let authToken: string | undefined;
|
|
1452
|
+
|
|
1453
|
+
for (let i = 0; i < args.length; i++) {
|
|
1454
|
+
if (args[i] === '--port' && i + 1 < args.length) {
|
|
1455
|
+
port = parseInt(args[++i]);
|
|
1456
|
+
} else if (args[i] === '--cert' && i + 1 < args.length) {
|
|
1457
|
+
cert = args[++i];
|
|
1458
|
+
} else if (args[i] === '--key' && i + 1 < args.length) {
|
|
1459
|
+
key = args[++i];
|
|
1460
|
+
} else if (args[i] === '--auth-token' && i + 1 < args.length) {
|
|
1461
|
+
authToken = args[++i];
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
await cli.quicStartServer({ port, cert, key, authToken });
|
|
1466
|
+
} else if (subcommand === 'connect') {
|
|
1467
|
+
// Parse host and port
|
|
1468
|
+
const host = args[0];
|
|
1469
|
+
const port = parseInt(args[1]);
|
|
1470
|
+
|
|
1471
|
+
if (!host || !port) {
|
|
1472
|
+
log.error('Missing required arguments: host and port');
|
|
1473
|
+
log.info('Usage: agentdb sync connect <host> <port> [--auth-token <token>] [--cert <path>]');
|
|
1474
|
+
process.exit(1);
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
let authToken: string | undefined;
|
|
1478
|
+
let cert: string | undefined;
|
|
1479
|
+
|
|
1480
|
+
for (let i = 2; i < args.length; i++) {
|
|
1481
|
+
if (args[i] === '--auth-token' && i + 1 < args.length) {
|
|
1482
|
+
authToken = args[++i];
|
|
1483
|
+
} else if (args[i] === '--cert' && i + 1 < args.length) {
|
|
1484
|
+
cert = args[++i];
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
await cli.quicConnect({ host, port, authToken, cert });
|
|
1489
|
+
} else if (subcommand === 'push') {
|
|
1490
|
+
// Parse options
|
|
1491
|
+
let server: string | undefined;
|
|
1492
|
+
let incremental = false;
|
|
1493
|
+
let filter: string | undefined;
|
|
1494
|
+
|
|
1495
|
+
for (let i = 0; i < args.length; i++) {
|
|
1496
|
+
if (args[i] === '--server' && i + 1 < args.length) {
|
|
1497
|
+
server = args[++i];
|
|
1498
|
+
} else if (args[i] === '--incremental') {
|
|
1499
|
+
incremental = true;
|
|
1500
|
+
} else if (args[i] === '--filter' && i + 1 < args.length) {
|
|
1501
|
+
filter = args[++i];
|
|
1502
|
+
} else if (!args[i].startsWith('--') && !server) {
|
|
1503
|
+
server = args[i];
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
if (!server) {
|
|
1508
|
+
log.error('Missing required --server parameter');
|
|
1509
|
+
log.info('Usage: agentdb sync push --server <host:port> [--incremental] [--filter <pattern>]');
|
|
1510
|
+
process.exit(1);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
await cli.quicPush({ server, incremental, filter });
|
|
1514
|
+
} else if (subcommand === 'pull') {
|
|
1515
|
+
// Parse options
|
|
1516
|
+
let server: string | undefined;
|
|
1517
|
+
let incremental = false;
|
|
1518
|
+
let filter: string | undefined;
|
|
1519
|
+
|
|
1520
|
+
for (let i = 0; i < args.length; i++) {
|
|
1521
|
+
if (args[i] === '--server' && i + 1 < args.length) {
|
|
1522
|
+
server = args[++i];
|
|
1523
|
+
} else if (args[i] === '--incremental') {
|
|
1524
|
+
incremental = true;
|
|
1525
|
+
} else if (args[i] === '--filter' && i + 1 < args.length) {
|
|
1526
|
+
filter = args[++i];
|
|
1527
|
+
} else if (!args[i].startsWith('--') && !server) {
|
|
1528
|
+
server = args[i];
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
if (!server) {
|
|
1533
|
+
log.error('Missing required --server parameter');
|
|
1534
|
+
log.info('Usage: agentdb sync pull --server <host:port> [--incremental] [--filter <pattern>]');
|
|
1535
|
+
process.exit(1);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
await cli.quicPull({ server, incremental, filter });
|
|
1539
|
+
} else if (subcommand === 'status') {
|
|
1540
|
+
await cli.quicStatus();
|
|
1541
|
+
} else {
|
|
1542
|
+
log.error(`Unknown sync subcommand: ${subcommand}`);
|
|
1543
|
+
log.info('Available subcommands: start-server, connect, push, pull, status');
|
|
1544
|
+
printHelp();
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
// Query command - semantic search across reflexion episodes with context synthesis
|
|
1049
1549
|
async function handleQueryCommand(cli: AgentDBCLI, args: string[]) {
|
|
1050
1550
|
// Parse command-line arguments
|
|
1051
1551
|
let domain = '';
|
|
@@ -1053,6 +1553,8 @@ async function handleQueryCommand(cli: AgentDBCLI, args: string[]) {
|
|
|
1053
1553
|
let k = 5;
|
|
1054
1554
|
let minConfidence = 0.0;
|
|
1055
1555
|
let format = 'json';
|
|
1556
|
+
let synthesizeContext = false;
|
|
1557
|
+
let filters: any = {};
|
|
1056
1558
|
|
|
1057
1559
|
for (let i = 0; i < args.length; i++) {
|
|
1058
1560
|
if (args[i] === '--domain' && i + 1 < args.length) {
|
|
@@ -1065,6 +1567,15 @@ async function handleQueryCommand(cli: AgentDBCLI, args: string[]) {
|
|
|
1065
1567
|
minConfidence = parseFloat(args[++i]);
|
|
1066
1568
|
} else if (args[i] === '--format' && i + 1 < args.length) {
|
|
1067
1569
|
format = args[++i];
|
|
1570
|
+
} else if (args[i] === '--synthesize-context') {
|
|
1571
|
+
synthesizeContext = true;
|
|
1572
|
+
} else if (args[i] === '--filters' && i + 1 < args.length) {
|
|
1573
|
+
try {
|
|
1574
|
+
filters = JSON.parse(args[++i]);
|
|
1575
|
+
} catch (error) {
|
|
1576
|
+
log.error(`Invalid JSON in --filters parameter: ${(error as Error).message}`);
|
|
1577
|
+
process.exit(1);
|
|
1578
|
+
}
|
|
1068
1579
|
}
|
|
1069
1580
|
}
|
|
1070
1581
|
|
|
@@ -1073,18 +1584,77 @@ async function handleQueryCommand(cli: AgentDBCLI, args: string[]) {
|
|
|
1073
1584
|
process.exit(1);
|
|
1074
1585
|
}
|
|
1075
1586
|
|
|
1587
|
+
// Validate filters if provided
|
|
1588
|
+
if (Object.keys(filters).length > 0) {
|
|
1589
|
+
const validation = MetadataFilter.validate(filters);
|
|
1590
|
+
if (!validation.valid) {
|
|
1591
|
+
log.error('Invalid filters:');
|
|
1592
|
+
validation.errors.forEach(err => log.error(` - ${err}`));
|
|
1593
|
+
process.exit(1);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1076
1597
|
// Use reflexionRetrieveJson method for JSON output
|
|
1077
|
-
|
|
1598
|
+
let results = await cli.reflexionRetrieveJson({
|
|
1078
1599
|
task: query,
|
|
1079
1600
|
k,
|
|
1080
1601
|
minReward: minConfidence,
|
|
1081
1602
|
onlySuccesses: domain === 'successful-edits'
|
|
1082
1603
|
});
|
|
1083
1604
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1605
|
+
// Apply metadata filters if provided
|
|
1606
|
+
if (Object.keys(filters).length > 0) {
|
|
1607
|
+
results = MetadataFilter.apply(results, filters);
|
|
1608
|
+
log.info(`Filtered to ${results.length} results matching metadata criteria`);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
// Synthesize context if requested
|
|
1612
|
+
if (synthesizeContext && results.length > 0) {
|
|
1613
|
+
const context = ContextSynthesizer.synthesize(results.map((r: any) => ({
|
|
1614
|
+
task: r.task,
|
|
1615
|
+
reward: r.reward,
|
|
1616
|
+
success: r.success,
|
|
1617
|
+
critique: r.critique,
|
|
1618
|
+
input: r.input,
|
|
1619
|
+
output: r.output,
|
|
1620
|
+
similarity: r.similarity
|
|
1621
|
+
})));
|
|
1622
|
+
|
|
1623
|
+
if (format === 'json') {
|
|
1624
|
+
console.log(JSON.stringify({ results, synthesizedContext: context }, null, 2));
|
|
1625
|
+
} else {
|
|
1626
|
+
console.log('\n' + '═'.repeat(80));
|
|
1627
|
+
console.log('SYNTHESIZED CONTEXT');
|
|
1628
|
+
console.log('═'.repeat(80));
|
|
1629
|
+
console.log(`\n${context.summary}\n`);
|
|
1630
|
+
|
|
1631
|
+
if (context.patterns.length > 0) {
|
|
1632
|
+
console.log('Common Patterns:');
|
|
1633
|
+
context.patterns.forEach(p => console.log(` • ${p}`));
|
|
1634
|
+
console.log('');
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
if (context.keyInsights.length > 0) {
|
|
1638
|
+
console.log('Key Insights:');
|
|
1639
|
+
context.keyInsights.forEach(i => console.log(` • ${i}`));
|
|
1640
|
+
console.log('');
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
if (context.recommendations.length > 0) {
|
|
1644
|
+
console.log('Recommendations:');
|
|
1645
|
+
context.recommendations.forEach((r, i) => console.log(` ${i + 1}. ${r}`));
|
|
1646
|
+
console.log('');
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
console.log('═'.repeat(80));
|
|
1650
|
+
console.log(`\nMatched ${results.length} memories\n`);
|
|
1651
|
+
}
|
|
1086
1652
|
} else {
|
|
1087
|
-
|
|
1653
|
+
if (format === 'json') {
|
|
1654
|
+
console.log(JSON.stringify(results, null, 2));
|
|
1655
|
+
} else {
|
|
1656
|
+
console.log(results);
|
|
1657
|
+
}
|
|
1088
1658
|
}
|
|
1089
1659
|
}
|
|
1090
1660
|
|
|
@@ -1226,6 +1796,399 @@ async function handleOptimizeMemoryCommand(cli: AgentDBCLI, args: string[]) {
|
|
|
1226
1796
|
console.log(JSON.stringify({ success: true, message: 'Memory optimization completed' }, null, 2));
|
|
1227
1797
|
}
|
|
1228
1798
|
|
|
1799
|
+
// Vector-search command - direct vector similarity search with MMR diversity ranking
|
|
1800
|
+
async function handleVectorSearchCommand(args: string[]) {
|
|
1801
|
+
// Parse arguments
|
|
1802
|
+
let dbPath = './agentdb.db';
|
|
1803
|
+
let vector: number[] = [];
|
|
1804
|
+
let k = 10;
|
|
1805
|
+
let threshold = 0.0;
|
|
1806
|
+
let metric = 'cosine';
|
|
1807
|
+
let format = 'json';
|
|
1808
|
+
let verbose = false;
|
|
1809
|
+
let useMmr = false;
|
|
1810
|
+
let mmrLambda = 0.5;
|
|
1811
|
+
|
|
1812
|
+
for (let i = 0; i < args.length; i++) {
|
|
1813
|
+
const arg = args[i];
|
|
1814
|
+
if (arg === '-k' && i + 1 < args.length) {
|
|
1815
|
+
k = parseInt(args[++i]);
|
|
1816
|
+
} else if (arg === '-t' && i + 1 < args.length) {
|
|
1817
|
+
threshold = parseFloat(args[++i]);
|
|
1818
|
+
} else if (arg === '-m' && i + 1 < args.length) {
|
|
1819
|
+
metric = args[++i];
|
|
1820
|
+
} else if (arg === '-f' && i + 1 < args.length) {
|
|
1821
|
+
format = args[++i];
|
|
1822
|
+
} else if (arg === '-v' || arg === '--verbose') {
|
|
1823
|
+
verbose = true;
|
|
1824
|
+
} else if (arg === '--mmr') {
|
|
1825
|
+
useMmr = true;
|
|
1826
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1827
|
+
mmrLambda = parseFloat(args[++i]);
|
|
1828
|
+
}
|
|
1829
|
+
} else if (!dbPath.endsWith('.db') && !arg.startsWith('[')) {
|
|
1830
|
+
dbPath = arg;
|
|
1831
|
+
} else if (arg.startsWith('[') || (!isNaN(parseFloat(arg)))) {
|
|
1832
|
+
// Parse vector - either JSON array or space-separated numbers
|
|
1833
|
+
try {
|
|
1834
|
+
if (arg.startsWith('[')) {
|
|
1835
|
+
vector = JSON.parse(arg);
|
|
1836
|
+
} else {
|
|
1837
|
+
// Collect space-separated numbers
|
|
1838
|
+
while (i < args.length && !isNaN(parseFloat(args[i]))) {
|
|
1839
|
+
vector.push(parseFloat(args[i++]));
|
|
1840
|
+
}
|
|
1841
|
+
i--; // Back up one since loop will increment
|
|
1842
|
+
}
|
|
1843
|
+
} catch (e) {
|
|
1844
|
+
log.error('Invalid vector format. Use JSON array: "[0.1,0.2,0.3]" or space-separated: "0.1 0.2 0.3"');
|
|
1845
|
+
process.exit(1);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
if (vector.length === 0) {
|
|
1851
|
+
log.error('Missing required vector parameter');
|
|
1852
|
+
log.info('Usage: agentdb vector-search <db-path> <vector> [-k 10] [-t 0.75] [-m cosine] [-f json] [-v] [--mmr [lambda]]');
|
|
1853
|
+
process.exit(1);
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
if (useMmr) {
|
|
1857
|
+
log.info(`Using MMR diversity ranking (λ=${mmrLambda})`);
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
// Initialize database
|
|
1861
|
+
const cli = new AgentDBCLI();
|
|
1862
|
+
await cli.initialize(dbPath);
|
|
1863
|
+
|
|
1864
|
+
// Perform vector search using reflexion's retrieveRelevant (which uses embeddings)
|
|
1865
|
+
// We'll need to search episode_embeddings table directly
|
|
1866
|
+
const query = `
|
|
1867
|
+
SELECT
|
|
1868
|
+
e.id,
|
|
1869
|
+
e.session_id,
|
|
1870
|
+
e.task,
|
|
1871
|
+
e.reward,
|
|
1872
|
+
e.success,
|
|
1873
|
+
ee.embedding
|
|
1874
|
+
FROM episodes e
|
|
1875
|
+
JOIN episode_embeddings ee ON e.id = ee.episode_id
|
|
1876
|
+
LIMIT ?
|
|
1877
|
+
`;
|
|
1878
|
+
|
|
1879
|
+
const results = cli.db.prepare(query).all(k * 10); // Get more for filtering
|
|
1880
|
+
|
|
1881
|
+
// Calculate similarities
|
|
1882
|
+
let scored = results.map((row: any) => {
|
|
1883
|
+
const embedding = new Float32Array(row.embedding);
|
|
1884
|
+
const similarity = calculateSimilarity(vector, Array.from(embedding), metric);
|
|
1885
|
+
return {
|
|
1886
|
+
id: row.id,
|
|
1887
|
+
session_id: row.session_id,
|
|
1888
|
+
task: row.task,
|
|
1889
|
+
reward: row.reward,
|
|
1890
|
+
success: row.success,
|
|
1891
|
+
similarity,
|
|
1892
|
+
embedding: Array.from(embedding)
|
|
1893
|
+
};
|
|
1894
|
+
}).filter(r => r.similarity >= threshold)
|
|
1895
|
+
.sort((a, b) => b.similarity - a.similarity);
|
|
1896
|
+
|
|
1897
|
+
// Apply MMR diversity ranking if requested
|
|
1898
|
+
if (useMmr && scored.length > k) {
|
|
1899
|
+
scored = MMRDiversityRanker.selectDiverse(scored, vector, {
|
|
1900
|
+
lambda: mmrLambda,
|
|
1901
|
+
k,
|
|
1902
|
+
metric: metric as 'cosine' | 'euclidean' | 'dot'
|
|
1903
|
+
});
|
|
1904
|
+
} else {
|
|
1905
|
+
scored = scored.slice(0, k);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// Remove embedding from output
|
|
1909
|
+
const output = scored.map(({ embedding, ...rest }) => rest);
|
|
1910
|
+
|
|
1911
|
+
if (format === 'json') {
|
|
1912
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1913
|
+
} else {
|
|
1914
|
+
console.log(`Found ${output.length} results:`);
|
|
1915
|
+
output.forEach((r, i) => {
|
|
1916
|
+
console.log(`${i + 1}. [${r.id}] ${r.task} (similarity: ${r.similarity.toFixed(4)})`);
|
|
1917
|
+
if (verbose) {
|
|
1918
|
+
console.log(` Session: ${r.session_id}, Reward: ${r.reward}, Success: ${r.success}`);
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
// Helper function to calculate similarity
|
|
1925
|
+
function calculateSimilarity(v1: number[], v2: number[], metric: string): number {
|
|
1926
|
+
if (v1.length !== v2.length) {
|
|
1927
|
+
throw new Error(`Vector dimension mismatch: ${v1.length} vs ${v2.length}`);
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
if (metric === 'cosine') {
|
|
1931
|
+
let dot = 0, mag1 = 0, mag2 = 0;
|
|
1932
|
+
for (let i = 0; i < v1.length; i++) {
|
|
1933
|
+
dot += v1[i] * v2[i];
|
|
1934
|
+
mag1 += v1[i] * v1[i];
|
|
1935
|
+
mag2 += v2[i] * v2[i];
|
|
1936
|
+
}
|
|
1937
|
+
return dot / (Math.sqrt(mag1) * Math.sqrt(mag2));
|
|
1938
|
+
} else if (metric === 'euclidean') {
|
|
1939
|
+
let sum = 0;
|
|
1940
|
+
for (let i = 0; i < v1.length; i++) {
|
|
1941
|
+
const diff = v1[i] - v2[i];
|
|
1942
|
+
sum += diff * diff;
|
|
1943
|
+
}
|
|
1944
|
+
return 1 / (1 + Math.sqrt(sum)); // Normalize to 0-1 range
|
|
1945
|
+
} else if (metric === 'dot') {
|
|
1946
|
+
let dot = 0;
|
|
1947
|
+
for (let i = 0; i < v1.length; i++) {
|
|
1948
|
+
dot += v1[i] * v2[i];
|
|
1949
|
+
}
|
|
1950
|
+
return dot;
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
return 0;
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
// Export command - export vectors to JSON with optional compression
|
|
1957
|
+
async function handleExportCommand(args: string[]) {
|
|
1958
|
+
let dbPath = './agentdb.db';
|
|
1959
|
+
let outputPath = './agentdb-export.json';
|
|
1960
|
+
let compress = false;
|
|
1961
|
+
|
|
1962
|
+
// Parse arguments
|
|
1963
|
+
for (let i = 0; i < args.length; i++) {
|
|
1964
|
+
const arg = args[i];
|
|
1965
|
+
if (arg === '--compress') {
|
|
1966
|
+
compress = true;
|
|
1967
|
+
} else if (arg === '--output' && i + 1 < args.length) {
|
|
1968
|
+
outputPath = args[++i];
|
|
1969
|
+
} else if (!arg.startsWith('--')) {
|
|
1970
|
+
if (dbPath === './agentdb.db') {
|
|
1971
|
+
dbPath = arg;
|
|
1972
|
+
} else if (outputPath === './agentdb-export.json') {
|
|
1973
|
+
outputPath = arg;
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
// Add .gz extension if compressing and not already present
|
|
1979
|
+
if (compress && !outputPath.endsWith('.gz')) {
|
|
1980
|
+
outputPath += '.gz';
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
log.info(`Exporting vectors from: ${dbPath}`);
|
|
1984
|
+
if (compress) {
|
|
1985
|
+
log.info('Compression: enabled');
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
const cli = new AgentDBCLI();
|
|
1989
|
+
await cli.initialize(dbPath);
|
|
1990
|
+
|
|
1991
|
+
// Export all episodes with embeddings
|
|
1992
|
+
const query = `
|
|
1993
|
+
SELECT
|
|
1994
|
+
e.*,
|
|
1995
|
+
ee.embedding
|
|
1996
|
+
FROM episodes e
|
|
1997
|
+
LEFT JOIN episode_embeddings ee ON e.id = ee.episode_id
|
|
1998
|
+
`;
|
|
1999
|
+
|
|
2000
|
+
const results = cli.db.prepare(query).all();
|
|
2001
|
+
|
|
2002
|
+
const jsonData = JSON.stringify(results, null, 2);
|
|
2003
|
+
|
|
2004
|
+
try {
|
|
2005
|
+
if (compress) {
|
|
2006
|
+
// Compress with gzip
|
|
2007
|
+
const compressed = zlib.gzipSync(jsonData);
|
|
2008
|
+
fs.writeFileSync(outputPath, compressed);
|
|
2009
|
+
const originalSize = Buffer.byteLength(jsonData);
|
|
2010
|
+
const compressedSize = compressed.length;
|
|
2011
|
+
const ratio = ((1 - compressedSize / originalSize) * 100).toFixed(1);
|
|
2012
|
+
log.success(`Exported ${results.length} episodes to ${outputPath}`);
|
|
2013
|
+
log.info(`Original size: ${(originalSize / 1024).toFixed(2)} KB`);
|
|
2014
|
+
log.info(`Compressed size: ${(compressedSize / 1024).toFixed(2)} KB (${ratio}% reduction)`);
|
|
2015
|
+
} else {
|
|
2016
|
+
fs.writeFileSync(outputPath, jsonData);
|
|
2017
|
+
log.success(`Exported ${results.length} episodes to ${outputPath}`);
|
|
2018
|
+
}
|
|
2019
|
+
} catch (error) {
|
|
2020
|
+
log.error(`Failed to export: ${(error as Error).message}`);
|
|
2021
|
+
process.exit(1);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
// Import command - import vectors from JSON with optional decompression
|
|
2026
|
+
async function handleImportCommand(args: string[]) {
|
|
2027
|
+
let inputPath = '';
|
|
2028
|
+
let dbPath = './agentdb.db';
|
|
2029
|
+
let decompress = false;
|
|
2030
|
+
|
|
2031
|
+
// Parse arguments
|
|
2032
|
+
for (let i = 0; i < args.length; i++) {
|
|
2033
|
+
const arg = args[i];
|
|
2034
|
+
if (arg === '--decompress') {
|
|
2035
|
+
decompress = true;
|
|
2036
|
+
} else if (arg === '--db' && i + 1 < args.length) {
|
|
2037
|
+
dbPath = args[++i];
|
|
2038
|
+
} else if (!arg.startsWith('--')) {
|
|
2039
|
+
if (!inputPath) {
|
|
2040
|
+
inputPath = arg;
|
|
2041
|
+
} else if (dbPath === './agentdb.db') {
|
|
2042
|
+
dbPath = arg;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
// Auto-detect compression from .gz extension
|
|
2048
|
+
if (inputPath.endsWith('.gz')) {
|
|
2049
|
+
decompress = true;
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
if (!inputPath) {
|
|
2053
|
+
log.error('Missing required input file');
|
|
2054
|
+
log.info('Usage: agentdb import <input-file.json> [db-path] [--decompress]');
|
|
2055
|
+
process.exit(1);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
log.info(`Importing vectors from: ${inputPath}`);
|
|
2059
|
+
if (decompress) {
|
|
2060
|
+
log.info('Decompression: enabled');
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
let data: any[];
|
|
2064
|
+
|
|
2065
|
+
try {
|
|
2066
|
+
if (decompress) {
|
|
2067
|
+
// Decompress with gunzip
|
|
2068
|
+
const compressed = fs.readFileSync(inputPath);
|
|
2069
|
+
const decompressed = zlib.gunzipSync(compressed);
|
|
2070
|
+
data = JSON.parse(decompressed.toString('utf-8'));
|
|
2071
|
+
log.info(`Decompressed ${(compressed.length / 1024).toFixed(2)} KB to ${(decompressed.length / 1024).toFixed(2)} KB`);
|
|
2072
|
+
} else {
|
|
2073
|
+
data = JSON.parse(fs.readFileSync(inputPath, 'utf-8'));
|
|
2074
|
+
}
|
|
2075
|
+
} catch (error) {
|
|
2076
|
+
log.error(`Failed to read/parse input file: ${(error as Error).message}`);
|
|
2077
|
+
process.exit(1);
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
const cli = new AgentDBCLI();
|
|
2081
|
+
await cli.initialize(dbPath);
|
|
2082
|
+
|
|
2083
|
+
let imported = 0;
|
|
2084
|
+
for (const item of data) {
|
|
2085
|
+
try {
|
|
2086
|
+
// Import episode
|
|
2087
|
+
const episodeQuery = `
|
|
2088
|
+
INSERT INTO episodes (session_id, task, input, output, critique, reward, success, latency_ms, tokens_used, tags, metadata)
|
|
2089
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2090
|
+
`;
|
|
2091
|
+
|
|
2092
|
+
const result = cli.db.prepare(episodeQuery).run(
|
|
2093
|
+
item.session_id,
|
|
2094
|
+
item.task,
|
|
2095
|
+
item.input,
|
|
2096
|
+
item.output,
|
|
2097
|
+
item.critique,
|
|
2098
|
+
item.reward,
|
|
2099
|
+
item.success,
|
|
2100
|
+
item.latency_ms,
|
|
2101
|
+
item.tokens_used,
|
|
2102
|
+
item.tags,
|
|
2103
|
+
item.metadata
|
|
2104
|
+
);
|
|
2105
|
+
|
|
2106
|
+
// Import embedding if exists
|
|
2107
|
+
if (item.embedding) {
|
|
2108
|
+
const embeddingQuery = `INSERT INTO episode_embeddings (episode_id, embedding) VALUES (?, ?)`;
|
|
2109
|
+
cli.db.prepare(embeddingQuery).run(result.lastInsertRowid, item.embedding);
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
imported++;
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
log.warning(`Failed to import item ${imported + 1}: ${(error as Error).message}`);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
// Save database
|
|
2119
|
+
if (cli.db && typeof cli.db.save === 'function') {
|
|
2120
|
+
cli.db.save();
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
log.success(`Imported ${imported} episodes`);
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
// Stats command - show database statistics
|
|
2127
|
+
async function handleStatsCommand(args: string[]) {
|
|
2128
|
+
const dbPath = args[0] || './agentdb.db';
|
|
2129
|
+
|
|
2130
|
+
log.info(`Getting statistics for: ${dbPath}`);
|
|
2131
|
+
|
|
2132
|
+
const cli = new AgentDBCLI();
|
|
2133
|
+
await cli.initialize(dbPath);
|
|
2134
|
+
|
|
2135
|
+
// Get counts (with fallback for missing tables)
|
|
2136
|
+
const episodeCount = cli.db.prepare('SELECT COUNT(*) as count FROM episodes').get()?.count || 0;
|
|
2137
|
+
const embeddingCount = cli.db.prepare('SELECT COUNT(*) as count FROM episode_embeddings').get()?.count || 0;
|
|
2138
|
+
|
|
2139
|
+
let skillCount = 0;
|
|
2140
|
+
try {
|
|
2141
|
+
skillCount = cli.db.prepare('SELECT COUNT(*) as count FROM skill_library').get()?.count || 0;
|
|
2142
|
+
} catch (e) {
|
|
2143
|
+
// skill_library table may not exist in older databases
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
let causalEdges = 0;
|
|
2147
|
+
try {
|
|
2148
|
+
causalEdges = cli.db.prepare('SELECT COUNT(*) as count FROM causal_edges').get()?.count || 0;
|
|
2149
|
+
} catch (e) {
|
|
2150
|
+
// causal_edges table may not exist in older databases
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
// Get database file size
|
|
2154
|
+
let dbSize = 0;
|
|
2155
|
+
if (dbPath !== ':memory:' && fs.existsSync(dbPath)) {
|
|
2156
|
+
dbSize = fs.statSync(dbPath).size;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
// Get average confidence
|
|
2160
|
+
const avgConfidence = cli.db.prepare('SELECT AVG(reward) as avg FROM episodes').get().avg || 0;
|
|
2161
|
+
|
|
2162
|
+
// Get domains
|
|
2163
|
+
const domains = cli.db.prepare(`
|
|
2164
|
+
SELECT task, COUNT(*) as count
|
|
2165
|
+
FROM episodes
|
|
2166
|
+
GROUP BY task
|
|
2167
|
+
ORDER BY count DESC
|
|
2168
|
+
LIMIT 5
|
|
2169
|
+
`).all();
|
|
2170
|
+
|
|
2171
|
+
console.log(`
|
|
2172
|
+
📊 AgentDB Statistics
|
|
2173
|
+
|
|
2174
|
+
Database: ${dbPath}
|
|
2175
|
+
Size: ${(dbSize / 1024).toFixed(2)} KB
|
|
2176
|
+
|
|
2177
|
+
📈 Counts:
|
|
2178
|
+
Episodes: ${episodeCount}
|
|
2179
|
+
Embeddings: ${embeddingCount}
|
|
2180
|
+
Skills: ${skillCount}
|
|
2181
|
+
Causal Edges: ${causalEdges}
|
|
2182
|
+
|
|
2183
|
+
📊 Metrics:
|
|
2184
|
+
Average Reward: ${avgConfidence.toFixed(3)}
|
|
2185
|
+
Embedding Coverage: ${episodeCount > 0 ? ((embeddingCount / episodeCount) * 100).toFixed(1) : 0}%
|
|
2186
|
+
|
|
2187
|
+
🏷️ Top Domains:
|
|
2188
|
+
${domains.map(d => ` • ${d.task}: ${d.count}`).join('\n')}
|
|
2189
|
+
`);
|
|
2190
|
+
}
|
|
2191
|
+
|
|
1229
2192
|
function printHelp() {
|
|
1230
2193
|
console.log(`
|
|
1231
2194
|
${colors.bright}${colors.cyan}█▀█ █▀▀ █▀▀ █▄░█ ▀█▀ █▀▄ █▄▄
|
|
@@ -1237,13 +2200,96 @@ ${colors.bright}USAGE:${colors.reset}
|
|
|
1237
2200
|
agentdb <command> <subcommand> [options]
|
|
1238
2201
|
|
|
1239
2202
|
${colors.bright}SETUP COMMANDS:${colors.reset}
|
|
1240
|
-
agentdb init [db-path]
|
|
2203
|
+
agentdb init [db-path] [--dimension 1536] [--preset small|medium|large] [--in-memory]
|
|
1241
2204
|
Initialize a new AgentDB database (default: ./agentdb.db)
|
|
2205
|
+
Options:
|
|
2206
|
+
--dimension <n> Vector dimension (default: 1536 for OpenAI, 768 for sentence-transformers)
|
|
2207
|
+
--preset <size> small (<10K), medium (10K-100K), large (>100K vectors)
|
|
2208
|
+
--in-memory Use temporary in-memory database (:memory:)
|
|
2209
|
+
|
|
2210
|
+
${colors.bright}VECTOR SEARCH COMMANDS:${colors.reset}
|
|
2211
|
+
agentdb vector-search <db-path> <vector> [-k 10] [-t 0.75] [-m cosine] [-f json] [-v] [--mmr [lambda]]
|
|
2212
|
+
Direct vector similarity search without text embeddings
|
|
2213
|
+
Arguments:
|
|
2214
|
+
<db-path> Database file path (or :memory:)
|
|
2215
|
+
<vector> Vector as JSON array [0.1,0.2,...] or space-separated numbers
|
|
2216
|
+
Options:
|
|
2217
|
+
-k <n> Number of results (default: 10)
|
|
2218
|
+
-t <threshold> Minimum similarity threshold (default: 0.0)
|
|
2219
|
+
-m <metric> Similarity metric: cosine|euclidean|dot (default: cosine)
|
|
2220
|
+
-f <format> Output format: json|table (default: json)
|
|
2221
|
+
-v Verbose mode with similarity scores
|
|
2222
|
+
--mmr [lambda] Enable MMR diversity ranking (lambda: 0-1, default: 0.5)
|
|
2223
|
+
0 = max diversity, 1 = max relevance
|
|
2224
|
+
Example: agentdb vector-search ./vectors.db "[0.1,0.2,0.3]" -k 10 -m cosine
|
|
2225
|
+
Example: agentdb vector-search ./vectors.db "[0.1,0.2,0.3]" --mmr 0.7
|
|
2226
|
+
|
|
2227
|
+
agentdb export <db-path> [output-file] [--compress]
|
|
2228
|
+
Export all vectors and episodes to JSON file
|
|
2229
|
+
Options:
|
|
2230
|
+
--compress Compress output with gzip (adds .gz extension)
|
|
2231
|
+
--output <file> Output file path
|
|
2232
|
+
Example: agentdb export ./agentdb.db ./backup.json
|
|
2233
|
+
Example: agentdb export ./agentdb.db --compress --output backup.json.gz
|
|
2234
|
+
|
|
2235
|
+
agentdb import <input-file> [db-path] [--decompress]
|
|
2236
|
+
Import vectors and episodes from JSON file
|
|
2237
|
+
Options:
|
|
2238
|
+
--decompress Decompress gzip input (auto-detected for .gz files)
|
|
2239
|
+
--db <path> Database file path
|
|
2240
|
+
Example: agentdb import ./backup.json ./new-db.db
|
|
2241
|
+
Example: agentdb import ./backup.json.gz --decompress
|
|
2242
|
+
|
|
2243
|
+
agentdb stats [db-path]
|
|
2244
|
+
Show detailed database statistics and metrics
|
|
2245
|
+
Example: agentdb stats ./agentdb.db
|
|
1242
2246
|
|
|
1243
2247
|
${colors.bright}MCP COMMANDS:${colors.reset}
|
|
1244
2248
|
agentdb mcp start
|
|
1245
2249
|
Start the MCP server for Claude Desktop integration
|
|
1246
2250
|
|
|
2251
|
+
${colors.bright}QUIC SYNC COMMANDS:${colors.reset}
|
|
2252
|
+
agentdb sync start-server [--port 4433] [--cert <path>] [--key <path>] [--auth-token <token>]
|
|
2253
|
+
Start a QUIC synchronization server for multi-agent coordination
|
|
2254
|
+
Options:
|
|
2255
|
+
--port <n> Server port (default: 4433)
|
|
2256
|
+
--cert <path> TLS certificate file path
|
|
2257
|
+
--key <path> TLS key file path
|
|
2258
|
+
--auth-token <token> Authentication token (auto-generated if not provided)
|
|
2259
|
+
Example: agentdb sync start-server --port 4433 --cert ./cert.pem --key ./key.pem
|
|
2260
|
+
|
|
2261
|
+
agentdb sync connect <host> <port> [--auth-token <token>] [--cert <path>]
|
|
2262
|
+
Connect to a remote QUIC sync server
|
|
2263
|
+
Arguments:
|
|
2264
|
+
<host> Remote server hostname or IP
|
|
2265
|
+
<port> Remote server port
|
|
2266
|
+
Options:
|
|
2267
|
+
--auth-token <token> Authentication token
|
|
2268
|
+
--cert <path> TLS certificate for verification
|
|
2269
|
+
Example: agentdb sync connect 192.168.1.100 4433 --auth-token abc123
|
|
2270
|
+
|
|
2271
|
+
agentdb sync push --server <host:port> [--incremental] [--filter <pattern>]
|
|
2272
|
+
Push local changes to remote server
|
|
2273
|
+
Options:
|
|
2274
|
+
--server <host:port> Remote server address (e.g., 192.168.1.100:4433)
|
|
2275
|
+
--incremental Only push changes since last sync
|
|
2276
|
+
--filter <pattern> Filter changes by pattern (e.g., "episodes", "skills")
|
|
2277
|
+
Example: agentdb sync push --server 192.168.1.100:4433 --incremental
|
|
2278
|
+
Example: agentdb sync push --server localhost:4433 --filter "episodes"
|
|
2279
|
+
|
|
2280
|
+
agentdb sync pull --server <host:port> [--incremental] [--filter <pattern>]
|
|
2281
|
+
Pull remote changes from server
|
|
2282
|
+
Options:
|
|
2283
|
+
--server <host:port> Remote server address (e.g., 192.168.1.100:4433)
|
|
2284
|
+
--incremental Only pull changes since last sync
|
|
2285
|
+
--filter <pattern> Filter changes by pattern (e.g., "skills", "causal_edges")
|
|
2286
|
+
Example: agentdb sync pull --server 192.168.1.100:4433 --incremental
|
|
2287
|
+
Example: agentdb sync pull --server localhost:4433 --filter "skills"
|
|
2288
|
+
|
|
2289
|
+
agentdb sync status
|
|
2290
|
+
Show synchronization status, pending changes, and connected servers
|
|
2291
|
+
Example: agentdb sync status
|
|
2292
|
+
|
|
1247
2293
|
${colors.bright}CAUSAL COMMANDS:${colors.reset}
|
|
1248
2294
|
agentdb causal add-edge <cause> <effect> <uplift> [confidence] [sample-size]
|
|
1249
2295
|
Add a causal edge manually
|
|
@@ -1278,8 +2324,17 @@ ${colors.bright}REFLEXION COMMANDS:${colors.reset}
|
|
|
1278
2324
|
agentdb reflexion store <session-id> <task> <reward> <success> [critique] [input] [output] [latency-ms] [tokens]
|
|
1279
2325
|
Store episode with self-critique
|
|
1280
2326
|
|
|
1281
|
-
agentdb reflexion retrieve <task> [k] [min-reward] [only-failures] [only-successes]
|
|
2327
|
+
agentdb reflexion retrieve <task> [--k <n>] [--min-reward <r>] [--only-failures] [--only-successes] [--synthesize-context] [--filters <json>]
|
|
1282
2328
|
Retrieve relevant past episodes
|
|
2329
|
+
Options:
|
|
2330
|
+
--k <n> Number of results (default: 5)
|
|
2331
|
+
--min-reward <r> Minimum reward threshold
|
|
2332
|
+
--only-failures Return only failed episodes
|
|
2333
|
+
--only-successes Return only successful episodes
|
|
2334
|
+
--synthesize-context Generate coherent summary with patterns and insights
|
|
2335
|
+
--filters <json> MongoDB-style metadata filters (e.g., '{"metadata.year":{"$gte":2024}}')
|
|
2336
|
+
Example: agentdb reflexion retrieve "authentication" --k 10 --synthesize-context
|
|
2337
|
+
Example: agentdb reflexion retrieve "bug-fix" --filters '{"success":true,"reward":{"$gte":0.8}}'
|
|
1283
2338
|
|
|
1284
2339
|
agentdb reflexion critique-summary <task> [only-failures]
|
|
1285
2340
|
Get aggregated critique lessons
|
|
@@ -1307,9 +2362,18 @@ ${colors.bright}DATABASE COMMANDS:${colors.reset}
|
|
|
1307
2362
|
Show database statistics
|
|
1308
2363
|
|
|
1309
2364
|
${colors.bright}HOOKS INTEGRATION COMMANDS:${colors.reset}
|
|
1310
|
-
agentdb query --
|
|
2365
|
+
agentdb query --query <query> [--domain <domain>] [--k <k>] [--min-confidence <conf>] [--format json] [--synthesize-context] [--filters <json>]
|
|
1311
2366
|
Semantic search across stored episodes and patterns
|
|
1312
|
-
|
|
2367
|
+
Options:
|
|
2368
|
+
--query <q> Query string (required)
|
|
2369
|
+
--domain <d> Domain filter (e.g., "successful-edits")
|
|
2370
|
+
--k <n> Number of results (default: 5)
|
|
2371
|
+
--min-confidence <c> Minimum confidence threshold (default: 0.0)
|
|
2372
|
+
--format <f> Output format: json|text (default: json)
|
|
2373
|
+
--synthesize-context Generate coherent summary with patterns and insights
|
|
2374
|
+
--filters <json> MongoDB-style metadata filters
|
|
2375
|
+
Example: agentdb query --query "authentication" --k 5 --min-confidence 0.8 --synthesize-context
|
|
2376
|
+
Example: agentdb query --query "bug-fix" --filters '{"metadata.priority":"high"}' --synthesize-context
|
|
1313
2377
|
|
|
1314
2378
|
agentdb store-pattern --type <type> --domain <domain> --pattern <json> --confidence <conf>
|
|
1315
2379
|
Store a learned pattern for future retrieval
|
|
@@ -1327,6 +2391,23 @@ ${colors.bright}ENVIRONMENT:${colors.reset}
|
|
|
1327
2391
|
AGENTDB_PATH Database file path (default: ./agentdb.db)
|
|
1328
2392
|
|
|
1329
2393
|
${colors.bright}EXAMPLES:${colors.reset}
|
|
2394
|
+
# QUIC Sync: Multi-agent coordination
|
|
2395
|
+
# On server machine:
|
|
2396
|
+
agentdb sync start-server --port 4433 --auth-token secret123
|
|
2397
|
+
|
|
2398
|
+
# On client machines:
|
|
2399
|
+
agentdb sync connect 192.168.1.100 4433 --auth-token secret123
|
|
2400
|
+
agentdb sync push --server 192.168.1.100:4433 --incremental
|
|
2401
|
+
agentdb sync pull --server 192.168.1.100:4433 --incremental
|
|
2402
|
+
agentdb sync status
|
|
2403
|
+
|
|
2404
|
+
# Vector Search: Direct similarity queries
|
|
2405
|
+
agentdb init ./vectors.db --dimension 768 --preset medium
|
|
2406
|
+
agentdb vector-search ./vectors.db "[0.1,0.2,0.3]" -k 10 -m cosine -f json
|
|
2407
|
+
agentdb export ./vectors.db ./backup.json
|
|
2408
|
+
agentdb import ./backup.json ./new-vectors.db
|
|
2409
|
+
agentdb stats ./vectors.db
|
|
2410
|
+
|
|
1330
2411
|
# Reflexion: Store and retrieve episodes
|
|
1331
2412
|
agentdb reflexion store "session-1" "implement_auth" 0.95 true "Used OAuth2"
|
|
1332
2413
|
agentdb reflexion retrieve "authentication" 10 0.8
|