@o-lang/semantic-doc-search 1.0.24 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o-lang/semantic-doc-search",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "description": "O-lang Semantic Document Search Resolver with hybrid search, embeddings, rerank, and streaming.",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -1,29 +1,40 @@
1
+ /**
2
+ * Capability & metadata for vector backends.
3
+ * No hardcoded "default" assumptions.
4
+ * Resolvers and VectorRouter decide which backend to use at runtime.
5
+ */
6
+
1
7
  module.exports = {
2
8
  pgvector: {
3
9
  persistent: true,
4
10
  offline: false,
5
11
  distance: "cosine",
6
- maxDimension: 2000
12
+ maxDimension: 2000,
13
+ // capability declaration
14
+ capabilities: ["vector.insert", "vector.search"]
7
15
  },
8
16
 
9
17
  pinecone: {
10
18
  persistent: true,
11
19
  offline: false,
12
20
  distance: "cosine",
13
- maxDimension: 1536
21
+ maxDimension: 1536,
22
+ capabilities: ["vector.insert", "vector.search"]
14
23
  },
15
24
 
16
25
  redis: {
17
26
  persistent: true,
18
27
  offline: false,
19
28
  distance: "cosine",
20
- maxDimension: 2048
29
+ maxDimension: 2048,
30
+ capabilities: ["vector.insert", "vector.search"]
21
31
  },
22
32
 
23
33
  memory: {
24
34
  persistent: false,
25
35
  offline: true,
26
36
  distance: "cosine",
27
- maxDimension: 4096
37
+ maxDimension: 4096,
38
+ capabilities: ["vector.insert", "vector.search"]
28
39
  }
29
- };
40
+ };
@@ -1,7 +1,22 @@
1
1
  class VectorRouter {
2
2
  static create(config = {}) {
3
- const backend = config.backend || "pgvector";
3
+ // 1. Explicit backend override (advanced users only)
4
+ if (config.backend) {
5
+ return VectorRouter._createExplicitBackend(config.backend, config);
6
+ }
7
+
8
+ // 2. Auto-detect pgvector (DEFAULT)
9
+ if (config.POSTGRES_URL) {
10
+ const PgVectorAdapter = require("./pgvectorAdapter");
11
+ return new PgVectorAdapter(config);
12
+ }
13
+
14
+ // 3. Fallback to in-memory (safe default)
15
+ const InMemoryAdapter = require("./inMemoryAdapter");
16
+ return new InMemoryAdapter(config);
17
+ }
4
18
 
19
+ static _createExplicitBackend(backend, config) {
5
20
  switch (backend) {
6
21
  case "pgvector": {
7
22
  const PgVectorAdapter = require("./pgvectorAdapter");
package/src/index.js CHANGED
@@ -246,27 +246,10 @@ async function performDocQA(query, context) {
246
246
 
247
247
  /* ---------------- O-LANG RESOLVER ---------------- */
248
248
 
249
- async function docSearchResolver(action, context) {
250
- if (!action.startsWith("Ask doc-search")) return;
251
-
252
- // Extract the query string
253
- const match = action.match(/"(.*)"|'(.*)'/);
254
- const query = match ? match[1] || match[2] : action.replace("Ask doc-search", "").trim();
255
-
256
- // Optional: extract topK and minScore if provided in action, e.g. "Ask doc-search 'Vacation policy' topK=3 minScore=0.8"
257
- let topK = 5;
258
- let minScore = 0.75;
259
-
260
- const topKMatch = action.match(/topK\s*=\s*(\d+)/i);
261
- if (topKMatch) topK = parseInt(topKMatch[1], 10);
249
+ const semanticResolver = require("./resolver"); // ✅ IMPORT NEW FILE
262
250
 
263
- const minScoreMatch = action.match(/minScore\s*=\s*(0?\.\d+|1(\.0)?)/i);
264
- if (minScoreMatch) minScore = parseFloat(minScoreMatch[1]);
265
-
266
- // Pass these into context for hybrid search
267
- const searchContext = { ...context, topK, minScore };
268
-
269
- return performDocQA(query, searchContext);
251
+ async function docSearchResolver(action, context) {
252
+ return semanticResolver(action, context);
270
253
  }
271
254
 
272
255
  docSearchResolver.resolverName = "doc-search";
@@ -0,0 +1,40 @@
1
+ const VectorRouter = require("./adapters/vectorRouter");
2
+ const { embed } = require("./embeddings/local");
3
+ const { extractQuery } = require("./utils/extractQuery");
4
+ const { formatResults } = require("./utils/formatResults");
5
+
6
+ /**
7
+ * Semantic Doc Search Resolver
8
+ * Invoked by O-Lang runtime when workflow uses:
9
+ * Ask doc-search: "..."
10
+ */
11
+ async function resolver(action, context = {}) {
12
+ // Only handle doc-search actions
13
+ if (typeof action !== "string") return;
14
+ if (!action.toLowerCase().startsWith("ask doc-search")) return;
15
+
16
+ // 1️⃣ Extract natural language query
17
+ const query = extractQuery(action);
18
+
19
+ // 2️⃣ Select vector backend (pgvector if available, else fallback)
20
+ const vectorStore = VectorRouter.create(context);
21
+
22
+ if (!vectorStore.supports("vector.search")) {
23
+ throw new Error("Vector backend does not support vector.search");
24
+ }
25
+
26
+ // 3️⃣ Generate embedding
27
+ const vector = await embed(query);
28
+
29
+ // 4️⃣ Execute similarity search
30
+ const results = await vectorStore.query({
31
+ vector,
32
+ topK: context.topK || 5,
33
+ minScore: context.minScore || 0
34
+ });
35
+
36
+ // 5️⃣ Normalize output for workflow consumption
37
+ return formatResults(results, query);
38
+ }
39
+
40
+ module.exports = resolver;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Extracts the query from an O-Lang action.
3
+ * Example:
4
+ * "Ask doc-search: vacation policy"
5
+ */
6
+ function extractQuery(action) {
7
+ const match = action.match(/ask doc-search\s*:?\s*(.+)$/i);
8
+
9
+ if (!match || !match[1]) {
10
+ throw new Error("Invalid doc-search action format");
11
+ }
12
+
13
+ return match[1].trim();
14
+ }
15
+
16
+ module.exports = {
17
+ extractQuery
18
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Normalizes vector search results for O-Lang workflows.
3
+ */
4
+ function formatResults(results = [], query) {
5
+ return {
6
+ query,
7
+ matches: results.map(r => ({
8
+ id: r.id,
9
+ content: r.content,
10
+ source: r.source,
11
+ score: typeof r.score === "number"
12
+ ? Number(r.score.toFixed(4))
13
+ : undefined
14
+ }))
15
+ };
16
+ }
17
+
18
+ module.exports = {
19
+ formatResults
20
+ };