@rubytech/create-realagent-code 0.1.116 → 0.1.118

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 (90) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +104 -0
  3. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  4. package/payload/platform/plugins/admin/PLUGIN.md +1 -0
  5. package/payload/platform/plugins/aeo/.claude-plugin/plugin.json +17 -0
  6. package/payload/platform/plugins/aeo/PLUGIN.md +81 -0
  7. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.d.ts +2 -0
  8. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.d.ts.map +1 -0
  9. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.js +121 -0
  10. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.js.map +1 -0
  11. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.d.ts +2 -0
  12. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.d.ts.map +1 -0
  13. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.js +129 -0
  14. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.js.map +1 -0
  15. package/payload/platform/plugins/aeo/mcp/dist/index.d.ts +2 -0
  16. package/payload/platform/plugins/aeo/mcp/dist/index.d.ts.map +1 -0
  17. package/payload/platform/plugins/aeo/mcp/dist/index.js +171 -0
  18. package/payload/platform/plugins/aeo/mcp/dist/index.js.map +1 -0
  19. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.d.ts +27 -0
  20. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.d.ts.map +1 -0
  21. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.js +274 -0
  22. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.js.map +1 -0
  23. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.d.ts +5 -0
  24. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.d.ts.map +1 -0
  25. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.js +38 -0
  26. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.js.map +1 -0
  27. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.d.ts +48 -0
  28. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.d.ts.map +1 -0
  29. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.js +254 -0
  30. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.js.map +1 -0
  31. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.d.ts +25 -0
  32. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.d.ts.map +1 -0
  33. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.js +78 -0
  34. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.js.map +1 -0
  35. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.d.ts +18 -0
  36. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.d.ts.map +1 -0
  37. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.js +56 -0
  38. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.js.map +1 -0
  39. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts +37 -0
  40. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts.map +1 -0
  41. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js +94 -0
  42. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js.map +1 -0
  43. package/payload/platform/plugins/aeo/mcp/package.json +22 -0
  44. package/payload/platform/plugins/aeo/mcp/vitest.config.ts +9 -0
  45. package/payload/platform/plugins/aeo/skills/structured-answer/SKILL.md +53 -0
  46. package/payload/platform/plugins/docs/PLUGIN.md +1 -0
  47. package/payload/platform/plugins/docs/references/admin-session.md +1 -1
  48. package/payload/platform/plugins/docs/references/aeo.md +87 -0
  49. package/payload/platform/plugins/docs/references/deployment.md +1 -1
  50. package/payload/platform/plugins/email/PLUGIN.md +6 -0
  51. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +180 -0
  52. package/payload/platform/plugins/memory/mcp/dist/index.js +5 -0
  53. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  54. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.d.ts +2 -0
  55. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.d.ts.map +1 -0
  56. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js +62 -0
  57. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js.map +1 -0
  58. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.d.ts +2 -0
  59. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.d.ts.map +1 -0
  60. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js +62 -0
  61. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js.map +1 -0
  62. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts +18 -0
  63. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts.map +1 -0
  64. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js +29 -0
  65. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js.map +1 -0
  66. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +2 -0
  67. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
  68. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +1 -1
  69. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -1
  70. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +3 -0
  71. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
  72. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +9 -1
  73. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  74. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  75. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +8 -0
  76. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  77. package/payload/platform/plugins/memory/mcp/vitest.config.ts +4 -0
  78. package/payload/platform/plugins/memory/references/schema-base.md +5 -1
  79. package/payload/platform/scripts/smoke-boot-services.sh +30 -2
  80. package/payload/platform/templates/specialists/agents/signal-detector.md +1 -1
  81. package/payload/server/public/assets/{admin-DloKrK2i.js → admin-D6IfAzYY.js} +1 -1
  82. package/payload/server/public/assets/{data-NMvGx6jm.js → data-BGbQyufe.js} +1 -1
  83. package/payload/server/public/assets/{graph-CN60KyTy.js → graph-D-1lRTeL.js} +1 -1
  84. package/payload/server/public/assets/{graph-labels-h39S93Xo.js → graph-labels-BRXJHNYE.js} +1 -1
  85. package/payload/server/public/assets/{page-B0iMmY6t.js → page-B4oirCvn.js} +1 -1
  86. package/payload/server/public/assets/{page-CFRU-BdJ.js → page-FmJ7PIYx.js} +1 -1
  87. package/payload/server/public/data.html +3 -3
  88. package/payload/server/public/graph.html +3 -3
  89. package/payload/server/public/index.html +4 -4
  90. package/payload/server/server.js +14 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Maps Neo4j node labels to schema.org types and builds JSON-LD payloads
3
+ * suitable for inline `<script type="application/ld+json">` blocks on
4
+ * rendered pages.
5
+ *
6
+ * Coverage matches Task 354 spec §1 — the seven page types that the
7
+ * platform's typed nodes cover natively. Labels outside this set fall
8
+ * through to a generic `schema:Thing` projection; callers should treat
9
+ * a generic result as a doc gap, not a success.
10
+ *
11
+ * The mapper is deliberately strict: every emitted JSON-LD object names
12
+ * `@context` and `@type` and carries `@id` when an `elementId` is
13
+ * available. Missing required properties for the chosen type produce a
14
+ * `MissingPropertyError`; callers surface this rather than emitting an
15
+ * invalid block.
16
+ */
17
+ export class MissingPropertyError extends Error {
18
+ schemaType;
19
+ missing;
20
+ constructor(schemaType, missing) {
21
+ super(`JSON-LD ${schemaType} requires ${missing.join(", ")} but received none`);
22
+ this.schemaType = schemaType;
23
+ this.missing = missing;
24
+ this.name = "MissingPropertyError";
25
+ }
26
+ }
27
+ /**
28
+ * Label-to-schema.org-type resolution.
29
+ *
30
+ * - `LocalBusiness` keeps its own schema type (it's a schema.org subtype
31
+ * of `Organization`, but is more specific and SEO-relevant when set).
32
+ * - `Article` covers the platform's narrative `CreativeWork` label when
33
+ * it has article-shaped fields (`headline` or `title`).
34
+ * - `FAQPage` is recognised by the `FAQPage` label OR a `Question`
35
+ * collection — the caller picks.
36
+ * - `RealEstateListing` is the schema.org subtype of `Product` used by
37
+ * estate-agent verticals.
38
+ */
39
+ const LABEL_TO_SCHEMA_TYPE = {
40
+ Organization: "Organization",
41
+ LocalBusiness: "LocalBusiness",
42
+ Person: "Person",
43
+ Service: "Service",
44
+ Product: "Product",
45
+ CreativeWork: "Article",
46
+ Article: "Article",
47
+ FAQPage: "FAQPage",
48
+ RealEstateListing: "RealEstateListing",
49
+ Listing: "RealEstateListing",
50
+ Event: "Event",
51
+ };
52
+ export function resolveSchemaType(label) {
53
+ return LABEL_TO_SCHEMA_TYPE[label] ?? "Thing";
54
+ }
55
+ function readStr(v) {
56
+ if (typeof v !== "string")
57
+ return undefined;
58
+ const trimmed = v.trim();
59
+ return trimmed.length > 0 ? trimmed : undefined;
60
+ }
61
+ function readNum(v) {
62
+ if (typeof v === "number" && Number.isFinite(v))
63
+ return v;
64
+ if (typeof v === "string" && v.trim().length > 0) {
65
+ const n = Number(v);
66
+ return Number.isFinite(n) ? n : undefined;
67
+ }
68
+ return undefined;
69
+ }
70
+ const TYPE_SPECS = {
71
+ Organization: {
72
+ required: ["name"],
73
+ rename: { website: "url", phone: "telephone" },
74
+ },
75
+ LocalBusiness: {
76
+ required: ["name"],
77
+ rename: { website: "url", phone: "telephone" },
78
+ enrich: (props, out) => {
79
+ const street = readStr(props.streetAddress);
80
+ const locality = readStr(props.addressLocality);
81
+ const postalCode = readStr(props.postalCode);
82
+ if (street || locality || postalCode) {
83
+ out.address = {
84
+ "@type": "PostalAddress",
85
+ ...(street ? { streetAddress: street } : {}),
86
+ ...(locality ? { addressLocality: locality } : {}),
87
+ ...(postalCode ? { postalCode } : {}),
88
+ };
89
+ }
90
+ },
91
+ },
92
+ Person: {
93
+ required: ["givenName", "familyName"],
94
+ rename: { phone: "telephone" },
95
+ enrich: (props, out) => {
96
+ const given = readStr(props.givenName);
97
+ const family = readStr(props.familyName);
98
+ if (given && family)
99
+ out.name = `${given} ${family}`;
100
+ },
101
+ },
102
+ Service: {
103
+ required: ["name"],
104
+ enrich: (props, out) => {
105
+ const price = readNum(props.price);
106
+ const currency = readStr(props.priceCurrency);
107
+ if (price !== undefined) {
108
+ out.offers = {
109
+ "@type": "Offer",
110
+ price,
111
+ ...(currency ? { priceCurrency: currency } : { priceCurrency: "GBP" }),
112
+ };
113
+ }
114
+ },
115
+ },
116
+ Product: {
117
+ required: ["name"],
118
+ enrich: (props, out) => {
119
+ const price = readNum(props.price);
120
+ const currency = readStr(props.priceCurrency);
121
+ if (price !== undefined) {
122
+ out.offers = {
123
+ "@type": "Offer",
124
+ price,
125
+ ...(currency ? { priceCurrency: currency } : { priceCurrency: "GBP" }),
126
+ };
127
+ }
128
+ },
129
+ },
130
+ Article: {
131
+ required: ["title"],
132
+ rename: { title: "headline", abstract: "description", body: "articleBody" },
133
+ },
134
+ FAQPage: {
135
+ required: ["name"],
136
+ enrich: (props, out) => {
137
+ const questions = Array.isArray(props.questions)
138
+ ? props.questions
139
+ : [];
140
+ const mainEntity = [];
141
+ for (const q of questions) {
142
+ const name = readStr(q.name);
143
+ const answer = readStr(q.acceptedAnswer);
144
+ if (!name || !answer)
145
+ continue;
146
+ mainEntity.push({
147
+ "@type": "Question",
148
+ name,
149
+ acceptedAnswer: { "@type": "Answer", text: answer },
150
+ });
151
+ }
152
+ if (mainEntity.length > 0)
153
+ out.mainEntity = mainEntity;
154
+ },
155
+ },
156
+ RealEstateListing: {
157
+ required: ["name"],
158
+ rename: { title: "name", abstract: "description" },
159
+ enrich: (props, out) => {
160
+ const price = readNum(props.price);
161
+ const currency = readStr(props.priceCurrency);
162
+ if (price !== undefined) {
163
+ out.offers = {
164
+ "@type": "Offer",
165
+ price,
166
+ ...(currency ? { priceCurrency: currency } : { priceCurrency: "GBP" }),
167
+ };
168
+ }
169
+ const street = readStr(props.streetAddress);
170
+ const locality = readStr(props.addressLocality);
171
+ const postalCode = readStr(props.postalCode);
172
+ if (street || locality || postalCode) {
173
+ out.address = {
174
+ "@type": "PostalAddress",
175
+ ...(street ? { streetAddress: street } : {}),
176
+ ...(locality ? { addressLocality: locality } : {}),
177
+ ...(postalCode ? { postalCode } : {}),
178
+ };
179
+ }
180
+ },
181
+ },
182
+ Event: {
183
+ required: ["name", "startDate"],
184
+ rename: {},
185
+ },
186
+ };
187
+ /** Plain properties always copied verbatim when present. */
188
+ const COMMON_KEYS = [
189
+ "name",
190
+ "description",
191
+ "url",
192
+ "image",
193
+ "email",
194
+ "telephone",
195
+ "givenName",
196
+ "familyName",
197
+ "jobTitle",
198
+ "headline",
199
+ "articleBody",
200
+ "datePublished",
201
+ "dateModified",
202
+ "startDate",
203
+ "endDate",
204
+ "location",
205
+ ];
206
+ function applyCommon(props, out, rename = {}) {
207
+ const renameInverse = {};
208
+ for (const [from, to] of Object.entries(rename))
209
+ renameInverse[from] = to;
210
+ for (const key of COMMON_KEYS) {
211
+ const v = props[key];
212
+ if (typeof v === "string" || typeof v === "number") {
213
+ out[key] = v;
214
+ }
215
+ }
216
+ for (const [from, to] of Object.entries(renameInverse)) {
217
+ const v = props[from];
218
+ if (typeof v === "string" || typeof v === "number") {
219
+ out[to] = v;
220
+ }
221
+ }
222
+ }
223
+ /**
224
+ * Build a JSON-LD object from a typed entity. Throws
225
+ * `MissingPropertyError` when the resolved schema.org type's required
226
+ * properties are not satisfied.
227
+ */
228
+ export function buildJsonLd(input) {
229
+ const schemaType = resolveSchemaType(input.label);
230
+ const out = {
231
+ "@context": "https://schema.org",
232
+ "@type": schemaType,
233
+ };
234
+ if (input.elementId)
235
+ out["@id"] = input.elementId;
236
+ if (schemaType === "Thing") {
237
+ applyCommon(input.properties, out);
238
+ return out;
239
+ }
240
+ const spec = TYPE_SPECS[schemaType];
241
+ applyCommon(input.properties, out, spec.rename);
242
+ spec.enrich?.(input.properties, out);
243
+ const renamedRequired = spec.required.map((k) => spec.rename?.[k] ?? k);
244
+ const missing = renamedRequired.filter((k) => out[k] === undefined);
245
+ if (missing.length > 0) {
246
+ throw new MissingPropertyError(schemaType, missing);
247
+ }
248
+ return out;
249
+ }
250
+ /** Render a JSON-LD object as a `<script>` block string. */
251
+ export function renderJsonLdScript(obj) {
252
+ return `<script type="application/ld+json">\n${JSON.stringify(obj, null, 2)}\n</script>`;
253
+ }
254
+ //# sourceMappingURL=schema-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-mapping.js","sourceRoot":"","sources":["../../src/lib/schema-mapping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type AuditResult } from "../lib/audit-heuristics.js";
2
+ export interface AuditPageInput {
3
+ accountId: string;
4
+ /** Provide one of `url` or `html`. */
5
+ url?: string;
6
+ html?: string;
7
+ /**
8
+ * When true, the audit result is persisted as an `:AEOAudit` node
9
+ * with `HAS_AEO_AUDIT` edge from `targetKnowledgeDocumentId` (if
10
+ * given) or the synthetic `targetUrl` audit history.
11
+ */
12
+ persist?: boolean;
13
+ targetKnowledgeDocumentId?: string;
14
+ agentSlug?: string;
15
+ sessionId?: string;
16
+ }
17
+ export interface AuditPageResult extends AuditResult {
18
+ target: string;
19
+ audit: {
20
+ elementId?: string;
21
+ runAt: string;
22
+ };
23
+ }
24
+ export declare function auditPage(input: AuditPageInput): Promise<AuditPageResult>;
25
+ //# sourceMappingURL=aeo-audit-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-audit-page.d.ts","sourceRoot":"","sources":["../../src/tools/aeo-audit-page.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAeD,wBAAsB,SAAS,CAC7B,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CA2E1B"}
@@ -0,0 +1,78 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { auditHtml } from "../lib/audit-heuristics.js";
3
+ import { getSession } from "../lib/neo4j.js";
4
+ async function fetchHtml(url) {
5
+ const res = await fetch(url, {
6
+ redirect: "follow",
7
+ headers: { "User-Agent": "maxy-aeo-audit/0.1" },
8
+ });
9
+ if (!res.ok) {
10
+ throw new Error(`aeo-audit-page: GET ${url} returned HTTP ${res.status}`);
11
+ }
12
+ return await res.text();
13
+ }
14
+ export async function auditPage(input) {
15
+ if (!input.url && !input.html) {
16
+ throw new Error("aeo-audit-page requires one of url or html");
17
+ }
18
+ if (input.url && input.html) {
19
+ throw new Error("aeo-audit-page: pass exactly one of url or html, not both");
20
+ }
21
+ const html = input.html ?? (await fetchHtml(input.url));
22
+ const target = input.url ?? "(inline html)";
23
+ const result = auditHtml(html);
24
+ const runAt = new Date().toISOString();
25
+ const fails = result.heuristics
26
+ .filter((h) => h.status === "fail")
27
+ .map((h) => h.name);
28
+ const warns = result.heuristics
29
+ .filter((h) => h.status === "warn")
30
+ .map((h) => h.name);
31
+ process.stderr.write(`[aeo-audit] target=${target} score=${result.score} fails=${fails.join(",") || "-"} warns=${warns.join(",") || "-"}\n`);
32
+ let elementId;
33
+ if (input.persist) {
34
+ const auditId = randomUUID();
35
+ const session = getSession();
36
+ try {
37
+ const r = await session.run(`CREATE (a:AEOAudit {
38
+ accountId: $accountId,
39
+ auditId: $auditId,
40
+ target: $target,
41
+ score: $score,
42
+ heuristicsJson: $heuristicsJson,
43
+ runAt: $runAt,
44
+ createdByAgent: $agent,
45
+ createdBySession: $session,
46
+ createdAt: $runAt
47
+ })
48
+ WITH a
49
+ OPTIONAL MATCH (d:KnowledgeDocument)
50
+ WHERE elementId(d) = $kdocId AND d.accountId = $accountId
51
+ FOREACH (_ IN CASE WHEN d IS NULL THEN [] ELSE [1] END |
52
+ MERGE (d)-[:HAS_AEO_AUDIT]->(a)
53
+ )
54
+ RETURN elementId(a) AS id`, {
55
+ accountId: input.accountId,
56
+ auditId,
57
+ target,
58
+ score: result.score,
59
+ heuristicsJson: JSON.stringify(result.heuristics),
60
+ runAt,
61
+ agent: input.agentSlug ?? "system",
62
+ session: input.sessionId ?? null,
63
+ kdocId: input.targetKnowledgeDocumentId ?? null,
64
+ });
65
+ elementId = r.records[0]?.get("id");
66
+ process.stderr.write(`[aeo-audit] persisted auditId=${auditId} elementId=${elementId ?? "-"}\n`);
67
+ }
68
+ finally {
69
+ await session.close();
70
+ }
71
+ }
72
+ return {
73
+ ...result,
74
+ target,
75
+ audit: { elementId, runAt },
76
+ };
77
+ }
78
+ //# sourceMappingURL=aeo-audit-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-audit-page.js","sourceRoot":"","sources":["../../src/tools/aeo-audit-page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { MissingPropertyError, type JsonLdObject } from "../lib/schema-mapping.js";
2
+ export interface EmitJsonLdInput {
3
+ accountId: string;
4
+ /** Pull entity from the graph by Neo4j elementId. */
5
+ entityId?: string;
6
+ /** Or render a JSON-LD block from an inline label + property bag. */
7
+ label?: string;
8
+ properties?: Record<string, unknown>;
9
+ }
10
+ export interface EmitJsonLdResult {
11
+ jsonLd: JsonLdObject;
12
+ scriptBlock: string;
13
+ schemaType: string;
14
+ source: "graph" | "inline";
15
+ }
16
+ export declare function emitJsonLd(input: EmitJsonLdInput): Promise<EmitJsonLdResult>;
17
+ export { MissingPropertyError };
18
+ //# sourceMappingURL=aeo-emit-jsonld.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-emit-jsonld.d.ts","sourceRoot":"","sources":["../../src/tools/aeo-emit-jsonld.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,oBAAoB,EACpB,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAMD,wBAAsB,UAAU,CAC9B,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,gBAAgB,CAAC,CA8D3B;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { buildJsonLd, renderJsonLdScript, MissingPropertyError, } from "../lib/schema-mapping.js";
3
+ function isPropertyBag(v) {
4
+ return typeof v === "object" && v !== null && !Array.isArray(v);
5
+ }
6
+ export async function emitJsonLd(input) {
7
+ if (!input.entityId && !input.label) {
8
+ throw new Error("aeo-emit-jsonld requires either entityId or label+properties");
9
+ }
10
+ if (input.entityId) {
11
+ const session = getSession();
12
+ try {
13
+ const r = await session.run(`MATCH (n) WHERE elementId(n) = $id AND n.accountId = $accountId
14
+ RETURN labels(n) AS labels, properties(n) AS props, elementId(n) AS id LIMIT 1`, { id: input.entityId, accountId: input.accountId });
15
+ if (r.records.length === 0) {
16
+ throw new Error(`aeo-emit-jsonld: no node with elementId=${input.entityId} in account=${input.accountId}`);
17
+ }
18
+ const rec = r.records[0];
19
+ const labels = rec.get("labels");
20
+ const props = rec.get("props");
21
+ const id = rec.get("id");
22
+ const primaryLabel = labels.find((l) => l !== "Resource") ?? labels[0];
23
+ const obj = buildJsonLd({
24
+ label: primaryLabel,
25
+ elementId: id,
26
+ properties: props,
27
+ });
28
+ process.stderr.write(`[aeo-emit-jsonld] entityId=${id} schemaType=${obj["@type"]} source=graph\n`);
29
+ return {
30
+ jsonLd: obj,
31
+ scriptBlock: renderJsonLdScript(obj),
32
+ schemaType: obj["@type"],
33
+ source: "graph",
34
+ };
35
+ }
36
+ finally {
37
+ await session.close();
38
+ }
39
+ }
40
+ if (!input.label || !isPropertyBag(input.properties)) {
41
+ throw new Error("aeo-emit-jsonld: label requires a properties object");
42
+ }
43
+ const obj = buildJsonLd({
44
+ label: input.label,
45
+ properties: input.properties,
46
+ });
47
+ process.stderr.write(`[aeo-emit-jsonld] label=${input.label} schemaType=${obj["@type"]} source=inline\n`);
48
+ return {
49
+ jsonLd: obj,
50
+ scriptBlock: renderJsonLdScript(obj),
51
+ schemaType: obj["@type"],
52
+ source: "inline",
53
+ };
54
+ }
55
+ export { MissingPropertyError };
56
+ //# sourceMappingURL=aeo-emit-jsonld.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-emit-jsonld.js","sourceRoot":"","sources":["../../src/tools/aeo-emit-jsonld.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Generates the `llms.txt` and `llms-full.txt` pair for an account's
3
+ * published content. Format follows the current llmstxt.org draft:
4
+ *
5
+ * # <Site name>
6
+ * > <Short description>
7
+ *
8
+ * ## <Section name>
9
+ * - [<Title>](<URL>): <Summary>
10
+ *
11
+ * `llms-full.txt` concatenates the full text of every listed page in
12
+ * the same order, separated by a blank line and the page's title as an
13
+ * H1.
14
+ *
15
+ * Source: `KnowledgeDocument` nodes for the account that have a `url`
16
+ * property. `summary` and `body` properties feed the index and the
17
+ * concatenated dump respectively. Pages without a `url` are skipped
18
+ * (they aren't reachable from a public site), and the count of skipped
19
+ * pages is returned so the operator can audit completeness.
20
+ */
21
+ export interface WriteLlmsTxtInput {
22
+ accountId: string;
23
+ siteName: string;
24
+ siteDescription?: string;
25
+ }
26
+ export interface WriteLlmsTxtResult {
27
+ llmsTxt: string;
28
+ llmsFullTxt: string;
29
+ pageCount: number;
30
+ skippedNoUrl: number;
31
+ sizeBytes: {
32
+ index: number;
33
+ full: number;
34
+ };
35
+ }
36
+ export declare function writeLlmsTxt(input: WriteLlmsTxtInput): Promise<WriteLlmsTxtResult>;
37
+ //# sourceMappingURL=aeo-write-llms-txt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-write-llms-txt.d.ts","sourceRoot":"","sources":["../../src/tools/aeo-write-llms-txt.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAqBD,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,kBAAkB,CAAC,CA4F7B"}
@@ -0,0 +1,94 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ const HEADER_RX = /^#\s/m;
3
+ function escapeMarkdown(text) {
4
+ return text.replace(/[\[\]\(\)\n\r]/g, " ").trim();
5
+ }
6
+ function summariseBody(body) {
7
+ const flat = body.replace(/\s+/g, " ").trim();
8
+ if (flat.length <= 200)
9
+ return flat;
10
+ return flat.slice(0, 197).trimEnd() + "…";
11
+ }
12
+ export async function writeLlmsTxt(input) {
13
+ const session = getSession();
14
+ let rows = [];
15
+ let skippedNoUrl = 0;
16
+ try {
17
+ const r = await session.run(`MATCH (d:KnowledgeDocument {accountId: $accountId})
18
+ RETURN d.title AS title, d.url AS url, d.summary AS summary,
19
+ coalesce(d.body, d.abstract, '') AS body
20
+ ORDER BY d.title ASC`, { accountId: input.accountId });
21
+ for (const rec of r.records) {
22
+ const title = rec.get("title") ?? "";
23
+ const url = rec.get("url") ?? "";
24
+ const summary = rec.get("summary") ?? "";
25
+ const body = rec.get("body") ?? "";
26
+ if (!url || !title) {
27
+ skippedNoUrl += 1;
28
+ continue;
29
+ }
30
+ rows.push({
31
+ title: escapeMarkdown(title),
32
+ url: url.trim(),
33
+ summary: escapeMarkdown(summary) || summariseBody(body) || "(no summary)",
34
+ body: body.trim(),
35
+ });
36
+ }
37
+ }
38
+ finally {
39
+ await session.close();
40
+ }
41
+ const indexLines = [];
42
+ indexLines.push(`# ${escapeMarkdown(input.siteName)}`);
43
+ indexLines.push("");
44
+ if (input.siteDescription) {
45
+ indexLines.push(`> ${escapeMarkdown(input.siteDescription)}`);
46
+ indexLines.push("");
47
+ }
48
+ indexLines.push("## Pages");
49
+ indexLines.push("");
50
+ for (const row of rows) {
51
+ indexLines.push(`- [${row.title}](${row.url}): ${row.summary}`);
52
+ }
53
+ indexLines.push("");
54
+ indexLines.push("<!-- generated by @maxy/aeo aeo-write-llms-txt; spec: https://llmstxt.org/ -->");
55
+ const llmsTxt = indexLines.join("\n");
56
+ const fullLines = [];
57
+ fullLines.push(`# ${escapeMarkdown(input.siteName)}`);
58
+ fullLines.push("");
59
+ if (input.siteDescription) {
60
+ fullLines.push(`> ${escapeMarkdown(input.siteDescription)}`);
61
+ fullLines.push("");
62
+ }
63
+ for (const row of rows) {
64
+ fullLines.push(`# ${row.title}`);
65
+ fullLines.push("");
66
+ fullLines.push(`Source: ${row.url}`);
67
+ fullLines.push("");
68
+ if (row.body) {
69
+ // Demote any in-body H1s to H2 so a single H1 hierarchy holds.
70
+ const safeBody = row.body.replace(HEADER_RX, "## ");
71
+ fullLines.push(safeBody);
72
+ }
73
+ else {
74
+ fullLines.push(row.summary);
75
+ }
76
+ fullLines.push("");
77
+ fullLines.push("---");
78
+ fullLines.push("");
79
+ }
80
+ const llmsFullTxt = fullLines.join("\n");
81
+ const sizeBytes = {
82
+ index: Buffer.byteLength(llmsTxt, "utf-8"),
83
+ full: Buffer.byteLength(llmsFullTxt, "utf-8"),
84
+ };
85
+ process.stderr.write(`[aeo-llms-txt] site=${input.siteName} pages=${rows.length} skippedNoUrl=${skippedNoUrl} indexBytes=${sizeBytes.index} fullBytes=${sizeBytes.full}\n`);
86
+ return {
87
+ llmsTxt,
88
+ llmsFullTxt,
89
+ pageCount: rows.length,
90
+ skippedNoUrl,
91
+ sizeBytes,
92
+ };
93
+ }
94
+ //# sourceMappingURL=aeo-write-llms-txt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-write-llms-txt.js","sourceRoot":"","sources":["../../src/tools/aeo-write-llms-txt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@maxy/aeo",
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
+ "test": "vitest run"
11
+ },
12
+ "dependencies": {
13
+ "@modelcontextprotocol/sdk": "^1.12.1",
14
+ "neo4j-driver": "^5.28.1",
15
+ "zod": "^3.24.0"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.7.0",
19
+ "@types/node": "^22.0.0",
20
+ "vitest": "^4.1.2"
21
+ }
22
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["src/**/__tests__/**/*.test.ts"],
7
+ testTimeout: 10_000,
8
+ },
9
+ });