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,132 @@
|
|
|
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.keys = keys;
|
|
7
|
+
const db_1 = require("../../core/db");
|
|
8
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
+
const backend_1 = require("@clerk/backend");
|
|
10
|
+
async function verifyClerkToken(req) {
|
|
11
|
+
const token = req.headers.authorization?.replace("Bearer ", "");
|
|
12
|
+
if (!token)
|
|
13
|
+
return null;
|
|
14
|
+
try {
|
|
15
|
+
const session = await (0, backend_1.verifyToken)(token, { secretKey: process.env.CLERK_SECRET_KEY });
|
|
16
|
+
const user = await db_1.q.get_user_by_clerk_id.get(session.sub);
|
|
17
|
+
return user;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function keys(app) {
|
|
24
|
+
app.get("/keys", async (req, res) => {
|
|
25
|
+
// Try API key auth first, then Clerk JWT
|
|
26
|
+
let user = req.user;
|
|
27
|
+
if (!user?.user_id) {
|
|
28
|
+
user = await verifyClerkToken(req);
|
|
29
|
+
}
|
|
30
|
+
if (!user?.user_id)
|
|
31
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
32
|
+
try {
|
|
33
|
+
const keys = await db_1.q.get_memory_keys_by_user.all(user.user_id);
|
|
34
|
+
res.json({ keys });
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
res.status(500).json({ error: e.message });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
app.post("/keys", async (req, res) => {
|
|
41
|
+
let user = req.user;
|
|
42
|
+
if (!user?.user_id) {
|
|
43
|
+
user = await verifyClerkToken(req);
|
|
44
|
+
}
|
|
45
|
+
if (!user?.user_id)
|
|
46
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
47
|
+
const { label } = req.body;
|
|
48
|
+
if (!label)
|
|
49
|
+
return res.status(400).json({ error: "Label is required" });
|
|
50
|
+
try {
|
|
51
|
+
const id = crypto_1.default.randomUUID();
|
|
52
|
+
const secret_key = `opm_sk_${crypto_1.default.randomBytes(24).toString("hex")}`;
|
|
53
|
+
await db_1.q.ins_memory_key.run(id, user.user_id, label, secret_key, Date.now());
|
|
54
|
+
res.json({ id, label, secret_key });
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
res.status(500).json({ error: e.message });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
app.patch("/keys/:id", async (req, res) => {
|
|
61
|
+
let user = req.user;
|
|
62
|
+
if (!user?.user_id) {
|
|
63
|
+
user = await verifyClerkToken(req);
|
|
64
|
+
}
|
|
65
|
+
if (!user?.user_id)
|
|
66
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
67
|
+
const { id } = req.params;
|
|
68
|
+
const { label } = req.body;
|
|
69
|
+
// Validate label is non-empty (reject empty or whitespace-only labels)
|
|
70
|
+
if (!label || typeof label !== 'string' || label.trim().length === 0) {
|
|
71
|
+
return res.status(400).json({ error: "Label is required" });
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const updated_at = Date.now();
|
|
75
|
+
await db_1.q.upd_memory_key_label.run(label, updated_at, id, user.user_id);
|
|
76
|
+
res.json({ id, label, updated_at });
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
res.status(500).json({ error: e.message });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
app.delete("/keys/:id", async (req, res) => {
|
|
83
|
+
let user = req.user;
|
|
84
|
+
if (!user?.user_id) {
|
|
85
|
+
user = await verifyClerkToken(req);
|
|
86
|
+
}
|
|
87
|
+
if (!user?.user_id)
|
|
88
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
89
|
+
const { id } = req.params;
|
|
90
|
+
try {
|
|
91
|
+
await db_1.q.del_memory_key.run(id, user.user_id);
|
|
92
|
+
res.json({ ok: true });
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
res.status(500).json({ error: e.message });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
// GET /keys/stats - Get workspace statistics with memory counts
|
|
99
|
+
app.get("/keys/stats", async (req, res) => {
|
|
100
|
+
let user = req.user;
|
|
101
|
+
if (!user?.user_id) {
|
|
102
|
+
user = await verifyClerkToken(req);
|
|
103
|
+
}
|
|
104
|
+
if (!user?.user_id)
|
|
105
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
106
|
+
try {
|
|
107
|
+
// Get all workspaces for the user (already sorted by created_at desc)
|
|
108
|
+
const workspaces = await db_1.q.get_memory_keys_by_user.all(user.user_id);
|
|
109
|
+
// Get memory counts grouped by memory_key_id
|
|
110
|
+
const memoryCounts = await db_1.q.get_memory_counts_by_key.all(user.user_id);
|
|
111
|
+
// Create a map of memory_key_id -> count for efficient lookup
|
|
112
|
+
const countMap = new Map();
|
|
113
|
+
for (const item of memoryCounts) {
|
|
114
|
+
if (item.memory_key_id) {
|
|
115
|
+
countMap.set(item.memory_key_id, item.count);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Merge workspaces with memory counts (default to 0 if no memories)
|
|
119
|
+
const workspacesWithStats = workspaces.map((workspace) => ({
|
|
120
|
+
id: workspace.id,
|
|
121
|
+
label: workspace.label,
|
|
122
|
+
secret_key: workspace.secret_key,
|
|
123
|
+
created_at: workspace.created_at,
|
|
124
|
+
memory_count: countMap.get(workspace.id) || 0
|
|
125
|
+
}));
|
|
126
|
+
res.json({ workspaces: workspacesWithStats });
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
res.status(500).json({ error: e.message });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.lg = lg;
|
|
4
|
+
const graph_1 = require("../../ai/graph");
|
|
5
|
+
function lg(app) {
|
|
6
|
+
app.get("/lgm/config", (_req, res) => {
|
|
7
|
+
res.json((0, graph_1.get_lg_cfg)());
|
|
8
|
+
});
|
|
9
|
+
app.post("/lgm/store", async (req, res) => {
|
|
10
|
+
try {
|
|
11
|
+
const r = await (0, graph_1.store_node_mem)(req.body);
|
|
12
|
+
res.json(r);
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.error("[LGM] store error:", e);
|
|
16
|
+
res.status(400).json({
|
|
17
|
+
err: "lgm_store_failed",
|
|
18
|
+
message: e.message,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
app.post("/lgm/retrieve", async (req, res) => {
|
|
23
|
+
try {
|
|
24
|
+
const r = await (0, graph_1.retrieve_node_mems)(req.body);
|
|
25
|
+
res.json(r);
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
console.error("[LGM] retrieve error:", e);
|
|
29
|
+
res.status(400).json({
|
|
30
|
+
err: "lgm_retrieve_failed",
|
|
31
|
+
message: e.message,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
app.post("/lgm/context", async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const r = await (0, graph_1.get_graph_ctx)(req.body);
|
|
38
|
+
res.json(r);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
console.error("[LGM] context error:", e);
|
|
42
|
+
res.status(400).json({
|
|
43
|
+
err: "lgm_context_failed",
|
|
44
|
+
message: e.message,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
app.post("/lgm/reflection", async (req, res) => {
|
|
49
|
+
try {
|
|
50
|
+
const r = await (0, graph_1.create_refl)(req.body);
|
|
51
|
+
res.json(r);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
console.error("[LGM] reflection error:", e);
|
|
55
|
+
res.status(400).json({
|
|
56
|
+
err: "lgm_reflection_failed",
|
|
57
|
+
message: e.message,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mem = mem;
|
|
4
|
+
const db_1 = require("../../core/db");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
|
+
const hsg_1 = require("../../memory/hsg");
|
|
7
|
+
const ingest_1 = require("../../ops/ingest");
|
|
8
|
+
const user_summary_1 = require("../../memory/user_summary");
|
|
9
|
+
function mem(app) {
|
|
10
|
+
app.post("/memory/add", async (req, res) => {
|
|
11
|
+
const b = req.body;
|
|
12
|
+
if (!b?.content)
|
|
13
|
+
return res.status(400).json({ err: "content" });
|
|
14
|
+
try {
|
|
15
|
+
const m = await (0, hsg_1.add_hsg_memory)(b.content, (0, utils_1.j)(b.tags || []), b.metadata, b.user_id, req.key_id);
|
|
16
|
+
res.json(m);
|
|
17
|
+
if (b.user_id) {
|
|
18
|
+
(0, user_summary_1.update_user_summary)(b.user_id).catch((e) => console.error("[mem] user summary update failed:", e));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
res.status(500).json({ err: e.message });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
app.post("/memory/ingest", async (req, res) => {
|
|
26
|
+
const b = req.body;
|
|
27
|
+
if (!b?.content_type || !b?.data)
|
|
28
|
+
return res.status(400).json({ err: "missing" });
|
|
29
|
+
try {
|
|
30
|
+
const r = await (0, ingest_1.ingestDocument)(b.content_type, b.data, b.metadata, b.config, b.user_id);
|
|
31
|
+
res.json(r);
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
res.status(500).json({ err: "ingest_fail", msg: e.message });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
app.post("/memory/ingest/url", async (req, res) => {
|
|
38
|
+
const b = req.body;
|
|
39
|
+
if (!b?.url)
|
|
40
|
+
return res.status(400).json({ err: "no_url" });
|
|
41
|
+
try {
|
|
42
|
+
const r = await (0, ingest_1.ingestURL)(b.url, b.metadata, b.config, b.user_id);
|
|
43
|
+
res.json(r);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
res.status(500).json({ err: "url_fail", msg: e.message });
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
app.post("/memory/query", async (req, res) => {
|
|
50
|
+
const b = req.body;
|
|
51
|
+
const k = b.k || 8;
|
|
52
|
+
try {
|
|
53
|
+
const f = {
|
|
54
|
+
sectors: b.filters?.sector ? [b.filters.sector] : undefined,
|
|
55
|
+
minSalience: b.filters?.min_score,
|
|
56
|
+
user_id: b.filters?.user_id || b.user_id,
|
|
57
|
+
startTime: b.filters?.startTime,
|
|
58
|
+
endTime: b.filters?.endTime,
|
|
59
|
+
};
|
|
60
|
+
const m = await (0, hsg_1.hsg_query)(b.query, k, f);
|
|
61
|
+
res.json({
|
|
62
|
+
query: b.query,
|
|
63
|
+
matches: m.map((x) => ({
|
|
64
|
+
id: x.id,
|
|
65
|
+
content: x.content,
|
|
66
|
+
score: x.score,
|
|
67
|
+
sectors: x.sectors,
|
|
68
|
+
primary_sector: x.primary_sector,
|
|
69
|
+
path: x.path,
|
|
70
|
+
salience: x.salience,
|
|
71
|
+
last_seen_at: x.last_seen_at,
|
|
72
|
+
})),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
res.json({ query: b.query, matches: [] });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
app.post("/memory/reinforce", async (req, res) => {
|
|
80
|
+
const b = req.body;
|
|
81
|
+
if (!b?.id)
|
|
82
|
+
return res.status(400).json({ err: "id" });
|
|
83
|
+
try {
|
|
84
|
+
await (0, hsg_1.reinforce_memory)(b.id, b.boost);
|
|
85
|
+
res.json({ ok: true });
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
res.status(404).json({ err: "nf" });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
app.patch("/memory/:id", async (req, res) => {
|
|
92
|
+
const id = req.params.id;
|
|
93
|
+
const b = req.body;
|
|
94
|
+
if (!id)
|
|
95
|
+
return res.status(400).json({ err: "id" });
|
|
96
|
+
try {
|
|
97
|
+
// Check if memory exists and user has permission
|
|
98
|
+
const m = await db_1.q.get_mem.get(id);
|
|
99
|
+
if (!m)
|
|
100
|
+
return res.status(404).json({ err: "nf" });
|
|
101
|
+
// Check user ownership if user_id is provided
|
|
102
|
+
if (b.user_id && m.user_id !== b.user_id) {
|
|
103
|
+
return res.status(403).json({ err: "forbidden" });
|
|
104
|
+
}
|
|
105
|
+
const r = await (0, hsg_1.update_memory)(id, b.content, b.tags, b.metadata);
|
|
106
|
+
res.json(r);
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
if (e.message.includes("not found")) {
|
|
110
|
+
res.status(404).json({ err: "nf" });
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
res.status(500).json({ err: "internal" });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
app.get("/memory/all", async (req, res) => {
|
|
118
|
+
try {
|
|
119
|
+
const u = req.query.u ? parseInt(req.query.u) : 0;
|
|
120
|
+
const l = req.query.l ? parseInt(req.query.l) : 100;
|
|
121
|
+
const s = req.query.sector;
|
|
122
|
+
const user_id = req.query.user_id;
|
|
123
|
+
let r;
|
|
124
|
+
if (user_id) {
|
|
125
|
+
// Filter by user_id
|
|
126
|
+
r = await db_1.q.all_mem_by_user.all(user_id, l, u);
|
|
127
|
+
}
|
|
128
|
+
else if (s) {
|
|
129
|
+
// Filter by sector
|
|
130
|
+
r = await db_1.q.all_mem_by_sector.all(s, l, u);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// No filter
|
|
134
|
+
r = await db_1.q.all_mem.all(l, u);
|
|
135
|
+
}
|
|
136
|
+
if (req.query.key_id) {
|
|
137
|
+
r = r.filter((x) => x.memory_key_id === req.query.key_id);
|
|
138
|
+
}
|
|
139
|
+
const i = r.map((x) => ({
|
|
140
|
+
id: x.id,
|
|
141
|
+
content: x.content,
|
|
142
|
+
tags: (0, utils_1.p)(x.tags),
|
|
143
|
+
metadata: (0, utils_1.p)(x.meta),
|
|
144
|
+
created_at: x.created_at,
|
|
145
|
+
updated_at: x.updated_at,
|
|
146
|
+
last_seen_at: x.last_seen_at,
|
|
147
|
+
salience: x.salience,
|
|
148
|
+
decay_lambda: x.decay_lambda,
|
|
149
|
+
primary_sector: x.primary_sector,
|
|
150
|
+
version: x.version,
|
|
151
|
+
user_id: x.user_id,
|
|
152
|
+
memory_key_id: x.memory_key_id,
|
|
153
|
+
}));
|
|
154
|
+
res.json({ items: i });
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
res.status(500).json({ err: "internal" });
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
app.get("/memory/:id", async (req, res) => {
|
|
161
|
+
try {
|
|
162
|
+
const id = req.params.id;
|
|
163
|
+
const user_id = req.query.user_id;
|
|
164
|
+
const m = await db_1.q.get_mem.get(id);
|
|
165
|
+
if (!m)
|
|
166
|
+
return res.status(404).json({ err: "nf" });
|
|
167
|
+
// Check user ownership if user_id is provided
|
|
168
|
+
if (user_id && m.user_id !== user_id) {
|
|
169
|
+
return res.status(403).json({ err: "forbidden" });
|
|
170
|
+
}
|
|
171
|
+
const v = await db_1.vector_store.getVectorsById(id);
|
|
172
|
+
const sec = v.map((x) => x.sector);
|
|
173
|
+
res.json({
|
|
174
|
+
id: m.id,
|
|
175
|
+
content: m.content,
|
|
176
|
+
primary_sector: m.primary_sector,
|
|
177
|
+
sectors: sec,
|
|
178
|
+
tags: (0, utils_1.p)(m.tags),
|
|
179
|
+
metadata: (0, utils_1.p)(m.meta),
|
|
180
|
+
created_at: m.created_at,
|
|
181
|
+
updated_at: m.updated_at,
|
|
182
|
+
last_seen_at: m.last_seen_at,
|
|
183
|
+
salience: m.salience,
|
|
184
|
+
decay_lambda: m.decay_lambda,
|
|
185
|
+
version: m.version,
|
|
186
|
+
user_id: m.user_id,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
catch (e) {
|
|
190
|
+
res.status(500).json({ err: "internal" });
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
app.delete("/memory/:id", async (req, res) => {
|
|
194
|
+
try {
|
|
195
|
+
const id = req.params.id;
|
|
196
|
+
const user_id = req.query.user_id || req.body?.user_id;
|
|
197
|
+
const m = await db_1.q.get_mem.get(id);
|
|
198
|
+
if (!m)
|
|
199
|
+
return res.status(404).json({ err: "nf" });
|
|
200
|
+
// Check user ownership if user_id is provided
|
|
201
|
+
if (user_id && m.user_id !== user_id) {
|
|
202
|
+
return res.status(403).json({ err: "forbidden" });
|
|
203
|
+
}
|
|
204
|
+
await db_1.q.del_mem.run(id);
|
|
205
|
+
await db_1.vector_store.deleteVectors(id);
|
|
206
|
+
await db_1.q.del_waypoints.run(id, id);
|
|
207
|
+
res.json({ ok: true });
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
res.status(500).json({ err: "internal" });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* sources webhook routes - ingest data from external sources via HTTP
|
|
4
|
+
*
|
|
5
|
+
* POST /sources/:source/ingest
|
|
6
|
+
* body: { creds: {...}, filters: {...}, user_id?: string }
|
|
7
|
+
*
|
|
8
|
+
* POST /sources/webhook/:source
|
|
9
|
+
* generic webhook endpoint for source-specific payloads
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.src = src;
|
|
46
|
+
const sources = __importStar(require("../../sources"));
|
|
47
|
+
function src(app) {
|
|
48
|
+
// list available sources
|
|
49
|
+
app.get("/sources", async (req, res) => {
|
|
50
|
+
res.json({
|
|
51
|
+
sources: ["github", "notion", "google_drive", "google_sheets", "google_slides", "onedrive", "web_crawler"],
|
|
52
|
+
usage: {
|
|
53
|
+
ingest: "POST /sources/:source/ingest { creds: {}, filters: {}, user_id? }",
|
|
54
|
+
webhook: "POST /sources/webhook/:source (source-specific payload)"
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
// ingest from a source
|
|
59
|
+
app.post("/sources/:source/ingest", async (req, res) => {
|
|
60
|
+
const { source } = req.params;
|
|
61
|
+
const { creds = {}, filters = {}, user_id } = req.body || {};
|
|
62
|
+
const source_map = {
|
|
63
|
+
github: sources.github_source,
|
|
64
|
+
notion: sources.notion_source,
|
|
65
|
+
google_drive: sources.google_drive_source,
|
|
66
|
+
google_sheets: sources.google_sheets_source,
|
|
67
|
+
google_slides: sources.google_slides_source,
|
|
68
|
+
onedrive: sources.onedrive_source,
|
|
69
|
+
web_crawler: sources.web_crawler_source,
|
|
70
|
+
};
|
|
71
|
+
if (!source_map[source]) {
|
|
72
|
+
return res.status(400).json({ error: `unknown source: ${source}`, available: Object.keys(source_map) });
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const src = new source_map[source](user_id);
|
|
76
|
+
await src.connect(creds);
|
|
77
|
+
const ids = await src.ingest_all(filters);
|
|
78
|
+
res.json({ ok: true, ingested: ids.length, memory_ids: ids });
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
res.status(500).json({ error: e.message });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// webhook endpoint for github events
|
|
85
|
+
app.post("/sources/webhook/github", async (req, res) => {
|
|
86
|
+
const event_type = req.headers["x-github-event"];
|
|
87
|
+
const payload = req.body;
|
|
88
|
+
if (!payload) {
|
|
89
|
+
return res.status(400).json({ error: "no payload" });
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const { ingestDocument } = await Promise.resolve().then(() => __importStar(require("../../ops/ingest")));
|
|
93
|
+
// handle different github events
|
|
94
|
+
let content = "";
|
|
95
|
+
let meta = { source: "github_webhook", event: event_type };
|
|
96
|
+
if (event_type === "push") {
|
|
97
|
+
const commits = payload.commits || [];
|
|
98
|
+
content = commits.map((c) => `${c.message}\n${c.url}`).join("\n\n");
|
|
99
|
+
meta.repo = payload.repository?.full_name;
|
|
100
|
+
meta.ref = payload.ref;
|
|
101
|
+
}
|
|
102
|
+
else if (event_type === "issues") {
|
|
103
|
+
content = `[${payload.action}] ${payload.issue?.title}\n${payload.issue?.body || ""}`;
|
|
104
|
+
meta.repo = payload.repository?.full_name;
|
|
105
|
+
meta.issue_number = payload.issue?.number;
|
|
106
|
+
}
|
|
107
|
+
else if (event_type === "pull_request") {
|
|
108
|
+
content = `[${payload.action}] PR: ${payload.pull_request?.title}\n${payload.pull_request?.body || ""}`;
|
|
109
|
+
meta.repo = payload.repository?.full_name;
|
|
110
|
+
meta.pr_number = payload.pull_request?.number;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
content = JSON.stringify(payload, null, 2);
|
|
114
|
+
}
|
|
115
|
+
if (content) {
|
|
116
|
+
const result = await ingestDocument("text", content, meta);
|
|
117
|
+
res.json({ ok: true, memory_id: result.root_memory_id, event: event_type });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
res.json({ ok: true, skipped: true, reason: "no content" });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
res.status(500).json({ error: e.message });
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// generic webhook for notion
|
|
128
|
+
app.post("/sources/webhook/notion", async (req, res) => {
|
|
129
|
+
const payload = req.body;
|
|
130
|
+
try {
|
|
131
|
+
const { ingestDocument } = await Promise.resolve().then(() => __importStar(require("../../ops/ingest")));
|
|
132
|
+
const content = JSON.stringify(payload, null, 2);
|
|
133
|
+
const result = await ingestDocument("text", content, { source: "notion_webhook" });
|
|
134
|
+
res.json({ ok: true, memory_id: result.root_memory_id });
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
res.status(500).json({ error: e.message });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sys = sys;
|
|
4
|
+
const db_1 = require("../../core/db");
|
|
5
|
+
const hsg_1 = require("../../memory/hsg");
|
|
6
|
+
const embed_1 = require("../../memory/embed");
|
|
7
|
+
const cfg_1 = require("../../core/cfg");
|
|
8
|
+
const TIER_BENEFITS = {
|
|
9
|
+
hybrid: {
|
|
10
|
+
recall: 98,
|
|
11
|
+
qps: "700-800",
|
|
12
|
+
ram: "0.5gb/10k",
|
|
13
|
+
use: "For high accuracy",
|
|
14
|
+
},
|
|
15
|
+
fast: {
|
|
16
|
+
recall: 70,
|
|
17
|
+
qps: "700-850",
|
|
18
|
+
ram: "0.6GB/10k",
|
|
19
|
+
use: "Local apps, extensions",
|
|
20
|
+
},
|
|
21
|
+
smart: {
|
|
22
|
+
recall: 85,
|
|
23
|
+
qps: "500-600",
|
|
24
|
+
ram: "0.9GB/10k",
|
|
25
|
+
use: "Production servers",
|
|
26
|
+
},
|
|
27
|
+
deep: {
|
|
28
|
+
recall: 94,
|
|
29
|
+
qps: "350-400",
|
|
30
|
+
ram: "1.6GB/10k",
|
|
31
|
+
use: "Cloud, high-accuracy",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
function sys(app) {
|
|
35
|
+
app.get("/health", async (incoming_http_request, outgoing_http_response) => {
|
|
36
|
+
outgoing_http_response.json({
|
|
37
|
+
ok: true,
|
|
38
|
+
version: "2.0-hsg-tiered",
|
|
39
|
+
embedding: (0, embed_1.getEmbeddingInfo)(),
|
|
40
|
+
tier: cfg_1.tier,
|
|
41
|
+
dim: cfg_1.env.vec_dim,
|
|
42
|
+
cache: cfg_1.env.cache_segments,
|
|
43
|
+
expected: TIER_BENEFITS[cfg_1.tier],
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
app.get("/sectors", async (incoming_http_request, outgoing_http_response) => {
|
|
47
|
+
try {
|
|
48
|
+
const database_sector_statistics_rows = await (0, db_1.all_async)(`
|
|
49
|
+
select primary_sector as sector, count(*) as count, avg(salience) as avg_salience
|
|
50
|
+
from memories
|
|
51
|
+
group by primary_sector
|
|
52
|
+
`);
|
|
53
|
+
outgoing_http_response.json({
|
|
54
|
+
sectors: Object.keys(hsg_1.sector_configs),
|
|
55
|
+
configs: hsg_1.sector_configs,
|
|
56
|
+
stats: database_sector_statistics_rows,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (unexpected_error_fetching_sectors) {
|
|
60
|
+
outgoing_http_response.status(500).json({ err: "internal" });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|