@rubytech/create-realagent-code 0.1.254 → 0.1.256
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/__tests__/plugin-install.test.js +58 -40
- package/dist/index.js +77 -26
- package/dist/lib/plugin-install.js +31 -29
- package/package.json +1 -1
- package/payload/platform/.docs/search-surface-contract.md +58 -0
- package/payload/platform/config/brand-registry.json +8 -0
- package/payload/platform/config/brand.json +2 -2
- package/payload/platform/lib/embed-client/dist/index.d.ts +4 -0
- package/payload/platform/lib/embed-client/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/embed-client/dist/index.js +53 -0
- package/payload/platform/lib/embed-client/dist/index.js.map +1 -0
- package/payload/platform/lib/embed-client/src/index.ts +53 -0
- package/payload/platform/lib/embed-client/tsconfig.json +8 -0
- package/payload/platform/lib/graph-search/dist/index.d.ts +27 -6
- package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-search/dist/index.js +19 -1
- package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +12 -0
- package/payload/platform/lib/graph-search/src/index.ts +28 -6
- package/payload/platform/lib/graph-write/dist/index.d.ts +25 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +80 -2
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +98 -1
- package/payload/platform/neo4j/schema.cypher +126 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +3 -6
- package/payload/platform/plugins/admin/mcp/dist/index.js +14 -60
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/insight/SKILL.md +24 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +84 -31
- package/payload/platform/plugins/docs/PLUGIN.md +1 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +18 -5
- package/payload/platform/plugins/docs/references/graph.md +2 -0
- package/payload/platform/plugins/docs/references/internals.md +12 -1
- package/payload/platform/plugins/docs/references/memory-guide.md +4 -0
- package/payload/platform/plugins/docs/references/neo4j.md +2 -2
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/session-retrospective.md +5 -18
- package/payload/platform/plugins/docs/references/slides.md +31 -0
- package/payload/platform/plugins/docs/references/voice-mirror-guide.md +1 -1
- package/payload/platform/plugins/email/PLUGIN.md +2 -2
- package/payload/platform/plugins/email/mcp/dist/index.js +8 -0
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts +19 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js +64 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +4 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +6 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +7 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +4 -0
- package/payload/platform/plugins/memory/PLUGIN.md +1 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js +6 -44
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js +41 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js +90 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js +27 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts +10 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js +47 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts +1 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js +5 -28
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js +20 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js +67 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js +34 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js +61 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +23 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js +87 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +3 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js +34 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +19 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +33 -6
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +280 -10
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +76 -37
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +11 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +4 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +20 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +6 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -0
- package/payload/platform/plugins/memory/references/schema-base.md +1 -1
- package/payload/platform/plugins/memory/references/schema-construction.md +72 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +15 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -1
- package/payload/platform/plugins/slides/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/slides/LICENSE +21 -0
- package/payload/platform/plugins/slides/PLUGIN.md +18 -0
- package/payload/platform/plugins/slides/PROVENANCE.md +40 -0
- package/payload/platform/plugins/slides/commands/add-slide.md +29 -0
- package/payload/platform/plugins/slides/commands/slides-claus.md +39 -0
- package/payload/platform/plugins/slides/commands/slides-new-component.md +39 -0
- package/payload/platform/plugins/slides/commands/slides-outline.md +43 -0
- package/payload/platform/plugins/slides/commands/slides-review.md +52 -0
- package/payload/platform/plugins/slides/commands/slides-theme.md +64 -0
- package/payload/platform/plugins/slides/commands/slides.md +59 -0
- package/payload/platform/plugins/slides/skills/deck-system/REFERENCE.md +581 -0
- package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +607 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-board.md +426 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-claus.md +185 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-mbb.md +450 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-product-launch.md +579 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sales.md +464 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sequoia.md +489 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING.md +273 -0
- package/payload/platform/plugins/slides/skills/deck-system/deck-craft.html +1371 -0
- package/payload/platform/plugins/slides/skills/deck-system/deck-solid.html +1667 -0
- package/payload/platform/plugins/slides/skills/deck-system/deck.html +1359 -0
- package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/url-get/PLUGIN.md +26 -21
- package/payload/platform/plugins/url-get/mcp/dist/index.js +3 -3
- package/payload/platform/plugins/url-get/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts +1 -2
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts.map +1 -1
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js +20 -40
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +4 -0
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
- package/payload/platform/scripts/identity-forbidden-token-check.mjs +0 -1
- package/payload/platform/scripts/setup-account.sh +0 -15
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +23 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +29 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -2
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +5 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +32 -2
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +8 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts +13 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +26 -2
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +2 -2
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +12 -3
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +3 -2
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
- package/payload/platform/templates/specialists/agents/database-operator.md +3 -7
- package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +1 -1
- package/payload/server/{chunk-M6A6EZD4.js → chunk-76HRO7NX.js} +16 -2
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/AdminShell-T-YknnBn.js +1 -0
- package/payload/server/public/assets/Checkbox-DmDxpqVv.js +1 -0
- package/payload/server/public/assets/admin-COUV-jgt.js +1 -0
- package/payload/server/public/assets/{arc-aUiRP9AS.js → arc-B2CweJq3.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-Dnn6Hc65.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-c09loTER.js → architectureDiagram-Q4EWVU46-DP2o-MFV.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Cjdeyoq1.js → blockDiagram-DXYQGD6D-DO4mcYDJ.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-NY6Wlzo2.js → c4Diagram-AHTNJAMY-Sy1giHbj.js} +1 -1
- package/payload/server/public/assets/channel-CEpR_0rE.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BK3470lx.js → chunk-2KRD3SAO-CKsCYCsN.js} +1 -1
- package/payload/server/public/assets/chunk-336JU56O-C0-P-aUF.js +2 -0
- package/payload/server/public/assets/chunk-426QAEUC-DFjEt3Zb.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-BOvVdJLf.js → chunk-4BX2VUAB-B8bqAmBa.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BXpto3yW.js → chunk-4TB4RGXK-D1k0VSlW.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-BwZyF7vR.js → chunk-55IACEB6-B-p_QNqz.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-C403gCUk.js → chunk-5FUZZQ4R-D6U6tV_j.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-CjVzXQEp.js → chunk-5PVQY5BW-CYK76xfs.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-D5bhMrtY.js → chunk-67CJDMHE-BC9js-lf.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-Si7Lgrwc.js → chunk-7N4EOEYR-4j2OqKkv.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-DMuHtDqO.js → chunk-AA7GKIK3-Coen-fXN.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-L79XKVcb.js → chunk-BSJP7CBP-CAiOBvec.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-C0O7Upmg.js → chunk-CIAEETIT-AJzzpZVb.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-DJcJAsAg.js → chunk-EDXVE4YY-BL4BKozX.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-CFDNvYu1.js → chunk-ENJZ2VHE-mhAFG8UD.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-C_E43NFJ.js → chunk-FMBD7UC4-H231gZA_.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-D9lWWHAu.js → chunk-FOC6F5B3-Cl3ZZjYG.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-ecLOxGhL.js → chunk-ICPOFSXX-DOEzvzJa.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-DuhsNH4c.js → chunk-K5T4RW27-C_ipbUDD.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-B4-A1Abi.js → chunk-KGLVRYIC-CTsDNSCU.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-BxqgHRgT.js → chunk-LIHQZDEY-DvSXhkGf.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-DEYQ5WaJ.js → chunk-ORNJ4GCN-p574NOI7.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-B7MW66KB.js → chunk-OYMX7WX6-BlEgFM6U.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-DpF06ZZQ.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-BMawmsyk.js → chunk-U2HBQHQK-B2bDK0jv.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CT6g7pno.js → chunk-X2U36JSP-D69BxKFw.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-CBfZXZDB.js → chunk-XPW4576I-Dm-PcyUi.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-xeAluiAH.js → chunk-YZCP3GAM-Be8RnXgx.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-BRN9qUC5.js → chunk-ZZ45TVLE-Ck8PCTa4.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CYbXvKLI.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DEyHzRhq.js +1 -0
- package/payload/server/public/assets/clone-y8gexbBy.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-Br2gjtEO.js → cose-bilkent-S5V4N54A-CmkW2Eaj.js} +1 -1
- package/payload/server/public/assets/{dagre-DTjePoco.js → dagre-Dqp-ns8F.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-DHBkRke4.js → dagre-KV5264BT-ZgWWXPLc.js} +1 -1
- package/payload/server/public/assets/data-gy6QH9c1.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-BIq1-idL.js → diagram-5BDNPKRD-CTX5-ScM.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BsIUDzV6.js → diagram-G4DWMVQ6-BovIsO6H.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-CgHSri2i.js → diagram-MMDJMWI5-DcETsQy-.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-Ce2Wh9ZX.js → diagram-TYMM5635-yyq6peoZ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-BU0Kh6OQ.js → erDiagram-SMLLAGMA-CiNToftB.js} +1 -1
- package/payload/server/public/assets/{flatten-Bo6YRmWl.js → flatten-BtFI066E.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B0N06MF7.js → flowDiagram-DWJPFMVM-Xnl3SpIM.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BVbx4ARZ.js → ganttDiagram-T4ZO3ILL-C1iyWe0f.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-CNs-LD5i.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C-xRJ94t.js → gitGraphDiagram-UUTBAWPF-D97pbMQb.js} +1 -1
- package/payload/server/public/assets/graph-labels-cZu4pK16.js +1 -0
- package/payload/server/public/assets/{graph-g48ZcA5M.js → graph-qz5tFKqU.js} +3 -3
- package/payload/server/public/assets/{graphlib-YmNcoMjY.js → graphlib-Lq8ijgON.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-DsTNigSS.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-C_OarRTA.js +2 -0
- package/payload/server/public/assets/{isEmpty-D6Kr-M1M.js → isEmpty-D6QovjYR.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DTrq54yC.js → ishikawaDiagram-UXIWVN3A-B8XBdjJn.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-OZZZMrFX.js → journeyDiagram-VCZTEJTY-CZYbiOaQ.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY--w-IP9pN.js → kanban-definition-6JOO6SKY-B1PybFoh.js} +1 -1
- package/payload/server/public/assets/{line-Ckeulv5T.js → line-D-tw3hHp.js} +1 -1
- package/payload/server/public/assets/{linear-DOh_6k2k.js → linear-BHhXD3cd.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-CVRAxYRD.js → mermaid-parser.core-C9RAnysF.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-B-mE18I1.js → mermaid.core-B532LT1r.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Bm8mDicL.js → mindmap-definition-QFDTVHPH-DGlgeeTV.js} +1 -1
- package/payload/server/public/assets/{ordinal-BDi6f4xk.js → ordinal-Bl-aM5b9.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DGES22b-.js +1 -0
- package/payload/server/public/assets/pie-ZZUOXDRM-ChKeDbzt.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-BCmRLgGO.js → pieDiagram-DEJITSTG-DV9FIWko.js} +1 -1
- package/payload/server/public/assets/{public-DknO-g9S.js → public-Bu2_Xi0a.js} +5 -5
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CniTIUTm.js → quadrantDiagram-34T5L4WZ-Betwya4l.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-FGG5Fs7N.js +1 -0
- package/payload/server/public/assets/{reduce-CGi9ik8i.js → reduce-BD4xUd2c.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-CoxBSj9M.js → requirementDiagram-MS252O5E-Cq3vODdg.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BjS-4jzq.js → sankeyDiagram-XADWPNL6-x8krXWcS.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-B9jVOnPR.js → sequenceDiagram-FGHM5R23-i-_uH-Yl.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BvOQPzP8.js → stateDiagram-FHFEXIEX-il4KqSgI.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B6zNJ6Tv.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CdfgWLo1.js → timeline-definition-GMOUNBTQ-DATdZkA5.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-VAQQdbtf.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-DKchO3zI.js +1 -0
- package/payload/server/public/assets/useSelectionMode-A5KItZ2T.js +13 -0
- package/payload/server/public/assets/{brand-D0gNihp7.css → useSelectionMode-C-Ojh7W9.css} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-JCgpIbj-.js → vennDiagram-DHZGUBPP-BJh9tJTt.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-CBGtx0bS.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Dei3VqHo.js → wardleyDiagram-NUSXRM2D-EMN1Hdfg.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DUtIyoIb.js → xychartDiagram-5P7HB3ND-DbUWXa7T.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +5 -6
- package/payload/server/public/public.html +4 -5
- package/payload/server/server.js +525 -39
- package/payload/platform/plugins/admin/hooks/__tests__/session-end-retrospective.test.sh +0 -396
- package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +0 -239
- package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +0 -214
- package/payload/server/public/assets/AdminShell-892Jy_rs.js +0 -1
- package/payload/server/public/assets/Checkbox-Bc2QzX9b.js +0 -1
- package/payload/server/public/assets/admin-D3K13ndi.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL--v-pJPNp.js +0 -1
- package/payload/server/public/assets/brand-CcN3dELF.js +0 -9
- package/payload/server/public/assets/channel-B1IT7to2.js +0 -1
- package/payload/server/public/assets/chunk-336JU56O-CdKRCIeE.js +0 -2
- package/payload/server/public/assets/chunk-426QAEUC-BybuQ3Ve.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-Bd-GrQM6.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-rjCize6i.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BORWOUt0.js +0 -1
- package/payload/server/public/assets/clone-Csqv5U6T.js +0 -1
- package/payload/server/public/assets/data-Br-pdljK.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-CI0s_tqn.js +0 -1
- package/payload/server/public/assets/graph-labels-BYH-IPCb.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-g3gYW7Qm.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-Di6oPQ_-.js +0 -2
- package/payload/server/public/assets/packet-4T2RLAQJ-CT0TB9HI.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-CXLe7TFF.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-DnPLBl-D.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-v4ND10uR.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-C3cb7Xwe.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-Dc7G3Bgm.js +0 -1
- package/payload/server/public/assets/useSelectionMode-DwsyptOw.js +0 -5
- package/payload/server/public/assets/wardley-RL74JXVD-DtgibWAt.js +0 -1
- /package/payload/server/public/assets/{_baseFor-Cam2PbSt.js → _baseFor-Cs8Y-rGh.js} +0 -0
- /package/payload/server/public/assets/{array-DYRGGQae.js → array-iHZP4KWJ.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-nWsJMTNI.js → cytoscape.esm-BR2GOQ8_.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-Du1XY3Dp.js → defaultLocale-B9aLeOTg.js} +0 -0
- /package/payload/server/public/assets/{dist-BzAsli7o.js → dist-DB-VPj_8.js} +0 -0
- /package/payload/server/public/assets/{init-B5BXBRcm.js → init-BNFRgqHM.js} +0 -0
- /package/payload/server/public/assets/{katex-HOUACuRw.js → katex-B-EfS3nw.js} +0 -0
- /package/payload/server/public/assets/{path-CNO468J-.js → path-DmWWdwp7.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-DRO6hWPh.js → rough.esm-Ci7Kjt46.js} +0 -0
- /package/payload/server/public/assets/{src-CWiyyVfn.js → src-C1jfwBq0.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Real Agent ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
|
|
4
|
-
content-hash: sha256:
|
|
4
|
+
content-hash: sha256:0c253f3a1c9946f4256daea47978fa363b3a6eef6875b4a417792393c4fc00e9
|
|
5
5
|
brand: realagent-code
|
|
6
6
|
product-name: Real Agent
|
|
7
7
|
---
|
|
@@ -174,7 +174,7 @@ Roles are installed during setup and listed when Maxy introduces itself. Some pr
|
|
|
174
174
|
|
|
175
175
|
Maxy maintains a graph database (Neo4j) of everything you've told it. People, conversations, preferences, and context are stored as connected nodes. When you ask Maxy something, it searches this graph to retrieve relevant context before responding.
|
|
176
176
|
|
|
177
|
-
**The recording loop.** Maxy dispatches `database-operator` inline at its own discretion when a write must complete before the assistant response ends. The full graph-completeness sweep runs
|
|
177
|
+
**The recording loop.** Maxy dispatches `database-operator` inline at its own discretion when a write must complete before the assistant response ends. The full graph-completeness sweep runs on demand: when you invoke the `/insight` admin skill, it runs a four-pass instruction and Maxy walks the session for any node, edge, or commitment that was discussed but not written in-flight, dispatches one `database-operator` Task per candidate write, then carries on in the same session.
|
|
178
178
|
|
|
179
179
|
The memory graph is stored on your Pi. It never leaves your network.
|
|
180
180
|
|
|
@@ -337,7 +337,7 @@ These are part of Maxy's foundation and cannot be disabled:
|
|
|
337
337
|
| `workflows` | Persistent named workflows — reusable instruction sets |
|
|
338
338
|
| `contacts` | CRM contact management — create, lookup, update, list |
|
|
339
339
|
| `prompt-optimiser` | Prompt optimiser — two modes. Chat-app mode turns a rough draft or task description into a single finished, copy-pasteable prompt tuned for Opus 4.7 adaptive thinking (claude.ai, Mac, iOS). In-session mode is applied automatically: a standing `UserPromptSubmit` directive hook (`admin/hooks/prompt-optimiser-directive.sh`) injects context every turn telling the admin agent to restate each non-trivial prompt through this skill and act on the restatement, skipped for one-word confirmations, slash-commands, and direct continuations. Compliance is behavioural — the hook steers the agent, it cannot force the skill call. |
|
|
340
|
-
| `url-get` | Faithful page retrieval — fetches a server-rendered page, writes a verbatim markdown copy to an account-scoped reference file (no model in the path, so no copyright refusal), and returns
|
|
340
|
+
| `url-get` | Faithful page retrieval — fetches a server-rendered page, writes a verbatim markdown copy to an account-scoped reference file (no model in the path, so no copyright refusal), and returns the cleaned page text (capped) plus the file path. No summary and no subprocess: a caller that wants a summary invokes url-get from a delegated subagent. Use instead of WebFetch when a faithful copy is needed (e.g. ingesting your own published writing). |
|
|
341
341
|
|
|
342
342
|
### Maxy Plugins (user-selectable)
|
|
343
343
|
|
|
@@ -1541,6 +1541,10 @@ Every node also carries a provenance stamp — which agent wrote it, in which se
|
|
|
1541
1541
|
|
|
1542
1542
|
**Two write surfaces, one substrate.** General agents write through schema-aware helpers — Maxy can record a new contact, a new commitment, a new preference without ever typing a database query, and the helper enforces the connection-and-provenance rule above structurally. The graph-steward role (the specialist Maxy dispatches when you ask for graph hygiene — "merge those two duplicate contacts," "wire those four tasks to the meeting," "rename the legacy label across the graph") additionally has a raw Cypher write tool for the multi-step operations the helpers cannot express. The steward role internalises the same connection-and-provenance discipline in its prompt; a post-write audit emits a warning on every breach so the same rules apply to both surfaces. Both paths feed the same hourly orphan trend and the same forensic provenance fields — read-side, you cannot tell the two apart, and that is the point.
|
|
1543
1543
|
|
|
1544
|
+
## Vertical schemas
|
|
1545
|
+
|
|
1546
|
+
On top of the base graph, each brand boots one optional **vertical** — an extra set of entity types tailored to a trade. The vertical is named by `brand.json#vertical` and defined in a `schema-<name>.md` reference; the memory plugin loads it at startup and validates every write against base + the active vertical. Real Agent boots `schema-estate-agent` (Listing, Property, Viewing, Offer). SiteOffice boots `schema-construction`, which adds the building-contractor entities — `Job`, `LineItem`, `Valuation`, `Milestone`, `QuoteDocument`, `VariationNote`, `InboundInvoice`, `SubContractor`, `TimeLog`, `SubInvoice`, `WhatsAppGroup` — grounded in real builder job folders so a job's quote, valuations, variations, supplier invoices, and subcontractor timesheets all hang off one `Job` node. The default Maxy brand boots no vertical (base graph only).
|
|
1547
|
+
|
|
1544
1548
|
## Public-facing summaries for customer-readable subjects
|
|
1545
1549
|
|
|
1546
1550
|
Some entities in your graph are knowable by people outside your team — companies you work with, projects you've delivered, the business itself. For those entities (Maxy treats `:Organization`, `:Concept`, `:Project`, and `:LocalBusiness` this way), Maxy maintains two summaries: a private one only you and your specialist agents see, and a customer-facing public one your public agents are allowed to surface.
|
|
@@ -1656,6 +1660,42 @@ This means you can always trace a finished piece of work back to the Task that a
|
|
|
1656
1660
|
|
|
1657
1661
|
Cross-account access is refused. A Task that belongs to a different account on the same install is invisible to this loop — Maxy will not read it, name it, or surface it.
|
|
1658
1662
|
|
|
1663
|
+
---
|
|
1664
|
+
# Slides
|
|
1665
|
+
Source: https://docs.getmaxy.com/slides.md
|
|
1666
|
+
|
|
1667
|
+
# Slides — user guide
|
|
1668
|
+
|
|
1669
|
+
The Slides plugin turns a description into a finished, self-contained HTML slide deck. The output is one `deck.html` file — inline CSS and JavaScript, no build step, no dependencies beyond Google Fonts. Open it in any browser, navigate with arrow keys or swipe, and press `P` to export to PDF.
|
|
1670
|
+
|
|
1671
|
+
## When to use it
|
|
1672
|
+
|
|
1673
|
+
- You need a deck and want to describe what to say rather than format slides by hand.
|
|
1674
|
+
- You have an existing `deck.html` and want to add slides, restyle it, or get a critique.
|
|
1675
|
+
- You want a presentation that lives as plain text — version-controllable, diffable, and readable without a binary editor.
|
|
1676
|
+
|
|
1677
|
+
## The commands
|
|
1678
|
+
|
|
1679
|
+
- **`/slides`** — generate a complete deck from a description. Auto-detects the best storytelling format (talk, pitch, sales, board, product launch) and writes a single `deck.html`. You can pass the brief inline (`/slides "a 20-minute talk on AI-assisted development"`) or run it bare and describe in the follow-up.
|
|
1680
|
+
- **`/slides-outline`** — draft just the structure (section-by-section) without producing HTML, so you can agree the narrative first.
|
|
1681
|
+
- **`/add-slide`** — insert one or more slides into an existing deck, matching its theme and components.
|
|
1682
|
+
- **`/slides-theme`** — restyle a deck. Three built-in themes: **Default** (warm, editorial), **Craft** (richer textures, art overlays), **Solid** (glass morphism, gradients). Any other argument is treated as a custom theme described in text or extracted from an attached image.
|
|
1683
|
+
- **`/slides-review`** — critique the current deck on storytelling, design, and voice consistency.
|
|
1684
|
+
- **`/slides-new-component`** — build a new reusable slide component aligned with the design system's tokens.
|
|
1685
|
+
- **`/slides-claus`** — generate a deck using the Solid theme with the Claus storytelling structure.
|
|
1686
|
+
|
|
1687
|
+
## Storytelling formats
|
|
1688
|
+
|
|
1689
|
+
`/slides` routes to one of six narrative structures based on your brief: conference **talk** (TED-style), **Sequoia** investor pitch, McKinsey **SCR** (situation-complication-resolution), **product launch**, **board update**, and **sales**. Name the format in your brief to force one explicitly.
|
|
1690
|
+
|
|
1691
|
+
## What you get
|
|
1692
|
+
|
|
1693
|
+
A 25-component design system (title slides, metric cards, quotes, comparison tables, timelines, and more), responsive layout, and three interchangeable themes — all inside one portable file.
|
|
1694
|
+
|
|
1695
|
+
## Notes
|
|
1696
|
+
|
|
1697
|
+
This is a frozen, vendored copy of the open-source Slides™ framework (MIT). It ships installed and available on every account; enable it per session like any other plugin if it is not already active.
|
|
1698
|
+
|
|
1659
1699
|
---
|
|
1660
1700
|
# Telegram
|
|
1661
1701
|
Source: https://docs.getmaxy.com/telegram-guide.md
|
|
@@ -1992,33 +2032,20 @@ Diagnostic path: `grep -E '^\[aeo-' platform-logs/*.log | grep <urlOrEntityId>`.
|
|
|
1992
2032
|
# Session Retrospective
|
|
1993
2033
|
Source: https://docs.getmaxy.com/session-retrospective.md
|
|
1994
2034
|
|
|
1995
|
-
#
|
|
2035
|
+
# Insight pass
|
|
1996
2036
|
|
|
1997
|
-
When you
|
|
2037
|
+
When you type `/insight` on its own in an admin session, the admin agent runs one extra review over the session so far, then carries on. It walks the conversation and writes down four kinds of thing that would otherwise be lost:
|
|
1998
2038
|
|
|
1999
2039
|
- corrections and learnings you gave the agent during the session,
|
|
2000
2040
|
- tonal and working-style preferences worth carrying forward,
|
|
2001
2041
|
- people, decisions, commitments, or business facts that came up but were not yet saved to the graph,
|
|
2002
2042
|
- typed edges between any new prose-bearing nodes (messages, meetings, notes, pages) and the entities they mention — the auto-extraction pass that "wires the graph" so future questions can hop from a person to the companies they founded to the events they attended.
|
|
2003
2043
|
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
The extra turn is one or two messages from the agent, then a short summary of what was written. It runs inside the same session you were already in; nothing happens in the background, no second session is spawned. The typed-edge pass itself is delegated to the `database-operator` specialist so the writes land where graph writes are supposed to live.
|
|
2007
|
-
|
|
2008
|
-
## When the retrospective is skipped
|
|
2044
|
+
You can run it whenever you want the brain brought up to date — for example before you open a second session that needs the first session's learnings, preferences, or graph writes.
|
|
2009
2045
|
|
|
2010
|
-
|
|
2011
|
-
- Closing the browser tab or losing power closes the session without the retrospective. The mid-session recording route (the agent writes facts as they come up) is the primary safety net; the retrospective is the catch-net for what slips through.
|
|
2046
|
+
The pass is one or two messages from the agent, then a short summary of what was written. It runs inside the session you are already in: nothing happens in the background, no second session is spawned, and the session is not closed, reset, or cleared — the conversation continues straight afterward against the same live state. The typed-edge pass itself is delegated to the `database-operator` specialist so the writes land where graph writes are supposed to live.
|
|
2012
2047
|
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
## Skip-rate visibility
|
|
2016
|
-
|
|
2017
|
-
At the start of every admin session, the agent checks how many of your recent sessions closed without firing the retrospective. If any did, it surfaces one line — for example, "the last 10 sessions: 4 ended without a retrospective; their typed edges land at the next `/end`." This is informational, not nagging — it lets you choose to end the next session properly so the deferred extraction lands sooner.
|
|
2018
|
-
|
|
2019
|
-
## What you see if the agent tries to skip it
|
|
2020
|
-
|
|
2021
|
-
If the agent replies with a prose summary of "what it learned" without actually performing the retrospective, the session does not close — the Stop gate blocks until the agent calls the deterministic completion tool. You can tell it happened correctly by the final reply naming the five counts (learnings, tonal observations, graph updates, typed edges accepted, prose nodes scanned); the absence of those counts is the signal that something went wrong.
|
|
2048
|
+
You can tell the pass ran correctly by the final reply naming the five counts (learnings, tonal observations, graph updates, typed edges accepted, prose nodes scanned). The typed-edge pass is scoped by "what changed since the last completed insight pass," so two passes in a row never re-process the same nodes, and a session that never runs one simply defers its extraction to the next time you type `/insight`.
|
|
2022
2049
|
|
|
2023
2050
|
---
|
|
2024
2051
|
# Visitor Graph
|
|
@@ -2175,7 +2202,7 @@ Voice mirror is on by default for every drafting skill. To opt out for one, set
|
|
|
2175
2202
|
|
|
2176
2203
|
## Status
|
|
2177
2204
|
|
|
2178
|
-
Voice mirror is live end-to-end. Six corpus formats (text, email, social-post, article, note, marketing-copy), five tools (`voice-tag-content`, `voice-distil-profile`, `voice-retrieve-conditioning`, `voice-record-feedback`, `voice-ingest-session-text`),
|
|
2205
|
+
Voice mirror is live end-to-end. Six corpus formats (text, email, social-post, article, note, marketing-copy), five tools (`voice-tag-content`, `voice-distil-profile`, `voice-retrieve-conditioning`, `voice-record-feedback`, `voice-ingest-session-text`), on-demand session-turn capture, and wiring into the three live drafting surfaces (email composition, property brochures, investor data room) are all live. When no voice profile exists on the account for a given format, every drafting skill degrades gracefully — the output matches what it was before voice mirror was installed.
|
|
2179
2206
|
|
|
2180
2207
|
---
|
|
2181
2208
|
# Admin UI Reference
|
|
@@ -2229,7 +2256,7 @@ either is a regression.
|
|
|
2229
2256
|
| `/sessions` | Legacy admin-server conversation routes. No UI consumer remains after the ConversationsModal was retired; the surviving handlers are deletion candidates and not described here. | (legacy, no live caller) |
|
|
2230
2257
|
| `/sidebar-sessions` | Sole data path for the sidebar Sessions list (Tasks 538 + 543). One JSONL on disk equals one row. The row's delete button (Task 543) is the only way a row disappears. Each row carries `sessionId`, `title`, `startedAt`, `live`, `isSubagent`, `pid: number \| null` (basename of the matched `sessions/<pid>.json`), and `projectDir` (the directory holding the JSONL — consumed by the delete route). The payload also carries top-level `accountId` so the pane renders the full UUID label whose first ~8 chars prefix-match the truncated Remote Control daemon entry in claude.ai/code. The legacy `rcUrl` field is gone (Task 543) — the row's external-link affordance now POSTs `/session-rc-spawn` to start a fresh local `claude --remote-control <name> --session-id <sid>` PTY on every click. | `GET /` |
|
|
2231
2258
|
| `/session-delete` | POST `{ sessionId, projectDir }` (Task 543). Best-effort SIGTERM of the live PID (resolved from `sessions/<pid>.json` body match) then unlink the JSONL + `<sid>.meta.json` sidecar. Absent PID file is not an error. Containment: `projectDir` must live under `<CLAUDE_CONFIG_DIR>/projects/`. | `POST /` |
|
|
2232
|
-
| `/session-rc-spawn` | POST `{ sessionId?, name? }` (Task 543). Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
|
|
2259
|
+
| `/session-rc-spawn` | POST `{ sessionId?, name? }` (Task 543). Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (Task 648, raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. The Sidebar navigates the opened tab to `claude.ai/code/session_<id>` on `outcome=bound`; on `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
|
|
2233
2260
|
| `/claude-sessions` | **Spawn surface only** (Task 500). `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (Task 626 removed the recorder loopback caller; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
|
|
2234
2261
|
|
|
2235
2262
|
Task 500 — **admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot. The maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
|
|
@@ -2466,6 +2493,8 @@ When a search is active and you click a node, the neighbourhood you pivot into i
|
|
|
2466
2493
|
|
|
2467
2494
|
Searches reach **every textual property** of every operator-meaningful label, including denormalised fields the platform writes specifically so search can reach them — for example, the current job title of each LinkedIn connection (originally stored on the connection edge, copied to the Person node so the fulltext index can match it).
|
|
2468
2495
|
|
|
2496
|
+
Search behaves the same here, in the agent's own memory recall, and on the `/data` page: with **no filter chips selected** a search reaches **all** labels — the same scope the agent sees — and every surface applies the **same default relevance floor**, so the same query returns the same nodes everywhere. There is no longer a "select a chip first" gate; an empty chip set means "search everything". Selecting chips narrows the result to those labels.
|
|
2497
|
+
|
|
2469
2498
|
## Conversation label tiers
|
|
2470
2499
|
|
|
2471
2500
|
Conversation nodes carry the most operator-meaningful identity in the
|
|
@@ -2624,9 +2653,9 @@ How Maxy's graph wires itself.
|
|
|
2624
2653
|
|
|
2625
2654
|
## Typed-edge auto-extraction
|
|
2626
2655
|
|
|
2627
|
-
|
|
2656
|
+
When the operator types `/insight`, the admin agent delegates one pass to the `database-operator` specialist. That pass reads every prose-bearing node your account wrote since the last completed insight pass — messages, meetings, notes, pages, posts, reports, emails, ideas — and asks Claude Haiku to propose typed edges from the text. Only edges that match a closed allowlist of `(sourceLabel, EDGE_TYPE, targetLabel)` shapes are MERGEd into the graph. The graph wires itself; you do not have to ask for it.
|
|
2628
2657
|
|
|
2629
|
-
If a session
|
|
2658
|
+
If a session never runs an insight pass, its prose nodes are not lost — the next `/insight`, in that session or a later one, picks them up, because the pass is scoped by what changed since the last completed one rather than by which session wrote it. The cost of skipping is a delay, not lost extraction.
|
|
2630
2659
|
|
|
2631
2660
|
## Typed-edge allowlist
|
|
2632
2661
|
|
|
@@ -2777,7 +2806,11 @@ Indexed labels: `Question`, `DefinedTerm`, `Review`, `Service`, `Person`, `Local
|
|
|
2777
2806
|
|
|
2778
2807
|
### Embedding lifecycle
|
|
2779
2808
|
|
|
2780
|
-
Embeddings are computed
|
|
2809
|
+
Embeddings are computed at write time for **every** node of a vector-indexed label, on every write path — the per-node tools (`memory-write`, `memory-ingest`, `profile-update`, `project-create`), the bulk archive ingest (`memory-archive-write`: LinkedIn / Obsidian / Notion), the conversation-insight emitters, and the raw-Cypher admin/scheduling/UI paths. Small entities embed a bounded props representation; document/archive labels embed a bounded `summary` plus per-`:Section` body embeddings (the archive path uses a deterministic sectioniser since it has no LLM classifier). The authoritative indexed-label set is `VECTOR_INDEXED_LABELS` in `platform/lib/graph-write`, pinned to `schema.cypher` by a drift test.
|
|
2810
|
+
|
|
2811
|
+
If Ollama is unavailable at write time, the node is stored without an embedding (property-searchable, not vector-searchable) and a `[graph-write] warn reason=embed-failed` line is emitted — a failed embed never aborts the write. The two standing audits in the UI server's `graph-health` timer surface any backlog: `[embed-audit] null-embedding labels=… count=N` and `[account-audit] null-account labels=… count=N` (both healthy at 0).
|
|
2812
|
+
|
|
2813
|
+
The `memory-reindex` tool backfills missing embeddings by iterating nodes where `embedding IS NULL`. It uses the bounded representation (the `summary` for document/archive labels, never the raw body), embeds in batches with a per-node fallback on batch error, and **skips and continues** past a failing node — keeping skipped nodes out of the re-fetch via an exclude set — instead of aborting the whole run. `embed()`/`embedBatch()` cap oversized input (`EMBED_INPUT_MAX_CHARS`) before the Ollama POST, so a large body embeds truncated rather than throwing. Per-node `[reindex] op=embedded|skip-error` lines and a terminal `[reindex] op=done processed=N skipped=M`.
|
|
2781
2814
|
|
|
2782
2815
|
---
|
|
2783
2816
|
|
|
@@ -2913,6 +2946,13 @@ When `search` is true and `query` is non-null, the rewritten query replaces the
|
|
|
2913
2946
|
|
|
2914
2947
|
The public agent is toolless by construction (Task 615): it has no `memory-search`, no graph access mid-turn, and no tools of any kind. KNOWLEDGE.md (when present) plus SOUL are assembled into the agent's system prompt at spawn time and are the entire knowledge surface. Every `role=public` spawn (webchat, whatsapp, telegram) resolves an empty allowlist and runs in `dontAsk` (Task 506) with a per-spawn `permissions.deny` covering every native, harness, and memory-MCP tool (Task 612). The spawner anchors the empty allowlist with a single non-native deny-basis token (`mcp__none__deny-basis`) so `--allowed-tools` is always present and native-excluding (Task 609) — without it, `dontAsk` would have nothing to deny against and the brand `allow:["*"]` would re-open native tools.
|
|
2915
2948
|
|
|
2949
|
+
### The canonical public-agent locator (Task 638)
|
|
2950
|
+
|
|
2951
|
+
There is exactly one place each datum is read from, and every subsystem reads it the same way:
|
|
2952
|
+
|
|
2953
|
+
- **Default agent + account id** come from the canonical account config `data/accounts/<id>/account.json`, resolved via `resolveAccount` / `resolveDefaultAgentSlug` / `getDefaultAccountId` (`app/lib/claude-agent/account.ts`). The UI server's bare-root handler and branding loader read it through these helpers — never from `~/.<brand>/account.json`, which nothing writes. A `null` default means a genuinely unset `defaultAgent`; the root logs `[public-root] op=serve-default slug=<s>` on success and `op=no-default` only when the canonical default is truly empty.
|
|
2954
|
+
- **Identity files** (IDENTITY.md, SOUL.md, KNOWLEDGE.md) come from `agents/<slug>/` — keyed on the agent's slug, never the literal role. A public agent renamed to a slug `≠ "public"` (e.g. `maxy-info`) spawns from `agents/maxy-info/`. Admin reads `agents/admin/`. The spawn composer and the standing reachability audit resolve this directory through one shared function, `resolveAgentIdentityDir(accountDir, role, slug)` (`claude-session-manager/src/agent-identity-locator.ts`), so the path the audit vouches for is byte-identical to the path the spawn reads — the audit's `reachable=true` implies the spawn will find the files, and a slug whose files are misplaced is reported `reachable=false reason=files-missing file=<path>` without a visitor request.
|
|
2955
|
+
|
|
2916
2956
|
### Observability
|
|
2917
2957
|
|
|
2918
2958
|
Admin: `[admin-query-classifier]` log line with `topicChange`, `topicChangeConfidence`, `existingTopic`, `latencyMs`.
|
|
@@ -3289,6 +3329,20 @@ There is no onboarding state machine. At install time the installer writes three
|
|
|
3289
3329
|
|
|
3290
3330
|
Grep for both in `~/.<brand>/logs/install-*.log`. Absence after a clean install is the failure signal.
|
|
3291
3331
|
|
|
3332
|
+
## Plugin cache refresh on upgrade
|
|
3333
|
+
|
|
3334
|
+
Claude Code loads each platform plugin's skills, commands, and MCP from a per-install snapshot under `~/.<brand>/.claude/plugins/cache/<marketplace>/<plugin>/<version>/`, recorded as `installPath` in `installed_plugins.json` — not from the live tree. The local marketplaces (`maxy-platform`, `maxy-premium-*`) are *directory sources*: an upgrade overwrites their tree in place with no version bump. `claude plugin install` and `claude plugin update` both short-circuit on the unchanged version, so the snapshot would otherwise freeze at first-install time and newly-shipped skills would never register (Task 643).
|
|
3335
|
+
|
|
3336
|
+
The installer therefore **resyncs every directory-source plugin on every run**: `claude plugin uninstall` then `claude plugin install`, the only sequence that rebuilds the snapshot from the live tree. Remote marketplaces (the Anthropic ones, GitHub externals) keep version-pinned idempotence. Diagnostic lines on the Pi:
|
|
3337
|
+
|
|
3338
|
+
```
|
|
3339
|
+
[plugin-install] recache <name>@<marketplace>
|
|
3340
|
+
[plugin-install] audit <name>@<marketplace> live-skills=<n> cache-skills=<m>
|
|
3341
|
+
[plugin-install] WARN cache-drift <name>@<marketplace> live-skills=<n> cache-skills=<m>
|
|
3342
|
+
```
|
|
3343
|
+
|
|
3344
|
+
Grep `~/.<brand>/logs/install-*.log`. After an upgrade every directory-source plugin shows a `recache` line and an `audit` line whose `live-skills` and `cache-skills` counts are equal. A `WARN cache-drift` line — or unequal counts — means the snapshot did not fully rebuild and the running agent will see stale skills.
|
|
3345
|
+
|
|
3292
3346
|
The first user-domain write the agent attempts (e.g. recording who the operator is) hits the graph-write gate's `Write blocked (no-admin-user)` or `Write blocked (no-local-business)` error. The agent then asks the persona question, persists the answer through the `business-profile` skill or `profile-update.personFields`, and proceeds. The error itself is the signal — grep `Write blocked` in `~/.<brand>/logs/server.log` to confirm.
|
|
3293
3347
|
|
|
3294
3348
|
Cloudflare, WhatsApp, Telegram, and any other dormant capability surfaces on owner request via the `<dormant-plugins>` sentinel the manager injects per-spawn. Execution is the existing plugin skill (`cloudflare:cloudflare`, etc.) — no banner, no per-step flag.
|
|
@@ -3433,16 +3487,15 @@ Skills, agents, hooks, and commands directories at the plugin root are auto-disc
|
|
|
3433
3487
|
3. Snapshot `claude plugin list` once.
|
|
3434
3488
|
4. Build the desired plugin set = (every local marketplace's plugin entries) + (`brand.json#externalPlugins`).
|
|
3435
3489
|
5. For each desired plugin not in the snapshot, run `claude plugin install <name>@<marketplace> --scope user`. Already-installed plugins log `idempotent=true`. Failures log `[plugin-install] ERROR <name>@<src> exit=<n> stderr=<short>` but do not abort the installer — one plugin failing must not block the rest.
|
|
3436
|
-
|
|
3490
|
+
|
|
3491
|
+
External channel plugins (telegram, discord) are installed but not configured at install time. The operator pairs a channel by running `/<name>:configure <token>` in a real session; no token is read from the install environment.
|
|
3437
3492
|
|
|
3438
3493
|
**Brand declaration** — `brands/<brand>/brand.json#externalPlugins`:
|
|
3439
3494
|
|
|
3440
3495
|
```jsonc
|
|
3441
3496
|
"externalPlugins": [
|
|
3442
|
-
{ "name": "telegram", "marketplace": "claude-plugins-official",
|
|
3443
|
-
|
|
3444
|
-
{ "name": "discord", "marketplace": "claude-plugins-official",
|
|
3445
|
-
"configureSecret": "DISCORD_BOT_TOKEN", "channelPlugin": true },
|
|
3497
|
+
{ "name": "telegram", "marketplace": "claude-plugins-official", "channelPlugin": true },
|
|
3498
|
+
{ "name": "discord", "marketplace": "claude-plugins-official", "channelPlugin": true },
|
|
3446
3499
|
{ "name": "imessage", "marketplace": "claude-plugins-official", "channelPlugin": true }
|
|
3447
3500
|
]
|
|
3448
3501
|
```
|
|
@@ -24,6 +24,7 @@ Load these when users ask about Maxy features or need guidance:
|
|
|
24
24
|
- **Settings** → `references/settings.md` — output style, effort level, account preferences
|
|
25
25
|
- **Access Control** → `references/access-control.md` — who can chat with your public agent, invitations, authentication
|
|
26
26
|
- **Projects** → `references/projects-guide.md` — creating projects, tracking health, phase transitions, completing
|
|
27
|
+
- **Slides** → `references/slides.md` — generating, theming, and reviewing HTML slide decks with `/slides`
|
|
27
28
|
- **Troubleshooting** → `references/troubleshooting.md` — common issues and how to resolve them
|
|
28
29
|
|
|
29
30
|
## Platform Reference
|
|
@@ -46,7 +46,7 @@ either is a regression.
|
|
|
46
46
|
| `/sessions` | Legacy admin-server conversation routes. No UI consumer remains after the ConversationsModal was retired; the surviving handlers are deletion candidates and not described here. | (legacy, no live caller) |
|
|
47
47
|
| `/sidebar-sessions` | Sole data path for the sidebar Sessions list (Tasks 538 + 543). One JSONL on disk equals one row. The row's delete button (Task 543) is the only way a row disappears. Each row carries `sessionId`, `title`, `startedAt`, `live`, `isSubagent`, `pid: number \| null` (basename of the matched `sessions/<pid>.json`), and `projectDir` (the directory holding the JSONL — consumed by the delete route). The payload also carries top-level `accountId` so the pane renders the full UUID label whose first ~8 chars prefix-match the truncated Remote Control daemon entry in claude.ai/code. The legacy `rcUrl` field is gone (Task 543) — the row's external-link affordance now POSTs `/session-rc-spawn` to start a fresh local `claude --remote-control <name> --session-id <sid>` PTY on every click. | `GET /` |
|
|
48
48
|
| `/session-delete` | POST `{ sessionId, projectDir }` (Task 543). Best-effort SIGTERM of the live PID (resolved from `sessions/<pid>.json` body match) then unlink the JSONL + `<sid>.meta.json` sidecar. Absent PID file is not an error. Containment: `projectDir` must live under `<CLAUDE_CONFIG_DIR>/projects/`. | `POST /` |
|
|
49
|
-
| `/session-rc-spawn` | POST `{ sessionId?, name? }` (Task 543). Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
|
|
49
|
+
| `/session-rc-spawn` | POST `{ sessionId?, name? }` (Task 543). Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (Task 648, raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. The Sidebar navigates the opened tab to `claude.ai/code/session_<id>` on `outcome=bound`; on `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
|
|
50
50
|
| `/claude-sessions` | **Spawn surface only** (Task 500). `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (Task 626 removed the recorder loopback caller; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
|
|
51
51
|
|
|
52
52
|
Task 500 — **admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot. The maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
|
|
@@ -68,6 +68,20 @@ There is no onboarding state machine. At install time the installer writes three
|
|
|
68
68
|
|
|
69
69
|
Grep for both in `~/.<brand>/logs/install-*.log`. Absence after a clean install is the failure signal.
|
|
70
70
|
|
|
71
|
+
## Plugin cache refresh on upgrade
|
|
72
|
+
|
|
73
|
+
Claude Code loads each platform plugin's skills, commands, and MCP from a per-install snapshot under `~/.<brand>/.claude/plugins/cache/<marketplace>/<plugin>/<version>/`, recorded as `installPath` in `installed_plugins.json` — not from the live tree. The local marketplaces (`maxy-platform`, `maxy-premium-*`) are *directory sources*: an upgrade overwrites their tree in place with no version bump. `claude plugin install` and `claude plugin update` both short-circuit on the unchanged version, so the snapshot would otherwise freeze at first-install time and newly-shipped skills would never register (Task 643).
|
|
74
|
+
|
|
75
|
+
The installer therefore **resyncs every directory-source plugin on every run**: `claude plugin uninstall` then `claude plugin install`, the only sequence that rebuilds the snapshot from the live tree. Remote marketplaces (the Anthropic ones, GitHub externals) keep version-pinned idempotence. Diagnostic lines on the Pi:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
[plugin-install] recache <name>@<marketplace>
|
|
79
|
+
[plugin-install] audit <name>@<marketplace> live-skills=<n> cache-skills=<m>
|
|
80
|
+
[plugin-install] WARN cache-drift <name>@<marketplace> live-skills=<n> cache-skills=<m>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Grep `~/.<brand>/logs/install-*.log`. After an upgrade every directory-source plugin shows a `recache` line and an `audit` line whose `live-skills` and `cache-skills` counts are equal. A `WARN cache-drift` line — or unequal counts — means the snapshot did not fully rebuild and the running agent will see stale skills.
|
|
84
|
+
|
|
71
85
|
The first user-domain write the agent attempts (e.g. recording who the operator is) hits the graph-write gate's `Write blocked (no-admin-user)` or `Write blocked (no-local-business)` error. The agent then asks the persona question, persists the answer through the `business-profile` skill or `profile-update.personFields`, and proceeds. The error itself is the signal — grep `Write blocked` in `~/.<brand>/logs/server.log` to confirm.
|
|
72
86
|
|
|
73
87
|
Cloudflare, WhatsApp, Telegram, and any other dormant capability surfaces on owner request via the `<dormant-plugins>` sentinel the manager injects per-spawn. Execution is the existing plugin skill (`cloudflare:cloudflare`, etc.) — no banner, no per-step flag.
|
|
@@ -212,16 +226,15 @@ Skills, agents, hooks, and commands directories at the plugin root are auto-disc
|
|
|
212
226
|
3. Snapshot `claude plugin list` once.
|
|
213
227
|
4. Build the desired plugin set = (every local marketplace's plugin entries) + (`brand.json#externalPlugins`).
|
|
214
228
|
5. For each desired plugin not in the snapshot, run `claude plugin install <name>@<marketplace> --scope user`. Already-installed plugins log `idempotent=true`. Failures log `[plugin-install] ERROR <name>@<src> exit=<n> stderr=<short>` but do not abort the installer — one plugin failing must not block the rest.
|
|
215
|
-
|
|
229
|
+
|
|
230
|
+
External channel plugins (telegram, discord) are installed but not configured at install time. The operator pairs a channel by running `/<name>:configure <token>` in a real session; no token is read from the install environment.
|
|
216
231
|
|
|
217
232
|
**Brand declaration** — `brands/<brand>/brand.json#externalPlugins`:
|
|
218
233
|
|
|
219
234
|
```jsonc
|
|
220
235
|
"externalPlugins": [
|
|
221
|
-
{ "name": "telegram", "marketplace": "claude-plugins-official",
|
|
222
|
-
|
|
223
|
-
{ "name": "discord", "marketplace": "claude-plugins-official",
|
|
224
|
-
"configureSecret": "DISCORD_BOT_TOKEN", "channelPlugin": true },
|
|
236
|
+
{ "name": "telegram", "marketplace": "claude-plugins-official", "channelPlugin": true },
|
|
237
|
+
{ "name": "discord", "marketplace": "claude-plugins-official", "channelPlugin": true },
|
|
225
238
|
{ "name": "imessage", "marketplace": "claude-plugins-official", "channelPlugin": true }
|
|
226
239
|
]
|
|
227
240
|
```
|
|
@@ -12,6 +12,8 @@ When a search is active and you click a node, the neighbourhood you pivot into i
|
|
|
12
12
|
|
|
13
13
|
Searches reach **every textual property** of every operator-meaningful label, including denormalised fields the platform writes specifically so search can reach them — for example, the current job title of each LinkedIn connection (originally stored on the connection edge, copied to the Person node so the fulltext index can match it).
|
|
14
14
|
|
|
15
|
+
Search behaves the same here, in the agent's own memory recall, and on the `/data` page: with **no filter chips selected** a search reaches **all** labels — the same scope the agent sees — and every surface applies the **same default relevance floor**, so the same query returns the same nodes everywhere. There is no longer a "select a chip first" gate; an empty chip set means "search everything". Selecting chips narrows the result to those labels.
|
|
16
|
+
|
|
15
17
|
## Conversation label tiers
|
|
16
18
|
|
|
17
19
|
Conversation nodes carry the most operator-meaningful identity in the
|
|
@@ -89,7 +89,11 @@ Indexed labels: `Question`, `DefinedTerm`, `Review`, `Service`, `Person`, `Local
|
|
|
89
89
|
|
|
90
90
|
### Embedding lifecycle
|
|
91
91
|
|
|
92
|
-
Embeddings are computed
|
|
92
|
+
Embeddings are computed at write time for **every** node of a vector-indexed label, on every write path — the per-node tools (`memory-write`, `memory-ingest`, `profile-update`, `project-create`), the bulk archive ingest (`memory-archive-write`: LinkedIn / Obsidian / Notion), the conversation-insight emitters, and the raw-Cypher admin/scheduling/UI paths. Small entities embed a bounded props representation; document/archive labels embed a bounded `summary` plus per-`:Section` body embeddings (the archive path uses a deterministic sectioniser since it has no LLM classifier). The authoritative indexed-label set is `VECTOR_INDEXED_LABELS` in `platform/lib/graph-write`, pinned to `schema.cypher` by a drift test.
|
|
93
|
+
|
|
94
|
+
If Ollama is unavailable at write time, the node is stored without an embedding (property-searchable, not vector-searchable) and a `[graph-write] warn reason=embed-failed` line is emitted — a failed embed never aborts the write. The two standing audits in the UI server's `graph-health` timer surface any backlog: `[embed-audit] null-embedding labels=… count=N` and `[account-audit] null-account labels=… count=N` (both healthy at 0).
|
|
95
|
+
|
|
96
|
+
The `memory-reindex` tool backfills missing embeddings by iterating nodes where `embedding IS NULL`. It uses the bounded representation (the `summary` for document/archive labels, never the raw body), embeds in batches with a per-node fallback on batch error, and **skips and continues** past a failing node — keeping skipped nodes out of the re-fetch via an exclude set — instead of aborting the whole run. `embed()`/`embedBatch()` cap oversized input (`EMBED_INPUT_MAX_CHARS`) before the Ollama POST, so a large body embeds truncated rather than throwing. Per-node `[reindex] op=embedded|skip-error` lines and a terminal `[reindex] op=done processed=N skipped=M`.
|
|
93
97
|
|
|
94
98
|
---
|
|
95
99
|
|
|
@@ -225,6 +229,13 @@ When `search` is true and `query` is non-null, the rewritten query replaces the
|
|
|
225
229
|
|
|
226
230
|
The public agent is toolless by construction (Task 615): it has no `memory-search`, no graph access mid-turn, and no tools of any kind. KNOWLEDGE.md (when present) plus SOUL are assembled into the agent's system prompt at spawn time and are the entire knowledge surface. Every `role=public` spawn (webchat, whatsapp, telegram) resolves an empty allowlist and runs in `dontAsk` (Task 506) with a per-spawn `permissions.deny` covering every native, harness, and memory-MCP tool (Task 612). The spawner anchors the empty allowlist with a single non-native deny-basis token (`mcp__none__deny-basis`) so `--allowed-tools` is always present and native-excluding (Task 609) — without it, `dontAsk` would have nothing to deny against and the brand `allow:["*"]` would re-open native tools.
|
|
227
231
|
|
|
232
|
+
### The canonical public-agent locator (Task 638)
|
|
233
|
+
|
|
234
|
+
There is exactly one place each datum is read from, and every subsystem reads it the same way:
|
|
235
|
+
|
|
236
|
+
- **Default agent + account id** come from the canonical account config `data/accounts/<id>/account.json`, resolved via `resolveAccount` / `resolveDefaultAgentSlug` / `getDefaultAccountId` (`app/lib/claude-agent/account.ts`). The UI server's bare-root handler and branding loader read it through these helpers — never from `~/.<brand>/account.json`, which nothing writes. A `null` default means a genuinely unset `defaultAgent`; the root logs `[public-root] op=serve-default slug=<s>` on success and `op=no-default` only when the canonical default is truly empty.
|
|
237
|
+
- **Identity files** (IDENTITY.md, SOUL.md, KNOWLEDGE.md) come from `agents/<slug>/` — keyed on the agent's slug, never the literal role. A public agent renamed to a slug `≠ "public"` (e.g. `maxy-info`) spawns from `agents/maxy-info/`. Admin reads `agents/admin/`. The spawn composer and the standing reachability audit resolve this directory through one shared function, `resolveAgentIdentityDir(accountDir, role, slug)` (`claude-session-manager/src/agent-identity-locator.ts`), so the path the audit vouches for is byte-identical to the path the spawn reads — the audit's `reachable=true` implies the spawn will find the files, and a slug whose files are misplaced is reported `reachable=false reason=files-missing file=<path>` without a visitor request.
|
|
238
|
+
|
|
228
239
|
### Observability
|
|
229
240
|
|
|
230
241
|
Admin: `[admin-query-classifier]` log line with `topicChange`, `topicChangeConfidence`, `existingTopic`, `latencyMs`.
|
|
@@ -142,6 +142,10 @@ Every node also carries a provenance stamp — which agent wrote it, in which se
|
|
|
142
142
|
|
|
143
143
|
**Two write surfaces, one substrate.** General agents write through schema-aware helpers — {{productName}} can record a new contact, a new commitment, a new preference without ever typing a database query, and the helper enforces the connection-and-provenance rule above structurally. The graph-steward role (the specialist {{productName}} dispatches when you ask for graph hygiene — "merge those two duplicate contacts," "wire those four tasks to the meeting," "rename the legacy label across the graph") additionally has a raw Cypher write tool for the multi-step operations the helpers cannot express. The steward role internalises the same connection-and-provenance discipline in its prompt; a post-write audit emits a warning on every breach so the same rules apply to both surfaces. Both paths feed the same hourly orphan trend and the same forensic provenance fields — read-side, you cannot tell the two apart, and that is the point.
|
|
144
144
|
|
|
145
|
+
## Vertical schemas
|
|
146
|
+
|
|
147
|
+
On top of the base graph, each brand boots one optional **vertical** — an extra set of entity types tailored to a trade. The vertical is named by `brand.json#vertical` and defined in a `schema-<name>.md` reference; the memory plugin loads it at startup and validates every write against base + the active vertical. Real Agent boots `schema-estate-agent` (Listing, Property, Viewing, Offer). SiteOffice boots `schema-construction`, which adds the building-contractor entities — `Job`, `LineItem`, `Valuation`, `Milestone`, `QuoteDocument`, `VariationNote`, `InboundInvoice`, `SubContractor`, `TimeLog`, `SubInvoice`, `WhatsAppGroup` — grounded in real builder job folders so a job's quote, valuations, variations, supplier invoices, and subcontractor timesheets all hang off one `Job` node. The default Maxy brand boots no vertical (base graph only).
|
|
148
|
+
|
|
145
149
|
## Public-facing summaries for customer-readable subjects
|
|
146
150
|
|
|
147
151
|
Some entities in your graph are knowable by people outside your team — companies you work with, projects you've delivered, the business itself. For those entities ({{productName}} treats `:Organization`, `:Concept`, `:Project`, and `:LocalBusiness` this way), {{productName}} maintains two summaries: a private one only you and your specialist agents see, and a customer-facing public one your public agents are allowed to surface.
|
|
@@ -4,9 +4,9 @@ How Maxy's graph wires itself.
|
|
|
4
4
|
|
|
5
5
|
## Typed-edge auto-extraction
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
When the operator types `/insight`, the admin agent delegates one pass to the `database-operator` specialist. That pass reads every prose-bearing node your account wrote since the last completed insight pass — messages, meetings, notes, pages, posts, reports, emails, ideas — and asks Claude Haiku to propose typed edges from the text. Only edges that match a closed allowlist of `(sourceLabel, EDGE_TYPE, targetLabel)` shapes are MERGEd into the graph. The graph wires itself; you do not have to ask for it.
|
|
8
8
|
|
|
9
|
-
If a session
|
|
9
|
+
If a session never runs an insight pass, its prose nodes are not lost — the next `/insight`, in that session or a later one, picks them up, because the pass is scoped by what changed since the last completed one rather than by which session wrote it. The cost of skipping is a delay, not lost extraction.
|
|
10
10
|
|
|
11
11
|
## Typed-edge allowlist
|
|
12
12
|
|
|
@@ -62,7 +62,7 @@ Roles are installed during setup and listed when {{productName}} introduces itse
|
|
|
62
62
|
|
|
63
63
|
{{productName}} maintains a graph database (Neo4j) of everything you've told it. People, conversations, preferences, and context are stored as connected nodes. When you ask {{productName}} something, it searches this graph to retrieve relevant context before responding.
|
|
64
64
|
|
|
65
|
-
**The recording loop.** {{productName}} dispatches `database-operator` inline at its own discretion when a write must complete before the assistant response ends. The full graph-completeness sweep runs
|
|
65
|
+
**The recording loop.** {{productName}} dispatches `database-operator` inline at its own discretion when a write must complete before the assistant response ends. The full graph-completeness sweep runs on demand: when you invoke the `/insight` admin skill, it runs a four-pass instruction and {{productName}} walks the session for any node, edge, or commitment that was discussed but not written in-flight, dispatches one `database-operator` Task per candidate write, then carries on in the same session.
|
|
66
66
|
|
|
67
67
|
The memory graph is stored on your Pi. It never leaves your network.
|
|
68
68
|
|
|
@@ -27,7 +27,7 @@ These are part of {{productName}}'s foundation and cannot be disabled:
|
|
|
27
27
|
| `workflows` | Persistent named workflows — reusable instruction sets |
|
|
28
28
|
| `contacts` | CRM contact management — create, lookup, update, list |
|
|
29
29
|
| `prompt-optimiser` | Prompt optimiser — two modes. Chat-app mode turns a rough draft or task description into a single finished, copy-pasteable prompt tuned for Opus 4.7 adaptive thinking (claude.ai, Mac, iOS). In-session mode is applied automatically: a standing `UserPromptSubmit` directive hook (`admin/hooks/prompt-optimiser-directive.sh`) injects context every turn telling the admin agent to restate each non-trivial prompt through this skill and act on the restatement, skipped for one-word confirmations, slash-commands, and direct continuations. Compliance is behavioural — the hook steers the agent, it cannot force the skill call. |
|
|
30
|
-
| `url-get` | Faithful page retrieval — fetches a server-rendered page, writes a verbatim markdown copy to an account-scoped reference file (no model in the path, so no copyright refusal), and returns
|
|
30
|
+
| `url-get` | Faithful page retrieval — fetches a server-rendered page, writes a verbatim markdown copy to an account-scoped reference file (no model in the path, so no copyright refusal), and returns the cleaned page text (capped) plus the file path. No summary and no subprocess: a caller that wants a summary invokes url-get from a delegated subagent. Use instead of WebFetch when a faithful copy is needed (e.g. ingesting your own published writing). |
|
|
31
31
|
|
|
32
32
|
### {{productName}} Plugins (user-selectable)
|
|
33
33
|
|
|
@@ -1,27 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Insight pass
|
|
2
2
|
|
|
3
|
-
When you
|
|
3
|
+
When you type `/insight` on its own in an admin session, the admin agent runs one extra review over the session so far, then carries on. It walks the conversation and writes down four kinds of thing that would otherwise be lost:
|
|
4
4
|
|
|
5
5
|
- corrections and learnings you gave the agent during the session,
|
|
6
6
|
- tonal and working-style preferences worth carrying forward,
|
|
7
7
|
- people, decisions, commitments, or business facts that came up but were not yet saved to the graph,
|
|
8
8
|
- typed edges between any new prose-bearing nodes (messages, meetings, notes, pages) and the entities they mention — the auto-extraction pass that "wires the graph" so future questions can hop from a person to the companies they founded to the events they attended.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
You can run it whenever you want the brain brought up to date — for example before you open a second session that needs the first session's learnings, preferences, or graph writes.
|
|
11
11
|
|
|
12
|
-
The
|
|
12
|
+
The pass is one or two messages from the agent, then a short summary of what was written. It runs inside the session you are already in: nothing happens in the background, no second session is spawned, and the session is not closed, reset, or cleared — the conversation continues straight afterward against the same live state. The typed-edge pass itself is delegated to the `database-operator` specialist so the writes land where graph writes are supposed to live.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- Clicking the Archive button in the Sidebar closes the session directly and skips the retrospective. The four typed phrases above are the only signals that trigger it.
|
|
17
|
-
- Closing the browser tab or losing power closes the session without the retrospective. The mid-session recording route (the agent writes facts as they come up) is the primary safety net; the retrospective is the catch-net for what slips through.
|
|
18
|
-
|
|
19
|
-
Skipped sessions do not lose typed-edge work. The next session's retrospective picks up any prose nodes the previous session wrote, because the pass is scoped by "what changed since the last completed retrospective" — not by which session wrote it. The cost of skipping is one session of delay, not lost extraction.
|
|
20
|
-
|
|
21
|
-
## Skip-rate visibility
|
|
22
|
-
|
|
23
|
-
At the start of every admin session, the agent checks how many of your recent sessions closed without firing the retrospective. If any did, it surfaces one line — for example, "the last 10 sessions: 4 ended without a retrospective; their typed edges land at the next `/end`." This is informational, not nagging — it lets you choose to end the next session properly so the deferred extraction lands sooner.
|
|
24
|
-
|
|
25
|
-
## What you see if the agent tries to skip it
|
|
26
|
-
|
|
27
|
-
If the agent replies with a prose summary of "what it learned" without actually performing the retrospective, the session does not close — the Stop gate blocks until the agent calls the deterministic completion tool. You can tell it happened correctly by the final reply naming the five counts (learnings, tonal observations, graph updates, typed edges accepted, prose nodes scanned); the absence of those counts is the signal that something went wrong.
|
|
14
|
+
You can tell the pass ran correctly by the final reply naming the five counts (learnings, tonal observations, graph updates, typed edges accepted, prose nodes scanned). The typed-edge pass is scoped by "what changed since the last completed insight pass," so two passes in a row never re-process the same nodes, and a session that never runs one simply defers its extraction to the next time you type `/insight`.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Slides — user guide
|
|
2
|
+
|
|
3
|
+
The Slides plugin turns a description into a finished, self-contained HTML slide deck. The output is one `deck.html` file — inline CSS and JavaScript, no build step, no dependencies beyond Google Fonts. Open it in any browser, navigate with arrow keys or swipe, and press `P` to export to PDF.
|
|
4
|
+
|
|
5
|
+
## When to use it
|
|
6
|
+
|
|
7
|
+
- You need a deck and want to describe what to say rather than format slides by hand.
|
|
8
|
+
- You have an existing `deck.html` and want to add slides, restyle it, or get a critique.
|
|
9
|
+
- You want a presentation that lives as plain text — version-controllable, diffable, and readable without a binary editor.
|
|
10
|
+
|
|
11
|
+
## The commands
|
|
12
|
+
|
|
13
|
+
- **`/slides`** — generate a complete deck from a description. Auto-detects the best storytelling format (talk, pitch, sales, board, product launch) and writes a single `deck.html`. You can pass the brief inline (`/slides "a 20-minute talk on AI-assisted development"`) or run it bare and describe in the follow-up.
|
|
14
|
+
- **`/slides-outline`** — draft just the structure (section-by-section) without producing HTML, so you can agree the narrative first.
|
|
15
|
+
- **`/add-slide`** — insert one or more slides into an existing deck, matching its theme and components.
|
|
16
|
+
- **`/slides-theme`** — restyle a deck. Three built-in themes: **Default** (warm, editorial), **Craft** (richer textures, art overlays), **Solid** (glass morphism, gradients). Any other argument is treated as a custom theme described in text or extracted from an attached image.
|
|
17
|
+
- **`/slides-review`** — critique the current deck on storytelling, design, and voice consistency.
|
|
18
|
+
- **`/slides-new-component`** — build a new reusable slide component aligned with the design system's tokens.
|
|
19
|
+
- **`/slides-claus`** — generate a deck using the Solid theme with the Claus storytelling structure.
|
|
20
|
+
|
|
21
|
+
## Storytelling formats
|
|
22
|
+
|
|
23
|
+
`/slides` routes to one of six narrative structures based on your brief: conference **talk** (TED-style), **Sequoia** investor pitch, McKinsey **SCR** (situation-complication-resolution), **product launch**, **board update**, and **sales**. Name the format in your brief to force one explicitly.
|
|
24
|
+
|
|
25
|
+
## What you get
|
|
26
|
+
|
|
27
|
+
A 25-component design system (title slides, metric cards, quotes, comparison tables, timelines, and more), responsive layout, and three interchangeable themes — all inside one portable file.
|
|
28
|
+
|
|
29
|
+
## Notes
|
|
30
|
+
|
|
31
|
+
This is a frozen, vendored copy of the open-source Slides™ framework (MIT). It ships installed and available on every account; enable it per session like any other plugin if it is not already active.
|
|
@@ -61,4 +61,4 @@ Voice mirror is on by default for every drafting skill. To opt out for one, set
|
|
|
61
61
|
|
|
62
62
|
## Status
|
|
63
63
|
|
|
64
|
-
Voice mirror is live end-to-end. Six corpus formats (text, email, social-post, article, note, marketing-copy), five tools (`voice-tag-content`, `voice-distil-profile`, `voice-retrieve-conditioning`, `voice-record-feedback`, `voice-ingest-session-text`),
|
|
64
|
+
Voice mirror is live end-to-end. Six corpus formats (text, email, social-post, article, note, marketing-copy), five tools (`voice-tag-content`, `voice-distil-profile`, `voice-retrieve-conditioning`, `voice-record-feedback`, `voice-ingest-session-text`), on-demand session-turn capture, and wiring into the three live drafting surfaces (email composition, property brochures, investor data room) are all live. When no voice profile exists on the account for a given format, every drafting skill degrades gracefully — the output matches what it was before voice mirror was installed.
|
|
@@ -64,8 +64,8 @@ Manages the agent's own dedicated email account — IMAP for reading, SMTP for s
|
|
|
64
64
|
- **Setup:** `email-setup` — collect credentials in plain chat and connect IMAP/SMTP. Hosts are auto-inferred for known providers; supports alias addresses (`agentAddress`).
|
|
65
65
|
- **Read inbox:** `email-read` — metadata only (UID, sender, subject, date), plus a best-effort `Archive`/`Archive-Section` hint when the IMAP message's `receivedAt` falls inside a stored `:ConversationArchive {source:'email'}` section, plus an `Attachments (N): filename (mime, size); …` footer when the message carries enclosures. Supports pagination (`before_uid`), folders (`inbox`/`sent`), filtering by sender/date/subject. Metadata is derived from IMAP `bodyStructure` — no bytes downloaded.
|
|
66
66
|
- **Search inbox:** `email-search` — live IMAP search by sender, subject, body keyword, date range. Same per-archive hint and attachment footer as `email-read`.
|
|
67
|
-
- **Send:** `email-send` — new outbound email.
|
|
68
|
-
- **Reply:** `email-reply` — threaded reply to an existing email by `messageId`. Resolves the original envelope via IMAP `SEARCH HEADER Message-ID` (INBOX then `\Sent`), so threading works for any message still present on the server even if the graph never ingested it. Supports `replyAll
|
|
67
|
+
- **Send:** `email-send` — new outbound email. Pass `attachments` (absolute file paths under the account directory, ≤25 MB each) to attach files as SMTP attachments; an invalid path fails the send with no email dispatched.
|
|
68
|
+
- **Reply:** `email-reply` — threaded reply to an existing email by `messageId`. Resolves the original envelope via IMAP `SEARCH HEADER Message-ID` (INBOX then `\Sent`), so threading works for any message still present on the server even if the graph never ingested it. Supports `replyAll` and `attachments` (same path rules as `email-send`).
|
|
69
69
|
- **Ingestion — fetch:** `email-fetch` — list new IMAP messages since the stored high-water mark. Metadata + body preview only — including attachment names, mimetypes, and sizes so the operator sees what's attached before approving (Task 402). No bytes downloaded, no graph writes. Stages the batch in-memory for `email-ingest`.
|
|
70
70
|
- **Ingestion — apply:** `email-ingest` — apply the operator's per-message decisions to the staged batch. Each Message-ID must carry a disposition (`ingest` or `discard`). Approved messages land on `:ConversationArchive {source:'email'}` via the source-agnostic conversation-archive pipeline (one archive per thread, sessionised into `:Section` chunks). Attachment bytes are fetched, archived to `{accountDir}/archive/email/<uidValidity>-<uid>/<sha256>-<filename>` (0o600, 25 MB cap), and each attachment lands as a content-addressed `:DigitalDocument` keyed on `attachmentId = sha256(bytes)`; the `:HAS_ENCLOSURE` edge from the parent `:ConversationArchive` is wired by `memory-ingest` on its next pass via the `pendingArchiveEdges` queue (Task 402). Advances the inbox high-water mark only after a successful write.
|
|
71
71
|
- **Recall/history:** `email-graph-query` — search stored email archives in Neo4j by natural language, participant address, or date range. Each thread is one `:ConversationArchive {source:'email'}` with `:Section` chunks; operator participants attach via `:PARTICIPANT_IN` edges from `:Person`/`:AdminUser`. List mode surfaces a per-archive summary built from concatenated `:Section.summary` values; query mode runs vector search over the `section_embedding` index and dedups to the parent archive.
|
|
@@ -152,6 +152,10 @@ eagerTool(server, "email-send", "Send an email from the agent's email account vi
|
|
|
152
152
|
subject: z.string().describe("Email subject line"),
|
|
153
153
|
body: z.string().describe("Plain text email body"),
|
|
154
154
|
html: z.string().optional().describe("Optional HTML email body"),
|
|
155
|
+
attachments: z
|
|
156
|
+
.array(z.string())
|
|
157
|
+
.optional()
|
|
158
|
+
.describe("Absolute local file paths to attach as SMTP attachments. Each must be a regular file inside the account directory and ≤25 MB. Omit for a text-only message."),
|
|
155
159
|
}, async (params) => {
|
|
156
160
|
if (!accountId)
|
|
157
161
|
return refuseNoAccount("email-send");
|
|
@@ -262,6 +266,10 @@ eagerTool(server, "email-reply", "Reply to an email in-thread. Looks up the orig
|
|
|
262
266
|
body: z.string().min(1).describe("Plain text reply body"),
|
|
263
267
|
html: z.string().optional().describe("Optional HTML reply body"),
|
|
264
268
|
replyAll: z.boolean().optional().describe("If true, reply to all original recipients (To + CC). Default: false (reply to sender only)."),
|
|
269
|
+
attachments: z
|
|
270
|
+
.array(z.string())
|
|
271
|
+
.optional()
|
|
272
|
+
.describe("Absolute local file paths to attach as SMTP attachments. Each must be a regular file inside the account directory and ≤25 MB. Omit for a text-only reply."),
|
|
265
273
|
}, async (params) => {
|
|
266
274
|
if (!accountId)
|
|
267
275
|
return refuseNoAccount("email-reply");
|