@rubytech/create-maxy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/dist/index.js +428 -0
  2. package/package.json +31 -0
  3. package/payload/maxy/.env.example +12 -0
  4. package/payload/maxy/app/admin/components/ActivityTimeline.tsx +348 -0
  5. package/payload/maxy/app/admin/components/MarkdownMessage.tsx +40 -0
  6. package/payload/maxy/app/api/admin/chat/route.ts +72 -0
  7. package/payload/maxy/app/api/admin/logs/route.ts +40 -0
  8. package/payload/maxy/app/api/admin/session/route.ts +74 -0
  9. package/payload/maxy/app/api/chat/route.ts +72 -0
  10. package/payload/maxy/app/api/health/route.ts +26 -0
  11. package/payload/maxy/app/api/onboarding/claude-auth/route.ts +216 -0
  12. package/payload/maxy/app/api/onboarding/set-pin/route.ts +44 -0
  13. package/payload/maxy/app/api/session/route.ts +51 -0
  14. package/payload/maxy/app/api/telegram/webhook/route.ts +107 -0
  15. package/payload/maxy/app/apple-icon.png +0 -0
  16. package/payload/maxy/app/bot/page.tsx +373 -0
  17. package/payload/maxy/app/favicon.ico +0 -0
  18. package/payload/maxy/app/globals.css +1681 -0
  19. package/payload/maxy/app/layout.tsx +58 -0
  20. package/payload/maxy/app/lib/claude-agent.ts +503 -0
  21. package/payload/maxy/app/og/layout.tsx +15 -0
  22. package/payload/maxy/app/og/page.tsx +252 -0
  23. package/payload/maxy/app/page.tsx +594 -0
  24. package/payload/maxy/app/privacy/page.tsx +72 -0
  25. package/payload/maxy/app/public/page.tsx +266 -0
  26. package/payload/maxy/next.config.mjs +26 -0
  27. package/payload/maxy/package-lock.json +2198 -0
  28. package/payload/maxy/package.json +25 -0
  29. package/payload/maxy/proxy.ts +41 -0
  30. package/payload/maxy/public/brand/claude.png +0 -0
  31. package/payload/maxy/public/brand/maxy-black.png +0 -0
  32. package/payload/maxy/public/brand/maxy.png +0 -0
  33. package/payload/maxy/public/favicon.ico +0 -0
  34. package/payload/maxy/public/og-landscape.png +0 -0
  35. package/payload/maxy/public/og-portrait.png +0 -0
  36. package/payload/maxy/public/og-square.png +0 -0
  37. package/payload/maxy/public/pi-5.jpg +0 -0
  38. package/payload/maxy/public/robots.txt +5 -0
  39. package/payload/maxy/tsconfig.json +41 -0
  40. package/payload/maxy/tsconfig.tsbuildinfo +1 -0
  41. package/payload/maxy/ui.md +28 -0
  42. package/payload/platform/config/cloudflared.yml +17 -0
  43. package/payload/platform/knowledge/maxy.md +161 -0
  44. package/payload/platform/neo4j/schema.cypher +108 -0
  45. package/payload/platform/package-lock.json +1835 -0
  46. package/payload/platform/package.json +17 -0
  47. package/payload/platform/plugins/admin/PLUGIN.md +24 -0
  48. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +56 -0
  49. package/payload/platform/plugins/admin/hooks/session-start.sh +20 -0
  50. package/payload/platform/plugins/admin/mcp/dist/index.d.ts +2 -0
  51. package/payload/platform/plugins/admin/mcp/dist/index.d.ts.map +1 -0
  52. package/payload/platform/plugins/admin/mcp/dist/index.js +149 -0
  53. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -0
  54. package/payload/platform/plugins/admin/mcp/package.json +18 -0
  55. package/payload/platform/plugins/anthropic/PLUGIN.md +30 -0
  56. package/payload/platform/plugins/anthropic/references/setup-guide.md +146 -0
  57. package/payload/platform/plugins/business-assistant/PLUGIN.md +46 -0
  58. package/payload/platform/plugins/business-assistant/references/crm.md +112 -0
  59. package/payload/platform/plugins/business-assistant/references/document-management.md +96 -0
  60. package/payload/platform/plugins/business-assistant/references/escalation.md +126 -0
  61. package/payload/platform/plugins/business-assistant/references/invoicing.md +163 -0
  62. package/payload/platform/plugins/business-assistant/references/quoting.md +56 -0
  63. package/payload/platform/plugins/business-assistant/references/scheduling.md +127 -0
  64. package/payload/platform/plugins/cloudflare/PLUGIN.md +31 -0
  65. package/payload/platform/plugins/cloudflare/mcp/dist/index.d.ts +2 -0
  66. package/payload/platform/plugins/cloudflare/mcp/dist/index.d.ts.map +1 -0
  67. package/payload/platform/plugins/cloudflare/mcp/dist/index.js +174 -0
  68. package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -0
  69. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts +45 -0
  70. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts.map +1 -0
  71. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js +256 -0
  72. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js.map +1 -0
  73. package/payload/platform/plugins/cloudflare/mcp/package.json +18 -0
  74. package/payload/platform/plugins/cloudflare/references/setup-guide.md +110 -0
  75. package/payload/platform/plugins/contacts/PLUGIN.md +18 -0
  76. package/payload/platform/plugins/contacts/mcp/dist/index.d.ts +2 -0
  77. package/payload/platform/plugins/contacts/mcp/dist/index.d.ts.map +1 -0
  78. package/payload/platform/plugins/contacts/mcp/dist/index.js +182 -0
  79. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -0
  80. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.d.ts +5 -0
  81. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.d.ts.map +1 -0
  82. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js +34 -0
  83. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js.map +1 -0
  84. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +19 -0
  85. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -0
  86. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +68 -0
  87. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -0
  88. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts +22 -0
  89. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts.map +1 -0
  90. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js +46 -0
  91. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js.map +1 -0
  92. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +20 -0
  93. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -0
  94. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +56 -0
  95. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -0
  96. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts +13 -0
  97. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts.map +1 -0
  98. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js +54 -0
  99. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js.map +1 -0
  100. package/payload/platform/plugins/contacts/mcp/package.json +19 -0
  101. package/payload/platform/plugins/documents/PLUGIN.md +12 -0
  102. package/payload/platform/plugins/documents/mcp/dist/index.d.ts +2 -0
  103. package/payload/platform/plugins/documents/mcp/dist/index.d.ts.map +1 -0
  104. package/payload/platform/plugins/documents/mcp/dist/index.js +82 -0
  105. package/payload/platform/plugins/documents/mcp/dist/index.js.map +1 -0
  106. package/payload/platform/plugins/documents/mcp/package.json +20 -0
  107. package/payload/platform/plugins/memory/PLUGIN.md +17 -0
  108. package/payload/platform/plugins/memory/mcp/dist/index.d.ts +2 -0
  109. package/payload/platform/plugins/memory/mcp/dist/index.d.ts.map +1 -0
  110. package/payload/platform/plugins/memory/mcp/dist/index.js +164 -0
  111. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -0
  112. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts +3 -0
  113. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts.map +1 -0
  114. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js +29 -0
  115. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js.map +1 -0
  116. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +5 -0
  117. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts.map +1 -0
  118. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +34 -0
  119. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js.map +1 -0
  120. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +8 -0
  121. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -0
  122. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +71 -0
  123. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -0
  124. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts +24 -0
  125. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -0
  126. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +125 -0
  127. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -0
  128. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +18 -0
  129. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -0
  130. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +56 -0
  131. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -0
  132. package/payload/platform/plugins/memory/mcp/package.json +19 -0
  133. package/payload/platform/plugins/sales/PLUGIN.md +65 -0
  134. package/payload/platform/plugins/sales/references/close-tracking.md +76 -0
  135. package/payload/platform/plugins/sales/references/closing-framework.md +108 -0
  136. package/payload/platform/plugins/sales/references/comparisons.md +99 -0
  137. package/payload/platform/plugins/sales/references/competitive-positioning.md +51 -0
  138. package/payload/platform/plugins/sales/references/faq.md +62 -0
  139. package/payload/platform/plugins/sales/references/objection-handling.md +157 -0
  140. package/payload/platform/plugins/sales/references/pricing.md +71 -0
  141. package/payload/platform/plugins/sales/references/waitlist.md +23 -0
  142. package/payload/platform/plugins/scheduling/PLUGIN.md +12 -0
  143. package/payload/platform/plugins/scheduling/mcp/dist/index.d.ts +2 -0
  144. package/payload/platform/plugins/scheduling/mcp/dist/index.d.ts.map +1 -0
  145. package/payload/platform/plugins/scheduling/mcp/dist/index.js +13 -0
  146. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -0
  147. package/payload/platform/plugins/scheduling/mcp/package.json +18 -0
  148. package/payload/platform/plugins/telegram/PLUGIN.md +31 -0
  149. package/payload/platform/plugins/telegram/mcp/dist/index.d.ts +2 -0
  150. package/payload/platform/plugins/telegram/mcp/dist/index.d.ts.map +1 -0
  151. package/payload/platform/plugins/telegram/mcp/dist/index.js +101 -0
  152. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -0
  153. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts +27 -0
  154. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts.map +1 -0
  155. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js +41 -0
  156. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js.map +1 -0
  157. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts +16 -0
  158. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts.map +1 -0
  159. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js +62 -0
  160. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js.map +1 -0
  161. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts +20 -0
  162. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -0
  163. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +34 -0
  164. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -0
  165. package/payload/platform/plugins/telegram/mcp/package.json +19 -0
  166. package/payload/platform/plugins/telegram/references/setup-guide.md +50 -0
  167. package/payload/platform/plugins/web/PLUGIN.md +12 -0
  168. package/payload/platform/plugins/web/mcp/dist/index.d.ts +2 -0
  169. package/payload/platform/plugins/web/mcp/dist/index.d.ts.map +1 -0
  170. package/payload/platform/plugins/web/mcp/dist/index.js +12 -0
  171. package/payload/platform/plugins/web/mcp/dist/index.js.map +1 -0
  172. package/payload/platform/plugins/web/mcp/package.json +18 -0
  173. package/payload/platform/scripts/seed-neo4j.sh +73 -0
  174. package/payload/platform/scripts/setup.sh +177 -0
  175. package/payload/platform/scripts/start.sh +62 -0
  176. package/payload/platform/templates/account.json +4 -0
  177. package/payload/platform/templates/agents/admin/IDENTITY.md +28 -0
  178. package/payload/platform/templates/agents/admin/SOUL.md +1 -0
  179. package/payload/platform/templates/agents/public/IDENTITY.md +21 -0
  180. package/payload/platform/templates/agents/public/SOUL.md +1 -0
  181. package/payload/platform/tsconfig.base.json +18 -0
@@ -0,0 +1,157 @@
1
+ # Objection Handling
2
+
3
+ ## Pivots vs Objections
4
+
5
+ The most important distinction in closing: is the prospect **pivoting** (changing topic to avoid commitment) or **objecting** (raising a genuine concern that needs resolving)?
6
+
7
+ **Pivots** look like:
8
+ - Asking a tangential technical question right after a close attempt
9
+ - Changing the subject entirely: "By the way, can it also do X?"
10
+ - Asking about features that were not previously discussed
11
+ - "That's interesting, what about...?"
12
+
13
+ **Objections** look like:
14
+ - Expressing a specific concern: "I'm worried about the cost"
15
+ - Raising a blocker: "I need to check with my partner first"
16
+ - Questioning capability directly: "Can it actually handle that?"
17
+ - Asking for evidence: "Do you have any case studies?"
18
+
19
+ **The rule:** Handle pivots with acknowledge-then-anchor. Handle objections with empathy, resolution, then close.
20
+
21
+ ## Acknowledge-Then-Anchor (for Pivots)
22
+
23
+ The pattern:
24
+
25
+ 1. **Acknowledge** — Show you heard the question. Do not dismiss it.
26
+ 2. **Brief answer** — 1-2 sentences maximum. Enough to satisfy curiosity, not enough to derail.
27
+ 3. **Re-anchor** — Return to the commitment ask.
28
+
29
+ The brief answer is genuine — you are not dodging the question, you are prioritising the close while still being helpful.
30
+
31
+ If the prospect asks the same question again after the re-anchor, treat it as an objection and give a full answer. A repeated question is no longer a pivot.
32
+
33
+ ## Feel / Felt / Found
34
+
35
+ The universal objection-handling pattern. Works for price and almost any other concern:
36
+
37
+ > "I understand how you **feel** — [validate their concern]. Many of our users **felt** exactly the same way. However, most **found** that [positive outcome], which made the investment worthwhile."
38
+
39
+ **Examples:**
40
+
41
+ *Price too high:*
42
+ > "I understand how you feel — it's a significant investment. Many people felt the same way initially. However, most found that within the first month, the time saved more than covered the cost."
43
+
44
+ *Unsure about value:*
45
+ > "I get how you feel — it's hard to know if it's worth it before you've tried it. Others felt the same. What they found was that once Maxy started managing their calendar and messages proactively, they couldn't go back."
46
+
47
+ *Comparing to cheaper option:*
48
+ > "I understand how you feel — the price difference is noticeable. Others have felt the same and tried the cheaper option first. What they found was it couldn't act proactively or connect their services together, and they ended up coming back."
49
+
50
+ The key: the "found" part must be **specific and credible**. Vague claims are worthless. Concrete outcomes are persuasive.
51
+
52
+ ## Common Objection Patterns
53
+
54
+ ### Price: "I need to think about it" / "That's more than I expected"
55
+
56
+ This is usually about value, not money. The prospect is not sure the product is worth the price.
57
+
58
+ 1. Acknowledge the concern without defensiveness
59
+ 2. Restate the specific value that matches their stated needs
60
+ 3. If alternatives exist, offer them (different tier, payment plan)
61
+ 4. Surface the real objection: "Of course — what specifically would you like to think over? I want to make sure I've given you everything you need to decide."
62
+
63
+ Never discount without authorisation. Never make the prospect feel bad for asking about price.
64
+
65
+ ### "That's more than I expected"
66
+
67
+ Response: "What were you expecting?" — then bridge the gap with value, not discount.
68
+
69
+ ### "Your competitor is cheaper"
70
+
71
+ Response: "They may well be — and that's a valid consideration. Can I ask what's most important to you: the lowest price, or the best outcome?" Then demonstrate why the higher price delivers a better net result.
72
+
73
+ ### "Can you do it for less?"
74
+
75
+ Never say no outright. Instead:
76
+ > "The price reflects what's included. I could adjust it if we reduce scope. Would that work, or is the full package what you actually need?"
77
+
78
+ This teaches them that price is linked to value.
79
+
80
+ ### Timing: "Not right now" / "Maybe next month"
81
+
82
+ Respect the timing. Do not push against an explicit deferral.
83
+
84
+ 1. Acknowledge: "No problem at all"
85
+ 2. Set a concrete follow-up: "Shall I check back in with you on [specific date]?"
86
+ 3. Save the deferral to memory with the agreed follow-up date
87
+ 4. When the follow-up date arrives, use the Return Close
88
+
89
+ ### Capability: "Can it do X?" / "What about Y integration?"
90
+
91
+ If this comes mid-close, it is likely a pivot. If it comes before any close attempt, it is genuine discovery.
92
+
93
+ **Mid-close (pivot):**
94
+ > "Good question — [brief honest answer]. We can go deeper on that once you're set up. Shall we get you started?"
95
+
96
+ **Pre-close (genuine):**
97
+ Answer fully. This is discovery, not closing. Do not try to close during discovery.
98
+
99
+ ### Authority: "I need to check with my partner/family"
100
+
101
+ This is a legitimate blocker.
102
+
103
+ 1. Respect it: "Of course — makes sense to discuss together"
104
+ 2. Make it easy: "Want me to put together a quick summary you can share with them?"
105
+ 3. Set a follow-up: "When do you think you'll have had a chance to chat? I can check back in"
106
+ 4. Save to memory: who the decision-maker is, when the follow-up should happen
107
+
108
+ ### Competition: "I'm also looking at [competitor]"
109
+
110
+ 1. Never disparage the competitor
111
+ 2. Ask what matters most to them — let them tell you what to sell
112
+ 3. Position on genuine differentiators, not feature lists
113
+ 4. Load `references/comparisons.md` for specific positioning
114
+
115
+ ### Trust: "How do I know it actually works?"
116
+
117
+ 1. Offer to walk them through specifics relevant to their use case
118
+ 2. Reference the waitlist and early access — being honest about where Maxy is builds trust
119
+ 3. Emphasise the local-first privacy model — data stays in their home
120
+ 4. Be honest: "We're early — the best way to see is to try it. That's why we're building a waitlist of people who want to shape what Maxy becomes."
121
+
122
+ ## Concession Strategy
123
+
124
+ If you must concede (with authorisation only):
125
+
126
+ 1. **Never concede first.** Let them state what they want.
127
+ 2. **Never concede for free.** Always ask for something in return:
128
+ - Faster commitment: "I can do that if you confirm today"
129
+ - Longer term: "I can reduce the monthly if you commit for 12 months"
130
+ - Referral: "I can offer a discount if you're happy to refer us to two others"
131
+ - Case study: "I can adjust the price if we can use this as a case study"
132
+ 3. **Concede slowly.** Small steps, not big jumps. Each concession should feel hard-won.
133
+ 4. **Name what you're giving up.** Don't just lower the number — show what the concession costs.
134
+
135
+ ## When to Hold Firm
136
+
137
+ - The prospect hasn't completed discovery (they don't understand the value yet)
138
+ - You've already reframed and the value is clear
139
+ - A minimum price has been set
140
+ - The prospect is negotiating for sport, not from genuine budget constraints
141
+
142
+ ## When to Flex
143
+
144
+ - The prospect has genuine budget constraints but is otherwise a great fit
145
+ - A smaller deal now could lead to a larger one later
146
+ - Flexibility has been authorised
147
+ - You can reduce scope rather than reduce price
148
+
149
+ ## Escalation
150
+
151
+ Some objections require a human. Escalate when:
152
+
153
+ - The prospect wants to negotiate pricing or custom terms
154
+ - The prospect wants a personal guarantee or commitment the agent cannot make
155
+ - The prospect raises a concern that cannot be resolved from available knowledge
156
+ - The objection has been addressed but the prospect is still not moving forward after 3 attempts
157
+ - The prospect requests human contact — always respect this immediately
@@ -0,0 +1,71 @@
1
+ # Maxy Pricing
2
+
3
+ ## Subscription Plans
4
+
5
+ ### Solo — £20/month
6
+ For individuals. One user, one Maxy instance.
7
+
8
+ Includes:
9
+ - Maxy core assistant (calendar, reminders, messages, smart home)
10
+ - WhatsApp, voice, and web access
11
+ - Memory and context across conversations
12
+ - Claude Pro AI backbone (£16/month value included)
13
+
14
+ Hardware required: Maxy Pi (from £125, one-time purchase)
15
+
16
+ ### Family — £60/month
17
+ For households. Multiple users, shared context with individual privacy.
18
+
19
+ Includes:
20
+ - Everything in Solo
21
+ - Multi-user support (family members each get their own profile)
22
+ - Family-aware coordination (shared calendar, household tasks, family reminders)
23
+ - Claude Max AI backbone (£80/month value included)
24
+
25
+ Hardware required: Maxy Pi (from £180 for Family-spec device, one-time purchase)
26
+
27
+ ## Skill Packs — £5/month each, or all 6 for £20/month
28
+
29
+ Modular capabilities you add based on what you need:
30
+
31
+ | Skill Pack | What it does |
32
+ |-----------|-------------|
33
+ | **Home** | Smart home management, energy monitoring, household routines |
34
+ | **Finance** | Budget tracking, bill reminders, spending insights |
35
+ | **Wellness** | Health reminders, fitness tracking integration, wellbeing check-ins |
36
+ | **Professional** | Work calendar, meeting prep, email drafting, task management |
37
+ | **Family** | Family coordination, school schedules, activity planning, shared lists |
38
+ | **Travel** | Trip planning, booking assistance, itinerary management |
39
+
40
+ **Bundle deal:** All 6 plugin packs for £20/month (save £10/month vs buying individually).
41
+
42
+ ## Premium Skills
43
+
44
+ ### Beagle — Separate Product
45
+ Beagle is a premium booking agent for local services. It finds, compares, and books local service providers (plumbers, cleaners, electricians, etc.) on your behalf.
46
+
47
+ Beagle is a separate product with its own pricing — not included in the Maxy subscription or plugin pack bundles.
48
+
49
+ ## Hardware
50
+
51
+ ### Maxy Pi — from £125
52
+ Raspberry Pi-based home hub. Runs Maxy locally. Your data stays in your home.
53
+
54
+ - Solo spec: from £125
55
+ - Family spec: from £180 (more processing power for multi-user)
56
+ - One-time purchase, no rental or lease
57
+
58
+ ### Maxy Mini — ~£370
59
+ Reachy Mini robot form factor. Physical presence in the home. Same Maxy brain, embodied.
60
+
61
+ - Desktop robot with screen and movement
62
+ - Voice interaction with physical presence
63
+ - Premium hardware option for those who want Maxy to feel more tangible
64
+
65
+ ## Pricing Principles
66
+
67
+ - **Never apologise for the price.** The value is real. Frame cost as investment.
68
+ - **Always show what's included.** The Claude Pro/Max backbone alone costs £16-£80/month — Maxy wraps that in a complete assistant experience.
69
+ - **Lead with the plan, not the hardware.** Monthly subscription is the ongoing relationship. Hardware is the one-time setup cost.
70
+ - **Plugin packs are upsell, not barrier.** Core Maxy works without plugin packs. Packs add depth in specific areas.
71
+ - **The bundle is the anchor.** When discussing plugin packs, mention the all-6-for-£20 bundle first — it makes individual packs feel like a bargain.
@@ -0,0 +1,23 @@
1
+ # Waitlist Capture
2
+
3
+ ## When to Offer
4
+
5
+ After substantive engagement (3+ exchanges or a direct interest signal such as "how do I sign up", "I want this", "when can I start"), naturally offer the waitlist. Do not force it — let it flow from the conversation.
6
+
7
+ ## Flow
8
+
9
+ 1. Ask for their name and email
10
+ 2. Confirm: "You're on the list! We'll be in touch as soon as your spot opens up."
11
+
12
+ If they decline, respect it and continue the conversation. Do not re-ask in the same session.
13
+
14
+ ## What Happens Next
15
+
16
+ You do not write any data. The name and email collected in conversation are extracted by the admin team's periodic review job, which creates the Person node in the graph. The admin reviews all public conversations on a regular cycle.
17
+
18
+ ## Tone
19
+
20
+ - Warm, not pushy
21
+ - One ask per session maximum
22
+ - Frame it as keeping them informed, not as a commitment
23
+ - If they've already expressed interest in a prior session, acknowledge that warmly
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: scheduling
3
+ description: "Scheduling plugin. Provides calendar and appointment management tools. Phase 1 — stub implementation."
4
+ icon: 📅
5
+ tools: []
6
+ always: false
7
+ embed: false
8
+ ---
9
+
10
+ # Scheduling
11
+
12
+ Calendar and appointment management. Phase 1 stub — not yet implemented.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ const server = new McpServer({
5
+ name: "maxy-scheduling",
6
+ version: "0.1.0",
7
+ });
8
+ server.tool("schedule-event", "Schedule an event or appointment", { summary: z.string(), startDate: z.string(), endDate: z.string().optional() }, async () => ({ content: [{ type: "text", text: "Scheduling is not available in Phase 0. This capability will be added in Phase 1." }] }));
9
+ server.tool("schedule-list", "List upcoming scheduled events", { from: z.string().optional(), to: z.string().optional() }, async () => ({ content: [{ type: "text", text: "Scheduling is not available in Phase 0. This capability will be added in Phase 1." }] }));
10
+ server.tool("schedule-cancel", "Cancel a scheduled event", { eventId: z.string() }, async () => ({ content: [{ type: "text", text: "Scheduling is not available in Phase 0. This capability will be added in Phase 1." }] }));
11
+ const transport = new StdioServerTransport();
12
+ await server.connect(transport);
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,kCAAkC,EAClC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAC9E,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,mFAAmF,EAAE,CAAC,EAAE,CAAC,CAClJ,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,gCAAgC,EAChC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAC1D,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,mFAAmF,EAAE,CAAC,EAAE,CAAC,CAClJ,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,0BAA0B,EAC1B,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EACvB,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,mFAAmF,EAAE,CAAC,EAAE,CAAC,CAClJ,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@maxy/scheduling",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "^1.12.1"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.7.0",
16
+ "@types/node": "^22.0.0"
17
+ }
18
+ }
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: telegram
3
+ description: Guide users through connecting a Telegram bot — creating a bot via BotFather, finding user IDs, and configuring admin vs public bots.
4
+ metadata: {"taskmaster":{"emoji":"✈️"}}
5
+ ---
6
+
7
+ # Telegram Setup
8
+
9
+ Walks users through connecting Telegram bots to Taskmaster. Covers bot creation, token configuration, finding numeric user IDs, and choosing between admin and public bot roles.
10
+
11
+ ## When to activate
12
+
13
+ - User asks how to connect Telegram or set up a Telegram bot
14
+ - User asks about BotFather, bot tokens, or Telegram integration
15
+ - User needs to find their Telegram user ID for admin binding
16
+ - User asks about admin vs public bot configuration
17
+ - User is on the Setup page and asks about the Telegram section
18
+
19
+ ## What it unlocks
20
+
21
+ - Telegram as a messaging channel — DMs and group conversations routed to the AI assistant
22
+ - Multi-bot support — separate admin and public bots with different access policies
23
+ - Admin routing — restrict a bot to admin-only access via numeric user ID bindings
24
+
25
+ ## References
26
+
27
+ | Task | When to use | Reference |
28
+ |------|-------------|-----------|
29
+ | Guided setup | User wants help connecting Telegram | `references/setup-guide.md` |
30
+
31
+ Load the reference and follow its instructions.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,101 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { message } from "./tools/message.js";
5
+ import { messageHistory } from "./tools/message-history.js";
6
+ const server = new McpServer({
7
+ name: "maxy-messaging",
8
+ version: "0.1.0",
9
+ });
10
+ server.tool("message", "Send a message via Telegram. Supports text with HTML formatting and inline keyboards for interactive choices.", {
11
+ channel: z.literal("telegram").describe("Delivery channel"),
12
+ chatId: z
13
+ .union([z.string(), z.number()])
14
+ .describe("Telegram chat ID to send to"),
15
+ text: z.string().describe("Message text (HTML formatting supported)"),
16
+ parseMode: z
17
+ .enum(["HTML", "Markdown", "MarkdownV2"])
18
+ .optional()
19
+ .describe("Parse mode (default: HTML)"),
20
+ inlineKeyboard: z
21
+ .array(z.array(z.object({
22
+ text: z.string().describe("Button label"),
23
+ callbackData: z
24
+ .string()
25
+ .optional()
26
+ .describe("Callback data for button press"),
27
+ url: z.string().optional().describe("URL to open on button press"),
28
+ })))
29
+ .optional()
30
+ .describe("Inline keyboard rows for interactive buttons"),
31
+ }, async (params) => {
32
+ try {
33
+ const result = await message(params);
34
+ if (!result.sent) {
35
+ return {
36
+ content: [
37
+ {
38
+ type: "text",
39
+ text: `Message failed: ${result.error}`,
40
+ },
41
+ ],
42
+ isError: true,
43
+ };
44
+ }
45
+ return {
46
+ content: [
47
+ {
48
+ type: "text",
49
+ text: `Message sent via ${result.channel} (ID: ${result.messageId})`,
50
+ },
51
+ ],
52
+ };
53
+ }
54
+ catch (err) {
55
+ return {
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: `Send failed: ${err instanceof Error ? err.message : String(err)}`,
60
+ },
61
+ ],
62
+ isError: true,
63
+ };
64
+ }
65
+ });
66
+ server.tool("message-history", "Query conversation history from the message log.", {
67
+ channel: z.string().optional().describe("Filter by channel (telegram)"),
68
+ chatId: z.string().optional().describe("Filter by chat ID"),
69
+ limit: z.number().optional().describe("Max messages to return (default 20)"),
70
+ }, async ({ channel, chatId, limit }) => {
71
+ try {
72
+ const history = await messageHistory({ channel, chatId, limit });
73
+ if (history.length === 0) {
74
+ return {
75
+ content: [
76
+ { type: "text", text: "No message history found." },
77
+ ],
78
+ };
79
+ }
80
+ const formatted = history
81
+ .map((h) => `[${h.timestamp}] ${h.channel}/${h.chatId} (${h.role}): ${h.content.slice(0, 200)}${h.content.length > 200 ? "..." : ""}`)
82
+ .join("\n");
83
+ return {
84
+ content: [{ type: "text", text: formatted }],
85
+ };
86
+ }
87
+ catch (err) {
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: `History query failed: ${err instanceof Error ? err.message : String(err)}`,
93
+ },
94
+ ],
95
+ isError: true,
96
+ };
97
+ }
98
+ });
99
+ const transport = new StdioServerTransport();
100
+ await server.connect(transport);
101
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface TelegramSendOptions {
2
+ chatId: string | number;
3
+ text: string;
4
+ parseMode?: "HTML" | "Markdown" | "MarkdownV2";
5
+ replyMarkup?: TelegramInlineKeyboard;
6
+ }
7
+ export interface TelegramInlineKeyboard {
8
+ inline_keyboard: Array<Array<{
9
+ text: string;
10
+ callback_data?: string;
11
+ url?: string;
12
+ }>>;
13
+ }
14
+ export declare function sendMessage(botToken: string, options: TelegramSendOptions): Promise<{
15
+ ok: boolean;
16
+ messageId?: number;
17
+ error?: string;
18
+ }>;
19
+ export declare function setWebhook(botToken: string, webhookUrl: string): Promise<{
20
+ ok: boolean;
21
+ error?: string;
22
+ }>;
23
+ export declare function getWebhookInfo(botToken: string): Promise<{
24
+ url: string;
25
+ pendingUpdateCount: number;
26
+ }>;
27
+ //# sourceMappingURL=telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/lib/telegram.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC;IAC/C,WAAW,CAAC,EAAE,sBAAsB,CAAC;CACtC;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,KAAK,CACpB,KAAK,CAAC;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC,CACH,CAAC;CACH;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyB9D;AAED,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiB1C;AAED,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAWtD"}
@@ -0,0 +1,41 @@
1
+ const TELEGRAM_API = "https://api.telegram.org";
2
+ export async function sendMessage(botToken, options) {
3
+ const res = await fetch(`${TELEGRAM_API}/bot${botToken}/sendMessage`, {
4
+ method: "POST",
5
+ headers: { "Content-Type": "application/json" },
6
+ body: JSON.stringify({
7
+ chat_id: options.chatId,
8
+ text: options.text,
9
+ parse_mode: options.parseMode ?? "HTML",
10
+ reply_markup: options.replyMarkup
11
+ ? JSON.stringify(options.replyMarkup)
12
+ : undefined,
13
+ }),
14
+ });
15
+ const data = (await res.json());
16
+ if (!data.ok) {
17
+ return { ok: false, error: data.description ?? "Unknown Telegram error" };
18
+ }
19
+ return { ok: true, messageId: data.result?.message_id };
20
+ }
21
+ export async function setWebhook(botToken, webhookUrl) {
22
+ const res = await fetch(`${TELEGRAM_API}/bot${botToken}/setWebhook`, {
23
+ method: "POST",
24
+ headers: { "Content-Type": "application/json" },
25
+ body: JSON.stringify({ url: webhookUrl }),
26
+ });
27
+ const data = (await res.json());
28
+ if (!data.ok) {
29
+ return { ok: false, error: data.description ?? "Failed to set webhook" };
30
+ }
31
+ return { ok: true };
32
+ }
33
+ export async function getWebhookInfo(botToken) {
34
+ const res = await fetch(`${TELEGRAM_API}/bot${botToken}/getWebhookInfo`);
35
+ const data = (await res.json());
36
+ return {
37
+ url: data.result.url,
38
+ pendingUpdateCount: data.result.pending_update_count,
39
+ };
40
+ }
41
+ //# sourceMappingURL=telegram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/lib/telegram.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAmBhD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,OAA4B;IAE5B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,OAAO,QAAQ,cAAc,EAAE;QACpE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,OAAO,CAAC,MAAM;YACvB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM;YACvC,YAAY,EAAE,OAAO,CAAC,WAAW;gBAC/B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC;gBACrC,CAAC,CAAC,SAAS;SACd,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;IAEF,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,IAAI,wBAAwB,EAAE,CAAC;IAC5E,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAgB,EAChB,UAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,OAAO,QAAQ,aAAa,EAAE;QACnE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;KAC1C,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;IAEF,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,IAAI,uBAAuB,EAAE,CAAC;IAC3E,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,GAAG,YAAY,OAAO,QAAQ,iBAAiB,CAChD,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;IACF,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG;QACpB,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB;KACrD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ interface HistoryParams {
2
+ channel?: string;
3
+ chatId?: string;
4
+ accountId?: string;
5
+ limit?: number;
6
+ }
7
+ interface HistoryEntry {
8
+ channel: string;
9
+ chatId: string;
10
+ role: string;
11
+ content: string;
12
+ timestamp: string;
13
+ }
14
+ export declare function messageHistory(params: HistoryParams): Promise<HistoryEntry[]>;
15
+ export {};
16
+ //# sourceMappingURL=message-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-history.d.ts","sourceRoot":"","sources":["../../src/tools/message-history.ts"],"names":[],"mappings":"AAiCA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyCzB"}
@@ -0,0 +1,62 @@
1
+ import neo4j from "neo4j-driver";
2
+ import { readFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ let driver = null;
5
+ function readPassword() {
6
+ if (process.env.NEO4J_PASSWORD)
7
+ return process.env.NEO4J_PASSWORD;
8
+ const passwordFile = resolve(process.env.PLATFORM_ROOT ?? resolve(import.meta.dirname, "../../../.."), "config/.neo4j-password");
9
+ try {
10
+ return readFileSync(passwordFile, "utf-8").trim();
11
+ }
12
+ catch {
13
+ throw new Error(`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`);
14
+ }
15
+ }
16
+ function getSession() {
17
+ if (!driver) {
18
+ const uri = process.env.NEO4J_URI ?? "bolt://localhost:7687";
19
+ const user = process.env.NEO4J_USER ?? "neo4j";
20
+ const password = readPassword();
21
+ driver = neo4j.driver(uri, neo4j.auth.basic(user, password));
22
+ }
23
+ return driver.session();
24
+ }
25
+ export async function messageHistory(params) {
26
+ const { channel, chatId, accountId, limit = 20 } = params;
27
+ const session = getSession();
28
+ try {
29
+ const conditions = ["m.accountId = $accountId"];
30
+ const queryParams = { accountId, limit };
31
+ if (channel) {
32
+ conditions.push("m.channel = $channel");
33
+ queryParams.channel = channel;
34
+ }
35
+ if (chatId) {
36
+ conditions.push("m.chatId = $chatId");
37
+ queryParams.chatId = chatId;
38
+ }
39
+ const query = `
40
+ MATCH (m:Communication)
41
+ WHERE ${conditions.join(" AND ")}
42
+ RETURN m
43
+ ORDER BY m.dateSent DESC
44
+ LIMIT $limit
45
+ `;
46
+ const result = await session.run(query, queryParams);
47
+ return result.records.map((record) => {
48
+ const m = record.get("m").properties;
49
+ return {
50
+ channel: m.channel,
51
+ chatId: m.chatId,
52
+ role: m.role,
53
+ content: m.content,
54
+ timestamp: m.dateSent,
55
+ };
56
+ });
57
+ }
58
+ finally {
59
+ await session.close();
60
+ }
61
+ }
62
+ //# sourceMappingURL=message-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-history.js","sourceRoot":"","sources":["../../src/tools/message-history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAElE,MAAM,YAAY,GAAG,OAAO,CAC1B,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EACxE,wBAAwB,CACzB,CAAC;IAEF,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,yCAAyC,YAAY,gCAAgC,CACtF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,uBAAuB,CAAC;QAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC;QAC/C,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC;AAiBD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAqB;IAErB,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC;IAE1D,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAChD,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QAElE,IAAI,OAAO,EAAE,CAAC;YACZ,UAAU,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;YACxC,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC;QAChC,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;QAED,MAAM,KAAK,GAAG;;cAEJ,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;;;;KAIjC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAErD,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACnC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACrC,OAAO;gBACL,OAAO,EAAE,CAAC,CAAC,OAAiB;gBAC5B,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,IAAI,EAAE,CAAC,CAAC,IAAc;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAiB;gBAC5B,SAAS,EAAE,CAAC,CAAC,QAAkB;aAChC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ interface MessageParams {
2
+ channel: "telegram";
3
+ chatId: string | number;
4
+ text: string;
5
+ parseMode?: "HTML" | "Markdown" | "MarkdownV2";
6
+ inlineKeyboard?: Array<Array<{
7
+ text: string;
8
+ callbackData?: string;
9
+ url?: string;
10
+ }>>;
11
+ }
12
+ interface MessageResult {
13
+ sent: boolean;
14
+ channel: string;
15
+ messageId?: number;
16
+ error?: string;
17
+ }
18
+ export declare function message(params: MessageParams): Promise<MessageResult>;
19
+ export {};
20
+ //# sourceMappingURL=message.d.ts.map