@o-lang/olang 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 +1 -1
- package/src/runtime.js +5 -4
- package/src/vector/VectorBackend.js +33 -0
- package/src/vector/backends/pgvector.js +95 -0
- package/src/vector/index.js +24 -0
package/package.json
CHANGED
package/src/runtime.js
CHANGED
|
@@ -346,10 +346,11 @@ class RuntimeAPI {
|
|
|
346
346
|
};
|
|
347
347
|
|
|
348
348
|
// ✅ Check for Advanced Evolution Service (paid tier)
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
349
|
+
// ✅ Check for Advanced Evolution Service (paid tier)
|
|
350
|
+
if (process.env.OLANG_EVOLUTION_API_KEY) {
|
|
351
|
+
evolutionResult.status = 'advanced_evolution_enabled';
|
|
352
|
+
evolutionResult.message = 'Advanced evolution service would process this request';
|
|
353
|
+
}
|
|
353
354
|
|
|
354
355
|
if (step.saveAs) {
|
|
355
356
|
this.context[step.saveAs] = evolutionResult;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract capability-based vector backend.
|
|
3
|
+
* Backends expose what they support via `supports(capability)`
|
|
4
|
+
* and execute via `call(capability, payload, context)`.
|
|
5
|
+
*/
|
|
6
|
+
class VectorBackend {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check whether a capability is supported.
|
|
13
|
+
* @param {string} capability
|
|
14
|
+
* @returns {boolean}
|
|
15
|
+
*/
|
|
16
|
+
supports(capability) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Execute a capability.
|
|
22
|
+
* @param {string} capability
|
|
23
|
+
* @param {object} payload
|
|
24
|
+
* @param {object} context
|
|
25
|
+
*/
|
|
26
|
+
async call(capability, payload, context) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Vector backend does not support capability: ${capability}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = VectorBackend;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const { Pool } = require("pg");
|
|
2
|
+
const VectorBackend = require("../VectorBackend");
|
|
3
|
+
|
|
4
|
+
class PgVectorBackend extends VectorBackend {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
super(options);
|
|
7
|
+
|
|
8
|
+
if (!options.POSTGRES_URL) {
|
|
9
|
+
throw new Error("PgVectorBackend requires POSTGRES_URL");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
this.pool = new Pool({
|
|
13
|
+
connectionString: options.POSTGRES_URL
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
this.table = options.table || "olang_vectors";
|
|
17
|
+
this.dimensions = options.dimensions;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
supports(capability) {
|
|
21
|
+
return [
|
|
22
|
+
"vector.insert",
|
|
23
|
+
"vector.search"
|
|
24
|
+
].includes(capability);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async call(capability, payload) {
|
|
28
|
+
switch (capability) {
|
|
29
|
+
case "vector.insert":
|
|
30
|
+
return this.insert(payload);
|
|
31
|
+
case "vector.search":
|
|
32
|
+
return this.search(payload);
|
|
33
|
+
default:
|
|
34
|
+
return super.call(capability, payload);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* ---------------- Internal ops ---------------- */
|
|
39
|
+
|
|
40
|
+
async ensureTable() {
|
|
41
|
+
if (this._tableReady) return;
|
|
42
|
+
|
|
43
|
+
await this.pool.query(`
|
|
44
|
+
CREATE TABLE IF NOT EXISTS ${this.table} (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
vector VECTOR(${this.dimensions}),
|
|
47
|
+
content TEXT,
|
|
48
|
+
source TEXT
|
|
49
|
+
);
|
|
50
|
+
`);
|
|
51
|
+
|
|
52
|
+
this._tableReady = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async insert({ id, vector, content, source }) {
|
|
56
|
+
await this.ensureTable();
|
|
57
|
+
|
|
58
|
+
await this.pool.query(
|
|
59
|
+
`
|
|
60
|
+
INSERT INTO ${this.table} (id, vector, content, source)
|
|
61
|
+
VALUES ($1, $2, $3, $4)
|
|
62
|
+
ON CONFLICT (id)
|
|
63
|
+
DO UPDATE SET
|
|
64
|
+
vector = EXCLUDED.vector,
|
|
65
|
+
content = EXCLUDED.content,
|
|
66
|
+
source = EXCLUDED.source
|
|
67
|
+
`,
|
|
68
|
+
[id, vector, content, source]
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return { inserted: true };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async search({ vector, topK = 5, minScore = 0 }) {
|
|
75
|
+
await this.ensureTable();
|
|
76
|
+
|
|
77
|
+
const res = await this.pool.query(
|
|
78
|
+
`
|
|
79
|
+
SELECT
|
|
80
|
+
id,
|
|
81
|
+
content,
|
|
82
|
+
source,
|
|
83
|
+
1 - (vector <=> $1) AS score
|
|
84
|
+
FROM ${this.table}
|
|
85
|
+
ORDER BY vector <=> $1
|
|
86
|
+
LIMIT $2
|
|
87
|
+
`,
|
|
88
|
+
[vector, topK]
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return res.rows.filter(r => r.score >= minScore);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = PgVectorBackend;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const PgVectorBackend = require("./backends/pgvector");
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vector backend factory.
|
|
5
|
+
* Kernel never imports pgvector directly.
|
|
6
|
+
*/
|
|
7
|
+
function createVectorBackend(context = {}) {
|
|
8
|
+
// Default backend: pgvector
|
|
9
|
+
if (!context.POSTGRES_URL) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"No vector backend available: POSTGRES_URL not provided"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return new PgVectorBackend({
|
|
16
|
+
POSTGRES_URL: context.POSTGRES_URL,
|
|
17
|
+
table: context.vector_table,
|
|
18
|
+
dimensions: context.vector_dimensions
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
createVectorBackend
|
|
24
|
+
};
|