@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,174 @@
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 { join } from "node:path";
5
+ import * as cloudflared from "./lib/cloudflared.js";
6
+ const server = new McpServer({
7
+ name: "cloudflare",
8
+ version: "0.1.0",
9
+ });
10
+ // ===================================================================
11
+ // Cloudflare Tunnel tools
12
+ // ===================================================================
13
+ server.tool("tunnel-status", "Full Cloudflare Tunnel status: installed, version, authenticated, running, domain, URLs.", {
14
+ domain: z.string().optional().describe("The bare domain (e.g. 'maxy.bot'). If omitted, domain info is excluded."),
15
+ }, async ({ domain }) => {
16
+ try {
17
+ const status = cloudflared.getStatus(domain);
18
+ return {
19
+ content: [{ type: "text", text: JSON.stringify(status, null, 2) }],
20
+ };
21
+ }
22
+ catch (err) {
23
+ return {
24
+ content: [{ type: "text", text: `Failed: ${err instanceof Error ? err.message : String(err)}` }],
25
+ isError: true,
26
+ };
27
+ }
28
+ });
29
+ server.tool("tunnel-install", "Install the cloudflared binary if not already present.", {}, async () => {
30
+ const { execFileSync } = await import("node:child_process");
31
+ if (cloudflared.isInstalled()) {
32
+ const v = cloudflared.version();
33
+ return {
34
+ content: [{ type: "text", text: `cloudflared is already installed (v${v}).` }],
35
+ };
36
+ }
37
+ try {
38
+ const arch = process.arch === "arm64" ? "arm64" : "amd64";
39
+ const debUrl = `https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${arch}.deb`;
40
+ execFileSync("curl", ["-fsSL", debUrl, "-o", "/tmp/cloudflared.deb"], { timeout: 60000 });
41
+ execFileSync("sudo", ["dpkg", "-i", "/tmp/cloudflared.deb"], { timeout: 30000 });
42
+ execFileSync("rm", ["-f", "/tmp/cloudflared.deb"]);
43
+ return {
44
+ content: [{ type: "text", text: `cloudflared installed (v${cloudflared.version()}).` }],
45
+ };
46
+ }
47
+ catch (err) {
48
+ return {
49
+ content: [{ type: "text", text: `Installation failed: ${err instanceof Error ? err.message : String(err)}` }],
50
+ isError: true,
51
+ };
52
+ }
53
+ });
54
+ server.tool("tunnel-login", "Start Cloudflare authentication. Returns a URL (and QR code data) that the user must visit to authorise this device. On a headless device, scan the QR code with your phone.", {}, async () => {
55
+ if (!cloudflared.isInstalled()) {
56
+ return {
57
+ content: [{ type: "text", text: "cloudflared is not installed. Run tunnel-install first." }],
58
+ isError: true,
59
+ };
60
+ }
61
+ if (cloudflared.isAuthenticated()) {
62
+ return {
63
+ content: [{ type: "text", text: "Already authenticated with Cloudflare." }],
64
+ };
65
+ }
66
+ try {
67
+ const login = cloudflared.startLogin();
68
+ // Wait up to 15 seconds for the auth URL to appear in output
69
+ const startTime = Date.now();
70
+ while (!login.authUrl && Date.now() - startTime < 15000) {
71
+ await new Promise((r) => setTimeout(r, 500));
72
+ }
73
+ if (!login.authUrl) {
74
+ login.process.kill();
75
+ return {
76
+ content: [{ type: "text", text: "Timed out waiting for Cloudflare auth URL. Check cloudflared logs." }],
77
+ isError: true,
78
+ };
79
+ }
80
+ return {
81
+ content: [
82
+ {
83
+ type: "text",
84
+ text: `Cloudflare authentication started.\n\nVisit this URL to authorise this device:\n${login.authUrl}\n\nOn a headless device, use qr-generate to create a QR code for this URL, then scan it with your phone.\n\nWaiting for authentication to complete...`,
85
+ },
86
+ ],
87
+ };
88
+ }
89
+ catch (err) {
90
+ return {
91
+ content: [{ type: "text", text: `Login failed: ${err instanceof Error ? err.message : String(err)}` }],
92
+ isError: true,
93
+ };
94
+ }
95
+ });
96
+ server.tool("tunnel-create", "Create a Cloudflare Tunnel and route DNS for admin.{domain} and public.{domain}.", {
97
+ domain: z.string().describe("The bare domain (e.g. 'maxy.bot'). Subdomains admin. and public. are created automatically."),
98
+ tunnelName: z.string().optional().describe("Human-readable tunnel name (default: derived from domain)"),
99
+ }, async ({ domain, tunnelName }) => {
100
+ if (!cloudflared.isInstalled()) {
101
+ return {
102
+ content: [{ type: "text", text: "cloudflared is not installed. Run tunnel-install first." }],
103
+ isError: true,
104
+ };
105
+ }
106
+ if (!cloudflared.isAuthenticated()) {
107
+ return {
108
+ content: [{ type: "text", text: "Not authenticated with Cloudflare. Run tunnel-login first." }],
109
+ isError: true,
110
+ };
111
+ }
112
+ try {
113
+ const name = tunnelName ?? domain.replace(/\./g, "-");
114
+ const result = cloudflared.createTunnel(name);
115
+ cloudflared.routeDns(result.tunnelId, `admin.${domain}`);
116
+ cloudflared.routeDns(result.tunnelId, `public.${domain}`);
117
+ const configPath = cloudflared.writeConfig(result.tunnelId, result.credentialsFile, domain, 19200);
118
+ return {
119
+ content: [
120
+ {
121
+ type: "text",
122
+ text: `Tunnel created.\n\n ID: ${result.tunnelId}\n Name: ${result.tunnelName}\n DNS: admin.${domain} → tunnel\n DNS: public.${domain} → tunnel\n Config: ${configPath}\n\nUse tunnel-enable to start the tunnel.`,
123
+ },
124
+ ],
125
+ };
126
+ }
127
+ catch (err) {
128
+ return {
129
+ content: [{ type: "text", text: `Create failed: ${err instanceof Error ? err.message : String(err)}` }],
130
+ isError: true,
131
+ };
132
+ }
133
+ });
134
+ server.tool("tunnel-enable", "Start the Cloudflare Tunnel process. The tunnel must be created first via tunnel-create.", {
135
+ tunnelId: z.string().describe("Tunnel UUID from tunnel-create"),
136
+ domain: z.string().describe("The bare domain (e.g. 'maxy.bot')"),
137
+ }, async ({ tunnelId, domain }) => {
138
+ try {
139
+ const credentialsFile = join(process.env.HOME ?? "/root", `.cloudflared/${tunnelId}.json`);
140
+ const configPath = cloudflared.writeConfig(tunnelId, credentialsFile, domain, 19200);
141
+ cloudflared.startTunnel(configPath);
142
+ return {
143
+ content: [
144
+ {
145
+ type: "text",
146
+ text: `Tunnel started.\n\n Admin: https://admin.${domain}\n Public: https://public.${domain}`,
147
+ },
148
+ ],
149
+ };
150
+ }
151
+ catch (err) {
152
+ return {
153
+ content: [{ type: "text", text: `Enable failed: ${err instanceof Error ? err.message : String(err)}` }],
154
+ isError: true,
155
+ };
156
+ }
157
+ });
158
+ server.tool("tunnel-disable", "Stop the Cloudflare Tunnel process. Config is preserved for re-enabling.", {}, async () => {
159
+ try {
160
+ cloudflared.stopTunnel();
161
+ return {
162
+ content: [{ type: "text", text: "Tunnel stopped. Config preserved — use tunnel-enable to restart." }],
163
+ };
164
+ }
165
+ catch (err) {
166
+ return {
167
+ content: [{ type: "text", text: `Disable failed: ${err instanceof Error ? err.message : String(err)}` }],
168
+ isError: true,
169
+ };
170
+ }
171
+ });
172
+ const transport = new StdioServerTransport();
173
+ await server.connect(transport);
174
+ //# 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;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,WAAW,MAAM,sBAAsB,CAAC;AAEpD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,sEAAsE;AACtE,0BAA0B;AAC1B,sEAAsE;AAEtE,MAAM,CAAC,IAAI,CACT,eAAe,EACf,0FAA0F,EAC1F;IACE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yEAAyE,CAAC;CAClH,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;IACnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC7C,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,WAAW,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACzG,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,wDAAwD,EACxD,EAAE,EACF,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAE5D,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;QAChC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,sCAAsC,CAAC,IAAI,EAAE,CAAC;SACxF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAC1D,MAAM,MAAM,GAAG,wFAAwF,IAAI,MAAM,CAAC;QAElH,YAAY,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1F,YAAY,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,sBAAsB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAEnD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,2BAA2B,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;SACjG,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACtH,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,8KAA8K,EAC9K,EAAE,EACF,KAAK,IAAI,EAAE;IACT,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,yDAAyD,EAAE,CAAC;YACrG,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,CAAC,eAAe,EAAE,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,wCAAwC,EAAE,CAAC;SACrF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC;QAEvC,6DAA6D;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC;YACxD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,oEAAoE,EAAE,CAAC;gBAChH,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,mFAAmF,KAAK,CAAC,OAAO,wJAAwJ;iBAC/P;aACF;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iBAAiB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YAC/G,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,kFAAkF,EAClF;IACE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6FAA6F,CAAC;IAC1H,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;CACxG,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;IAC/B,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,yDAAyD,EAAE,CAAC;YACrG,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,4DAA4D,EAAE,CAAC;YACxG,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAE9C,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;QACzD,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;QAE1D,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAEnG,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,4BAA4B,MAAM,CAAC,QAAQ,aAAa,MAAM,CAAC,UAAU,kBAAkB,MAAM,4BAA4B,MAAM,wBAAwB,UAAU,4CAA4C;iBACxN;aACF;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YAChH,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,0FAA0F,EAC1F;IACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;IAC/D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;CACjE,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;IAC7B,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,IAAI,CAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,EAC3B,gBAAgB,QAAQ,OAAO,CAChC,CAAC;QACF,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACrF,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAEpC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,6CAA6C,MAAM,8BAA8B,MAAM,EAAE;iBAChG;aACF;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YAChH,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,0EAA0E,EAC1E,EAAE,EACF,KAAK,IAAI,EAAE;IACT,IAAI,CAAC;QACH,WAAW,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,kEAAkE,EAAE,CAAC;SAC/G,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACjH,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ export declare function findBinary(): string | null;
3
+ export declare function isInstalled(): boolean;
4
+ export declare function version(): string | null;
5
+ export declare function isAuthenticated(): boolean;
6
+ /**
7
+ * Start the cloudflared login flow.
8
+ * Returns the auth URL that the user must visit (or encode as QR code).
9
+ * This is a long-running process — it waits for the user to authenticate
10
+ * in their browser. The process completes when cert.pem is written.
11
+ */
12
+ export declare function startLogin(): {
13
+ authUrl: string;
14
+ process: ChildProcess;
15
+ };
16
+ interface TunnelCreateResult {
17
+ tunnelId: string;
18
+ tunnelName: string;
19
+ credentialsFile: string;
20
+ }
21
+ export declare function createTunnel(name: string): TunnelCreateResult;
22
+ export declare function routeDns(tunnelId: string, hostname: string): void;
23
+ interface TunnelInfo {
24
+ id: string;
25
+ name: string;
26
+ }
27
+ export declare function listTunnels(): TunnelInfo[];
28
+ export declare function writeConfig(tunnelId: string, credentialsFile: string, domain: string, port: number): string;
29
+ export interface TunnelStatus {
30
+ installed: boolean;
31
+ version: string | null;
32
+ authenticated: boolean;
33
+ running: boolean;
34
+ pid: number | null;
35
+ domain: string | null;
36
+ adminUrl: string | null;
37
+ publicUrl: string | null;
38
+ upSince: number | null;
39
+ restartCount: number;
40
+ }
41
+ export declare function getStatus(domain?: string): TunnelStatus;
42
+ export declare function startTunnel(configPath: string): void;
43
+ export declare function stopTunnel(): void;
44
+ export {};
45
+ //# sourceMappingURL=cloudflared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflared.d.ts","sourceRoot":"","sources":["../../src/lib/cloudflared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiB5E,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAsB1C;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,OAAO,IAAI,MAAM,GAAG,IAAI,CAUvC;AAQD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAmCvE;AAMD,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CA4B7D;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAcjE;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,WAAW,IAAI,UAAU,EAAE,CAc1C;AAMD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,MAAM,CAkBR;AAcD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAavD;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAapD;AA8BD,wBAAgB,UAAU,IAAI,IAAI,CAsBjC"}
@@ -0,0 +1,256 @@
1
+ import { execFileSync, spawn } from "node:child_process";
2
+ import { existsSync, writeFileSync, mkdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ // ---------------------------------------------------------------------------
6
+ // Binary detection
7
+ // ---------------------------------------------------------------------------
8
+ let cachedBinaryPath = null;
9
+ const SEARCH_PATHS = [
10
+ "/usr/local/bin/cloudflared",
11
+ "/usr/bin/cloudflared",
12
+ join(homedir(), ".local/bin/cloudflared"),
13
+ ];
14
+ export function findBinary() {
15
+ if (cachedBinaryPath)
16
+ return cachedBinaryPath;
17
+ // Try `which` first
18
+ try {
19
+ cachedBinaryPath = execFileSync("which", ["cloudflared"], {
20
+ encoding: "utf-8",
21
+ timeout: 5000,
22
+ }).trim();
23
+ return cachedBinaryPath;
24
+ }
25
+ catch {
26
+ // not on PATH
27
+ }
28
+ for (const p of SEARCH_PATHS) {
29
+ if (existsSync(p)) {
30
+ cachedBinaryPath = p;
31
+ return p;
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ export function isInstalled() {
37
+ return findBinary() !== null;
38
+ }
39
+ export function version() {
40
+ const bin = findBinary();
41
+ if (!bin)
42
+ return null;
43
+ try {
44
+ const out = execFileSync(bin, ["--version"], { encoding: "utf-8", timeout: 5000 });
45
+ const match = out.match(/cloudflared version (\S+)/);
46
+ return match?.[1] ?? out.trim();
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Authentication
54
+ // ---------------------------------------------------------------------------
55
+ const CERT_PATH = join(homedir(), ".cloudflared/cert.pem");
56
+ export function isAuthenticated() {
57
+ return existsSync(CERT_PATH);
58
+ }
59
+ /**
60
+ * Start the cloudflared login flow.
61
+ * Returns the auth URL that the user must visit (or encode as QR code).
62
+ * This is a long-running process — it waits for the user to authenticate
63
+ * in their browser. The process completes when cert.pem is written.
64
+ */
65
+ export function startLogin() {
66
+ const bin = findBinary();
67
+ if (!bin)
68
+ throw new Error("cloudflared is not installed");
69
+ const child = spawn(bin, ["tunnel", "login"], {
70
+ stdio: ["ignore", "pipe", "pipe"],
71
+ });
72
+ let authUrl = "";
73
+ let stderrBuffer = "";
74
+ // cloudflared prints the auth URL to stderr
75
+ child.stderr?.on("data", (chunk) => {
76
+ stderrBuffer += chunk.toString();
77
+ const match = stderrBuffer.match(/(https:\/\/dash\.cloudflare\.com\/argotunnel[^\s]+)/);
78
+ if (match && !authUrl) {
79
+ authUrl = match[1];
80
+ }
81
+ });
82
+ // Also check stdout (some versions print there)
83
+ child.stdout?.on("data", (chunk) => {
84
+ const text = chunk.toString();
85
+ const match = text.match(/(https:\/\/dash\.cloudflare\.com\/argotunnel[^\s]+)/);
86
+ if (match && !authUrl) {
87
+ authUrl = match[1];
88
+ }
89
+ });
90
+ return {
91
+ get authUrl() {
92
+ return authUrl;
93
+ },
94
+ process: child,
95
+ };
96
+ }
97
+ export function createTunnel(name) {
98
+ const bin = findBinary();
99
+ if (!bin)
100
+ throw new Error("cloudflared is not installed");
101
+ // Check for existing tunnel with this name
102
+ const existing = listTunnels().find((t) => t.name === name);
103
+ if (existing) {
104
+ const credentialsFile = join(homedir(), `.cloudflared/${existing.id}.json`);
105
+ return {
106
+ tunnelId: existing.id,
107
+ tunnelName: existing.name,
108
+ credentialsFile,
109
+ };
110
+ }
111
+ const output = execFileSync(bin, ["tunnel", "create", name], {
112
+ encoding: "utf-8",
113
+ timeout: 30000,
114
+ });
115
+ // Parse tunnel ID from output: "Created tunnel {name} with id {uuid}"
116
+ const match = output.match(/with id ([a-f0-9-]+)/);
117
+ if (!match)
118
+ throw new Error(`Failed to parse tunnel ID from: ${output}`);
119
+ const tunnelId = match[1];
120
+ const credentialsFile = join(homedir(), `.cloudflared/${tunnelId}.json`);
121
+ return { tunnelId, tunnelName: name, credentialsFile };
122
+ }
123
+ export function routeDns(tunnelId, hostname) {
124
+ const bin = findBinary();
125
+ if (!bin)
126
+ throw new Error("cloudflared is not installed");
127
+ try {
128
+ execFileSync(bin, ["tunnel", "route", "dns", "--overwrite-dns", tunnelId, hostname], {
129
+ encoding: "utf-8",
130
+ timeout: 30000,
131
+ });
132
+ }
133
+ catch (err) {
134
+ const msg = err instanceof Error ? err.message : String(err);
135
+ // "already exists" is success
136
+ if (!msg.includes("already exists"))
137
+ throw err;
138
+ }
139
+ }
140
+ export function listTunnels() {
141
+ const bin = findBinary();
142
+ if (!bin)
143
+ return [];
144
+ try {
145
+ const output = execFileSync(bin, ["tunnel", "list", "--output", "json"], {
146
+ encoding: "utf-8",
147
+ timeout: 15000,
148
+ });
149
+ const tunnels = JSON.parse(output);
150
+ return tunnels.map((t) => ({ id: t.id, name: t.name }));
151
+ }
152
+ catch {
153
+ return [];
154
+ }
155
+ }
156
+ // ---------------------------------------------------------------------------
157
+ // Config generation
158
+ // ---------------------------------------------------------------------------
159
+ export function writeConfig(tunnelId, credentialsFile, domain, port) {
160
+ const configDir = join(homedir(), ".cloudflared");
161
+ mkdirSync(configDir, { recursive: true });
162
+ const configPath = join(configDir, `tunnel-${tunnelId}.yml`);
163
+ const yaml = `tunnel: ${tunnelId}
164
+ credentials-file: ${credentialsFile}
165
+
166
+ ingress:
167
+ - hostname: admin.${domain}
168
+ service: http://localhost:${port}
169
+ - hostname: public.${domain}
170
+ service: http://localhost:${port}
171
+ - service: http_status:404
172
+ `;
173
+ writeFileSync(configPath, yaml, "utf-8");
174
+ return configPath;
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Process management
178
+ // ---------------------------------------------------------------------------
179
+ let tunnelProcess = null;
180
+ let tunnelUpSince = null;
181
+ let suppressRestart = false;
182
+ let restartCount = 0;
183
+ const BACKOFF = [5_000, 10_000, 20_000, 30_000];
184
+ let healthInterval = null;
185
+ export function getStatus(domain) {
186
+ return {
187
+ installed: isInstalled(),
188
+ version: version(),
189
+ authenticated: isAuthenticated(),
190
+ running: tunnelProcess !== null && tunnelProcess.exitCode === null,
191
+ pid: tunnelProcess?.pid ?? null,
192
+ domain: domain ?? null,
193
+ adminUrl: domain ? `https://admin.${domain}` : null,
194
+ publicUrl: domain ? `https://public.${domain}` : null,
195
+ upSince: tunnelUpSince,
196
+ restartCount,
197
+ };
198
+ }
199
+ export function startTunnel(configPath) {
200
+ const bin = findBinary();
201
+ if (!bin)
202
+ throw new Error("cloudflared is not installed");
203
+ if (tunnelProcess && tunnelProcess.exitCode === null) {
204
+ throw new Error("Tunnel is already running");
205
+ }
206
+ suppressRestart = false;
207
+ restartCount = 0;
208
+ spawnTunnel(bin, configPath);
209
+ startHealthCheck(bin, configPath);
210
+ }
211
+ function spawnTunnel(bin, configPath) {
212
+ tunnelProcess = spawn(bin, ["tunnel", "--config", configPath, "run"], {
213
+ stdio: ["ignore", "pipe", "pipe"],
214
+ });
215
+ tunnelUpSince = Date.now();
216
+ tunnelProcess.on("exit", (code) => {
217
+ tunnelUpSince = null;
218
+ if (!suppressRestart) {
219
+ const delay = BACKOFF[Math.min(restartCount, BACKOFF.length - 1)];
220
+ restartCount++;
221
+ setTimeout(() => {
222
+ if (!suppressRestart)
223
+ spawnTunnel(bin, configPath);
224
+ }, delay);
225
+ }
226
+ });
227
+ }
228
+ function startHealthCheck(bin, configPath) {
229
+ if (healthInterval)
230
+ clearInterval(healthInterval);
231
+ healthInterval = setInterval(() => {
232
+ if (tunnelProcess && tunnelProcess.exitCode !== null && !suppressRestart) {
233
+ spawnTunnel(bin, configPath);
234
+ }
235
+ }, 30_000);
236
+ }
237
+ export function stopTunnel() {
238
+ suppressRestart = true;
239
+ if (healthInterval) {
240
+ clearInterval(healthInterval);
241
+ healthInterval = null;
242
+ }
243
+ if (tunnelProcess && tunnelProcess.exitCode === null) {
244
+ tunnelProcess.kill("SIGTERM");
245
+ // Force kill after 5 seconds
246
+ const timeout = setTimeout(() => {
247
+ if (tunnelProcess && tunnelProcess.exitCode === null) {
248
+ tunnelProcess.kill("SIGKILL");
249
+ }
250
+ }, 5000);
251
+ tunnelProcess.on("exit", () => clearTimeout(timeout));
252
+ }
253
+ tunnelProcess = null;
254
+ tunnelUpSince = null;
255
+ }
256
+ //# sourceMappingURL=cloudflared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflared.js","sourceRoot":"","sources":["../../src/lib/cloudflared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@maxy/cloudflare",
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,110 @@
1
+ # Cloudflare Tunnel Setup Guide
2
+
3
+ ## Prerequisites
4
+
5
+ - A Cloudflare account (free at cloudflare.com)
6
+ - A domain on Cloudflare (see "Getting a domain on Cloudflare" below)
7
+ - Access to the control panel Setup page on the local network
8
+
9
+ ### Getting a domain on Cloudflare
10
+
11
+ The tunnel needs a domain managed by Cloudflare. There are two paths:
12
+
13
+ **Option A: Buy a new domain through Cloudflare**
14
+ 1. Go to cloudflare.com → **Domains** → **Buy a domain**
15
+ 2. Search for a domain name and purchase it (Cloudflare sells at cost, no markup)
16
+ 3. The domain is automatically set up — no further DNS configuration needed
17
+
18
+ **Option B: Add an existing domain**
19
+ If the user already owns a domain through another registrar (GoDaddy, Namecheap, etc.):
20
+ 1. Go to cloudflare.com → **Domains** → **Onboard a domain**
21
+ 2. Enter the domain and select the **Free** plan
22
+ 3. Cloudflare scans existing DNS records and imports them — review the list to make sure everything is there (website, email, etc.)
23
+ 4. Cloudflare shows two nameservers (e.g. `anna.ns.cloudflare.com`, `bob.ns.cloudflare.com`)
24
+ 5. Go to the domain registrar and replace the existing nameservers with the Cloudflare ones
25
+ 6. Wait for propagation (usually minutes, can take up to 24 hours)
26
+ 7. Cloudflare shows the domain as **Active** once propagation is complete
27
+
28
+ **Will my website go down?** No. Cloudflare imports all existing DNS records in step 3, so traffic continues to reach the same servers as before. Cloudflare sits in front as a proxy — existing websites, email, and other services keep working. The only thing that changes is which nameservers answer DNS queries. If in doubt, check the imported records match what the registrar had before switching.
29
+
30
+ Once the domain is active on Cloudflare, Taskmaster uses it to create two subdomains automatically. Any domain works — including ones with a `www` prefix (e.g. `www.mybusiness.com`).
31
+
32
+ ## Setup Flow
33
+
34
+ The entire setup is done from the **Setup page** in the control panel. Look for the **Cloudflare** row in the setup cards.
35
+
36
+ ### Step 1: Install cloudflared
37
+
38
+ The Setup page checks whether cloudflared is installed automatically.
39
+
40
+ - If it shows "Not Installed", tap **Install** — the system handles it
41
+ - If auto-install fails (e.g. on an unsupported platform), the UI shows manual install instructions specific to the device's OS
42
+ - Once installed, the status updates automatically
43
+
44
+ ### Step 2: Authenticate with Cloudflare
45
+
46
+ Tap **Connect** on the Cloudflare card. This opens a browser window on the device:
47
+
48
+ - Sign in to the Cloudflare account if prompted
49
+ - A list of domains (zones) appears — select the domain to use for the tunnel
50
+ - A confirmation dialog appears: "Authorize Tunnel for [domain]" — click **Authorize**
51
+ - The browser confirms success and the Setup page updates automatically
52
+
53
+ The user needs a Cloudflare account with at least one active domain before this step. If they don't have one, guide them through the prerequisites above first.
54
+
55
+ ### Step 3: Create the tunnel
56
+
57
+ Tap **Set up** to open the wizard. It shows the two endpoints that will be created automatically:
58
+
59
+ - **Control panel** — `admin.{domain}` — for remote access to the setup and admin interface
60
+ - **Public chat** — `public.{domain}` — for customers to reach the chat
61
+
62
+ There is nothing to fill in — both addresses are derived from the domain authorised in Step 2. The tunnel creates the DNS records (CNAMEs) for both automatically — no need to touch the Cloudflare dashboard.
63
+
64
+ ### Step 4: Set a remote password
65
+
66
+ The wizard's second step asks for a username and password. This protects the control panel when accessed from the public internet via `admin.{domain}`.
67
+
68
+ Explain to the user:
69
+ - This is separate from the device PIN (which is for local network access only)
70
+ - These credentials work for all accounts on the device (like a router admin password)
71
+ - The password must be at least 8 characters, contain a number, contain a special character, and have no leading/trailing spaces
72
+ - The wizard shows a live checklist of password requirements as they type
73
+
74
+ ### Step 5: Enable Tunnel
75
+
76
+ The wizard's final step shows a summary and an **Enable Tunnel** button. Once enabled:
77
+
78
+ - The control panel is live at `https://admin.{domain}` — requires the username and password set in Step 4
79
+ - The public chat is live at `https://public.{domain}/chat/{account-slug}`
80
+ - Local network access continues to work with just the PIN
81
+
82
+ ## After Setup
83
+
84
+ The Cloudflare card on the Setup page shows the tunnel status and the admin hostname. Tapping the card opens an info panel with connection details and the public chat URL.
85
+
86
+ ## Troubleshooting
87
+
88
+ ### Tunnel won't start
89
+ - Check the Cloudflare card on the Setup page for status details
90
+ - If authentication has expired, tap **Log in** again to re-authenticate
91
+ - If the credentials file is missing, the tunnel may need to be recreated via the wizard
92
+
93
+ ### DNS not resolving
94
+ - DNS propagation can take 1-5 minutes after tunnel creation
95
+ - Verify the tunnel is running (green status on the Setup page)
96
+ - Check the Cloudflare dashboard to confirm the CNAME records exist for both `admin.{domain}` and `public.{domain}`
97
+
98
+ ### Remote login issues
99
+ - After 5 failed login attempts, there's a 15-minute lockout — wait for it to expire
100
+ - The password can be reset from the Setup page on the local network
101
+
102
+ ### Changing domain
103
+ - Disable the tunnel from the Setup page
104
+ - Re-authenticate with Cloudflare using the new domain
105
+ - Run the wizard again — it will create new DNS records for the new domain
106
+ - Old DNS records can be removed from the Cloudflare dashboard
107
+
108
+ ## Agent Tools
109
+
110
+ The tunnel tools (`tunnel_status`, `tunnel_enable`, `tunnel_disable`) give the agent visibility and control over the tunnel. Use these when the user asks about tunnel status or wants to enable/disable remotely via chat. For initial setup, always direct users to the Setup page wizard.
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: contacts
3
+ description: "CRM contacts plugin. Provides contact-create, contact-lookup, contact-update, and contact-list tools for managing the customer contact graph."
4
+ icon: 👥
5
+ tools:
6
+ - contact-create
7
+ - contact-lookup
8
+ - contact-update
9
+ - contact-list
10
+ always: true
11
+ embed: false
12
+ ---
13
+
14
+ # Contacts
15
+
16
+ Manages customer contact records in the knowledge graph. Admin agent only — the public agent has no write access.
17
+
18
+ Tools are available via the `contacts` MCP server.
@@ -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":""}