@rubytech/create-realagent-code 0.1.31 → 0.1.32

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 (136) hide show
  1. package/dist/index.js +37 -39
  2. package/package.json +1 -1
  3. package/payload/platform/lib/graph-trash/dist/index.d.ts +1 -1
  4. package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
  5. package/payload/platform/lib/graph-trash/dist/index.js +1 -2
  6. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
  7. package/payload/platform/lib/graph-trash/src/index.ts +1 -2
  8. package/payload/platform/neo4j/schema.cypher +4 -16
  9. package/payload/platform/plugins/admin/PLUGIN.md +0 -4
  10. package/payload/platform/plugins/admin/mcp/dist/index.js +1 -533
  11. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  12. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +0 -47
  13. package/payload/platform/plugins/docs/references/cloudflare.md +0 -1
  14. package/payload/platform/plugins/docs/references/deployment.md +9 -18
  15. package/payload/platform/plugins/docs/references/internals.md +4 -4
  16. package/payload/platform/plugins/docs/references/platform.md +5 -1
  17. package/payload/platform/plugins/docs/references/troubleshooting.md +11 -7
  18. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  19. package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
  20. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  21. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +2 -3
  22. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +2 -3
  24. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts +1 -1
  26. package/payload/platform/plugins/memory/references/graph-primitives.md +5 -5
  27. package/payload/platform/scripts/seed-neo4j.sh +9 -38
  28. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  29. package/payload/platform/services/claude-session-manager/dist/http-server.js +1 -14
  30. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  31. package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +1 -1
  32. package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
  33. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +0 -14
  34. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  35. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +2 -9
  36. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  37. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -28
  38. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  39. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +4 -78
  40. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  41. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -0
  42. package/payload/server/{chunk-NL7QLVAD.js → chunk-KVGTWNKQ.js} +1 -70
  43. package/payload/server/{chunk-2MRZBQMH.js → chunk-RZQMYJVY.js} +1 -1
  44. package/payload/server/{chunk-YPZFYTYP.js → chunk-ZGJ6CUU2.js} +1 -1
  45. package/payload/server/{cloudflare-task-tracker-QVOGHKWV.js → cloudflare-task-tracker-4PKOLE4H.js} +2 -2
  46. package/payload/server/maxy-edge.js +2 -2
  47. package/payload/server/public/assets/{Checkbox-YIF0payo.js → Checkbox-C6zXApx_.js} +1 -1
  48. package/payload/server/public/assets/{admin-Bk2eXMFD.js → admin-Cuu1QdAA.js} +53 -53
  49. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Bz8mlxZZ.js → architectureDiagram-Q4EWVU46-BYXgFii5.js} +1 -1
  50. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DwV8Z8-i.js → blockDiagram-DXYQGD6D-GIQ0eO13.js} +1 -1
  51. package/payload/server/public/assets/{brand-Bm671owU.js → brand-B-bNrpwc.js} +1 -1
  52. package/payload/server/public/assets/{brand-DqiRNMlu.css → brand-DdhkC994.css} +1 -1
  53. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DiUTejMp.js → c4Diagram-AHTNJAMY-BmyWfG-l.js} +1 -1
  54. package/payload/server/public/assets/channel-C76knBRO.js +1 -0
  55. package/payload/server/public/assets/{chunk-336JU56O-4mHZpBXe.js → chunk-336JU56O-DcWl0MQo.js} +2 -2
  56. package/payload/server/public/assets/{chunk-426QAEUC-Cbv0vrN9.js → chunk-426QAEUC-BIW6kq6y.js} +1 -1
  57. package/payload/server/public/assets/{chunk-4TB4RGXK-BvLhId_2.js → chunk-4TB4RGXK-CdoHpV4X.js} +1 -1
  58. package/payload/server/public/assets/{chunk-5FUZZQ4R-bBafOTkw.js → chunk-5FUZZQ4R-bn_a4sfU.js} +1 -1
  59. package/payload/server/public/assets/{chunk-5PVQY5BW-B0NqBKVy.js → chunk-5PVQY5BW-C_Rq8j_M.js} +1 -1
  60. package/payload/server/public/assets/{chunk-EDXVE4YY-CFd4SqI6.js → chunk-EDXVE4YY-CWQvoVKV.js} +1 -1
  61. package/payload/server/public/assets/{chunk-ENJZ2VHE-ajf2sb6c.js → chunk-ENJZ2VHE-DBHn1kSk.js} +1 -1
  62. package/payload/server/public/assets/{chunk-ICPOFSXX-pWg6bug7.js → chunk-ICPOFSXX-SW2Qx11O.js} +1 -1
  63. package/payload/server/public/assets/{chunk-OYMX7WX6-OjEd-17c.js → chunk-OYMX7WX6-BvIG7tVW.js} +1 -1
  64. package/payload/server/public/assets/{chunk-U2HBQHQK-DbEFSPoh.js → chunk-U2HBQHQK-BiBUb0cF.js} +1 -1
  65. package/payload/server/public/assets/{chunk-X2U36JSP-COdNwrBb.js → chunk-X2U36JSP-Y0MKZCCh.js} +1 -1
  66. package/payload/server/public/assets/{chunk-YZCP3GAM-CHMWuY9B.js → chunk-YZCP3GAM-DKPh06GH.js} +1 -1
  67. package/payload/server/public/assets/{chunk-ZZ45TVLE-B-uDLQOB.js → chunk-ZZ45TVLE-C2WNo-fK.js} +1 -1
  68. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Bohexn7P.js +1 -0
  69. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DVsmsAu7.js +1 -0
  70. package/payload/server/public/assets/clone-DUrXF4sO.js +1 -0
  71. package/payload/server/public/assets/{dagre-bhIG_KnW.js → dagre-CrK8E9ee.js} +1 -1
  72. package/payload/server/public/assets/{dagre-KV5264BT-CMEzmhIL.js → dagre-KV5264BT-_o6uXcH8.js} +1 -1
  73. package/payload/server/public/assets/data-j1WNhF8t.js +1 -0
  74. package/payload/server/public/assets/{device-url-actions-AcOyLSeF.js → device-url-actions-BcHerWqJ.js} +1 -1
  75. package/payload/server/public/assets/{diagram-5BDNPKRD-6RIoQhIL.js → diagram-5BDNPKRD-FFP9DKhc.js} +1 -1
  76. package/payload/server/public/assets/{diagram-G4DWMVQ6-BSp36TVv.js → diagram-G4DWMVQ6-DpwD1jBP.js} +1 -1
  77. package/payload/server/public/assets/{diagram-MMDJMWI5-D54fo52D.js → diagram-MMDJMWI5-C3K5agdK.js} +1 -1
  78. package/payload/server/public/assets/{diagram-TYMM5635-CWL8z-Pq.js → diagram-TYMM5635-CbeDipbC.js} +1 -1
  79. package/payload/server/public/assets/{erDiagram-SMLLAGMA-AnnHBo3z.js → erDiagram-SMLLAGMA-XBIFndNy.js} +1 -1
  80. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-laWmBl5o.js → flowDiagram-DWJPFMVM-BvEgySyn.js} +1 -1
  81. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-B94ko8ie.js → ganttDiagram-T4ZO3ILL-D7gIRKJf.js} +1 -1
  82. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DxzL1fxZ.js → gitGraphDiagram-UUTBAWPF-vJu_hcri.js} +1 -1
  83. package/payload/server/public/assets/graph-C_f_9L_7.js +1 -0
  84. package/payload/server/public/assets/graph-labels-BSQJHlgf.js +1 -0
  85. package/payload/server/public/assets/{graphlib-CY-zIElM.js → graphlib-Dp0mN6JW.js} +1 -1
  86. package/payload/server/public/assets/{infoDiagram-42DDH7IO-BMTajIIr.js → infoDiagram-42DDH7IO-g4Dlc5Cr.js} +1 -1
  87. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-B_QauE5O.js → ishikawaDiagram-UXIWVN3A-D_45LXOe.js} +1 -1
  88. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DmlqSIih.js → journeyDiagram-VCZTEJTY-CggbHl6N.js} +1 -1
  89. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-ZGDQT7xB.js → kanban-definition-6JOO6SKY-CysAe-Ab.js} +1 -1
  90. package/payload/server/public/assets/{line-D13opgep.js → line-BAxq_DSY.js} +1 -1
  91. package/payload/server/public/assets/{mermaid-parser.core-C650Sual.js → mermaid-parser.core-DbFuvkjL.js} +1 -1
  92. package/payload/server/public/assets/{mermaid.core-BqnQoXTp.js → mermaid.core-CehvJn5b.js} +3 -3
  93. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BS_8y-tY.js → mindmap-definition-QFDTVHPH-DbPbBJ9h.js} +1 -1
  94. package/payload/server/public/assets/page-B0BPrSE3.js +1 -0
  95. package/payload/server/public/assets/{page-Dk73ZO1F.js → page-Co7KCRV8.js} +2 -2
  96. package/payload/server/public/assets/{pieDiagram-DEJITSTG-B5OmNvBO.js → pieDiagram-DEJITSTG-cagLL9ng.js} +1 -1
  97. package/payload/server/public/assets/{public-DDsYgotk.js → public-B6TEcDLx.js} +5 -5
  98. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DTYITdNo.js → quadrantDiagram-34T5L4WZ-Keaa1jDh.js} +1 -1
  99. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CRZWxH06.js → requirementDiagram-MS252O5E-BcYRyn5z.js} +1 -1
  100. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DazRENhe.js → sankeyDiagram-XADWPNL6--fKoG9NR.js} +1 -1
  101. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BcHTxmPy.js → sequenceDiagram-FGHM5R23-lKG36-Di.js} +1 -1
  102. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DYU7nbqg.js → stateDiagram-FHFEXIEX-BuVsrlig.js} +1 -1
  103. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSt88_xL.js +1 -0
  104. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BKGmqkST.js → timeline-definition-GMOUNBTQ-D6X6uq17.js} +1 -1
  105. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BXvLPmX7.js → vennDiagram-DHZGUBPP-BgvcfRVf.js} +1 -1
  106. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BCclUa3Z.js → wardleyDiagram-NUSXRM2D-Cpd1xsrt.js} +1 -1
  107. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-C-Xp-Eoc.js → xychartDiagram-5P7HB3ND-CDF5ZVFv.js} +1 -1
  108. package/payload/server/public/data.html +5 -5
  109. package/payload/server/public/graph.html +6 -6
  110. package/payload/server/public/index.html +8 -8
  111. package/payload/server/public/public.html +5 -5
  112. package/payload/server/server.js +151 -362
  113. package/payload/platform/plugins/admin/hooks/onboarding-skill-drift.sh +0 -103
  114. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +0 -240
  115. package/payload/platform/services/claude-session-manager/scripts/onboarding-advance.sh +0 -61
  116. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-0.md +0 -5
  117. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-1.md +0 -3
  118. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-2.md +0 -3
  119. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-3.md +0 -8
  120. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-4.md +0 -9
  121. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-5.md +0 -3
  122. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-6.md +0 -5
  123. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-7.md +0 -5
  124. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-8.md +0 -5
  125. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-9.md +0 -8
  126. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-complete.md +0 -3
  127. package/payload/platform/services/claude-session-manager/scripts/onboarding-prompts/step-unreachable.md +0 -3
  128. package/payload/server/public/assets/channel-PtVtoBEL.js +0 -1
  129. package/payload/server/public/assets/classDiagram-6PBFFD2Q-RVH_SEhY.js +0 -1
  130. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Cm3rAb93.js +0 -1
  131. package/payload/server/public/assets/clone-BjY0Wzht.js +0 -1
  132. package/payload/server/public/assets/data-ll_OwVNL.js +0 -1
  133. package/payload/server/public/assets/graph-DJ2VWioQ.js +0 -1
  134. package/payload/server/public/assets/graph-labels-qhU8xZDH.js +0 -1
  135. package/payload/server/public/assets/page-DsYsdBUK.js +0 -1
  136. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BgljVtlp.js +0 -1
@@ -8,7 +8,7 @@ import { readFile, writeFile } from "node:fs/promises";
8
8
  import { resolve, join } from "node:path";
9
9
  import { execFileSync } from "node:child_process";
10
10
  import { appendFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
11
- import { writeKey, validateKey, hasKey, keyFilePath, deleteKey } from "../../../../lib/anthropic-key/dist/index.js";
11
+ import { writeKey, validateKey, keyFilePath } from "../../../../lib/anthropic-key/dist/index.js";
12
12
  import { writeAdminEntry, removeAdminFromAccount } from "../../../../lib/admins-write/dist/index.js";
13
13
  import { deviceUrlBlock } from "../../../../lib/device-url/dist/index.js";
14
14
  import { substituteBrandPlaceholders } from "../../../../lib/brand-templating/dist/index.js";
@@ -18,7 +18,6 @@ import { createConnection } from "node:net";
18
18
  import { homedir, hostname as osHostname } from "node:os";
19
19
  import QRCode from "qrcode";
20
20
  import { getSession, closeDriver } from "./lib/neo4j.js";
21
- import { getOnboardingState, completeOnboardingStep } from "./lib/onboarding.js";
22
21
  import { findSkillOwners, computePluginReadHint, loadSkill, parseRequiredInputs } from "./skill-resolution.js";
23
22
  import { resolvePublicHostname } from "./lib/public-hostname.js";
24
23
  const server = new McpServer({
@@ -485,70 +484,6 @@ eagerTool(server, "brand-settings", "Read the brand/styling configuration (name,
485
484
  };
486
485
  }
487
486
  });
488
- /* ── Plugin selector options (deterministic) ────────────────────── */
489
- const PLUGIN_DISPLAY = {
490
- admin: { value: "admin", label: "admin", description: "Platform management — system status, account settings, logs, session control." },
491
- memory: { value: "memory", label: "memory", description: "Graph memory — search, write, reindex, and ingest knowledge." },
492
- docs: { value: "docs", label: "maxy-guide", description: "User guide and platform documentation — loaded on demand." },
493
- cloudflare: { value: "cloudflare", label: "cloudflare", description: "Cloudflare Tunnel — expose your assistant publicly via a custom domain." },
494
- anthropic: { value: "anthropic", label: "anthropic", description: "Claude connection — API key acquisition and configuration." },
495
- scheduling: { value: "scheduling", label: "scheduling", description: "Calendar and scheduling — events, appointments, recurring triggers." },
496
- email: { value: "email", label: "email", description: "Agent email account — setup, read, send, search." },
497
- contacts: { value: "contacts", label: "contacts", description: "CRM contact management — create, lookup, update, list." },
498
- tasks: { value: "tasks", label: "tasks", description: "Graph-backed task lifecycle — create, update, list, relate, complete." },
499
- workflows: { value: "workflows", label: "workflows", description: "Persistent named workflows — reusable instruction sets." },
500
- projects: { value: "projects", label: "projects", description: "Structured project execution — phased sprints, investigations, reviews, retrospectives." },
501
- "business-assistant": { value: "business-assistant", label: "business-assistant", description: "Customer enquiries, scheduling, quoting, invoicing, daily briefings. Enhances: personal-assistant" },
502
- sales: { value: "sales", label: "sales", description: "Buying signal detection, closing techniques, objection handling. Enhances: personal-assistant" },
503
- "deep-research": { value: "deep-research", label: "deep-research", description: "Structured multi-source research — query decomposition, source evaluation, citation formatting. Enhances: research-assistant" },
504
- telegram: { value: "telegram", label: "telegram", description: "Telegram bot setup — BotFather, admin and public channels. Enhances: personal-assistant" },
505
- whatsapp: { value: "whatsapp", label: "whatsapp", description: "WhatsApp messaging, pairing, and conversation browsing. Enhances: personal-assistant" },
506
- waitlist: { value: "waitlist", label: "waitlist", description: "Waitlist lifecycle — extract sign-ups, review, schedule automation." },
507
- replicate: { value: "replicate", label: "replicate", description: "Image generation — photorealistic, design, and fast draft images via Replicate. Enhances: content-producer, research-assistant" },
508
- };
509
- server.tool("onboarding-plugin-options", "Return the fully-assembled plugin options array for onboarding Step 1. Classification (core/recommended/available) is derived from brand.json — the agent presents the entries to the operator as a numbered list in plain chat without further transformation.", {}, async () => {
510
- try {
511
- const brandPath = resolve(PLATFORM_ROOT, "config", "brand.json");
512
- if (!existsSync(brandPath)) {
513
- return { content: [{ type: "text", text: "No brand.json found at " + brandPath + " — platform not properly installed." }], isError: true };
514
- }
515
- const brand = JSON.parse(readFileSync(brandPath, "utf-8"));
516
- const plugins = brand?.plugins;
517
- if (!plugins)
518
- return { content: [{ type: "text", text: "brand.json has no plugins configuration." }], isError: true };
519
- const coreSet = new Set(plugins.core ?? []);
520
- const defaultSet = new Set(plugins.defaultEnabled ?? []);
521
- const availableSet = new Set(plugins.available ?? []);
522
- const options = [];
523
- for (const name of plugins.core ?? []) {
524
- const meta = PLUGIN_DISPLAY[name] ?? { value: name, label: name, description: "" };
525
- options.push({ ...meta, badge: "Core", group: "Core — always active", locked: true, defaultSelected: true });
526
- }
527
- for (const name of plugins.defaultEnabled ?? []) {
528
- if (coreSet.has(name))
529
- continue;
530
- const meta = PLUGIN_DISPLAY[name] ?? { value: name, label: name, description: "" };
531
- options.push({ ...meta, badge: "Recommended", group: "Maxy", defaultSelected: true });
532
- }
533
- for (const name of plugins.available ?? []) {
534
- if (coreSet.has(name) || defaultSet.has(name))
535
- continue;
536
- const meta = PLUGIN_DISPLAY[name] ?? { value: name, label: name, description: "" };
537
- options.push({ ...meta, group: "Maxy" });
538
- }
539
- // Task 976: signal that the onboarding skill will append three Anthropic
540
- // vertical entries from the claude-for-financial-services and
541
- // knowledge-work-plugins marketplaces. The count is fixed because the
542
- // skill prose always appends the same three (kyc-screener,
543
- // meeting-prep-agent, pdf-viewer). Absence of this line post-install
544
- // = the group was not surfaced (release blocker per task spec).
545
- console.error(`[plugin-onboarding] group=anthropic-verticals presented=3`);
546
- return { content: [{ type: "text", text: JSON.stringify(options, null, 2) }] };
547
- }
548
- catch (err) {
549
- return { content: [{ type: "text", text: `Failed: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
550
- }
551
- });
552
487
  eagerTool(server, "account-manage", "Read the account configuration (tier, domains, settings).", {}, async () => {
553
488
  try {
554
489
  const config = await readAccountConfig();
@@ -1851,473 +1786,6 @@ eagerTool(server, "api-key-verify", "Verify the stored Anthropic API key works b
1851
1786
  };
1852
1787
  });
1853
1788
  // ===================================================================
1854
- // Anthropic setup — deterministic state machine
1855
- // ===================================================================
1856
- /*
1857
- * anthropic-setup state machine (action-relay pattern)
1858
- *
1859
- * Call 1: anthropic-setup({})
1860
- * ├─ no public endpoint → { status: "not_needed" } ← Phase 0 gate
1861
- * ├─ key stored + valid? → { status: "complete" }
1862
- * ├─ key stored + billing → { status: "awaiting_credits" }
1863
- * ├─ key stored + error → { status: "error" }
1864
- * └─ no key → { status: "awaiting_signin", action }
1865
- *
1866
- * Call 2: anthropic-setup({ consoleResult: "..." })
1867
- * ├─ no_session → { status: "awaiting_signin", action }
1868
- * ├─ no_org → { status: "error" }
1869
- * ├─ no_credits → { status: "awaiting_credits", action }
1870
- * ├─ success → writeKey → validateKey → { status: "complete" }
1871
- * └─ *_failed → { status: "error" }
1872
- */
1873
- const CONSOLE_BASE = "https://platform.claude.com";
1874
- /**
1875
- * JavaScript expression for browser_evaluate that runs the complete
1876
- * Console API pipeline in one call: check session → find API org →
1877
- * check credits → create key. Returns a structured JSON result.
1878
- */
1879
- function consoleEvaluateExpression(keyName) {
1880
- return `async () => {
1881
- try {
1882
- const orgsRes = await fetch("/api/organizations", { credentials: "include" });
1883
- if (orgsRes.status === 401 || orgsRes.status === 403) {
1884
- return JSON.stringify({ status: "no_session" });
1885
- }
1886
- if (!orgsRes.ok) {
1887
- return JSON.stringify({ status: "fetch_error", error: "organizations: " + orgsRes.status });
1888
- }
1889
- const orgs = await orgsRes.json();
1890
- const apiOrg = orgs.find(o => o.capabilities && o.capabilities.includes("api"));
1891
- if (!apiOrg) {
1892
- return JSON.stringify({ status: "no_org" });
1893
- }
1894
- const creditsRes = await fetch("/api/organizations/" + apiOrg.uuid + "/prepaid/credits", { credentials: "include" });
1895
- if (!creditsRes.ok) {
1896
- return JSON.stringify({ status: "fetch_error", error: "credits: " + creditsRes.status });
1897
- }
1898
- const credits = await creditsRes.json();
1899
- if (typeof credits.amount === "number" && credits.amount <= 0) {
1900
- return JSON.stringify({ status: "no_credits", orgId: apiOrg.uuid, orgName: apiOrg.name, creditUrl: "${CONSOLE_BASE}/settings/billing" });
1901
- }
1902
- const createRes = await fetch("/api/console/organizations/" + apiOrg.uuid + "/workspaces/default/api_keys", {
1903
- method: "POST",
1904
- credentials: "include",
1905
- headers: { "content-type": "application/json" },
1906
- body: JSON.stringify({ name: ${JSON.stringify(keyName)} })
1907
- });
1908
- if (!createRes.ok) {
1909
- return JSON.stringify({ status: "create_failed", error: "key creation: " + createRes.status });
1910
- }
1911
- const keyData = await createRes.json();
1912
- if (!keyData.raw_key) {
1913
- return JSON.stringify({ status: "create_failed", error: "no raw_key in response" });
1914
- }
1915
- return JSON.stringify({
1916
- status: "success",
1917
- key: keyData.raw_key,
1918
- keyId: keyData.id,
1919
- keyHint: keyData.partial_key_hint,
1920
- orgName: apiOrg.name,
1921
- credits: credits.amount
1922
- });
1923
- } catch (err) {
1924
- return JSON.stringify({ status: "fetch_error", error: String(err) });
1925
- }
1926
- }`;
1927
- }
1928
- function anthropicResult(r) {
1929
- return {
1930
- content: [{ type: "text", text: JSON.stringify(r, null, 2) }],
1931
- ...(r.status === "error" ? { isError: true } : {}),
1932
- };
1933
- }
1934
- /**
1935
- * Check whether a public-facing hostname is configured. The Anthropic API key
1936
- * powers the public agent only — admin runs on Claude OAuth — so without a
1937
- * public endpoint there is nothing for the key to power.
1938
- *
1939
- * Mirrors the runtime `isPublicHost(host)` predicate in
1940
- * `platform/ui/server/index.ts`: a host is public iff it starts with `public.`
1941
- * OR is listed in `~/{configDir}/alias-domains.json`. Step 7's form submit
1942
- * handler at `platform/ui/server/routes/admin/cloudflare.ts` writes secondary
1943
- * hostnames (apex + custom public labels) to `alias-domains.json` and skips
1944
- * `public.*` because the prefix itself is the signal — so the two predicates
1945
- * together cover every shape the form can produce.
1946
- *
1947
- * Returns true if any configured hostname satisfies either predicate.
1948
- */
1949
- function hasPublicEndpointConfigured() {
1950
- const aliasPath = join(CONFIG_DIR, "alias-domains.json");
1951
- if (existsSync(aliasPath)) {
1952
- try {
1953
- const parsed = JSON.parse(readFileSync(aliasPath, "utf-8"));
1954
- if (Array.isArray(parsed)) {
1955
- const entries = parsed.filter((h) => typeof h === "string" && h.length > 0);
1956
- if (entries.length > 0) {
1957
- return { has: true, reason: `alias-domains.json: ${entries.join(", ")}` };
1958
- }
1959
- }
1960
- }
1961
- catch {
1962
- // Malformed file — treat as empty; matches the server-side reader's tolerance.
1963
- }
1964
- }
1965
- const cfConfigPath = join(CONFIG_DIR, "cloudflared", "config.yml");
1966
- if (existsSync(cfConfigPath)) {
1967
- try {
1968
- const yaml = readFileSync(cfConfigPath, "utf-8");
1969
- const hostnames = [...yaml.matchAll(/^\s*-\s*hostname:\s*(\S+)/gm)].map((m) => m[1]);
1970
- const publicPrefixed = hostnames.find((h) => h.startsWith("public."));
1971
- if (publicPrefixed) {
1972
- return { has: true, reason: `cloudflared/config.yml ingress: ${publicPrefixed}` };
1973
- }
1974
- }
1975
- catch {
1976
- // Unreadable — treat as no public host.
1977
- }
1978
- }
1979
- return {
1980
- has: false,
1981
- reason: "no entries in alias-domains.json and no public.* hostname in cloudflared/config.yml",
1982
- };
1983
- }
1984
- eagerTool(server, "anthropic-setup", "Deterministic state machine for Anthropic API key acquisition. " +
1985
- "Checks current state, advances as far as possible, and returns a structured JSON result. " +
1986
- "On first call (no consoleResult): first verifies a public-facing endpoint is configured " +
1987
- "(the key only powers the public agent); if not, returns status 'not_needed'. Otherwise " +
1988
- "checks if a valid key is already stored. If not, returns status 'awaiting_signin' with " +
1989
- "a browser_evaluate action — the agent must open the browser to platform.claude.com, run " +
1990
- "the action's function via browser_evaluate, and pass the string result back as " +
1991
- "consoleResult on the next call. " +
1992
- "On second call (with consoleResult): parses the Console API result, stores the key, " +
1993
- "verifies it, and returns status 'complete'. " +
1994
- "Statuses: complete (key stored and verified), not_needed (no public endpoint configured — " +
1995
- "skip the step), awaiting_signin (user must sign in to Console), awaiting_credits (signed in " +
1996
- "but no credits — user must add credits), error (fatal — relay message).", {
1997
- consoleResult: z.string().optional().describe("JSON string result from running the browser_evaluate action returned by a prior call. " +
1998
- "Omit on the first call."),
1999
- }, async ({ consoleResult }) => {
2000
- const log = (msg) => console.error(`[anthropic-setup] ${msg}`);
2001
- // ── Phase 0: gate on public endpoint existence ─────────────
2002
- // The API key only powers the public-facing agent. If no public hostname
2003
- // is configured (operator skipped step 7, or completed it without a
2004
- // public/apex hostname) the key has no consumer — short-circuit before
2005
- // any Console interaction so we never create keys the operator cannot use.
2006
- if (!consoleResult) {
2007
- const publicCheck = hasPublicEndpointConfigured();
2008
- if (!publicCheck.has) {
2009
- log(`gate: no public endpoint (${publicCheck.reason}) — returning not_needed`);
2010
- return anthropicResult({
2011
- status: "not_needed",
2012
- message: "No public-facing endpoint is configured, so an Anthropic API key is not needed. " +
2013
- "The key powers the public agent only — admin runs on your Claude OAuth session. " +
2014
- "When you set up a public hostname via Cloudflare (or apex domain), come back and " +
2015
- "ask to set up the API key then.",
2016
- });
2017
- }
2018
- log(`gate: public endpoint present (${publicCheck.reason})`);
2019
- }
2020
- // ── Phase 1: check stored key ──────────────────────────────
2021
- if (!consoleResult) {
2022
- log("checking stored key");
2023
- if (hasKey()) {
2024
- const verification = await validateKey();
2025
- log(`stored key verification: ${verification.status}`);
2026
- switch (verification.status) {
2027
- case "valid":
2028
- log("key valid, returning complete");
2029
- return anthropicResult({
2030
- status: "complete",
2031
- message: `API key is stored and working. Key file: ${keyFilePath()}.`,
2032
- });
2033
- case "billing":
2034
- log("key valid but billing issue");
2035
- return anthropicResult({
2036
- status: "awaiting_credits",
2037
- message: "API key is stored and valid, but your account has insufficient credits. " +
2038
- `Add credits at ${CONSOLE_BASE}/settings/billing, then call this tool again.`,
2039
- data: { url: `${CONSOLE_BASE}/settings/billing` },
2040
- });
2041
- case "auth_error":
2042
- // Deterministic transition: the state machine knows the key file
2043
- // path and the only recovery is to delete and restart sign-in.
2044
- // Auto-reset here so the agent never has to rediscover the path
2045
- // via filesystem probes.
2046
- log(`auth_error → auto-resetting: deleting revoked key at ${keyFilePath()}`);
2047
- try {
2048
- deleteKey();
2049
- }
2050
- catch (err) {
2051
- const msg = err instanceof Error ? err.message : String(err);
2052
- log(`auto-reset failed: ${msg}`);
2053
- return anthropicResult({
2054
- status: "error",
2055
- message: `The stored API key was rejected and auto-reset failed: ${msg}. ` +
2056
- `Manual intervention needed — remove ${keyFilePath()} and call this tool again.`,
2057
- });
2058
- }
2059
- // Fall through to the awaiting_signin path below.
2060
- break;
2061
- case "missing":
2062
- // hasKey() returned true but readKey() returned null — shouldn't happen
2063
- log("hasKey true but validate returned missing — proceeding to setup");
2064
- break;
2065
- case "error":
2066
- log(`verification failed: ${verification.message}`);
2067
- return anthropicResult({
2068
- status: "error",
2069
- message: `Could not verify the stored key: ${verification.message}. ` +
2070
- "This may be a network issue or Anthropic outage. Try again later.",
2071
- });
2072
- }
2073
- }
2074
- else {
2075
- log("no key stored");
2076
- }
2077
- // No valid key — return action for Console API calls
2078
- const expression = consoleEvaluateExpression(BRAND_NAME);
2079
- log("returning awaiting_signin with browser_evaluate action");
2080
- return anthropicResult({
2081
- status: "awaiting_signin",
2082
- message: "No valid API key stored. Open the browser to the Anthropic Console " +
2083
- `(${CONSOLE_BASE}) and sign in. This is a separate service from Claude — ` +
2084
- "you may need to sign in again even if you used the same credentials earlier. " +
2085
- "Once signed in, run the browser_evaluate action below, then call this tool " +
2086
- "again with the result as consoleResult.",
2087
- data: {
2088
- url: CONSOLE_BASE,
2089
- action: {
2090
- tool: "browser_evaluate",
2091
- params: { function: expression },
2092
- },
2093
- },
2094
- });
2095
- }
2096
- // ── Phase 2: process Console API result ────────────────────
2097
- log("processing consoleResult");
2098
- let parsed;
2099
- try {
2100
- parsed = JSON.parse(consoleResult);
2101
- }
2102
- catch {
2103
- log(`consoleResult parse failed: ${consoleResult.slice(0, 200)}`);
2104
- return anthropicResult({
2105
- status: "error",
2106
- message: "Failed to parse the browser result. The Console session may have " +
2107
- "been lost or the browser encountered an error. Please try again — " +
2108
- "open the browser to platform.claude.com, sign in, and re-run the action.",
2109
- });
2110
- }
2111
- log(`console result status: ${parsed.status}`);
2112
- switch (parsed.status) {
2113
- case "no_session": {
2114
- log("no Console session — user needs to sign in");
2115
- const expression = consoleEvaluateExpression(BRAND_NAME);
2116
- return anthropicResult({
2117
- status: "awaiting_signin",
2118
- message: "Not signed in to the Anthropic Console. Please sign in at " +
2119
- `${CONSOLE_BASE} and then run the browser_evaluate action below.`,
2120
- data: {
2121
- url: CONSOLE_BASE,
2122
- action: {
2123
- tool: "browser_evaluate",
2124
- params: { function: expression },
2125
- },
2126
- },
2127
- });
2128
- }
2129
- case "no_org":
2130
- log("no API organization found");
2131
- return anthropicResult({
2132
- status: "error",
2133
- message: "No API organization found in your Anthropic account. " +
2134
- "You may be signed in to a Claude consumer account instead of the API Console. " +
2135
- `Sign in at ${CONSOLE_BASE} with an account that has API access.`,
2136
- });
2137
- case "no_credits": {
2138
- log(`no credits — org: ${parsed.orgName ?? "unknown"}`);
2139
- const expression = consoleEvaluateExpression(BRAND_NAME);
2140
- return anthropicResult({
2141
- status: "awaiting_credits",
2142
- message: `Your API organization (${parsed.orgName ?? "unknown"}) has no credits. ` +
2143
- `Add credits at ${parsed.creditUrl ?? CONSOLE_BASE + "/settings/billing"}, ` +
2144
- "then run the browser_evaluate action below.",
2145
- data: {
2146
- url: parsed.creditUrl ?? `${CONSOLE_BASE}/settings/billing`,
2147
- action: {
2148
- tool: "browser_evaluate",
2149
- params: { function: expression },
2150
- },
2151
- },
2152
- });
2153
- }
2154
- case "create_failed":
2155
- log(`key creation failed: ${parsed.error ?? "unknown"}`);
2156
- return anthropicResult({
2157
- status: "error",
2158
- message: `Failed to create API key: ${parsed.error ?? "unknown error"}. ` +
2159
- "This may be a permissions issue or a temporary Console error. Try again.",
2160
- });
2161
- case "fetch_error":
2162
- log(`fetch error: ${parsed.error ?? "unknown"}`);
2163
- return anthropicResult({
2164
- status: "error",
2165
- message: `Console API error: ${parsed.error ?? "unknown"}. ` +
2166
- "The Console may be temporarily unavailable. Try again.",
2167
- });
2168
- case "success": {
2169
- if (!parsed.key) {
2170
- log("success status but no key in result");
2171
- return anthropicResult({
2172
- status: "error",
2173
- message: "Key creation succeeded but the key was not returned. " +
2174
- "This is unexpected. Please try again.",
2175
- });
2176
- }
2177
- log(`key created: ${parsed.keyId ?? "unknown"} (hint: ${parsed.keyHint ?? "n/a"}) — org: ${parsed.orgName ?? "unknown"}`);
2178
- // Store the key — persist AFTER confirmation (sprint learning: Task 201)
2179
- try {
2180
- writeKey(parsed.key);
2181
- log("key stored");
2182
- }
2183
- catch (err) {
2184
- log(`key storage failed: ${err instanceof Error ? err.message : String(err)}`);
2185
- return anthropicResult({
2186
- status: "error",
2187
- message: `Key was created in the Console but could not be stored locally: ` +
2188
- `${err instanceof Error ? err.message : String(err)}`,
2189
- });
2190
- }
2191
- // Verify the stored key
2192
- const verification = await validateKey();
2193
- log(`post-store verification: ${verification.status}`);
2194
- switch (verification.status) {
2195
- case "valid":
2196
- log("key stored and verified");
2197
- return anthropicResult({
2198
- status: "complete",
2199
- message: `API key created, stored at ${keyFilePath()}, and verified. ` +
2200
- `Organization: ${parsed.orgName ?? "unknown"}. ` +
2201
- `Credits: $${((parsed.credits ?? 0) / 100).toFixed(2)}.`,
2202
- });
2203
- case "billing":
2204
- log("key stored but billing issue on verification");
2205
- return anthropicResult({
2206
- status: "awaiting_credits",
2207
- message: "API key created and stored, but your account has insufficient credits. " +
2208
- `Add credits at ${CONSOLE_BASE}/settings/billing, then verify the key with api-key-verify.`,
2209
- data: { url: `${CONSOLE_BASE}/settings/billing` },
2210
- });
2211
- default:
2212
- log(`unexpected verification status after store: ${verification.status} — ${verification.message}`);
2213
- return anthropicResult({
2214
- status: "error",
2215
- message: `Key was stored but verification returned: ${verification.status}. ` +
2216
- `${verification.message}. Try running api-key-verify manually.`,
2217
- });
2218
- }
2219
- }
2220
- default:
2221
- log(`unknown console result status: ${parsed.status}`);
2222
- return anthropicResult({
2223
- status: "error",
2224
- message: `Unexpected result from Console: status "${parsed.status}". ` +
2225
- "Please try again.",
2226
- });
2227
- }
2228
- });
2229
- // ===================================================================
2230
- // Onboarding tools
2231
- // ===================================================================
2232
- server.tool("onboarding-get", "Read the current onboarding state from the graph. Returns which setup steps " +
2233
- "have been completed and their timestamps. On first call for an account, " +
2234
- "migrates any existing onboardingStep from account.json to the graph and " +
2235
- "removes it from the file. If Neo4j is unreachable, returns an error — " +
2236
- "the agent should skip onboarding for this session and retry next time.", {}, async () => {
2237
- try {
2238
- const state = await getOnboardingState(getSession, ACCOUNT_ID, getAccountDir());
2239
- return {
2240
- content: [{
2241
- type: "text",
2242
- text: JSON.stringify(state, null, 2),
2243
- }],
2244
- };
2245
- }
2246
- catch (err) {
2247
- return {
2248
- content: [{
2249
- type: "text",
2250
- text: `Failed to read onboarding state: ${err instanceof Error ? err.message : String(err)}`,
2251
- }],
2252
- isError: true,
2253
- };
2254
- }
2255
- });
2256
- server.tool("onboarding-complete-step", "Mark an onboarding step as completed. Sets a completion timestamp on the step " +
2257
- "and updates currentStep to the highest completed step. Idempotent — completing " +
2258
- "an already-completed step preserves its original timestamp. Step must be 1–9. " +
2259
- "When step is 1, optionally pass acceptedAnthropicVerticals + declinedAnthropicVerticals " +
2260
- "(both required together) to emit the paired counter for the [plugin-onboarding] " +
2261
- "group=anthropic-verticals prefix; the skill derives both arrays from the closed set " +
2262
- "{kyc-screener, meeting-prep-agent, pdf-viewer} and the user's submission.", {
2263
- step: z.number().int().min(1).max(9).describe("The onboarding step number (1–9) to mark as completed"),
2264
- acceptedAnthropicVerticals: z.array(z.string()).optional().describe("Step 1 only: plugin slugs the user accepted from the Anthropic verticals group. Pass together with declinedAnthropicVerticals."),
2265
- declinedAnthropicVerticals: z.array(z.string()).optional().describe("Step 1 only: plugin slugs the user declined from the Anthropic verticals group. Pass together with acceptedAnthropicVerticals."),
2266
- }, async ({ step, acceptedAnthropicVerticals, declinedAnthropicVerticals }) => {
2267
- try {
2268
- const state = await completeOnboardingStep(getSession, ACCOUNT_ID, step);
2269
- // Task 977: closed set lives in skill prose, not server validation — a fourth vertical updates the skill.
2270
- if (step === 1 && acceptedAnthropicVerticals !== undefined && declinedAnthropicVerticals !== undefined) {
2271
- console.error(`[plugin-onboarding] group=anthropic-verticals accepted=${acceptedAnthropicVerticals.length} declined=${declinedAnthropicVerticals.length}`);
2272
- }
2273
- return {
2274
- content: [{
2275
- type: "text",
2276
- text: JSON.stringify(state, null, 2),
2277
- }],
2278
- };
2279
- }
2280
- catch (err) {
2281
- return {
2282
- content: [{
2283
- type: "text",
2284
- text: `Failed to complete onboarding step: ${err instanceof Error ? err.message : String(err)}`,
2285
- }],
2286
- isError: true,
2287
- };
2288
- }
2289
- });
2290
- // Task 704: pin the operator's persona (personal/business-owner) at step 9
2291
- // BEFORE any graph write happens. The agent calls this immediately on the
2292
- // user's single-select submission. The tool's job is twofold:
2293
- // 1. Emit a deterministic [onboarding-step9-mode] log line for the
2294
- // diagnostic-grep path on the Pi (matches [onboarding-step-complete]
2295
- // format — same accountId-prefix slicing, same surrounding code).
2296
- // 2. Return the next-action prose so the agent's branching is anchored to
2297
- // the tool surface, not free-text inference.
2298
- // No persistence — the graph state (LocalBusiness exists vs Person with
2299
- // role=admin-personal exists) remains the source of truth for gate
2300
- // satisfaction. Re-calling this tool with a different mode on the same
2301
- // session is allowed; the most recent log line wins for diagnostic purposes.
2302
- server.tool("onboarding-step9-mode", "Step 9 onboarding fork: record the operator's persona (personal or " +
2303
- "business-owner) before any graph write. Logs the choice for diagnostic " +
2304
- "grep and returns the deterministic next-action prose for the agent.", {
2305
- mode: z
2306
- .enum(["personal", "business-owner"])
2307
- .describe("The operator's persona: 'personal' for an individual using Maxy for personal operations (including someone with an employer that is NOT being registered here), or 'business-owner' for someone setting up Maxy as the operations agent for their own company."),
2308
- }, async ({ mode }) => {
2309
- console.log(`[onboarding-step9-mode] accountId=${ACCOUNT_ID.slice(0, 8)}… mode=${mode}`);
2310
- const nextAction = mode === "business-owner"
2311
- ? "Invoke the `business-profile` skill to create AdminUser + LocalBusiness and capture the business identity. Mark step 9 complete only after both nodes exist in the graph."
2312
- : "Ask the user for their email (one sentence). Use their name from `admin-identity` in the system prompt; split into givenName + familyName. Call `memory-write` to create the AdminUser node, then call `memory-write` to create a Person node with `role: \"admin-personal\"`, the givenName, familyName, email, and an OWNS edge from the AdminUser. Then call `onboarding-complete-step` with step 9. Do not invoke the `business-profile` skill — personal mode does not register a LocalBusiness.";
2313
- return {
2314
- content: [{
2315
- type: "text",
2316
- text: JSON.stringify({ mode, nextAction }, null, 2),
2317
- }],
2318
- };
2319
- });
2320
- // ===================================================================
2321
1789
  // Utility tools
2322
1790
  // ===================================================================
2323
1791
  eagerTool(server, "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.", {