@desktalk/core 0.1.0-alpha.1

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 (281) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +82 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/frontend/assets/frontend-B3QNYf3p.js +413 -0
  7. package/dist/frontend/assets/frontend-B3QNYf3p.js.map +1 -0
  8. package/dist/frontend/assets/frontend-B4aeXn9d.js +416 -0
  9. package/dist/frontend/assets/frontend-B4aeXn9d.js.map +1 -0
  10. package/dist/frontend/assets/frontend-BwyRSlHp.js +6513 -0
  11. package/dist/frontend/assets/frontend-BwyRSlHp.js.map +1 -0
  12. package/dist/frontend/assets/frontend-Dix2OWTT.js +229 -0
  13. package/dist/frontend/assets/frontend-Dix2OWTT.js.map +1 -0
  14. package/dist/frontend/assets/frontend-Dx41dEM9.js +407 -0
  15. package/dist/frontend/assets/frontend-Dx41dEM9.js.map +1 -0
  16. package/dist/frontend/assets/frontend-WpQng8Mt.js +1991 -0
  17. package/dist/frontend/assets/frontend-WpQng8Mt.js.map +1 -0
  18. package/dist/frontend/assets/frontend-rTwBdJbn.js +2123 -0
  19. package/dist/frontend/assets/frontend-rTwBdJbn.js.map +1 -0
  20. package/dist/frontend/assets/highlighted-body-TPN3WLV5-DD4wpkf4.js +2 -0
  21. package/dist/frontend/assets/highlighted-body-TPN3WLV5-DD4wpkf4.js.map +1 -0
  22. package/dist/frontend/assets/index-C5-XUOS7.js +1863 -0
  23. package/dist/frontend/assets/index-C5-XUOS7.js.map +1 -0
  24. package/dist/frontend/assets/index-C_e3_6yE.css +1 -0
  25. package/dist/frontend/index.html +22 -0
  26. package/dist/frontend/pcm-capture-processor.js +65 -0
  27. package/dist/i18n/manifest.json +34 -0
  28. package/dist/i18n/zh-CN.json +7 -0
  29. package/dist/index.d.ts +6 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +6 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/server/admin-routes.d.ts +14 -0
  34. package/dist/server/admin-routes.d.ts.map +1 -0
  35. package/dist/server/admin-routes.js +118 -0
  36. package/dist/server/admin-routes.js.map +1 -0
  37. package/dist/server/api-routes.d.ts +8 -0
  38. package/dist/server/api-routes.d.ts.map +1 -0
  39. package/dist/server/api-routes.js +203 -0
  40. package/dist/server/api-routes.js.map +1 -0
  41. package/dist/server/auth-routes.d.ts +19 -0
  42. package/dist/server/auth-routes.d.ts.map +1 -0
  43. package/dist/server/auth-routes.js +155 -0
  44. package/dist/server/auth-routes.js.map +1 -0
  45. package/dist/server/dtfs-routes.d.ts +3 -0
  46. package/dist/server/dtfs-routes.d.ts.map +1 -0
  47. package/dist/server/dtfs-routes.js +183 -0
  48. package/dist/server/dtfs-routes.js.map +1 -0
  49. package/dist/server/index.d.ts +15 -0
  50. package/dist/server/index.d.ts.map +1 -0
  51. package/dist/server/index.js +158 -0
  52. package/dist/server/index.js.map +1 -0
  53. package/dist/server/monaco-routes.d.ts +3 -0
  54. package/dist/server/monaco-routes.d.ts.map +1 -0
  55. package/dist/server/monaco-routes.js +45 -0
  56. package/dist/server/monaco-routes.js.map +1 -0
  57. package/dist/server/voice-routes.d.ts +7 -0
  58. package/dist/server/voice-routes.d.ts.map +1 -0
  59. package/dist/server/voice-routes.js +142 -0
  60. package/dist/server/voice-routes.js.map +1 -0
  61. package/dist/server/ws-routes.d.ts +29 -0
  62. package/dist/server/ws-routes.d.ts.map +1 -0
  63. package/dist/server/ws-routes.js +334 -0
  64. package/dist/server/ws-routes.js.map +1 -0
  65. package/dist/services/ai/action-tool.d.ts +9 -0
  66. package/dist/services/ai/action-tool.d.ts.map +1 -0
  67. package/dist/services/ai/action-tool.js +51 -0
  68. package/dist/services/ai/action-tool.js.map +1 -0
  69. package/dist/services/ai/app-tools.d.ts +15 -0
  70. package/dist/services/ai/app-tools.d.ts.map +1 -0
  71. package/dist/services/ai/app-tools.js +119 -0
  72. package/dist/services/ai/app-tools.js.map +1 -0
  73. package/dist/services/ai/chat-service.d.ts +27 -0
  74. package/dist/services/ai/chat-service.d.ts.map +1 -0
  75. package/dist/services/ai/chat-service.js +213 -0
  76. package/dist/services/ai/chat-service.js.map +1 -0
  77. package/dist/services/ai/create-liveapp-tool.d.ts +15 -0
  78. package/dist/services/ai/create-liveapp-tool.d.ts.map +1 -0
  79. package/dist/services/ai/create-liveapp-tool.js +142 -0
  80. package/dist/services/ai/create-liveapp-tool.js.map +1 -0
  81. package/dist/services/ai/desktop-tool.d.ts +27 -0
  82. package/dist/services/ai/desktop-tool.d.ts.map +1 -0
  83. package/dist/services/ai/desktop-tool.js +106 -0
  84. package/dist/services/ai/desktop-tool.js.map +1 -0
  85. package/dist/services/ai/edit-history.d.ts +16 -0
  86. package/dist/services/ai/edit-history.d.ts.map +1 -0
  87. package/dist/services/ai/edit-history.js +137 -0
  88. package/dist/services/ai/edit-history.js.map +1 -0
  89. package/dist/services/ai/edit-tool.d.ts +9 -0
  90. package/dist/services/ai/edit-tool.d.ts.map +1 -0
  91. package/dist/services/ai/edit-tool.js +113 -0
  92. package/dist/services/ai/edit-tool.js.map +1 -0
  93. package/dist/services/ai/generate-html-tool.d.ts +15 -0
  94. package/dist/services/ai/generate-html-tool.d.ts.map +1 -0
  95. package/dist/services/ai/generate-html-tool.js +140 -0
  96. package/dist/services/ai/generate-html-tool.js.map +1 -0
  97. package/dist/services/ai/generate-icon-tool.d.ts +10 -0
  98. package/dist/services/ai/generate-icon-tool.d.ts.map +1 -0
  99. package/dist/services/ai/generate-icon-tool.js +58 -0
  100. package/dist/services/ai/generate-icon-tool.js.map +1 -0
  101. package/dist/services/ai/html-bridge-script.d.ts +2 -0
  102. package/dist/services/ai/html-bridge-script.d.ts.map +1 -0
  103. package/dist/services/ai/html-bridge-script.js +2 -0
  104. package/dist/services/ai/html-bridge-script.js.map +1 -0
  105. package/dist/services/ai/html-guidelines-tool.d.ts +3 -0
  106. package/dist/services/ai/html-guidelines-tool.d.ts.map +1 -0
  107. package/dist/services/ai/html-guidelines-tool.js +157 -0
  108. package/dist/services/ai/html-guidelines-tool.js.map +1 -0
  109. package/dist/services/ai/html-stream-coordinator.d.ts +92 -0
  110. package/dist/services/ai/html-stream-coordinator.d.ts.map +1 -0
  111. package/dist/services/ai/html-stream-coordinator.js +314 -0
  112. package/dist/services/ai/html-stream-coordinator.js.map +1 -0
  113. package/dist/services/ai/html-theme-link.d.ts +9 -0
  114. package/dist/services/ai/html-theme-link.d.ts.map +1 -0
  115. package/dist/services/ai/html-theme-link.js +12 -0
  116. package/dist/services/ai/html-theme-link.js.map +1 -0
  117. package/dist/services/ai/html-ui-script.d.ts +9 -0
  118. package/dist/services/ai/html-ui-script.d.ts.map +1 -0
  119. package/dist/services/ai/html-ui-script.js +9 -0
  120. package/dist/services/ai/html-ui-script.js.map +1 -0
  121. package/dist/services/ai/image-generation-service.d.ts +26 -0
  122. package/dist/services/ai/image-generation-service.d.ts.map +1 -0
  123. package/dist/services/ai/image-generation-service.js +205 -0
  124. package/dist/services/ai/image-generation-service.js.map +1 -0
  125. package/dist/services/ai/manual-pages/desktop-actions.md +36 -0
  126. package/dist/services/ai/manual-pages/desktop-windows.md +24 -0
  127. package/dist/services/ai/manual-pages/dt-badge.md +36 -0
  128. package/dist/services/ai/manual-pages/dt-button.md +38 -0
  129. package/dist/services/ai/manual-pages/dt-card.md +22 -0
  130. package/dist/services/ai/manual-pages/dt-chart.md +261 -0
  131. package/dist/services/ai/manual-pages/dt-divider.md +25 -0
  132. package/dist/services/ai/manual-pages/dt-grid.md +29 -0
  133. package/dist/services/ai/manual-pages/dt-list-view.md +96 -0
  134. package/dist/services/ai/manual-pages/dt-markdown-editor.md +90 -0
  135. package/dist/services/ai/manual-pages/dt-markdown.md +86 -0
  136. package/dist/services/ai/manual-pages/dt-select.md +21 -0
  137. package/dist/services/ai/manual-pages/dt-stack.md +31 -0
  138. package/dist/services/ai/manual-pages/dt-stat.md +43 -0
  139. package/dist/services/ai/manual-pages/dt-table-view.md +120 -0
  140. package/dist/services/ai/manual-pages/dt-tooltip.md +18 -0
  141. package/dist/services/ai/manual-pages/editing-preview.md +25 -0
  142. package/dist/services/ai/manual-pages/html-actions.md +74 -0
  143. package/dist/services/ai/manual-pages/html-bridge.md +187 -0
  144. package/dist/services/ai/manual-pages/html-components.md +66 -0
  145. package/dist/services/ai/manual-pages/html-examples.md +185 -0
  146. package/dist/services/ai/manual-pages/html-layouts.md +128 -0
  147. package/dist/services/ai/manual-pages/html-storage.md +153 -0
  148. package/dist/services/ai/manual-pages/html-tokens.md +26 -0
  149. package/dist/services/ai/manual-pages/index.d.ts +10 -0
  150. package/dist/services/ai/manual-pages/index.d.ts.map +1 -0
  151. package/dist/services/ai/manual-pages/index.js +186 -0
  152. package/dist/services/ai/manual-pages/index.js.map +1 -0
  153. package/dist/services/ai/manual-tool.d.ts +3 -0
  154. package/dist/services/ai/manual-tool.d.ts.map +1 -0
  155. package/dist/services/ai/manual-tool.js +104 -0
  156. package/dist/services/ai/manual-tool.js.map +1 -0
  157. package/dist/services/ai/pi-session-service.d.ts +101 -0
  158. package/dist/services/ai/pi-session-service.d.ts.map +1 -0
  159. package/dist/services/ai/pi-session-service.js +697 -0
  160. package/dist/services/ai/pi-session-service.js.map +1 -0
  161. package/dist/services/ai/providers.d.ts +21 -0
  162. package/dist/services/ai/providers.d.ts.map +1 -0
  163. package/dist/services/ai/providers.js +93 -0
  164. package/dist/services/ai/providers.js.map +1 -0
  165. package/dist/services/ai/redo-edit-tool.d.ts +9 -0
  166. package/dist/services/ai/redo-edit-tool.d.ts.map +1 -0
  167. package/dist/services/ai/redo-edit-tool.js +44 -0
  168. package/dist/services/ai/redo-edit-tool.js.map +1 -0
  169. package/dist/services/ai/system-prompt.d.ts +7 -0
  170. package/dist/services/ai/system-prompt.d.ts.map +1 -0
  171. package/dist/services/ai/system-prompt.js +72 -0
  172. package/dist/services/ai/system-prompt.js.map +1 -0
  173. package/dist/services/ai/undo-edit-tool.d.ts +9 -0
  174. package/dist/services/ai/undo-edit-tool.d.ts.map +1 -0
  175. package/dist/services/ai/undo-edit-tool.js +44 -0
  176. package/dist/services/ai/undo-edit-tool.js.map +1 -0
  177. package/dist/services/ai/window-tools.d.ts +27 -0
  178. package/dist/services/ai/window-tools.d.ts.map +1 -0
  179. package/dist/services/ai/window-tools.js +155 -0
  180. package/dist/services/ai/window-tools.js.map +1 -0
  181. package/dist/services/backend-host.d.ts +10 -0
  182. package/dist/services/backend-host.d.ts.map +1 -0
  183. package/dist/services/backend-host.js +117 -0
  184. package/dist/services/backend-host.js.map +1 -0
  185. package/dist/services/backend-ipc.d.ts +60 -0
  186. package/dist/services/backend-ipc.d.ts.map +1 -0
  187. package/dist/services/backend-ipc.js +2 -0
  188. package/dist/services/backend-ipc.js.map +1 -0
  189. package/dist/services/backend-process-manager.d.ts +60 -0
  190. package/dist/services/backend-process-manager.d.ts.map +1 -0
  191. package/dist/services/backend-process-manager.js +203 -0
  192. package/dist/services/backend-process-manager.js.map +1 -0
  193. package/dist/services/filesystem.d.ts +8 -0
  194. package/dist/services/filesystem.d.ts.map +1 -0
  195. package/dist/services/filesystem.js +94 -0
  196. package/dist/services/filesystem.js.map +1 -0
  197. package/dist/services/i18n.d.ts +28 -0
  198. package/dist/services/i18n.d.ts.map +1 -0
  199. package/dist/services/i18n.js +76 -0
  200. package/dist/services/i18n.js.map +1 -0
  201. package/dist/services/liveapp-icon.d.ts +9 -0
  202. package/dist/services/liveapp-icon.d.ts.map +1 -0
  203. package/dist/services/liveapp-icon.js +28 -0
  204. package/dist/services/liveapp-icon.js.map +1 -0
  205. package/dist/services/liveapps.d.ts +12 -0
  206. package/dist/services/liveapps.d.ts.map +1 -0
  207. package/dist/services/liveapps.js +84 -0
  208. package/dist/services/liveapps.js.map +1 -0
  209. package/dist/services/logger.d.ts +34 -0
  210. package/dist/services/logger.d.ts.map +1 -0
  211. package/dist/services/logger.js +74 -0
  212. package/dist/services/logger.js.map +1 -0
  213. package/dist/services/messaging.d.ts +14 -0
  214. package/dist/services/messaging.d.ts.map +1 -0
  215. package/dist/services/messaging.js +41 -0
  216. package/dist/services/messaging.js.map +1 -0
  217. package/dist/services/miniapp-icon.d.ts +9 -0
  218. package/dist/services/miniapp-icon.d.ts.map +1 -0
  219. package/dist/services/miniapp-icon.js +25 -0
  220. package/dist/services/miniapp-icon.js.map +1 -0
  221. package/dist/services/miniapp-registry.d.ts +73 -0
  222. package/dist/services/miniapp-registry.d.ts.map +1 -0
  223. package/dist/services/miniapp-registry.js +144 -0
  224. package/dist/services/miniapp-registry.js.map +1 -0
  225. package/dist/services/onboarding-config.d.ts +37 -0
  226. package/dist/services/onboarding-config.d.ts.map +1 -0
  227. package/dist/services/onboarding-config.js +76 -0
  228. package/dist/services/onboarding-config.js.map +1 -0
  229. package/dist/services/preferences.d.ts +10 -0
  230. package/dist/services/preferences.d.ts.map +1 -0
  231. package/dist/services/preferences.js +48 -0
  232. package/dist/services/preferences.js.map +1 -0
  233. package/dist/services/proxy-dispatcher.d.ts +18 -0
  234. package/dist/services/proxy-dispatcher.d.ts.map +1 -0
  235. package/dist/services/proxy-dispatcher.js +33 -0
  236. package/dist/services/proxy-dispatcher.js.map +1 -0
  237. package/dist/services/storage.d.ts +7 -0
  238. package/dist/services/storage.d.ts.map +1 -0
  239. package/dist/services/storage.js +55 -0
  240. package/dist/services/storage.js.map +1 -0
  241. package/dist/services/theme-css.d.ts +21 -0
  242. package/dist/services/theme-css.d.ts.map +1 -0
  243. package/dist/services/theme-css.js +213 -0
  244. package/dist/services/theme-css.js.map +1 -0
  245. package/dist/services/user-db.d.ts +69 -0
  246. package/dist/services/user-db.d.ts.map +1 -0
  247. package/dist/services/user-db.js +175 -0
  248. package/dist/services/user-db.js.map +1 -0
  249. package/dist/services/voice/audio-format.d.ts +5 -0
  250. package/dist/services/voice/audio-format.d.ts.map +1 -0
  251. package/dist/services/voice/audio-format.js +27 -0
  252. package/dist/services/voice/audio-format.js.map +1 -0
  253. package/dist/services/voice/azure-openai-whisper-adapter.d.ts +23 -0
  254. package/dist/services/voice/azure-openai-whisper-adapter.d.ts.map +1 -0
  255. package/dist/services/voice/azure-openai-whisper-adapter.js +60 -0
  256. package/dist/services/voice/azure-openai-whisper-adapter.js.map +1 -0
  257. package/dist/services/voice/openai-whisper-adapter.d.ts +22 -0
  258. package/dist/services/voice/openai-whisper-adapter.d.ts.map +1 -0
  259. package/dist/services/voice/openai-whisper-adapter.js +61 -0
  260. package/dist/services/voice/openai-whisper-adapter.js.map +1 -0
  261. package/dist/services/voice/stt-adapter.d.ts +31 -0
  262. package/dist/services/voice/stt-adapter.d.ts.map +1 -0
  263. package/dist/services/voice/stt-adapter.js +8 -0
  264. package/dist/services/voice/stt-adapter.js.map +1 -0
  265. package/dist/services/voice/vad-segmenter.d.ts +68 -0
  266. package/dist/services/voice/vad-segmenter.d.ts.map +1 -0
  267. package/dist/services/voice/vad-segmenter.js +159 -0
  268. package/dist/services/voice/vad-segmenter.js.map +1 -0
  269. package/dist/services/voice/voice-session.d.ts +54 -0
  270. package/dist/services/voice/voice-session.d.ts.map +1 -0
  271. package/dist/services/voice/voice-session.js +137 -0
  272. package/dist/services/voice/voice-session.js.map +1 -0
  273. package/dist/services/window-manager.d.ts +94 -0
  274. package/dist/services/window-manager.d.ts.map +1 -0
  275. package/dist/services/window-manager.js +282 -0
  276. package/dist/services/window-manager.js.map +1 -0
  277. package/dist/services/workspace.d.ts +51 -0
  278. package/dist/services/workspace.d.ts.map +1 -0
  279. package/dist/services/workspace.js +144 -0
  280. package/dist/services/workspace.js.map +1 -0
  281. package/package.json +89 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Fastify plugin that registers authentication and setup routes.
3
+ *
4
+ * Public routes (no session required):
5
+ * POST /api/auth/login
6
+ * GET /api/auth/me
7
+ * GET /api/setup/status
8
+ * POST /api/setup
9
+ *
10
+ * Authenticated routes:
11
+ * POST /api/auth/logout
12
+ * PUT /api/auth/me/password
13
+ */
14
+ import '@fastify/cookie';
15
+ import { verifyPassword, createUser, createSession, deleteSession, updateUserPassword, hasAdmin, findUser, validateSession, } from '../services/user-db.js';
16
+ import { ensureUserHome } from '../services/workspace.js';
17
+ import { saveOnboardingConfig } from '../services/onboarding-config.js';
18
+ const COOKIE_NAME = 'desktalk_session';
19
+ /** Cookie options shared across set/clear. */
20
+ function cookieOptions(secure) {
21
+ return {
22
+ path: '/',
23
+ httpOnly: true,
24
+ sameSite: 'strict',
25
+ secure,
26
+ };
27
+ }
28
+ export async function authRoutes(app) {
29
+ const isSecure = false; // TODO: derive from app config once HTTPS is supported
30
+ // ─── POST /api/auth/login (public) ──────────────────────────────────
31
+ app.post('/api/auth/login', async (req, reply) => {
32
+ const { username, password } = req.body ?? {};
33
+ if (!username || !password) {
34
+ reply.code(400);
35
+ return { error: 'Username and password are required.' };
36
+ }
37
+ const user = verifyPassword(username, password);
38
+ if (!user) {
39
+ reply.code(401);
40
+ return { error: 'Invalid username or password.' };
41
+ }
42
+ ensureUserHome(user.username);
43
+ const token = createSession(username);
44
+ reply.setCookie(COOKIE_NAME, token, cookieOptions(isSecure));
45
+ return {
46
+ username: user.username,
47
+ displayName: user.displayName,
48
+ role: user.role,
49
+ };
50
+ });
51
+ // ─── POST /api/auth/logout ──────────────────────────────────────────
52
+ app.post('/api/auth/logout', async (req, reply) => {
53
+ const token = req.cookies[COOKIE_NAME];
54
+ if (token) {
55
+ deleteSession(token);
56
+ }
57
+ reply.clearCookie(COOKIE_NAME, cookieOptions(isSecure));
58
+ return { ok: true };
59
+ });
60
+ // ─── GET /api/auth/me (public) ───────────────────────────────────────
61
+ // When authenticated: returns the current user info.
62
+ // When unauthenticated: returns { authenticated: false, needsSetup }
63
+ // so the frontend can decide between login vs onboard page.
64
+ app.get('/api/auth/me', async (req) => {
65
+ const requestUser = req.user;
66
+ const token = req.cookies[COOKIE_NAME];
67
+ const user = requestUser ?? (token ? validateSession(token) : undefined);
68
+ if (!user) {
69
+ return {
70
+ authenticated: false,
71
+ needsSetup: !hasAdmin(),
72
+ };
73
+ }
74
+ ensureUserHome(user.username);
75
+ return {
76
+ authenticated: true,
77
+ username: user.username,
78
+ displayName: user.displayName,
79
+ role: user.role,
80
+ };
81
+ });
82
+ // ─── PUT /api/auth/me/password ──────────────────────────────────────
83
+ app.put('/api/auth/me/password', async (req, reply) => {
84
+ const user = req.user;
85
+ if (!user) {
86
+ reply.code(401);
87
+ return { error: 'Not authenticated.' };
88
+ }
89
+ const { oldPassword, newPassword } = req.body ?? {};
90
+ if (!oldPassword || !newPassword) {
91
+ reply.code(400);
92
+ return { error: 'Both oldPassword and newPassword are required.' };
93
+ }
94
+ if (newPassword.length < 8) {
95
+ reply.code(400);
96
+ return { error: 'Password must be at least 8 characters.' };
97
+ }
98
+ // Verify old password
99
+ const verified = verifyPassword(user.username, oldPassword);
100
+ if (!verified) {
101
+ reply.code(403);
102
+ return { error: 'Current password is incorrect.' };
103
+ }
104
+ updateUserPassword(user.username, newPassword);
105
+ return { ok: true };
106
+ });
107
+ // ─── GET /api/setup/status (public) ─────────────────────────────────
108
+ // Returns whether the system needs initial setup (no admin account).
109
+ app.get('/api/setup/status', async () => {
110
+ return { needsSetup: !hasAdmin() };
111
+ });
112
+ // ─── POST /api/setup (public) ───────────────────────────────────────
113
+ // Creates the initial admin account during onboarding.
114
+ // Only succeeds when no admin account exists yet.
115
+ app.post('/api/setup', async (req, reply) => {
116
+ // Guard: only allow setup when no admin exists
117
+ if (hasAdmin()) {
118
+ reply.code(403);
119
+ return { error: 'System is already set up. An admin account exists.' };
120
+ }
121
+ const { username, displayName, password, aiConfig, voiceConfig } = req.body ?? {};
122
+ if (!username || !displayName || !password) {
123
+ reply.code(400);
124
+ return { error: 'Username, displayName, and password are required.' };
125
+ }
126
+ if (!/^[a-zA-Z0-9_-]{1,32}$/.test(username)) {
127
+ reply.code(400);
128
+ return { error: 'Username must be 1-32 alphanumeric characters, hyphens, or underscores.' };
129
+ }
130
+ if (password.length < 8) {
131
+ reply.code(400);
132
+ return { error: 'Password must be at least 8 characters.' };
133
+ }
134
+ if (findUser(username)) {
135
+ reply.code(409);
136
+ return { error: `User "${username}" already exists.` };
137
+ }
138
+ // Create the admin account and their home directory
139
+ const user = createUser(username, password, 'admin', displayName);
140
+ ensureUserHome(username);
141
+ // Persist optional provider configuration from onboarding
142
+ saveOnboardingConfig(username, aiConfig, voiceConfig);
143
+ // Automatically log the admin in
144
+ const token = createSession(username);
145
+ reply.setCookie(COOKIE_NAME, token, cookieOptions(isSecure));
146
+ return {
147
+ ok: true,
148
+ username: user.username,
149
+ displayName: user.displayName,
150
+ role: user.role,
151
+ };
152
+ });
153
+ }
154
+ export { COOKIE_NAME };
155
+ //# sourceMappingURL=auth-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-routes.js","sourceRoot":"","sources":["../../src/server/auth-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ export declare function dtfsRoutes(app: FastifyInstance): Promise<void>;
3
+ //# sourceMappingURL=dtfs-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtfs-routes.d.ts","sourceRoot":"","sources":["../../src/server/dtfs-routes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA4I/C,wBAAsB,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EpE"}
@@ -0,0 +1,183 @@
1
+ import { createReadStream } from 'node:fs';
2
+ import { lstat, readFile, realpath } from 'node:fs/promises';
3
+ import { extname, resolve, sep } from 'node:path';
4
+ import { createHtmlBridgeScript } from '@desktalk/sdk';
5
+ import { getUserHomeDir } from '../services/workspace.js';
6
+ const MIME_TYPES = {
7
+ '.css': 'text/css; charset=utf-8',
8
+ '.gif': 'image/gif',
9
+ '.htm': 'text/html; charset=utf-8',
10
+ '.html': 'text/html; charset=utf-8',
11
+ '.jpeg': 'image/jpeg',
12
+ '.jpg': 'image/jpeg',
13
+ '.js': 'application/javascript; charset=utf-8',
14
+ '.json': 'application/json; charset=utf-8',
15
+ '.mjs': 'application/javascript; charset=utf-8',
16
+ '.mp3': 'audio/mpeg',
17
+ '.mp4': 'video/mp4',
18
+ '.ogg': 'audio/ogg',
19
+ '.png': 'image/png',
20
+ '.svg': 'image/svg+xml',
21
+ '.txt': 'text/plain; charset=utf-8',
22
+ '.wav': 'audio/wav',
23
+ '.webm': 'video/webm',
24
+ '.webp': 'image/webp',
25
+ };
26
+ function createThemeLinkTag(accentColor, mode) {
27
+ const params = new URLSearchParams({ accent: accentColor, theme: mode });
28
+ return `<link rel="stylesheet" href="/api/ui/desktalk-theme.css?${params.toString()}" data-dt-theme>`;
29
+ }
30
+ function createThemeSyncScript(accentColor, mode) {
31
+ return `<script data-dt-theme-sync>
32
+ (() => {
33
+ const THEME_MESSAGE = 'desktalk:theme-update';
34
+ const THEME_SELECTOR = 'link[data-dt-theme]';
35
+ const updateTheme = (nextAccent, nextMode) => {
36
+ const params = new URLSearchParams({ accent: nextAccent, theme: nextMode });
37
+ const href = '/api/ui/desktalk-theme.css?' + params.toString();
38
+ let link = document.querySelector(THEME_SELECTOR);
39
+ if (!link) {
40
+ link = document.createElement('link');
41
+ link.rel = 'stylesheet';
42
+ link.setAttribute('data-dt-theme', '');
43
+ document.head.prepend(link);
44
+ }
45
+ link.href = href;
46
+ document.documentElement.dataset.theme = nextMode;
47
+ document.documentElement.style.colorScheme = nextMode;
48
+ document.documentElement.style.backgroundColor = nextMode === 'dark' ? '#101114' : '#f7f7fa';
49
+ document.body?.style.setProperty('background-color', nextMode === 'dark' ? '#101114' : '#f7f7fa');
50
+ };
51
+ updateTheme(${JSON.stringify(accentColor)}, ${JSON.stringify(mode)});
52
+ window.addEventListener('message', (event) => {
53
+ const data = event.data;
54
+ if (!data || data.type !== THEME_MESSAGE) return;
55
+ updateTheme(data.accentColor, data.mode === 'light' ? 'light' : 'dark');
56
+ });
57
+ })();
58
+ </script>`;
59
+ }
60
+ function stripDtInjections(html) {
61
+ return html
62
+ .replace(/<link[^>]*data-dt-theme[^>]*>\s*/gi, '')
63
+ .replace(/<script[^>]*data-dt-theme-sync[^>]*>[\s\S]*?<\/script>\s*/gi, '')
64
+ .replace(/<script[^>]*data-dt-ui[^>]*><\/script>\s*/gi, '')
65
+ .replace(/<script[^>]*data-dt-bridge[^>]*>[\s\S]*?<\/script>\s*/gi, '');
66
+ }
67
+ function injectIntoHtmlHead(html, snippet) {
68
+ const headMatch = html.match(/<head(\s[^>]*)?>|<head>/i);
69
+ if (headMatch && headMatch.index !== undefined) {
70
+ const insertPos = headMatch.index + headMatch[0].length;
71
+ return html.slice(0, insertPos) + '\n' + snippet + '\n' + html.slice(insertPos);
72
+ }
73
+ return snippet + '\n' + html;
74
+ }
75
+ function injectDtRuntime(html, options) {
76
+ const cleanHtml = stripDtInjections(html);
77
+ const snippet = [
78
+ createThemeLinkTag(options.accentColor, options.theme),
79
+ createThemeSyncScript(options.accentColor, options.theme),
80
+ '<script src="/api/ui/desktalk-ui.js" data-dt-ui></script>',
81
+ createHtmlBridgeScript(options.streamId, options.bridgeToken),
82
+ ].join('\n');
83
+ return injectIntoHtmlHead(cleanHtml, snippet);
84
+ }
85
+ function normalizeRelativePath(rawPath) {
86
+ return rawPath.replace(/\\/g, '/');
87
+ }
88
+ function isAllowedHiddenPath(relativePath) {
89
+ return relativePath === '.data/liveapps' || relativePath.startsWith('.data/liveapps/');
90
+ }
91
+ function hasDisallowedHiddenSegment(relativePath) {
92
+ const segments = normalizeRelativePath(relativePath).split('/').filter(Boolean);
93
+ const allowLiveAppsRoot = isAllowedHiddenPath(relativePath);
94
+ return segments.some((segment, index) => {
95
+ if (!segment.startsWith('.')) {
96
+ return false;
97
+ }
98
+ if (allowLiveAppsRoot && index === 0 && segment === '.data') {
99
+ return false;
100
+ }
101
+ if (allowLiveAppsRoot && index === 1 && segment === 'liveapps') {
102
+ return false;
103
+ }
104
+ return true;
105
+ });
106
+ }
107
+ function resolveUserFile(userHomeDir, relativePath) {
108
+ const normalized = normalizeRelativePath(relativePath).replace(/^\/+/, '');
109
+ const resolvedPath = resolve(userHomeDir, normalized);
110
+ const homePrefix = `${resolve(userHomeDir)}${sep}`;
111
+ if (resolvedPath !== resolve(userHomeDir) && !resolvedPath.startsWith(homePrefix)) {
112
+ throw new Error('Path escapes the user home directory.');
113
+ }
114
+ return resolvedPath;
115
+ }
116
+ function getMimeType(filePath) {
117
+ return MIME_TYPES[extname(filePath).toLowerCase()] ?? 'application/octet-stream';
118
+ }
119
+ export async function dtfsRoutes(app) {
120
+ app.get('/@dtfs/*', async (req, reply) => {
121
+ const rawPath = req.params['*'];
122
+ if (!rawPath) {
123
+ reply.code(404);
124
+ return { error: 'Not found' };
125
+ }
126
+ const relativePath = normalizeRelativePath(decodeURIComponent(rawPath));
127
+ if (!relativePath || relativePath.split('/').some((segment) => segment === '..')) {
128
+ reply.code(400);
129
+ return { error: 'Invalid file path' };
130
+ }
131
+ if (hasDisallowedHiddenSegment(relativePath)) {
132
+ reply.code(403);
133
+ return { error: 'Access denied' };
134
+ }
135
+ const userHomeDir = getUserHomeDir(req.user.username);
136
+ const absolutePath = resolveUserFile(userHomeDir, relativePath);
137
+ let stat;
138
+ try {
139
+ stat = await lstat(absolutePath);
140
+ }
141
+ catch (error) {
142
+ if (error.code === 'ENOENT') {
143
+ reply.code(404);
144
+ return { error: 'Not found' };
145
+ }
146
+ throw error;
147
+ }
148
+ if (!stat.isFile() || stat.isSymbolicLink()) {
149
+ reply.code(403);
150
+ return { error: 'Access denied' };
151
+ }
152
+ const realFilePath = await realpath(absolutePath);
153
+ const realHomeDir = await realpath(userHomeDir);
154
+ const realHomePrefix = `${realHomeDir}${sep}`;
155
+ if (realFilePath !== realHomeDir && !realFilePath.startsWith(realHomePrefix)) {
156
+ reply.code(403);
157
+ return { error: 'Access denied' };
158
+ }
159
+ const mimeType = getMimeType(relativePath);
160
+ const isHtml = mimeType.startsWith('text/html');
161
+ const isLiveAppHtml = isHtml && isAllowedHiddenPath(relativePath);
162
+ reply.header('X-Content-Type-Options', 'nosniff');
163
+ reply.header('Cache-Control', isHtml ? 'no-store' : 'no-cache');
164
+ if (!isHtml) {
165
+ reply.type(mimeType);
166
+ return reply.send(createReadStream(realFilePath));
167
+ }
168
+ let html = await readFile(realFilePath, 'utf-8');
169
+ const streamId = req.query.streamId;
170
+ const token = req.query.token;
171
+ if (isLiveAppHtml && streamId && token) {
172
+ html = injectDtRuntime(html, {
173
+ accentColor: req.query.accent ?? '#7c6ff7',
174
+ theme: req.query.theme === 'light' ? 'light' : 'dark',
175
+ streamId,
176
+ bridgeToken: token,
177
+ });
178
+ }
179
+ reply.type('text/html; charset=utf-8');
180
+ return reply.send(html);
181
+ });
182
+ }
183
+ //# sourceMappingURL=dtfs-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtfs-routes.js","sourceRoot":"","sources":["../../src/server/dtfs-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type pino from 'pino';
2
+ import { type PublicUser } from '../services/user-db.js';
3
+ export interface ServerOptions {
4
+ dev: boolean;
5
+ host: string;
6
+ port: number;
7
+ logger: pino.Logger;
8
+ }
9
+ declare module 'fastify' {
10
+ interface FastifyRequest {
11
+ user?: PublicUser;
12
+ }
13
+ }
14
+ export declare function createServer(options: ServerOptions): Promise<import("fastify").FastifyInstance<import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, pino.Logger<never, boolean>, import("fastify").FastifyTypeProviderDefault>>;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAO7B,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAavE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;CACrB;AAGD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,IAAI,CAAC,EAAE,UAAU,CAAC;KACnB;CACF;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,4TAiMxD"}
@@ -0,0 +1,158 @@
1
+ import Fastify from 'fastify';
2
+ import fastifyCookie from '@fastify/cookie';
3
+ import fastifyWebsocket from '@fastify/websocket';
4
+ import fastifyStatic from '@fastify/static';
5
+ import { join, dirname } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { broadcastRaw } from '../services/messaging.js';
8
+ import { registry } from '../services/miniapp-registry.js';
9
+ import { PiSessionService } from '../services/ai/pi-session-service.js';
10
+ import { getStoredPreference } from '../services/preferences.js';
11
+ import { getWorkspacePaths, getUserHomeDir } from '../services/workspace.js';
12
+ import { WindowManagerService } from '../services/window-manager.js';
13
+ import { validateSession } from '../services/user-db.js';
14
+ import { COOKIE_NAME, authRoutes } from './auth-routes.js';
15
+ import { adminRoutes } from './admin-routes.js';
16
+ import { wsRoutes } from './ws-routes.js';
17
+ import { voiceRoutes } from './voice-routes.js';
18
+ import { apiRoutes } from './api-routes.js';
19
+ import { dtfsRoutes } from './dtfs-routes.js';
20
+ import { monacoRoutes } from './monaco-routes.js';
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = dirname(__filename);
23
+ const corePackageRoot = join(__dirname, '..', '..');
24
+ export async function createServer(options) {
25
+ const app = Fastify({ loggerInstance: options.logger.child({ scope: 'http' }) });
26
+ const log = options.logger;
27
+ const workspacePaths = getWorkspacePaths();
28
+ const windowManager = new WindowManagerService(join(getUserHomeDir('admin'), '.storage', 'window-state.json'));
29
+ // ─── Track the "current user" for the AI service ───────────────────────
30
+ // The AI service is currently a singleton (not per-user). We track the
31
+ // most recently authenticated WebSocket user so the AI can activate
32
+ // MiniApps on their behalf.
33
+ let currentWsUsername = null;
34
+ windowManager.activatePersistedMiniApps(async (miniAppId, launchArgs) => {
35
+ // During startup restore, use the admin user as the default owner.
36
+ // In practice, persisted windows will be re-associated when the user logs in.
37
+ await registry.activate(miniAppId, 'admin', { launchArgs });
38
+ });
39
+ // ─── Pending requests for action invocations brokered to the frontend ───
40
+ const pendingWindowActionRequests = new Map();
41
+ async function invokeWindowAction(windowId, actionName, actionParams) {
42
+ const requestId = `window-action-${Date.now()}-${Math.random().toString(36).slice(2)}`;
43
+ return new Promise((resolve, reject) => {
44
+ const timeout = setTimeout(() => {
45
+ pendingWindowActionRequests.delete(requestId);
46
+ reject(new Error(`Timed out waiting for action result: ${actionName}`));
47
+ }, 10000);
48
+ pendingWindowActionRequests.set(requestId, { resolve, reject, timeout });
49
+ broadcastRaw({
50
+ type: 'window:invoke_action',
51
+ requestId,
52
+ windowId,
53
+ actionName,
54
+ params: actionParams ?? null,
55
+ });
56
+ });
57
+ }
58
+ // ─── Pending requests for AI window commands sent to the frontend ───
59
+ const pendingAiCommandRequests = new Map();
60
+ async function sendAiCommand(command) {
61
+ const requestId = `ai-cmd-${Date.now()}-${Math.random().toString(36).slice(2)}`;
62
+ return new Promise((resolve, reject) => {
63
+ const timeout = setTimeout(() => {
64
+ pendingAiCommandRequests.delete(requestId);
65
+ reject(new Error(`Timed out waiting for AI command result: ${command.action}`));
66
+ }, 10000);
67
+ pendingAiCommandRequests.set(requestId, { resolve, reject, timeout });
68
+ broadcastRaw({
69
+ type: 'window:ai_command',
70
+ requestId,
71
+ ...command,
72
+ });
73
+ });
74
+ }
75
+ const piSessionService = await PiSessionService.create(workspacePaths, async (key) => getStoredPreference(key), windowManager, invokeWindowAction, sendAiCommand, () => currentWsUsername ?? 'admin', log.child({ scope: 'ai-session' }));
76
+ // ─── Plugins ──────────────────────────────────────────────────────────────
77
+ await app.register(fastifyCookie);
78
+ await app.register(fastifyWebsocket);
79
+ if (!options.dev) {
80
+ const frontendDir = join(__dirname, '..', 'frontend');
81
+ await app.register(fastifyStatic, {
82
+ root: frontendDir,
83
+ prefix: '/',
84
+ wildcard: false,
85
+ });
86
+ }
87
+ // ─── Auth middleware ──────────────────────────────────────────────────────
88
+ // Validate session cookie on every request except public routes.
89
+ const PUBLIC_ROUTES = new Set([
90
+ '/api/auth/login',
91
+ '/api/auth/me',
92
+ '/api/setup/status',
93
+ '/api/setup',
94
+ '/api/preferences/public',
95
+ '/api/ui/desktalk-theme.css',
96
+ ]);
97
+ app.addHook('onRequest', async (req, reply) => {
98
+ // Skip auth for public routes
99
+ if (PUBLIC_ROUTES.has(req.url))
100
+ return;
101
+ if (req.url.startsWith('/api/ui/') && req.url.endsWith('.js'))
102
+ return;
103
+ if (req.url.startsWith('/api/ui/fonts/'))
104
+ return;
105
+ if (req.url.startsWith('/api/miniapps/text-edit/monaco/'))
106
+ return;
107
+ // Skip auth for static file requests (non-API, non-WS, non-dtfs)
108
+ if (!req.url.startsWith('/api/') && !req.url.startsWith('/ws') && !req.url.startsWith('/@dtfs'))
109
+ return;
110
+ const token = req.cookies[COOKIE_NAME];
111
+ if (!token) {
112
+ reply.code(401);
113
+ reply.send({ error: 'Authentication required.' });
114
+ return;
115
+ }
116
+ const user = validateSession(token);
117
+ if (!user) {
118
+ reply.code(401);
119
+ reply.send({ error: 'Session expired or invalid.' });
120
+ return;
121
+ }
122
+ req.user = user;
123
+ });
124
+ // ─── Auth & Admin Routes ──────────────────────────────────────────────────
125
+ await app.register(authRoutes);
126
+ await app.register(adminRoutes, { prefix: '/api/admin' });
127
+ await app.register(wsRoutes, {
128
+ logger: log,
129
+ piSessionService,
130
+ windowManager,
131
+ pendingWindowActionRequests,
132
+ pendingAiCommandRequests,
133
+ setCurrentWsUsername: (username) => {
134
+ currentWsUsername = username;
135
+ },
136
+ });
137
+ await app.register(voiceRoutes, { logger: log });
138
+ await app.register(apiRoutes, {
139
+ corePackageRoot,
140
+ piSessionService,
141
+ });
142
+ await app.register(monacoRoutes);
143
+ await app.register(dtfsRoutes);
144
+ app.setNotFoundHandler(async (req, reply) => {
145
+ if (req.url.startsWith('/api/') || req.url.startsWith('/ws')) {
146
+ reply.code(404);
147
+ return { error: 'Not found' };
148
+ }
149
+ if (options.dev) {
150
+ reply.code(404);
151
+ return { error: 'Frontend is served by the Vite dev server in development mode.' };
152
+ }
153
+ return reply.sendFile('index.html');
154
+ });
155
+ await app.listen({ host: options.host, port: options.port });
156
+ return app;
157
+ }
158
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ export declare function monacoRoutes(app: FastifyInstance): Promise<void>;
3
+ //# sourceMappingURL=monaco-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monaco-routes.d.ts","sourceRoot":"","sources":["../../src/server/monaco-routes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAkB/C,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BtE"}
@@ -0,0 +1,45 @@
1
+ import fastifyStatic from '@fastify/static';
2
+ import { createRequire } from 'node:module';
3
+ import { dirname, join } from 'node:path';
4
+ const MONACO_WORKER_PATHS = {
5
+ editorWorkerService: 'vs/editor/editor.worker.js',
6
+ json: 'vs/language/json/json.worker.js',
7
+ css: 'vs/language/css/css.worker.js',
8
+ scss: 'vs/language/css/css.worker.js',
9
+ less: 'vs/language/css/css.worker.js',
10
+ html: 'vs/language/html/html.worker.js',
11
+ handlebars: 'vs/language/html/html.worker.js',
12
+ razor: 'vs/language/html/html.worker.js',
13
+ typescript: 'vs/language/typescript/ts.worker.js',
14
+ javascript: 'vs/language/typescript/ts.worker.js',
15
+ };
16
+ const MONACO_ASSET_PREFIX = '/api/miniapps/text-edit/monaco/assets/';
17
+ const MONACO_WORKER_PREFIX = '/api/miniapps/text-edit/monaco/worker/';
18
+ export async function monacoRoutes(app) {
19
+ const require = createRequire(import.meta.url);
20
+ const editorWorkerEntry = require.resolve('monaco-editor/esm/vs/editor/editor.worker.js');
21
+ const monacoEsmDir = join(dirname(editorWorkerEntry), '..', '..');
22
+ await app.register(fastifyStatic, {
23
+ root: monacoEsmDir,
24
+ prefix: MONACO_ASSET_PREFIX,
25
+ decorateReply: false,
26
+ cacheControl: true,
27
+ immutable: true,
28
+ maxAge: '1d',
29
+ });
30
+ app.get(`${MONACO_WORKER_PREFIX}:label`, async (req, reply) => {
31
+ const workerPath = MONACO_WORKER_PATHS[req.params.label];
32
+ if (!workerPath) {
33
+ reply.code(404);
34
+ return { error: 'Unknown Monaco worker' };
35
+ }
36
+ const bootstrap = [
37
+ `globalThis._VSCODE_FILE_ROOT = new URL(${JSON.stringify(MONACO_ASSET_PREFIX)}, globalThis.location.origin).toString();`,
38
+ `await import(new URL(${JSON.stringify(`${MONACO_ASSET_PREFIX}${workerPath}`)}, globalThis.location.origin).toString());`,
39
+ ].join('\n');
40
+ reply.header('Content-Type', 'application/javascript; charset=utf-8');
41
+ reply.header('Cache-Control', 'public, max-age=86400, immutable');
42
+ return reply.send(bootstrap);
43
+ });
44
+ }
45
+ //# sourceMappingURL=monaco-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monaco-routes.js","sourceRoot":"","sources":["../../src/server/monaco-routes.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,mBAAmB,GAA2B;IAClD,mBAAmB,EAAE,4BAA4B;IACjD,IAAI,EAAE,iCAAiC;IACvC,GAAG,EAAE,+BAA+B;IACpC,IAAI,EAAE,+BAA+B;IACrC,IAAI,EAAE,+BAA+B;IACrC,IAAI,EAAE,iCAAiC;IACvC,UAAU,EAAE,iCAAiC;IAC7C,KAAK,EAAE,iCAAiC;IACxC,UAAU,EAAE,qCAAqC;IACjD,UAAU,EAAE,qCAAqC;CAClD,CAAC;AAEF,MAAM,mBAAmB,GAAG,wCAAwC,CAAC;AACrE,MAAM,oBAAoB,GAAG,wCAAwC,CAAC;AAEtE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAoB;IACrD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC;IAC1F,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAElE,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE;QAChC,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,mBAAmB;QAC3B,aAAa,EAAE,KAAK;QACpB,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAgC,GAAG,oBAAoB,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC3F,MAAM,UAAU,GAAG,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC5C,CAAC;QAED,MAAM,SAAS,GAAG;YAChB,0CAA0C,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,2CAA2C;YACxH,wBAAwB,IAAI,CAAC,SAAS,CAAC,GAAG,mBAAmB,GAAG,UAAU,EAAE,CAAC,4CAA4C;SAC1H,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,uCAAuC,CAAC,CAAC;QACtE,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,kCAAkC,CAAC,CAAC;QAClE,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type pino from 'pino';
3
+ export interface VoiceRoutesOptions {
4
+ logger: pino.Logger;
5
+ }
6
+ export declare function voiceRoutes(app: FastifyInstance, options: VoiceRoutesOptions): Promise<void>;
7
+ //# sourceMappingURL=voice-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-routes.d.ts","sourceRoot":"","sources":["../../src/server/voice-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAO7B,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;CACrB;AAqED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CA+Gf"}