@rubytech/create-maxy 1.0.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 (181) hide show
  1. package/dist/index.js +428 -0
  2. package/package.json +31 -0
  3. package/payload/maxy/.env.example +12 -0
  4. package/payload/maxy/app/admin/components/ActivityTimeline.tsx +348 -0
  5. package/payload/maxy/app/admin/components/MarkdownMessage.tsx +40 -0
  6. package/payload/maxy/app/api/admin/chat/route.ts +72 -0
  7. package/payload/maxy/app/api/admin/logs/route.ts +40 -0
  8. package/payload/maxy/app/api/admin/session/route.ts +74 -0
  9. package/payload/maxy/app/api/chat/route.ts +72 -0
  10. package/payload/maxy/app/api/health/route.ts +26 -0
  11. package/payload/maxy/app/api/onboarding/claude-auth/route.ts +216 -0
  12. package/payload/maxy/app/api/onboarding/set-pin/route.ts +44 -0
  13. package/payload/maxy/app/api/session/route.ts +51 -0
  14. package/payload/maxy/app/api/telegram/webhook/route.ts +107 -0
  15. package/payload/maxy/app/apple-icon.png +0 -0
  16. package/payload/maxy/app/bot/page.tsx +373 -0
  17. package/payload/maxy/app/favicon.ico +0 -0
  18. package/payload/maxy/app/globals.css +1681 -0
  19. package/payload/maxy/app/layout.tsx +58 -0
  20. package/payload/maxy/app/lib/claude-agent.ts +503 -0
  21. package/payload/maxy/app/og/layout.tsx +15 -0
  22. package/payload/maxy/app/og/page.tsx +252 -0
  23. package/payload/maxy/app/page.tsx +594 -0
  24. package/payload/maxy/app/privacy/page.tsx +72 -0
  25. package/payload/maxy/app/public/page.tsx +266 -0
  26. package/payload/maxy/next.config.mjs +26 -0
  27. package/payload/maxy/package-lock.json +2198 -0
  28. package/payload/maxy/package.json +25 -0
  29. package/payload/maxy/proxy.ts +41 -0
  30. package/payload/maxy/public/brand/claude.png +0 -0
  31. package/payload/maxy/public/brand/maxy-black.png +0 -0
  32. package/payload/maxy/public/brand/maxy.png +0 -0
  33. package/payload/maxy/public/favicon.ico +0 -0
  34. package/payload/maxy/public/og-landscape.png +0 -0
  35. package/payload/maxy/public/og-portrait.png +0 -0
  36. package/payload/maxy/public/og-square.png +0 -0
  37. package/payload/maxy/public/pi-5.jpg +0 -0
  38. package/payload/maxy/public/robots.txt +5 -0
  39. package/payload/maxy/tsconfig.json +41 -0
  40. package/payload/maxy/tsconfig.tsbuildinfo +1 -0
  41. package/payload/maxy/ui.md +28 -0
  42. package/payload/platform/config/cloudflared.yml +17 -0
  43. package/payload/platform/knowledge/maxy.md +161 -0
  44. package/payload/platform/neo4j/schema.cypher +108 -0
  45. package/payload/platform/package-lock.json +1835 -0
  46. package/payload/platform/package.json +17 -0
  47. package/payload/platform/plugins/admin/PLUGIN.md +24 -0
  48. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +56 -0
  49. package/payload/platform/plugins/admin/hooks/session-start.sh +20 -0
  50. package/payload/platform/plugins/admin/mcp/dist/index.d.ts +2 -0
  51. package/payload/platform/plugins/admin/mcp/dist/index.d.ts.map +1 -0
  52. package/payload/platform/plugins/admin/mcp/dist/index.js +149 -0
  53. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -0
  54. package/payload/platform/plugins/admin/mcp/package.json +18 -0
  55. package/payload/platform/plugins/anthropic/PLUGIN.md +30 -0
  56. package/payload/platform/plugins/anthropic/references/setup-guide.md +146 -0
  57. package/payload/platform/plugins/business-assistant/PLUGIN.md +46 -0
  58. package/payload/platform/plugins/business-assistant/references/crm.md +112 -0
  59. package/payload/platform/plugins/business-assistant/references/document-management.md +96 -0
  60. package/payload/platform/plugins/business-assistant/references/escalation.md +126 -0
  61. package/payload/platform/plugins/business-assistant/references/invoicing.md +163 -0
  62. package/payload/platform/plugins/business-assistant/references/quoting.md +56 -0
  63. package/payload/platform/plugins/business-assistant/references/scheduling.md +127 -0
  64. package/payload/platform/plugins/cloudflare/PLUGIN.md +31 -0
  65. package/payload/platform/plugins/cloudflare/mcp/dist/index.d.ts +2 -0
  66. package/payload/platform/plugins/cloudflare/mcp/dist/index.d.ts.map +1 -0
  67. package/payload/platform/plugins/cloudflare/mcp/dist/index.js +174 -0
  68. package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -0
  69. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts +45 -0
  70. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts.map +1 -0
  71. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js +256 -0
  72. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js.map +1 -0
  73. package/payload/platform/plugins/cloudflare/mcp/package.json +18 -0
  74. package/payload/platform/plugins/cloudflare/references/setup-guide.md +110 -0
  75. package/payload/platform/plugins/contacts/PLUGIN.md +18 -0
  76. package/payload/platform/plugins/contacts/mcp/dist/index.d.ts +2 -0
  77. package/payload/platform/plugins/contacts/mcp/dist/index.d.ts.map +1 -0
  78. package/payload/platform/plugins/contacts/mcp/dist/index.js +182 -0
  79. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -0
  80. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.d.ts +5 -0
  81. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.d.ts.map +1 -0
  82. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js +34 -0
  83. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js.map +1 -0
  84. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +19 -0
  85. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -0
  86. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +68 -0
  87. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -0
  88. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts +22 -0
  89. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts.map +1 -0
  90. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js +46 -0
  91. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js.map +1 -0
  92. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +20 -0
  93. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -0
  94. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +56 -0
  95. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -0
  96. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts +13 -0
  97. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts.map +1 -0
  98. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js +54 -0
  99. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js.map +1 -0
  100. package/payload/platform/plugins/contacts/mcp/package.json +19 -0
  101. package/payload/platform/plugins/documents/PLUGIN.md +12 -0
  102. package/payload/platform/plugins/documents/mcp/dist/index.d.ts +2 -0
  103. package/payload/platform/plugins/documents/mcp/dist/index.d.ts.map +1 -0
  104. package/payload/platform/plugins/documents/mcp/dist/index.js +82 -0
  105. package/payload/platform/plugins/documents/mcp/dist/index.js.map +1 -0
  106. package/payload/platform/plugins/documents/mcp/package.json +20 -0
  107. package/payload/platform/plugins/memory/PLUGIN.md +17 -0
  108. package/payload/platform/plugins/memory/mcp/dist/index.d.ts +2 -0
  109. package/payload/platform/plugins/memory/mcp/dist/index.d.ts.map +1 -0
  110. package/payload/platform/plugins/memory/mcp/dist/index.js +164 -0
  111. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -0
  112. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts +3 -0
  113. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts.map +1 -0
  114. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js +29 -0
  115. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js.map +1 -0
  116. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +5 -0
  117. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts.map +1 -0
  118. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +34 -0
  119. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js.map +1 -0
  120. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +8 -0
  121. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -0
  122. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +71 -0
  123. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -0
  124. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts +24 -0
  125. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -0
  126. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +125 -0
  127. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -0
  128. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +18 -0
  129. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -0
  130. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +56 -0
  131. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -0
  132. package/payload/platform/plugins/memory/mcp/package.json +19 -0
  133. package/payload/platform/plugins/sales/PLUGIN.md +65 -0
  134. package/payload/platform/plugins/sales/references/close-tracking.md +76 -0
  135. package/payload/platform/plugins/sales/references/closing-framework.md +108 -0
  136. package/payload/platform/plugins/sales/references/comparisons.md +99 -0
  137. package/payload/platform/plugins/sales/references/competitive-positioning.md +51 -0
  138. package/payload/platform/plugins/sales/references/faq.md +62 -0
  139. package/payload/platform/plugins/sales/references/objection-handling.md +157 -0
  140. package/payload/platform/plugins/sales/references/pricing.md +71 -0
  141. package/payload/platform/plugins/sales/references/waitlist.md +23 -0
  142. package/payload/platform/plugins/scheduling/PLUGIN.md +12 -0
  143. package/payload/platform/plugins/scheduling/mcp/dist/index.d.ts +2 -0
  144. package/payload/platform/plugins/scheduling/mcp/dist/index.d.ts.map +1 -0
  145. package/payload/platform/plugins/scheduling/mcp/dist/index.js +13 -0
  146. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -0
  147. package/payload/platform/plugins/scheduling/mcp/package.json +18 -0
  148. package/payload/platform/plugins/telegram/PLUGIN.md +31 -0
  149. package/payload/platform/plugins/telegram/mcp/dist/index.d.ts +2 -0
  150. package/payload/platform/plugins/telegram/mcp/dist/index.d.ts.map +1 -0
  151. package/payload/platform/plugins/telegram/mcp/dist/index.js +101 -0
  152. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -0
  153. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts +27 -0
  154. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts.map +1 -0
  155. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js +41 -0
  156. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js.map +1 -0
  157. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts +16 -0
  158. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts.map +1 -0
  159. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js +62 -0
  160. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js.map +1 -0
  161. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts +20 -0
  162. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -0
  163. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +34 -0
  164. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -0
  165. package/payload/platform/plugins/telegram/mcp/package.json +19 -0
  166. package/payload/platform/plugins/telegram/references/setup-guide.md +50 -0
  167. package/payload/platform/plugins/web/PLUGIN.md +12 -0
  168. package/payload/platform/plugins/web/mcp/dist/index.d.ts +2 -0
  169. package/payload/platform/plugins/web/mcp/dist/index.d.ts.map +1 -0
  170. package/payload/platform/plugins/web/mcp/dist/index.js +12 -0
  171. package/payload/platform/plugins/web/mcp/dist/index.js.map +1 -0
  172. package/payload/platform/plugins/web/mcp/package.json +18 -0
  173. package/payload/platform/scripts/seed-neo4j.sh +73 -0
  174. package/payload/platform/scripts/setup.sh +177 -0
  175. package/payload/platform/scripts/start.sh +62 -0
  176. package/payload/platform/templates/account.json +4 -0
  177. package/payload/platform/templates/agents/admin/IDENTITY.md +28 -0
  178. package/payload/platform/templates/agents/admin/SOUL.md +1 -0
  179. package/payload/platform/templates/agents/public/IDENTITY.md +21 -0
  180. package/payload/platform/templates/agents/public/SOUL.md +1 -0
  181. package/payload/platform/tsconfig.base.json +18 -0
@@ -0,0 +1,82 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import QRCode from "qrcode";
5
+ const server = new McpServer({
6
+ name: "maxy-documents",
7
+ version: "0.1.0",
8
+ });
9
+ server.tool("qr-generate", "Generate a QR code from text or a URL. Returns the QR code as a data URI (PNG) or saves to a file path.", {
10
+ data: z.string().describe("The text or URL to encode in the QR code"),
11
+ outputPath: z
12
+ .string()
13
+ .optional()
14
+ .describe("File path to save the PNG. If omitted, returns a data URI."),
15
+ width: z.number().optional().describe("Width in pixels (default 300)"),
16
+ }, async ({ data, outputPath, width }) => {
17
+ try {
18
+ const options = { width: width ?? 300, margin: 2 };
19
+ if (outputPath) {
20
+ await QRCode.toFile(outputPath, data, options);
21
+ return {
22
+ content: [
23
+ {
24
+ type: "text",
25
+ text: `QR code saved to ${outputPath}`,
26
+ },
27
+ ],
28
+ };
29
+ }
30
+ const dataUri = await QRCode.toDataURL(data, options);
31
+ return {
32
+ content: [
33
+ {
34
+ type: "text",
35
+ text: `QR code generated for: ${data}`,
36
+ },
37
+ {
38
+ type: "image",
39
+ data: dataUri.replace(/^data:image\/png;base64,/, ""),
40
+ mimeType: "image/png",
41
+ },
42
+ ],
43
+ };
44
+ }
45
+ catch (err) {
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: `QR generation failed: ${err instanceof Error ? err.message : String(err)}`,
51
+ },
52
+ ],
53
+ isError: true,
54
+ };
55
+ }
56
+ });
57
+ server.tool("document-create-pdf", "Generate a PDF document from markdown or HTML content", {
58
+ content: z.string(),
59
+ format: z.enum(["markdown", "html"]).optional(),
60
+ title: z.string().optional(),
61
+ }, async () => ({
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: "PDF generation is not available in Phase 0. This capability will be added in Phase 1.",
66
+ },
67
+ ],
68
+ }));
69
+ server.tool("document-list", "List documents for an account", {
70
+ accountId: z.string().optional(),
71
+ type: z.string().optional(),
72
+ }, async () => ({
73
+ content: [
74
+ {
75
+ type: "text",
76
+ text: "Document management is not available in Phase 0. This capability will be added in Phase 1.",
77
+ },
78
+ ],
79
+ }));
80
+ const transport = new StdioServerTransport();
81
+ await server.connect(transport);
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@maxy/documents",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "^1.12.1",
13
+ "qrcode": "^1.5.4"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^22.0.0",
17
+ "@types/qrcode": "^1.5.6",
18
+ "typescript": "^5.7.0"
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: memory
3
+ description: "Graph memory plugin. Provides memory-search and memory-write tools for reading from and writing to the Neo4j knowledge graph."
4
+ icon: 🧠
5
+ tools:
6
+ - memory-search
7
+ - memory-write
8
+ - memory-reindex
9
+ always: true
10
+ embed: false
11
+ ---
12
+
13
+ # Memory
14
+
15
+ Provides access to the Neo4j knowledge graph. All agents use memory-search before responding. Write operations are restricted to the admin agent — the public agent is read-only.
16
+
17
+ Tools are available via the `memory` MCP server.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,164 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { memorySearch } from "./tools/memory-search.js";
5
+ import { memoryWrite } from "./tools/memory-write.js";
6
+ import { memoryReindex } from "./tools/memory-reindex.js";
7
+ import { closeDriver } from "./lib/neo4j.js";
8
+ const server = new McpServer({
9
+ name: "maxy-memory",
10
+ version: "0.1.0",
11
+ });
12
+ const readOnly = process.env.READ_ONLY === "true";
13
+ const accountId = process.env.ACCOUNT_ID;
14
+ if (!accountId) {
15
+ throw new Error("ACCOUNT_ID environment variable is required");
16
+ }
17
+ server.tool("memory-search", "Search the knowledge graph using semantic vector search with graph traversal. Returns relevant nodes and their relationships.", {
18
+ query: z.string().describe("Natural language search query"),
19
+ labels: z
20
+ .array(z.string())
21
+ .optional()
22
+ .describe("Filter by node labels (e.g. FAQ, Service, Feature, Comparison, Person)"),
23
+ limit: z
24
+ .number()
25
+ .optional()
26
+ .describe("Maximum number of results (default 10)"),
27
+ expandHops: z
28
+ .number()
29
+ .optional()
30
+ .describe("Graph traversal depth for related nodes (default 1)"),
31
+ }, async ({ query, labels, limit, expandHops }) => {
32
+ try {
33
+ const results = await memorySearch({
34
+ query,
35
+ labels,
36
+ accountId,
37
+ limit,
38
+ expandHops,
39
+ });
40
+ if (results.length === 0) {
41
+ return {
42
+ content: [
43
+ {
44
+ type: "text",
45
+ text: "No results found for this query.",
46
+ },
47
+ ],
48
+ };
49
+ }
50
+ const formatted = results.map((r) => {
51
+ let text = `[${r.labels.join(", ")}] (score: ${r.score.toFixed(3)})\n`;
52
+ for (const [k, v] of Object.entries(r.properties)) {
53
+ text += ` ${k}: ${String(v)}\n`;
54
+ }
55
+ if (r.related.length > 0) {
56
+ text += " Related:\n";
57
+ for (const rel of r.related) {
58
+ const arrow = rel.direction === "outgoing" ? `--[${rel.relationship}]-->` : `<--[${rel.relationship}]--`;
59
+ text += ` ${arrow} [${rel.labels.join(", ")}]`;
60
+ const relProps = Object.entries(rel.properties)
61
+ .filter(([k]) => k !== "embedding" && k !== "accountId")
62
+ .map(([k, v]) => `${k}: ${String(v)}`)
63
+ .join(", ");
64
+ if (relProps)
65
+ text += ` {${relProps}}`;
66
+ text += "\n";
67
+ }
68
+ }
69
+ return text;
70
+ });
71
+ return {
72
+ content: [{ type: "text", text: formatted.join("\n---\n") }],
73
+ };
74
+ }
75
+ catch (err) {
76
+ return {
77
+ content: [
78
+ {
79
+ type: "text",
80
+ text: `Search failed: ${err instanceof Error ? err.message : String(err)}`,
81
+ },
82
+ ],
83
+ isError: true,
84
+ };
85
+ }
86
+ });
87
+ if (!readOnly) {
88
+ server.tool("memory-write", "Create a new node in the knowledge graph with automatic embedding computation.", {
89
+ labels: z
90
+ .array(z.string())
91
+ .describe("Node labels (e.g. ['Person'], ['FAQ'], ['Feature'])"),
92
+ properties: z
93
+ .record(z.string(), z.unknown())
94
+ .describe("Node properties as key-value pairs"),
95
+ relationships: z
96
+ .array(z.object({
97
+ type: z.string().describe("Relationship type (e.g. HAS_PRICING, OFFERS)"),
98
+ direction: z.enum(["outgoing", "incoming"]),
99
+ targetNodeId: z.string().describe("Element ID of the target node"),
100
+ }))
101
+ .optional()
102
+ .describe("Relationships to create with existing nodes"),
103
+ }, async ({ labels, properties, relationships }) => {
104
+ try {
105
+ const result = await memoryWrite({
106
+ labels,
107
+ properties: properties,
108
+ accountId,
109
+ relationships,
110
+ });
111
+ return {
112
+ content: [
113
+ {
114
+ type: "text",
115
+ text: `Node created: [${result.labels.join(", ")}] (ID: ${result.nodeId})`,
116
+ },
117
+ ],
118
+ };
119
+ }
120
+ catch (err) {
121
+ return {
122
+ content: [
123
+ {
124
+ type: "text",
125
+ text: `Write failed: ${err instanceof Error ? err.message : String(err)}`,
126
+ },
127
+ ],
128
+ isError: true,
129
+ };
130
+ }
131
+ });
132
+ server.tool("memory-reindex", "Rebuild vector embeddings for all nodes missing embeddings. Run after seeding or bulk updates.", {}, async () => {
133
+ try {
134
+ const result = await memoryReindex(accountId);
135
+ return {
136
+ content: [
137
+ {
138
+ type: "text",
139
+ text: `Reindex complete: ${result.nodesProcessed} processed, ${result.nodesSkipped} skipped.${result.errors.length > 0 ? `\nErrors: ${result.errors.join("; ")}` : ""}`,
140
+ },
141
+ ],
142
+ };
143
+ }
144
+ catch (err) {
145
+ return {
146
+ content: [
147
+ {
148
+ type: "text",
149
+ text: `Reindex failed: ${err instanceof Error ? err.message : String(err)}`,
150
+ },
151
+ ],
152
+ isError: true,
153
+ };
154
+ }
155
+ });
156
+ }
157
+ // Cleanup on exit
158
+ process.on("SIGINT", async () => {
159
+ await closeDriver();
160
+ process.exit(0);
161
+ });
162
+ const transport = new StdioServerTransport();
163
+ await server.connect(transport);
164
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function embed(text: string): Promise<number[]>;
2
+ export declare function embedBatch(texts: string[]): Promise<number[][]>;
3
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAGA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAc3D;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAcrE"}
@@ -0,0 +1,29 @@
1
+ const OLLAMA_URL = process.env.OLLAMA_URL ?? "http://localhost:11434";
2
+ const EMBED_MODEL = process.env.EMBED_MODEL ?? "nomic-embed-text";
3
+ export async function embed(text) {
4
+ const res = await fetch(`${OLLAMA_URL}/api/embed`, {
5
+ method: "POST",
6
+ headers: { "Content-Type": "application/json" },
7
+ body: JSON.stringify({ model: EMBED_MODEL, input: text }),
8
+ });
9
+ if (!res.ok) {
10
+ const body = await res.text();
11
+ throw new Error(`Ollama embedding failed (${res.status}): ${body}`);
12
+ }
13
+ const data = (await res.json());
14
+ return data.embeddings[0];
15
+ }
16
+ export async function embedBatch(texts) {
17
+ const res = await fetch(`${OLLAMA_URL}/api/embed`, {
18
+ method: "POST",
19
+ headers: { "Content-Type": "application/json" },
20
+ body: JSON.stringify({ model: EMBED_MODEL, input: texts }),
21
+ });
22
+ if (!res.ok) {
23
+ const body = await res.text();
24
+ throw new Error(`Ollama batch embedding failed (${res.status}): ${body}`);
25
+ }
26
+ const data = (await res.json());
27
+ return data.embeddings;
28
+ }
29
+ //# sourceMappingURL=embeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,wBAAwB,CAAC;AACtE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,kBAAkB,CAAC;AAElE,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,YAAY,EAAE;QACjD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;KAC1D,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA+B,CAAC;IAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAe;IAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,YAAY,EAAE;QACjD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;KAC3D,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA+B,CAAC;IAC9D,OAAO,IAAI,CAAC,UAAU,CAAC;AACzB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Driver, Session } from "neo4j-driver";
2
+ export declare function getDriver(): Driver;
3
+ export declare function getSession(): Session;
4
+ export declare function closeDriver(): Promise<void>;
5
+ //# sourceMappingURL=neo4j.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neo4j.d.ts","sourceRoot":"","sources":["../../src/lib/neo4j.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAuBtD,wBAAgB,SAAS,IAAI,MAAM,CAQlC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAKjD"}
@@ -0,0 +1,34 @@
1
+ import neo4j from "neo4j-driver";
2
+ import { readFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ let driver = null;
5
+ function readPassword() {
6
+ if (process.env.NEO4J_PASSWORD)
7
+ return process.env.NEO4J_PASSWORD;
8
+ const passwordFile = resolve(process.env.PLATFORM_ROOT ?? resolve(import.meta.dirname, "../../../.."), "config/.neo4j-password");
9
+ try {
10
+ return readFileSync(passwordFile, "utf-8").trim();
11
+ }
12
+ catch {
13
+ throw new Error(`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`);
14
+ }
15
+ }
16
+ export function getDriver() {
17
+ if (!driver) {
18
+ const uri = process.env.NEO4J_URI ?? "bolt://localhost:7687";
19
+ const user = process.env.NEO4J_USER ?? "neo4j";
20
+ const password = readPassword();
21
+ driver = neo4j.driver(uri, neo4j.auth.basic(user, password));
22
+ }
23
+ return driver;
24
+ }
25
+ export function getSession() {
26
+ return getDriver().session();
27
+ }
28
+ export async function closeDriver() {
29
+ if (driver) {
30
+ await driver.close();
31
+ driver = null;
32
+ }
33
+ }
34
+ //# sourceMappingURL=neo4j.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neo4j.js","sourceRoot":"","sources":["../../src/lib/neo4j.ts"],"names":[],"mappings":"AAAA,OAAO,KAA0B,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAElE,MAAM,YAAY,GAAG,OAAO,CAC1B,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EACxE,wBAAwB,CACzB,CAAC;IAEF,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,yCAAyC,YAAY,gCAAgC,CACtF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,uBAAuB,CAAC;QAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC;QAC/C,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ interface ReindexResult {
2
+ nodesProcessed: number;
3
+ nodesSkipped: number;
4
+ errors: string[];
5
+ }
6
+ export declare function memoryReindex(accountId: string): Promise<ReindexResult>;
7
+ export {};
8
+ //# sourceMappingURL=memory-reindex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-reindex.d.ts","sourceRoot":"","sources":["../../src/tools/memory-reindex.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CA4ExB"}
@@ -0,0 +1,71 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { embedBatch } from "../lib/embeddings.js";
3
+ export async function memoryReindex(accountId) {
4
+ const session = getSession();
5
+ const batchSize = 50;
6
+ let nodesProcessed = 0;
7
+ let nodesSkipped = 0;
8
+ const errors = [];
9
+ try {
10
+ // Find all nodes missing embeddings or with stale embeddings
11
+ const countResult = await session.run(`MATCH (n) WHERE n.accountId = $accountId AND n.embedding IS NULL RETURN count(n) AS total`, { accountId });
12
+ const total = countResult.records[0].get("total").toNumber();
13
+ if (total === 0) {
14
+ return { nodesProcessed: 0, nodesSkipped: 0, errors: [] };
15
+ }
16
+ // Process in batches
17
+ let offset = 0;
18
+ while (offset < total) {
19
+ const batchResult = await session.run(`MATCH (n)
20
+ WHERE n.accountId = $accountId AND n.embedding IS NULL
21
+ RETURN elementId(n) AS nodeId, labels(n) AS nodeLabels, properties(n) AS props
22
+ SKIP $offset LIMIT $batchSize`, { accountId, offset, batchSize });
23
+ if (batchResult.records.length === 0)
24
+ break;
25
+ const texts = [];
26
+ const nodeIds = [];
27
+ for (const record of batchResult.records) {
28
+ const nodeId = record.get("nodeId");
29
+ const labels = record.get("nodeLabels");
30
+ const props = record.get("props");
31
+ const text = buildTextForEmbedding(labels, props);
32
+ if (text.length < 5) {
33
+ nodesSkipped++;
34
+ continue;
35
+ }
36
+ texts.push(text);
37
+ nodeIds.push(nodeId);
38
+ }
39
+ if (texts.length > 0) {
40
+ try {
41
+ const embeddings = await embedBatch(texts);
42
+ for (let i = 0; i < nodeIds.length; i++) {
43
+ await session.run(`MATCH (n) WHERE elementId(n) = $nodeId SET n.embedding = $embedding`, { nodeId: nodeIds[i], embedding: embeddings[i] });
44
+ }
45
+ nodesProcessed += texts.length;
46
+ }
47
+ catch (err) {
48
+ errors.push(`Batch at offset ${offset}: ${err instanceof Error ? err.message : String(err)}`);
49
+ }
50
+ }
51
+ offset += batchSize;
52
+ }
53
+ return { nodesProcessed, nodesSkipped, errors };
54
+ }
55
+ finally {
56
+ await session.close();
57
+ }
58
+ }
59
+ function buildTextForEmbedding(labels, properties) {
60
+ const parts = [`[${labels.join(", ")}]`];
61
+ for (const [key, value] of Object.entries(properties)) {
62
+ if (value !== null &&
63
+ value !== undefined &&
64
+ key !== "embedding" &&
65
+ key !== "accountId") {
66
+ parts.push(`${key}: ${String(value)}`);
67
+ }
68
+ }
69
+ return parts.join(" | ");
70
+ }
71
+ //# sourceMappingURL=memory-reindex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-reindex.js","sourceRoot":"","sources":["../../src/tools/memory-reindex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAQlD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAiB;IAEjB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,EAAE,CAAC;IACrB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC;QACH,6DAA6D;QAC7D,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC,2FAA2F,EAC3F,EAAE,SAAS,EAAE,CACd,CAAC;QACF,MAAM,KAAK,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAA4B,CAAC,QAAQ,EAAE,CAAC;QAEzF,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC5D,CAAC;QAED,qBAAqB;QACrB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,KAAK,EAAE,CAAC;YACtB,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC;;;uCAG+B,EAC/B,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CACjC,CAAC;YAEF,IAAI,WAAW,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM;YAE5C,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAa,EAAE,CAAC;YAE7B,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACzC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAW,CAAC;gBAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAa,CAAC;gBACpD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAA4B,CAAC;gBAE7D,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBAClD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,YAAY,EAAE,CAAC;oBACf,SAAS;gBACX,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YAED,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;oBAE3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBACxC,MAAM,OAAO,CAAC,GAAG,CACf,qEAAqE,EACrE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CACjD,CAAC;oBACJ,CAAC;oBAED,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC;gBACjC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,IAAI,CACT,mBAAmB,MAAM,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACjF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,MAAM,IAAI,SAAS,CAAC;QACtB,CAAC;QAED,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAgB,EAChB,UAAmC;IAEnC,MAAM,KAAK,GAAa,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEnD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,IACE,KAAK,KAAK,IAAI;YACd,KAAK,KAAK,SAAS;YACnB,GAAG,KAAK,WAAW;YACnB,GAAG,KAAK,WAAW,EACnB,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,24 @@
1
+ interface SearchParams {
2
+ query: string;
3
+ labels?: string[];
4
+ accountId?: string;
5
+ limit?: number;
6
+ expandHops?: number;
7
+ }
8
+ interface SearchResult {
9
+ nodeId: string;
10
+ labels: string[];
11
+ properties: Record<string, unknown>;
12
+ score: number;
13
+ related: Array<{
14
+ relationship: string;
15
+ direction: string;
16
+ labels: string[];
17
+ properties: Record<string, unknown>;
18
+ }>;
19
+ }
20
+ /** Clear the index cache — call after schema changes. */
21
+ export declare function clearIndexCache(): void;
22
+ export declare function memorySearch(params: SearchParams): Promise<SearchResult[]>;
23
+ export {};
24
+ //# sourceMappingURL=memory-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-search.d.ts","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"AAGA,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC,CAAC;CACJ;AAiCD,yDAAyD;AACzD,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA6FhF"}
@@ -0,0 +1,125 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { embed } from "../lib/embeddings.js";
3
+ // Cached vector index map — discovered from Neo4j at first query.
4
+ let indexCache = null;
5
+ /**
6
+ * Discover all vector indexes from Neo4j.
7
+ * Returns a map of label → index name.
8
+ */
9
+ async function discoverIndexes() {
10
+ if (indexCache)
11
+ return indexCache;
12
+ const session = getSession();
13
+ try {
14
+ const result = await session.run(`SHOW INDEXES WHERE type = 'VECTOR' YIELD name, labelsOrTypes RETURN name, labelsOrTypes`);
15
+ indexCache = new Map();
16
+ for (const record of result.records) {
17
+ const name = record.get("name");
18
+ const labels = record.get("labelsOrTypes");
19
+ for (const label of labels) {
20
+ indexCache.set(label, name);
21
+ }
22
+ }
23
+ return indexCache;
24
+ }
25
+ finally {
26
+ await session.close();
27
+ }
28
+ }
29
+ /** Clear the index cache — call after schema changes. */
30
+ export function clearIndexCache() {
31
+ indexCache = null;
32
+ }
33
+ export async function memorySearch(params) {
34
+ const { query: queryText, labels, accountId, limit = 10, expandHops = 1, } = params;
35
+ const queryEmbedding = await embed(queryText);
36
+ const labelToIndex = await discoverIndexes();
37
+ const session = getSession();
38
+ try {
39
+ // Determine which vector indexes to query
40
+ let indexesToQuery;
41
+ if (labels && labels.length > 0) {
42
+ indexesToQuery = labels
43
+ .map((l) => labelToIndex.get(l))
44
+ .filter((idx) => idx !== undefined);
45
+ if (indexesToQuery.length === 0) {
46
+ return [];
47
+ }
48
+ }
49
+ else {
50
+ // Query all discovered vector indexes
51
+ indexesToQuery = [...new Set(labelToIndex.values())];
52
+ }
53
+ const allResults = [];
54
+ for (const indexName of indexesToQuery) {
55
+ const vectorQuery = `
56
+ CALL db.index.vector.queryNodes($indexName, $limit, $embedding)
57
+ YIELD node, score
58
+ WHERE node.accountId = $accountId
59
+ RETURN node, score, labels(node) AS nodeLabels, elementId(node) AS nodeId
60
+ ORDER BY score DESC
61
+ LIMIT $limit
62
+ `;
63
+ const vectorResult = await session.run(vectorQuery, {
64
+ indexName,
65
+ embedding: queryEmbedding,
66
+ limit,
67
+ accountId,
68
+ });
69
+ for (const record of vectorResult.records) {
70
+ const node = record.get("node");
71
+ const score = record.get("score");
72
+ const nodeLabels = record.get("nodeLabels");
73
+ const nodeId = record.get("nodeId");
74
+ const result = {
75
+ nodeId,
76
+ labels: nodeLabels,
77
+ properties: nodeToPlain(node.properties),
78
+ score: typeof score === "number" ? score : Number(score),
79
+ related: [],
80
+ };
81
+ if (expandHops > 0) {
82
+ const expandQuery = `
83
+ MATCH (n)-[r]-(related)
84
+ WHERE elementId(n) = $nodeId
85
+ RETURN type(r) AS relType,
86
+ CASE WHEN startNode(r) = n THEN 'outgoing' ELSE 'incoming' END AS direction,
87
+ labels(related) AS relatedLabels,
88
+ related
89
+ LIMIT 20
90
+ `;
91
+ const expandResult = await session.run(expandQuery, { nodeId });
92
+ for (const relRecord of expandResult.records) {
93
+ result.related.push({
94
+ relationship: relRecord.get("relType"),
95
+ direction: relRecord.get("direction"),
96
+ labels: relRecord.get("relatedLabels"),
97
+ properties: nodeToPlain(relRecord.get("related").properties),
98
+ });
99
+ }
100
+ }
101
+ allResults.push(result);
102
+ }
103
+ }
104
+ allResults.sort((a, b) => b.score - a.score);
105
+ return allResults.slice(0, limit);
106
+ }
107
+ finally {
108
+ await session.close();
109
+ }
110
+ }
111
+ function nodeToPlain(properties) {
112
+ const plain = {};
113
+ for (const [key, value] of Object.entries(properties)) {
114
+ if (key === "embedding")
115
+ continue;
116
+ if (value && typeof value === "object" && "toNumber" in value) {
117
+ plain[key] = value.toNumber();
118
+ }
119
+ else {
120
+ plain[key] = value;
121
+ }
122
+ }
123
+ return plain;
124
+ }
125
+ //# sourceMappingURL=memory-search.js.map