@backendkit-labs/agent-enterprise 0.2.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/README.md +185 -0
- package/dist/__tests__/integration/ObsidianRAGProvider.test.d.ts +2 -0
- package/dist/__tests__/integration/ObsidianRAGProvider.test.d.ts.map +1 -0
- package/dist/__tests__/integration/ObsidianRAGProvider.test.js +237 -0
- package/dist/__tests__/integration/ObsidianRAGProvider.test.js.map +1 -0
- package/dist/__tests__/integration/OllamaEmbedder.test.d.ts +2 -0
- package/dist/__tests__/integration/OllamaEmbedder.test.d.ts.map +1 -0
- package/dist/__tests__/integration/OllamaEmbedder.test.js +101 -0
- package/dist/__tests__/integration/OllamaEmbedder.test.js.map +1 -0
- package/dist/__tests__/unit/VaultIndexer.test.d.ts +2 -0
- package/dist/__tests__/unit/VaultIndexer.test.d.ts.map +1 -0
- package/dist/__tests__/unit/VaultIndexer.test.js +174 -0
- package/dist/__tests__/unit/VaultIndexer.test.js.map +1 -0
- package/dist/__tests__/unit/VectorStore.test.d.ts +2 -0
- package/dist/__tests__/unit/VectorStore.test.d.ts.map +1 -0
- package/dist/__tests__/unit/VectorStore.test.js +146 -0
- package/dist/__tests__/unit/VectorStore.test.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/rag/ObsidianRAGProvider.d.ts +52 -0
- package/dist/rag/ObsidianRAGProvider.d.ts.map +1 -0
- package/dist/rag/ObsidianRAGProvider.js +148 -0
- package/dist/rag/ObsidianRAGProvider.js.map +1 -0
- package/dist/rag/OllamaEmbedder.d.ts +15 -0
- package/dist/rag/OllamaEmbedder.d.ts.map +1 -0
- package/dist/rag/OllamaEmbedder.js +50 -0
- package/dist/rag/OllamaEmbedder.js.map +1 -0
- package/dist/rag/VaultIndexer.d.ts +34 -0
- package/dist/rag/VaultIndexer.d.ts.map +1 -0
- package/dist/rag/VaultIndexer.js +230 -0
- package/dist/rag/VaultIndexer.js.map +1 -0
- package/dist/rag/VaultWriter.d.ts +33 -0
- package/dist/rag/VaultWriter.d.ts.map +1 -0
- package/dist/rag/VaultWriter.js +112 -0
- package/dist/rag/VaultWriter.js.map +1 -0
- package/dist/rag/VectorStore.d.ts +36 -0
- package/dist/rag/VectorStore.d.ts.map +1 -0
- package/dist/rag/VectorStore.js +119 -0
- package/dist/rag/VectorStore.js.map +1 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# @backendkit-labs/agent-enterprise
|
|
2
|
+
|
|
3
|
+
Enterprise knowledge layer for the BackendKit Agent Framework — local RAG over Obsidian vaults, shared knowledge vault with agent write-back, and pluggable embedders.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @backendkit-labs/agent-enterprise
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
> Requires `@backendkit-labs/agent-core`. Works with any LLM provider — no cloud dependency required.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Gives your agents a **shared, persistent knowledge base** backed by Markdown files:
|
|
16
|
+
|
|
17
|
+
- **Read** — agents search the vault semantically (`search_knowledge` tool)
|
|
18
|
+
- **Write** — agents contribute new knowledge back to the vault (`write_knowledge` tool)
|
|
19
|
+
- **Index** — incremental indexing by file mtime; only re-embeds new or modified files
|
|
20
|
+
- **Human-readable** — the vault is plain Markdown, openable in Obsidian or any editor
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick start — RAG over an Obsidian vault
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { AgentEngine, ToolRegistry } from '@backendkit-labs/agent-core';
|
|
28
|
+
import { ObsidianRAGProvider } from '@backendkit-labs/agent-enterprise';
|
|
29
|
+
|
|
30
|
+
const rag = new ObsidianRAGProvider({
|
|
31
|
+
vaultPath: '/path/to/your/vault',
|
|
32
|
+
ollamaHost: 'http://localhost:11434', // default
|
|
33
|
+
embeddingModel: 'nomic-embed-text', // default
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Index the vault (incremental — only changed files on subsequent runs)
|
|
37
|
+
await rag.index({ verbose: true });
|
|
38
|
+
|
|
39
|
+
// Register the search_knowledge tool with your engine
|
|
40
|
+
const tools = new ToolRegistry();
|
|
41
|
+
tools.register(rag.createTool());
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The agent calls `search_knowledge` automatically when it needs information from the vault.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Shared vault with agent write-back
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { ObsidianRAGProvider, VaultWriter } from '@backendkit-labs/agent-enterprise';
|
|
52
|
+
|
|
53
|
+
const rag = new ObsidianRAGProvider({ vaultPath: '/vault', ...opts });
|
|
54
|
+
const writer = new VaultWriter({ vaultPath: '/vault' });
|
|
55
|
+
|
|
56
|
+
const tools = new ToolRegistry();
|
|
57
|
+
tools.register(rag.createTool()); // search_knowledge
|
|
58
|
+
tools.register(writer.createTool('analyst')); // write_knowledge — baked in with agent id
|
|
59
|
+
|
|
60
|
+
// After the agent writes a note, re-index to make it searchable:
|
|
61
|
+
await rag.index();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Agent-written notes land in `<vaultPath>/agentes/` with standard frontmatter:
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
---
|
|
68
|
+
title: "Cache Decision for RAG Embeddings"
|
|
69
|
+
author: "agent/analyst"
|
|
70
|
+
date: 2026-06-10
|
|
71
|
+
tags: ["área/rag", "tipo/decisión"]
|
|
72
|
+
description: "LRU in-memory cache chosen over persistent or semantic cache"
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Context
|
|
76
|
+
...
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Custom embedder — no Ollama required
|
|
82
|
+
|
|
83
|
+
Pass any object that implements `Embedder` to skip Ollama:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { ObsidianRAGProvider, type Embedder } from '@backendkit-labs/agent-enterprise';
|
|
87
|
+
|
|
88
|
+
class MyEmbedder implements Embedder {
|
|
89
|
+
readonly model = 'my-model-v1';
|
|
90
|
+
async embed(texts: string[]): Promise<number[][]> { /* ... */ }
|
|
91
|
+
async embedOne(text: string): Promise<number[]> { /* ... */ }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const rag = new ObsidianRAGProvider({
|
|
95
|
+
vaultPath: '/vault',
|
|
96
|
+
embedder: new MyEmbedder(), // ollamaHost and embeddingModel are ignored
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## SimpleEmbedder — local testing without Ollama
|
|
103
|
+
|
|
104
|
+
For tests and CI where Ollama is not available:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// Not exported from the package — copy from pilot/src/embedders/SimpleEmbedder.ts
|
|
108
|
+
// TF-IDF feature hashing, 256 dims, pure Node.js, zero dependencies
|
|
109
|
+
const rag = new ObsidianRAGProvider({
|
|
110
|
+
vaultPath: '/vault',
|
|
111
|
+
embedder: new SimpleEmbedder(),
|
|
112
|
+
minScore: 0.1, // lower threshold for keyword-based vectors
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## ObsidianRAGProvider options
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
new ObsidianRAGProvider({
|
|
122
|
+
vaultPath: string; // absolute path to vault directory
|
|
123
|
+
folders?: string[]; // sub-folders to index (default: all)
|
|
124
|
+
indexPath?: string; // where to save the vector index JSON
|
|
125
|
+
embedder?: Embedder; // custom embedder (overrides ollamaHost/embeddingModel)
|
|
126
|
+
ollamaHost?: string; // default: http://localhost:11434
|
|
127
|
+
embeddingModel?: string; // default: nomic-embed-text
|
|
128
|
+
topK?: number; // max results per search (default: 5)
|
|
129
|
+
minScore?: number; // min cosine similarity 0–1 (default: 0.3)
|
|
130
|
+
excludeTags?: string[]; // frontmatter tags to skip (default: ['skill'])
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## VaultWriter options
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
new VaultWriter({
|
|
140
|
+
vaultPath: string; // must match the ObsidianRAGProvider vaultPath
|
|
141
|
+
agentFolder?: string; // sub-folder for agent notes (default: 'agentes')
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
writer.createTool(agentId: string): ToolDefinition
|
|
145
|
+
// Returns write_knowledge tool with agentId baked into each note's author field
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Vault structure
|
|
151
|
+
|
|
152
|
+
Recommended layout for enterprise deployments:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
vault/
|
|
156
|
+
rrhh/ ← HR domain — only HR Agent indexed here
|
|
157
|
+
ventas/ ← Sales domain
|
|
158
|
+
ops/ ← Operations
|
|
159
|
+
compartido/ ← Cross-domain, all agents read
|
|
160
|
+
agentes/ ← Auto-created — agent-written notes land here
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Mount only the relevant folders per agent:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
new ObsidianRAGProvider({ vaultPath, folders: ['ventas', 'compartido', 'agentes'] })
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## How indexing works
|
|
172
|
+
|
|
173
|
+
1. `VaultIndexer` scans `.md` files and reads their `mtime`
|
|
174
|
+
2. Compares against stored mtimes in `VectorStore`
|
|
175
|
+
3. Only embeds files that are new or modified since last index
|
|
176
|
+
4. Chunks each file by `##` headings (max 500 words per chunk)
|
|
177
|
+
5. Stores vectors + metadata in a single JSON file on disk
|
|
178
|
+
|
|
179
|
+
The JSON store scales to ~5–10k chunks. For larger vaults, use a proper vector DB (pgvector, Qdrant) with a custom `Embedder` adapter.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT © [BackendKit Labs](https://github.com/BackendKit-labs)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObsidianRAGProvider.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/ObsidianRAGProvider.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const fs = __importStar(require("fs/promises"));
|
|
37
|
+
const os = __importStar(require("os"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const ObsidianRAGProvider_1 = require("../../rag/ObsidianRAGProvider");
|
|
40
|
+
const OLLAMA_HOST = process.env.OLLAMA_HOST ?? 'http://localhost:11434';
|
|
41
|
+
const EMBED_MODEL = process.env.EMBEDDING_MODEL ?? 'nomic-embed-text';
|
|
42
|
+
// ── Vault de fixtures ─────────────────────────────────────────────────────────
|
|
43
|
+
const FIXTURES = {
|
|
44
|
+
'agentes-orquestacion.md': `---
|
|
45
|
+
title: Orquestación de Agentes IA
|
|
46
|
+
tags: [área/arquitectura, stack/typescript]
|
|
47
|
+
description: Patrones para coordinar múltiples agentes especializados
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Patrón orquestador-especialista
|
|
51
|
+
|
|
52
|
+
El orquestador recibe la tarea del usuario y la descompone en subtareas.
|
|
53
|
+
Cada subtarea se delega a un agente especialista a través del tool ask_agent.
|
|
54
|
+
Los especialistas devuelven su resultado al orquestador, que sintetiza la respuesta final.
|
|
55
|
+
|
|
56
|
+
## Delegación paralela
|
|
57
|
+
|
|
58
|
+
Cuando las subtareas son independientes entre sí, el orquestador puede lanzar
|
|
59
|
+
múltiples ask_agent en el mismo turno. El engine ejecuta todas las delegaciones
|
|
60
|
+
en paralelo, limitado por el bulkhead de 6 slots concurrentes.
|
|
61
|
+
`,
|
|
62
|
+
'rag-vectorial.md': `---
|
|
63
|
+
title: RAG con Vector Store Local
|
|
64
|
+
tags: [área/ia, stack/typescript]
|
|
65
|
+
description: Implementación de Retrieval Augmented Generation sin dependencias externas
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Embeddings con Ollama
|
|
69
|
+
|
|
70
|
+
Los embeddings se generan usando el modelo nomic-embed-text de Ollama.
|
|
71
|
+
La API es POST /api/embed con el texto y el nombre del modelo.
|
|
72
|
+
El resultado es un vector de 768 dimensiones para nomic-embed-text.
|
|
73
|
+
|
|
74
|
+
## Similitud coseno
|
|
75
|
+
|
|
76
|
+
La búsqueda semántica compara el embedding de la consulta con los embeddings
|
|
77
|
+
almacenados usando similitud coseno. El resultado más cercano a 1.0 es el más relevante.
|
|
78
|
+
|
|
79
|
+
## Indexación incremental
|
|
80
|
+
|
|
81
|
+
El VectorStore guarda el mtime de cada archivo. En el siguiente índice,
|
|
82
|
+
solo se re-embeden los archivos nuevos o modificados.
|
|
83
|
+
`,
|
|
84
|
+
'typescript-patterns.md': `---
|
|
85
|
+
title: Patrones TypeScript en el Framework
|
|
86
|
+
tags: [stack/typescript, área/arquitectura]
|
|
87
|
+
description: Convenciones de código usadas en el proyecto
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Tipos estrictos
|
|
91
|
+
|
|
92
|
+
El proyecto usa strict mode de TypeScript. Todos los parámetros opcionales
|
|
93
|
+
deben declararse explícitamente. No se permite any sin justificación.
|
|
94
|
+
|
|
95
|
+
## Inyección de dependencias
|
|
96
|
+
|
|
97
|
+
Los providers se registran en ProviderRegistry y se resuelven por nombre.
|
|
98
|
+
Esto permite intercambiar OllamaProvider por otros providers en tests.
|
|
99
|
+
`,
|
|
100
|
+
};
|
|
101
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
102
|
+
async function ollamaAvailable() {
|
|
103
|
+
try {
|
|
104
|
+
const res = await fetch(`${OLLAMA_HOST}/api/tags`, {
|
|
105
|
+
signal: AbortSignal.timeout(3000),
|
|
106
|
+
});
|
|
107
|
+
if (!res.ok)
|
|
108
|
+
return false;
|
|
109
|
+
const data = await res.json();
|
|
110
|
+
return (data.models ?? []).some(m => m.name.startsWith(EMBED_MODEL));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function createFixtureVault(dir) {
|
|
117
|
+
for (const [name, content] of Object.entries(FIXTURES)) {
|
|
118
|
+
await fs.writeFile(path.join(dir, name), content, 'utf-8');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// ── Suite ─────────────────────────────────────────────────────────────────────
|
|
122
|
+
describe('ObsidianRAGProvider — integración', () => {
|
|
123
|
+
let available = false;
|
|
124
|
+
let vaultDir;
|
|
125
|
+
let indexDir;
|
|
126
|
+
beforeAll(async () => {
|
|
127
|
+
available = await ollamaAvailable();
|
|
128
|
+
if (!available) {
|
|
129
|
+
console.warn(`\n⚠ ObsidianRAGProvider tests saltados — Ollama no disponible en ${OLLAMA_HOST} ` +
|
|
130
|
+
`o modelo '${EMBED_MODEL}' no descargado.\n` +
|
|
131
|
+
` Para ejecutarlos: ollama serve && ollama pull ${EMBED_MODEL}\n`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const base = await fs.mkdtemp(path.join(os.tmpdir(), 'bk-rag-e2e-'));
|
|
135
|
+
vaultDir = path.join(base, 'vault');
|
|
136
|
+
indexDir = path.join(base, 'index');
|
|
137
|
+
await fs.mkdir(vaultDir);
|
|
138
|
+
await fs.mkdir(indexDir);
|
|
139
|
+
await createFixtureVault(vaultDir);
|
|
140
|
+
});
|
|
141
|
+
afterAll(async () => {
|
|
142
|
+
if (vaultDir) {
|
|
143
|
+
await fs.rm(path.dirname(vaultDir), { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
test('index() indexa todos los archivos del vault fixture', async () => {
|
|
147
|
+
if (!available)
|
|
148
|
+
return;
|
|
149
|
+
const rag = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
150
|
+
vaultPath: vaultDir,
|
|
151
|
+
indexPath: path.join(indexDir, 'index.json'),
|
|
152
|
+
ollamaHost: OLLAMA_HOST,
|
|
153
|
+
embeddingModel: EMBED_MODEL,
|
|
154
|
+
});
|
|
155
|
+
const { indexed, removed } = await rag.index({ verbose: false });
|
|
156
|
+
expect(indexed).toBeGreaterThan(0); // al menos un chunk por archivo
|
|
157
|
+
expect(removed).toBe(0);
|
|
158
|
+
expect(rag.chunkCount).toBeGreaterThan(0);
|
|
159
|
+
});
|
|
160
|
+
test('index() incremental no re-indexa archivos sin cambios', async () => {
|
|
161
|
+
if (!available)
|
|
162
|
+
return;
|
|
163
|
+
const indexPath = path.join(indexDir, 'incremental.json');
|
|
164
|
+
const rag = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
165
|
+
vaultPath: vaultDir, indexPath, ollamaHost: OLLAMA_HOST, embeddingModel: EMBED_MODEL,
|
|
166
|
+
});
|
|
167
|
+
await rag.index(); // primera pasada — indexa todo
|
|
168
|
+
const rag2 = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
169
|
+
vaultPath: vaultDir, indexPath, ollamaHost: OLLAMA_HOST, embeddingModel: EMBED_MODEL,
|
|
170
|
+
});
|
|
171
|
+
const { indexed } = await rag2.index(); // segunda pasada — nada cambió
|
|
172
|
+
expect(indexed).toBe(0);
|
|
173
|
+
});
|
|
174
|
+
test('search devuelve el chunk más relevante para "orquestador"', async () => {
|
|
175
|
+
if (!available)
|
|
176
|
+
return;
|
|
177
|
+
const rag = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
178
|
+
vaultPath: vaultDir,
|
|
179
|
+
indexPath: path.join(indexDir, 'search-test.json'),
|
|
180
|
+
ollamaHost: OLLAMA_HOST,
|
|
181
|
+
embeddingModel: EMBED_MODEL,
|
|
182
|
+
topK: 3,
|
|
183
|
+
minScore: 0.1,
|
|
184
|
+
});
|
|
185
|
+
const result = await rag.search('patrón orquestador especialista delegación');
|
|
186
|
+
expect(result).toContain('orquestaci'); // título o contenido del archivo relevante
|
|
187
|
+
expect(result).not.toBe('No se encontró información relevante en la base de conocimiento para esa consulta.');
|
|
188
|
+
});
|
|
189
|
+
test('search devuelve mensaje de no-resultados para consulta sin match', async () => {
|
|
190
|
+
if (!available)
|
|
191
|
+
return;
|
|
192
|
+
const rag = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
193
|
+
vaultPath: vaultDir,
|
|
194
|
+
indexPath: path.join(indexDir, 'no-match.json'),
|
|
195
|
+
ollamaHost: OLLAMA_HOST,
|
|
196
|
+
embeddingModel: EMBED_MODEL,
|
|
197
|
+
minScore: 0.99, // umbral imposible de alcanzar
|
|
198
|
+
});
|
|
199
|
+
const result = await rag.search('xyzabcnonexistent987');
|
|
200
|
+
expect(result).toContain('No se encontró información relevante');
|
|
201
|
+
});
|
|
202
|
+
test('búsquedas sobre temas distintos devuelven fuentes distintas', async () => {
|
|
203
|
+
if (!available)
|
|
204
|
+
return;
|
|
205
|
+
const rag = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
206
|
+
vaultPath: vaultDir,
|
|
207
|
+
indexPath: path.join(indexDir, 'multi-topic.json'),
|
|
208
|
+
ollamaHost: OLLAMA_HOST,
|
|
209
|
+
embeddingModel: EMBED_MODEL,
|
|
210
|
+
topK: 1,
|
|
211
|
+
minScore: 0.1,
|
|
212
|
+
});
|
|
213
|
+
const resultOrq = await rag.search('orquestador y delegación de agentes');
|
|
214
|
+
const resultTS = await rag.search('strict mode TypeScript inyección dependencias');
|
|
215
|
+
// Los resultados top deben venir de archivos distintos
|
|
216
|
+
const titleOrq = resultOrq.match(/Fuente: ([^\n]+)/)?.[1] ?? '';
|
|
217
|
+
const titleTS = resultTS.match(/Fuente: ([^\n]+)/)?.[1] ?? '';
|
|
218
|
+
expect(titleOrq).not.toBe(titleTS);
|
|
219
|
+
});
|
|
220
|
+
test('createTool devuelve un ToolDefinition ejecutable', async () => {
|
|
221
|
+
if (!available)
|
|
222
|
+
return;
|
|
223
|
+
const rag = new ObsidianRAGProvider_1.ObsidianRAGProvider({
|
|
224
|
+
vaultPath: vaultDir,
|
|
225
|
+
indexPath: path.join(indexDir, 'tool-test.json'),
|
|
226
|
+
ollamaHost: OLLAMA_HOST,
|
|
227
|
+
embeddingModel: EMBED_MODEL,
|
|
228
|
+
});
|
|
229
|
+
const tool = rag.createTool();
|
|
230
|
+
expect(tool.name).toBe('search_knowledge');
|
|
231
|
+
expect(typeof tool.execute).toBe('function');
|
|
232
|
+
const result = await tool.execute({ query: 'embeddings vectoriales' }, {});
|
|
233
|
+
expect(typeof result).toBe('string');
|
|
234
|
+
expect(result.length).toBeGreaterThan(0);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
//# sourceMappingURL=ObsidianRAGProvider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObsidianRAGProvider.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/ObsidianRAGProvider.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OllamaEmbedder.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/OllamaEmbedder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const OllamaEmbedder_1 = require("../../rag/OllamaEmbedder");
|
|
4
|
+
const OLLAMA_HOST = process.env.OLLAMA_HOST ?? 'http://localhost:11434';
|
|
5
|
+
const EMBED_MODEL = process.env.EMBEDDING_MODEL ?? 'nomic-embed-text';
|
|
6
|
+
async function ollamaAvailable() {
|
|
7
|
+
try {
|
|
8
|
+
const res = await fetch(`${OLLAMA_HOST}/api/tags`, {
|
|
9
|
+
signal: AbortSignal.timeout(3000),
|
|
10
|
+
});
|
|
11
|
+
return res.ok;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function modelAvailable(model) {
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(`${OLLAMA_HOST}/api/tags`);
|
|
20
|
+
const data = await res.json();
|
|
21
|
+
return (data.models ?? []).some(m => m.name.startsWith(model));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
describe('OllamaEmbedder — integración', () => {
|
|
28
|
+
let available = false;
|
|
29
|
+
beforeAll(async () => {
|
|
30
|
+
available = await ollamaAvailable() && await modelAvailable(EMBED_MODEL);
|
|
31
|
+
if (!available) {
|
|
32
|
+
console.warn(`\n⚠ OllamaEmbedder tests saltados — Ollama no disponible en ${OLLAMA_HOST} ` +
|
|
33
|
+
`o modelo '${EMBED_MODEL}' no descargado.\n` +
|
|
34
|
+
` Para ejecutarlos: ollama serve && ollama pull ${EMBED_MODEL}\n`);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
test('checkConnection no lanza si Ollama está corriendo', async () => {
|
|
38
|
+
if (!available)
|
|
39
|
+
return;
|
|
40
|
+
const embedder = new OllamaEmbedder_1.OllamaEmbedder({ host: OLLAMA_HOST, model: EMBED_MODEL });
|
|
41
|
+
await expect(embedder.checkConnection()).resolves.not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
test('embedOne devuelve un vector de la dimensión correcta (768 para nomic-embed-text)', async () => {
|
|
44
|
+
if (!available)
|
|
45
|
+
return;
|
|
46
|
+
const embedder = new OllamaEmbedder_1.OllamaEmbedder({ host: OLLAMA_HOST, model: EMBED_MODEL });
|
|
47
|
+
const vec = await embedder.embedOne('Hola mundo');
|
|
48
|
+
expect(Array.isArray(vec)).toBe(true);
|
|
49
|
+
expect(vec.length).toBeGreaterThan(0);
|
|
50
|
+
// nomic-embed-text produce vectores de 768 dimensiones
|
|
51
|
+
if (EMBED_MODEL === 'nomic-embed-text') {
|
|
52
|
+
expect(vec.length).toBe(768);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
test('embed([]) devuelve array vacío sin llamar a Ollama', async () => {
|
|
56
|
+
// Este test no requiere Ollama — verifica el early-return
|
|
57
|
+
const embedder = new OllamaEmbedder_1.OllamaEmbedder({ host: OLLAMA_HOST, model: EMBED_MODEL });
|
|
58
|
+
const result = await embedder.embed([]);
|
|
59
|
+
expect(result).toEqual([]);
|
|
60
|
+
});
|
|
61
|
+
test('embed de un batch devuelve tantos vectores como textos', async () => {
|
|
62
|
+
if (!available)
|
|
63
|
+
return;
|
|
64
|
+
const embedder = new OllamaEmbedder_1.OllamaEmbedder({ host: OLLAMA_HOST, model: EMBED_MODEL });
|
|
65
|
+
const texts = ['primer texto', 'segundo texto', 'tercer texto'];
|
|
66
|
+
const vecs = await embedder.embed(texts);
|
|
67
|
+
expect(vecs).toHaveLength(3);
|
|
68
|
+
for (const v of vecs) {
|
|
69
|
+
expect(v.length).toBeGreaterThan(0);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
test('textos similares tienen mayor similitud coseno que textos no relacionados', async () => {
|
|
73
|
+
if (!available)
|
|
74
|
+
return;
|
|
75
|
+
const embedder = new OllamaEmbedder_1.OllamaEmbedder({ host: OLLAMA_HOST, model: EMBED_MODEL });
|
|
76
|
+
const [vBase, vSimilar, vUnrelated] = await embedder.embed([
|
|
77
|
+
'orquestación de agentes IA',
|
|
78
|
+
'coordinación de múltiples agentes inteligentes',
|
|
79
|
+
'receta de paella valenciana',
|
|
80
|
+
]);
|
|
81
|
+
const cosine = (a, b) => {
|
|
82
|
+
let dot = 0, na = 0, nb = 0;
|
|
83
|
+
for (let i = 0; i < a.length; i++) {
|
|
84
|
+
dot += a[i] * b[i];
|
|
85
|
+
na += a[i] ** 2;
|
|
86
|
+
nb += b[i] ** 2;
|
|
87
|
+
}
|
|
88
|
+
return dot / (Math.sqrt(na) * Math.sqrt(nb));
|
|
89
|
+
};
|
|
90
|
+
const simSimilar = cosine(vBase, vSimilar);
|
|
91
|
+
const simUnrelated = cosine(vBase, vUnrelated);
|
|
92
|
+
expect(simSimilar).toBeGreaterThan(simUnrelated);
|
|
93
|
+
});
|
|
94
|
+
test('lanza error descriptivo si el modelo no existe', async () => {
|
|
95
|
+
if (!available)
|
|
96
|
+
return;
|
|
97
|
+
const embedder = new OllamaEmbedder_1.OllamaEmbedder({ host: OLLAMA_HOST, model: 'modelo-inexistente-xyz' });
|
|
98
|
+
await expect(embedder.embedOne('test')).rejects.toThrow(/modelo-inexistente-xyz/i);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=OllamaEmbedder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OllamaEmbedder.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/OllamaEmbedder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VaultIndexer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/VaultIndexer.test.ts"],"names":[],"mappings":""}
|