@rubytech/create-realagent 1.0.627 → 1.0.630
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/dist/index.js +34 -0
- package/package.json +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.d.ts +26 -0
- package/payload/platform/lib/graph-mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/index.js +193 -0
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -0
- package/payload/platform/lib/graph-mcp/src/index.ts +225 -0
- package/payload/platform/lib/graph-mcp/tsconfig.json +8 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/cloudflare/scripts/_stream-log.sh +124 -0
- package/payload/platform/plugins/cloudflare/scripts/reset-tunnel.sh +45 -3
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +151 -10
- package/payload/platform/plugins/docs/references/memory-guide.md +8 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +2 -0
- package/payload/platform/plugins/memory/mcp/scripts/graph/accept.sh +129 -0
- package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +59 -0
- package/payload/platform/plugins/memory/references/graph-primitives.md +195 -0
- package/payload/server/public/assets/admin-DirN63aF.js +352 -0
- package/payload/server/public/assets/public-Cizdj15i.js +5 -0
- package/payload/server/public/assets/useVoiceRecorder-DIV9KAk_.css +1 -0
- package/payload/server/public/assets/{useVoiceRecorder-CiYPZu3g.js → useVoiceRecorder-tbj4tUsl.js} +1 -1
- package/payload/server/public/index.html +3 -3
- package/payload/server/public/public.html +3 -3
- package/payload/server/server.js +481 -102
- package/payload/server/public/assets/admin-BxVuKRJZ.js +0 -352
- package/payload/server/public/assets/public-Bgm9WQFZ.js +0 -5
- package/payload/server/public/assets/useVoiceRecorder-BORuG_su.css +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<!-- Injected into admin system prompt by claude-agent.ts when agentType === "admin". -->
|
|
2
|
+
<!-- Consumed by the upstream mcp-neo4j-cypher server via `maxy-graph_read_neo4j_cypher`. -->
|
|
3
|
+
<!-- Source of truth for node labels and properties: platform/neo4j/schema.cypher + plugins/memory/references/schema-*.md. -->
|
|
4
|
+
|
|
5
|
+
# Graph interrogation (read-only Cypher cookbook)
|
|
6
|
+
|
|
7
|
+
When a user asks a relational question about their own graph — *"list all my
|
|
8
|
+
people", "how many tasks do I have", "find the person with email X", "what's
|
|
9
|
+
linked to this business", "show me the 20 most recently created nodes" — use
|
|
10
|
+
`maxy-graph_read_neo4j_cypher` or `maxy-graph_get_neo4j_schema`, not
|
|
11
|
+
`memory-search`. Vector search is for "things like this"; Cypher is for "the
|
|
12
|
+
exact set where".
|
|
13
|
+
|
|
14
|
+
The connected Neo4j instance contains only this brand's data (per-brand
|
|
15
|
+
instance architecture — see `.docs/neo4j.md`). You never need an account
|
|
16
|
+
filter in the query.
|
|
17
|
+
|
|
18
|
+
## Non-negotiable: never return raw nodes
|
|
19
|
+
|
|
20
|
+
`RETURN n` dumps every property, including the 768-dim `embedding` float
|
|
21
|
+
array. This blows the context budget on the first row. **Always enumerate the
|
|
22
|
+
properties you want.**
|
|
23
|
+
|
|
24
|
+
Wrong: `MATCH (n:Person) RETURN n LIMIT 20`
|
|
25
|
+
Right: `MATCH (n:Person) RETURN elementId(n) AS id, n.givenName, n.familyName, n.email, n.telephone LIMIT 20`
|
|
26
|
+
|
|
27
|
+
Apply this convention to every query. Only project the fields you need to
|
|
28
|
+
answer the question. When in doubt, exclude `embedding`, `embeddingText`, and
|
|
29
|
+
any property whose name ends in `_vector`.
|
|
30
|
+
|
|
31
|
+
## Cookbook
|
|
32
|
+
|
|
33
|
+
Parameterise results with `ORDER BY` and `LIMIT` every time — even an
|
|
34
|
+
"inventory" query should bound itself. Default limit: 50.
|
|
35
|
+
|
|
36
|
+
### Enumerate
|
|
37
|
+
|
|
38
|
+
All nodes, grouped by label, with a human-readable name:
|
|
39
|
+
|
|
40
|
+
```cypher
|
|
41
|
+
MATCH (n)
|
|
42
|
+
RETURN labels(n)[0] AS type,
|
|
43
|
+
coalesce(n.name, n.title, n.givenName + ' ' + n.familyName, n.email, '(unnamed)') AS name,
|
|
44
|
+
elementId(n) AS id
|
|
45
|
+
ORDER BY type, name
|
|
46
|
+
LIMIT 200
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
One label only:
|
|
50
|
+
|
|
51
|
+
```cypher
|
|
52
|
+
MATCH (n:Person)
|
|
53
|
+
RETURN elementId(n) AS id, n.givenName, n.familyName, n.email, n.telephone
|
|
54
|
+
ORDER BY n.familyName, n.givenName
|
|
55
|
+
LIMIT 100
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Count
|
|
59
|
+
|
|
60
|
+
Total across the graph:
|
|
61
|
+
|
|
62
|
+
```cypher
|
|
63
|
+
MATCH (n)
|
|
64
|
+
RETURN count(n) AS total
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
By label:
|
|
68
|
+
|
|
69
|
+
```cypher
|
|
70
|
+
MATCH (n)
|
|
71
|
+
RETURN labels(n)[0] AS type, count(*) AS n
|
|
72
|
+
ORDER BY n DESC
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Find
|
|
76
|
+
|
|
77
|
+
By exact email:
|
|
78
|
+
|
|
79
|
+
```cypher
|
|
80
|
+
MATCH (p:Person {email: $email})
|
|
81
|
+
RETURN elementId(p) AS id, p.givenName, p.familyName, p.telephone, p.status
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Partial name, case-insensitive:
|
|
85
|
+
|
|
86
|
+
```cypher
|
|
87
|
+
MATCH (p:Person)
|
|
88
|
+
WHERE toLower(p.givenName) CONTAINS toLower($q)
|
|
89
|
+
OR toLower(p.familyName) CONTAINS toLower($q)
|
|
90
|
+
RETURN elementId(p) AS id, p.givenName, p.familyName, p.email
|
|
91
|
+
LIMIT 20
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Neighbours
|
|
95
|
+
|
|
96
|
+
What is linked to a node (1 hop out, undirected):
|
|
97
|
+
|
|
98
|
+
```cypher
|
|
99
|
+
MATCH (n)-[r]-(m)
|
|
100
|
+
WHERE elementId(n) = $id
|
|
101
|
+
RETURN type(r) AS rel,
|
|
102
|
+
labels(m)[0] AS neighbourType,
|
|
103
|
+
coalesce(m.name, m.title, m.email, '(unnamed)') AS neighbour,
|
|
104
|
+
elementId(m) AS neighbourId
|
|
105
|
+
LIMIT 50
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Recent
|
|
109
|
+
|
|
110
|
+
Most recently created nodes (any label):
|
|
111
|
+
|
|
112
|
+
```cypher
|
|
113
|
+
MATCH (n)
|
|
114
|
+
WHERE n.createdAt IS NOT NULL
|
|
115
|
+
RETURN labels(n)[0] AS type,
|
|
116
|
+
coalesce(n.name, n.title, n.givenName + ' ' + n.familyName, n.email, '(unnamed)') AS name,
|
|
117
|
+
toString(n.createdAt) AS createdAt,
|
|
118
|
+
elementId(n) AS id
|
|
119
|
+
ORDER BY n.createdAt DESC
|
|
120
|
+
LIMIT 20
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Most recently updated:
|
|
124
|
+
|
|
125
|
+
```cypher
|
|
126
|
+
MATCH (n)
|
|
127
|
+
WHERE n.updatedAt IS NOT NULL
|
|
128
|
+
RETURN labels(n)[0] AS type,
|
|
129
|
+
coalesce(n.name, n.title, n.email, '(unnamed)') AS name,
|
|
130
|
+
toString(n.updatedAt) AS updatedAt,
|
|
131
|
+
elementId(n) AS id
|
|
132
|
+
ORDER BY n.updatedAt DESC
|
|
133
|
+
LIMIT 20
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Schema
|
|
137
|
+
|
|
138
|
+
All labels present in the graph:
|
|
139
|
+
|
|
140
|
+
```cypher
|
|
141
|
+
CALL db.labels() YIELD label RETURN label ORDER BY label
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
All relationship types:
|
|
145
|
+
|
|
146
|
+
```cypher
|
|
147
|
+
CALL db.relationshipTypes() YIELD relationshipType RETURN relationshipType ORDER BY relationshipType
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Or use `maxy-graph_get_neo4j_schema` for a richer one-shot structural summary.
|
|
151
|
+
|
|
152
|
+
### Fulltext
|
|
153
|
+
|
|
154
|
+
Use the `knowledge_fulltext` index for keyword-style search across
|
|
155
|
+
KnowledgeDocument / Section / Chunk content:
|
|
156
|
+
|
|
157
|
+
```cypher
|
|
158
|
+
CALL db.index.fulltext.queryNodes('knowledge_fulltext', $query)
|
|
159
|
+
YIELD node, score
|
|
160
|
+
WHERE score > 0.5
|
|
161
|
+
RETURN labels(node)[0] AS type,
|
|
162
|
+
coalesce(node.name, node.title, node.heading, '(unnamed)') AS name,
|
|
163
|
+
score,
|
|
164
|
+
elementId(node) AS id
|
|
165
|
+
LIMIT 20
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Filter by status or category
|
|
169
|
+
|
|
170
|
+
Events that are cancelled:
|
|
171
|
+
|
|
172
|
+
```cypher
|
|
173
|
+
MATCH (e:Event {status: 'cancelled'})
|
|
174
|
+
RETURN elementId(e) AS id, e.name, toString(e.startDate) AS start
|
|
175
|
+
ORDER BY e.startDate DESC
|
|
176
|
+
LIMIT 50
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Tasks by status:
|
|
180
|
+
|
|
181
|
+
```cypher
|
|
182
|
+
MATCH (t:Task {status: $status})
|
|
183
|
+
RETURN elementId(t) AS id, t.title, toString(t.createdAt) AS created, t.priority
|
|
184
|
+
ORDER BY t.createdAt DESC
|
|
185
|
+
LIMIT 50
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## When to switch back to memory-search
|
|
189
|
+
|
|
190
|
+
- "Things similar to X" → `memory-search` (vector + BM25 hybrid)
|
|
191
|
+
- "Candidates to rank by criterion Y" → `memory-rank`
|
|
192
|
+
- "Conversations where we discussed Z" → `conversation-search`
|
|
193
|
+
|
|
194
|
+
Cypher is for relational certainty. Vector search is for similarity. They
|
|
195
|
+
answer different questions; don't use one to fake the other.
|