@lssm/lib.knowledge 0.0.0-canary-20251217080011 → 1.41.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.
@@ -1,49 +1 @@
1
- //#region src/access/guard.ts
2
- const DEFAULT_DISALLOWED_WRITE = ["external", "ephemeral"];
3
- var KnowledgeAccessGuard = class {
4
- disallowedWrite;
5
- requireWorkflowBinding;
6
- requireAgentBinding;
7
- constructor(options = {}) {
8
- this.disallowedWrite = new Set(options.disallowWriteCategories ?? DEFAULT_DISALLOWED_WRITE);
9
- this.requireWorkflowBinding = options.requireWorkflowBinding ?? true;
10
- this.requireAgentBinding = options.requireAgentBinding ?? false;
11
- }
12
- checkAccess(spaceBinding, context, appConfig) {
13
- const { binding, space } = spaceBinding;
14
- if (binding.required !== false && !this.isSpaceBound(spaceBinding, appConfig)) return {
15
- allowed: false,
16
- reason: `Knowledge space "${space.meta.key}" is not bound in the resolved app config.`
17
- };
18
- if (context.operation === "write" && this.disallowedWrite.has(space.meta.category)) return {
19
- allowed: false,
20
- reason: `Knowledge space "${space.meta.key}" is category "${space.meta.category}" and is read-only.`
21
- };
22
- if (this.requireWorkflowBinding && context.workflowName) {
23
- const allowedWorkflows = binding.scope?.workflows;
24
- if (allowedWorkflows && !allowedWorkflows.includes(context.workflowName)) return {
25
- allowed: false,
26
- reason: `Workflow "${context.workflowName}" is not authorized to access knowledge space "${space.meta.key}".`
27
- };
28
- }
29
- if (this.requireAgentBinding && context.agentName) {
30
- const allowedAgents = binding.scope?.agents;
31
- if (allowedAgents && !allowedAgents.includes(context.agentName)) return {
32
- allowed: false,
33
- reason: `Agent "${context.agentName}" is not authorized to access knowledge space "${space.meta.key}".`
34
- };
35
- }
36
- if (space.meta.category === "ephemeral") return {
37
- allowed: true,
38
- severity: "warning",
39
- reason: `Knowledge space "${space.meta.key}" is ephemeral; results may be transient.`
40
- };
41
- return { allowed: true };
42
- }
43
- isSpaceBound(resolved, appConfig) {
44
- return appConfig.knowledge.some((entry) => entry.space.meta.key === resolved.space.meta.key && (resolved.space.meta.version == null || entry.space.meta.version === resolved.space.meta.version));
45
- }
46
- };
47
-
48
- //#endregion
49
- export { KnowledgeAccessGuard };
1
+ const e=[`external`,`ephemeral`];var t=class{disallowedWrite;requireWorkflowBinding;requireAgentBinding;constructor(t={}){this.disallowedWrite=new Set(t.disallowWriteCategories??e),this.requireWorkflowBinding=t.requireWorkflowBinding??!0,this.requireAgentBinding=t.requireAgentBinding??!1}checkAccess(e,t,n){let{binding:r,space:i}=e;if(r.required!==!1&&!this.isSpaceBound(e,n))return{allowed:!1,reason:`Knowledge space "${i.meta.key}" is not bound in the resolved app config.`};if(t.operation===`write`&&this.disallowedWrite.has(i.meta.category))return{allowed:!1,reason:`Knowledge space "${i.meta.key}" is category "${i.meta.category}" and is read-only.`};if(this.requireWorkflowBinding&&t.workflowName){let e=r.scope?.workflows;if(e&&!e.includes(t.workflowName))return{allowed:!1,reason:`Workflow "${t.workflowName}" is not authorized to access knowledge space "${i.meta.key}".`}}if(this.requireAgentBinding&&t.agentName){let e=r.scope?.agents;if(e&&!e.includes(t.agentName))return{allowed:!1,reason:`Agent "${t.agentName}" is not authorized to access knowledge space "${i.meta.key}".`}}return i.meta.category===`ephemeral`?{allowed:!0,severity:`warning`,reason:`Knowledge space "${i.meta.key}" is ephemeral; results may be transient.`}:{allowed:!0}}isSpaceBound(e,t){return t.knowledge.some(t=>t.space.meta.key===e.space.meta.key&&(e.space.meta.version==null||t.space.meta.version===e.space.meta.version))}};export{t as KnowledgeAccessGuard};
@@ -1,3 +1 @@
1
- import { KnowledgeAccessGuard } from "./guard.js";
2
-
3
- export { KnowledgeAccessGuard };
1
+ import{KnowledgeAccessGuard as e}from"./guard.js";export{e as KnowledgeAccessGuard};
package/dist/index.js CHANGED
@@ -1,12 +1 @@
1
- import { StaticRetriever, createStaticRetriever } from "./retriever/static-retriever.js";
2
- import { VectorRetriever, createVectorRetriever } from "./retriever/vector-retriever.js";
3
- import { KnowledgeQueryService } from "./query/service.js";
4
- import { DocumentProcessor } from "./ingestion/document-processor.js";
5
- import { EmbeddingService } from "./ingestion/embedding-service.js";
6
- import { VectorIndexer } from "./ingestion/vector-indexer.js";
7
- import { GmailIngestionAdapter } from "./ingestion/gmail-adapter.js";
8
- import { StorageIngestionAdapter } from "./ingestion/storage-adapter.js";
9
- import "./ingestion/index.js";
10
- import { KnowledgeAccessGuard } from "./access/guard.js";
11
-
12
- export { DocumentProcessor, EmbeddingService, GmailIngestionAdapter, KnowledgeAccessGuard, KnowledgeQueryService, StaticRetriever, StorageIngestionAdapter, VectorIndexer, VectorRetriever, createStaticRetriever, createVectorRetriever };
1
+ import{StaticRetriever as e,createStaticRetriever as t}from"./retriever/static-retriever.js";import{VectorRetriever as n,createVectorRetriever as r}from"./retriever/vector-retriever.js";import{KnowledgeQueryService as i}from"./query/service.js";import{DocumentProcessor as a}from"./ingestion/document-processor.js";import{EmbeddingService as o}from"./ingestion/embedding-service.js";import{VectorIndexer as s}from"./ingestion/vector-indexer.js";import{GmailIngestionAdapter as c}from"./ingestion/gmail-adapter.js";import{StorageIngestionAdapter as l}from"./ingestion/storage-adapter.js";import"./ingestion/index.js";import{KnowledgeAccessGuard as u}from"./access/guard.js";export{a as DocumentProcessor,o as EmbeddingService,c as GmailIngestionAdapter,u as KnowledgeAccessGuard,i as KnowledgeQueryService,e as StaticRetriever,l as StorageIngestionAdapter,s as VectorIndexer,n as VectorRetriever,t as createStaticRetriever,r as createVectorRetriever};
@@ -1,54 +1 @@
1
- import { Buffer } from "node:buffer";
2
-
3
- //#region src/ingestion/document-processor.ts
4
- var DocumentProcessor = class {
5
- extractors = /* @__PURE__ */ new Map();
6
- constructor() {
7
- this.registerExtractor("text/plain", this.extractText.bind(this));
8
- this.registerExtractor("application/json", this.extractJson.bind(this));
9
- }
10
- registerExtractor(mimeType, extractor) {
11
- this.extractors.set(mimeType.toLowerCase(), extractor);
12
- }
13
- async process(document) {
14
- const extractor = this.extractors.get(document.mimeType.toLowerCase()) ?? this.extractors.get("*/*");
15
- if (!extractor) throw new Error(`No extractor registered for mime type ${document.mimeType}`);
16
- const fragments = await extractor(document);
17
- if (fragments.length === 0) return [{
18
- id: `${document.id}:0`,
19
- documentId: document.id,
20
- text: "",
21
- metadata: document.metadata
22
- }];
23
- return fragments;
24
- }
25
- async extractText(document) {
26
- const text = Buffer.from(document.data).toString("utf-8");
27
- return [{
28
- id: `${document.id}:0`,
29
- documentId: document.id,
30
- text,
31
- metadata: document.metadata
32
- }];
33
- }
34
- async extractJson(document) {
35
- const text = Buffer.from(document.data).toString("utf-8");
36
- try {
37
- const json = JSON.parse(text);
38
- return [{
39
- id: `${document.id}:0`,
40
- documentId: document.id,
41
- text: JSON.stringify(json, null, 2),
42
- metadata: {
43
- ...document.metadata,
44
- contentType: "application/json"
45
- }
46
- }];
47
- } catch {
48
- return this.extractText(document);
49
- }
50
- }
51
- };
52
-
53
- //#endregion
54
- export { DocumentProcessor };
1
+ import{Buffer as e}from"node:buffer";var t=class{extractors=new Map;constructor(){this.registerExtractor(`text/plain`,this.extractText.bind(this)),this.registerExtractor(`application/json`,this.extractJson.bind(this))}registerExtractor(e,t){this.extractors.set(e.toLowerCase(),t)}async process(e){let t=this.extractors.get(e.mimeType.toLowerCase())??this.extractors.get(`*/*`);if(!t)throw Error(`No extractor registered for mime type ${e.mimeType}`);let n=await t(e);return n.length===0?[{id:`${e.id}:0`,documentId:e.id,text:``,metadata:e.metadata}]:n}async extractText(t){let n=e.from(t.data).toString(`utf-8`);return[{id:`${t.id}:0`,documentId:t.id,text:n,metadata:t.metadata}]}async extractJson(t){let n=e.from(t.data).toString(`utf-8`);try{let e=JSON.parse(n);return[{id:`${t.id}:0`,documentId:t.id,text:JSON.stringify(e,null,2),metadata:{...t.metadata,contentType:`application/json`}}]}catch{return this.extractText(t)}}};export{t as DocumentProcessor};
@@ -1,25 +1 @@
1
- //#region src/ingestion/embedding-service.ts
2
- var EmbeddingService = class {
3
- provider;
4
- batchSize;
5
- constructor(provider, batchSize = 16) {
6
- this.provider = provider;
7
- this.batchSize = batchSize;
8
- }
9
- async embedFragments(fragments) {
10
- const results = [];
11
- for (let i = 0; i < fragments.length; i += this.batchSize) {
12
- const documents = fragments.slice(i, i + this.batchSize).map((fragment) => ({
13
- id: fragment.id,
14
- text: fragment.text,
15
- metadata: fragment.metadata
16
- }));
17
- const embeddings = await this.provider.embedDocuments(documents);
18
- results.push(...embeddings);
19
- }
20
- return results;
21
- }
22
- };
23
-
24
- //#endregion
25
- export { EmbeddingService };
1
+ var e=class{provider;batchSize;constructor(e,t=16){this.provider=e,this.batchSize=t}async embedFragments(e){let t=[];for(let n=0;n<e.length;n+=this.batchSize){let r=e.slice(n,n+this.batchSize).map(e=>({id:e.id,text:e.text,metadata:e.metadata})),i=await this.provider.embedDocuments(r);t.push(...i)}return t}};export{e as EmbeddingService};
@@ -1,51 +1,6 @@
1
- //#region src/ingestion/gmail-adapter.ts
2
- var GmailIngestionAdapter = class {
3
- constructor(gmail, processor, embeddings, indexer) {
4
- this.gmail = gmail;
5
- this.processor = processor;
6
- this.embeddings = embeddings;
7
- this.indexer = indexer;
8
- }
9
- async syncThreads(query) {
10
- const threads = await this.gmail.listThreads(query);
11
- for (const thread of threads) await this.ingestThread(thread);
12
- }
13
- async ingestThread(thread) {
14
- const document = this.toRawDocument(thread);
15
- const fragments = await this.processor.process(document);
16
- const embeddings = await this.embeddings.embedFragments(fragments);
17
- await this.indexer.upsert(fragments, embeddings);
18
- }
19
- toRawDocument(thread) {
20
- const content = composeThreadText(thread);
21
- return {
22
- id: thread.id,
23
- mimeType: "text/plain",
24
- data: Buffer.from(content, "utf-8"),
25
- metadata: {
26
- subject: thread.subject ?? "",
27
- participants: thread.participants.map((p) => p.email).join(", "),
28
- updatedAt: thread.updatedAt.toISOString()
29
- }
30
- };
31
- }
32
- };
33
- function composeThreadText(thread) {
34
- const header = [`Subject: ${thread.subject ?? ""}`, `Snippet: ${thread.snippet ?? ""}`];
35
- const messageTexts = thread.messages.map((message) => {
36
- const parts = [`From: ${formatAddress(message.from)}`, `To: ${message.to.map(formatAddress).join(", ")}`];
37
- if (message.sentAt) parts.push(`Date: ${message.sentAt.toISOString()}`);
38
- const body = message.textBody ?? stripHtml(message.htmlBody ?? "");
39
- return `${parts.join("\n")}\n\n${body ?? ""}`;
40
- });
41
- return [...header, ...messageTexts].join("\n\n---\n\n");
42
- }
43
- function formatAddress(address) {
44
- return address.name ? `${address.name} <${address.email}>` : address.email;
45
- }
46
- function stripHtml(html) {
47
- return html.replace(/<[^>]+>/g, " ");
48
- }
1
+ var e=class{constructor(e,t,n,r){this.gmail=e,this.processor=t,this.embeddings=n,this.indexer=r}async syncThreads(e){let t=await this.gmail.listThreads(e);for(let e of t)await this.ingestThread(e)}async ingestThread(e){let t=this.toRawDocument(e),n=await this.processor.process(t),r=await this.embeddings.embedFragments(n);await this.indexer.upsert(n,r)}toRawDocument(e){let n=t(e);return{id:e.id,mimeType:`text/plain`,data:Buffer.from(n,`utf-8`),metadata:{subject:e.subject??``,participants:e.participants.map(e=>e.email).join(`, `),updatedAt:e.updatedAt.toISOString()}}}};function t(e){let t=[`Subject: ${e.subject??``}`,`Snippet: ${e.snippet??``}`],i=e.messages.map(e=>{let t=[`From: ${n(e.from)}`,`To: ${e.to.map(n).join(`, `)}`];e.sentAt&&t.push(`Date: ${e.sentAt.toISOString()}`);let i=e.textBody??r(e.htmlBody??``);return`${t.join(`
2
+ `)}\n\n${i??``}`});return[...t,...i].join(`
49
3
 
50
- //#endregion
51
- export { GmailIngestionAdapter };
4
+ ---
5
+
6
+ `)}function n(e){return e.name?`${e.name} <${e.email}>`:e.email}function r(e){return e.replace(/<[^>]+>/g,` `)}export{e as GmailIngestionAdapter};
@@ -1,7 +1 @@
1
- import { DocumentProcessor } from "./document-processor.js";
2
- import { EmbeddingService } from "./embedding-service.js";
3
- import { VectorIndexer } from "./vector-indexer.js";
4
- import { GmailIngestionAdapter } from "./gmail-adapter.js";
5
- import { StorageIngestionAdapter } from "./storage-adapter.js";
6
-
7
- export { DocumentProcessor, EmbeddingService, GmailIngestionAdapter, StorageIngestionAdapter, VectorIndexer };
1
+ import{DocumentProcessor as e}from"./document-processor.js";import{EmbeddingService as t}from"./embedding-service.js";import{VectorIndexer as n}from"./vector-indexer.js";import{GmailIngestionAdapter as r}from"./gmail-adapter.js";import{StorageIngestionAdapter as i}from"./storage-adapter.js";export{e as DocumentProcessor,t as EmbeddingService,r as GmailIngestionAdapter,i as StorageIngestionAdapter,n as VectorIndexer};
@@ -1,26 +1 @@
1
- //#region src/ingestion/storage-adapter.ts
2
- var StorageIngestionAdapter = class {
3
- constructor(processor, embeddings, indexer) {
4
- this.processor = processor;
5
- this.embeddings = embeddings;
6
- this.indexer = indexer;
7
- }
8
- async ingestObject(object) {
9
- if (!("data" in object) || !object.data) throw new Error("Storage ingestion requires object data");
10
- const raw = {
11
- id: object.key,
12
- mimeType: object.contentType ?? "application/octet-stream",
13
- data: object.data,
14
- metadata: {
15
- bucket: object.bucket,
16
- checksum: object.checksum ?? ""
17
- }
18
- };
19
- const fragments = await this.processor.process(raw);
20
- const embeddings = await this.embeddings.embedFragments(fragments);
21
- await this.indexer.upsert(fragments, embeddings);
22
- }
23
- };
24
-
25
- //#endregion
26
- export { StorageIngestionAdapter };
1
+ var e=class{constructor(e,t,n){this.processor=e,this.embeddings=t,this.indexer=n}async ingestObject(e){if(!(`data`in e)||!e.data)throw Error(`Storage ingestion requires object data`);let t={id:e.key,mimeType:e.contentType??`application/octet-stream`,data:e.data,metadata:{bucket:e.bucket,checksum:e.checksum??``}},n=await this.processor.process(t),r=await this.embeddings.embedFragments(n);await this.indexer.upsert(n,r)}};export{e as StorageIngestionAdapter};
@@ -1,32 +1 @@
1
- //#region src/ingestion/vector-indexer.ts
2
- var VectorIndexer = class {
3
- provider;
4
- config;
5
- constructor(provider, config) {
6
- this.provider = provider;
7
- this.config = config;
8
- }
9
- async upsert(fragments, embeddings) {
10
- const documents = embeddings.map((embedding) => {
11
- const fragment = fragments.find((f) => f.id === embedding.id);
12
- return {
13
- id: embedding.id,
14
- vector: embedding.vector,
15
- payload: {
16
- ...this.config.metadata,
17
- ...fragment?.metadata ?? {},
18
- documentId: fragment?.documentId
19
- },
20
- namespace: this.config.namespace
21
- };
22
- });
23
- const request = {
24
- collection: this.config.collection,
25
- documents
26
- };
27
- await this.provider.upsert(request);
28
- }
29
- };
30
-
31
- //#endregion
32
- export { VectorIndexer };
1
+ var e=class{provider;config;constructor(e,t){this.provider=e,this.config=t}async upsert(e,t){let n=t.map(t=>{let n=e.find(e=>e.id===t.id);return{id:t.id,vector:t.vector,payload:{...this.config.metadata,...n?.metadata??{},documentId:n?.documentId},namespace:this.config.namespace}}),r={collection:this.config.collection,documents:n};await this.provider.upsert(r)}};export{e as VectorIndexer};
@@ -1,3 +1 @@
1
- import { KnowledgeQueryService } from "./service.js";
2
-
3
- export { KnowledgeQueryService };
1
+ import{KnowledgeQueryService as e}from"./service.js";export{e as KnowledgeQueryService};
@@ -1,65 +1,3 @@
1
- //#region src/query/service.ts
2
- var KnowledgeQueryService = class {
3
- embeddings;
4
- vectorStore;
5
- llm;
6
- config;
7
- constructor(embeddings, vectorStore, llm, config) {
8
- this.embeddings = embeddings;
9
- this.vectorStore = vectorStore;
10
- this.llm = llm;
11
- this.config = config;
12
- }
13
- async query(question) {
14
- const embedding = await this.embeddings.embedQuery(question);
15
- const results = await this.vectorStore.search({
16
- collection: this.config.collection,
17
- vector: embedding.vector,
18
- topK: this.config.topK ?? 5,
19
- namespace: this.config.namespace,
20
- filter: void 0
21
- });
22
- const context = buildContext(results);
23
- const messages = this.buildMessages(question, context);
24
- const response = await this.llm.chat(messages);
25
- return {
26
- answer: response.message.content.map((part) => "text" in part ? part.text : "").join(""),
27
- references: results.map((result) => ({
28
- ...result,
29
- text: extractText(result)
30
- })),
31
- usage: response.usage
32
- };
33
- }
34
- buildMessages(question, context) {
35
- return [{
36
- role: "system",
37
- content: [{
38
- type: "text",
39
- text: this.config.systemPrompt ?? "You are a knowledge assistant that answers questions using the provided context. Cite relevant sources if possible."
40
- }]
41
- }, {
42
- role: "user",
43
- content: [{
44
- type: "text",
45
- text: `Question:\n${question}\n\nContext:\n${context}`
46
- }]
47
- }];
48
- }
49
- };
50
- function buildContext(results) {
51
- if (results.length === 0) return "No relevant documents found.";
52
- return results.map((result, index) => {
53
- const text = extractText(result);
54
- return `Source ${index + 1} (score: ${result.score.toFixed(3)}):\n${text}`;
55
- }).join("\n\n");
56
- }
57
- function extractText(result) {
58
- const payload = result.payload ?? {};
59
- if (typeof payload.text === "string") return payload.text;
60
- if (typeof payload.content === "string") return payload.content;
61
- return JSON.stringify(payload);
62
- }
1
+ var e=class{embeddings;vectorStore;llm;config;constructor(e,t,n,r){this.embeddings=e,this.vectorStore=t,this.llm=n,this.config=r}async query(e){let r=await this.embeddings.embedQuery(e),i=await this.vectorStore.search({collection:this.config.collection,vector:r.vector,topK:this.config.topK??5,namespace:this.config.namespace,filter:void 0}),a=t(i),o=this.buildMessages(e,a),s=await this.llm.chat(o);return{answer:s.message.content.map(e=>`text`in e?e.text:``).join(``),references:i.map(e=>({...e,text:n(e)})),usage:s.usage}}buildMessages(e,t){return[{role:`system`,content:[{type:`text`,text:this.config.systemPrompt??`You are a knowledge assistant that answers questions using the provided context. Cite relevant sources if possible.`}]},{role:`user`,content:[{type:`text`,text:`Question:\n${e}\n\nContext:\n${t}`}]}]}};function t(e){return e.length===0?`No relevant documents found.`:e.map((e,t)=>{let r=n(e);return`Source ${t+1} (score: ${e.score.toFixed(3)}):\n${r}`}).join(`
63
2
 
64
- //#endregion
65
- export { KnowledgeQueryService };
3
+ `)}function n(e){let t=e.payload??{};return typeof t.text==`string`?t.text:typeof t.content==`string`?t.content:JSON.stringify(t)}export{e as KnowledgeQueryService};
@@ -1,4 +1 @@
1
- import { StaticRetriever, createStaticRetriever } from "./static-retriever.js";
2
- import { VectorRetriever, createVectorRetriever } from "./vector-retriever.js";
3
-
4
- export { StaticRetriever, VectorRetriever, createStaticRetriever, createVectorRetriever };
1
+ import{StaticRetriever as e,createStaticRetriever as t}from"./static-retriever.js";import{VectorRetriever as n,createVectorRetriever as r}from"./vector-retriever.js";export{e as StaticRetriever,n as VectorRetriever,t as createStaticRetriever,r as createVectorRetriever};
@@ -1,47 +1,2 @@
1
- //#region src/retriever/static-retriever.ts
2
- /**
3
- * A simple in-memory retriever for static knowledge content.
4
- *
5
- * Useful for:
6
- * - Required knowledge that doesn't need semantic search
7
- * - Testing and development
8
- * - Small knowledge bases that fit in memory
9
- */
10
- var StaticRetriever = class {
11
- content;
12
- constructor(config) {
13
- this.content = config.content instanceof Map ? config.content : new Map(Object.entries(config.content));
14
- }
15
- async retrieve(query, options) {
16
- const content = this.content.get(options.spaceKey);
17
- if (!content) return [];
18
- const queryLower = query.toLowerCase();
19
- const lines = content.split("\n").filter((line) => line.trim());
20
- const results = [];
21
- for (const line of lines) if (line.toLowerCase().includes(queryLower)) results.push({
22
- content: line,
23
- source: options.spaceKey,
24
- score: 1,
25
- metadata: { type: "static" }
26
- });
27
- return results.slice(0, options.topK ?? 5);
28
- }
29
- async getStatic(spaceKey) {
30
- return this.content.get(spaceKey) ?? null;
31
- }
32
- supportsSpace(spaceKey) {
33
- return this.content.has(spaceKey);
34
- }
35
- listSpaces() {
36
- return [...this.content.keys()];
37
- }
38
- };
39
- /**
40
- * Create a static retriever from a content map.
41
- */
42
- function createStaticRetriever(content) {
43
- return new StaticRetriever({ content });
44
- }
45
-
46
- //#endregion
47
- export { StaticRetriever, createStaticRetriever };
1
+ var e=class{content;constructor(e){this.content=e.content instanceof Map?e.content:new Map(Object.entries(e.content))}async retrieve(e,t){let n=this.content.get(t.spaceKey);if(!n)return[];let r=e.toLowerCase(),i=n.split(`
2
+ `).filter(e=>e.trim()),a=[];for(let e of i)e.toLowerCase().includes(r)&&a.push({content:e,source:t.spaceKey,score:1,metadata:{type:`static`}});return a.slice(0,t.topK??5)}async getStatic(e){return this.content.get(e)??null}supportsSpace(e){return this.content.has(e)}listSpaces(){return[...this.content.keys()]}};function t(t){return new e({content:t})}export{e as StaticRetriever,t as createStaticRetriever};
@@ -1,60 +1 @@
1
- //#region src/retriever/vector-retriever.ts
2
- /**
3
- * A retriever that uses vector similarity search.
4
- *
5
- * Uses embedding provider to vectorize queries and vector store
6
- * provider to perform similarity search.
7
- */
8
- var VectorRetriever = class {
9
- config;
10
- spaceCollections;
11
- staticContent;
12
- constructor(config) {
13
- this.config = config;
14
- this.spaceCollections = config.spaceCollections instanceof Map ? config.spaceCollections : new Map(Object.entries(config.spaceCollections));
15
- this.staticContent = config.staticContent ? config.staticContent instanceof Map ? config.staticContent : new Map(Object.entries(config.staticContent)) : /* @__PURE__ */ new Map();
16
- }
17
- async retrieve(query, options) {
18
- const collection = this.spaceCollections.get(options.spaceKey);
19
- if (!collection) return [];
20
- const embedding = await this.config.embeddings.embedQuery(query);
21
- const results = await this.config.vectorStore.search({
22
- collection,
23
- vector: embedding.vector,
24
- topK: options.topK ?? this.config.defaultTopK ?? 5,
25
- namespace: options.tenantId,
26
- filter: options.filter
27
- });
28
- const minScore = options.minScore ?? this.config.defaultMinScore ?? 0;
29
- return results.filter((r) => r.score >= minScore).map((result) => ({
30
- content: this.extractContent(result.payload),
31
- source: result.id,
32
- score: result.score,
33
- metadata: result.payload
34
- }));
35
- }
36
- async getStatic(spaceKey) {
37
- return this.staticContent.get(spaceKey) ?? null;
38
- }
39
- supportsSpace(spaceKey) {
40
- return this.spaceCollections.has(spaceKey);
41
- }
42
- listSpaces() {
43
- return [...this.spaceCollections.keys()];
44
- }
45
- extractContent(payload) {
46
- if (!payload) return "";
47
- if (typeof payload.text === "string") return payload.text;
48
- if (typeof payload.content === "string") return payload.content;
49
- return JSON.stringify(payload);
50
- }
51
- };
52
- /**
53
- * Create a vector retriever from configuration.
54
- */
55
- function createVectorRetriever(config) {
56
- return new VectorRetriever(config);
57
- }
58
-
59
- //#endregion
60
- export { VectorRetriever, createVectorRetriever };
1
+ var e=class{config;spaceCollections;staticContent;constructor(e){this.config=e,this.spaceCollections=e.spaceCollections instanceof Map?e.spaceCollections:new Map(Object.entries(e.spaceCollections)),this.staticContent=e.staticContent?e.staticContent instanceof Map?e.staticContent:new Map(Object.entries(e.staticContent)):new Map}async retrieve(e,t){let n=this.spaceCollections.get(t.spaceKey);if(!n)return[];let r=await this.config.embeddings.embedQuery(e),i=await this.config.vectorStore.search({collection:n,vector:r.vector,topK:t.topK??this.config.defaultTopK??5,namespace:t.tenantId,filter:t.filter}),a=t.minScore??this.config.defaultMinScore??0;return i.filter(e=>e.score>=a).map(e=>({content:this.extractContent(e.payload),source:e.id,score:e.score,metadata:e.payload}))}async getStatic(e){return this.staticContent.get(e)??null}supportsSpace(e){return this.spaceCollections.has(e)}listSpaces(){return[...this.spaceCollections.keys()]}extractContent(e){return e?typeof e.text==`string`?e.text:typeof e.content==`string`?e.content:JSON.stringify(e):``}};function t(t){return new e(t)}export{e as VectorRetriever,t as createVectorRetriever};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/lib.knowledge",
3
- "version": "0.0.0-canary-20251217080011",
3
+ "version": "1.41.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -11,7 +11,6 @@
11
11
  ],
12
12
  "scripts": {
13
13
  "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
14
- "publish:pkg:canary": "bun publish:pkg --tag canary",
15
14
  "build": "bun build:bundle && bun build:types",
16
15
  "build:bundle": "tsdown",
17
16
  "build:types": "tsc --noEmit",
@@ -23,31 +22,31 @@
23
22
  "test": "bun test"
24
23
  },
25
24
  "dependencies": {
26
- "@lssm/lib.contracts": "0.0.0-canary-20251217080011"
25
+ "@lssm/lib.contracts": "workspace:*"
27
26
  },
28
27
  "devDependencies": {
29
- "@lssm/tool.tsdown": "0.0.0-canary-20251217080011",
30
- "@lssm/tool.typescript": "0.0.0-canary-20251217080011",
28
+ "@lssm/tool.tsdown": "workspace:*",
29
+ "@lssm/tool.typescript": "workspace:*",
31
30
  "tsdown": "^0.17.4",
32
31
  "typescript": "^5.9.3"
33
32
  },
34
33
  "exports": {
35
- ".": "./dist/index.js",
36
- "./access": "./dist/access/index.js",
37
- "./access/guard": "./dist/access/guard.js",
38
- "./ingestion": "./dist/ingestion/index.js",
39
- "./ingestion/document-processor": "./dist/ingestion/document-processor.js",
40
- "./ingestion/embedding-service": "./dist/ingestion/embedding-service.js",
41
- "./ingestion/gmail-adapter": "./dist/ingestion/gmail-adapter.js",
42
- "./ingestion/storage-adapter": "./dist/ingestion/storage-adapter.js",
43
- "./ingestion/vector-indexer": "./dist/ingestion/vector-indexer.js",
44
- "./query": "./dist/query/index.js",
45
- "./query/service": "./dist/query/service.js",
46
- "./retriever": "./dist/retriever/index.js",
47
- "./retriever/interface": "./dist/retriever/interface.js",
48
- "./retriever/static-retriever": "./dist/retriever/static-retriever.js",
49
- "./retriever/vector-retriever": "./dist/retriever/vector-retriever.js",
50
- "./types": "./dist/types.js",
34
+ ".": "./src/index.ts",
35
+ "./access": "./src/access/index.ts",
36
+ "./access/guard": "./src/access/guard.ts",
37
+ "./ingestion": "./src/ingestion/index.ts",
38
+ "./ingestion/document-processor": "./src/ingestion/document-processor.ts",
39
+ "./ingestion/embedding-service": "./src/ingestion/embedding-service.ts",
40
+ "./ingestion/gmail-adapter": "./src/ingestion/gmail-adapter.ts",
41
+ "./ingestion/storage-adapter": "./src/ingestion/storage-adapter.ts",
42
+ "./ingestion/vector-indexer": "./src/ingestion/vector-indexer.ts",
43
+ "./query": "./src/query/index.ts",
44
+ "./query/service": "./src/query/service.ts",
45
+ "./retriever": "./src/retriever/index.ts",
46
+ "./retriever/interface": "./src/retriever/interface.ts",
47
+ "./retriever/static-retriever": "./src/retriever/static-retriever.ts",
48
+ "./retriever/vector-retriever": "./src/retriever/vector-retriever.ts",
49
+ "./types": "./src/types.ts",
51
50
  "./*": "./*"
52
51
  },
53
52
  "publishConfig": {
@@ -1,20 +0,0 @@
1
- import { KnowledgeAccessContext, KnowledgeAccessResult } from "../types.js";
2
- import { ResolvedAppConfig, ResolvedKnowledge } from "@lssm/lib.contracts/app-config";
3
- import { KnowledgeCategory } from "@lssm/lib.contracts/knowledge";
4
-
5
- //#region src/access/guard.d.ts
6
- interface KnowledgeAccessGuardOptions {
7
- disallowWriteCategories?: KnowledgeCategory[];
8
- requireWorkflowBinding?: boolean;
9
- requireAgentBinding?: boolean;
10
- }
11
- declare class KnowledgeAccessGuard {
12
- private readonly disallowedWrite;
13
- private readonly requireWorkflowBinding;
14
- private readonly requireAgentBinding;
15
- constructor(options?: KnowledgeAccessGuardOptions);
16
- checkAccess(spaceBinding: ResolvedKnowledge, context: KnowledgeAccessContext, appConfig: ResolvedAppConfig): KnowledgeAccessResult;
17
- private isSpaceBound;
18
- }
19
- //#endregion
20
- export { KnowledgeAccessGuard, KnowledgeAccessGuardOptions };
@@ -1,2 +0,0 @@
1
- import { KnowledgeAccessGuard, KnowledgeAccessGuardOptions } from "./guard.js";
2
- export { KnowledgeAccessGuard, KnowledgeAccessGuardOptions };
package/dist/index.d.ts DELETED
@@ -1,12 +0,0 @@
1
- import { KnowledgeAccessContext, KnowledgeAccessResult, RetrievalOptions, RetrievalResult } from "./types.js";
2
- import { KnowledgeAccessGuard, KnowledgeAccessGuardOptions } from "./access/guard.js";
3
- import { KnowledgeRetriever, RetrieverConfig } from "./retriever/interface.js";
4
- import { StaticRetriever, StaticRetrieverConfig, createStaticRetriever } from "./retriever/static-retriever.js";
5
- import { VectorRetriever, VectorRetrieverConfig, createVectorRetriever } from "./retriever/vector-retriever.js";
6
- import { KnowledgeAnswer, KnowledgeQueryConfig, KnowledgeQueryService } from "./query/service.js";
7
- import { DocumentFragment, DocumentProcessor, RawDocument } from "./ingestion/document-processor.js";
8
- import { EmbeddingService } from "./ingestion/embedding-service.js";
9
- import { VectorIndexConfig, VectorIndexer } from "./ingestion/vector-indexer.js";
10
- import { GmailIngestionAdapter } from "./ingestion/gmail-adapter.js";
11
- import { StorageIngestionAdapter } from "./ingestion/storage-adapter.js";
12
- export { DocumentFragment, DocumentProcessor, EmbeddingService, GmailIngestionAdapter, KnowledgeAccessContext, KnowledgeAccessGuard, KnowledgeAccessGuardOptions, KnowledgeAccessResult, KnowledgeAnswer, KnowledgeQueryConfig, KnowledgeQueryService, KnowledgeRetriever, RawDocument, RetrievalOptions, RetrievalResult, RetrieverConfig, StaticRetriever, StaticRetrieverConfig, StorageIngestionAdapter, VectorIndexConfig, VectorIndexer, VectorRetriever, VectorRetrieverConfig, createStaticRetriever, createVectorRetriever };
@@ -1,24 +0,0 @@
1
- //#region src/ingestion/document-processor.d.ts
2
- interface RawDocument {
3
- id: string;
4
- mimeType: string;
5
- data: Uint8Array;
6
- metadata?: Record<string, string>;
7
- }
8
- interface DocumentFragment {
9
- id: string;
10
- documentId: string;
11
- text: string;
12
- metadata?: Record<string, string>;
13
- }
14
- type Extractor = (input: RawDocument) => Promise<DocumentFragment[]>;
15
- declare class DocumentProcessor {
16
- private readonly extractors;
17
- constructor();
18
- registerExtractor(mimeType: string, extractor: Extractor): void;
19
- process(document: RawDocument): Promise<DocumentFragment[]>;
20
- private extractText;
21
- private extractJson;
22
- }
23
- //#endregion
24
- export { DocumentFragment, DocumentProcessor, RawDocument };
@@ -1,12 +0,0 @@
1
- import { DocumentFragment } from "./document-processor.js";
2
- import { EmbeddingProvider, EmbeddingResult } from "@lssm/lib.contracts/integrations/providers";
3
-
4
- //#region src/ingestion/embedding-service.d.ts
5
- declare class EmbeddingService {
6
- private readonly provider;
7
- private readonly batchSize;
8
- constructor(provider: EmbeddingProvider, batchSize?: number);
9
- embedFragments(fragments: DocumentFragment[]): Promise<EmbeddingResult[]>;
10
- }
11
- //#endregion
12
- export { EmbeddingService };
@@ -1,18 +0,0 @@
1
- import { DocumentProcessor } from "./document-processor.js";
2
- import { EmbeddingService } from "./embedding-service.js";
3
- import { VectorIndexer } from "./vector-indexer.js";
4
- import { EmailInboundProvider, EmailThread } from "@lssm/lib.contracts/integrations/providers";
5
-
6
- //#region src/ingestion/gmail-adapter.d.ts
7
- declare class GmailIngestionAdapter {
8
- private readonly gmail;
9
- private readonly processor;
10
- private readonly embeddings;
11
- private readonly indexer;
12
- constructor(gmail: EmailInboundProvider, processor: DocumentProcessor, embeddings: EmbeddingService, indexer: VectorIndexer);
13
- syncThreads(query?: Parameters<EmailInboundProvider['listThreads']>[0]): Promise<void>;
14
- ingestThread(thread: EmailThread): Promise<void>;
15
- private toRawDocument;
16
- }
17
- //#endregion
18
- export { GmailIngestionAdapter };
@@ -1,6 +0,0 @@
1
- import { DocumentFragment, DocumentProcessor, RawDocument } from "./document-processor.js";
2
- import { EmbeddingService } from "./embedding-service.js";
3
- import { VectorIndexConfig, VectorIndexer } from "./vector-indexer.js";
4
- import { GmailIngestionAdapter } from "./gmail-adapter.js";
5
- import { StorageIngestionAdapter } from "./storage-adapter.js";
6
- export { DocumentFragment, DocumentProcessor, EmbeddingService, GmailIngestionAdapter, RawDocument, StorageIngestionAdapter, VectorIndexConfig, VectorIndexer };
@@ -1,15 +0,0 @@
1
- import { DocumentProcessor } from "./document-processor.js";
2
- import { EmbeddingService } from "./embedding-service.js";
3
- import { VectorIndexer } from "./vector-indexer.js";
4
- import { GetObjectResult } from "@lssm/lib.contracts/integrations/providers";
5
-
6
- //#region src/ingestion/storage-adapter.d.ts
7
- declare class StorageIngestionAdapter {
8
- private readonly processor;
9
- private readonly embeddings;
10
- private readonly indexer;
11
- constructor(processor: DocumentProcessor, embeddings: EmbeddingService, indexer: VectorIndexer);
12
- ingestObject(object: GetObjectResult): Promise<void>;
13
- }
14
- //#endregion
15
- export { StorageIngestionAdapter };
@@ -1,17 +0,0 @@
1
- import { DocumentFragment } from "./document-processor.js";
2
- import { EmbeddingResult, VectorStoreProvider } from "@lssm/lib.contracts/integrations/providers";
3
-
4
- //#region src/ingestion/vector-indexer.d.ts
5
- interface VectorIndexConfig {
6
- collection: string;
7
- namespace?: string;
8
- metadata?: Record<string, string>;
9
- }
10
- declare class VectorIndexer {
11
- private readonly provider;
12
- private readonly config;
13
- constructor(provider: VectorStoreProvider, config: VectorIndexConfig);
14
- upsert(fragments: DocumentFragment[], embeddings: EmbeddingResult[]): Promise<void>;
15
- }
16
- //#endregion
17
- export { VectorIndexConfig, VectorIndexer };
@@ -1,2 +0,0 @@
1
- import { KnowledgeAnswer, KnowledgeQueryConfig, KnowledgeQueryService } from "./service.js";
2
- export { KnowledgeAnswer, KnowledgeQueryConfig, KnowledgeQueryService };
@@ -1,27 +0,0 @@
1
- import { EmbeddingProvider, LLMProvider, LLMResponse, VectorSearchResult, VectorStoreProvider } from "@lssm/lib.contracts/integrations/providers";
2
-
3
- //#region src/query/service.d.ts
4
- interface KnowledgeQueryConfig {
5
- collection: string;
6
- namespace?: string;
7
- topK?: number;
8
- systemPrompt?: string;
9
- }
10
- interface KnowledgeAnswer {
11
- answer: string;
12
- references: (VectorSearchResult & {
13
- text?: string;
14
- })[];
15
- usage?: LLMResponse['usage'];
16
- }
17
- declare class KnowledgeQueryService {
18
- private readonly embeddings;
19
- private readonly vectorStore;
20
- private readonly llm;
21
- private readonly config;
22
- constructor(embeddings: EmbeddingProvider, vectorStore: VectorStoreProvider, llm: LLMProvider, config: KnowledgeQueryConfig);
23
- query(question: string): Promise<KnowledgeAnswer>;
24
- private buildMessages;
25
- }
26
- //#endregion
27
- export { KnowledgeAnswer, KnowledgeQueryConfig, KnowledgeQueryService };
@@ -1,4 +0,0 @@
1
- import { KnowledgeRetriever, RetrieverConfig } from "./interface.js";
2
- import { StaticRetriever, StaticRetrieverConfig, createStaticRetriever } from "./static-retriever.js";
3
- import { VectorRetriever, VectorRetrieverConfig, createVectorRetriever } from "./vector-retriever.js";
4
- export { KnowledgeRetriever, RetrieverConfig, StaticRetriever, StaticRetrieverConfig, VectorRetriever, VectorRetrieverConfig, createStaticRetriever, createVectorRetriever };
@@ -1,55 +0,0 @@
1
- import { RetrievalOptions, RetrievalResult } from "../types.js";
2
-
3
- //#region src/retriever/interface.d.ts
4
-
5
- /**
6
- * Unified interface for knowledge retrieval.
7
- *
8
- * Implementations can use vector stores, static content, or hybrid approaches.
9
- * This interface is consumed by @lssm/lib.ai-agent for both static injection
10
- * and dynamic RAG tool queries.
11
- */
12
- interface KnowledgeRetriever {
13
- /**
14
- * Retrieve relevant content for a query using semantic search.
15
- *
16
- * @param query - The search query or question
17
- * @param options - Retrieval options including space key and filters
18
- * @returns Array of retrieval results sorted by relevance
19
- */
20
- retrieve(query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
21
- /**
22
- * Get static content by space key (for required knowledge injection).
23
- *
24
- * Used for injecting required knowledge into agent system prompts
25
- * without performing semantic search.
26
- *
27
- * @param spaceKey - The knowledge space key
28
- * @returns The static content or null if not available
29
- */
30
- getStatic(spaceKey: string): Promise<string | null>;
31
- /**
32
- * Check if this retriever supports a given knowledge space.
33
- *
34
- * @param spaceKey - The knowledge space key to check
35
- * @returns True if the space is supported
36
- */
37
- supportsSpace(spaceKey: string): boolean;
38
- /**
39
- * List all supported knowledge space keys.
40
- *
41
- * @returns Array of supported space keys
42
- */
43
- listSpaces(): string[];
44
- }
45
- /**
46
- * Configuration for creating a retriever.
47
- */
48
- interface RetrieverConfig {
49
- /** Default number of results to return */
50
- defaultTopK?: number;
51
- /** Default minimum score threshold */
52
- defaultMinScore?: number;
53
- }
54
- //#endregion
55
- export { KnowledgeRetriever, RetrieverConfig };
@@ -1,34 +0,0 @@
1
- import { RetrievalOptions, RetrievalResult } from "../types.js";
2
- import { KnowledgeRetriever, RetrieverConfig } from "./interface.js";
3
-
4
- //#region src/retriever/static-retriever.d.ts
5
-
6
- /**
7
- * Configuration for the static retriever.
8
- */
9
- interface StaticRetrieverConfig extends RetrieverConfig {
10
- /** Map of space key to static content */
11
- content: Map<string, string> | Record<string, string>;
12
- }
13
- /**
14
- * A simple in-memory retriever for static knowledge content.
15
- *
16
- * Useful for:
17
- * - Required knowledge that doesn't need semantic search
18
- * - Testing and development
19
- * - Small knowledge bases that fit in memory
20
- */
21
- declare class StaticRetriever implements KnowledgeRetriever {
22
- private readonly content;
23
- constructor(config: StaticRetrieverConfig);
24
- retrieve(query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
25
- getStatic(spaceKey: string): Promise<string | null>;
26
- supportsSpace(spaceKey: string): boolean;
27
- listSpaces(): string[];
28
- }
29
- /**
30
- * Create a static retriever from a content map.
31
- */
32
- declare function createStaticRetriever(content: Record<string, string> | Map<string, string>): StaticRetriever;
33
- //#endregion
34
- export { StaticRetriever, StaticRetrieverConfig, createStaticRetriever };
@@ -1,42 +0,0 @@
1
- import { RetrievalOptions, RetrievalResult } from "../types.js";
2
- import { KnowledgeRetriever, RetrieverConfig } from "./interface.js";
3
- import { EmbeddingProvider, VectorStoreProvider } from "@lssm/lib.contracts/integrations/providers";
4
-
5
- //#region src/retriever/vector-retriever.d.ts
6
-
7
- /**
8
- * Configuration for the vector retriever.
9
- */
10
- interface VectorRetrieverConfig extends RetrieverConfig {
11
- /** Embedding provider for query vectorization */
12
- embeddings: EmbeddingProvider;
13
- /** Vector store provider for similarity search */
14
- vectorStore: VectorStoreProvider;
15
- /** Map of space key to collection name */
16
- spaceCollections: Map<string, string> | Record<string, string>;
17
- /** Optional static content for getStatic() calls */
18
- staticContent?: Map<string, string> | Record<string, string>;
19
- }
20
- /**
21
- * A retriever that uses vector similarity search.
22
- *
23
- * Uses embedding provider to vectorize queries and vector store
24
- * provider to perform similarity search.
25
- */
26
- declare class VectorRetriever implements KnowledgeRetriever {
27
- private readonly config;
28
- private readonly spaceCollections;
29
- private readonly staticContent;
30
- constructor(config: VectorRetrieverConfig);
31
- retrieve(query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
32
- getStatic(spaceKey: string): Promise<string | null>;
33
- supportsSpace(spaceKey: string): boolean;
34
- listSpaces(): string[];
35
- private extractContent;
36
- }
37
- /**
38
- * Create a vector retriever from configuration.
39
- */
40
- declare function createVectorRetriever(config: VectorRetrieverConfig): VectorRetriever;
41
- //#endregion
42
- export { VectorRetriever, VectorRetrieverConfig, createVectorRetriever };
package/dist/types.d.ts DELETED
@@ -1,55 +0,0 @@
1
- import { KnowledgeCategory } from "@lssm/lib.contracts/knowledge";
2
-
3
- //#region src/types.d.ts
4
-
5
- /**
6
- * Result from a knowledge retrieval operation.
7
- */
8
- interface RetrievalResult {
9
- /** The retrieved content/text */
10
- content: string;
11
- /** Source identifier (document ID, URL, etc.) */
12
- source: string;
13
- /** Relevance score (0-1, higher is more relevant) */
14
- score: number;
15
- /** Additional metadata about the result */
16
- metadata?: Record<string, unknown>;
17
- }
18
- /**
19
- * Options for knowledge retrieval.
20
- */
21
- interface RetrievalOptions {
22
- /** Knowledge space key to query */
23
- spaceKey: string;
24
- /** Maximum number of results to return */
25
- topK?: number;
26
- /** Minimum relevance score threshold */
27
- minScore?: number;
28
- /** Filter by knowledge category */
29
- category?: KnowledgeCategory;
30
- /** Tenant-scoped retrieval */
31
- tenantId?: string;
32
- /** Additional filter criteria */
33
- filter?: Record<string, unknown>;
34
- }
35
- /**
36
- * Context for knowledge access operations.
37
- */
38
- interface KnowledgeAccessContext {
39
- tenantId: string;
40
- appId: string;
41
- environment?: string;
42
- workflowName?: string;
43
- agentName?: string;
44
- operation: 'read' | 'write' | 'search';
45
- }
46
- /**
47
- * Result of an access check.
48
- */
49
- interface KnowledgeAccessResult {
50
- allowed: boolean;
51
- reason?: string;
52
- severity?: 'error' | 'warning';
53
- }
54
- //#endregion
55
- export { KnowledgeAccessContext, KnowledgeAccessResult, RetrievalOptions, RetrievalResult };