@rubytech/create-maxy-code 0.1.23 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +63 -16
- package/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +50 -23
- package/payload/platform/plugins/admin/skills/admin-user-management/SKILL.md +47 -0
- package/payload/platform/plugins/admin/skills/commitment-followthrough/SKILL.md +60 -0
- package/payload/platform/plugins/admin/skills/file-presentation/SKILL.md +67 -0
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +111 -126
- package/payload/platform/plugins/admin/skills/session-management/SKILL.md +62 -0
- package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +37 -0
- package/payload/platform/plugins/cloudflare/references/manual-setup.md +81 -1
- package/payload/platform/plugins/cloudflare/scripts/__tests__/tunnel-ingress.test.ts +241 -0
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +267 -28
- package/payload/platform/plugins/cloudflare/scripts/tunnel-ingress.ts +291 -0
- package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +42 -0
- package/payload/platform/plugins/contacts/PLUGIN.md +18 -9
- package/payload/platform/plugins/deep-research/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/deep-research/PLUGIN.md +7 -1
- package/payload/platform/plugins/deep-research/recipes/README.md +36 -0
- package/payload/platform/plugins/deep-research/skills/academic-verify/SKILL.md +75 -0
- package/payload/platform/plugins/deep-research/skills/book-mirror/SKILL.md +68 -0
- package/payload/platform/plugins/deep-research/skills/data-research/SKILL.md +108 -0
- package/payload/platform/plugins/deep-research/skills/strategic-reading/SKILL.md +69 -0
- package/payload/platform/plugins/docs/references/deployment.md +3 -2
- package/payload/platform/plugins/docs/references/platform.md +2 -0
- package/payload/platform/plugins/docs/references/troubleshooting.md +12 -0
- package/payload/platform/plugins/email/PLUGIN.md +18 -9
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts +17 -0
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +185 -0
- package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js +34 -111
- package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts +7 -2
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +7 -2
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +2 -0
- package/payload/platform/plugins/memory/PLUGIN.md +64 -29
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts +3 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +105 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +16 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/skills/archive-crawler/SKILL.md +67 -0
- package/payload/platform/plugins/memory/skills/concept-synthesis/SKILL.md +80 -0
- package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +2 -0
- package/payload/platform/plugins/outlook/PLUGIN.md +14 -7
- package/payload/platform/plugins/replicate/PLUGIN.md +6 -3
- package/payload/platform/plugins/scheduling/PLUGIN.md +19 -8
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts +7 -3
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +7 -3
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +75 -0
- package/payload/platform/plugins/scheduling/skills/daily-prep/SKILL.md +61 -0
- package/payload/platform/plugins/tasks/PLUGIN.md +28 -14
- package/payload/platform/plugins/telegram/PLUGIN.md +6 -3
- package/payload/platform/plugins/waitlist/PLUGIN.md +12 -6
- package/payload/platform/plugins/whatsapp/PLUGIN.md +25 -13
- package/payload/platform/plugins/workflows/PLUGIN.md +16 -8
- package/payload/platform/scripts/conversation-id-allowlist.txt +0 -1
- 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 +27 -2
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +27 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +36 -0
- 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 +41 -3
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +25 -1
- 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 +54 -3
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +25 -0
- package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js +149 -0
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -0
- package/payload/platform/templates/agents/admin/IDENTITY.md +38 -284
- package/payload/platform/templates/agents/admin/SOUL.md +4 -4
- package/payload/platform/templates/specialists/agents/content-producer.md +24 -69
- package/payload/platform/templates/specialists/agents/database-operator.md +49 -155
- package/payload/platform/templates/specialists/agents/personal-assistant.md +27 -177
- package/payload/platform/templates/specialists/agents/project-manager.md +29 -96
- package/payload/platform/templates/specialists/agents/research-assistant.md +36 -78
- package/payload/premium-plugins/real-agency/agents/compliance.md +14 -0
- package/payload/premium-plugins/real-agency/agents/negotiator.md +22 -0
- package/payload/premium-plugins/real-agency/agents/valuer.md +16 -0
- package/payload/premium-plugins/real-agency/plugins/estate-business/.claude-plugin/plugin.json +1 -1
- package/payload/premium-plugins/real-agency/plugins/estate-business/PLUGIN.md +44 -13
- package/payload/premium-plugins/real-agency/plugins/estate-business/skills/commission-calculator/SKILL.md +40 -0
- package/payload/premium-plugins/real-agency/plugins/estate-business/skills/month-end-close/SKILL.md +69 -0
- package/payload/premium-plugins/real-agency/plugins/estate-business/skills/payment-batch-stager/SKILL.md +42 -0
- package/payload/premium-plugins/real-agency/plugins/estate-business/skills/period-reconciler/SKILL.md +42 -0
- package/payload/premium-plugins/real-agency/plugins/estate-sales/.claude-plugin/plugin.json +1 -1
- package/payload/premium-plugins/real-agency/plugins/estate-sales/PLUGIN.md +32 -13
- package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/chase-progression/SKILL.md +107 -0
- package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/risk-scorer/SKILL.md +42 -0
- package/payload/premium-plugins/real-agency/plugins/leads/.claude-plugin/plugin.json +1 -1
- package/payload/premium-plugins/real-agency/plugins/leads/PLUGIN.md +40 -10
- package/payload/premium-plugins/real-agency/plugins/leads/skills/chain-progression-tracker/SKILL.md +51 -0
- package/payload/premium-plugins/real-agency/plugins/leads/skills/diary-builder/SKILL.md +38 -0
- package/payload/premium-plugins/real-agency/plugins/leads/skills/enquiry-triage/SKILL.md +36 -0
- package/payload/premium-plugins/real-agency/plugins/leads/skills/morning-round/SKILL.md +72 -0
- package/payload/premium-plugins/real-agency/plugins/listings/.claude-plugin/plugin.json +1 -1
- package/payload/premium-plugins/real-agency/plugins/listings/PLUGIN.md +82 -12
- package/payload/premium-plugins/real-agency/plugins/listings/skills/comparable-finder/SKILL.md +52 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/epc-checker/SKILL.md +38 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/listing-copy-writer/SKILL.md +55 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/local-market-stats/SKILL.md +33 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/new-instruction/SKILL.md +78 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/particulars-builder/SKILL.md +48 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/portal-launch-scheduler/SKILL.md +49 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/pricing-scenario-builder/SKILL.md +35 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/supplier-booker/SKILL.md +39 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/talk-track-composer/SKILL.md +36 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/terms-of-business-drafter/SKILL.md +54 -0
- package/payload/premium-plugins/real-agency/plugins/listings/skills/valuation-prep/SKILL.md +69 -0
- package/payload/premium-plugins/real-agency/plugins/loop/PLUGIN.md +35 -0
- package/payload/premium-plugins/real-agency/plugins/loop/skills/compliance-flag-checker/SKILL.md +53 -0
- package/payload/premium-plugins/real-agency/plugins/loop/skills/priority-ranker/SKILL.md +40 -0
- package/payload/premium-plugins/real-agency/plugins/loop/skills/tone-matched-drafter/SKILL.md +53 -0
- package/payload/premium-plugins/real-agency/plugins/loop/skills/variance-narrator/SKILL.md +50 -0
- package/payload/premium-plugins/real-agency/plugins/loop/skills/vendor-research/SKILL.md +54 -0
- package/payload/server/{chunk-2ZNKHCQB.js → chunk-2MRZBQMH.js} +1 -1
- package/payload/server/{chunk-GPUCA2RQ.js → chunk-NL7QLVAD.js} +0 -192
- package/payload/server/{chunk-IDKWGLM5.js → chunk-YPZFYTYP.js} +1 -247
- package/payload/server/{cloudflare-task-tracker-LYI5BTYI.js → cloudflare-task-tracker-QVOGHKWV.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/package.json +0 -2
- package/payload/server/public/assets/{Checkbox-D1OQD43b.js → Checkbox-YIF0payo.js} +1 -1
- package/payload/server/public/assets/{admin-czNBxWor.js → admin-DW8IJcLc.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-BcwgT80u.js → architectureDiagram-Q4EWVU46-Bz8mlxZZ.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BMSyZUQA.js → blockDiagram-DXYQGD6D-DwV8Z8-i.js} +1 -1
- package/payload/server/public/assets/{brand-2cku8WFs.css → brand-DqiRNMlu.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DPRGY1jJ.js → c4Diagram-AHTNJAMY-DiUTejMp.js} +1 -1
- package/payload/server/public/assets/channel-PtVtoBEL.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-B7oQ3g1c.js → chunk-336JU56O-4mHZpBXe.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-C1P0yFXw.js → chunk-426QAEUC-Cbv0vrN9.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-LI7kOJd0.js → chunk-4TB4RGXK-BvLhId_2.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-CXQRGTQE.js → chunk-5FUZZQ4R-bBafOTkw.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-NSyzpXRy.js → chunk-5PVQY5BW-B0NqBKVy.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-voNwxbDs.js → chunk-EDXVE4YY-CFd4SqI6.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-CMEMPzYY.js → chunk-ENJZ2VHE-ajf2sb6c.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-hEbwu-pe.js → chunk-ICPOFSXX-pWg6bug7.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-DxskDrLs.js → chunk-OYMX7WX6-OjEd-17c.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-D7TKgUo0.js → chunk-U2HBQHQK-DbEFSPoh.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-BvPUQEPm.js → chunk-X2U36JSP-COdNwrBb.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-BY-RWQUW.js → chunk-YZCP3GAM-CHMWuY9B.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-DZvOYDY6.js → chunk-ZZ45TVLE-B-uDLQOB.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-RVH_SEhY.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Cm3rAb93.js +1 -0
- package/payload/server/public/assets/clone-BjY0Wzht.js +1 -0
- package/payload/server/public/assets/{dagre-KV5264BT-Cnj0mUZl.js → dagre-KV5264BT-CMEzmhIL.js} +1 -1
- package/payload/server/public/assets/{dagre-Bt-fpckL.js → dagre-bhIG_KnW.js} +1 -1
- package/payload/server/public/assets/data-K_kS__sL.js +1 -0
- package/payload/server/public/assets/{device-url-actions-Bjz3Xzbm.js → device-url-actions-AcOyLSeF.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-DjLzvOlx.js → diagram-5BDNPKRD-6RIoQhIL.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DTfuRd-T.js → diagram-G4DWMVQ6-BSp36TVv.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-BaL2mCnx.js → diagram-MMDJMWI5-D54fo52D.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-C5InWY5R.js → diagram-TYMM5635-CWL8z-Pq.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-DO7BXTpn.js → erDiagram-SMLLAGMA-AnnHBo3z.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-DDdAKfLf.js → flowDiagram-DWJPFMVM-laWmBl5o.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-arJD8Utm.js → ganttDiagram-T4ZO3ILL-B94ko8ie.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C55GH-OS.js → gitGraphDiagram-UUTBAWPF-DxzL1fxZ.js} +1 -1
- package/payload/server/public/assets/graph-DeEigyO_.js +1 -0
- package/payload/server/public/assets/graph-labels-C7I5QvNv.js +1 -0
- package/payload/server/public/assets/{graphlib-DL9PM7Ex.js → graphlib-CY-zIElM.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-BMSGqUbG.js → infoDiagram-42DDH7IO-BMTajIIr.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-Dw6BZ6BG.js → ishikawaDiagram-UXIWVN3A-B_QauE5O.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DrywUGXw.js → journeyDiagram-VCZTEJTY-DmlqSIih.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DuwtVBBc.js → kanban-definition-6JOO6SKY-ZGDQT7xB.js} +1 -1
- package/payload/server/public/assets/{line-JAksyKHj.js → line-D13opgep.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-BMq-ApBW.js → mermaid-parser.core-C650Sual.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-tH4oX0Kh.js → mermaid.core-BqnQoXTp.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-D1OiiJga.js → mindmap-definition-QFDTVHPH-BS_8y-tY.js} +1 -1
- package/payload/server/public/assets/{page-BZpoS7iR.js → page-B_rpjIRr.js} +1 -1
- package/payload/server/public/assets/{page-CkvBvezS.js → page-qSH972X0.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-Ckwm69PW.js → pieDiagram-DEJITSTG-B5OmNvBO.js} +1 -1
- package/payload/server/public/assets/{public-C-dTMgXu.js → public-DDsYgotk.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-COw3yZ1j.js → quadrantDiagram-34T5L4WZ-DTYITdNo.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DqGzM4K-.js → requirementDiagram-MS252O5E-CRZWxH06.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-D-l1c_Pl.js → sankeyDiagram-XADWPNL6-DazRENhe.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BeIi0DtJ.js → sequenceDiagram-FGHM5R23-BcHTxmPy.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-C-jgegLk.js → stateDiagram-FHFEXIEX-DYU7nbqg.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BgljVtlp.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BGFKkYmi.js → timeline-definition-GMOUNBTQ-BKGmqkST.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-5NuIhJLS.js → vennDiagram-DHZGUBPP-BXvLPmX7.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Be9ytVut.js → wardleyDiagram-NUSXRM2D-BCclUa3Z.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DCyHg41R.js → xychartDiagram-5P7HB3ND-C-Xp-Eoc.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 +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +1152 -2564
- package/payload/platform/scripts/check-sdk-oauth.mjs +0 -185
- package/payload/server/public/assets/channel-fxEghWew.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BsWzGW0N.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BGVa3h90.js +0 -1
- package/payload/server/public/assets/clone-Khvocke2.js +0 -1
- package/payload/server/public/assets/data-DBd-Buhp.js +0 -1
- package/payload/server/public/assets/graph-DUtVdnZ6.js +0 -1
- package/payload/server/public/assets/graph-labels-Dxfue-fP.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BaMs8Znv.js +0 -1
- /package/payload/server/public/assets/{brand-CSQuxS9w.js → brand-Bm671owU.js} +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: data-research
|
|
3
|
+
description: "Recipe-driven structured-data extraction. Takes a named recipe and a set of sources (emails, reports, web pages, forms, PDFs) and writes typed entities to the graph per the recipe's schema. Triggers when the owner says 'extract X from these emails', 'track investor updates', 'pull donation amounts', 'build a table of Y from these documents'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Data research
|
|
7
|
+
|
|
8
|
+
This skill turns unstructured-looking sources (emails, reports, forms, web pages) into structured graph entities. The transformation is always recipe-driven: a named YAML recipe declares what fields to extract, what validations to apply, and what graph nodes to write. The skill runs a named recipe; it never invents a schema on the fly.
|
|
9
|
+
|
|
10
|
+
**Default parent.** Every recipe declares its hierarchy parent via `graph_target.parent` — either `Project` (the run-time recipe argument names which Project elementId to attach to) or `LocalBusiness` (the account root, for cross-project recipes like investor-updates). The skill refuses to run a recipe whose `parent` field is missing or whose named Project does not exist. Per-row writes attach to that parent via the canonical containment edge; the recipe's `relationships:` block describes cross-hierarchy edges (e.g. `ROUND_FOR → Organization`) which are written separately and do not substitute for the parent.
|
|
11
|
+
|
|
12
|
+
## When to run
|
|
13
|
+
|
|
14
|
+
Run when the owner wants the same extraction repeated across many sources. The trigger phrases are above. Do not run for one-off extractions; a one-off is what `document-ingest` does.
|
|
15
|
+
|
|
16
|
+
## Inputs
|
|
17
|
+
|
|
18
|
+
| Input | Meaning |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `recipe` | The name of an existing recipe at `plugins/deep-research/recipes/<name>.yaml`. |
|
|
21
|
+
| `sources` | One or more source paths or URLs. Email thread paths, PDF paths, web URLs, or a folder. |
|
|
22
|
+
| `parent` | The Project elementId (or `LocalBusiness` for cross-project recipes) the writes anchor to. Required when the recipe's `parent` field is `Project`; ignored when the recipe's parent is `LocalBusiness` (the account root resolves automatically). |
|
|
23
|
+
|
|
24
|
+
If `recipe` does not match any file in the recipes directory, refuse. List the available recipe names. Do not invent a recipe.
|
|
25
|
+
|
|
26
|
+
If the owner asks for an extraction shape that no existing recipe covers, the answer is "no recipe exists for that yet. Want me to draft one?". The skill never extracts data without a recipe; that is the point of the recipe layer.
|
|
27
|
+
|
|
28
|
+
## Recipe shape
|
|
29
|
+
|
|
30
|
+
A recipe is a YAML file with this shape:
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
name: investor-updates
|
|
34
|
+
description: One-line description of what this recipe extracts.
|
|
35
|
+
source_kinds:
|
|
36
|
+
- email-thread
|
|
37
|
+
- web-page
|
|
38
|
+
- pdf
|
|
39
|
+
fields:
|
|
40
|
+
- name: company_name
|
|
41
|
+
type: string
|
|
42
|
+
required: true
|
|
43
|
+
- name: round
|
|
44
|
+
type: string
|
|
45
|
+
required: false
|
|
46
|
+
- name: amount_gbp
|
|
47
|
+
type: number
|
|
48
|
+
required: false
|
|
49
|
+
validation:
|
|
50
|
+
min: 0
|
|
51
|
+
- name: date_announced
|
|
52
|
+
type: date
|
|
53
|
+
required: true
|
|
54
|
+
graph_target:
|
|
55
|
+
label: FundingRound
|
|
56
|
+
parent: LocalBusiness # or `Project` — names the hierarchy anchor for every row
|
|
57
|
+
identity:
|
|
58
|
+
- company_name
|
|
59
|
+
- date_announced
|
|
60
|
+
relationships:
|
|
61
|
+
- type: ROUND_FOR
|
|
62
|
+
target_label: Organization
|
|
63
|
+
target_match: company_name
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Method
|
|
67
|
+
|
|
68
|
+
1. **Load and validate the recipe.** Read the recipe file. Check that every field declared has a `name` and `type`. Check that `graph_target.label` is a label in the live ontology (`maxy-graph-get_neo4j_schema`). Check that `graph_target.parent` is present and resolves (Project elementId supplied at call time, or `LocalBusiness` resolved from the account root). If anything fails, refuse and report the recipe's defect.
|
|
69
|
+
2. **Iterate sources.** For each source: classify by kind against `source_kinds`. Skip sources whose kind is not in the recipe's allowed list, list them in the report.
|
|
70
|
+
3. **Extract per source.** Fetch the source. Use Haiku-driven classification (`memory-classify` with a recipe-specific prompt) to extract each declared field. Apply each field's validation. Reject rows that fail required-field checks; capture them in a rejected list.
|
|
71
|
+
4. **Write to the graph.** For each accepted row, `memory-write` a node with the declared label and the extracted properties. Attach it to the resolved hierarchy parent via the canonical containment edge. Stamp `createdByAgent: data-research`, `createdByRecipe: <recipe name>`, `sourceDocumentId: <source>`. Write the declared cross-hierarchy relationships, resolving target nodes via `memory-search` on the named match property.
|
|
72
|
+
5. **Report.** Return one line per source (accepted count, rejected count) and one summary line: total rows written, total rejected, total relationships created.
|
|
73
|
+
|
|
74
|
+
## Output format
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
**Recipe.** <name>
|
|
78
|
+
**Sources.** <N> processed.
|
|
79
|
+
|
|
80
|
+
| Source | Accepted | Rejected | Reason |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| <source path or URL> | 3 | 1 | "amount_gbp negative" |
|
|
83
|
+
| ... | | | |
|
|
84
|
+
|
|
85
|
+
**Total.** 12 rows written as :<Label>, 9 relationships created via <RelType>.
|
|
86
|
+
**Rejections.** 3 rows rejected (full list below).
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Why recipes
|
|
90
|
+
|
|
91
|
+
A recipe is a contract. The owner reads the recipe and knows what will be written. The recipe is version-controlled and auditable. Without recipes, the skill would extract whatever the LLM thinks is interesting, which means the graph schema drifts with every run and the owner cannot trust what arrives. The recipe layer is the difference between a controlled pipeline and a junk shop.
|
|
92
|
+
|
|
93
|
+
## Failure modes
|
|
94
|
+
|
|
95
|
+
- **Recipe file is malformed.** Surface the YAML error literally and refuse.
|
|
96
|
+
- **Recipe declares a `graph_target.label` not in the ontology.** Refuse. Tell the owner the label is missing and recommend either adjusting the recipe or extending the ontology.
|
|
97
|
+
- **Recipe's `graph_target.parent` is missing or unresolvable.** Refuse. The hierarchy parent is mandatory; without it, every row would land as an orphan.
|
|
98
|
+
- **No sources match the recipe's allowed kinds.** Refuse. List what the recipe accepts.
|
|
99
|
+
- **Target-match relationship cannot resolve** (the recipe wants `ROUND_FOR -> Organization` and the named company is not in the graph). Capture in the rejected list with the reason "target organisation not found"; do not create a placeholder organisation.
|
|
100
|
+
- **Embedding service unavailable mid-batch.** Stop. Report which sources completed and which did not.
|
|
101
|
+
|
|
102
|
+
## Where recipes live
|
|
103
|
+
|
|
104
|
+
Recipes live at `platform/plugins/deep-research/recipes/<name>.yaml`. The directory is part of the plugin and ships with the platform. To author a new recipe, the owner names the extraction they want; the skill can scaffold the YAML and the owner reviews and saves it. Recipe authoring is a separate path; this skill consumes recipes, it does not write them inline.
|
|
105
|
+
|
|
106
|
+
## What this skill does not do
|
|
107
|
+
|
|
108
|
+
It does not run free-form extractions. It does not write to the graph without an approved recipe. It does not modify recipes during a run; if the recipe needs changing, the run aborts, the owner edits the recipe, and the run is re-issued.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: strategic-reading
|
|
3
|
+
description: "Reads a source (article, book, report, document) through a specific lens the owner names, and produces both a faithful summary and an applied playbook. Triggers when the owner says 'read this through the lens of X', 'apply this to my problem', 'extract a playbook for Y from this', 'what can I learn from this about Z'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Strategic reading
|
|
7
|
+
|
|
8
|
+
This skill reads a document with a specific question in mind. The owner names the lens (a project, a problem, a goal). The skill summarises what the source actually says, then translates each section into how it applies to the named lens, and closes with a playbook of three to seven concrete steps. Both halves are grounded: the left half in the source text, the right half in the graph.
|
|
9
|
+
|
|
10
|
+
## When to run
|
|
11
|
+
|
|
12
|
+
Run when the owner has a specific problem and wants to test what a particular source teaches them about it. Not for general reading; for applied reading. The trigger phrases are above.
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
| Input | Meaning |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `source` | The text to read. Path to a file, a URL, or pasted text. |
|
|
19
|
+
| `lens` | The named focus. A `:Project`, a `:Goal`, a problem statement in the owner's words, or an entity in the graph the owner wants to apply the source to. |
|
|
20
|
+
|
|
21
|
+
If `lens` is missing, ask once: "Through which lens: a project, a goal, or a problem statement?".
|
|
22
|
+
|
|
23
|
+
## Method
|
|
24
|
+
|
|
25
|
+
1. **Confirm the source.** Read or fetch it. If it cannot be read, refuse; do not paraphrase from training memory.
|
|
26
|
+
2. **Resolve the lens.** If the lens is a named entity, `memory-search` for it and pull its current state, recent obstacles, related entities. If the lens is a free-text problem, capture it verbatim; it is the question every section will be tested against.
|
|
27
|
+
3. **Walk the source in sections.** Section boundaries are the source's own headings. For each section, two paragraphs:
|
|
28
|
+
- **The section.** One paragraph: what it claims and what its evidence is. Quote verbatim only when the wording matters.
|
|
29
|
+
- **Applied to <lens>.** One paragraph: how the section's claim helps or hurts the lens. Use graph specifics. Name entities. Do not write "this could apply" or "consider how this might"; write the specific implication for the specific lens.
|
|
30
|
+
4. **Produce the playbook.** After the last section, compose a single list of three to seven concrete actions the owner could take. Each action is imperative, names a specific next step, and (where possible) names the entity it touches.
|
|
31
|
+
5. **Save the result.** Compose the whole pack as one `:KnowledgeDocument` linked to the lens's underlying entity via `INFORMS` (or `REFERENCES` if `INFORMS` is not in the live ontology).
|
|
32
|
+
|
|
33
|
+
## Output format
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
# Strategic reading: <source title> for <lens>
|
|
37
|
+
|
|
38
|
+
## Lens
|
|
39
|
+
<one-paragraph restatement of the lens, including the graph context the skill loaded>
|
|
40
|
+
|
|
41
|
+
## Section 1: <section heading>
|
|
42
|
+
|
|
43
|
+
**The section.** <one paragraph on the source's claim>
|
|
44
|
+
|
|
45
|
+
**Applied to <lens>.** <one paragraph on the implication for this owner>
|
|
46
|
+
|
|
47
|
+
## Section 2: ...
|
|
48
|
+
|
|
49
|
+
## Playbook
|
|
50
|
+
1. <imperative action, names entity>
|
|
51
|
+
2. <imperative action, names entity>
|
|
52
|
+
... (three to seven items)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Render the pack via `render-component name: document-editor` for review before save.
|
|
56
|
+
|
|
57
|
+
## Difference from book-mirror
|
|
58
|
+
|
|
59
|
+
Book mirror walks every chapter and produces a chapter-by-chapter application: the unit of work is the chapter. Strategic reading uses the source's own sections and is filtered by a specific question: the unit of work is the section, and the filter is the lens. A book mirrored is a personalised version of the whole book. A source read strategically is the answer to one question about that source.
|
|
60
|
+
|
|
61
|
+
## Failure modes
|
|
62
|
+
|
|
63
|
+
- **Lens resolves to an entity with no graph context.** Surface the gap and ask whether to proceed with the lens as a free-text problem instead.
|
|
64
|
+
- **Source covers a topic the lens does not touch.** Each section's right-hand column will read as "this section does not apply directly to <lens>". Surface this pattern after section 3; the owner may want to abandon the read or change the lens.
|
|
65
|
+
- **Source is shorter than three sections** (a short blog post, a one-page memo). Use paragraph boundaries instead of section boundaries. If the source is fewer than 200 words, do not run; the owner can read it themselves faster than the skill can mirror it.
|
|
66
|
+
|
|
67
|
+
## What this skill does not do
|
|
68
|
+
|
|
69
|
+
It does not produce a critical review of the source. It does not score the source. It does not compare it against other sources. It produces one specific output: one source read with one lens, ending in one playbook.
|
|
@@ -45,8 +45,8 @@ After install, the first time you open the admin URL, {{productName}} walks you
|
|
|
45
45
|
|
|
46
46
|
- `seed-neo4j.sh` writes the node at install time with `currentStep=0`. The installer re-reads it before exiting; a missing node or an unreachable Neo4j fails the install loudly (`[install-invariant] onboarding-state-MISSING` or `onboarding-state-UNREACHABLE`).
|
|
47
47
|
- Every admin session-create reads `currentStep`. Anything below 9 keeps `onboarding_complete=false` on `/api/health` and `/api/admin/session`, and the chat opens on the next step's component (multi-select, dropdown, etc.).
|
|
48
|
-
-
|
|
49
|
-
- If Neo4j is unreachable at session-create, the
|
|
48
|
+
- Every freshly-spawned admin claude session ships the `<onboarding-state currentStep="N">` directive as a third sentinel-wrapped section in `--append-system-prompt` (alongside `<host>` and `<attachment-ceiling>`). The agent's first turn calls `skill-load skillName=onboarding`. Resumed sessions skip the section so the agent doesn't re-ask the same step. (Task 043 — pre-fix the directive was prepended to the first user message; the Claude CLI's Ink TextInput interpreted each `\n` in the block as Enter, dropping the directive bytes before they reached the agent. The system prompt is the only multi-line-safe surface for PTY-spawned Claude Code.)
|
|
49
|
+
- If Neo4j is unreachable at session-create, the section becomes a loud-fail block (`graphUnreachable="true"`) and `onboarding_complete` is reported false — never silently skipped.
|
|
50
50
|
|
|
51
51
|
Diagnostic command on the Pi (substitute the brand's Neo4j port from `~/.maxy/.env` or `~/.realagent/.env`):
|
|
52
52
|
|
|
@@ -61,6 +61,7 @@ Failure signals to grep in `~/.maxy/logs/server.log` (or `~/.realagent/logs/serv
|
|
|
61
61
|
- `[install-invariant] onboarding-state-MISSING`
|
|
62
62
|
- `[onboarding-gate] step=null complete=true` (the pre-Task-033 bug)
|
|
63
63
|
- missing `[skill-load] name=onboarding` while `[onboarding-gate]` reports `complete=false`
|
|
64
|
+
- missing `[onboarding-prompt] step=<n|missing|graph-unreachable> bytes=<n>` for a fresh spawn whose `[pty-spawn] appendSystemPromptBytes=` is at the bare 622-byte host + ceiling size (Task 043 — the onboarding directive failed to ship in the system prompt)
|
|
64
65
|
|
|
65
66
|
## Service Management
|
|
66
67
|
|
|
@@ -69,6 +69,8 @@ The admin interface is a three-pane layout: a sidebar on the left with your bran
|
|
|
69
69
|
|
|
70
70
|
Page titles are brand-aware: the browser tab shows your product name (e.g. `Real Agent` instead of `Maxy`) on every shell — chat, graph, and data — so a non-default brand never leaks the default name in tab strips or browser history.
|
|
71
71
|
|
|
72
|
+
**Sidebar sessions list — 3s poll contract.** The sidebar Sessions list and the ConversationsModal share one fetch loop (`useAdminSessions`). It hits `/api/admin/claude-sessions` every 3s while the operator is signed in, but the poll path is render-quiet: `setLoading` is not toggled, and the sessions array is only re-committed when the projection `{ sessionId, displayName, lastMessageAt, status }` actually changes. Byte-identical responses do nothing visible to React. Each tick emits exactly one diagnostic line: `[admin-ui] sessions-poll outcome=<unchanged|changed|error> count=<n> cacheKey=<8>` (in the browser DevTools console; mirrored to `~/.maxy/logs/admin-ui-console.log` where the operator forwards them). The explicit operator-initiated paths — first load (`ensureLoaded`) and post-action `refetch()` (after spawn / delete) — still toggle `loading` so consumers can show a spinner. The 3s manager-truth reconciliation is unchanged; only the React-side noise was removed.
|
|
73
|
+
|
|
72
74
|
The Data search panel ranks results by combining vector similarity with keyword (BM25) matching. Each row shows a one-line score breakdown — `vector 0.NN · bm25 0.NN · combined 0.NN` — so you can tell whether a row surfaced because of meaning, exact-keyword match, or both. A bm25 column of `0.00` across every row means your search term wasn't in the keyword index, so ranking fell back to pure vector similarity (this can produce surprising results — the breakdown tells you when to interpret with caution). Above the result list, a chip row shows the unique types in your current results — click one to filter, click again to clear. Click any row to jump straight to that node's neighbourhood in the Graph; from the artefact pane the graph opens alongside chat, from the standalone Data page it opens in place.
|
|
73
75
|
|
|
74
76
|
## Software Update and Cloudflare Setup
|
|
@@ -530,3 +530,15 @@ sudo systemctl --user start maxy-ui
|
|
|
530
530
|
**Installer aborted with "identity-match FAILED":** Multi-account installs where no sibling matches `users.json[0].userId` abort loud — the installer refuses to pick one and refuses to sweep. Resolution: inspect `account.json` in each candidate dir (listed in the abort output), identify the correct owner, move the other(s) aside manually, then re-run the installer.
|
|
531
531
|
|
|
532
532
|
**A chat turn looks broken — assistant bubble never rendered:** Open `claude-agent-stream-<sessionKey>.log` and grep for `[sse-client]`. The five phases (`connected`, `event_received`, `render_complete`, `error`, `close`) tell the story in order. Missing `connected` = the chat fetch never returned 200; missing `event_received` = the server emitted nothing or the client lost the stream before the first frame; missing `render_complete` = the reducer never committed the assistant bubble (persist_ack never arrived). The operator can also click "Report this turn" in the chat menu to append a `[failure-report]` line carrying the same sessionKey + conversationId + clientSnapshot, plus copy the payload to the clipboard.
|
|
533
|
+
|
|
534
|
+
## Admin DevTools console floods with `onboarding-banner-mount` or unsorted `sessions-poll` lines
|
|
535
|
+
|
|
536
|
+
**Symptom:** Open DevTools on the admin shell at `/` with `onboardingComplete=false`, leave the page idle for a minute or two, then scroll back through the console. Pre-Task-050 you would see thousands of `[admin-ui] onboarding-banner-mount onboardingComplete=false` lines (one per AdminShell render — roughly 40/min from the 3s sessions poll alone) and no per-tick poll telemetry at all.
|
|
537
|
+
|
|
538
|
+
**Post-Task-050 invariants (steady-state idle at `/`):**
|
|
539
|
+
|
|
540
|
+
- `grep -c '\[admin-ui\] onboarding-banner-mount' ~/.maxy/logs/admin-ui-console.log` equals page-load count plus onboarding-flip count, not the render count. Sustained climb at idle ⇒ the banner mount log regressed back into the render body.
|
|
541
|
+
- `grep -c '\[admin-ui\] sessions-poll' ~/.maxy/logs/admin-ui-console.log` grows ~20/min (one per 3s tick) and `outcome=unchanged` dominates `outcome=changed` once the cache is warm. `outcome=changed` every idle tick ⇒ the `useAdminSessions` projection (`sessionId / displayName / lastMessageAt / status`) is missing a field that is churning on every fetch, or a downstream component is mutating the response in place before comparison.
|
|
542
|
+
- `outcome=error` lines name a real fetch failure — they do NOT update sidebar state and do NOT set the `error` field (the operator-initiated `refetch()` still owns that channel).
|
|
543
|
+
|
|
544
|
+
**Why this matters.** The render-body log was misleading: it read as "the admin agent is checking onboarding state continuously", when in fact `onboardingComplete` had not changed at all — it was just the sessions poll re-rendering AdminShell twice per tick. With the structured poll line in place, the console is a faithful record of what the page actually did each tick.
|
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
name: email
|
|
3
3
|
description: "Email — dedicated email account. Retrieval: email-graph-query for stored email history, recall, and search ('what emails are in memory?', 'emails about X', 'what did Y send?'); email-read / email-search for live IMAP inbox. Sending: email-send (new), email-reply (threaded). Config: email-setup, email-status, email-auto-respond-config, email-otp-extract."
|
|
4
4
|
tools:
|
|
5
|
-
- email-setup
|
|
6
|
-
|
|
7
|
-
- email-
|
|
8
|
-
|
|
9
|
-
- email-
|
|
10
|
-
|
|
11
|
-
- email-
|
|
12
|
-
|
|
13
|
-
- email-
|
|
5
|
+
- name: email-setup
|
|
6
|
+
publicAllowlist: false
|
|
7
|
+
- name: email-read
|
|
8
|
+
publicAllowlist: false
|
|
9
|
+
- name: email-send
|
|
10
|
+
publicAllowlist: false
|
|
11
|
+
- name: email-reply
|
|
12
|
+
publicAllowlist: false
|
|
13
|
+
- name: email-search
|
|
14
|
+
publicAllowlist: false
|
|
15
|
+
- name: email-graph-query
|
|
16
|
+
publicAllowlist: false
|
|
17
|
+
- name: email-otp-extract
|
|
18
|
+
publicAllowlist: false
|
|
19
|
+
- name: email-status
|
|
20
|
+
publicAllowlist: false
|
|
21
|
+
- name: email-auto-respond-config
|
|
22
|
+
publicAllowlist: false
|
|
14
23
|
always: false
|
|
15
24
|
embed: ["admin"]
|
|
16
25
|
metadata: {"platform":{}}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface DispatchInput {
|
|
2
|
+
accountId: string;
|
|
3
|
+
senderEmail: string;
|
|
4
|
+
text: string;
|
|
5
|
+
timeoutMs: number;
|
|
6
|
+
}
|
|
7
|
+
export type DispatchResult = {
|
|
8
|
+
turnText: string;
|
|
9
|
+
} | {
|
|
10
|
+
error: string;
|
|
11
|
+
};
|
|
12
|
+
/** Send an email body to the per-sender claude PTY session, await the
|
|
13
|
+
* next assistant end_turn, return the response text. Reuses the session
|
|
14
|
+
* across cron invocations via the manager's senderId index. */
|
|
15
|
+
export declare function dispatchEmailToClaude(input: DispatchInput): Promise<DispatchResult>;
|
|
16
|
+
export declare function emailTurnTimeoutMs(): number;
|
|
17
|
+
//# sourceMappingURL=claude-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-bridge.d.ts","sourceRoot":"","sources":["../../src/lib/claude-bridge.ts"],"names":[],"mappings":"AAmDA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA8HtE;;gEAEgE;AAChE,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAqCzF;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// Email → claude PTY bridge.
|
|
2
|
+
//
|
|
3
|
+
// Task 004 Track B. The email-auto-respond cron script dispatches each
|
|
4
|
+
// inbound email through this module: find-or-spawn a per-sender PTY
|
|
5
|
+
// session via the loopback claude-session-manager, write the email text
|
|
6
|
+
// to the session's PTY stdin, follow claude's per-session JSONL until
|
|
7
|
+
// `stop_reason: "end_turn"`, return the assistant turn text. The cron
|
|
8
|
+
// script then SMTPs the response.
|
|
9
|
+
//
|
|
10
|
+
// This module lives inside the email plugin's MCP source (not under
|
|
11
|
+
// platform/ui/app/lib/) because the cron script is a separate Node
|
|
12
|
+
// process — it cannot share in-process state with the platform/ui
|
|
13
|
+
// channel-pty-bridge instance. Each cron invocation queries the manager
|
|
14
|
+
// for the existing session via `GET /list?senderId=...` rather than
|
|
15
|
+
// caching it in memory.
|
|
16
|
+
//
|
|
17
|
+
// Doctrine references:
|
|
18
|
+
// - Manager HTTP contract: ../../../../services/claude-session-manager/src/http-server.ts
|
|
19
|
+
// - Shared bridge core (in-process, used by whatsapp / webchat):
|
|
20
|
+
// ../../../../../ui/app/lib/channel-pty-bridge/
|
|
21
|
+
// - Task 004 brief: maxy-code/.tasks/004-channel-adaptors-rest.md
|
|
22
|
+
const TAG = "[email-adaptor]";
|
|
23
|
+
function managerBase() {
|
|
24
|
+
const port = Number(process.env.CLAUDE_SESSION_MANAGER_PORT ?? "19400");
|
|
25
|
+
return `http://127.0.0.1:${port}`;
|
|
26
|
+
}
|
|
27
|
+
// ─── Manager HTTP ─────────────────────────────────────────────────────
|
|
28
|
+
async function findExistingSession(senderId) {
|
|
29
|
+
try {
|
|
30
|
+
const res = await fetch(`${managerBase()}/list?senderId=${encodeURIComponent(senderId)}`);
|
|
31
|
+
if (!res.ok)
|
|
32
|
+
return null;
|
|
33
|
+
const sessions = (await res.json());
|
|
34
|
+
const alive = sessions.find((s) => s.status === "alive" && s.channel === "email");
|
|
35
|
+
return alive?.sessionId ?? null;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function spawnSession(opts) {
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${managerBase()}/spawn`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "content-type": "application/json" },
|
|
46
|
+
body: JSON.stringify({
|
|
47
|
+
senderId: opts.senderId,
|
|
48
|
+
role: "public",
|
|
49
|
+
channel: "email",
|
|
50
|
+
accountId: opts.accountId,
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
console.error(`${TAG} reject reason=spawn-failed senderId=${opts.senderId} status=${res.status}`);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const body = (await res.json());
|
|
58
|
+
return body.sessionId;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const m = err instanceof Error ? err.message : String(err);
|
|
62
|
+
console.error(`${TAG} reject reason=spawn-unreachable senderId=${opts.senderId} message=${m}`);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function writeInput(sessionId, text) {
|
|
67
|
+
try {
|
|
68
|
+
const res = await fetch(`${managerBase()}/${sessionId}/input`, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: { "content-type": "application/json" },
|
|
71
|
+
body: JSON.stringify({ text }),
|
|
72
|
+
});
|
|
73
|
+
return res.ok;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ─── JSONL follower (one-shot, waits for next end_turn) ──────────────
|
|
80
|
+
async function awaitNextTurn(sessionId, timeoutMs) {
|
|
81
|
+
const abort = new AbortController();
|
|
82
|
+
const timeoutHandle = setTimeout(() => abort.abort(), timeoutMs);
|
|
83
|
+
try {
|
|
84
|
+
const res = await fetch(`${managerBase()}/${sessionId}/log?follow=1`, { signal: abort.signal });
|
|
85
|
+
if (!res.ok || !res.body) {
|
|
86
|
+
return { error: `follow-status-${res.status}` };
|
|
87
|
+
}
|
|
88
|
+
const reader = res.body.getReader();
|
|
89
|
+
const decoder = new TextDecoder("utf8");
|
|
90
|
+
let buffered = "";
|
|
91
|
+
let turnText = "";
|
|
92
|
+
while (!abort.signal.aborted) {
|
|
93
|
+
const { value, done } = await reader.read();
|
|
94
|
+
if (done)
|
|
95
|
+
break;
|
|
96
|
+
buffered += decoder.decode(value, { stream: true });
|
|
97
|
+
let nl = buffered.indexOf("\n");
|
|
98
|
+
while (nl !== -1) {
|
|
99
|
+
const line = buffered.slice(0, nl);
|
|
100
|
+
buffered = buffered.slice(nl + 1);
|
|
101
|
+
nl = buffered.indexOf("\n");
|
|
102
|
+
if (!line)
|
|
103
|
+
continue;
|
|
104
|
+
let event;
|
|
105
|
+
try {
|
|
106
|
+
event = JSON.parse(line);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (event.type === "user") {
|
|
112
|
+
turnText = "";
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (event.type !== "assistant")
|
|
116
|
+
continue;
|
|
117
|
+
const msg = event.message;
|
|
118
|
+
if (!msg)
|
|
119
|
+
continue;
|
|
120
|
+
if (Array.isArray(msg.content)) {
|
|
121
|
+
for (const block of msg.content) {
|
|
122
|
+
if (block?.type === "text" && typeof block.text === "string") {
|
|
123
|
+
turnText += block.text;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (msg.stop_reason === "end_turn") {
|
|
128
|
+
if (turnText.trim()) {
|
|
129
|
+
// Abort the stream so the manager closes the follower
|
|
130
|
+
// immediately; we have our turn.
|
|
131
|
+
abort.abort();
|
|
132
|
+
return { turnText };
|
|
133
|
+
}
|
|
134
|
+
turnText = "";
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { error: abort.signal.aborted ? "timeout" : "stream-closed" };
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
if (abort.signal.aborted)
|
|
142
|
+
return { error: "timeout" };
|
|
143
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
clearTimeout(timeoutHandle);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// ─── Public dispatch ─────────────────────────────────────────────────
|
|
150
|
+
/** Send an email body to the per-sender claude PTY session, await the
|
|
151
|
+
* next assistant end_turn, return the response text. Reuses the session
|
|
152
|
+
* across cron invocations via the manager's senderId index. */
|
|
153
|
+
export async function dispatchEmailToClaude(input) {
|
|
154
|
+
if (!input.text.trim())
|
|
155
|
+
return { error: "empty-text" };
|
|
156
|
+
const bytes = Buffer.byteLength(input.text, "utf8");
|
|
157
|
+
console.error(`${TAG} inbound from=${input.senderEmail} bytes=${bytes} accountId=${input.accountId}`);
|
|
158
|
+
let sessionId = await findExistingSession(input.senderEmail);
|
|
159
|
+
let action = "reuse";
|
|
160
|
+
if (!sessionId) {
|
|
161
|
+
action = "spawn";
|
|
162
|
+
sessionId = await spawnSession({ senderId: input.senderEmail, accountId: input.accountId });
|
|
163
|
+
if (!sessionId)
|
|
164
|
+
return { error: "spawn-failed" };
|
|
165
|
+
}
|
|
166
|
+
console.error(`${TAG} session-resolved senderId=${input.senderEmail} action=${action} sessionId=${sessionId.slice(0, 8)}`);
|
|
167
|
+
const writeOk = await writeInput(sessionId, input.text);
|
|
168
|
+
if (!writeOk) {
|
|
169
|
+
console.error(`${TAG} reject reason=input-failed senderId=${input.senderEmail} sessionId=${sessionId.slice(0, 8)}`);
|
|
170
|
+
return { error: "input-failed" };
|
|
171
|
+
}
|
|
172
|
+
const startedAt = Date.now();
|
|
173
|
+
const result = await awaitNextTurn(sessionId, input.timeoutMs);
|
|
174
|
+
const idleMs = Date.now() - startedAt;
|
|
175
|
+
if ("error" in result) {
|
|
176
|
+
console.error(`${TAG} reject reason=turn-${result.error} senderId=${input.senderEmail} sessionId=${sessionId.slice(0, 8)} idle-ms=${idleMs}`);
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
console.error(`${TAG} outbound to=${input.senderEmail} bytes=${Buffer.byteLength(result.turnText, "utf8")} sessionId=${sessionId.slice(0, 8)} idle-ms=${idleMs}`);
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
export function emailTurnTimeoutMs() {
|
|
183
|
+
return Number(process.env.EMAIL_POLL_TURN_TIMEOUT_MS ?? String(10 * 60_000));
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=claude-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-bridge.js","sourceRoot":"","sources":["../../src/lib/claude-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -134,7 +134,7 @@ export declare function searchMessages(config: EmailConfig, password: string, qu
|
|
|
134
134
|
beforeUid?: number;
|
|
135
135
|
}): Promise<PaginatedMessages>;
|
|
136
136
|
/**
|
|
137
|
-
* Result from an incremental email fetch
|
|
137
|
+
* Result from an incremental email fetch performed by the email-fetch dispatcher.
|
|
138
138
|
* Includes the raw envelope data needed for graph storage (not just display).
|
|
139
139
|
*/
|
|
140
140
|
export interface FetchedEmail {
|