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.
Files changed (141) hide show
  1. package/.prettierrc +8 -0
  2. package/Dockerfile +59 -0
  3. package/RAW_SKILL.md +219 -0
  4. package/README.md +277 -0
  5. package/SKILL.md +58 -0
  6. package/bin/opm.js +268 -0
  7. package/data/openmemory.sqlite +0 -0
  8. package/data/openmemory.sqlite-shm +0 -0
  9. package/data/openmemory.sqlite-wal +0 -0
  10. package/dist/ai/graph.js +293 -0
  11. package/dist/ai/mcp.js +397 -0
  12. package/dist/cli.js +78 -0
  13. package/dist/core/cfg.js +87 -0
  14. package/dist/core/db.js +636 -0
  15. package/dist/core/memory.js +116 -0
  16. package/dist/core/migrate.js +227 -0
  17. package/dist/core/models.js +105 -0
  18. package/dist/core/telemetry.js +57 -0
  19. package/dist/core/types.js +2 -0
  20. package/dist/core/vector/postgres.js +52 -0
  21. package/dist/core/vector/valkey.js +246 -0
  22. package/dist/core/vector_store.js +2 -0
  23. package/dist/index.js +44 -0
  24. package/dist/memory/decay.js +301 -0
  25. package/dist/memory/embed.js +675 -0
  26. package/dist/memory/hsg.js +959 -0
  27. package/dist/memory/reflect.js +131 -0
  28. package/dist/memory/user_summary.js +99 -0
  29. package/dist/migrate.js +9 -0
  30. package/dist/ops/compress.js +255 -0
  31. package/dist/ops/dynamics.js +189 -0
  32. package/dist/ops/extract.js +333 -0
  33. package/dist/ops/ingest.js +214 -0
  34. package/dist/server/index.js +109 -0
  35. package/dist/server/middleware/auth.js +137 -0
  36. package/dist/server/routes/auth.js +186 -0
  37. package/dist/server/routes/compression.js +108 -0
  38. package/dist/server/routes/dashboard.js +399 -0
  39. package/dist/server/routes/docs.js +241 -0
  40. package/dist/server/routes/dynamics.js +312 -0
  41. package/dist/server/routes/ide.js +280 -0
  42. package/dist/server/routes/index.js +33 -0
  43. package/dist/server/routes/keys.js +132 -0
  44. package/dist/server/routes/langgraph.js +61 -0
  45. package/dist/server/routes/memory.js +213 -0
  46. package/dist/server/routes/sources.js +140 -0
  47. package/dist/server/routes/system.js +63 -0
  48. package/dist/server/routes/temporal.js +293 -0
  49. package/dist/server/routes/users.js +101 -0
  50. package/dist/server/routes/vercel.js +57 -0
  51. package/dist/server/server.js +211 -0
  52. package/dist/server.js +3 -0
  53. package/dist/sources/base.js +223 -0
  54. package/dist/sources/github.js +171 -0
  55. package/dist/sources/google_drive.js +166 -0
  56. package/dist/sources/google_sheets.js +112 -0
  57. package/dist/sources/google_slides.js +139 -0
  58. package/dist/sources/index.js +34 -0
  59. package/dist/sources/notion.js +165 -0
  60. package/dist/sources/onedrive.js +143 -0
  61. package/dist/sources/web_crawler.js +166 -0
  62. package/dist/temporal_graph/index.js +20 -0
  63. package/dist/temporal_graph/query.js +240 -0
  64. package/dist/temporal_graph/store.js +116 -0
  65. package/dist/temporal_graph/timeline.js +241 -0
  66. package/dist/temporal_graph/types.js +2 -0
  67. package/dist/utils/chunking.js +60 -0
  68. package/dist/utils/index.js +31 -0
  69. package/dist/utils/keyword.js +94 -0
  70. package/dist/utils/text.js +120 -0
  71. package/nodemon.json +7 -0
  72. package/package.json +50 -0
  73. package/references/api_reference.md +66 -0
  74. package/references/examples.md +45 -0
  75. package/src/ai/graph.ts +363 -0
  76. package/src/ai/mcp.ts +494 -0
  77. package/src/cli.ts +94 -0
  78. package/src/core/cfg.ts +110 -0
  79. package/src/core/db.ts +1052 -0
  80. package/src/core/memory.ts +99 -0
  81. package/src/core/migrate.ts +302 -0
  82. package/src/core/models.ts +107 -0
  83. package/src/core/telemetry.ts +47 -0
  84. package/src/core/types.ts +130 -0
  85. package/src/core/vector/postgres.ts +61 -0
  86. package/src/core/vector/valkey.ts +261 -0
  87. package/src/core/vector_store.ts +9 -0
  88. package/src/index.ts +5 -0
  89. package/src/memory/decay.ts +427 -0
  90. package/src/memory/embed.ts +707 -0
  91. package/src/memory/hsg.ts +1245 -0
  92. package/src/memory/reflect.ts +158 -0
  93. package/src/memory/user_summary.ts +110 -0
  94. package/src/migrate.ts +8 -0
  95. package/src/ops/compress.ts +296 -0
  96. package/src/ops/dynamics.ts +272 -0
  97. package/src/ops/extract.ts +360 -0
  98. package/src/ops/ingest.ts +286 -0
  99. package/src/server/index.ts +159 -0
  100. package/src/server/middleware/auth.ts +156 -0
  101. package/src/server/routes/auth.ts +223 -0
  102. package/src/server/routes/compression.ts +106 -0
  103. package/src/server/routes/dashboard.ts +420 -0
  104. package/src/server/routes/docs.ts +380 -0
  105. package/src/server/routes/dynamics.ts +516 -0
  106. package/src/server/routes/ide.ts +283 -0
  107. package/src/server/routes/index.ts +32 -0
  108. package/src/server/routes/keys.ts +131 -0
  109. package/src/server/routes/langgraph.ts +71 -0
  110. package/src/server/routes/memory.ts +440 -0
  111. package/src/server/routes/sources.ts +111 -0
  112. package/src/server/routes/system.ts +68 -0
  113. package/src/server/routes/temporal.ts +335 -0
  114. package/src/server/routes/users.ts +111 -0
  115. package/src/server/routes/vercel.ts +55 -0
  116. package/src/server/server.js +215 -0
  117. package/src/server.ts +1 -0
  118. package/src/sources/base.ts +257 -0
  119. package/src/sources/github.ts +156 -0
  120. package/src/sources/google_drive.ts +144 -0
  121. package/src/sources/google_sheets.ts +85 -0
  122. package/src/sources/google_slides.ts +115 -0
  123. package/src/sources/index.ts +19 -0
  124. package/src/sources/notion.ts +148 -0
  125. package/src/sources/onedrive.ts +131 -0
  126. package/src/sources/web_crawler.ts +161 -0
  127. package/src/temporal_graph/index.ts +4 -0
  128. package/src/temporal_graph/query.ts +299 -0
  129. package/src/temporal_graph/store.ts +156 -0
  130. package/src/temporal_graph/timeline.ts +319 -0
  131. package/src/temporal_graph/types.ts +41 -0
  132. package/src/utils/chunking.ts +66 -0
  133. package/src/utils/index.ts +25 -0
  134. package/src/utils/keyword.ts +137 -0
  135. package/src/utils/text.ts +115 -0
  136. package/tests/test_api_workspace_management.ts +413 -0
  137. package/tests/test_bulk_delete.ts +267 -0
  138. package/tests/test_omnibus.ts +166 -0
  139. package/tests/test_workspace_management.ts +278 -0
  140. package/tests/verify.ts +104 -0
  141. package/tsconfig.json +15 -0
@@ -0,0 +1,223 @@
1
+ import { q } from "../../core/db";
2
+ import { env } from "../../core/cfg";
3
+ import crypto from "crypto";
4
+ import Stripe from "stripe";
5
+
6
+ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", {
7
+ apiVersion: "2025-01-27.acacia" as any,
8
+ });
9
+
10
+ import { createClerkClient, verifyToken } from "@clerk/backend";
11
+
12
+ const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY });
13
+
14
+ export const auth = (app: any) => {
15
+ // Sync user from Clerk with JWT verification
16
+ app.post("/auth/clerk-sync", async (req: any, res: any) => {
17
+ try {
18
+ const token = req.headers.authorization?.replace("Bearer ", "");
19
+ if (!token) return res.status(401).json({ error: "No token provided" });
20
+
21
+ const session = await verifyToken(token, { secretKey: process.env.CLERK_SECRET_KEY });
22
+ const clerk_id = session.sub;
23
+ const { email } = req.body;
24
+
25
+ let user = await q.get_user_by_clerk_id.get(clerk_id);
26
+ if (!user) {
27
+ // Create new user
28
+ const user_id = crypto.randomUUID();
29
+ const api_key = `opm_${crypto.randomBytes(24).toString("hex")}`;
30
+
31
+ // Create Stripe customer
32
+ let stripe_customer_id = "";
33
+ try {
34
+ const customer = await stripe.customers.create({
35
+ email,
36
+ metadata: { clerk_id, user_id },
37
+ });
38
+ stripe_customer_id = customer.id;
39
+ } catch (e) {
40
+ console.error("[STRIPE] Customer creation failed:", e);
41
+ }
42
+
43
+ await q.ins_user.run(
44
+ user_id,
45
+ clerk_id,
46
+ api_key,
47
+ stripe_customer_id,
48
+ null, // subscription_id
49
+ 100, // free tier capacity (100 memories)
50
+ 0, // current usage
51
+ "", // summary
52
+ 0, // reflection_count
53
+ Date.now(),
54
+ Date.now()
55
+ );
56
+ user = await q.get_user_by_clerk_id.get(clerk_id);
57
+ } else if (!user.stripe_customer_id && email) {
58
+ // Backward compatibility: create Stripe customer for existing user
59
+ try {
60
+ const customer = await stripe.customers.create({
61
+ email,
62
+ metadata: { clerk_id: user.clerk_id, user_id: user.user_id },
63
+ });
64
+ await q.upd_user_billing.run(
65
+ user.user_id,
66
+ customer.id,
67
+ user.stripe_subscription_id,
68
+ user.memory_capacity,
69
+ Date.now()
70
+ );
71
+ user.stripe_customer_id = customer.id;
72
+ console.log(`[STRIPE] Fixed missing customer for ${clerk_id}`);
73
+ } catch (e) {
74
+ console.error("[STRIPE] Customer repair failed:", e);
75
+ }
76
+ }
77
+
78
+ res.json(user);
79
+ } catch (err: any) {
80
+ console.error("[AUTH] Clerk Sync Error:", err);
81
+ res.status(500).json({ error: err.message, stack: err.stack });
82
+ }
83
+ });
84
+
85
+ // Create Stripe Checkout Session with JWT verification
86
+ app.post("/auth/create-checkout", async (req: any, res: any) => {
87
+ try {
88
+ const token = req.headers.authorization?.replace("Bearer ", "");
89
+ if (!token) return res.status(401).json({ error: "No token provided" });
90
+
91
+ const clerkSession = await verifyToken(token, { secretKey: process.env.CLERK_SECRET_KEY });
92
+ const clerk_id = clerkSession.sub;
93
+ const { plan } = req.body;
94
+
95
+ const user = await q.get_user_by_clerk_id.get(clerk_id);
96
+ if (!user) return res.status(404).json({ error: "User not found" });
97
+
98
+ const priceMap: Record<string, number> = {
99
+ "starter": 2000, // $20.00/month
100
+ "pro": 10000, // $100.00/month
101
+ };
102
+
103
+ const checkoutOptions: Stripe.Checkout.SessionCreateParams = {
104
+ payment_method_types: ["card"],
105
+ line_items: [{
106
+ price_data: {
107
+ currency: "usd",
108
+ product_data: {
109
+ name: `OpenMemory ${plan.toUpperCase()} Plan`,
110
+ },
111
+ unit_amount: priceMap[plan] || 2000,
112
+ recurring: { interval: "month" },
113
+ },
114
+ quantity: 1,
115
+ }],
116
+ mode: "subscription",
117
+ success_url: `${process.env.DASHBOARD_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
118
+ cancel_url: `${process.env.DASHBOARD_URL}/cancel`,
119
+ metadata: { clerk_id, plan },
120
+ };
121
+
122
+ if (user.stripe_customer_id) {
123
+ checkoutOptions.customer = user.stripe_customer_id;
124
+ } else {
125
+ // Should have been fixed by clerk-sync, but use email as fallback
126
+ const clerkUser = await clerk.users.getUser(clerk_id);
127
+ checkoutOptions.customer_email = clerkUser.emailAddresses[0]?.emailAddress;
128
+ }
129
+
130
+ const session = await stripe.checkout.sessions.create(checkoutOptions);
131
+
132
+ res.json({ url: session.url });
133
+ } catch (err: any) {
134
+ console.error("[STRIPE] Checkout Error:", err);
135
+ res.status(500).json({ error: err.message, stack: err.stack });
136
+ }
137
+ });
138
+
139
+ // Create Stripe Customer Portal Session
140
+ app.post("/auth/create-portal", async (req: any, res: any) => {
141
+ try {
142
+ const token = req.headers.authorization?.replace("Bearer ", "");
143
+ if (!token) return res.status(401).json({ error: "No token provided" });
144
+
145
+ const clerkSession = await verifyToken(token, { secretKey: process.env.CLERK_SECRET_KEY });
146
+ const clerk_id = clerkSession.sub;
147
+
148
+ const user = await q.get_user_by_clerk_id.get(clerk_id);
149
+ if (!user || !user.stripe_customer_id) {
150
+ return res.status(400).json({ error: "User or customer not found" });
151
+ }
152
+
153
+ const session = await stripe.billingPortal.sessions.create({
154
+ customer: user.stripe_customer_id,
155
+ return_url: `${process.env.DASHBOARD_URL}/dashboard`,
156
+ });
157
+
158
+ res.json({ url: session.url });
159
+ } catch (err: any) {
160
+ console.error("[STRIPE] Portal Error:", err);
161
+ res.status(500).json({ error: err.message });
162
+ }
163
+ });
164
+
165
+ // Stripe Webhook
166
+ app.post("/auth/stripe-webhook", async (req: any, res: any) => {
167
+ const sig = req.headers["stripe-signature"];
168
+ let event;
169
+
170
+ try {
171
+ event = stripe.webhooks.constructEvent(
172
+ req.rawBody || JSON.stringify(req.body),
173
+ sig,
174
+ process.env.STRIPE_WEBHOOK_SECRET || ""
175
+ );
176
+ } catch (err: any) {
177
+ return res.status(400).send(`Webhook Error: ${err.message}`);
178
+ }
179
+
180
+ if (event.type === "checkout.session.completed") {
181
+ const session = event.data.object as Stripe.Checkout.Session;
182
+ const clerk_id = session.metadata?.clerk_id;
183
+ const plan = session.metadata?.plan;
184
+
185
+ if (clerk_id) {
186
+ const user = await q.get_user_by_clerk_id.get(clerk_id);
187
+ if (user) {
188
+ const capacityMap: Record<string, number> = {
189
+ "starter": 10000, // 10,000 memories
190
+ "pro": 100000, // 100,000 memories
191
+ };
192
+ const new_capacity = capacityMap[plan!] || 10000;
193
+ await q.upd_user_billing.run(
194
+ user.user_id,
195
+ user.stripe_customer_id,
196
+ session.subscription as string,
197
+ new_capacity,
198
+ Date.now()
199
+ );
200
+ console.log(`[STRIPE] Updated capacity for ${clerk_id} to ${new_capacity}`);
201
+ }
202
+ }
203
+ } else if (event.type === "customer.subscription.deleted") {
204
+ const subscription = event.data.object as Stripe.Subscription;
205
+ const customer_id = subscription.customer as string;
206
+
207
+ // Downgrade user to free tier
208
+ const user = await q.get_user_by_stripe_customer_id.get(customer_id);
209
+ if (user) {
210
+ await q.upd_user_billing.run(
211
+ user.user_id,
212
+ user.stripe_customer_id,
213
+ null,
214
+ 100, // back to free tier (100 memories)
215
+ Date.now()
216
+ );
217
+ console.log(`[STRIPE] Downgraded ${user.clerk_id} to free tier`);
218
+ }
219
+ }
220
+
221
+ res.json({ received: true });
222
+ });
223
+ };
@@ -0,0 +1,106 @@
1
+ import { compressionEngine, CompressionMetrics } from "../../ops/compress";
2
+
3
+ export function compression(app: any) {
4
+ app.post("/api/compression/compress", async (req: any, res: any) => {
5
+ try {
6
+ const { text, algorithm } = req.body;
7
+ if (!text) return res.status(400).json({ error: "text required" });
8
+ let r;
9
+ if (
10
+ algorithm &&
11
+ ["semantic", "syntactic", "aggressive"].includes(algorithm)
12
+ ) {
13
+ r = compressionEngine.compress(text, algorithm);
14
+ } else {
15
+ r = compressionEngine.auto(text);
16
+ }
17
+ res.json({ ok: true, comp: r.comp, m: r.metrics, hash: r.hash });
18
+ } catch (e: any) {
19
+ res.status(500).json({ error: e.message });
20
+ }
21
+ });
22
+
23
+ app.post("/api/compression/batch", async (req: any, res: any) => {
24
+ try {
25
+ const { texts, algorithm = "semantic" } = req.body;
26
+ if (!Array.isArray(texts))
27
+ return res.status(400).json({ error: "texts must be array" });
28
+ if (!["semantic", "syntactic", "aggressive"].includes(algorithm))
29
+ return res.status(400).json({ error: "invalid algo" });
30
+ const r = compressionEngine.batch(texts, algorithm);
31
+ res.json({
32
+ ok: true,
33
+ results: r.map((x: any) => ({
34
+ comp: x.comp,
35
+ m: x.metrics,
36
+ hash: x.hash,
37
+ })),
38
+ total: r.reduce((s: any, x: any) => s + x.metrics.saved, 0),
39
+ });
40
+ } catch (e: any) {
41
+ res.status(500).json({ error: e.message });
42
+ }
43
+ });
44
+
45
+ app.post("/api/compression/analyze", async (req: any, res: any) => {
46
+ try {
47
+ const { text } = req.body;
48
+ if (!text) return res.status(400).json({ error: "text required" });
49
+ const a = compressionEngine.analyze(text);
50
+ let best = "semantic";
51
+ let max = 0;
52
+ for (const [algo, m] of Object.entries(a)) {
53
+ const met = m as CompressionMetrics;
54
+ if (met.pct > max) {
55
+ max = met.pct;
56
+ best = algo;
57
+ }
58
+ }
59
+ res.json({
60
+ ok: true,
61
+ analysis: a,
62
+ rec: {
63
+ algo: best,
64
+ save: (a as any)[best].pct.toFixed(2) + "%",
65
+ lat: (a as any)[best].latency.toFixed(2) + "ms",
66
+ },
67
+ });
68
+ } catch (e: any) {
69
+ res.status(500).json({ error: e.message });
70
+ }
71
+ });
72
+
73
+ app.get("/api/compression/stats", async (req: any, res: any) => {
74
+ try {
75
+ const s = compressionEngine.getStats();
76
+ res.json({
77
+ ok: true,
78
+ stats: {
79
+ ...s,
80
+ avgRatio: (s.avgRatio * 100).toFixed(2) + "%",
81
+ totalPct:
82
+ s.ogTok > 0
83
+ ? ((s.saved / s.ogTok) * 100).toFixed(2) + "%"
84
+ : "0%",
85
+ lat: s.latency.toFixed(2) + "ms",
86
+ avgLat:
87
+ s.total > 0
88
+ ? (s.latency / s.total).toFixed(2) + "ms"
89
+ : "0ms",
90
+ },
91
+ });
92
+ } catch (e: any) {
93
+ res.status(500).json({ error: e.message });
94
+ }
95
+ });
96
+
97
+ app.post("/api/compression/reset", async (req: any, res: any) => {
98
+ try {
99
+ compressionEngine.reset();
100
+ compressionEngine.clear();
101
+ res.json({ ok: true, msg: "reset done" });
102
+ } catch (e: any) {
103
+ res.status(500).json({ error: e.message });
104
+ }
105
+ });
106
+ }