@chatcops/core 0.5.0 → 0.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/dist/agent/run-turn.d.ts +11 -0
- package/dist/agent/run-turn.d.ts.map +1 -1
- package/dist/agent/run-turn.js +65 -9
- package/dist/agent/run-turn.js.map +1 -1
- package/dist/agent/tool-registry.d.ts +2 -0
- package/dist/agent/tool-registry.d.ts.map +1 -1
- package/dist/agent/tool-registry.js +4 -7
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/analytics/collector.d.ts +2 -0
- package/dist/analytics/collector.d.ts.map +1 -1
- package/dist/analytics/collector.js +16 -10
- package/dist/analytics/collector.js.map +1 -1
- package/dist/analytics/index.d.ts +1 -0
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/analytics/index.js +1 -0
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/names.d.ts +21 -0
- package/dist/analytics/names.d.ts.map +1 -0
- package/dist/analytics/names.js +41 -0
- package/dist/analytics/names.js.map +1 -0
- package/dist/analytics/sink.d.ts +3 -0
- package/dist/analytics/sink.d.ts.map +1 -1
- package/dist/analytics/sink.js +15 -12
- package/dist/analytics/sink.js.map +1 -1
- package/dist/conversation/manager.d.ts +3 -0
- package/dist/conversation/manager.d.ts.map +1 -1
- package/dist/conversation/manager.js +2 -1
- package/dist/conversation/manager.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/knowledge/base.d.ts +8 -0
- package/dist/knowledge/base.d.ts.map +1 -1
- package/dist/knowledge/tokenize.d.ts.map +1 -1
- package/dist/knowledge/tokenize.js +4 -4
- package/dist/knowledge/tokenize.js.map +1 -1
- package/dist/logger.d.ts +36 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +40 -0
- package/dist/logger.js.map +1 -0
- package/dist/providers/base.d.ts +2 -1
- package/dist/providers/base.d.ts.map +1 -1
- package/dist/providers/base.js +2 -2
- package/dist/providers/base.js.map +1 -1
- package/dist/providers/claude.d.ts +15 -1
- package/dist/providers/claude.d.ts.map +1 -1
- package/dist/providers/claude.js +48 -8
- package/dist/providers/claude.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +6 -3
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/tool-execution.d.ts +3 -0
- package/dist/providers/tool-execution.d.ts.map +1 -1
- package/dist/providers/tool-execution.js +13 -3
- package/dist/providers/tool-execution.js.map +1 -1
- package/dist/providers/types.d.ts +18 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/retrieval/citations.d.ts +44 -0
- package/dist/retrieval/citations.d.ts.map +1 -0
- package/dist/retrieval/citations.js +97 -0
- package/dist/retrieval/citations.js.map +1 -0
- package/dist/retrieval/cohere-reranker.d.ts +13 -0
- package/dist/retrieval/cohere-reranker.d.ts.map +1 -0
- package/dist/retrieval/cohere-reranker.js +33 -0
- package/dist/retrieval/cohere-reranker.js.map +1 -0
- package/dist/retrieval/gemini-embedder.d.ts +26 -0
- package/dist/retrieval/gemini-embedder.d.ts.map +1 -0
- package/dist/retrieval/gemini-embedder.js +36 -0
- package/dist/retrieval/gemini-embedder.js.map +1 -0
- package/dist/retrieval/http.d.ts +20 -0
- package/dist/retrieval/http.d.ts.map +1 -0
- package/dist/retrieval/http.js +68 -0
- package/dist/retrieval/http.js.map +1 -0
- package/dist/retrieval/index.d.ts +14 -0
- package/dist/retrieval/index.d.ts.map +1 -0
- package/dist/retrieval/index.js +13 -0
- package/dist/retrieval/index.js.map +1 -0
- package/dist/retrieval/knowledge.d.ts +16 -0
- package/dist/retrieval/knowledge.d.ts.map +1 -0
- package/dist/retrieval/knowledge.js +21 -0
- package/dist/retrieval/knowledge.js.map +1 -0
- package/dist/retrieval/openai-embedder.d.ts +25 -0
- package/dist/retrieval/openai-embedder.d.ts.map +1 -0
- package/dist/retrieval/openai-embedder.js +30 -0
- package/dist/retrieval/openai-embedder.js.map +1 -0
- package/dist/retrieval/query.d.ts +8 -0
- package/dist/retrieval/query.d.ts.map +1 -0
- package/dist/retrieval/query.js +19 -0
- package/dist/retrieval/query.js.map +1 -0
- package/dist/retrieval/retrievers.d.ts +30 -0
- package/dist/retrieval/retrievers.d.ts.map +1 -0
- package/dist/retrieval/retrievers.js +89 -0
- package/dist/retrieval/retrievers.js.map +1 -0
- package/dist/retrieval/sources.d.ts +16 -0
- package/dist/retrieval/sources.d.ts.map +1 -0
- package/dist/retrieval/sources.js +37 -0
- package/dist/retrieval/sources.js.map +1 -0
- package/dist/retrieval/types.d.ts +50 -0
- package/dist/retrieval/types.d.ts.map +1 -0
- package/dist/retrieval/types.js +2 -0
- package/dist/retrieval/types.js.map +1 -0
- package/dist/retrieval/voyage-embedder.d.ts +33 -0
- package/dist/retrieval/voyage-embedder.d.ts.map +1 -0
- package/dist/retrieval/voyage-embedder.js +33 -0
- package/dist/retrieval/voyage-embedder.js.map +1 -0
- package/dist/retrieval/voyage-reranker.d.ts +13 -0
- package/dist/retrieval/voyage-reranker.d.ts.map +1 -0
- package/dist/retrieval/voyage-reranker.js +38 -0
- package/dist/retrieval/voyage-reranker.js.map +1 -0
- package/dist/retrieval/workers-ai-embedder.d.ts +21 -0
- package/dist/retrieval/workers-ai-embedder.d.ts.map +1 -0
- package/dist/retrieval/workers-ai-embedder.js +42 -0
- package/dist/retrieval/workers-ai-embedder.js.map +1 -0
- package/dist/retrieval/workers-ai-reranker.d.ts +11 -0
- package/dist/retrieval/workers-ai-reranker.d.ts.map +1 -0
- package/dist/retrieval/workers-ai-reranker.js +54 -0
- package/dist/retrieval/workers-ai-reranker.js.map +1 -0
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/memory-vectors.d.ts +22 -0
- package/dist/storage/memory-vectors.d.ts.map +1 -0
- package/dist/storage/memory-vectors.js +140 -0
- package/dist/storage/memory-vectors.js.map +1 -0
- package/dist/storage/types.d.ts +70 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/testing/conformance.d.ts +4 -3
- package/dist/testing/conformance.d.ts.map +1 -1
- package/dist/testing/conformance.js +172 -2
- package/dist/testing/conformance.js.map +1 -1
- package/dist/testing/provider.d.ts +2 -0
- package/dist/testing/provider.d.ts.map +1 -1
- package/dist/testing/provider.js +1 -0
- package/dist/testing/provider.js.map +1 -1
- package/dist/tools/lead-capture.d.ts +2 -2
- package/dist/tools/lead-capture.d.ts.map +1 -1
- package/dist/tools/lead-capture.js +3 -2
- package/dist/tools/lead-capture.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { MetadataFilter, MetadataValue, VectorSource } from '../storage/types.js';
|
|
2
|
+
import type { ChatMessage } from '../types.js';
|
|
3
|
+
/** Turns text into vectors. The same embedder has to build an index and search it. */
|
|
4
|
+
export interface Embedder {
|
|
5
|
+
/**
|
|
6
|
+
* Names the model and size, such as `openai:text-embedding-3-small@1024`.
|
|
7
|
+
* Stored with an index, so searching it with a different embedder is caught.
|
|
8
|
+
*/
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly dimensions: number;
|
|
11
|
+
/**
|
|
12
|
+
* One vector per text, in order. Some models embed a search query
|
|
13
|
+
* differently from the documents it searches, hence `kind`.
|
|
14
|
+
*/
|
|
15
|
+
embed(texts: string[], kind: 'document' | 'query', options?: {
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}): Promise<Float32Array[]>;
|
|
18
|
+
}
|
|
19
|
+
/** A piece of a page that matched a question. */
|
|
20
|
+
export interface RetrievedChunk {
|
|
21
|
+
id: string;
|
|
22
|
+
text: string;
|
|
23
|
+
/** Higher is better. Only comparable between chunks from the same retriever. */
|
|
24
|
+
score: number;
|
|
25
|
+
source: VectorSource;
|
|
26
|
+
metadata?: Record<string, MetadataValue>;
|
|
27
|
+
}
|
|
28
|
+
export interface RetrievalQuery {
|
|
29
|
+
/** The visitor's latest message. */
|
|
30
|
+
text: string;
|
|
31
|
+
/** How many chunks to return. Retrievers default to 5. */
|
|
32
|
+
topK?: number;
|
|
33
|
+
filter?: MetadataFilter;
|
|
34
|
+
/** The conversation before `text`, oldest first, for follow-up questions. */
|
|
35
|
+
history?: ChatMessage[];
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
export interface Retriever {
|
|
39
|
+
retrieve(query: RetrievalQuery): Promise<RetrievedChunk[]>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Puts chunks in a better order for a question, usually with a model trained
|
|
43
|
+
* for it. Retrievers hand it more candidates than they return.
|
|
44
|
+
*/
|
|
45
|
+
export interface Reranker {
|
|
46
|
+
rerank(query: string, chunks: RetrievedChunk[], topN: number, options?: {
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
}): Promise<RetrievedChunk[]>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/retrieval/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,sFAAsF;AACtF,MAAM,WAAW,QAAQ;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACjH;AAED,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CAC9H"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/retrieval/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Embedder } from './types.js';
|
|
2
|
+
export interface VoyageEmbedderOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
/** Default `voyage-4-large`. */
|
|
5
|
+
model?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Vector length. Default 1024, which every planned store can index and every
|
|
8
|
+
* current Voyage model can produce. Only the models that take
|
|
9
|
+
* `output_dimension` (`voyage-4`, `voyage-4-large`, `voyage-4-lite`,
|
|
10
|
+
* `voyage-3.5`, `voyage-3.5-lite`, `voyage-3-large` and `voyage-code-3`) can
|
|
11
|
+
* change it, to 256, 512, 1024 or 2048. For any other model, set the model's
|
|
12
|
+
* own length.
|
|
13
|
+
*/
|
|
14
|
+
dimensions?: number;
|
|
15
|
+
/** Default `https://api.voyageai.com/v1`, or a proxy for it. */
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Texts per request. Default 128, and at most 1000, which is what Voyage
|
|
19
|
+
* accepts. Every model also limits the tokens in one request (120,000 for
|
|
20
|
+
* `voyage-4-large`), so lower this for very long texts.
|
|
21
|
+
*/
|
|
22
|
+
batchSize?: number;
|
|
23
|
+
/** For tests and proxies. */
|
|
24
|
+
fetch?: typeof fetch;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Embeddings from Voyage AI's API, with `fetch` only. Queries and documents are
|
|
28
|
+
* embedded differently (`input_type`), so `kind` is sent on. Rate limits and
|
|
29
|
+
* server errors are retried twice, waiting as long as `retry-after` says (or
|
|
30
|
+
* 1s, then 2s).
|
|
31
|
+
*/
|
|
32
|
+
export declare function voyageEmbedder(options: VoyageEmbedderOptions): Embedder;
|
|
33
|
+
//# sourceMappingURL=voyage-embedder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voyage-embedder.d.ts","sourceRoot":"","sources":["../../src/retrieval/voyage-embedder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,QAAQ,CA4BvE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { batchSizeFor, checkedVectors, inBatches, postWithRetries } from './http.js';
|
|
2
|
+
const MAX_BATCH_SIZE = 1000;
|
|
3
|
+
// The models whose docs list `output_dimension`. The others make one fixed length.
|
|
4
|
+
const SHORTENABLE = /^voyage-(?:4|3\.5|3-large|code-3)(?:-|$)/;
|
|
5
|
+
/**
|
|
6
|
+
* Embeddings from Voyage AI's API, with `fetch` only. Queries and documents are
|
|
7
|
+
* embedded differently (`input_type`), so `kind` is sent on. Rate limits and
|
|
8
|
+
* server errors are retried twice, waiting as long as `retry-after` says (or
|
|
9
|
+
* 1s, then 2s).
|
|
10
|
+
*/
|
|
11
|
+
export function voyageEmbedder(options) {
|
|
12
|
+
const model = options.model ?? 'voyage-4-large';
|
|
13
|
+
const dimensions = options.dimensions ?? 1024;
|
|
14
|
+
const baseUrl = (options.baseUrl ?? 'https://api.voyageai.com/v1').replace(/\/$/, '');
|
|
15
|
+
const batchSize = batchSizeFor(options.batchSize, 128, MAX_BATCH_SIZE);
|
|
16
|
+
const send = options.fetch ?? fetch;
|
|
17
|
+
const shortens = SHORTENABLE.test(model);
|
|
18
|
+
return {
|
|
19
|
+
id: `voyage:${model}@${dimensions}`,
|
|
20
|
+
dimensions,
|
|
21
|
+
embed: (texts, kind, embedOptions = {}) => inBatches(texts, batchSize, async (input) => {
|
|
22
|
+
const response = await postWithRetries('Voyage', send, {
|
|
23
|
+
url: `${baseUrl}/embeddings`,
|
|
24
|
+
headers: { authorization: `Bearer ${options.apiKey}` },
|
|
25
|
+
body: { model, input, input_type: kind, ...(shortens ? { output_dimension: dimensions } : {}) },
|
|
26
|
+
}, embedOptions.signal);
|
|
27
|
+
const body = (await response.json());
|
|
28
|
+
const data = [...(body.data ?? [])].sort((a, b) => a.index - b.index);
|
|
29
|
+
return checkedVectors('Voyage', model, data.map((item) => item.embedding), input.length, dimensions);
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=voyage-embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voyage-embedder.js","sourceRoot":"","sources":["../../src/retrieval/voyage-embedder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AA4BrF,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,mFAAmF;AACnF,MAAM,WAAW,GAAG,0CAA0C,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,gBAAgB,CAAC;IAChD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,6BAA6B,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtF,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEzC,OAAO;QACL,EAAE,EAAE,UAAU,KAAK,IAAI,UAAU,EAAE;QACnC,UAAU;QACV,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,GAAG,EAAE,EAAE,EAAE,CACxC,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC1C,MAAM,QAAQ,GAAG,MAAM,eAAe,CACpC,QAAQ,EACR,IAAI,EACJ;gBACE,GAAG,EAAE,GAAG,OAAO,aAAa;gBAC5B,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE,EAAE;gBACtD,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;aAChG,EACD,YAAY,CAAC,MAAM,CACpB,CAAC;YACF,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6D,CAAC;YACjG,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YACtE,OAAO,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACvG,CAAC,CAAC;KACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Reranker } from './types.js';
|
|
2
|
+
export interface VoyageRerankerOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
/** Default `rerank-3`, Voyage's current recommended model. */
|
|
5
|
+
model?: string;
|
|
6
|
+
/** Default `https://api.voyageai.com/v1`, or a proxy for it. */
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
/** For tests and proxies. */
|
|
9
|
+
fetch?: typeof fetch;
|
|
10
|
+
}
|
|
11
|
+
/** Reranks retrieved chunks with Voyage AI's Reranker API. */
|
|
12
|
+
export declare function voyageReranker(options: VoyageRerankerOptions): Reranker;
|
|
13
|
+
//# sourceMappingURL=voyage-reranker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voyage-reranker.d.ts","sourceRoot":"","sources":["../../src/retrieval/voyage-reranker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAMD,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,QAAQ,CA2CvE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { postWithRetries } from './http.js';
|
|
2
|
+
/** Reranks retrieved chunks with Voyage AI's Reranker API. */
|
|
3
|
+
export function voyageReranker(options) {
|
|
4
|
+
const model = options.model ?? 'rerank-3';
|
|
5
|
+
const baseUrl = (options.baseUrl ?? 'https://api.voyageai.com/v1').replace(/\/$/, '');
|
|
6
|
+
const send = options.fetch ?? fetch;
|
|
7
|
+
return {
|
|
8
|
+
async rerank(query, chunks, topN, rerankOptions = {}) {
|
|
9
|
+
const limit = Math.floor(topN);
|
|
10
|
+
if (chunks.length === 0 || limit <= 0)
|
|
11
|
+
return [];
|
|
12
|
+
const response = await postWithRetries('Voyage', send, {
|
|
13
|
+
url: `${baseUrl}/rerank`,
|
|
14
|
+
headers: { authorization: `Bearer ${options.apiKey}` },
|
|
15
|
+
body: { query, documents: chunks.map((chunk) => chunk.text), model, top_k: Math.min(limit, chunks.length) },
|
|
16
|
+
}, rerankOptions.signal, 'rerank');
|
|
17
|
+
const body = (await response.json());
|
|
18
|
+
if (!body || typeof body !== 'object' || !Array.isArray(body.data)) {
|
|
19
|
+
throw new Error('Voyage returned an invalid rerank response: data must be an array.');
|
|
20
|
+
}
|
|
21
|
+
return body.data.slice(0, limit).map(({ index, relevance_score }) => {
|
|
22
|
+
if (typeof index !== 'number' ||
|
|
23
|
+
!Number.isInteger(index) ||
|
|
24
|
+
index < 0 ||
|
|
25
|
+
index >= chunks.length ||
|
|
26
|
+
typeof relevance_score !== 'number' ||
|
|
27
|
+
!Number.isFinite(relevance_score)) {
|
|
28
|
+
throw new Error('Voyage returned an invalid rerank result.');
|
|
29
|
+
}
|
|
30
|
+
const chunk = chunks[index];
|
|
31
|
+
if (!chunk)
|
|
32
|
+
throw new Error('Voyage returned an invalid rerank result.');
|
|
33
|
+
return { ...chunk, score: relevance_score };
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=voyage-reranker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voyage-reranker.js","sourceRoot":"","sources":["../../src/retrieval/voyage-reranker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAiB5C,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC;IAC1C,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,6BAA6B,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IAEpC,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,EAAE;YAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;gBAAE,OAAO,EAAE,CAAC;YAEjD,MAAM,QAAQ,GAAG,MAAM,eAAe,CACpC,QAAQ,EACR,IAAI,EACJ;gBACE,GAAG,EAAE,GAAG,OAAO,SAAS;gBACxB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE,EAAE;gBACtD,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE;aAC5G,EACD,aAAa,CAAC,MAAM,EACpB,QAAQ,CACT,CAAC;YAEF,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;YAC7D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnE,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;YACxF,CAAC;YACD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE;gBAClE,IACE,OAAO,KAAK,KAAK,QAAQ;oBACzB,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;oBACxB,KAAK,GAAG,CAAC;oBACT,KAAK,IAAI,MAAM,CAAC,MAAM;oBACtB,OAAO,eAAe,KAAK,QAAQ;oBACnC,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EACjC,CAAC;oBACD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;gBAC/D,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5B,IAAI,CAAC,KAAK;oBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;gBACzE,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Embedder } from './types.js';
|
|
2
|
+
export interface WorkersAiBinding {
|
|
3
|
+
run(model: string, input: unknown): Promise<unknown>;
|
|
4
|
+
}
|
|
5
|
+
export interface WorkersAiEmbedderOptions {
|
|
6
|
+
/** The Cloudflare Workers AI binding (`env.AI`). */
|
|
7
|
+
ai: WorkersAiBinding;
|
|
8
|
+
/** Default `@cf/baai/bge-m3`. */
|
|
9
|
+
model?: string;
|
|
10
|
+
/** Vector length. Default 1024. */
|
|
11
|
+
dimensions?: number;
|
|
12
|
+
/** Max texts per `ai.run` call. Default 100, matching the model input limit. */
|
|
13
|
+
batchSize?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Embeddings from Cloudflare Workers AI via binding (`env.AI`).
|
|
17
|
+
* Calls `ai.run` in batches (default up to 100 texts), validating
|
|
18
|
+
* response shape, vector count and dimensions.
|
|
19
|
+
*/
|
|
20
|
+
export declare function workersAiEmbedder(options: WorkersAiEmbedderOptions): Embedder;
|
|
21
|
+
//# sourceMappingURL=workers-ai-embedder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workers-ai-embedder.d.ts","sourceRoot":"","sources":["../../src/retrieval/workers-ai-embedder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,wBAAwB;IACvC,oDAAoD;IACpD,EAAE,EAAE,gBAAgB,CAAC;IACrB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,CAiC7E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { batchSizeFor, checkedVectors, inBatches } from './http.js';
|
|
2
|
+
const DEFAULT_MODEL = '@cf/baai/bge-m3';
|
|
3
|
+
const DEFAULT_DIMENSIONS = 1024;
|
|
4
|
+
const DEFAULT_BATCH_SIZE = 100;
|
|
5
|
+
/**
|
|
6
|
+
* Embeddings from Cloudflare Workers AI via binding (`env.AI`).
|
|
7
|
+
* Calls `ai.run` in batches (default up to 100 texts), validating
|
|
8
|
+
* response shape, vector count and dimensions.
|
|
9
|
+
*/
|
|
10
|
+
export function workersAiEmbedder(options) {
|
|
11
|
+
if (!options?.ai || typeof options.ai.run !== 'function') {
|
|
12
|
+
throw new Error('workersAiEmbedder requires an ai binding with a run() method.');
|
|
13
|
+
}
|
|
14
|
+
const model = options.model ?? DEFAULT_MODEL;
|
|
15
|
+
const dimensions = options.dimensions ?? DEFAULT_DIMENSIONS;
|
|
16
|
+
const batchSize = batchSizeFor(options.batchSize, DEFAULT_BATCH_SIZE, DEFAULT_BATCH_SIZE);
|
|
17
|
+
const ai = options.ai;
|
|
18
|
+
return {
|
|
19
|
+
id: `workers-ai:${model}@${dimensions}`,
|
|
20
|
+
dimensions,
|
|
21
|
+
async embed(texts, _kind, embedOptions = {}) {
|
|
22
|
+
if (embedOptions.signal?.aborted) {
|
|
23
|
+
throw embedOptions.signal.reason;
|
|
24
|
+
}
|
|
25
|
+
return inBatches(texts, batchSize, async (batch) => {
|
|
26
|
+
if (embedOptions.signal?.aborted) {
|
|
27
|
+
throw embedOptions.signal.reason;
|
|
28
|
+
}
|
|
29
|
+
const response = await ai.run(model, { text: batch });
|
|
30
|
+
if (!response || typeof response !== 'object' || !('data' in response) || !Array.isArray(response.data)) {
|
|
31
|
+
throw new Error(`Workers AI returned an invalid response for ${model}.`);
|
|
32
|
+
}
|
|
33
|
+
const data = response.data;
|
|
34
|
+
if (data.some((embedding) => !Array.isArray(embedding) && !(embedding instanceof Float32Array))) {
|
|
35
|
+
throw new Error(`Workers AI returned an invalid embedding for ${model}.`);
|
|
36
|
+
}
|
|
37
|
+
return checkedVectors('Workers AI', model, data, batch.length, dimensions);
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=workers-ai-embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workers-ai-embedder.js","sourceRoot":"","sources":["../../src/retrieval/workers-ai-embedder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAkBpE,MAAM,aAAa,GAAG,iBAAiB,CAAC;AACxC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAiC;IACjE,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,OAAO,OAAO,CAAC,EAAE,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,CAAC;IAC5D,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;IAC1F,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;IAEtB,OAAO;QACL,EAAE,EAAE,cAAc,KAAK,IAAI,UAAU,EAAE;QACvC,UAAU;QACV,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,GAAG,EAAE;YACzC,IAAI,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBACjC,MAAM,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC;YACnC,CAAC;YACD,OAAO,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACjD,IAAI,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;oBACjC,MAAM,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC;gBACnC,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACtD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,QAA+B,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChI,MAAM,IAAI,KAAK,CAAC,+CAA+C,KAAK,GAAG,CAAC,CAAC;gBAC3E,CAAC;gBACD,MAAM,IAAI,GAAI,QAAgC,CAAC,IAAI,CAAC;gBACpD,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,YAAY,YAAY,CAAC,CAAC,EAAE,CAAC;oBAChG,MAAM,IAAI,KAAK,CAAC,gDAAgD,KAAK,GAAG,CAAC,CAAC;gBAC5E,CAAC;gBACD,OAAO,cAAc,CAAC,YAAY,EAAE,KAAK,EAAE,IAA6B,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACtG,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Reranker } from './types.js';
|
|
2
|
+
import type { WorkersAiBinding } from './workers-ai-embedder.js';
|
|
3
|
+
export interface WorkersAiRerankerOptions {
|
|
4
|
+
/** The Cloudflare Workers AI binding (`env.AI`). */
|
|
5
|
+
ai: WorkersAiBinding;
|
|
6
|
+
/** Default `@cf/baai/bge-reranker-base`. */
|
|
7
|
+
model?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Reranks retrieved chunks with Cloudflare Workers AI via the native binding. */
|
|
10
|
+
export declare function workersAiReranker(options: WorkersAiRerankerOptions): Reranker;
|
|
11
|
+
//# sourceMappingURL=workers-ai-reranker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workers-ai-reranker.d.ts","sourceRoot":"","sources":["../../src/retrieval/workers-ai-reranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,WAAW,wBAAwB;IACvC,oDAAoD;IACpD,EAAE,EAAE,gBAAgB,CAAC;IACrB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AASD,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,QAAQ,CAuD7E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const DEFAULT_MODEL = '@cf/baai/bge-reranker-base';
|
|
2
|
+
/** Reranks retrieved chunks with Cloudflare Workers AI via the native binding. */
|
|
3
|
+
export function workersAiReranker(options) {
|
|
4
|
+
if (!options?.ai || typeof options.ai.run !== 'function') {
|
|
5
|
+
throw new Error('workersAiReranker requires an ai binding with a run() method.');
|
|
6
|
+
}
|
|
7
|
+
const model = options.model ?? DEFAULT_MODEL;
|
|
8
|
+
const ai = options.ai;
|
|
9
|
+
return {
|
|
10
|
+
async rerank(query, chunks, topN, rerankOptions = {}) {
|
|
11
|
+
if (rerankOptions.signal?.aborted)
|
|
12
|
+
throw rerankOptions.signal.reason;
|
|
13
|
+
const requestedLimit = Number.isFinite(topN) && topN > 0 ? Math.floor(topN) : 0;
|
|
14
|
+
if (!requestedLimit || !chunks.length)
|
|
15
|
+
return [];
|
|
16
|
+
const limit = Math.min(requestedLimit, chunks.length);
|
|
17
|
+
const response = await ai.run(model, {
|
|
18
|
+
query,
|
|
19
|
+
contexts: chunks.map(({ text }) => ({ text })),
|
|
20
|
+
top_k: limit,
|
|
21
|
+
});
|
|
22
|
+
if (rerankOptions.signal?.aborted)
|
|
23
|
+
throw rerankOptions.signal.reason;
|
|
24
|
+
if (!response || typeof response !== 'object' || !('response' in response) || !Array.isArray(response.response)) {
|
|
25
|
+
throw new Error(`Workers AI returned an invalid reranking response for ${model}.`);
|
|
26
|
+
}
|
|
27
|
+
const ranked = response.response.map((item) => {
|
|
28
|
+
if (!item ||
|
|
29
|
+
typeof item !== 'object' ||
|
|
30
|
+
!('id' in item) ||
|
|
31
|
+
!Number.isInteger(item.id) ||
|
|
32
|
+
!('score' in item) ||
|
|
33
|
+
typeof item.score !== 'number' ||
|
|
34
|
+
!Number.isFinite(item.score) ||
|
|
35
|
+
item.id < 0 ||
|
|
36
|
+
item.id >= chunks.length) {
|
|
37
|
+
throw new Error(`Workers AI returned an invalid reranking result for ${model}.`);
|
|
38
|
+
}
|
|
39
|
+
return { id: item.id, score: item.score };
|
|
40
|
+
});
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
for (const result of ranked) {
|
|
43
|
+
if (seen.has(result.id))
|
|
44
|
+
throw new Error(`Workers AI returned a duplicate reranking result for ${model}.`);
|
|
45
|
+
seen.add(result.id);
|
|
46
|
+
}
|
|
47
|
+
return ranked
|
|
48
|
+
.sort((a, b) => b.score - a.score)
|
|
49
|
+
.slice(0, limit)
|
|
50
|
+
.map(({ id, score }) => ({ ...chunks[id], score }));
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=workers-ai-reranker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workers-ai-reranker.js","sourceRoot":"","sources":["../../src/retrieval/workers-ai-reranker.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export type { AppendOptions, ChatCopsStorage, ConversationStore, ConversationSummary, CounterStore, CounterValue, EventCount, EventQuery, EventSink, KeyValueStore, ListQuery, } from './types.js';
|
|
1
|
+
export type { AppendOptions, ChatCopsStorage, ConversationStore, ConversationSummary, CounterStore, CounterValue, EventCount, EventQuery, EventSink, KeyValueStore, ListQuery, KeywordQuery, MetadataFilter, MetadataValue, ScoredRecord, VectorQuery, VectorRecord, VectorSource, VectorStore, } from './types.js';
|
|
2
2
|
export { ConflictError, isConflictError, CONFLICT_ERROR_CODE } from './errors.js';
|
|
3
3
|
export { memoryStorage, type MemoryStorageOptions } from './memory.js';
|
|
4
|
+
export { memoryVectors, matchesFilter, segmentWords, type MemoryVectorsOptions } from './memory-vectors.js';
|
|
4
5
|
export { withAppend, isLegacyConversationStore, type ConversationStoreWithAppend } from './adapt.js';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,SAAS,EACT,YAAY,EACZ,cAAc,EACd,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC5G,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,KAAK,2BAA2B,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/storage/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ConflictError, isConflictError, CONFLICT_ERROR_CODE } from './errors.js';
|
|
2
2
|
export { memoryStorage } from './memory.js';
|
|
3
|
+
export { memoryVectors, matchesFilter, segmentWords } from './memory-vectors.js';
|
|
3
4
|
export { withAppend, isLegacyConversationStore } from './adapt.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,aAAa,EAA6B,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAA6B,MAAM,qBAAqB,CAAC;AAC5G,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAoC,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MetadataFilter, MetadataValue, VectorStore } from './types.js';
|
|
2
|
+
export interface MemoryVectorsOptions {
|
|
3
|
+
/** The length of every vector, set by the embedder (1024 for the default). */
|
|
4
|
+
dimensions: number;
|
|
5
|
+
/** Upserts that would go past this many records fail. Default 50,000. */
|
|
6
|
+
maxRecords?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The words in a text, lowercased. `Intl.Segmenter` finds word boundaries in
|
|
10
|
+
* languages written without spaces (Japanese, Chinese, Thai), where splitting
|
|
11
|
+
* on whitespace would make a whole sentence one word.
|
|
12
|
+
*/
|
|
13
|
+
export declare function segmentWords(text: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Vectors kept in this process, searched by comparing against every record.
|
|
16
|
+
* Fine for tests, local development and a few thousand chunks; use a store
|
|
17
|
+
* package with a vector index for more.
|
|
18
|
+
*/
|
|
19
|
+
export declare function memoryVectors(options: MemoryVectorsOptions): VectorStore;
|
|
20
|
+
/** Whether metadata passes a filter, by the rules on `MetadataFilter`. */
|
|
21
|
+
export declare function matchesFilter(metadata: Record<string, MetadataValue> | undefined, filter: MetadataFilter): boolean;
|
|
22
|
+
//# sourceMappingURL=memory-vectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-vectors.d.ts","sourceRoot":"","sources":["../../src/storage/memory-vectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,cAAc,EACd,aAAa,EAIb,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAMxE;AA+FD,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAMlH"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// BM25's usual constants.
|
|
2
|
+
const K1 = 1.2;
|
|
3
|
+
const B = 0.75;
|
|
4
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: 'word' });
|
|
5
|
+
/**
|
|
6
|
+
* The words in a text, lowercased. `Intl.Segmenter` finds word boundaries in
|
|
7
|
+
* languages written without spaces (Japanese, Chinese, Thai), where splitting
|
|
8
|
+
* on whitespace would make a whole sentence one word.
|
|
9
|
+
*/
|
|
10
|
+
export function segmentWords(text) {
|
|
11
|
+
const words = [];
|
|
12
|
+
for (const part of segmenter.segment(text.normalize('NFKC').toLowerCase())) {
|
|
13
|
+
if (part.isWordLike)
|
|
14
|
+
words.push(part.segment);
|
|
15
|
+
}
|
|
16
|
+
return words;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Vectors kept in this process, searched by comparing against every record.
|
|
20
|
+
* Fine for tests, local development and a few thousand chunks; use a store
|
|
21
|
+
* package with a vector index for more.
|
|
22
|
+
*/
|
|
23
|
+
export function memoryVectors(options) {
|
|
24
|
+
const { dimensions } = options;
|
|
25
|
+
if (!Number.isInteger(dimensions) || dimensions < 1) {
|
|
26
|
+
throw new Error(`memoryVectors needs dimensions as a positive whole number, got ${dimensions}.`);
|
|
27
|
+
}
|
|
28
|
+
return new MemoryVectorStore(dimensions, options.maxRecords ?? 50_000);
|
|
29
|
+
}
|
|
30
|
+
class MemoryVectorStore {
|
|
31
|
+
dimensions;
|
|
32
|
+
maxRecords;
|
|
33
|
+
records = new Map();
|
|
34
|
+
constructor(dimensions, maxRecords) {
|
|
35
|
+
this.dimensions = dimensions;
|
|
36
|
+
this.maxRecords = maxRecords;
|
|
37
|
+
}
|
|
38
|
+
async upsert(records) {
|
|
39
|
+
for (const record of records)
|
|
40
|
+
this.checkVector(record.vector, `record ${record.id}`);
|
|
41
|
+
const added = new Set(records.map((record) => record.id).filter((id) => !this.records.has(id))).size;
|
|
42
|
+
if (this.records.size + added > this.maxRecords) {
|
|
43
|
+
throw new Error(`memoryVectors holds at most ${this.maxRecords} records, and this upsert would make ${this.records.size + added}. Use a store package for an index this size.`);
|
|
44
|
+
}
|
|
45
|
+
for (const { vector, ...rest } of records) {
|
|
46
|
+
const copy = Float32Array.from(vector);
|
|
47
|
+
const words = segmentWords(rest.text);
|
|
48
|
+
const terms = new Map();
|
|
49
|
+
for (const word of words)
|
|
50
|
+
terms.set(word, (terms.get(word) ?? 0) + 1);
|
|
51
|
+
this.records.set(rest.id, {
|
|
52
|
+
record: structuredClone(rest),
|
|
53
|
+
vector: copy,
|
|
54
|
+
norm: length(copy),
|
|
55
|
+
terms,
|
|
56
|
+
length: words.length,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async query({ vector, topK, filter }) {
|
|
61
|
+
this.checkVector(vector, 'the query');
|
|
62
|
+
const norm = length(vector);
|
|
63
|
+
const scored = [];
|
|
64
|
+
for (const stored of this.matching(filter)) {
|
|
65
|
+
let dot = 0;
|
|
66
|
+
for (let i = 0; i < vector.length; i++)
|
|
67
|
+
dot += vector[i] * stored.vector[i];
|
|
68
|
+
scored.push([stored, norm === 0 || stored.norm === 0 ? 0 : dot / (norm * stored.norm)]);
|
|
69
|
+
}
|
|
70
|
+
return best(scored, topK);
|
|
71
|
+
}
|
|
72
|
+
async keywordQuery({ text, topK, filter }) {
|
|
73
|
+
const words = [...new Set(segmentWords(text))];
|
|
74
|
+
const candidates = [...this.matching(filter)];
|
|
75
|
+
if (words.length === 0 || candidates.length === 0)
|
|
76
|
+
return [];
|
|
77
|
+
const averageLength = candidates.reduce((sum, stored) => sum + stored.length, 0) / candidates.length || 1;
|
|
78
|
+
const scored = [];
|
|
79
|
+
const idf = new Map(words.map((word) => {
|
|
80
|
+
const withWord = candidates.filter((stored) => stored.terms.has(word)).length;
|
|
81
|
+
return [word, Math.log(1 + (candidates.length - withWord + 0.5) / (withWord + 0.5))];
|
|
82
|
+
}));
|
|
83
|
+
for (const stored of candidates) {
|
|
84
|
+
let score = 0;
|
|
85
|
+
for (const word of words) {
|
|
86
|
+
const count = stored.terms.get(word);
|
|
87
|
+
if (!count)
|
|
88
|
+
continue;
|
|
89
|
+
score += (idf.get(word) ?? 0) * ((count * (K1 + 1)) / (count + K1 * (1 - B + (B * stored.length) / averageLength)));
|
|
90
|
+
}
|
|
91
|
+
if (score > 0)
|
|
92
|
+
scored.push([stored, score]);
|
|
93
|
+
}
|
|
94
|
+
return best(scored, topK);
|
|
95
|
+
}
|
|
96
|
+
async deleteBySource(sourceId) {
|
|
97
|
+
for (const [id, stored] of this.records) {
|
|
98
|
+
if (stored.record.source.id === sourceId)
|
|
99
|
+
this.records.delete(id);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
*matching(filter) {
|
|
103
|
+
for (const stored of this.records.values()) {
|
|
104
|
+
if (!filter || matchesFilter(stored.record.metadata, filter))
|
|
105
|
+
yield stored;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
checkVector(vector, what) {
|
|
109
|
+
if (vector.length !== this.dimensions) {
|
|
110
|
+
throw new Error(`The vector for ${what} has ${vector.length} dimensions, but this store holds ${this.dimensions}.`);
|
|
111
|
+
}
|
|
112
|
+
if (!vector.every(Number.isFinite))
|
|
113
|
+
throw new Error(`The vector for ${what} has a value that isn't a finite number.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function length(vector) {
|
|
117
|
+
let sum = 0;
|
|
118
|
+
for (const value of vector)
|
|
119
|
+
sum += value * value;
|
|
120
|
+
return Math.sqrt(sum);
|
|
121
|
+
}
|
|
122
|
+
/** Whether metadata passes a filter, by the rules on `MetadataFilter`. */
|
|
123
|
+
export function matchesFilter(metadata, filter) {
|
|
124
|
+
return Object.entries(filter).every(([key, wanted]) => {
|
|
125
|
+
if (!metadata || !Object.hasOwn(metadata, key))
|
|
126
|
+
return false;
|
|
127
|
+
const value = metadata[key];
|
|
128
|
+
return Array.isArray(wanted) ? wanted.includes(value) : wanted === value;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** The `topK` highest scores, best first, ties broken by id so results are stable. */
|
|
132
|
+
function best(scored, topK) {
|
|
133
|
+
if (!(topK >= 1))
|
|
134
|
+
return [];
|
|
135
|
+
return scored
|
|
136
|
+
.sort(([a, x], [b, y]) => y - x || (a.record.id < b.record.id ? -1 : 1))
|
|
137
|
+
.slice(0, Math.floor(topK))
|
|
138
|
+
.map(([stored, score]) => ({ ...structuredClone(stored.record), score }));
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=memory-vectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-vectors.js","sourceRoot":"","sources":["../../src/storage/memory-vectors.ts"],"names":[],"mappings":"AA0BA,0BAA0B;AAC1B,MAAM,EAAE,GAAG,GAAG,CAAC;AACf,MAAM,CAAC,GAAG,IAAI,CAAC;AAEf,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC3E,IAAI,IAAI,CAAC,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAA6B;IACzD,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,kEAAkE,UAAU,GAAG,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,IAAI,iBAAiB,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,iBAAiB;IAIV;IACQ;IAJF,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAErD,YACW,UAAkB,EACV,UAAkB;QAD1B,eAAU,GAAV,UAAU,CAAQ;QACV,eAAU,GAAV,UAAU,CAAQ;IAClC,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,OAAuB;QAClC,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACrF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrG,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,+BAA+B,IAAI,CAAC,UAAU,wCAAwC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,KAAK,+CAA+C,CAC/J,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;YACxC,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;gBACxB,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC;gBAC7B,MAAM,EAAE,IAAI;gBACZ,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;gBAClB,KAAK;gBACL,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAe;QAC/C,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAgB;QACrD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC7D,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC;QAC1G,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;YAC9E,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,CACH,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;YAChC,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrC,IAAI,CAAC,KAAK;oBAAE,SAAS;gBACrB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YACtH,CAAC;YACD,IAAI,KAAK,GAAG,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAEO,CAAC,QAAQ,CAAC,MAAkC;QAClD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAAE,MAAM,MAAM,CAAC;QAC7E,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,MAAoB,EAAE,IAAY;QACpD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,QAAQ,MAAM,CAAC,MAAM,qCAAqC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACtH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,0CAA0C,CAAC,CAAC;IACxH,CAAC;CACF;AAED,SAAS,MAAM,CAAC,MAAoB;IAClC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,GAAG,IAAI,KAAK,GAAG,KAAK,CAAC;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAAC,QAAmD,EAAE,MAAsB;IACvG,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE;QACpD,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC;AAED,sFAAsF;AACtF,SAAS,IAAI,CAAC,MAA+B,EAAE,IAAY;IACzD,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,MAAM;SACV,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACvE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAC1B,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC9E,CAAC"}
|