@folterung/project-memory 0.1.0

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 (215) hide show
  1. package/.memignore.example +11 -0
  2. package/README.md +48 -0
  3. package/docker-compose.yml +17 -0
  4. package/package.json +36 -0
  5. package/packages/cli/bin/mem.js +6 -0
  6. package/packages/cli/coverage/lcov-report/base.css +224 -0
  7. package/packages/cli/coverage/lcov-report/block-navigation.js +87 -0
  8. package/packages/cli/coverage/lcov-report/chunking/chunker.ts.html +538 -0
  9. package/packages/cli/coverage/lcov-report/chunking/hash.ts.html +148 -0
  10. package/packages/cli/coverage/lcov-report/chunking/index.html +146 -0
  11. package/packages/cli/coverage/lcov-report/chunking/types.ts.html +214 -0
  12. package/packages/cli/coverage/lcov-report/config/index.html +131 -0
  13. package/packages/cli/coverage/lcov-report/config/load.ts.html +184 -0
  14. package/packages/cli/coverage/lcov-report/config/types.ts.html +232 -0
  15. package/packages/cli/coverage/lcov-report/embedding/index.html +116 -0
  16. package/packages/cli/coverage/lcov-report/embedding/stub.ts.html +181 -0
  17. package/packages/cli/coverage/lcov-report/favicon.png +0 -0
  18. package/packages/cli/coverage/lcov-report/index.html +161 -0
  19. package/packages/cli/coverage/lcov-report/prettify.css +1 -0
  20. package/packages/cli/coverage/lcov-report/prettify.js +2 -0
  21. package/packages/cli/coverage/lcov-report/scope/allowlist.ts.html +199 -0
  22. package/packages/cli/coverage/lcov-report/scope/ignore.ts.html +343 -0
  23. package/packages/cli/coverage/lcov-report/scope/index.html +131 -0
  24. package/packages/cli/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  25. package/packages/cli/coverage/lcov-report/sorter.js +210 -0
  26. package/packages/cli/coverage/lcov.info +669 -0
  27. package/packages/cli/coverage/tmp/coverage-25917-1770055893226-0.json +1 -0
  28. package/packages/cli/coverage/tmp/coverage-25918-1770055893272-0.json +1 -0
  29. package/packages/cli/coverage/tmp/coverage-25919-1770055893273-0.json +1 -0
  30. package/packages/cli/coverage/tmp/coverage-25920-1770055893271-0.json +1 -0
  31. package/packages/cli/coverage/tmp/coverage-25921-1770055893279-0.json +1 -0
  32. package/packages/cli/coverage/tmp/coverage-25922-1770055893272-0.json +1 -0
  33. package/packages/cli/coverage/tmp/coverage-25923-1770055893275-0.json +1 -0
  34. package/packages/cli/coverage/tmp/coverage-25924-1770055893294-0.json +1 -0
  35. package/packages/cli/coverage/tmp/coverage-25925-1770055893290-0.json +1 -0
  36. package/packages/cli/dist/chunking/chunker.d.ts +2 -0
  37. package/packages/cli/dist/chunking/chunker.js +142 -0
  38. package/packages/cli/dist/chunking/chunker.js.map +1 -0
  39. package/packages/cli/dist/chunking/chunker.test.d.ts +1 -0
  40. package/packages/cli/dist/chunking/chunker.test.js +50 -0
  41. package/packages/cli/dist/chunking/chunker.test.js.map +1 -0
  42. package/packages/cli/dist/chunking/hash.d.ts +3 -0
  43. package/packages/cli/dist/chunking/hash.js +17 -0
  44. package/packages/cli/dist/chunking/hash.js.map +1 -0
  45. package/packages/cli/dist/chunking/hash.test.d.ts +1 -0
  46. package/packages/cli/dist/chunking/hash.test.js +36 -0
  47. package/packages/cli/dist/chunking/hash.test.js.map +1 -0
  48. package/packages/cli/dist/chunking/types.d.ts +19 -0
  49. package/packages/cli/dist/chunking/types.js +24 -0
  50. package/packages/cli/dist/chunking/types.js.map +1 -0
  51. package/packages/cli/dist/chunking/types.test.d.ts +1 -0
  52. package/packages/cli/dist/chunking/types.test.js +25 -0
  53. package/packages/cli/dist/chunking/types.test.js.map +1 -0
  54. package/packages/cli/dist/cli/index.d.ts +1 -0
  55. package/packages/cli/dist/cli/index.js +67 -0
  56. package/packages/cli/dist/cli/index.js.map +1 -0
  57. package/packages/cli/dist/commands/deep-index.d.ts +1 -0
  58. package/packages/cli/dist/commands/deep-index.js +17 -0
  59. package/packages/cli/dist/commands/deep-index.js.map +1 -0
  60. package/packages/cli/dist/commands/doctor.d.ts +1 -0
  61. package/packages/cli/dist/commands/doctor.js +27 -0
  62. package/packages/cli/dist/commands/doctor.js.map +1 -0
  63. package/packages/cli/dist/commands/down.d.ts +1 -0
  64. package/packages/cli/dist/commands/down.js +13 -0
  65. package/packages/cli/dist/commands/down.js.map +1 -0
  66. package/packages/cli/dist/commands/explain.d.ts +1 -0
  67. package/packages/cli/dist/commands/explain.js +23 -0
  68. package/packages/cli/dist/commands/explain.js.map +1 -0
  69. package/packages/cli/dist/commands/init.d.ts +1 -0
  70. package/packages/cli/dist/commands/init.js +35 -0
  71. package/packages/cli/dist/commands/init.js.map +1 -0
  72. package/packages/cli/dist/commands/query.d.ts +1 -0
  73. package/packages/cli/dist/commands/query.js +44 -0
  74. package/packages/cli/dist/commands/query.js.map +1 -0
  75. package/packages/cli/dist/commands/reset.d.ts +3 -0
  76. package/packages/cli/dist/commands/reset.js +28 -0
  77. package/packages/cli/dist/commands/reset.js.map +1 -0
  78. package/packages/cli/dist/commands/scaffold.d.ts +1 -0
  79. package/packages/cli/dist/commands/scaffold.js +52 -0
  80. package/packages/cli/dist/commands/scaffold.js.map +1 -0
  81. package/packages/cli/dist/commands/update.d.ts +5 -0
  82. package/packages/cli/dist/commands/update.js +23 -0
  83. package/packages/cli/dist/commands/update.js.map +1 -0
  84. package/packages/cli/dist/commands/watch.d.ts +1 -0
  85. package/packages/cli/dist/commands/watch.js +46 -0
  86. package/packages/cli/dist/commands/watch.js.map +1 -0
  87. package/packages/cli/dist/config/defaults.d.ts +2 -0
  88. package/packages/cli/dist/config/defaults.js +47 -0
  89. package/packages/cli/dist/config/defaults.js.map +1 -0
  90. package/packages/cli/dist/config/load.d.ts +4 -0
  91. package/packages/cli/dist/config/load.js +29 -0
  92. package/packages/cli/dist/config/load.js.map +1 -0
  93. package/packages/cli/dist/config/load.test.d.ts +1 -0
  94. package/packages/cli/dist/config/load.test.js +51 -0
  95. package/packages/cli/dist/config/load.test.js.map +1 -0
  96. package/packages/cli/dist/config/types.d.ts +32 -0
  97. package/packages/cli/dist/config/types.js +24 -0
  98. package/packages/cli/dist/config/types.js.map +1 -0
  99. package/packages/cli/dist/config/types.test.d.ts +1 -0
  100. package/packages/cli/dist/config/types.test.js +31 -0
  101. package/packages/cli/dist/config/types.test.js.map +1 -0
  102. package/packages/cli/dist/docker/compose.d.ts +5 -0
  103. package/packages/cli/dist/docker/compose.js +75 -0
  104. package/packages/cli/dist/docker/compose.js.map +1 -0
  105. package/packages/cli/dist/embedding/stub.d.ts +6 -0
  106. package/packages/cli/dist/embedding/stub.js +29 -0
  107. package/packages/cli/dist/embedding/stub.js.map +1 -0
  108. package/packages/cli/dist/embedding/stub.test.d.ts +1 -0
  109. package/packages/cli/dist/embedding/stub.test.js +31 -0
  110. package/packages/cli/dist/embedding/stub.test.js.map +1 -0
  111. package/packages/cli/dist/phase1/pipeline.d.ts +1 -0
  112. package/packages/cli/dist/phase1/pipeline.js +145 -0
  113. package/packages/cli/dist/phase1/pipeline.js.map +1 -0
  114. package/packages/cli/dist/phase2/deep-index.d.ts +1 -0
  115. package/packages/cli/dist/phase2/deep-index.js +105 -0
  116. package/packages/cli/dist/phase2/deep-index.js.map +1 -0
  117. package/packages/cli/dist/qdrant/upsert.d.ts +14 -0
  118. package/packages/cli/dist/qdrant/upsert.js +30 -0
  119. package/packages/cli/dist/qdrant/upsert.js.map +1 -0
  120. package/packages/cli/dist/scope/allowlist.d.ts +11 -0
  121. package/packages/cli/dist/scope/allowlist.js +36 -0
  122. package/packages/cli/dist/scope/allowlist.js.map +1 -0
  123. package/packages/cli/dist/scope/allowlist.test.d.ts +1 -0
  124. package/packages/cli/dist/scope/allowlist.test.js +23 -0
  125. package/packages/cli/dist/scope/allowlist.test.js.map +1 -0
  126. package/packages/cli/dist/scope/ignore.d.ts +2 -0
  127. package/packages/cli/dist/scope/ignore.js +80 -0
  128. package/packages/cli/dist/scope/ignore.js.map +1 -0
  129. package/packages/cli/dist/scope/ignore.test.d.ts +1 -0
  130. package/packages/cli/dist/scope/ignore.test.js +71 -0
  131. package/packages/cli/dist/scope/ignore.test.js.map +1 -0
  132. package/packages/cli/package.json +46 -0
  133. package/packages/cli/src/chunking/chunker.test.ts +54 -0
  134. package/packages/cli/src/chunking/chunker.ts +151 -0
  135. package/packages/cli/src/chunking/hash.test.ts +41 -0
  136. package/packages/cli/src/chunking/hash.ts +21 -0
  137. package/packages/cli/src/chunking/types.test.ts +28 -0
  138. package/packages/cli/src/chunking/types.ts +43 -0
  139. package/packages/cli/src/cli/index.ts +79 -0
  140. package/packages/cli/src/commands/deep-index.ts +16 -0
  141. package/packages/cli/src/commands/doctor.ts +32 -0
  142. package/packages/cli/src/commands/down.ts +12 -0
  143. package/packages/cli/src/commands/explain.ts +22 -0
  144. package/packages/cli/src/commands/init.ts +37 -0
  145. package/packages/cli/src/commands/query.ts +49 -0
  146. package/packages/cli/src/commands/reset.ts +30 -0
  147. package/packages/cli/src/commands/scaffold.ts +55 -0
  148. package/packages/cli/src/commands/update.ts +22 -0
  149. package/packages/cli/src/commands/watch.ts +47 -0
  150. package/packages/cli/src/config/defaults.ts +49 -0
  151. package/packages/cli/src/config/load.test.ts +55 -0
  152. package/packages/cli/src/config/load.ts +33 -0
  153. package/packages/cli/src/config/types.test.ts +43 -0
  154. package/packages/cli/src/config/types.ts +49 -0
  155. package/packages/cli/src/docker/compose.ts +75 -0
  156. package/packages/cli/src/embedding/stub.test.ts +35 -0
  157. package/packages/cli/src/embedding/stub.ts +32 -0
  158. package/packages/cli/src/phase1/pipeline.ts +164 -0
  159. package/packages/cli/src/phase2/deep-index.ts +120 -0
  160. package/packages/cli/src/qdrant/upsert.ts +45 -0
  161. package/packages/cli/src/scope/allowlist.test.ts +25 -0
  162. package/packages/cli/src/scope/allowlist.ts +38 -0
  163. package/packages/cli/src/scope/ignore.test.ts +71 -0
  164. package/packages/cli/src/scope/ignore.ts +86 -0
  165. package/packages/cli/tsconfig.json +16 -0
  166. package/packages/server/coverage/lcov-report/base.css +224 -0
  167. package/packages/server/coverage/lcov-report/block-navigation.js +87 -0
  168. package/packages/server/coverage/lcov-report/favicon.png +0 -0
  169. package/packages/server/coverage/lcov-report/index.html +116 -0
  170. package/packages/server/coverage/lcov-report/prettify.css +1 -0
  171. package/packages/server/coverage/lcov-report/prettify.js +2 -0
  172. package/packages/server/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  173. package/packages/server/coverage/lcov-report/sorter.js +210 -0
  174. package/packages/server/coverage/lcov-report/stub.ts.html +184 -0
  175. package/packages/server/coverage/lcov.info +57 -0
  176. package/packages/server/coverage/tmp/coverage-26012-1770055894042-0.json +1 -0
  177. package/packages/server/coverage/tmp/coverage-26013-1770055894077-0.json +1 -0
  178. package/packages/server/dist/api/explain.d.ts +6 -0
  179. package/packages/server/dist/api/explain.js +16 -0
  180. package/packages/server/dist/api/explain.js.map +1 -0
  181. package/packages/server/dist/api/health.d.ts +7 -0
  182. package/packages/server/dist/api/health.js +43 -0
  183. package/packages/server/dist/api/health.js.map +1 -0
  184. package/packages/server/dist/api/refresh.d.ts +2 -0
  185. package/packages/server/dist/api/refresh.js +8 -0
  186. package/packages/server/dist/api/refresh.js.map +1 -0
  187. package/packages/server/dist/api/search.d.ts +28 -0
  188. package/packages/server/dist/api/search.js +36 -0
  189. package/packages/server/dist/api/search.js.map +1 -0
  190. package/packages/server/dist/api/system.d.ts +6 -0
  191. package/packages/server/dist/api/system.js +17 -0
  192. package/packages/server/dist/api/system.js.map +1 -0
  193. package/packages/server/dist/embedding/stub.d.ts +7 -0
  194. package/packages/server/dist/embedding/stub.js +30 -0
  195. package/packages/server/dist/embedding/stub.js.map +1 -0
  196. package/packages/server/dist/embedding/stub.test.d.ts +1 -0
  197. package/packages/server/dist/embedding/stub.test.js +25 -0
  198. package/packages/server/dist/embedding/stub.test.js.map +1 -0
  199. package/packages/server/dist/index.d.ts +1 -0
  200. package/packages/server/dist/index.js +26 -0
  201. package/packages/server/dist/index.js.map +1 -0
  202. package/packages/server/dist/qdrant/client.d.ts +24 -0
  203. package/packages/server/dist/qdrant/client.js +55 -0
  204. package/packages/server/dist/qdrant/client.js.map +1 -0
  205. package/packages/server/package.json +37 -0
  206. package/packages/server/src/api/explain.ts +24 -0
  207. package/packages/server/src/api/health.ts +50 -0
  208. package/packages/server/src/api/refresh.ts +9 -0
  209. package/packages/server/src/api/search.ts +57 -0
  210. package/packages/server/src/api/system.ts +25 -0
  211. package/packages/server/src/embedding/stub.test.ts +28 -0
  212. package/packages/server/src/embedding/stub.ts +33 -0
  213. package/packages/server/src/index.ts +29 -0
  214. package/packages/server/src/qdrant/client.ts +92 -0
  215. package/packages/server/tsconfig.json +16 -0
@@ -0,0 +1,28 @@
1
+ import { strict as assert } from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { embedText, embedBatch, getVectorSize } from "./stub.js";
4
+
5
+ describe("embedding stub (server)", () => {
6
+ it("getVectorSize returns 384", () => {
7
+ assert.strictEqual(getVectorSize(), 384);
8
+ });
9
+
10
+ it("embedText returns array of length 384", () => {
11
+ const vec = embedText("hello world");
12
+ assert.strictEqual(vec.length, 384);
13
+ assert.ok(vec.every((x) => typeof x === "number" && x >= 0 && x <= 1));
14
+ });
15
+
16
+ it("embedText is deterministic for same input", () => {
17
+ const a = embedText("same text");
18
+ const b = embedText("same text");
19
+ assert.deepStrictEqual(a, b);
20
+ });
21
+
22
+ it("embedBatch returns one vector per text", () => {
23
+ const batch = embedBatch(["a", "b"]);
24
+ assert.strictEqual(batch.length, 2);
25
+ assert.strictEqual(batch[0].length, 384);
26
+ assert.strictEqual(batch[1].length, 384);
27
+ });
28
+ });
@@ -0,0 +1,33 @@
1
+ const VECTOR_SIZE = 384;
2
+
3
+ function simpleHash(str: string): number {
4
+ let h = 0;
5
+ for (let i = 0; i < str.length; i++) {
6
+ h = (h * 31 + str.charCodeAt(i)) >>> 0;
7
+ }
8
+ return h;
9
+ }
10
+
11
+ /**
12
+ * Stub embedder: deterministic pseudo-vector from text (same text -> same vector).
13
+ * V1 local default; replace with real model (e.g. transformers.js) later.
14
+ */
15
+ export function embedText(text: string): number[] {
16
+ const vec: number[] = [];
17
+ const words = text.split(/\s+/).filter(Boolean);
18
+ for (let i = 0; i < VECTOR_SIZE; i++) {
19
+ const seed = words[i % words.length]
20
+ ? simpleHash(words[i % words.length]) + i * 31
21
+ : i;
22
+ vec.push(Math.sin(seed) * 0.5 + 0.5);
23
+ }
24
+ return vec;
25
+ }
26
+
27
+ export function embedBatch(texts: string[]): number[][] {
28
+ return texts.map(embedText);
29
+ }
30
+
31
+ export function getVectorSize(): number {
32
+ return VECTOR_SIZE;
33
+ }
@@ -0,0 +1,29 @@
1
+ import Fastify from "fastify";
2
+ import { registerHealthRoutes } from "./api/health.js";
3
+ import { registerSearchRoutes } from "./api/search.js";
4
+ import { registerExplainRoutes } from "./api/explain.js";
5
+ import { registerSystemRoutes } from "./api/system.js";
6
+ import { registerRefreshRoutes } from "./api/refresh.js";
7
+
8
+ const PORT = Number(process.env.MEM_SERVER_PORT) || 31415;
9
+ const CWD = process.env.MEM_CWD || process.cwd();
10
+ const QDRANT_HOST = process.env.MEM_QDRANT_HOST || "127.0.0.1";
11
+ const QDRANT_PORT = Number(process.env.MEM_QDRANT_PORT) || 6333;
12
+ const COLLECTION = process.env.MEM_COLLECTION || "project_memory";
13
+
14
+ async function main() {
15
+ const app = Fastify({ logger: true });
16
+ registerHealthRoutes(app, { cwd: CWD, qdrantHost: QDRANT_HOST, qdrantPort: QDRANT_PORT, collection: COLLECTION });
17
+ registerSearchRoutes(app, { qdrantHost: QDRANT_HOST, qdrantPort: QDRANT_PORT, collection: COLLECTION });
18
+ registerExplainRoutes(app, { qdrantHost: QDRANT_HOST, qdrantPort: QDRANT_PORT, collection: COLLECTION });
19
+ registerSystemRoutes(app, { qdrantHost: QDRANT_HOST, qdrantPort: QDRANT_PORT, collection: COLLECTION });
20
+ registerRefreshRoutes(app);
21
+
22
+ await app.listen({ port: PORT, host: "127.0.0.1" });
23
+ console.log(`Memory server at http://127.0.0.1:${PORT}`);
24
+ }
25
+
26
+ main().catch((err) => {
27
+ console.error(err);
28
+ process.exit(1);
29
+ });
@@ -0,0 +1,92 @@
1
+ import { QdrantClient } from "@qdrant/js-client-rest";
2
+ import { getVectorSize } from "../embedding/stub.js";
3
+
4
+ const DEFAULT_COLLECTION = "project_memory";
5
+
6
+ export function createQdrantClient(host: string = "127.0.0.1", port: number = 6333): QdrantClient {
7
+ return new QdrantClient({ url: `http://${host}:${port}` });
8
+ }
9
+
10
+ export async function ensureCollection(
11
+ client: QdrantClient,
12
+ collectionName: string = DEFAULT_COLLECTION
13
+ ): Promise<void> {
14
+ const size = getVectorSize();
15
+ try {
16
+ await client.getCollection(collectionName);
17
+ } catch {
18
+ await client.createCollection(collectionName, {
19
+ vectors: { size, distance: "Cosine" },
20
+ });
21
+ }
22
+ }
23
+
24
+ export interface PointPayload {
25
+ kind: string;
26
+ path?: string;
27
+ text: string;
28
+ [key: string]: unknown;
29
+ }
30
+
31
+ export async function upsertPoints(
32
+ client: QdrantClient,
33
+ collectionName: string,
34
+ points: { id: string; vector: number[]; payload: PointPayload }[]
35
+ ): Promise<void> {
36
+ if (points.length === 0) return;
37
+ await client.upsert(collectionName, {
38
+ wait: true,
39
+ points: points.map((p) => ({
40
+ id: p.id,
41
+ vector: p.vector,
42
+ payload: p.payload,
43
+ })),
44
+ });
45
+ }
46
+
47
+ export async function searchPoints(
48
+ client: QdrantClient,
49
+ collectionName: string,
50
+ vector: number[],
51
+ limit: number = 10,
52
+ filterKind?: string
53
+ ): Promise<{ id: string; score: number; payload: PointPayload }[]> {
54
+ const filter = filterKind
55
+ ? { must: [{ key: "kind", match: { value: filterKind } }] }
56
+ : undefined;
57
+ return doSearch(client, collectionName, vector, limit, filter);
58
+ }
59
+
60
+ export async function searchPointsKinds(
61
+ client: QdrantClient,
62
+ collectionName: string,
63
+ vector: number[],
64
+ limit: number,
65
+ kinds: string[]
66
+ ): Promise<{ id: string; score: number; payload: PointPayload }[]> {
67
+ const filter =
68
+ kinds.length > 0
69
+ ? { should: kinds.map((k) => ({ key: "kind", match: { value: k } })) }
70
+ : undefined;
71
+ return doSearch(client, collectionName, vector, limit, filter);
72
+ }
73
+
74
+ async function doSearch(
75
+ client: QdrantClient,
76
+ collectionName: string,
77
+ vector: number[],
78
+ limit: number,
79
+ filter: { must?: unknown[]; should?: unknown[] } | undefined
80
+ ): Promise<{ id: string; score: number; payload: PointPayload }[]> {
81
+ const result = await client.search(collectionName, {
82
+ vector,
83
+ limit,
84
+ with_payload: true,
85
+ filter,
86
+ });
87
+ return result.map((r) => ({
88
+ id: (r.id as string) ?? String(r.id),
89
+ score: r.score ?? 0,
90
+ payload: (r.payload ?? {}) as PointPayload,
91
+ }));
92
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true,
12
+ "sourceMap": true
13
+ },
14
+ "include": ["src/**/*"],
15
+ "exclude": ["node_modules", "dist"]
16
+ }