ahok-skill 1.3.1
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/.prettierrc +8 -0
- package/Dockerfile +59 -0
- package/RAW_SKILL.md +219 -0
- package/README.md +277 -0
- package/SKILL.md +58 -0
- package/bin/opm.js +268 -0
- package/data/openmemory.sqlite +0 -0
- package/data/openmemory.sqlite-shm +0 -0
- package/data/openmemory.sqlite-wal +0 -0
- package/dist/ai/graph.js +293 -0
- package/dist/ai/mcp.js +397 -0
- package/dist/cli.js +78 -0
- package/dist/core/cfg.js +87 -0
- package/dist/core/db.js +636 -0
- package/dist/core/memory.js +116 -0
- package/dist/core/migrate.js +227 -0
- package/dist/core/models.js +105 -0
- package/dist/core/telemetry.js +57 -0
- package/dist/core/types.js +2 -0
- package/dist/core/vector/postgres.js +52 -0
- package/dist/core/vector/valkey.js +246 -0
- package/dist/core/vector_store.js +2 -0
- package/dist/index.js +44 -0
- package/dist/memory/decay.js +301 -0
- package/dist/memory/embed.js +675 -0
- package/dist/memory/hsg.js +959 -0
- package/dist/memory/reflect.js +131 -0
- package/dist/memory/user_summary.js +99 -0
- package/dist/migrate.js +9 -0
- package/dist/ops/compress.js +255 -0
- package/dist/ops/dynamics.js +189 -0
- package/dist/ops/extract.js +333 -0
- package/dist/ops/ingest.js +214 -0
- package/dist/server/index.js +109 -0
- package/dist/server/middleware/auth.js +137 -0
- package/dist/server/routes/auth.js +186 -0
- package/dist/server/routes/compression.js +108 -0
- package/dist/server/routes/dashboard.js +399 -0
- package/dist/server/routes/docs.js +241 -0
- package/dist/server/routes/dynamics.js +312 -0
- package/dist/server/routes/ide.js +280 -0
- package/dist/server/routes/index.js +33 -0
- package/dist/server/routes/keys.js +132 -0
- package/dist/server/routes/langgraph.js +61 -0
- package/dist/server/routes/memory.js +213 -0
- package/dist/server/routes/sources.js +140 -0
- package/dist/server/routes/system.js +63 -0
- package/dist/server/routes/temporal.js +293 -0
- package/dist/server/routes/users.js +101 -0
- package/dist/server/routes/vercel.js +57 -0
- package/dist/server/server.js +211 -0
- package/dist/server.js +3 -0
- package/dist/sources/base.js +223 -0
- package/dist/sources/github.js +171 -0
- package/dist/sources/google_drive.js +166 -0
- package/dist/sources/google_sheets.js +112 -0
- package/dist/sources/google_slides.js +139 -0
- package/dist/sources/index.js +34 -0
- package/dist/sources/notion.js +165 -0
- package/dist/sources/onedrive.js +143 -0
- package/dist/sources/web_crawler.js +166 -0
- package/dist/temporal_graph/index.js +20 -0
- package/dist/temporal_graph/query.js +240 -0
- package/dist/temporal_graph/store.js +116 -0
- package/dist/temporal_graph/timeline.js +241 -0
- package/dist/temporal_graph/types.js +2 -0
- package/dist/utils/chunking.js +60 -0
- package/dist/utils/index.js +31 -0
- package/dist/utils/keyword.js +94 -0
- package/dist/utils/text.js +120 -0
- package/nodemon.json +7 -0
- package/package.json +50 -0
- package/references/api_reference.md +66 -0
- package/references/examples.md +45 -0
- package/src/ai/graph.ts +363 -0
- package/src/ai/mcp.ts +494 -0
- package/src/cli.ts +94 -0
- package/src/core/cfg.ts +110 -0
- package/src/core/db.ts +1052 -0
- package/src/core/memory.ts +99 -0
- package/src/core/migrate.ts +302 -0
- package/src/core/models.ts +107 -0
- package/src/core/telemetry.ts +47 -0
- package/src/core/types.ts +130 -0
- package/src/core/vector/postgres.ts +61 -0
- package/src/core/vector/valkey.ts +261 -0
- package/src/core/vector_store.ts +9 -0
- package/src/index.ts +5 -0
- package/src/memory/decay.ts +427 -0
- package/src/memory/embed.ts +707 -0
- package/src/memory/hsg.ts +1245 -0
- package/src/memory/reflect.ts +158 -0
- package/src/memory/user_summary.ts +110 -0
- package/src/migrate.ts +8 -0
- package/src/ops/compress.ts +296 -0
- package/src/ops/dynamics.ts +272 -0
- package/src/ops/extract.ts +360 -0
- package/src/ops/ingest.ts +286 -0
- package/src/server/index.ts +159 -0
- package/src/server/middleware/auth.ts +156 -0
- package/src/server/routes/auth.ts +223 -0
- package/src/server/routes/compression.ts +106 -0
- package/src/server/routes/dashboard.ts +420 -0
- package/src/server/routes/docs.ts +380 -0
- package/src/server/routes/dynamics.ts +516 -0
- package/src/server/routes/ide.ts +283 -0
- package/src/server/routes/index.ts +32 -0
- package/src/server/routes/keys.ts +131 -0
- package/src/server/routes/langgraph.ts +71 -0
- package/src/server/routes/memory.ts +440 -0
- package/src/server/routes/sources.ts +111 -0
- package/src/server/routes/system.ts +68 -0
- package/src/server/routes/temporal.ts +335 -0
- package/src/server/routes/users.ts +111 -0
- package/src/server/routes/vercel.ts +55 -0
- package/src/server/server.js +215 -0
- package/src/server.ts +1 -0
- package/src/sources/base.ts +257 -0
- package/src/sources/github.ts +156 -0
- package/src/sources/google_drive.ts +144 -0
- package/src/sources/google_sheets.ts +85 -0
- package/src/sources/google_slides.ts +115 -0
- package/src/sources/index.ts +19 -0
- package/src/sources/notion.ts +148 -0
- package/src/sources/onedrive.ts +131 -0
- package/src/sources/web_crawler.ts +161 -0
- package/src/temporal_graph/index.ts +4 -0
- package/src/temporal_graph/query.ts +299 -0
- package/src/temporal_graph/store.ts +156 -0
- package/src/temporal_graph/timeline.ts +319 -0
- package/src/temporal_graph/types.ts +41 -0
- package/src/utils/chunking.ts +66 -0
- package/src/utils/index.ts +25 -0
- package/src/utils/keyword.ts +137 -0
- package/src/utils/text.ts +115 -0
- package/tests/test_api_workspace_management.ts +413 -0
- package/tests/test_bulk_delete.ts +267 -0
- package/tests/test_omnibus.ts +166 -0
- package/tests/test_workspace_management.ts +278 -0
- package/tests/verify.ts +104 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,116 @@
|
|
|
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
|
+
exports.Memory = void 0;
|
|
37
|
+
const hsg_1 = require("../memory/hsg");
|
|
38
|
+
const db_1 = require("./db");
|
|
39
|
+
class Memory {
|
|
40
|
+
default_user;
|
|
41
|
+
constructor(user_id) {
|
|
42
|
+
this.default_user = user_id || null;
|
|
43
|
+
}
|
|
44
|
+
async add(content, opts) {
|
|
45
|
+
const uid = opts?.user_id || this.default_user;
|
|
46
|
+
const tags = opts?.tags || [];
|
|
47
|
+
const meta = { ...opts };
|
|
48
|
+
delete meta.user_id;
|
|
49
|
+
delete meta.tags;
|
|
50
|
+
// Ensure tags is JSON string if needed by add_hsg_memory
|
|
51
|
+
// hsg.ts signature: add_hsg_memory(content, tags, meta, user_id)
|
|
52
|
+
// tags is usually stringified JSON or string?
|
|
53
|
+
// Checked hsg.ts: interface hsg_mem { tags?: string }
|
|
54
|
+
// Let's pass JSON string for tags.
|
|
55
|
+
const tags_str = JSON.stringify(tags);
|
|
56
|
+
// hsg.ts add_hsg_memory returns { id, ... } or similar?
|
|
57
|
+
// Let's check hsg.ts exports. It's likely async and returns object.
|
|
58
|
+
const res = await (0, hsg_1.add_hsg_memory)(content, tags_str, meta, uid ?? undefined);
|
|
59
|
+
return res;
|
|
60
|
+
}
|
|
61
|
+
async get(id) {
|
|
62
|
+
return await db_1.q.get_mem.get(id);
|
|
63
|
+
}
|
|
64
|
+
async search(query, opts) {
|
|
65
|
+
// hsg_query(qt, k, f)
|
|
66
|
+
const k = opts?.limit || 10;
|
|
67
|
+
const uid = opts?.user_id || this.default_user;
|
|
68
|
+
const f = {};
|
|
69
|
+
if (uid)
|
|
70
|
+
f.user_id = uid;
|
|
71
|
+
if (opts?.sectors)
|
|
72
|
+
f.sectors = opts.sectors;
|
|
73
|
+
return await (0, hsg_1.hsg_query)(query, k, f);
|
|
74
|
+
}
|
|
75
|
+
async delete_all(user_id) {
|
|
76
|
+
const uid = user_id || this.default_user;
|
|
77
|
+
if (uid) {
|
|
78
|
+
// q.del_mem usually exists or we execute raw SQL
|
|
79
|
+
// But we can't easily access q here if not exported or if we want to change memory.ts minimal
|
|
80
|
+
// I'll add a wipe() method that calls q directly if q is imported
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async wipe() {
|
|
84
|
+
console.log("[Memory] Wiping DB...");
|
|
85
|
+
// q is imported from db.ts
|
|
86
|
+
await db_1.q.clear_all.run();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* get a pre-configured source connector.
|
|
90
|
+
*
|
|
91
|
+
* usage:
|
|
92
|
+
* const github = mem.source("github")
|
|
93
|
+
* await github.connect({ token: "ghp_..." })
|
|
94
|
+
* await github.ingest_all({ repo: "owner/repo" })
|
|
95
|
+
*
|
|
96
|
+
* available sources: github, notion, google_drive, google_sheets,
|
|
97
|
+
* google_slides, onedrive, web_crawler
|
|
98
|
+
*/
|
|
99
|
+
source(name) {
|
|
100
|
+
// dynamic import to avoid circular deps
|
|
101
|
+
const sources = {
|
|
102
|
+
github: () => Promise.resolve().then(() => __importStar(require("../sources/github"))).then(m => new m.github_source(this.default_user ?? undefined)),
|
|
103
|
+
notion: () => Promise.resolve().then(() => __importStar(require("../sources/notion"))).then(m => new m.notion_source(this.default_user ?? undefined)),
|
|
104
|
+
google_drive: () => Promise.resolve().then(() => __importStar(require("../sources/google_drive"))).then(m => new m.google_drive_source(this.default_user ?? undefined)),
|
|
105
|
+
google_sheets: () => Promise.resolve().then(() => __importStar(require("../sources/google_sheets"))).then(m => new m.google_sheets_source(this.default_user ?? undefined)),
|
|
106
|
+
google_slides: () => Promise.resolve().then(() => __importStar(require("../sources/google_slides"))).then(m => new m.google_slides_source(this.default_user ?? undefined)),
|
|
107
|
+
onedrive: () => Promise.resolve().then(() => __importStar(require("../sources/onedrive"))).then(m => new m.onedrive_source(this.default_user ?? undefined)),
|
|
108
|
+
web_crawler: () => Promise.resolve().then(() => __importStar(require("../sources/web_crawler"))).then(m => new m.web_crawler_source(this.default_user ?? undefined)),
|
|
109
|
+
};
|
|
110
|
+
if (!(name in sources)) {
|
|
111
|
+
throw new Error(`unknown source: ${name}. available: ${Object.keys(sources).join(", ")}`);
|
|
112
|
+
}
|
|
113
|
+
return sources[name]();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.Memory = Memory;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.run_migrations = run_migrations;
|
|
7
|
+
const cfg_1 = require("./cfg");
|
|
8
|
+
const sqlite3_1 = __importDefault(require("sqlite3"));
|
|
9
|
+
const pg_1 = require("pg");
|
|
10
|
+
const is_pg = cfg_1.env.metadata_backend === "postgres";
|
|
11
|
+
const log = (msg) => console.log(`[MIGRATE] ${msg}`);
|
|
12
|
+
const migrations = [
|
|
13
|
+
{
|
|
14
|
+
version: "1.2.0",
|
|
15
|
+
desc: "Multi-user tenant support",
|
|
16
|
+
sqlite: [
|
|
17
|
+
`ALTER TABLE memories ADD COLUMN user_id TEXT`,
|
|
18
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_user ON memories(user_id)`,
|
|
19
|
+
`ALTER TABLE vectors ADD COLUMN user_id TEXT`,
|
|
20
|
+
`CREATE INDEX IF NOT EXISTS idx_vectors_user ON vectors(user_id)`,
|
|
21
|
+
`CREATE TABLE IF NOT EXISTS waypoints_new (
|
|
22
|
+
src_id TEXT, dst_id TEXT NOT NULL, user_id TEXT,
|
|
23
|
+
weight REAL NOT NULL, created_at INTEGER, updated_at INTEGER,
|
|
24
|
+
PRIMARY KEY(src_id, user_id)
|
|
25
|
+
)`,
|
|
26
|
+
`INSERT INTO waypoints_new SELECT src_id, dst_id, NULL, weight, created_at, updated_at FROM waypoints`,
|
|
27
|
+
`DROP TABLE waypoints`,
|
|
28
|
+
`ALTER TABLE waypoints_new RENAME TO waypoints`,
|
|
29
|
+
`CREATE INDEX IF NOT EXISTS idx_waypoints_src ON waypoints(src_id)`,
|
|
30
|
+
`CREATE INDEX IF NOT EXISTS idx_waypoints_dst ON waypoints(dst_id)`,
|
|
31
|
+
`CREATE INDEX IF NOT EXISTS idx_waypoints_user ON waypoints(user_id)`,
|
|
32
|
+
`CREATE TABLE IF NOT EXISTS users (
|
|
33
|
+
user_id TEXT PRIMARY KEY, summary TEXT,
|
|
34
|
+
reflection_count INTEGER DEFAULT 0,
|
|
35
|
+
created_at INTEGER, updated_at INTEGER
|
|
36
|
+
)`,
|
|
37
|
+
`CREATE TABLE IF NOT EXISTS stats (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
type TEXT NOT NULL, count INTEGER DEFAULT 1, ts INTEGER NOT NULL
|
|
40
|
+
)`,
|
|
41
|
+
`CREATE INDEX IF NOT EXISTS idx_stats_ts ON stats(ts)`,
|
|
42
|
+
`CREATE INDEX IF NOT EXISTS idx_stats_type ON stats(type)`,
|
|
43
|
+
],
|
|
44
|
+
postgres: [
|
|
45
|
+
`ALTER TABLE {m} ADD COLUMN IF NOT EXISTS user_id TEXT`,
|
|
46
|
+
`CREATE INDEX IF NOT EXISTS openmemory_memories_user_idx ON {m}(user_id)`,
|
|
47
|
+
`ALTER TABLE {v} ADD COLUMN IF NOT EXISTS user_id TEXT`,
|
|
48
|
+
`CREATE INDEX IF NOT EXISTS openmemory_vectors_user_idx ON {v}(user_id)`,
|
|
49
|
+
`ALTER TABLE {w} ADD COLUMN IF NOT EXISTS user_id TEXT`,
|
|
50
|
+
`ALTER TABLE {w} DROP CONSTRAINT IF EXISTS waypoints_pkey`,
|
|
51
|
+
`ALTER TABLE {w} ADD PRIMARY KEY (src_id, user_id)`,
|
|
52
|
+
`CREATE INDEX IF NOT EXISTS openmemory_waypoints_user_idx ON {w}(user_id)`,
|
|
53
|
+
`CREATE TABLE IF NOT EXISTS {u} (
|
|
54
|
+
user_id TEXT PRIMARY KEY, summary TEXT,
|
|
55
|
+
reflection_count INTEGER DEFAULT 0,
|
|
56
|
+
created_at BIGINT, updated_at BIGINT
|
|
57
|
+
)`,
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
async function get_db_version_sqlite(db) {
|
|
62
|
+
return new Promise((ok, no) => {
|
|
63
|
+
db.get(`SELECT name FROM sqlite_master WHERE type='table' AND name='schema_version'`, (err, row) => {
|
|
64
|
+
if (err)
|
|
65
|
+
return no(err);
|
|
66
|
+
if (!row)
|
|
67
|
+
return ok(null);
|
|
68
|
+
db.get(`SELECT version FROM schema_version ORDER BY applied_at DESC LIMIT 1`, (e, v) => {
|
|
69
|
+
if (e)
|
|
70
|
+
return no(e);
|
|
71
|
+
ok(v?.version || null);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async function set_db_version_sqlite(db, version) {
|
|
77
|
+
return new Promise((ok, no) => {
|
|
78
|
+
db.run(`CREATE TABLE IF NOT EXISTS schema_version (
|
|
79
|
+
version TEXT PRIMARY KEY, applied_at INTEGER
|
|
80
|
+
)`, (err) => {
|
|
81
|
+
if (err)
|
|
82
|
+
return no(err);
|
|
83
|
+
db.run(`INSERT OR REPLACE INTO schema_version VALUES (?, ?)`, [version, Date.now()], (e) => {
|
|
84
|
+
if (e)
|
|
85
|
+
return no(e);
|
|
86
|
+
ok();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
async function check_column_exists_sqlite(db, table, column) {
|
|
92
|
+
return new Promise((ok, no) => {
|
|
93
|
+
db.all(`PRAGMA table_info(${table})`, (err, rows) => {
|
|
94
|
+
if (err)
|
|
95
|
+
return no(err);
|
|
96
|
+
ok(rows.some((r) => r.name === column));
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async function run_sqlite_migration(db, m) {
|
|
101
|
+
log(`Running migration: ${m.version} - ${m.desc}`);
|
|
102
|
+
const has_user_id = await check_column_exists_sqlite(db, "memories", "user_id");
|
|
103
|
+
if (has_user_id) {
|
|
104
|
+
log(`Migration ${m.version} already applied (user_id exists), skipping`);
|
|
105
|
+
await set_db_version_sqlite(db, m.version);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
for (const sql of m.sqlite) {
|
|
109
|
+
await new Promise((ok, no) => {
|
|
110
|
+
db.run(sql, (err) => {
|
|
111
|
+
if (err && !err.message.includes("duplicate column")) {
|
|
112
|
+
log(`ERROR: ${err.message}`);
|
|
113
|
+
return no(err);
|
|
114
|
+
}
|
|
115
|
+
ok();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
await set_db_version_sqlite(db, m.version);
|
|
120
|
+
log(`Migration ${m.version} completed successfully`);
|
|
121
|
+
}
|
|
122
|
+
async function get_db_version_pg(pool) {
|
|
123
|
+
try {
|
|
124
|
+
const sc = process.env.OM_PG_SCHEMA || "public";
|
|
125
|
+
const check = await pool.query(`SELECT EXISTS (
|
|
126
|
+
SELECT FROM information_schema.tables
|
|
127
|
+
WHERE table_schema = $1 AND table_name = 'schema_version'
|
|
128
|
+
)`, [sc]);
|
|
129
|
+
if (!check.rows[0].exists)
|
|
130
|
+
return null;
|
|
131
|
+
const ver = await pool.query(`SELECT version FROM "${sc}"."schema_version" ORDER BY applied_at DESC LIMIT 1`);
|
|
132
|
+
return ver.rows[0]?.version || null;
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function set_db_version_pg(pool, version) {
|
|
139
|
+
const sc = process.env.OM_PG_SCHEMA || "public";
|
|
140
|
+
await pool.query(`CREATE TABLE IF NOT EXISTS "${sc}"."schema_version" (
|
|
141
|
+
version TEXT PRIMARY KEY, applied_at BIGINT
|
|
142
|
+
)`);
|
|
143
|
+
await pool.query(`INSERT INTO "${sc}"."schema_version" VALUES ($1, $2)
|
|
144
|
+
ON CONFLICT (version) DO UPDATE SET applied_at = EXCLUDED.applied_at`, [version, Date.now()]);
|
|
145
|
+
}
|
|
146
|
+
async function check_column_exists_pg(pool, table, column) {
|
|
147
|
+
const sc = process.env.OM_PG_SCHEMA || "public";
|
|
148
|
+
const tbl = table.replace(/"/g, "").split(".").pop() || table;
|
|
149
|
+
const res = await pool.query(`SELECT EXISTS (
|
|
150
|
+
SELECT FROM information_schema.columns
|
|
151
|
+
WHERE table_schema = $1 AND table_name = $2 AND column_name = $3
|
|
152
|
+
)`, [sc, tbl, column]);
|
|
153
|
+
return res.rows[0].exists;
|
|
154
|
+
}
|
|
155
|
+
async function run_pg_migration(pool, m) {
|
|
156
|
+
log(`Running migration: ${m.version} - ${m.desc}`);
|
|
157
|
+
const sc = process.env.OM_PG_SCHEMA || "public";
|
|
158
|
+
const mt = process.env.OM_PG_TABLE || "openmemory_memories";
|
|
159
|
+
const has_user_id = await check_column_exists_pg(pool, mt, "user_id");
|
|
160
|
+
if (has_user_id) {
|
|
161
|
+
log(`Migration ${m.version} already applied (user_id exists), skipping`);
|
|
162
|
+
await set_db_version_pg(pool, m.version);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const replacements = {
|
|
166
|
+
"{m}": `"${sc}"."${mt}"`,
|
|
167
|
+
"{v}": `"${sc}"."${process.env.OM_VECTOR_TABLE || "openmemory_vectors"}"`,
|
|
168
|
+
"{w}": `"${sc}"."openmemory_waypoints"`,
|
|
169
|
+
"{u}": `"${sc}"."openmemory_users"`,
|
|
170
|
+
};
|
|
171
|
+
for (let sql of m.postgres) {
|
|
172
|
+
for (const [k, v] of Object.entries(replacements)) {
|
|
173
|
+
sql = sql.replace(new RegExp(k, "g"), v);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
await pool.query(sql);
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
if (!e.message.includes("already exists") &&
|
|
180
|
+
!e.message.includes("duplicate")) {
|
|
181
|
+
log(`ERROR: ${e.message}`);
|
|
182
|
+
throw e;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
await set_db_version_pg(pool, m.version);
|
|
187
|
+
log(`Migration ${m.version} completed successfully`);
|
|
188
|
+
}
|
|
189
|
+
async function run_migrations() {
|
|
190
|
+
log("Checking for pending migrations...");
|
|
191
|
+
if (is_pg) {
|
|
192
|
+
const ssl = process.env.OM_PG_SSL === "require"
|
|
193
|
+
? { rejectUnauthorized: false }
|
|
194
|
+
: process.env.OM_PG_SSL === "disable"
|
|
195
|
+
? false
|
|
196
|
+
: undefined;
|
|
197
|
+
const pool = new pg_1.Pool({
|
|
198
|
+
host: process.env.OM_PG_HOST,
|
|
199
|
+
port: process.env.OM_PG_PORT ? +process.env.OM_PG_PORT : undefined,
|
|
200
|
+
database: process.env.OM_PG_DB || "openmemory",
|
|
201
|
+
user: process.env.OM_PG_USER,
|
|
202
|
+
password: process.env.OM_PG_PASSWORD,
|
|
203
|
+
ssl,
|
|
204
|
+
});
|
|
205
|
+
const current = await get_db_version_pg(pool);
|
|
206
|
+
log(`Current database version: ${current || "none"}`);
|
|
207
|
+
for (const m of migrations) {
|
|
208
|
+
if (!current || m.version > current) {
|
|
209
|
+
await run_pg_migration(pool, m);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
await pool.end();
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
const db_path = process.env.OM_DB_PATH || "./data/openmemory.sqlite";
|
|
216
|
+
const db = new sqlite3_1.default.Database(db_path);
|
|
217
|
+
const current = await get_db_version_sqlite(db);
|
|
218
|
+
log(`Current database version: ${current || "none"}`);
|
|
219
|
+
for (const m of migrations) {
|
|
220
|
+
if (!current || m.version > current) {
|
|
221
|
+
await run_sqlite_migration(db, m);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
await new Promise((ok) => db.close(() => ok()));
|
|
225
|
+
}
|
|
226
|
+
log("All migrations completed");
|
|
227
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.get_provider_config = exports.get_model = exports.load_models = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
let cfg = null;
|
|
7
|
+
const load_models = () => {
|
|
8
|
+
if (cfg)
|
|
9
|
+
return cfg;
|
|
10
|
+
const p = (0, path_1.join)(__dirname, "../../../models.yml");
|
|
11
|
+
if (!(0, fs_1.existsSync)(p)) {
|
|
12
|
+
console.error("[MODELS] models.yml not found, using defaults");
|
|
13
|
+
return get_defaults();
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const yml = (0, fs_1.readFileSync)(p, "utf-8");
|
|
17
|
+
cfg = parse_yaml(yml);
|
|
18
|
+
console.error(`[MODELS] Loaded models.yml (${Object.keys(cfg).length} sectors)`);
|
|
19
|
+
return cfg;
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.error("[MODELS] Failed to parse models.yml:", e);
|
|
23
|
+
return get_defaults();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.load_models = load_models;
|
|
27
|
+
const parse_yaml = (yml) => {
|
|
28
|
+
const lines = yml.split("\n");
|
|
29
|
+
const obj = {};
|
|
30
|
+
let cur_sec = null;
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
const trim = line.trim();
|
|
33
|
+
if (!trim || trim.startsWith("#"))
|
|
34
|
+
continue;
|
|
35
|
+
const indent = line.search(/\S/);
|
|
36
|
+
const [key, ...val_parts] = trim.split(":");
|
|
37
|
+
const val = val_parts.join(":").trim();
|
|
38
|
+
if (indent === 0 && val) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
else if (indent === 0) {
|
|
42
|
+
cur_sec = key;
|
|
43
|
+
obj[cur_sec] = {};
|
|
44
|
+
}
|
|
45
|
+
else if (cur_sec && val) {
|
|
46
|
+
obj[cur_sec][key] = val;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return obj;
|
|
50
|
+
};
|
|
51
|
+
const get_defaults = () => ({
|
|
52
|
+
episodic: {
|
|
53
|
+
ollama: "nomic-embed-text",
|
|
54
|
+
openai: "text-embedding-3-small",
|
|
55
|
+
gemini: "models/embedding-001",
|
|
56
|
+
aws: "amazon.titan-embed-text-v2:0",
|
|
57
|
+
local: "all-MiniLM-L6-v2",
|
|
58
|
+
},
|
|
59
|
+
semantic: {
|
|
60
|
+
ollama: "nomic-embed-text",
|
|
61
|
+
openai: "text-embedding-3-small",
|
|
62
|
+
gemini: "models/embedding-001",
|
|
63
|
+
aws: "amazon.titan-embed-text-v2:0",
|
|
64
|
+
local: "all-MiniLM-L6-v2",
|
|
65
|
+
},
|
|
66
|
+
procedural: {
|
|
67
|
+
ollama: "nomic-embed-text",
|
|
68
|
+
openai: "text-embedding-3-small",
|
|
69
|
+
gemini: "models/embedding-001",
|
|
70
|
+
aws: "amazon.titan-embed-text-v2:0",
|
|
71
|
+
local: "all-MiniLM-L6-v2",
|
|
72
|
+
},
|
|
73
|
+
emotional: {
|
|
74
|
+
ollama: "nomic-embed-text",
|
|
75
|
+
openai: "text-embedding-3-small",
|
|
76
|
+
gemini: "models/embedding-001",
|
|
77
|
+
aws: "amazon.titan-embed-text-v2:0",
|
|
78
|
+
local: "all-MiniLM-L6-v2",
|
|
79
|
+
},
|
|
80
|
+
reflective: {
|
|
81
|
+
ollama: "nomic-embed-text",
|
|
82
|
+
openai: "text-embedding-3-large",
|
|
83
|
+
gemini: "models/embedding-001",
|
|
84
|
+
aws: "amazon.titan-embed-text-v2:0",
|
|
85
|
+
local: "all-mpnet-base-v2",
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
const get_model = (sector, provider) => {
|
|
89
|
+
// Environment variable overrides
|
|
90
|
+
if (provider === "ollama" && process.env.OM_OLLAMA_MODEL) {
|
|
91
|
+
return process.env.OM_OLLAMA_MODEL;
|
|
92
|
+
}
|
|
93
|
+
if (provider === "openai" && process.env.OM_OPENAI_MODEL) {
|
|
94
|
+
return process.env.OM_OPENAI_MODEL;
|
|
95
|
+
}
|
|
96
|
+
const cfg = (0, exports.load_models)();
|
|
97
|
+
return (cfg[sector]?.[provider] ||
|
|
98
|
+
cfg.semantic?.[provider] ||
|
|
99
|
+
"nomic-embed-text");
|
|
100
|
+
};
|
|
101
|
+
exports.get_model = get_model;
|
|
102
|
+
const get_provider_config = (provider) => {
|
|
103
|
+
return {};
|
|
104
|
+
};
|
|
105
|
+
exports.get_provider_config = get_provider_config;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.sendTelemetry = void 0;
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const cfg_1 = require("./cfg");
|
|
9
|
+
const DISABLED = (process.env.OM_TELEMETRY ?? '').toLowerCase() === 'false';
|
|
10
|
+
const gatherVersion = () => {
|
|
11
|
+
if (process.env.npm_package_version)
|
|
12
|
+
return process.env.npm_package_version;
|
|
13
|
+
try {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
15
|
+
const pkg = require('../../package.json');
|
|
16
|
+
if (pkg?.version)
|
|
17
|
+
return pkg.version;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// ignore
|
|
21
|
+
}
|
|
22
|
+
return 'unknown';
|
|
23
|
+
};
|
|
24
|
+
const sendTelemetry = async () => {
|
|
25
|
+
if (DISABLED)
|
|
26
|
+
return;
|
|
27
|
+
try {
|
|
28
|
+
const ramMb = Math.round(node_os_1.default.totalmem() / (1024 * 1024));
|
|
29
|
+
const storageMb = ramMb * 4;
|
|
30
|
+
const payload = {
|
|
31
|
+
name: node_os_1.default.hostname(),
|
|
32
|
+
os: node_os_1.default.platform(),
|
|
33
|
+
embeddings: cfg_1.env.emb_kind || 'synthetic',
|
|
34
|
+
metadata: cfg_1.env.metadata_backend || 'sqlite',
|
|
35
|
+
version: gatherVersion(),
|
|
36
|
+
ram: ramMb,
|
|
37
|
+
storage: storageMb,
|
|
38
|
+
cpu: node_os_1.default.cpus()?.[0]?.model || 'unknown',
|
|
39
|
+
};
|
|
40
|
+
const res = await fetch('https://telemetry.spotit.dev', {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: { 'content-type': 'application/json' },
|
|
43
|
+
body: JSON.stringify(payload),
|
|
44
|
+
keepalive: true,
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
console.warn(``);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.log(`[telemetry] sent`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// silently ignore telemetry errors
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.sendTelemetry = sendTelemetry;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresVectorStore = void 0;
|
|
4
|
+
const embed_1 = require("../../memory/embed");
|
|
5
|
+
class PostgresVectorStore {
|
|
6
|
+
db;
|
|
7
|
+
table;
|
|
8
|
+
constructor(db, tableName = "vectors") {
|
|
9
|
+
this.db = db;
|
|
10
|
+
this.table = tableName;
|
|
11
|
+
}
|
|
12
|
+
async storeVector(id, sector, vector, dim, user_id) {
|
|
13
|
+
console.error(`[Vector] Storing ID: ${id}, Sector: ${sector}, Dim: ${dim}`);
|
|
14
|
+
const v = (0, embed_1.vectorToBuffer)(vector);
|
|
15
|
+
const sql = `insert into ${this.table}(id,sector,user_id,v,dim) values($1,$2,$3,$4,$5) on conflict(id,sector) do update set user_id=excluded.user_id,v=excluded.v,dim=excluded.dim`;
|
|
16
|
+
await this.db.run_async(sql, [id, sector, user_id || "anonymous", v, dim]);
|
|
17
|
+
}
|
|
18
|
+
async deleteVector(id, sector) {
|
|
19
|
+
await this.db.run_async(`delete from ${this.table} where id=$1 and sector=$2`, [id, sector]);
|
|
20
|
+
}
|
|
21
|
+
async deleteVectors(id) {
|
|
22
|
+
await this.db.run_async(`delete from ${this.table} where id=$1`, [id]);
|
|
23
|
+
}
|
|
24
|
+
async searchSimilar(sector, queryVec, topK) {
|
|
25
|
+
// Postgres implementation (in-memory cosine sim for now, as per original)
|
|
26
|
+
const rows = await this.db.all_async(`select id,v,dim from ${this.table} where sector=$1`, [sector]);
|
|
27
|
+
console.error(`[Vector] Search Sector: ${sector}, Found ${rows.length} rows.`);
|
|
28
|
+
const sims = [];
|
|
29
|
+
for (const row of rows) {
|
|
30
|
+
const vec = (0, embed_1.bufferToVector)(row.v);
|
|
31
|
+
const sim = (0, embed_1.cosineSimilarity)(queryVec, vec);
|
|
32
|
+
sims.push({ id: row.id, score: sim });
|
|
33
|
+
}
|
|
34
|
+
sims.sort((a, b) => b.score - a.score);
|
|
35
|
+
return sims.slice(0, topK);
|
|
36
|
+
}
|
|
37
|
+
async getVector(id, sector) {
|
|
38
|
+
const row = await this.db.get_async(`select v,dim from ${this.table} where id=$1 and sector=$2`, [id, sector]);
|
|
39
|
+
if (!row)
|
|
40
|
+
return null;
|
|
41
|
+
return { vector: (0, embed_1.bufferToVector)(row.v), dim: row.dim };
|
|
42
|
+
}
|
|
43
|
+
async getVectorsById(id) {
|
|
44
|
+
const rows = await this.db.all_async(`select sector,v,dim from ${this.table} where id=$1`, [id]);
|
|
45
|
+
return rows.map(row => ({ sector: row.sector, vector: (0, embed_1.bufferToVector)(row.v), dim: row.dim }));
|
|
46
|
+
}
|
|
47
|
+
async getVectorsBySector(sector) {
|
|
48
|
+
const rows = await this.db.all_async(`select id,v,dim from ${this.table} where sector=$1`, [sector]);
|
|
49
|
+
return rows.map(row => ({ id: row.id, vector: (0, embed_1.bufferToVector)(row.v), dim: row.dim }));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.PostgresVectorStore = PostgresVectorStore;
|