@customize-agent/knowledge 2.2.0 → 2.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@customize-agent/knowledge",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Local knowledge base infrastructure for customize-agent",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,41 +0,0 @@
1
- import type { CollectionClient, VectorCollectionInfo, VectorDocument, VectorSearchQuery, VectorSearchResult, VectorStoreInterface } from './types.js';
2
- interface ChromaQueryResponse {
3
- ids?: string[][];
4
- documents?: string[][];
5
- metadatas?: Array<Array<Record<string, unknown>>>;
6
- distances?: number[][];
7
- }
8
- export interface ChromaClientOptions {
9
- baseUrl?: string;
10
- tenant?: string;
11
- database?: string;
12
- }
13
- export declare class ChromaHttpClient implements CollectionClient {
14
- readonly baseUrl: string;
15
- readonly tenant: string;
16
- readonly database: string;
17
- private readonly collectionIds;
18
- constructor(options?: ChromaClientOptions);
19
- heartbeat(): Promise<boolean>;
20
- getOrCreateCollection(name: string, metadata?: Record<string, unknown>): Promise<VectorCollectionInfo>;
21
- listCollections(): Promise<VectorCollectionInfo[]>;
22
- deleteCollection(name: string): Promise<void>;
23
- upsert(collectionName: string, documents: VectorDocument[]): Promise<void>;
24
- deleteWhere(collectionName: string, where: Record<string, string | number | boolean>): Promise<void>;
25
- query(collectionName: string, query: VectorSearchQuery): Promise<ChromaQueryResponse>;
26
- private getCollectionId;
27
- private collectionsPath;
28
- private request;
29
- private toCollectionInfo;
30
- }
31
- export declare class ChromaVectorStore implements VectorStoreInterface {
32
- private readonly client;
33
- readonly collectionName: string;
34
- constructor(client: ChromaHttpClient, collectionName: string);
35
- ensureCollection(metadata?: Record<string, unknown>): Promise<void>;
36
- upsert(documents: VectorDocument[]): Promise<void>;
37
- deleteByFilePath(filePath: string): Promise<void>;
38
- search(query: VectorSearchQuery): Promise<VectorSearchResult[]>;
39
- private toMetadata;
40
- }
41
- export {};
@@ -1,162 +0,0 @@
1
- export class ChromaHttpClient {
2
- baseUrl;
3
- tenant;
4
- database;
5
- collectionIds = new Map();
6
- constructor(options = {}) {
7
- this.baseUrl = options.baseUrl ?? process.env.CHROMA_URL ?? process.env.CHROMA_BASE_URL ?? 'http://localhost:17322';
8
- this.tenant = options.tenant ?? 'default_tenant';
9
- this.database = options.database ?? 'default_database';
10
- }
11
- async heartbeat() {
12
- try {
13
- await this.request('/api/v2/heartbeat');
14
- return true;
15
- }
16
- catch {
17
- return false;
18
- }
19
- }
20
- async getOrCreateCollection(name, metadata = {}) {
21
- const body = { name, get_or_create: true };
22
- if (Object.keys(metadata).length > 0)
23
- body.metadata = metadata;
24
- const response = await this.request(this.collectionsPath(), {
25
- method: 'POST',
26
- body: JSON.stringify(body),
27
- }, 10000);
28
- if (response.id)
29
- this.collectionIds.set(name, response.id);
30
- return this.toCollectionInfo(response);
31
- }
32
- async listCollections() {
33
- const response = await this.request(this.collectionsPath(), {}, 10000);
34
- for (const collection of response)
35
- if (collection.id)
36
- this.collectionIds.set(collection.name, collection.id);
37
- return response.map(collection => this.toCollectionInfo(collection));
38
- }
39
- async deleteCollection(name) {
40
- await this.request(`${this.collectionsPath()}/${encodeURIComponent(name)}`, { method: 'DELETE' });
41
- this.collectionIds.delete(name);
42
- }
43
- async upsert(collectionName, documents) {
44
- if (documents.length === 0)
45
- return;
46
- const collectionId = await this.getCollectionId(collectionName);
47
- await this.request(`${this.collectionsPath()}/${encodeURIComponent(collectionId)}/upsert`, {
48
- method: 'POST',
49
- body: JSON.stringify({
50
- ids: documents.map(document => document.id),
51
- embeddings: documents.map(document => document.embedding),
52
- documents: documents.map(document => document.content),
53
- metadatas: documents.map(document => document.metadata),
54
- }),
55
- }, 30000);
56
- }
57
- async deleteWhere(collectionName, where) {
58
- const collectionId = await this.getCollectionId(collectionName);
59
- await this.request(`${this.collectionsPath()}/${encodeURIComponent(collectionId)}/delete`, {
60
- method: 'POST',
61
- body: JSON.stringify({ where }),
62
- }, 10000);
63
- }
64
- async query(collectionName, query) {
65
- const collectionId = await this.getCollectionId(collectionName);
66
- return this.request(`${this.collectionsPath()}/${encodeURIComponent(collectionId)}/query`, {
67
- method: 'POST',
68
- body: JSON.stringify({
69
- query_embeddings: [query.queryEmbedding],
70
- n_results: query.topK,
71
- where: query.where,
72
- include: ['documents', 'metadatas', 'distances'],
73
- }),
74
- }, 10000);
75
- }
76
- async getCollectionId(name) {
77
- const cached = this.collectionIds.get(name);
78
- if (cached)
79
- return cached;
80
- const collection = await this.getOrCreateCollection(name);
81
- if (!collection.id)
82
- throw new Error(`ChromaDB collection has no id: ${name}`);
83
- this.collectionIds.set(name, collection.id);
84
- return collection.id;
85
- }
86
- collectionsPath() {
87
- return `/api/v2/tenants/${encodeURIComponent(this.tenant)}/databases/${encodeURIComponent(this.database)}/collections`;
88
- }
89
- async request(path, init = {}, timeoutMs = 3000) {
90
- const controller = new AbortController();
91
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
92
- let response;
93
- try {
94
- response = await fetch(`${this.baseUrl}${path}`, {
95
- ...init,
96
- signal: controller.signal,
97
- headers: {
98
- 'content-type': 'application/json',
99
- ...(init.headers ?? {}),
100
- },
101
- });
102
- }
103
- finally {
104
- clearTimeout(timeout);
105
- }
106
- if (!response.ok) {
107
- throw new Error(`ChromaDB request failed: ${response.status} ${response.statusText}`);
108
- }
109
- if (response.status === 204)
110
- return undefined;
111
- return await response.json();
112
- }
113
- toCollectionInfo(collection) {
114
- return {
115
- id: collection.id,
116
- name: collection.name,
117
- metadata: collection.metadata,
118
- };
119
- }
120
- }
121
- export class ChromaVectorStore {
122
- client;
123
- collectionName;
124
- constructor(client, collectionName) {
125
- this.client = client;
126
- this.collectionName = collectionName;
127
- }
128
- async ensureCollection(metadata) {
129
- await this.client.getOrCreateCollection(this.collectionName, metadata);
130
- }
131
- async upsert(documents) {
132
- await this.client.upsert(this.collectionName, documents);
133
- }
134
- async deleteByFilePath(filePath) {
135
- await this.client.deleteWhere(this.collectionName, { file_path: filePath });
136
- }
137
- async search(query) {
138
- const response = await this.client.query(this.collectionName, query);
139
- const ids = response.ids?.[0] ?? [];
140
- const documents = response.documents?.[0] ?? [];
141
- const metadatas = response.metadatas?.[0] ?? [];
142
- const distances = response.distances?.[0] ?? [];
143
- return ids.map((id, index) => ({
144
- collection: this.collectionName,
145
- score: 1 - Number(distances[index] ?? 1),
146
- document: {
147
- id,
148
- content: documents[index] ?? '',
149
- metadata: this.toMetadata(metadatas[index] ?? {}),
150
- },
151
- }));
152
- }
153
- toMetadata(metadata) {
154
- const result = {};
155
- for (const [key, value] of Object.entries(metadata)) {
156
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) {
157
- result[key] = value;
158
- }
159
- }
160
- return result;
161
- }
162
- }
@@ -1,37 +0,0 @@
1
- import type { CollectionClient, VectorCollectionInfo, VectorDocument, VectorSearchQuery, VectorSearchResult, VectorStoreInterface } from './types.js';
2
- interface QdrantSearchPoint {
3
- id: string | number;
4
- score?: number;
5
- payload?: Record<string, unknown>;
6
- }
7
- export interface QdrantClientOptions {
8
- baseUrl?: string;
9
- }
10
- export declare class QdrantHttpClient implements CollectionClient {
11
- readonly baseUrl: string;
12
- constructor(options?: QdrantClientOptions);
13
- heartbeat(): Promise<boolean>;
14
- getOrCreateCollection(name: string, metadata?: Record<string, unknown>): Promise<VectorCollectionInfo>;
15
- listCollections(): Promise<VectorCollectionInfo[]>;
16
- deleteCollection(name: string): Promise<void>;
17
- upsert(collectionName: string, documents: VectorDocument[]): Promise<void>;
18
- deleteWhere(collectionName: string, where: Record<string, string | number | boolean>): Promise<void>;
19
- search(collectionName: string, query: VectorSearchQuery): Promise<QdrantSearchPoint[]>;
20
- private getCollection;
21
- private toFilter;
22
- private pointId;
23
- private toPayload;
24
- private request;
25
- }
26
- export declare class QdrantVectorStore implements VectorStoreInterface {
27
- private readonly client;
28
- readonly collectionName: string;
29
- constructor(client: QdrantHttpClient, collectionName: string);
30
- ensureCollection(metadata?: Record<string, unknown>): Promise<void>;
31
- upsert(documents: VectorDocument[]): Promise<void>;
32
- deleteByFilePath(filePath: string): Promise<void>;
33
- search(query: VectorSearchQuery): Promise<VectorSearchResult[]>;
34
- private payloadString;
35
- private toMetadata;
36
- }
37
- export {};
@@ -1,172 +0,0 @@
1
- import * as crypto from 'node:crypto';
2
- export class QdrantHttpClient {
3
- baseUrl;
4
- constructor(options = {}) {
5
- this.baseUrl = options.baseUrl ?? process.env.QDRANT_URL ?? process.env.QDRANT_BASE_URL ?? 'http://127.0.0.1:6333';
6
- }
7
- async heartbeat() {
8
- try {
9
- await this.request('/collections', {}, 3000);
10
- return true;
11
- }
12
- catch {
13
- return false;
14
- }
15
- }
16
- async getOrCreateCollection(name, metadata = {}) {
17
- const existing = await this.getCollection(name);
18
- if (existing)
19
- return existing;
20
- const size = Number(metadata.embedding_dimension ?? process.env.QDRANT_VECTOR_SIZE ?? 384);
21
- await this.request(`/collections/${encodeURIComponent(name)}`, {
22
- method: 'PUT',
23
- body: JSON.stringify({
24
- vectors: { size, distance: 'Cosine' },
25
- on_disk_payload: true,
26
- }),
27
- }, 30000);
28
- return { name, metadata };
29
- }
30
- async listCollections() {
31
- const response = await this.request('/collections', {}, 10000);
32
- return (response.result?.collections ?? []).map(collection => ({ name: collection.name }));
33
- }
34
- async deleteCollection(name) {
35
- await this.request(`/collections/${encodeURIComponent(name)}`, { method: 'DELETE' }, 30000);
36
- }
37
- async upsert(collectionName, documents) {
38
- if (documents.length === 0)
39
- return;
40
- await this.request(`/collections/${encodeURIComponent(collectionName)}/points?wait=true`, {
41
- method: 'PUT',
42
- body: JSON.stringify({
43
- points: documents.map(document => ({
44
- id: this.pointId(document.id),
45
- vector: document.embedding,
46
- payload: this.toPayload({
47
- ...document.metadata,
48
- id: document.id,
49
- content: document.content,
50
- }),
51
- })),
52
- }),
53
- }, 60000);
54
- }
55
- async deleteWhere(collectionName, where) {
56
- await this.request(`/collections/${encodeURIComponent(collectionName)}/points/delete?wait=true`, {
57
- method: 'POST',
58
- body: JSON.stringify({
59
- filter: this.toFilter(where),
60
- }),
61
- }, 30000);
62
- }
63
- async search(collectionName, query) {
64
- const response = await this.request(`/collections/${encodeURIComponent(collectionName)}/points/search`, {
65
- method: 'POST',
66
- body: JSON.stringify({
67
- vector: query.queryEmbedding,
68
- limit: query.topK,
69
- filter: query.where ? this.toFilter(query.where) : undefined,
70
- with_payload: true,
71
- }),
72
- }, 30000);
73
- return response.result ?? [];
74
- }
75
- async getCollection(name) {
76
- try {
77
- await this.request(`/collections/${encodeURIComponent(name)}`, {}, 10000);
78
- return { name };
79
- }
80
- catch (error) {
81
- if (error instanceof Error && error.message.includes('404'))
82
- return undefined;
83
- throw error;
84
- }
85
- }
86
- toFilter(where) {
87
- return {
88
- must: Object.entries(where).map(([key, value]) => ({ key, match: { value } })),
89
- };
90
- }
91
- pointId(id) {
92
- const hash = crypto.createHash('sha256').update(id).digest('hex');
93
- return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
94
- }
95
- toPayload(payload) {
96
- const result = {};
97
- for (const [key, value] of Object.entries(payload)) {
98
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
99
- result[key] = value;
100
- }
101
- }
102
- return result;
103
- }
104
- async request(path, init = {}, timeoutMs = 3000) {
105
- const controller = new AbortController();
106
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
107
- let response;
108
- try {
109
- response = await fetch(`${this.baseUrl}${path}`, {
110
- ...init,
111
- signal: controller.signal,
112
- headers: {
113
- 'content-type': 'application/json',
114
- ...(init.headers ?? {}),
115
- },
116
- });
117
- }
118
- finally {
119
- clearTimeout(timeout);
120
- }
121
- if (!response.ok) {
122
- const body = await response.text().catch(() => '');
123
- throw new Error(`Qdrant request failed: ${response.status} ${response.statusText} ${body}`.trim());
124
- }
125
- if (response.status === 204)
126
- return undefined;
127
- return await response.json();
128
- }
129
- }
130
- export class QdrantVectorStore {
131
- client;
132
- collectionName;
133
- constructor(client, collectionName) {
134
- this.client = client;
135
- this.collectionName = collectionName;
136
- }
137
- async ensureCollection(metadata) {
138
- await this.client.getOrCreateCollection(this.collectionName, metadata);
139
- }
140
- async upsert(documents) {
141
- await this.client.upsert(this.collectionName, documents);
142
- }
143
- async deleteByFilePath(filePath) {
144
- await this.client.deleteWhere(this.collectionName, { file_path: filePath });
145
- }
146
- async search(query) {
147
- const points = await this.client.search(this.collectionName, query);
148
- return points.map(point => ({
149
- collection: this.collectionName,
150
- score: Number(point.score ?? 0),
151
- document: {
152
- id: this.payloadString(point.payload?.id) ?? String(point.id),
153
- content: this.payloadString(point.payload?.content) ?? '',
154
- metadata: this.toMetadata(point.payload ?? {}),
155
- },
156
- }));
157
- }
158
- payloadString(value) {
159
- return typeof value === 'string' ? value : undefined;
160
- }
161
- toMetadata(payload) {
162
- const result = {};
163
- for (const [key, value] of Object.entries(payload)) {
164
- if (key === 'content')
165
- continue;
166
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) {
167
- result[key] = value;
168
- }
169
- }
170
- return result;
171
- }
172
- }