@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,142 @@
1
+ import { getStoredPreference } from '../services/preferences.js';
2
+ import { VoiceSession } from '../services/voice/voice-session.js';
3
+ import { AzureOpenAIWhisperAdapter } from '../services/voice/azure-openai-whisper-adapter.js';
4
+ import { OpenAIWhisperAdapter } from '../services/voice/openai-whisper-adapter.js';
5
+ async function getPreference(key) {
6
+ return getStoredPreference(key);
7
+ }
8
+ async function createSttAdapter() {
9
+ const provider = (await getPreference('voice.defaultProvider')) ??
10
+ (await getPreference('voice.provider')) ??
11
+ 'openai-whisper';
12
+ const providerPrefix = `voice.providers.${provider}`;
13
+ const apiKey = (await getPreference(`${providerPrefix}.apiKey`)) ??
14
+ (await getPreference('voice.apiKey'));
15
+ if (!apiKey)
16
+ return null;
17
+ if (provider === 'openai-whisper') {
18
+ const model = (await getPreference(`${providerPrefix}.model`)) ??
19
+ (await getPreference('voice.model')) ??
20
+ 'whisper-1';
21
+ const baseUrl = (await getPreference(`${providerPrefix}.baseUrl`)) ??
22
+ (await getPreference('voice.baseUrl')) ??
23
+ 'https://api.openai.com/v1';
24
+ return new OpenAIWhisperAdapter({ apiKey, model, baseUrl });
25
+ }
26
+ if (provider === 'azure-openai-whisper') {
27
+ const endpoint = (await getPreference(`${providerPrefix}.baseUrl`)) ??
28
+ (await getPreference('voice.baseUrl'));
29
+ const deployment = (await getPreference(`${providerPrefix}.azureDeployment`)) ??
30
+ (await getPreference('voice.azureDeployment'));
31
+ const apiVersion = (await getPreference(`${providerPrefix}.azureApiVersion`)) ??
32
+ (await getPreference('voice.azureApiVersion')) ??
33
+ '2024-06-01';
34
+ if (!endpoint || !deployment) {
35
+ return null;
36
+ }
37
+ return new AzureOpenAIWhisperAdapter({
38
+ apiKey,
39
+ endpoint,
40
+ deployment,
41
+ apiVersion,
42
+ });
43
+ }
44
+ return null;
45
+ }
46
+ async function getVadConfigFromPreferences() {
47
+ const silenceTimeoutMs = (await getPreference('voice.silenceTimeoutMs'));
48
+ const energyThreshold = (await getPreference('voice.energyThreshold'));
49
+ return {
50
+ ...(silenceTimeoutMs !== undefined ? { silenceTimeoutMs } : {}),
51
+ ...(energyThreshold !== undefined ? { energyThreshold } : {}),
52
+ };
53
+ }
54
+ export async function voiceRoutes(app, options) {
55
+ const voiceSessions = new Map();
56
+ const voiceLog = options.logger.child({ scope: 'voice' });
57
+ app.get('/ws/voice', { websocket: true }, (socket) => {
58
+ let session = null;
59
+ socket.on('message', async (raw) => {
60
+ if (Buffer.isBuffer(raw) || raw instanceof ArrayBuffer) {
61
+ let isJson = false;
62
+ try {
63
+ const str = Buffer.isBuffer(raw)
64
+ ? raw.toString('utf-8')
65
+ : Buffer.from(raw).toString('utf-8');
66
+ if (str.length > 0 && str[0] === '{') {
67
+ const msg = JSON.parse(str);
68
+ isJson = true;
69
+ await handleVoiceControlMessage(msg);
70
+ }
71
+ }
72
+ catch {
73
+ // Not JSON, treat as binary audio.
74
+ }
75
+ if (!isJson && session) {
76
+ const buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
77
+ await session.processAudioChunk(buf);
78
+ }
79
+ return;
80
+ }
81
+ if (Array.isArray(raw) && session) {
82
+ const buf = Buffer.concat(raw);
83
+ await session.processAudioChunk(buf);
84
+ }
85
+ });
86
+ async function handleVoiceControlMessage(msg) {
87
+ if (msg.type === 'session.start') {
88
+ const sessionId = msg.sessionId;
89
+ const sampleRate = msg.sampleRate ?? 16000;
90
+ const channels = msg.channels ?? 1;
91
+ const format = msg.format ?? 'pcm_s16le';
92
+ const prefLanguage = (await getPreference('general.language'));
93
+ const language = msg.language ?? prefLanguage;
94
+ const adapter = await createSttAdapter();
95
+ if (!adapter) {
96
+ socket.send(JSON.stringify({
97
+ type: 'error',
98
+ sessionId,
99
+ code: 'NO_STT_PROVIDER',
100
+ message: 'No STT provider configured. Check Preferences -> Voice for provider credentials.',
101
+ }));
102
+ return;
103
+ }
104
+ const vadConfig = await getVadConfigFromPreferences();
105
+ session = new VoiceSession(sessionId, socket, adapter, {
106
+ sampleRate,
107
+ channels,
108
+ format,
109
+ vad: vadConfig,
110
+ language,
111
+ }, voiceLog.child({ sessionId }));
112
+ voiceSessions.set(sessionId, session);
113
+ voiceLog.info({ sessionId, format, sampleRate, channels, language }, 'voice session started');
114
+ socket.send(JSON.stringify({
115
+ type: 'session.ready',
116
+ sessionId,
117
+ }));
118
+ }
119
+ else if (msg.type === 'session.end') {
120
+ const sessionId = msg.sessionId;
121
+ if (session) {
122
+ session.close();
123
+ voiceSessions.delete(session.sessionId);
124
+ session = null;
125
+ }
126
+ voiceLog.info({ sessionId }, 'voice session ended by client');
127
+ }
128
+ }
129
+ socket.on('close', () => {
130
+ if (session) {
131
+ voiceLog.info({ sessionId: session.sessionId }, 'voice session closed (connection lost)');
132
+ voiceSessions.delete(session.sessionId);
133
+ session.close();
134
+ session = null;
135
+ }
136
+ });
137
+ socket.on('error', (err) => {
138
+ voiceLog.error({ err: err.message }, 'voice WebSocket error');
139
+ });
140
+ });
141
+ }
142
+ //# sourceMappingURL=voice-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-routes.js","sourceRoot":"","sources":["../../src/server/voice-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type pino from 'pino';
3
+ import type { PiSessionService } from '../services/ai/pi-session-service.js';
4
+ import { type WindowManagerService } from '../services/window-manager.js';
5
+ type PendingWindowActionRequest = {
6
+ resolve: (value: unknown) => void;
7
+ reject: (reason?: unknown) => void;
8
+ timeout: ReturnType<typeof setTimeout>;
9
+ };
10
+ type PendingAiCommandRequest = {
11
+ resolve: (value: {
12
+ ok: boolean;
13
+ windowId?: string;
14
+ error?: string;
15
+ }) => void;
16
+ reject: (reason?: unknown) => void;
17
+ timeout: ReturnType<typeof setTimeout>;
18
+ };
19
+ export interface WsRoutesOptions {
20
+ logger: pino.Logger;
21
+ piSessionService: PiSessionService;
22
+ windowManager: WindowManagerService;
23
+ pendingWindowActionRequests: Map<string, PendingWindowActionRequest>;
24
+ pendingAiCommandRequests: Map<string, PendingAiCommandRequest>;
25
+ setCurrentWsUsername: (username: string | null) => void;
26
+ }
27
+ export declare function wsRoutes(app: FastifyInstance, options: WsRoutesOptions): Promise<void>;
28
+ export {};
29
+ //# sourceMappingURL=ws-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-routes.d.ts","sourceRoot":"","sources":["../../src/server/ws-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAM7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,4BAA4B,CAAC;AAEpC,KAAK,0BAA0B,GAAG;IAChC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CACxC,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,EAAE,oBAAoB,CAAC;IACpC,2BAA2B,EAAE,GAAG,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IACrE,wBAAwB,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAC/D,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACzD;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA4W5F"}
@@ -0,0 +1,334 @@
1
+ import { join } from 'node:path';
2
+ import { addClient } from '../services/messaging.js';
3
+ import { registry } from '../services/miniapp-registry.js';
4
+ import { processManager } from '../services/backend-process-manager.js';
5
+ import { setPreferenceUser } from '../services/preferences.js';
6
+ import { getUserHomeDir, ensureUserHome } from '../services/workspace.js';
7
+ export async function wsRoutes(app, options) {
8
+ const { logger, piSessionService, windowManager, pendingWindowActionRequests, pendingAiCommandRequests, setCurrentWsUsername, } = options;
9
+ app.get('/ws', { websocket: true }, (socket, req) => {
10
+ const user = req.user;
11
+ if (!user) {
12
+ socket.close(4001, 'Authentication required');
13
+ return;
14
+ }
15
+ const username = user.username;
16
+ setCurrentWsUsername(username);
17
+ addClient(socket);
18
+ let activeAiRequestId = null;
19
+ const cancelledAiRequestIds = new Set();
20
+ function sendAiEvent(event) {
21
+ socket.send(JSON.stringify({
22
+ type: 'ai:event',
23
+ event,
24
+ }));
25
+ }
26
+ void (async () => {
27
+ try {
28
+ ensureUserHome(username);
29
+ windowManager.switchUser(join(getUserHomeDir(username), '.storage', 'window-state.json'));
30
+ setPreferenceUser(username);
31
+ await windowManager.activatePersistedMiniApps(async (miniAppId, launchArgs) => {
32
+ await registry.activate(miniAppId, username, { launchArgs });
33
+ });
34
+ sendAiEvent({
35
+ type: 'history_sync',
36
+ sessionId: piSessionService.getSessionId(),
37
+ messages: piSessionService.getHistory(),
38
+ });
39
+ sendAiEvent({
40
+ type: 'sessions_sync',
41
+ sessionId: piSessionService.getSessionId(),
42
+ sessions: await piSessionService.listSessions(),
43
+ });
44
+ const persisted = windowManager.getPersistedState();
45
+ socket.send(JSON.stringify({
46
+ type: 'window:state',
47
+ version: persisted.version,
48
+ windows: persisted.windows,
49
+ tree: persisted.tree,
50
+ focusedWindowId: persisted.focusedWindowId,
51
+ fullscreenWindowId: persisted.fullscreenWindowId,
52
+ windowIdCounter: persisted.windowIdCounter,
53
+ nextSplitDirection: persisted.nextSplitDirection,
54
+ }));
55
+ }
56
+ catch (error) {
57
+ logger.error({ username, err: error instanceof Error ? error.message : String(error) }, 'failed to restore persisted miniapps for websocket session');
58
+ socket.close(1011, 'Failed to restore desktop state');
59
+ }
60
+ })();
61
+ socket.on('message', async (raw) => {
62
+ try {
63
+ const msg = JSON.parse(raw.toString());
64
+ if (msg.type === 'command:invoke') {
65
+ const { miniAppId, command, requestId, data } = msg;
66
+ const processKey = `${miniAppId}:${username}`;
67
+ try {
68
+ const result = await processManager.sendCommand(processKey, command, data);
69
+ socket.send(JSON.stringify({
70
+ type: 'command:response',
71
+ requestId,
72
+ data: result,
73
+ }));
74
+ }
75
+ catch (err) {
76
+ socket.send(JSON.stringify({
77
+ type: 'command:response',
78
+ requestId,
79
+ error: err.message,
80
+ }));
81
+ }
82
+ }
83
+ else if (msg.type === 'window:sync') {
84
+ if (Array.isArray(msg.windows)) {
85
+ windowManager.syncState({
86
+ version: 2,
87
+ windows: msg.windows,
88
+ tree: msg.tree ?? null,
89
+ focusedWindowId: typeof msg.focusedWindowId === 'string' ? msg.focusedWindowId : null,
90
+ fullscreenWindowId: typeof msg.fullscreenWindowId === 'string' ? msg.fullscreenWindowId : null,
91
+ windowIdCounter: typeof msg.windowIdCounter === 'number' ? msg.windowIdCounter : 0,
92
+ nextSplitDirection: msg.nextSplitDirection === 'horizontal' ||
93
+ msg.nextSplitDirection === 'vertical' ||
94
+ msg.nextSplitDirection === 'auto'
95
+ ? msg.nextSplitDirection
96
+ : 'auto',
97
+ });
98
+ }
99
+ }
100
+ else if (msg.type === 'window:actions_changed') {
101
+ if (typeof msg.windowId === 'string' && Array.isArray(msg.actions)) {
102
+ windowManager.setWindowActions(msg.windowId, msg.actions);
103
+ }
104
+ }
105
+ else if (msg.type === 'window:action_result') {
106
+ if (typeof msg.requestId === 'string') {
107
+ const pending = pendingWindowActionRequests.get(msg.requestId);
108
+ if (pending) {
109
+ clearTimeout(pending.timeout);
110
+ pendingWindowActionRequests.delete(msg.requestId);
111
+ if (typeof msg.error === 'string' && msg.error.length > 0) {
112
+ pending.reject(new Error(msg.error));
113
+ }
114
+ else {
115
+ pending.resolve(msg.result);
116
+ }
117
+ }
118
+ }
119
+ }
120
+ else if (msg.type === 'window:ai_command_result') {
121
+ if (typeof msg.requestId === 'string') {
122
+ const pending = pendingAiCommandRequests.get(msg.requestId);
123
+ if (pending) {
124
+ clearTimeout(pending.timeout);
125
+ pendingAiCommandRequests.delete(msg.requestId);
126
+ pending.resolve({
127
+ ok: msg.ok === true,
128
+ windowId: typeof msg.windowId === 'string' ? msg.windowId : undefined,
129
+ error: typeof msg.error === 'string' ? msg.error : undefined,
130
+ });
131
+ }
132
+ }
133
+ }
134
+ else if (msg.type === 'ai:sessions:list') {
135
+ sendAiEvent({
136
+ type: 'sessions_sync',
137
+ sessionId: piSessionService.getSessionId(),
138
+ sessions: await piSessionService.listSessions(),
139
+ });
140
+ }
141
+ else if (msg.type === 'ai:sessions:create') {
142
+ if (activeAiRequestId) {
143
+ sendAiEvent({
144
+ type: 'error',
145
+ message: 'Cannot create a new session while the AI is responding.',
146
+ });
147
+ return;
148
+ }
149
+ await piSessionService.createNewSession();
150
+ sendAiEvent({
151
+ type: 'history_sync',
152
+ sessionId: piSessionService.getSessionId(),
153
+ messages: piSessionService.getHistory(),
154
+ });
155
+ sendAiEvent({
156
+ type: 'sessions_sync',
157
+ sessionId: piSessionService.getSessionId(),
158
+ sessions: await piSessionService.listSessions(),
159
+ });
160
+ }
161
+ else if (msg.type === 'ai:sessions:switch') {
162
+ const sessionId = typeof msg.sessionId === 'string' ? msg.sessionId : '';
163
+ if (activeAiRequestId) {
164
+ sendAiEvent({
165
+ type: 'error',
166
+ message: 'Wait for the current AI response to finish before switching sessions.',
167
+ });
168
+ return;
169
+ }
170
+ if (!sessionId) {
171
+ sendAiEvent({
172
+ type: 'error',
173
+ message: 'A session ID is required to switch sessions.',
174
+ });
175
+ return;
176
+ }
177
+ const switched = await piSessionService.switchSession(sessionId);
178
+ if (!switched) {
179
+ sendAiEvent({
180
+ type: 'error',
181
+ message: 'The selected session could not be found.',
182
+ });
183
+ return;
184
+ }
185
+ sendAiEvent({
186
+ type: 'history_sync',
187
+ sessionId: piSessionService.getSessionId(),
188
+ messages: piSessionService.getHistory(),
189
+ });
190
+ sendAiEvent({
191
+ type: 'sessions_sync',
192
+ sessionId: piSessionService.getSessionId(),
193
+ sessions: await piSessionService.listSessions(),
194
+ });
195
+ }
196
+ else if (msg.type === 'ai:sessions:rename') {
197
+ const title = typeof msg.title === 'string' ? msg.title.trim() : '';
198
+ if (activeAiRequestId) {
199
+ sendAiEvent({
200
+ type: 'error',
201
+ message: 'Wait for the current AI response to finish before renaming sessions.',
202
+ });
203
+ return;
204
+ }
205
+ if (!title) {
206
+ sendAiEvent({
207
+ type: 'error',
208
+ message: 'A session title is required.',
209
+ });
210
+ return;
211
+ }
212
+ await piSessionService.renameCurrentSession(title);
213
+ sendAiEvent({
214
+ type: 'sessions_sync',
215
+ sessionId: piSessionService.getSessionId(),
216
+ sessions: await piSessionService.listSessions(),
217
+ });
218
+ }
219
+ else if (msg.type === 'ai:cancel') {
220
+ const requestId = typeof msg.requestId === 'string' ? msg.requestId : '';
221
+ if (!activeAiRequestId) {
222
+ sendAiEvent({
223
+ type: 'error',
224
+ requestId,
225
+ message: 'No AI request is currently running.',
226
+ });
227
+ return;
228
+ }
229
+ if (!requestId || requestId !== activeAiRequestId) {
230
+ sendAiEvent({
231
+ type: 'error',
232
+ requestId,
233
+ message: 'Only the active AI request can be cancelled.',
234
+ });
235
+ return;
236
+ }
237
+ if (cancelledAiRequestIds.has(requestId)) {
238
+ return;
239
+ }
240
+ cancelledAiRequestIds.add(requestId);
241
+ try {
242
+ await piSessionService.abort();
243
+ }
244
+ catch (err) {
245
+ cancelledAiRequestIds.delete(requestId);
246
+ sendAiEvent({
247
+ type: 'error',
248
+ requestId,
249
+ message: err.message,
250
+ });
251
+ }
252
+ }
253
+ else if (msg.type === 'ai:prompt') {
254
+ const requestId = typeof msg.requestId === 'string' ? msg.requestId : `ai-${Date.now()}`;
255
+ const text = typeof msg.text === 'string' ? msg.text.trim() : '';
256
+ const source = msg.source === 'voice' ? 'voice' : 'text';
257
+ const provider = typeof msg.provider === 'string' ? msg.provider : undefined;
258
+ if (!text) {
259
+ sendAiEvent({
260
+ type: 'error',
261
+ requestId,
262
+ message: 'Prompt cannot be empty.',
263
+ });
264
+ return;
265
+ }
266
+ if (activeAiRequestId) {
267
+ sendAiEvent({
268
+ type: 'error',
269
+ requestId,
270
+ message: 'Another AI request is already running. Wait for it to finish.',
271
+ });
272
+ return;
273
+ }
274
+ activeAiRequestId = requestId;
275
+ try {
276
+ await piSessionService.prompt({
277
+ text,
278
+ source,
279
+ provider,
280
+ }, {
281
+ onEvent: (event) => sendAiEvent({
282
+ requestId,
283
+ ...event,
284
+ }),
285
+ });
286
+ if (cancelledAiRequestIds.has(requestId)) {
287
+ sendAiEvent({
288
+ type: 'message_end',
289
+ requestId,
290
+ cancelled: true,
291
+ });
292
+ return;
293
+ }
294
+ sendAiEvent({
295
+ type: 'history_sync',
296
+ sessionId: piSessionService.getSessionId(),
297
+ messages: piSessionService.getHistory(),
298
+ });
299
+ sendAiEvent({
300
+ type: 'sessions_sync',
301
+ sessionId: piSessionService.getSessionId(),
302
+ sessions: await piSessionService.listSessions(),
303
+ });
304
+ }
305
+ catch (err) {
306
+ if (cancelledAiRequestIds.has(requestId)) {
307
+ sendAiEvent({
308
+ type: 'message_end',
309
+ requestId,
310
+ cancelled: true,
311
+ });
312
+ return;
313
+ }
314
+ sendAiEvent({
315
+ type: 'error',
316
+ requestId,
317
+ message: err.message,
318
+ });
319
+ }
320
+ finally {
321
+ cancelledAiRequestIds.delete(requestId);
322
+ if (activeAiRequestId === requestId) {
323
+ activeAiRequestId = null;
324
+ }
325
+ }
326
+ }
327
+ }
328
+ catch {
329
+ // Ignore malformed messages
330
+ }
331
+ });
332
+ });
333
+ }
334
+ //# sourceMappingURL=ws-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-routes.js","sourceRoot":"","sources":["../../src/server/ws-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ToolDefinition } from '@mariozechner/pi-coding-agent';
2
+ import type { WindowManagerService } from '../window-manager.js';
3
+ interface ActionToolOptions {
4
+ windowManager: WindowManagerService;
5
+ invokeAction: (windowId: string, actionName: string, actionParams?: Record<string, unknown>) => Promise<unknown>;
6
+ }
7
+ export declare function createActionTool(options: ActionToolOptions): ToolDefinition;
8
+ export {};
9
+ //# sourceMappingURL=action-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-tool.d.ts","sourceRoot":"","sources":["../../../src/services/ai/action-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAoB9D,UAAU,iBAAiB;IACzB,aAAa,EAAE,oBAAoB,CAAC;IACpC,YAAY,EAAE,CACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACnC,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAiD3E"}
@@ -0,0 +1,51 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ const actionSchema = Type.Object({
3
+ name: Type.String({ description: 'The action name to invoke (from the Desktop Context block)' }),
4
+ params: Type.Optional(Type.Record(Type.String(), Type.Unknown(), {
5
+ description: 'JSON parameters to pass to the action handler',
6
+ })),
7
+ windowId: Type.Optional(Type.String({ description: 'Target window ID. Defaults to the focused window.' })),
8
+ });
9
+ export function createActionTool(options) {
10
+ const { windowManager, invokeAction } = options;
11
+ return {
12
+ name: 'action',
13
+ label: 'Invoke Action',
14
+ description: 'Invoke a MiniApp action by name with JSON parameters. Available actions and their parameter schemas are listed in the [Desktop Context] block of each user message.',
15
+ promptSnippet: 'Invoke a MiniApp action on a DeskTalk window. See [Desktop Context] for available actions.',
16
+ promptGuidelines: [
17
+ 'Read the [Desktop Context] block in the user message to see available actions and their params.',
18
+ 'Provide all required params as a JSON object.',
19
+ 'If windowId is omitted, the action runs on the focused window.',
20
+ 'Call `read_manual` with `page: "desktop/actions"` when you need the full action-invocation workflow.',
21
+ ],
22
+ parameters: actionSchema,
23
+ async execute(_toolCallId, params) {
24
+ const input = params;
25
+ // Resolve target window — default to focused
26
+ const targetWindowId = input.windowId ?? windowManager.getFocusedWindow()?.id;
27
+ if (!targetWindowId) {
28
+ throw new Error('No target window: provide windowId or ensure a window is focused.');
29
+ }
30
+ // Validate that the action exists on the target window
31
+ const actions = windowManager.getWindowActions(targetWindowId);
32
+ const actionDef = actions.find((a) => a.name === input.name);
33
+ if (!actionDef) {
34
+ const available = actions.map((a) => a.name).join(', ') || 'none';
35
+ throw new Error(`Action "${input.name}" not found on window ${targetWindowId}. Available: ${available}`);
36
+ }
37
+ const result = await invokeAction(targetWindowId, input.name, input.params);
38
+ const payload = {
39
+ ok: true,
40
+ windowId: targetWindowId,
41
+ action: input.name,
42
+ result,
43
+ };
44
+ return {
45
+ content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],
46
+ details: payload,
47
+ };
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=action-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-tool.js","sourceRoot":"","sources":["../../../src/services/ai/action-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAAC;IAChG,MAAM,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE;QACzC,WAAW,EAAE,+CAA+C;KAC7D,CAAC,CACH;IACD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC,CAClF;CACF,CAAC,CAAC;AAiBH,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACzD,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAEhD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,qKAAqK;QACvK,aAAa,EACX,4FAA4F;QAC9F,gBAAgB,EAAE;YAChB,iGAAiG;YACjG,+CAA+C;YAC/C,gEAAgE;YAChE,sGAAsG;SACvG;QACD,UAAU,EAAE,YAAY;QACxB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM;YAC/B,MAAM,KAAK,GAAG,MAAsB,CAAC;YAErC,6CAA6C;YAC7C,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC,gBAAgB,EAAE,EAAE,EAAE,CAAC;YAC9E,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;YACvF,CAAC;YAED,uDAAuD;YACvD,MAAM,OAAO,GAAG,aAAa,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;YAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7D,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;gBAClE,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,CAAC,IAAI,yBAAyB,cAAc,gBAAgB,SAAS,EAAE,CACxF,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAC5E,MAAM,OAAO,GAAG;gBACd,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE,cAAc;gBACxB,MAAM,EAAE,KAAK,CAAC,IAAI;gBAClB,MAAM;aACP,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;gBACnE,OAAO,EAAE,OAAO;aACjB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ToolDefinition } from '@mariozechner/pi-coding-agent';
2
+ import type { MiniAppManifest } from '@desktalk/sdk';
3
+ import type { WindowManagerService } from '../window-manager.js';
4
+ import type { SendAiCommand } from './window-tools.js';
5
+ interface AppToolOptions {
6
+ windowManager: WindowManagerService;
7
+ getMiniApps: () => MiniAppManifest[];
8
+ activateMiniApp: (miniAppId: string) => void;
9
+ deactivateMiniApp: (miniAppId: string) => void;
10
+ isActivated: (miniAppId: string) => boolean;
11
+ sendAiCommand: SendAiCommand;
12
+ }
13
+ export declare function createAppControlTool(options: AppToolOptions): ToolDefinition;
14
+ export {};
15
+ //# sourceMappingURL=app-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-tools.d.ts","sourceRoot":"","sources":["../../../src/services/ai/app-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAYvD,UAAU,cAAc;IACtB,aAAa,EAAE,oBAAoB,CAAC;IACpC,WAAW,EAAE,MAAM,eAAe,EAAE,CAAC;IACrC,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,aAAa,EAAE,aAAa,CAAC;CAC9B;AAaD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAmI5E"}