@botbotgo/agent-harness 0.0.153 → 0.0.155

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.
@@ -3,6 +3,7 @@ import { mkdir } from "node:fs/promises";
3
3
  import { Document } from "@langchain/core/documents";
4
4
  import { createClient } from "@libsql/client";
5
5
  import { LibSQLVectorStore } from "@langchain/community/vectorstores/libsql";
6
+ import { QdrantClient } from "@qdrant/js-client-rest";
6
7
  import { compileVectorStore } from "../../workspace/resource-compilers.js";
7
8
  import { resolveRefId } from "../../workspace/support/workspace-ref-utils.js";
8
9
  import { resolveCompiledEmbeddingModel, resolveCompiledEmbeddingModelRef } from "./embedding-models.js";
@@ -52,6 +53,27 @@ async function ensureLibSqlSchema(db, table, column, dimensions) {
52
53
  ON ${safeTable}(libsql_vector_idx(${safeColumn}))
53
54
  `);
54
55
  }
56
+ function createQdrantClientForStore(vectorStore) {
57
+ return new QdrantClient({
58
+ ...(vectorStore.url ? { url: vectorStore.url } : {}),
59
+ ...(vectorStore.host ? { host: vectorStore.host } : {}),
60
+ ...(typeof vectorStore.port === "number" ? { port: vectorStore.port } : {}),
61
+ ...(vectorStore.authToken ? { apiKey: vectorStore.authToken } : {}),
62
+ checkCompatibility: false,
63
+ });
64
+ }
65
+ async function ensureQdrantCollection(client, collection, dimensions) {
66
+ const collections = await client.getCollections();
67
+ if (collections.collections.some((entry) => entry.name === collection)) {
68
+ return;
69
+ }
70
+ await client.createCollection(collection, {
71
+ vectors: {
72
+ size: dimensions,
73
+ distance: "Cosine",
74
+ },
75
+ });
76
+ }
55
77
  export function resolveCompiledVectorStoreRef(workspace, vectorStoreRef) {
56
78
  const resolvedId = vectorStoreRef ? resolveRefId(vectorStoreRef) : "default";
57
79
  const vectorStore = workspace.vectorStores.get(resolvedId);
@@ -75,6 +97,81 @@ export async function resolveCompiledVectorStore(workspace, vectorStore, options
75
97
  const embeddings = await resolveCompiledEmbeddingModel(embeddingModel, options.embeddingModelResolver);
76
98
  return createLlamaIndexVectorStore(workspace.workspaceRoot, vectorStore, embeddings);
77
99
  }
100
+ if (vectorStore.kind === "QdrantVectorStore") {
101
+ const embeddingModel = resolveCompiledEmbeddingModelRef(workspace, vectorStore.embeddingModelRef);
102
+ const embeddings = await resolveCompiledEmbeddingModel(embeddingModel, options.embeddingModelResolver);
103
+ const client = createQdrantClientForStore(vectorStore);
104
+ const collection = vectorStore.collection ?? "vectors";
105
+ const ensureCollectionForTexts = async (texts) => {
106
+ const seedText = texts.find((text) => text.trim().length > 0) ?? "seed";
107
+ const sample = await embeddings.embedQuery(seedText);
108
+ await ensureQdrantCollection(client, collection, sample.length);
109
+ };
110
+ return {
111
+ kind: vectorStore.kind,
112
+ embeddingModelRef: vectorStore.embeddingModelRef,
113
+ addDocuments: async (documents) => {
114
+ if (documents.length === 0) {
115
+ return [];
116
+ }
117
+ await ensureCollectionForTexts(documents.map((document) => document.pageContent));
118
+ const vectors = await embeddings.embedDocuments(documents.map((document) => document.pageContent));
119
+ const ids = documents.map((_, index) => `${Date.now()}-${index}-${Math.random().toString(36).slice(2, 10)}`);
120
+ await client.upsert(collection, {
121
+ wait: true,
122
+ points: documents.map((document, index) => ({
123
+ id: ids[index] ?? index,
124
+ vector: vectors[index] ?? [],
125
+ payload: {
126
+ pageContent: document.pageContent,
127
+ ...(document.metadata ? { metadata: document.metadata } : {}),
128
+ },
129
+ })),
130
+ });
131
+ return ids;
132
+ },
133
+ similaritySearch: async (query, limit) => {
134
+ const collections = await client.getCollections();
135
+ if (!collections.collections.some((entry) => entry.name === collection)) {
136
+ return [];
137
+ }
138
+ const queryVector = await embeddings.embedQuery(query);
139
+ const rows = await client.search(collection, {
140
+ vector: queryVector,
141
+ limit,
142
+ with_payload: true,
143
+ });
144
+ return rows.map((row) => {
145
+ const payload = (row.payload ?? {});
146
+ return {
147
+ pageContent: typeof payload.pageContent === "string" ? payload.pageContent : "",
148
+ metadata: typeof payload.metadata === "object" && payload.metadata && !Array.isArray(payload.metadata)
149
+ ? payload.metadata
150
+ : {},
151
+ score: typeof row.score === "number" ? row.score : undefined,
152
+ };
153
+ });
154
+ },
155
+ delete: async (params) => {
156
+ const collections = await client.getCollections();
157
+ if (!collections.collections.some((entry) => entry.name === collection)) {
158
+ return;
159
+ }
160
+ if (params.deleteAll) {
161
+ await client.deleteCollection(collection);
162
+ return;
163
+ }
164
+ const pointIds = (params.ids ?? []).filter((id) => typeof id === "string" || typeof id === "number");
165
+ if (pointIds.length === 0) {
166
+ return;
167
+ }
168
+ await client.delete(collection, {
169
+ wait: true,
170
+ points: pointIds,
171
+ });
172
+ },
173
+ };
174
+ }
78
175
  if (vectorStore.kind !== "LibSQLVectorStore") {
79
176
  throw new Error(`Vector store kind ${vectorStore.kind} is not supported by the built-in runtime.`);
80
177
  }
@@ -89,13 +89,21 @@ export function parseEmbeddingModelObject(object) {
89
89
  }
90
90
  export function parseVectorStoreObject(object) {
91
91
  const value = object.value;
92
+ const port = typeof value.port === "number" && Number.isInteger(value.port) ? value.port : undefined;
92
93
  return {
93
94
  id: object.id,
94
95
  kind: String(value.storeKind ?? value.kind ?? "LibSQLVectorStore").trim(),
95
96
  url: typeof value.url === "string" ? value.url : undefined,
97
+ host: typeof value.host === "string" ? value.host : undefined,
98
+ port,
96
99
  authToken: typeof value.authToken === "string" ? value.authToken : undefined,
97
100
  table: typeof value.table === "string" ? value.table : undefined,
98
101
  column: typeof value.column === "string" ? value.column : undefined,
102
+ collection: typeof value.collection === "string"
103
+ ? value.collection
104
+ : typeof value.collectionName === "string"
105
+ ? value.collectionName
106
+ : undefined,
99
107
  embeddingModelRef: typeof value.embeddingModelRef === "string"
100
108
  ? value.embeddingModelRef
101
109
  : typeof asObject(value.embeddingModel)?.ref === "string"
@@ -155,6 +163,14 @@ export function validateVectorStoreObject(vectorStore) {
155
163
  if ((vectorStore.kind === "LibSQLVectorStore" || vectorStore.kind === "LlamaIndexSimpleVectorStore") && !vectorStore.url) {
156
164
  throw new Error(`Vector store ${vectorStore.id} url must not be empty for ${vectorStore.kind}`);
157
165
  }
166
+ if (vectorStore.kind === "QdrantVectorStore") {
167
+ if (!vectorStore.url && !vectorStore.host) {
168
+ throw new Error(`Vector store ${vectorStore.id} must define url or host for QdrantVectorStore`);
169
+ }
170
+ if (!vectorStore.collection) {
171
+ throw new Error(`Vector store ${vectorStore.id} collection must not be empty for QdrantVectorStore`);
172
+ }
173
+ }
158
174
  }
159
175
  export function validateMcpServerObject(server) {
160
176
  if (!server.id.trim()) {
@@ -186,9 +202,12 @@ export function compileVectorStore(vectorStore) {
186
202
  id: vectorStore.id,
187
203
  kind: vectorStore.kind,
188
204
  url: vectorStore.url,
205
+ host: vectorStore.host,
206
+ port: vectorStore.port,
189
207
  authToken: vectorStore.authToken,
190
208
  table: vectorStore.table,
191
209
  column: vectorStore.column,
210
+ collection: vectorStore.collection,
192
211
  embeddingModelRef: vectorStore.embeddingModelRef,
193
212
  runtimeValue: vectorStore.kind,
194
213
  };
@@ -62,6 +62,8 @@ function normalizeKind(kind) {
62
62
  return "agent";
63
63
  case "FileStore":
64
64
  return "file-store";
65
+ case "SqliteStore":
66
+ return "sqlite-store";
65
67
  case "InMemoryStore":
66
68
  return "in-memory-store";
67
69
  case "RedisStore":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.153",
3
+ "version": "0.0.155",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",