@radaros/core 0.3.4 → 0.3.6

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.
Files changed (60) hide show
  1. package/dist/index.d.ts +1407 -0
  2. package/dist/index.js +5269 -0
  3. package/package.json +6 -2
  4. package/src/a2a/a2a-remote-agent.ts +0 -270
  5. package/src/a2a/types.ts +0 -142
  6. package/src/agent/agent.ts +0 -417
  7. package/src/agent/llm-loop.ts +0 -290
  8. package/src/agent/run-context.ts +0 -35
  9. package/src/agent/types.ts +0 -89
  10. package/src/events/event-bus.ts +0 -45
  11. package/src/events/types.ts +0 -16
  12. package/src/guardrails/types.ts +0 -5
  13. package/src/hooks/types.ts +0 -6
  14. package/src/index.ts +0 -157
  15. package/src/knowledge/knowledge-base.ts +0 -146
  16. package/src/logger/logger.ts +0 -249
  17. package/src/mcp/mcp-client.ts +0 -264
  18. package/src/memory/memory.ts +0 -87
  19. package/src/memory/types.ts +0 -13
  20. package/src/memory/user-memory.ts +0 -211
  21. package/src/models/provider.ts +0 -22
  22. package/src/models/providers/anthropic.ts +0 -360
  23. package/src/models/providers/google.ts +0 -386
  24. package/src/models/providers/ollama.ts +0 -211
  25. package/src/models/providers/openai.ts +0 -345
  26. package/src/models/providers/vertex.ts +0 -427
  27. package/src/models/registry.ts +0 -107
  28. package/src/models/types.ts +0 -124
  29. package/src/session/session-manager.ts +0 -75
  30. package/src/session/types.ts +0 -10
  31. package/src/storage/driver.ts +0 -10
  32. package/src/storage/in-memory.ts +0 -44
  33. package/src/storage/mongodb.ts +0 -70
  34. package/src/storage/postgres.ts +0 -81
  35. package/src/storage/sqlite.ts +0 -81
  36. package/src/team/modes.ts +0 -1
  37. package/src/team/team.ts +0 -323
  38. package/src/team/types.ts +0 -26
  39. package/src/toolkits/base.ts +0 -15
  40. package/src/toolkits/duckduckgo.ts +0 -256
  41. package/src/toolkits/gmail.ts +0 -226
  42. package/src/toolkits/hackernews.ts +0 -121
  43. package/src/toolkits/websearch.ts +0 -158
  44. package/src/toolkits/whatsapp.ts +0 -209
  45. package/src/tools/define-tool.ts +0 -22
  46. package/src/tools/tool-executor.ts +0 -221
  47. package/src/tools/types.ts +0 -36
  48. package/src/utils/retry.ts +0 -56
  49. package/src/vector/base.ts +0 -44
  50. package/src/vector/embeddings/google.ts +0 -64
  51. package/src/vector/embeddings/openai.ts +0 -66
  52. package/src/vector/in-memory.ts +0 -115
  53. package/src/vector/mongodb.ts +0 -241
  54. package/src/vector/pgvector.ts +0 -169
  55. package/src/vector/qdrant.ts +0 -203
  56. package/src/vector/types.ts +0 -55
  57. package/src/workflow/step-runner.ts +0 -303
  58. package/src/workflow/types.ts +0 -55
  59. package/src/workflow/workflow.ts +0 -68
  60. package/tsconfig.json +0 -8
@@ -1,44 +0,0 @@
1
- import type {
2
- VectorStore,
3
- VectorDocument,
4
- VectorSearchResult,
5
- VectorSearchOptions,
6
- EmbeddingProvider,
7
- } from "./types.js";
8
-
9
- export abstract class BaseVectorStore implements VectorStore {
10
- constructor(protected embedder?: EmbeddingProvider) {}
11
-
12
- protected async ensureEmbedding(doc: VectorDocument): Promise<number[]> {
13
- if (doc.embedding) return doc.embedding;
14
- if (!this.embedder) {
15
- throw new Error(
16
- "No embedding provided on document and no EmbeddingProvider configured"
17
- );
18
- }
19
- return this.embedder.embed(doc.content);
20
- }
21
-
22
- protected async ensureQueryVector(query: number[] | string): Promise<number[]> {
23
- if (Array.isArray(query)) return query;
24
- if (!this.embedder) {
25
- throw new Error(
26
- "String query requires an EmbeddingProvider to be configured"
27
- );
28
- }
29
- return this.embedder.embed(query);
30
- }
31
-
32
- abstract initialize(): Promise<void>;
33
- abstract upsert(collection: string, doc: VectorDocument): Promise<void>;
34
- abstract upsertBatch(collection: string, docs: VectorDocument[]): Promise<void>;
35
- abstract search(
36
- collection: string,
37
- query: number[] | string,
38
- options?: VectorSearchOptions
39
- ): Promise<VectorSearchResult[]>;
40
- abstract delete(collection: string, id: string): Promise<void>;
41
- abstract get(collection: string, id: string): Promise<VectorDocument | null>;
42
- abstract dropCollection(collection: string): Promise<void>;
43
- abstract close(): Promise<void>;
44
- }
@@ -1,64 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import type { EmbeddingProvider } from "../types.js";
3
-
4
- const _require = createRequire(import.meta.url);
5
-
6
- export interface GoogleEmbeddingConfig {
7
- apiKey?: string;
8
- model?: string;
9
- dimensions?: number;
10
- }
11
-
12
- const MODEL_DIMENSIONS: Record<string, number> = {
13
- "text-embedding-004": 768,
14
- "embedding-001": 768,
15
- };
16
-
17
- export class GoogleEmbedding implements EmbeddingProvider {
18
- readonly dimensions: number;
19
- private ai: any;
20
- private model: string;
21
-
22
- constructor(config: GoogleEmbeddingConfig = {}) {
23
- this.model = config.model ?? "text-embedding-004";
24
- this.dimensions =
25
- config.dimensions ?? MODEL_DIMENSIONS[this.model] ?? 768;
26
-
27
- try {
28
- const { GoogleGenAI } = _require("@google/genai");
29
- this.ai = new GoogleGenAI({
30
- apiKey: config.apiKey ?? process.env.GOOGLE_API_KEY,
31
- });
32
- } catch {
33
- throw new Error(
34
- "@google/genai is required for GoogleEmbedding. Install it: npm install @google/genai"
35
- );
36
- }
37
- }
38
-
39
- async embed(text: string): Promise<number[]> {
40
- const result = await this.ai.models.embedContent({
41
- model: this.model,
42
- contents: text,
43
- ...(this.dimensions !== MODEL_DIMENSIONS[this.model]
44
- ? { config: { outputDimensionality: this.dimensions } }
45
- : {}),
46
- });
47
- return result.embeddings[0].values;
48
- }
49
-
50
- async embedBatch(texts: string[]): Promise<number[][]> {
51
- const results = await Promise.all(
52
- texts.map((text) =>
53
- this.ai.models.embedContent({
54
- model: this.model,
55
- contents: text,
56
- ...(this.dimensions !== MODEL_DIMENSIONS[this.model]
57
- ? { config: { outputDimensionality: this.dimensions } }
58
- : {}),
59
- })
60
- )
61
- );
62
- return results.map((r: any) => r.embeddings[0].values);
63
- }
64
- }
@@ -1,66 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import type { EmbeddingProvider } from "../types.js";
3
-
4
- const _require = createRequire(import.meta.url);
5
-
6
- export interface OpenAIEmbeddingConfig {
7
- apiKey?: string;
8
- baseURL?: string;
9
- model?: string;
10
- dimensions?: number;
11
- }
12
-
13
- const MODEL_DIMENSIONS: Record<string, number> = {
14
- "text-embedding-3-small": 1536,
15
- "text-embedding-3-large": 3072,
16
- "text-embedding-ada-002": 1536,
17
- };
18
-
19
- export class OpenAIEmbedding implements EmbeddingProvider {
20
- readonly dimensions: number;
21
- private client: any;
22
- private model: string;
23
-
24
- constructor(config: OpenAIEmbeddingConfig = {}) {
25
- this.model = config.model ?? "text-embedding-3-small";
26
- this.dimensions =
27
- config.dimensions ?? MODEL_DIMENSIONS[this.model] ?? 1536;
28
-
29
- try {
30
- const mod = _require("openai");
31
- const OpenAI = mod.default ?? mod;
32
- this.client = new OpenAI({
33
- apiKey: config.apiKey ?? process.env.OPENAI_API_KEY,
34
- baseURL: config.baseURL,
35
- });
36
- } catch {
37
- throw new Error(
38
- "openai package is required for OpenAIEmbedding. Install it: npm install openai"
39
- );
40
- }
41
- }
42
-
43
- async embed(text: string): Promise<number[]> {
44
- const response = await this.client.embeddings.create({
45
- model: this.model,
46
- input: text,
47
- ...(this.dimensions !== MODEL_DIMENSIONS[this.model]
48
- ? { dimensions: this.dimensions }
49
- : {}),
50
- });
51
- return response.data[0].embedding;
52
- }
53
-
54
- async embedBatch(texts: string[]): Promise<number[][]> {
55
- const response = await this.client.embeddings.create({
56
- model: this.model,
57
- input: texts,
58
- ...(this.dimensions !== MODEL_DIMENSIONS[this.model]
59
- ? { dimensions: this.dimensions }
60
- : {}),
61
- });
62
- return response.data
63
- .sort((a: any, b: any) => a.index - b.index)
64
- .map((d: any) => d.embedding);
65
- }
66
- }
@@ -1,115 +0,0 @@
1
- import { BaseVectorStore } from "./base.js";
2
- import type {
3
- VectorDocument,
4
- VectorSearchResult,
5
- VectorSearchOptions,
6
- EmbeddingProvider,
7
- } from "./types.js";
8
-
9
- interface StoredDoc {
10
- id: string;
11
- content: string;
12
- embedding: number[];
13
- metadata: Record<string, unknown>;
14
- }
15
-
16
- export class InMemoryVectorStore extends BaseVectorStore {
17
- private collections = new Map<string, Map<string, StoredDoc>>();
18
-
19
- constructor(embedder?: EmbeddingProvider) {
20
- super(embedder);
21
- }
22
-
23
- async initialize(): Promise<void> {}
24
-
25
- private getCol(collection: string): Map<string, StoredDoc> {
26
- let col = this.collections.get(collection);
27
- if (!col) {
28
- col = new Map();
29
- this.collections.set(collection, col);
30
- }
31
- return col;
32
- }
33
-
34
- async upsert(collection: string, doc: VectorDocument): Promise<void> {
35
- const embedding = await this.ensureEmbedding(doc);
36
- this.getCol(collection).set(doc.id, {
37
- id: doc.id,
38
- content: doc.content,
39
- embedding,
40
- metadata: doc.metadata ?? {},
41
- });
42
- }
43
-
44
- async upsertBatch(collection: string, docs: VectorDocument[]): Promise<void> {
45
- for (const doc of docs) {
46
- await this.upsert(collection, doc);
47
- }
48
- }
49
-
50
- async search(
51
- collection: string,
52
- query: number[] | string,
53
- options?: VectorSearchOptions
54
- ): Promise<VectorSearchResult[]> {
55
- const vec = await this.ensureQueryVector(query);
56
- const topK = options?.topK ?? 10;
57
- const col = this.getCol(collection);
58
-
59
- const scored: VectorSearchResult[] = [];
60
- for (const doc of col.values()) {
61
- const score = this.cosineSimilarity(vec, doc.embedding);
62
- if (options?.minScore != null && score < options.minScore) continue;
63
- if (options?.filter) {
64
- let match = true;
65
- for (const [k, v] of Object.entries(options.filter)) {
66
- if (doc.metadata[k] !== v) {
67
- match = false;
68
- break;
69
- }
70
- }
71
- if (!match) continue;
72
- }
73
- scored.push({
74
- id: doc.id,
75
- content: doc.content,
76
- score,
77
- metadata: doc.metadata,
78
- });
79
- }
80
-
81
- scored.sort((a, b) => b.score - a.score);
82
- return scored.slice(0, topK);
83
- }
84
-
85
- private cosineSimilarity(a: number[], b: number[]): number {
86
- let dot = 0;
87
- let normA = 0;
88
- let normB = 0;
89
- for (let i = 0; i < a.length; i++) {
90
- dot += a[i] * b[i];
91
- normA += a[i] * a[i];
92
- normB += b[i] * b[i];
93
- }
94
- const denom = Math.sqrt(normA) * Math.sqrt(normB);
95
- return denom === 0 ? 0 : dot / denom;
96
- }
97
-
98
- async delete(collection: string, id: string): Promise<void> {
99
- this.getCol(collection).delete(id);
100
- }
101
-
102
- async get(collection: string, id: string): Promise<VectorDocument | null> {
103
- const doc = this.getCol(collection).get(id);
104
- if (!doc) return null;
105
- return { id: doc.id, content: doc.content, metadata: doc.metadata };
106
- }
107
-
108
- async dropCollection(collection: string): Promise<void> {
109
- this.collections.delete(collection);
110
- }
111
-
112
- async close(): Promise<void> {
113
- this.collections.clear();
114
- }
115
- }
@@ -1,241 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import { BaseVectorStore } from "./base.js";
3
- import type {
4
- VectorDocument,
5
- VectorSearchResult,
6
- VectorSearchOptions,
7
- EmbeddingProvider,
8
- } from "./types.js";
9
-
10
- const _require = createRequire(import.meta.url);
11
-
12
- export interface MongoDBVectorConfig {
13
- uri: string;
14
- dbName?: string;
15
- /** Atlas Search index name (must be pre-created for $vectorSearch). Defaults to "vector_index". */
16
- indexName?: string;
17
- }
18
-
19
- export class MongoDBVectorStore extends BaseVectorStore {
20
- private client: any;
21
- private db: any;
22
- private indexName: string;
23
- private dbName: string;
24
- private useAtlas: boolean | null = null;
25
-
26
- constructor(config: MongoDBVectorConfig, embedder?: EmbeddingProvider) {
27
- super(embedder);
28
- this.indexName = config.indexName ?? "vector_index";
29
- this.dbName = config.dbName ?? "radaros_vectors";
30
- try {
31
- const { MongoClient } = _require("mongodb");
32
- this.client = new MongoClient(config.uri);
33
- } catch {
34
- throw new Error(
35
- "mongodb is required for MongoDBVectorStore. Install it: npm install mongodb"
36
- );
37
- }
38
- }
39
-
40
- async initialize(): Promise<void> {
41
- await this.client.connect();
42
- this.db = this.client.db(this.dbName);
43
- }
44
-
45
- private col(collection: string) {
46
- return this.db.collection(collection);
47
- }
48
-
49
- async upsert(collection: string, doc: VectorDocument): Promise<void> {
50
- const embedding = await this.ensureEmbedding(doc);
51
- await this.col(collection).updateOne(
52
- { _id: doc.id },
53
- {
54
- $set: {
55
- content: doc.content,
56
- embedding,
57
- metadata: doc.metadata ?? {},
58
- updatedAt: new Date(),
59
- },
60
- },
61
- { upsert: true }
62
- );
63
- }
64
-
65
- async upsertBatch(collection: string, docs: VectorDocument[]): Promise<void> {
66
- const ops = await Promise.all(
67
- docs.map(async (doc) => {
68
- const embedding = await this.ensureEmbedding(doc);
69
- return {
70
- updateOne: {
71
- filter: { _id: doc.id },
72
- update: {
73
- $set: {
74
- content: doc.content,
75
- embedding,
76
- metadata: doc.metadata ?? {},
77
- updatedAt: new Date(),
78
- },
79
- },
80
- upsert: true,
81
- },
82
- };
83
- })
84
- );
85
- if (ops.length > 0) {
86
- await this.col(collection).bulkWrite(ops);
87
- }
88
- }
89
-
90
- async search(
91
- collection: string,
92
- query: number[] | string,
93
- options?: VectorSearchOptions
94
- ): Promise<VectorSearchResult[]> {
95
- const vec = await this.ensureQueryVector(query);
96
-
97
- if (this.useAtlas === true) {
98
- return this.atlasSearch(collection, vec, options);
99
- }
100
-
101
- if (this.useAtlas === false) {
102
- return this.localSearch(collection, vec, options);
103
- }
104
-
105
- // First call: auto-detect Atlas support
106
- try {
107
- const results = await this.atlasSearch(collection, vec, options);
108
- this.useAtlas = true;
109
- return results;
110
- } catch {
111
- this.useAtlas = false;
112
- return this.localSearch(collection, vec, options);
113
- }
114
- }
115
-
116
- private async atlasSearch(
117
- collection: string,
118
- vec: number[],
119
- options?: VectorSearchOptions
120
- ): Promise<VectorSearchResult[]> {
121
- const topK = options?.topK ?? 10;
122
-
123
- const pipeline: Record<string, unknown>[] = [
124
- {
125
- $vectorSearch: {
126
- index: this.indexName,
127
- path: "embedding",
128
- queryVector: vec,
129
- numCandidates: topK * 10,
130
- limit: topK,
131
- ...(options?.filter ? { filter: this.buildFilter(options.filter) } : {}),
132
- },
133
- },
134
- {
135
- $addFields: {
136
- score: { $meta: "vectorSearchScore" },
137
- },
138
- },
139
- ];
140
-
141
- if (options?.minScore != null) {
142
- pipeline.push({ $match: { score: { $gte: options.minScore } } });
143
- }
144
-
145
- pipeline.push({
146
- $project: { _id: 1, content: 1, score: 1, metadata: 1 },
147
- });
148
-
149
- const results = await this.col(collection).aggregate(pipeline).toArray();
150
-
151
- return results.map((r: any) => ({
152
- id: String(r._id),
153
- content: r.content ?? "",
154
- score: r.score,
155
- metadata: r.metadata,
156
- }));
157
- }
158
-
159
- private async localSearch(
160
- collection: string,
161
- vec: number[],
162
- options?: VectorSearchOptions
163
- ): Promise<VectorSearchResult[]> {
164
- const topK = options?.topK ?? 10;
165
- const filter: Record<string, unknown> = {};
166
- if (options?.filter) {
167
- for (const [k, v] of Object.entries(options.filter)) {
168
- filter[`metadata.${k}`] = v;
169
- }
170
- }
171
-
172
- const docs = await this.col(collection)
173
- .find(filter, { projection: { _id: 1, content: 1, embedding: 1, metadata: 1 } })
174
- .toArray();
175
-
176
- const scored: VectorSearchResult[] = [];
177
- for (const doc of docs) {
178
- if (!doc.embedding) continue;
179
- const score = cosine(vec, doc.embedding);
180
- if (options?.minScore != null && score < options.minScore) continue;
181
- scored.push({
182
- id: String(doc._id),
183
- content: doc.content ?? "",
184
- score,
185
- metadata: doc.metadata,
186
- });
187
- }
188
-
189
- scored.sort((a, b) => b.score - a.score);
190
- return scored.slice(0, topK);
191
- }
192
-
193
- private buildFilter(
194
- filter: Record<string, unknown>
195
- ): Record<string, unknown> {
196
- const conditions: Record<string, unknown> = {};
197
- for (const [key, value] of Object.entries(filter)) {
198
- conditions[`metadata.${key}`] = value;
199
- }
200
- return conditions;
201
- }
202
-
203
- async delete(collection: string, id: string): Promise<void> {
204
- await this.col(collection).deleteOne({ _id: id });
205
- }
206
-
207
- async get(collection: string, id: string): Promise<VectorDocument | null> {
208
- const doc = await this.col(collection).findOne({ _id: id });
209
- if (!doc) return null;
210
- return {
211
- id: String(doc._id),
212
- content: doc.content,
213
- metadata: doc.metadata,
214
- };
215
- }
216
-
217
- async dropCollection(collection: string): Promise<void> {
218
- try {
219
- await this.col(collection).drop();
220
- } catch {
221
- // collection may not exist
222
- }
223
- }
224
-
225
- async close(): Promise<void> {
226
- await this.client.close();
227
- }
228
- }
229
-
230
- function cosine(a: number[], b: number[]): number {
231
- let dot = 0;
232
- let normA = 0;
233
- let normB = 0;
234
- for (let i = 0; i < a.length; i++) {
235
- dot += a[i] * b[i];
236
- normA += a[i] * a[i];
237
- normB += b[i] * b[i];
238
- }
239
- const denom = Math.sqrt(normA) * Math.sqrt(normB);
240
- return denom === 0 ? 0 : dot / denom;
241
- }
@@ -1,169 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import { BaseVectorStore } from "./base.js";
3
- import type {
4
- VectorDocument,
5
- VectorSearchResult,
6
- VectorSearchOptions,
7
- EmbeddingProvider,
8
- } from "./types.js";
9
-
10
- const _require = createRequire(import.meta.url);
11
-
12
- export interface PgVectorConfig {
13
- connectionString: string;
14
- dimensions?: number;
15
- }
16
-
17
- export class PgVectorStore extends BaseVectorStore {
18
- private pool: any;
19
- private dimensions: number;
20
- private initializedCollections = new Set<string>();
21
-
22
- constructor(config: PgVectorConfig, embedder?: EmbeddingProvider) {
23
- super(embedder);
24
- this.dimensions = config.dimensions ?? embedder?.dimensions ?? 1536;
25
- try {
26
- const { Pool } = _require("pg");
27
- this.pool = new Pool({ connectionString: config.connectionString });
28
- } catch {
29
- throw new Error(
30
- "pg is required for PgVectorStore. Install it: npm install pg"
31
- );
32
- }
33
- }
34
-
35
- async initialize(): Promise<void> {
36
- await this.pool.query("CREATE EXTENSION IF NOT EXISTS vector");
37
- }
38
-
39
- private async ensureCollection(collection: string): Promise<void> {
40
- if (this.initializedCollections.has(collection)) return;
41
- const table = this.sanitize(collection);
42
- await this.pool.query(`
43
- CREATE TABLE IF NOT EXISTS ${table} (
44
- id TEXT PRIMARY KEY,
45
- content TEXT NOT NULL,
46
- embedding vector(${this.dimensions}),
47
- metadata JSONB DEFAULT '{}'::jsonb,
48
- created_at TIMESTAMPTZ DEFAULT NOW()
49
- )
50
- `);
51
- await this.pool.query(`
52
- CREATE INDEX IF NOT EXISTS ${table}_embedding_idx
53
- ON ${table} USING ivfflat (embedding vector_cosine_ops)
54
- WITH (lists = 100)
55
- `).catch(() => {
56
- // IVFFlat index needs enough rows; hnsw fallback
57
- });
58
- this.initializedCollections.add(collection);
59
- }
60
-
61
- private sanitize(name: string): string {
62
- return name.replace(/[^a-zA-Z0-9_]/g, "_");
63
- }
64
-
65
- private toSql(vec: number[]): string {
66
- return `[${vec.join(",")}]`;
67
- }
68
-
69
- async upsert(collection: string, doc: VectorDocument): Promise<void> {
70
- await this.ensureCollection(collection);
71
- const embedding = await this.ensureEmbedding(doc);
72
- const table = this.sanitize(collection);
73
- await this.pool.query(
74
- `INSERT INTO ${table} (id, content, embedding, metadata)
75
- VALUES ($1, $2, $3::vector, $4::jsonb)
76
- ON CONFLICT (id)
77
- DO UPDATE SET content = EXCLUDED.content,
78
- embedding = EXCLUDED.embedding,
79
- metadata = EXCLUDED.metadata`,
80
- [doc.id, doc.content, this.toSql(embedding), JSON.stringify(doc.metadata ?? {})]
81
- );
82
- }
83
-
84
- async upsertBatch(collection: string, docs: VectorDocument[]): Promise<void> {
85
- for (const doc of docs) {
86
- await this.upsert(collection, doc);
87
- }
88
- }
89
-
90
- async search(
91
- collection: string,
92
- query: number[] | string,
93
- options?: VectorSearchOptions
94
- ): Promise<VectorSearchResult[]> {
95
- await this.ensureCollection(collection);
96
- const vec = await this.ensureQueryVector(query);
97
- const topK = options?.topK ?? 10;
98
- const table = this.sanitize(collection);
99
-
100
- let filterClause = "";
101
- const params: unknown[] = [this.toSql(vec), topK];
102
-
103
- if (options?.filter) {
104
- const conditions = Object.entries(options.filter).map(([k, v], i) => {
105
- params.push(JSON.stringify(v));
106
- return `metadata->>'${k.replace(/'/g, "''")}' = $${i + 3}`;
107
- });
108
- if (conditions.length > 0) {
109
- filterClause = `WHERE ${conditions.join(" AND ")}`;
110
- }
111
- }
112
-
113
- const result = await this.pool.query(
114
- `SELECT id, content, metadata,
115
- 1 - (embedding <=> $1::vector) AS score
116
- FROM ${table}
117
- ${filterClause}
118
- ORDER BY embedding <=> $1::vector
119
- LIMIT $2`,
120
- params
121
- );
122
-
123
- let rows = result.rows as Array<{
124
- id: string;
125
- content: string;
126
- score: number;
127
- metadata: Record<string, unknown>;
128
- }>;
129
-
130
- if (options?.minScore != null) {
131
- rows = rows.filter((r) => r.score >= options.minScore!);
132
- }
133
-
134
- return rows.map((r) => ({
135
- id: r.id,
136
- content: r.content,
137
- score: r.score,
138
- metadata: r.metadata,
139
- }));
140
- }
141
-
142
- async delete(collection: string, id: string): Promise<void> {
143
- await this.ensureCollection(collection);
144
- const table = this.sanitize(collection);
145
- await this.pool.query(`DELETE FROM ${table} WHERE id = $1`, [id]);
146
- }
147
-
148
- async get(collection: string, id: string): Promise<VectorDocument | null> {
149
- await this.ensureCollection(collection);
150
- const table = this.sanitize(collection);
151
- const result = await this.pool.query(
152
- `SELECT id, content, metadata FROM ${table} WHERE id = $1`,
153
- [id]
154
- );
155
- if (result.rows.length === 0) return null;
156
- const row = result.rows[0];
157
- return { id: row.id, content: row.content, metadata: row.metadata };
158
- }
159
-
160
- async dropCollection(collection: string): Promise<void> {
161
- const table = this.sanitize(collection);
162
- await this.pool.query(`DROP TABLE IF EXISTS ${table}`);
163
- this.initializedCollections.delete(collection);
164
- }
165
-
166
- async close(): Promise<void> {
167
- await this.pool.end();
168
- }
169
- }