@mooncompany/uplink-chat 0.5.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.

Potentially problematic release.


This version of @mooncompany/uplink-chat might be problematic. Click here for more details.

Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/bin/uplink.js +279 -0
  4. package/middleware/error-handler.js +69 -0
  5. package/package.json +93 -0
  6. package/public/css/agents.36b98c0f.css +1469 -0
  7. package/public/css/agents.css +1469 -0
  8. package/public/css/app.a6a7f8f5.css +2731 -0
  9. package/public/css/app.css +2731 -0
  10. package/public/css/artifacts.css +444 -0
  11. package/public/css/commands.css +55 -0
  12. package/public/css/connection.css +131 -0
  13. package/public/css/dashboard.css +233 -0
  14. package/public/css/developer.css +328 -0
  15. package/public/css/files.css +123 -0
  16. package/public/css/markdown.css +156 -0
  17. package/public/css/message-actions.css +278 -0
  18. package/public/css/mobile.css +614 -0
  19. package/public/css/panels-unified.css +483 -0
  20. package/public/css/premium.css +415 -0
  21. package/public/css/realtime.css +189 -0
  22. package/public/css/satellites.css +401 -0
  23. package/public/css/shortcuts.css +185 -0
  24. package/public/css/split-view.4def0262.css +673 -0
  25. package/public/css/split-view.css +673 -0
  26. package/public/css/theme-generator.css +391 -0
  27. package/public/css/themes.css +387 -0
  28. package/public/css/timestamps.css +54 -0
  29. package/public/css/variables.css +78 -0
  30. package/public/dist/bundle.b55050c4.js +15757 -0
  31. package/public/favicon.svg +24 -0
  32. package/public/img/agents/ada.png +0 -0
  33. package/public/img/agents/clarice.png +0 -0
  34. package/public/img/agents/dennis-nedry.png +0 -0
  35. package/public/img/agents/elliot-alderson.png +0 -0
  36. package/public/img/agents/main.png +0 -0
  37. package/public/img/agents/scotty.png +0 -0
  38. package/public/img/agents/top-flight-security.png +0 -0
  39. package/public/index.html +1083 -0
  40. package/public/js/agents-data.js +234 -0
  41. package/public/js/agents-ui.js +72 -0
  42. package/public/js/agents.js +1525 -0
  43. package/public/js/app.js +79 -0
  44. package/public/js/appearance-settings.js +111 -0
  45. package/public/js/artifacts.js +432 -0
  46. package/public/js/audio-queue.js +168 -0
  47. package/public/js/bootstrap.js +54 -0
  48. package/public/js/chat.js +1211 -0
  49. package/public/js/commands.js +581 -0
  50. package/public/js/connection-api.js +121 -0
  51. package/public/js/connection.js +1231 -0
  52. package/public/js/context-tracker.js +271 -0
  53. package/public/js/core.js +172 -0
  54. package/public/js/dashboard.js +452 -0
  55. package/public/js/developer.js +432 -0
  56. package/public/js/encryption.js +124 -0
  57. package/public/js/errors.js +122 -0
  58. package/public/js/event-bus.js +77 -0
  59. package/public/js/fetch-utils.js +171 -0
  60. package/public/js/file-handler.js +229 -0
  61. package/public/js/files.js +352 -0
  62. package/public/js/gateway-chat.js +538 -0
  63. package/public/js/logger.js +112 -0
  64. package/public/js/markdown.js +190 -0
  65. package/public/js/message-actions.js +431 -0
  66. package/public/js/message-renderer.js +288 -0
  67. package/public/js/missed-messages.js +235 -0
  68. package/public/js/mobile-debug.js +95 -0
  69. package/public/js/notifications.js +367 -0
  70. package/public/js/offline-queue.js +178 -0
  71. package/public/js/onboarding.js +543 -0
  72. package/public/js/panels.js +156 -0
  73. package/public/js/premium.js +412 -0
  74. package/public/js/realtime-voice.js +844 -0
  75. package/public/js/satellite-sync.js +256 -0
  76. package/public/js/satellite-ui.js +175 -0
  77. package/public/js/satellites.js +1516 -0
  78. package/public/js/settings.js +1087 -0
  79. package/public/js/shortcuts.js +381 -0
  80. package/public/js/split-chat.js +1234 -0
  81. package/public/js/split-resize.js +211 -0
  82. package/public/js/splitview.js +340 -0
  83. package/public/js/storage.js +408 -0
  84. package/public/js/streaming-handler.js +324 -0
  85. package/public/js/stt-settings.js +316 -0
  86. package/public/js/theme-generator.js +661 -0
  87. package/public/js/themes.js +164 -0
  88. package/public/js/timestamps.js +198 -0
  89. package/public/js/tts-settings.js +575 -0
  90. package/public/js/ui.js +267 -0
  91. package/public/js/update-notifier.js +143 -0
  92. package/public/js/utils/constants.js +165 -0
  93. package/public/js/utils/sanitize.js +93 -0
  94. package/public/js/utils/sse-parser.js +195 -0
  95. package/public/js/voice.js +883 -0
  96. package/public/manifest.json +58 -0
  97. package/public/moon_texture.jpg +0 -0
  98. package/public/sw.js +221 -0
  99. package/public/three.min.js +6 -0
  100. package/server/channel.js +529 -0
  101. package/server/chat.js +270 -0
  102. package/server/config-store.js +362 -0
  103. package/server/config.js +159 -0
  104. package/server/context.js +131 -0
  105. package/server/gateway-commands.js +211 -0
  106. package/server/gateway-proxy.js +318 -0
  107. package/server/index.js +22 -0
  108. package/server/logger.js +89 -0
  109. package/server/middleware/auth.js +188 -0
  110. package/server/middleware.js +218 -0
  111. package/server/openclaw-discover.js +308 -0
  112. package/server/premium/index.js +156 -0
  113. package/server/premium/license.js +140 -0
  114. package/server/realtime/bridge.js +837 -0
  115. package/server/realtime/index.js +349 -0
  116. package/server/realtime/tts-stream.js +446 -0
  117. package/server/routes/agents.js +564 -0
  118. package/server/routes/artifacts.js +174 -0
  119. package/server/routes/chat.js +311 -0
  120. package/server/routes/config-settings.js +345 -0
  121. package/server/routes/config.js +603 -0
  122. package/server/routes/files.js +307 -0
  123. package/server/routes/index.js +18 -0
  124. package/server/routes/media.js +451 -0
  125. package/server/routes/missed-messages.js +107 -0
  126. package/server/routes/premium.js +75 -0
  127. package/server/routes/push.js +156 -0
  128. package/server/routes/satellite.js +406 -0
  129. package/server/routes/status.js +251 -0
  130. package/server/routes/stt.js +35 -0
  131. package/server/routes/voice.js +260 -0
  132. package/server/routes/webhooks.js +203 -0
  133. package/server/routes.js +206 -0
  134. package/server/runtime-config.js +336 -0
  135. package/server/share.js +305 -0
  136. package/server/stt/faster-whisper.js +72 -0
  137. package/server/stt/groq.js +51 -0
  138. package/server/stt/index.js +196 -0
  139. package/server/stt/openai.js +49 -0
  140. package/server/sync.js +244 -0
  141. package/server/tailscale-https.js +175 -0
  142. package/server/tts.js +646 -0
  143. package/server/update-checker.js +172 -0
  144. package/server/utils/filename.js +129 -0
  145. package/server/utils.js +147 -0
  146. package/server/watchdog.js +318 -0
  147. package/server/websocket/broadcast.js +359 -0
  148. package/server/websocket/connections.js +339 -0
  149. package/server/websocket/index.js +215 -0
  150. package/server/websocket/routing.js +277 -0
  151. package/server/websocket/sync.js +102 -0
  152. package/server.js +404 -0
  153. package/utils/detect-tool-usage.js +93 -0
  154. package/utils/errors.js +158 -0
  155. package/utils/html-escape.js +84 -0
  156. package/utils/id-sanitize.js +94 -0
  157. package/utils/response.js +130 -0
  158. package/utils/with-retry.js +105 -0
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Tailscale HTTPS Module
3
+ *
4
+ * Auto-detects Tailscale and provisions HTTPS certs for secure
5
+ * access over Tailscale. Enables getUserMedia (mic/camera) on mobile.
6
+ *
7
+ * Zero config — just works if Tailscale is running.
8
+ */
9
+
10
+ import https from 'https';
11
+ import { execSync, exec } from 'child_process';
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { log } from './utils.js';
15
+
16
+ const CERT_DIR = path.join(process.env.APPDATA || process.env.HOME || '.', 'uplink-certs');
17
+ const CERT_REFRESH_MS = 12 * 60 * 60 * 1000; // Refresh certs every 12 hours
18
+
19
+ /**
20
+ * Get the Tailscale FQDN for this machine
21
+ * @returns {string|null} e.g. "na8.tail8b977a.ts.net"
22
+ */
23
+ function getTailscaleDomain() {
24
+ try {
25
+ const statusJson = execSync('tailscale status --json', {
26
+ timeout: 5000,
27
+ encoding: 'utf-8',
28
+ stdio: ['pipe', 'pipe', 'pipe']
29
+ });
30
+ const status = JSON.parse(statusJson);
31
+
32
+ // CertDomains contains the FQDN(s) this node can get certs for
33
+ if (status.CertDomains && status.CertDomains.length > 0) {
34
+ return status.CertDomains[0];
35
+ }
36
+
37
+ // Fallback: construct from Self info
38
+ if (status.Self && status.Self.DNSName) {
39
+ // DNSName ends with a dot, remove it
40
+ return status.Self.DNSName.replace(/\.$/, '');
41
+ }
42
+
43
+ return null;
44
+ } catch (err) {
45
+ log('debug', `[Tailscale] Not available: ${err.message}`);
46
+ return null;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Get the Tailscale IP for this machine
52
+ * @returns {string|null}
53
+ */
54
+ function getTailscaleIP() {
55
+ try {
56
+ const ip = execSync('tailscale ip -4', {
57
+ timeout: 5000,
58
+ encoding: 'utf-8',
59
+ stdio: ['pipe', 'pipe', 'pipe']
60
+ }).trim();
61
+ return ip || null;
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Provision TLS certs from Tailscale for the given domain
69
+ * @param {string} domain
70
+ * @returns {{ cert: string, key: string } | null}
71
+ */
72
+ function provisionCerts(domain) {
73
+ try {
74
+ // Ensure cert directory exists
75
+ if (!fs.existsSync(CERT_DIR)) {
76
+ fs.mkdirSync(CERT_DIR, { recursive: true });
77
+ }
78
+
79
+ const certFile = path.join(CERT_DIR, `${domain}.crt`);
80
+ const keyFile = path.join(CERT_DIR, `${domain}.key`);
81
+
82
+ // Use tailscale cert to provision/renew
83
+ execSync(`tailscale cert --cert-file "${certFile}" --key-file "${keyFile}" "${domain}"`, {
84
+ timeout: 30000,
85
+ encoding: 'utf-8',
86
+ stdio: ['pipe', 'pipe', 'pipe']
87
+ });
88
+
89
+ if (fs.existsSync(certFile) && fs.existsSync(keyFile)) {
90
+ log('info', `[Tailscale] Certs provisioned for ${domain}`);
91
+ return {
92
+ cert: fs.readFileSync(certFile, 'utf-8'),
93
+ key: fs.readFileSync(keyFile, 'utf-8')
94
+ };
95
+ }
96
+
97
+ return null;
98
+ } catch (err) {
99
+ log('error', `[Tailscale] Failed to provision certs: ${err.message}`);
100
+ return null;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Set up HTTPS server with Tailscale certs
106
+ * Shares the same Express app as the HTTP server.
107
+ *
108
+ * @param {express.Application} app - Express app
109
+ * @param {object} options
110
+ * @param {number} options.httpsPort - Port for HTTPS (default: HTTP port + 1)
111
+ * @param {Function} options.onServer - Callback with (httpsServer, domain) to set up WebSocket etc.
112
+ * @returns {Promise<{ server: https.Server, domain: string, url: string } | null>}
113
+ */
114
+ export async function setupTailscaleHTTPS(app, options = {}) {
115
+ const domain = getTailscaleDomain();
116
+ if (!domain) {
117
+ log('info', '[Tailscale] Not detected, HTTPS disabled. Mic/camera requires localhost or HTTPS.');
118
+ return null;
119
+ }
120
+
121
+ const tsIP = getTailscaleIP();
122
+ log('info', `[Tailscale] Detected: ${domain} (${tsIP})`);
123
+
124
+ const certs = provisionCerts(domain);
125
+ if (!certs) {
126
+ log('warn', '[Tailscale] Could not provision certs. HTTPS disabled.');
127
+ return null;
128
+ }
129
+
130
+ const httpsPort = options.httpsPort || (parseInt(process.env.PORT || '3456') + 1);
131
+
132
+ const httpsServer = https.createServer({
133
+ cert: certs.cert,
134
+ key: certs.key
135
+ }, app);
136
+
137
+ // Let the caller wire up WebSocket handlers
138
+ if (options.onServer) {
139
+ options.onServer(httpsServer, domain);
140
+ }
141
+
142
+ return new Promise((resolve) => {
143
+ httpsServer.listen(httpsPort, '0.0.0.0', () => {
144
+ const url = `https://${domain}:${httpsPort}`;
145
+ log('info', `[Tailscale] HTTPS server running at ${url}`);
146
+
147
+ // Schedule cert refresh
148
+ const refreshInterval = setInterval(() => {
149
+ log('info', '[Tailscale] Refreshing certs...');
150
+ const newCerts = provisionCerts(domain);
151
+ if (newCerts) {
152
+ httpsServer.setSecureContext({
153
+ cert: newCerts.cert,
154
+ key: newCerts.key
155
+ });
156
+ log('info', '[Tailscale] Certs refreshed successfully');
157
+ }
158
+ }, CERT_REFRESH_MS);
159
+ refreshInterval.unref();
160
+
161
+ resolve({ server: httpsServer, domain, url, ip: tsIP });
162
+ });
163
+
164
+ httpsServer.on('error', (err) => {
165
+ if (err.code === 'EADDRINUSE') {
166
+ log('warn', `[Tailscale] Port ${httpsPort} in use, HTTPS disabled.`);
167
+ } else {
168
+ log('error', `[Tailscale] HTTPS server error: ${err.message}`);
169
+ }
170
+ resolve(null);
171
+ });
172
+ });
173
+ }
174
+
175
+ export { getTailscaleDomain, getTailscaleIP };