nastechai-desktop 18.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (546) hide show
  1. package/.prettierrc +11 -0
  2. package/DESIGN.md +167 -0
  3. package/README.md +141 -0
  4. package/assets/icon.icns +0 -0
  5. package/assets/icon.ico +0 -0
  6. package/assets/icon.png +0 -0
  7. package/components.json +21 -0
  8. package/electron/backend-env.cjs +112 -0
  9. package/electron/backend-env.test.cjs +111 -0
  10. package/electron/backend-probes.cjs +106 -0
  11. package/electron/backend-probes.test.cjs +82 -0
  12. package/electron/backend-ready.cjs +66 -0
  13. package/electron/bootstrap-platform.cjs +91 -0
  14. package/electron/bootstrap-platform.test.cjs +111 -0
  15. package/electron/bootstrap-runner.cjs +720 -0
  16. package/electron/bootstrap-runner.test.cjs +138 -0
  17. package/electron/connection-config.cjs +254 -0
  18. package/electron/connection-config.test.cjs +329 -0
  19. package/electron/dashboard-token.cjs +99 -0
  20. package/electron/dashboard-token.test.cjs +142 -0
  21. package/electron/desktop-uninstall.cjs +232 -0
  22. package/electron/desktop-uninstall.test.cjs +246 -0
  23. package/electron/entitlements.mac.inherit.plist +14 -0
  24. package/electron/entitlements.mac.plist +14 -0
  25. package/electron/fs-read-dir.cjs +109 -0
  26. package/electron/fs-read-dir.test.cjs +364 -0
  27. package/electron/gateway-ws-probe.cjs +188 -0
  28. package/electron/gateway-ws-probe.test.cjs +122 -0
  29. package/electron/git-root.cjs +54 -0
  30. package/electron/git-root.test.cjs +40 -0
  31. package/electron/git-worktrees.cjs +174 -0
  32. package/electron/hardening.cjs +184 -0
  33. package/electron/hardening.test.cjs +116 -0
  34. package/electron/main.cjs +5762 -0
  35. package/electron/oauth-net-request.cjs +20 -0
  36. package/electron/oauth-net-request.test.cjs +34 -0
  37. package/electron/preload.cjs +135 -0
  38. package/electron/session-windows.cjs +99 -0
  39. package/electron/session-windows.test.cjs +177 -0
  40. package/electron/update-remote.cjs +56 -0
  41. package/electron/update-remote.test.cjs +78 -0
  42. package/electron/vscode-marketplace.cjs +331 -0
  43. package/electron/vscode-marketplace.test.cjs +113 -0
  44. package/electron/windows-child-process.test.cjs +57 -0
  45. package/electron/windows-user-env.cjs +76 -0
  46. package/electron/windows-user-env.test.cjs +90 -0
  47. package/electron/workspace-cwd.cjs +38 -0
  48. package/electron/workspace-cwd.test.cjs +45 -0
  49. package/eslint.config.mjs +122 -0
  50. package/index.html +17 -0
  51. package/package.json +254 -0
  52. package/pr-assets/session-source-folders.png +0 -0
  53. package/preview-demo.html +65 -0
  54. package/public/apple-touch-icon.png +0 -0
  55. package/public/ds-assets/filler-bg0.jpg +0 -0
  56. package/public/nastech-frames/nastech-frame-0.png +0 -0
  57. package/public/nastech-frames/nastech-frame-1.png +0 -0
  58. package/public/nastech-frames/nastech-frame-2.png +0 -0
  59. package/public/nastech-frames/nastech-frame-3.png +0 -0
  60. package/public/nastech-frames/nastech-frame-4.png +0 -0
  61. package/public/nastech-frames/nastech-frame-5.png +0 -0
  62. package/public/nastech-frames/nastech-frame-6.png +0 -0
  63. package/public/nastech-frames/nastech-frame-7.png +0 -0
  64. package/public/nastech-girl.jpg +0 -0
  65. package/public/nastech-sprite.png +0 -0
  66. package/public/nastech.png +0 -0
  67. package/scripts/after-pack.cjs +41 -0
  68. package/scripts/assert-dist-built.cjs +70 -0
  69. package/scripts/assert-dist-built.test.cjs +84 -0
  70. package/scripts/assert-root-install.cjs +13 -0
  71. package/scripts/before-build.cjs +11 -0
  72. package/scripts/before-pack.cjs +78 -0
  73. package/scripts/before-pack.test.cjs +53 -0
  74. package/scripts/click-session.mjs +51 -0
  75. package/scripts/dev-no-hmr.mjs +22 -0
  76. package/scripts/diag-jump.mjs +115 -0
  77. package/scripts/diag-scroll-reset.mjs +229 -0
  78. package/scripts/eval.mjs +21 -0
  79. package/scripts/leak-typing.mjs +222 -0
  80. package/scripts/measure-jump.mjs +108 -0
  81. package/scripts/measure-latency.mjs +184 -0
  82. package/scripts/measure-real-stream.mjs +252 -0
  83. package/scripts/measure-submit.mjs +179 -0
  84. package/scripts/measure-synthetic-stream.mjs +322 -0
  85. package/scripts/notarize-artifact.cjs +77 -0
  86. package/scripts/notarize.cjs +100 -0
  87. package/scripts/patch-electron-builder-mac-binary.cjs +59 -0
  88. package/scripts/probe-renderer.mjs +38 -0
  89. package/scripts/probe-thread.mjs +40 -0
  90. package/scripts/profile-long-stream.mjs +191 -0
  91. package/scripts/profile-real-stream.mjs +137 -0
  92. package/scripts/profile-synth-stream.mjs +103 -0
  93. package/scripts/profile-typing-lag.md +381 -0
  94. package/scripts/profile-typing.mjs +260 -0
  95. package/scripts/reload-renderer.mjs +25 -0
  96. package/scripts/reload.mjs +36 -0
  97. package/scripts/set-exe-identity.cjs +94 -0
  98. package/scripts/stage-native-deps.cjs +159 -0
  99. package/scripts/test-desktop.mjs +425 -0
  100. package/scripts/write-build-stamp.cjs +126 -0
  101. package/src/app/agents/index.tsx +398 -0
  102. package/src/app/artifacts/index.test.ts +62 -0
  103. package/src/app/artifacts/index.tsx +906 -0
  104. package/src/app/chat/chat-drop-overlay.tsx +48 -0
  105. package/src/app/chat/chat-swap-overlay.tsx +47 -0
  106. package/src/app/chat/composer/attachments.tsx +114 -0
  107. package/src/app/chat/composer/completion-drawer.tsx +63 -0
  108. package/src/app/chat/composer/context-menu.tsx +172 -0
  109. package/src/app/chat/composer/controls.tsx +289 -0
  110. package/src/app/chat/composer/drop-affordance.ts +2 -0
  111. package/src/app/chat/composer/enter-submit-dom-race.test.tsx +218 -0
  112. package/src/app/chat/composer/focus.ts +134 -0
  113. package/src/app/chat/composer/help-hint.tsx +59 -0
  114. package/src/app/chat/composer/hooks/use-at-completions.ts +141 -0
  115. package/src/app/chat/composer/hooks/use-live-completion-adapter.ts +119 -0
  116. package/src/app/chat/composer/hooks/use-mic-recorder.ts +291 -0
  117. package/src/app/chat/composer/hooks/use-slash-completions.ts +114 -0
  118. package/src/app/chat/composer/hooks/use-voice-conversation.ts +390 -0
  119. package/src/app/chat/composer/hooks/use-voice-recorder.ts +116 -0
  120. package/src/app/chat/composer/ime-composition-dom-repro.test.tsx +108 -0
  121. package/src/app/chat/composer/index.tsx +1611 -0
  122. package/src/app/chat/composer/inline-refs.ts +138 -0
  123. package/src/app/chat/composer/model-pill.tsx +86 -0
  124. package/src/app/chat/composer/queue-panel.tsx +130 -0
  125. package/src/app/chat/composer/rich-editor.test.ts +18 -0
  126. package/src/app/chat/composer/rich-editor.ts +165 -0
  127. package/src/app/chat/composer/skin-slash-popover.tsx +61 -0
  128. package/src/app/chat/composer/slash-nav-dom-repro.test.tsx +186 -0
  129. package/src/app/chat/composer/status-stack/index.tsx +202 -0
  130. package/src/app/chat/composer/status-stack/status-row.tsx +155 -0
  131. package/src/app/chat/composer/text-utils.test.ts +77 -0
  132. package/src/app/chat/composer/text-utils.ts +107 -0
  133. package/src/app/chat/composer/trigger-popover.test.tsx +42 -0
  134. package/src/app/chat/composer/trigger-popover.tsx +116 -0
  135. package/src/app/chat/composer/types.ts +64 -0
  136. package/src/app/chat/composer/url-dialog.tsx +82 -0
  137. package/src/app/chat/composer/voice-activity.tsx +252 -0
  138. package/src/app/chat/hooks/use-composer-actions.test.ts +57 -0
  139. package/src/app/chat/hooks/use-composer-actions.ts +525 -0
  140. package/src/app/chat/hooks/use-file-drop-zone.ts +118 -0
  141. package/src/app/chat/index.tsx +390 -0
  142. package/src/app/chat/perf-probe.tsx +269 -0
  143. package/src/app/chat/right-rail/index.ts +1 -0
  144. package/src/app/chat/right-rail/preview-console-state.ts +82 -0
  145. package/src/app/chat/right-rail/preview-console.tsx +290 -0
  146. package/src/app/chat/right-rail/preview-file.tsx +559 -0
  147. package/src/app/chat/right-rail/preview-pane.test.tsx +43 -0
  148. package/src/app/chat/right-rail/preview-pane.tsx +657 -0
  149. package/src/app/chat/right-rail/preview.tsx +171 -0
  150. package/src/app/chat/scroll-to-bottom-button.test.tsx +67 -0
  151. package/src/app/chat/scroll-to-bottom-button.tsx +74 -0
  152. package/src/app/chat/sidebar/cron-jobs-section.tsx +325 -0
  153. package/src/app/chat/sidebar/index.tsx +1219 -0
  154. package/src/app/chat/sidebar/load-more-row.tsx +30 -0
  155. package/src/app/chat/sidebar/order.test.ts +21 -0
  156. package/src/app/chat/sidebar/order.ts +17 -0
  157. package/src/app/chat/sidebar/profile-switcher.tsx +516 -0
  158. package/src/app/chat/sidebar/session-actions-menu.tsx +264 -0
  159. package/src/app/chat/sidebar/session-row.tsx +257 -0
  160. package/src/app/chat/sidebar/virtual-session-list.tsx +154 -0
  161. package/src/app/chat/sidebar/workspace-groups.test.ts +149 -0
  162. package/src/app/chat/sidebar/workspace-groups.ts +326 -0
  163. package/src/app/chat/thread-loading.test.ts +34 -0
  164. package/src/app/chat/thread-loading.ts +26 -0
  165. package/src/app/command-center/index.tsx +654 -0
  166. package/src/app/command-palette/index.tsx +513 -0
  167. package/src/app/command-palette/marketplace-theme-page.tsx +157 -0
  168. package/src/app/cron/index.tsx +942 -0
  169. package/src/app/cron/job-state.ts +29 -0
  170. package/src/app/desktop-controller.tsx +938 -0
  171. package/src/app/floating-hud.ts +22 -0
  172. package/src/app/gateway/hooks/use-gateway-boot.test.tsx +265 -0
  173. package/src/app/gateway/hooks/use-gateway-boot.ts +387 -0
  174. package/src/app/gateway/hooks/use-gateway-request.ts +138 -0
  175. package/src/app/hooks/use-keybinds.ts +186 -0
  176. package/src/app/hooks/use-refresh-hotkey.ts +45 -0
  177. package/src/app/hooks/use-route-enum-param.ts +38 -0
  178. package/src/app/index.tsx +1 -0
  179. package/src/app/layout-constants.ts +13 -0
  180. package/src/app/messaging/index.tsx +648 -0
  181. package/src/app/messaging/platform-icon.tsx +93 -0
  182. package/src/app/model-picker-overlay.tsx +42 -0
  183. package/src/app/model-visibility-overlay.tsx +31 -0
  184. package/src/app/overlays/overlay-chrome.tsx +66 -0
  185. package/src/app/overlays/overlay-search-input.tsx +33 -0
  186. package/src/app/overlays/overlay-split-layout.tsx +130 -0
  187. package/src/app/overlays/overlay-view.tsx +91 -0
  188. package/src/app/page-search-shell.tsx +75 -0
  189. package/src/app/profiles/create-profile-dialog.tsx +154 -0
  190. package/src/app/profiles/delete-profile-dialog.tsx +65 -0
  191. package/src/app/profiles/index.tsx +671 -0
  192. package/src/app/profiles/rename-profile-dialog.tsx +125 -0
  193. package/src/app/right-sidebar/files/dnd-manager.ts +27 -0
  194. package/src/app/right-sidebar/files/ipc.test.ts +100 -0
  195. package/src/app/right-sidebar/files/ipc.ts +161 -0
  196. package/src/app/right-sidebar/files/remote-picker.tsx +177 -0
  197. package/src/app/right-sidebar/files/tree.tsx +224 -0
  198. package/src/app/right-sidebar/files/use-project-tree.test.ts +190 -0
  199. package/src/app/right-sidebar/files/use-project-tree.ts +268 -0
  200. package/src/app/right-sidebar/index.test.tsx +75 -0
  201. package/src/app/right-sidebar/index.tsx +395 -0
  202. package/src/app/right-sidebar/store.ts +15 -0
  203. package/src/app/right-sidebar/terminal/buffer.ts +65 -0
  204. package/src/app/right-sidebar/terminal/index.tsx +98 -0
  205. package/src/app/right-sidebar/terminal/persistent.tsx +122 -0
  206. package/src/app/right-sidebar/terminal/selection.ts +75 -0
  207. package/src/app/right-sidebar/terminal/use-terminal-session.ts +504 -0
  208. package/src/app/routes.ts +88 -0
  209. package/src/app/session/hooks/use-context-suggestions.ts +58 -0
  210. package/src/app/session/hooks/use-cwd-actions.ts +109 -0
  211. package/src/app/session/hooks/use-message-stream.ts +957 -0
  212. package/src/app/session/hooks/use-model-controls.test.tsx +198 -0
  213. package/src/app/session/hooks/use-model-controls.ts +106 -0
  214. package/src/app/session/hooks/use-nastech-config.ts +74 -0
  215. package/src/app/session/hooks/use-preview-routing.test.tsx +168 -0
  216. package/src/app/session/hooks/use-preview-routing.ts +223 -0
  217. package/src/app/session/hooks/use-prompt-actions.test.tsx +316 -0
  218. package/src/app/session/hooks/use-prompt-actions.ts +1030 -0
  219. package/src/app/session/hooks/use-route-resume.test.tsx +136 -0
  220. package/src/app/session/hooks/use-route-resume.ts +115 -0
  221. package/src/app/session/hooks/use-session-actions.test.tsx +119 -0
  222. package/src/app/session/hooks/use-session-actions.ts +885 -0
  223. package/src/app/session/hooks/use-session-state-cache.test.tsx +118 -0
  224. package/src/app/session/hooks/use-session-state-cache.ts +191 -0
  225. package/src/app/session-picker-overlay.tsx +32 -0
  226. package/src/app/session-switcher.tsx +107 -0
  227. package/src/app/settings/about-settings.tsx +173 -0
  228. package/src/app/settings/appearance-settings.tsx +162 -0
  229. package/src/app/settings/config-settings.tsx +384 -0
  230. package/src/app/settings/constants.ts +545 -0
  231. package/src/app/settings/credential-key-ui.tsx +373 -0
  232. package/src/app/settings/env-credentials.tsx +198 -0
  233. package/src/app/settings/env-var-actions-menu.tsx +136 -0
  234. package/src/app/settings/field-copy.ts +56 -0
  235. package/src/app/settings/gateway-settings.tsx +620 -0
  236. package/src/app/settings/helpers.test.ts +138 -0
  237. package/src/app/settings/helpers.ts +151 -0
  238. package/src/app/settings/index.tsx +237 -0
  239. package/src/app/settings/keys-settings.tsx +96 -0
  240. package/src/app/settings/mcp-settings.tsx +271 -0
  241. package/src/app/settings/model-settings.test.tsx +157 -0
  242. package/src/app/settings/model-settings.tsx +559 -0
  243. package/src/app/settings/notifications-settings.tsx +150 -0
  244. package/src/app/settings/primitives.tsx +115 -0
  245. package/src/app/settings/providers-settings.test.tsx +100 -0
  246. package/src/app/settings/providers-settings.tsx +258 -0
  247. package/src/app/settings/sessions-settings.tsx +276 -0
  248. package/src/app/settings/toolset-config-panel.test.tsx +289 -0
  249. package/src/app/settings/toolset-config-panel.tsx +449 -0
  250. package/src/app/settings/types.ts +42 -0
  251. package/src/app/settings/uninstall-section.tsx +185 -0
  252. package/src/app/settings/use-deep-link-highlight.ts +60 -0
  253. package/src/app/shell/app-shell.tsx +167 -0
  254. package/src/app/shell/gateway-menu-panel.tsx +150 -0
  255. package/src/app/shell/hooks/use-overlay-routing.ts +71 -0
  256. package/src/app/shell/hooks/use-status-snapshot.ts +57 -0
  257. package/src/app/shell/hooks/use-statusbar-items.tsx +403 -0
  258. package/src/app/shell/keybind-panel.tsx +220 -0
  259. package/src/app/shell/model-edit-submenu.test.tsx +84 -0
  260. package/src/app/shell/model-edit-submenu.tsx +245 -0
  261. package/src/app/shell/model-menu-panel.tsx +295 -0
  262. package/src/app/shell/sidebar-label.tsx +22 -0
  263. package/src/app/shell/statusbar-controls.tsx +185 -0
  264. package/src/app/shell/titlebar-controls.tsx +244 -0
  265. package/src/app/shell/titlebar.test.ts +26 -0
  266. package/src/app/shell/titlebar.ts +45 -0
  267. package/src/app/shell/use-group-registry.ts +39 -0
  268. package/src/app/skills/index.test.tsx +103 -0
  269. package/src/app/skills/index.tsx +371 -0
  270. package/src/app/types.ts +99 -0
  271. package/src/app/updates-overlay.tsx +369 -0
  272. package/src/components/Backdrop.tsx +114 -0
  273. package/src/components/assistant-ui/ansi-text.tsx +34 -0
  274. package/src/components/assistant-ui/clarify-tool.tsx +281 -0
  275. package/src/components/assistant-ui/directive-text.test.ts +39 -0
  276. package/src/components/assistant-ui/directive-text.tsx +389 -0
  277. package/src/components/assistant-ui/markdown-text.test.ts +204 -0
  278. package/src/components/assistant-ui/markdown-text.tsx +497 -0
  279. package/src/components/assistant-ui/message-render-boundary.test.tsx +80 -0
  280. package/src/components/assistant-ui/message-render-boundary.tsx +48 -0
  281. package/src/components/assistant-ui/streaming.test.tsx +739 -0
  282. package/src/components/assistant-ui/thread-list.tsx +307 -0
  283. package/src/components/assistant-ui/thread-virtualizer.tsx +512 -0
  284. package/src/components/assistant-ui/thread.tsx +1474 -0
  285. package/src/components/assistant-ui/todo-tool.tsx +109 -0
  286. package/src/components/assistant-ui/tool-approval-group.test.tsx +158 -0
  287. package/src/components/assistant-ui/tool-approval.test.tsx +81 -0
  288. package/src/components/assistant-ui/tool-approval.tsx +209 -0
  289. package/src/components/assistant-ui/tool-fallback-model.test.ts +66 -0
  290. package/src/components/assistant-ui/tool-fallback-model.ts +1368 -0
  291. package/src/components/assistant-ui/tool-fallback.tsx +466 -0
  292. package/src/components/assistant-ui/tooltip-icon-button.tsx +33 -0
  293. package/src/components/assistant-ui/user-message-edit.test.tsx +141 -0
  294. package/src/components/assistant-ui/user-message-text.tsx +150 -0
  295. package/src/components/boot-failure-overlay.tsx +246 -0
  296. package/src/components/boot-failure-reauth.test.ts +100 -0
  297. package/src/components/boot-failure-reauth.ts +81 -0
  298. package/src/components/brand-mark.tsx +19 -0
  299. package/src/components/chat/activity-timer-text.tsx +24 -0
  300. package/src/components/chat/activity-timer.test.tsx +43 -0
  301. package/src/components/chat/activity-timer.ts +64 -0
  302. package/src/components/chat/code-card.tsx +78 -0
  303. package/src/components/chat/compact-markdown.tsx +113 -0
  304. package/src/components/chat/composer-dock.ts +31 -0
  305. package/src/components/chat/diff-lines.tsx +54 -0
  306. package/src/components/chat/disclosure-row.tsx +63 -0
  307. package/src/components/chat/generated-image-context.tsx +19 -0
  308. package/src/components/chat/generated-image-result.tsx +174 -0
  309. package/src/components/chat/image-generation-placeholder.tsx +279 -0
  310. package/src/components/chat/intro-copy.jsonl +75 -0
  311. package/src/components/chat/intro.tsx +182 -0
  312. package/src/components/chat/preview-attachment.tsx +125 -0
  313. package/src/components/chat/shiki-highlighter.tsx +107 -0
  314. package/src/components/chat/status-row.tsx +70 -0
  315. package/src/components/chat/status-section.tsx +42 -0
  316. package/src/components/chat/terminal-output.tsx +50 -0
  317. package/src/components/chat/zoomable-image.tsx +177 -0
  318. package/src/components/desktop-install-overlay.tsx +595 -0
  319. package/src/components/desktop-onboarding-overlay.test.tsx +100 -0
  320. package/src/components/desktop-onboarding-overlay.tsx +1286 -0
  321. package/src/components/error-boundary.tsx +77 -0
  322. package/src/components/gateway-connecting-overlay.test.tsx +143 -0
  323. package/src/components/gateway-connecting-overlay.tsx +183 -0
  324. package/src/components/haptics-provider.tsx +19 -0
  325. package/src/components/language-switcher.test.tsx +53 -0
  326. package/src/components/language-switcher.tsx +175 -0
  327. package/src/components/model-picker.tsx +340 -0
  328. package/src/components/model-visibility-dialog.tsx +155 -0
  329. package/src/components/notifications.tsx +196 -0
  330. package/src/components/page-loader.tsx +34 -0
  331. package/src/components/pane-shell/context.ts +14 -0
  332. package/src/components/pane-shell/index.ts +4 -0
  333. package/src/components/pane-shell/pane-shell.test.tsx +333 -0
  334. package/src/components/pane-shell/pane-shell.tsx +330 -0
  335. package/src/components/prompt-overlays.tsx +234 -0
  336. package/src/components/session-picker.tsx +108 -0
  337. package/src/components/status-dot.tsx +26 -0
  338. package/src/components/ui/action-status.tsx +25 -0
  339. package/src/components/ui/alert.tsx +53 -0
  340. package/src/components/ui/badge.tsx +35 -0
  341. package/src/components/ui/braille-spinner.tsx +61 -0
  342. package/src/components/ui/button.tsx +81 -0
  343. package/src/components/ui/checkbox.tsx +27 -0
  344. package/src/components/ui/codicon.tsx +20 -0
  345. package/src/components/ui/command.tsx +111 -0
  346. package/src/components/ui/confirm-dialog.tsx +109 -0
  347. package/src/components/ui/context-menu.tsx +141 -0
  348. package/src/components/ui/control.ts +25 -0
  349. package/src/components/ui/copy-button.test.tsx +36 -0
  350. package/src/components/ui/copy-button.tsx +229 -0
  351. package/src/components/ui/dialog.tsx +152 -0
  352. package/src/components/ui/disclosure-caret.tsx +20 -0
  353. package/src/components/ui/dropdown-menu.tsx +291 -0
  354. package/src/components/ui/error-state.tsx +50 -0
  355. package/src/components/ui/fade-text.tsx +110 -0
  356. package/src/components/ui/glyph-spinner.tsx +63 -0
  357. package/src/components/ui/input.tsx +22 -0
  358. package/src/components/ui/kbd.tsx +37 -0
  359. package/src/components/ui/loader.tsx +558 -0
  360. package/src/components/ui/log-view.tsx +17 -0
  361. package/src/components/ui/pagination.tsx +114 -0
  362. package/src/components/ui/popover.tsx +44 -0
  363. package/src/components/ui/scroll-area.tsx +43 -0
  364. package/src/components/ui/search-field.tsx +80 -0
  365. package/src/components/ui/segmented-control.tsx +51 -0
  366. package/src/components/ui/select.tsx +92 -0
  367. package/src/components/ui/separator.tsx +26 -0
  368. package/src/components/ui/sheet.tsx +116 -0
  369. package/src/components/ui/sidebar.tsx +674 -0
  370. package/src/components/ui/skeleton.tsx +7 -0
  371. package/src/components/ui/switch.tsx +49 -0
  372. package/src/components/ui/tabs.tsx +36 -0
  373. package/src/components/ui/text-tab.tsx +43 -0
  374. package/src/components/ui/textarea.tsx +11 -0
  375. package/src/components/ui/tool-icon.tsx +65 -0
  376. package/src/components/ui/tooltip.tsx +69 -0
  377. package/src/fonts/JetBrainsMono-Bold.woff2 +0 -0
  378. package/src/fonts/JetBrainsMono-Italic.woff2 +0 -0
  379. package/src/fonts/JetBrainsMono-Regular.woff2 +0 -0
  380. package/src/global.d.ts +457 -0
  381. package/src/hooks/use-image-download.ts +85 -0
  382. package/src/hooks/use-media-query.ts +24 -0
  383. package/src/hooks/use-mobile.ts +3 -0
  384. package/src/hooks/use-resize-observer.ts +38 -0
  385. package/src/hooks/use-worktree-info.ts +68 -0
  386. package/src/i18n/catalog.ts +12 -0
  387. package/src/i18n/context.test.tsx +232 -0
  388. package/src/i18n/context.tsx +183 -0
  389. package/src/i18n/define-locale.ts +41 -0
  390. package/src/i18n/en.ts +1779 -0
  391. package/src/i18n/index.ts +20 -0
  392. package/src/i18n/ja.ts +1890 -0
  393. package/src/i18n/languages.test.ts +43 -0
  394. package/src/i18n/languages.ts +86 -0
  395. package/src/i18n/runtime.test.ts +75 -0
  396. package/src/i18n/runtime.ts +53 -0
  397. package/src/i18n/types.ts +1452 -0
  398. package/src/i18n/zh-hant.ts +1849 -0
  399. package/src/i18n/zh.ts +1923 -0
  400. package/src/lib/ansi.test.ts +123 -0
  401. package/src/lib/ansi.ts +175 -0
  402. package/src/lib/chat-messages.test.ts +708 -0
  403. package/src/lib/chat-messages.ts +885 -0
  404. package/src/lib/chat-runtime.test.ts +18 -0
  405. package/src/lib/chat-runtime.ts +335 -0
  406. package/src/lib/clipboard.ts +28 -0
  407. package/src/lib/commit-changelog.test.ts +114 -0
  408. package/src/lib/commit-changelog.ts +177 -0
  409. package/src/lib/completion-sound.ts +519 -0
  410. package/src/lib/desktop-fs.test.ts +116 -0
  411. package/src/lib/desktop-fs.ts +113 -0
  412. package/src/lib/desktop-slash-commands.test.ts +126 -0
  413. package/src/lib/desktop-slash-commands.ts +286 -0
  414. package/src/lib/embedded-images.test.ts +35 -0
  415. package/src/lib/embedded-images.ts +60 -0
  416. package/src/lib/external-link.test.tsx +168 -0
  417. package/src/lib/external-link.tsx +303 -0
  418. package/src/lib/gateway-events.test.ts +27 -0
  419. package/src/lib/gateway-events.ts +49 -0
  420. package/src/lib/gateway-ws-url.test.ts +78 -0
  421. package/src/lib/gateway-ws-url.ts +91 -0
  422. package/src/lib/generated-images.test.ts +97 -0
  423. package/src/lib/generated-images.ts +116 -0
  424. package/src/lib/haptics.ts +129 -0
  425. package/src/lib/icons.ts +203 -0
  426. package/src/lib/incremental-external-store-runtime.ts +188 -0
  427. package/src/lib/katex-memo.ts +260 -0
  428. package/src/lib/keybinds/actions.ts +125 -0
  429. package/src/lib/keybinds/combo.test.ts +86 -0
  430. package/src/lib/keybinds/combo.ts +169 -0
  431. package/src/lib/local-preview.ts +126 -0
  432. package/src/lib/markdown-code.test.ts +23 -0
  433. package/src/lib/markdown-code.ts +195 -0
  434. package/src/lib/markdown-preprocess.ts +386 -0
  435. package/src/lib/media.remote.test.ts +58 -0
  436. package/src/lib/media.ts +111 -0
  437. package/src/lib/model-status-label.test.ts +31 -0
  438. package/src/lib/model-status-label.ts +103 -0
  439. package/src/lib/mutable-ref.ts +6 -0
  440. package/src/lib/preview-targets.test.ts +27 -0
  441. package/src/lib/preview-targets.ts +63 -0
  442. package/src/lib/profile-color.ts +58 -0
  443. package/src/lib/provider-setup-errors.test.ts +26 -0
  444. package/src/lib/provider-setup-errors.ts +12 -0
  445. package/src/lib/query-client.ts +13 -0
  446. package/src/lib/remend-tail.test.ts +105 -0
  447. package/src/lib/remend-tail.ts +108 -0
  448. package/src/lib/runtime-readiness.test.ts +65 -0
  449. package/src/lib/runtime-readiness.ts +147 -0
  450. package/src/lib/session-export.ts +57 -0
  451. package/src/lib/session-search.test.ts +58 -0
  452. package/src/lib/session-search.ts +19 -0
  453. package/src/lib/session-source.ts +62 -0
  454. package/src/lib/speech-text.ts +35 -0
  455. package/src/lib/statusbar.ts +91 -0
  456. package/src/lib/storage.test.ts +25 -0
  457. package/src/lib/storage.ts +107 -0
  458. package/src/lib/todos.test.ts +35 -0
  459. package/src/lib/todos.ts +51 -0
  460. package/src/lib/tool-result-summary.test.ts +106 -0
  461. package/src/lib/tool-result-summary.ts +467 -0
  462. package/src/lib/update-copy.test.ts +38 -0
  463. package/src/lib/update-copy.ts +44 -0
  464. package/src/lib/use-enter-animation.ts +100 -0
  465. package/src/lib/utils.ts +6 -0
  466. package/src/lib/voice-playback.ts +128 -0
  467. package/src/lib/yolo-session.ts +26 -0
  468. package/src/main.tsx +43 -0
  469. package/src/nastech.test.ts +49 -0
  470. package/src/nastech.ts +718 -0
  471. package/src/store/activity.ts +100 -0
  472. package/src/store/boot.ts +91 -0
  473. package/src/store/clarify.test.ts +81 -0
  474. package/src/store/clarify.ts +69 -0
  475. package/src/store/command-palette.ts +20 -0
  476. package/src/store/compaction.test.ts +53 -0
  477. package/src/store/compaction.ts +38 -0
  478. package/src/store/completion-sound.ts +32 -0
  479. package/src/store/composer-input-history.test.ts +147 -0
  480. package/src/store/composer-input-history.ts +158 -0
  481. package/src/store/composer-queue.test.ts +148 -0
  482. package/src/store/composer-queue.ts +239 -0
  483. package/src/store/composer-status.test.ts +99 -0
  484. package/src/store/composer-status.ts +277 -0
  485. package/src/store/composer.test.ts +106 -0
  486. package/src/store/composer.ts +184 -0
  487. package/src/store/cron.ts +19 -0
  488. package/src/store/gateway.ts +290 -0
  489. package/src/store/haptics.ts +17 -0
  490. package/src/store/keybinds.ts +139 -0
  491. package/src/store/layout.ts +176 -0
  492. package/src/store/model-presets.test.ts +51 -0
  493. package/src/store/model-presets.ts +86 -0
  494. package/src/store/model-visibility.test.ts +37 -0
  495. package/src/store/model-visibility.ts +108 -0
  496. package/src/store/native-notifications.test.ts +192 -0
  497. package/src/store/native-notifications.ts +203 -0
  498. package/src/store/notifications.ts +165 -0
  499. package/src/store/onboarding.test.ts +372 -0
  500. package/src/store/onboarding.ts +866 -0
  501. package/src/store/panes.test.ts +146 -0
  502. package/src/store/panes.ts +145 -0
  503. package/src/store/preview.test.ts +135 -0
  504. package/src/store/preview.ts +466 -0
  505. package/src/store/profile.test.ts +89 -0
  506. package/src/store/profile.ts +365 -0
  507. package/src/store/prompts.test.ts +121 -0
  508. package/src/store/prompts.ts +115 -0
  509. package/src/store/session-switcher.test.ts +115 -0
  510. package/src/store/session-switcher.ts +128 -0
  511. package/src/store/session-sync.ts +25 -0
  512. package/src/store/session.test.ts +131 -0
  513. package/src/store/session.ts +255 -0
  514. package/src/store/subagents.test.ts +111 -0
  515. package/src/store/subagents.ts +260 -0
  516. package/src/store/thread-scroll.ts +46 -0
  517. package/src/store/todos.test.ts +47 -0
  518. package/src/store/todos.ts +64 -0
  519. package/src/store/tool-diffs.ts +23 -0
  520. package/src/store/tool-dismiss.ts +45 -0
  521. package/src/store/tool-view.ts +91 -0
  522. package/src/store/translucency.ts +38 -0
  523. package/src/store/updates.test.ts +77 -0
  524. package/src/store/updates.ts +315 -0
  525. package/src/store/voice-playback.ts +24 -0
  526. package/src/store/windows.test.ts +143 -0
  527. package/src/store/windows.ts +77 -0
  528. package/src/styles.css +1235 -0
  529. package/src/themes/color.ts +142 -0
  530. package/src/themes/context.tsx +339 -0
  531. package/src/themes/index.ts +3 -0
  532. package/src/themes/install.test.ts +119 -0
  533. package/src/themes/install.ts +95 -0
  534. package/src/themes/presets.test.ts +33 -0
  535. package/src/themes/presets.ts +293 -0
  536. package/src/themes/profile-theme.test.ts +41 -0
  537. package/src/themes/types.ts +66 -0
  538. package/src/themes/use-skin-command.ts +60 -0
  539. package/src/themes/user-themes.test.ts +63 -0
  540. package/src/themes/user-themes.ts +122 -0
  541. package/src/themes/vscode.test.ts +171 -0
  542. package/src/themes/vscode.ts +343 -0
  543. package/src/types/nastech.ts +646 -0
  544. package/src/vite-env.d.ts +1 -0
  545. package/tsconfig.json +25 -0
  546. package/vite.config.ts +56 -0
package/src/nastech.ts ADDED
@@ -0,0 +1,718 @@
1
+ import { JsonRpcGatewayClient } from '@NASTECH/shared'
2
+
3
+ import type {
4
+ ActionResponse,
5
+ ActionStatusResponse,
6
+ AnalyticsResponse,
7
+ AudioSpeakResponse,
8
+ AudioTranscriptionResponse,
9
+ AuxiliaryModelsResponse,
10
+ ConfigSchemaResponse,
11
+ CronJob,
12
+ CronJobCreatePayload,
13
+ CronJobUpdates,
14
+ ElevenLabsVoicesResponse,
15
+ EnvVarInfo,
16
+ NasTechConfig,
17
+ NasTechConfigRecord,
18
+ LogsResponse,
19
+ MessagingPlatformsResponse,
20
+ MessagingPlatformTestResponse,
21
+ MessagingPlatformUpdate,
22
+ ModelAssignmentRequest,
23
+ ModelAssignmentResponse,
24
+ ModelInfoResponse,
25
+ ModelOptionsResponse,
26
+ OAuthPollResponse,
27
+ OAuthProvidersResponse,
28
+ OAuthStartResponse,
29
+ OAuthSubmitResponse,
30
+ PaginatedSessions,
31
+ ProfileCreatePayload,
32
+ ProfileSetupCommand,
33
+ ProfileSoul,
34
+ ProfilesResponse,
35
+ SessionInfo,
36
+ SessionMessagesResponse,
37
+ SessionSearchResponse,
38
+ SkillInfo,
39
+ StatusResponse,
40
+ ToolsetConfig,
41
+ ToolsetInfo
42
+ } from '@/types/nastech'
43
+
44
+ const DEFAULT_GATEWAY_REQUEST_TIMEOUT_MS = 30_000
45
+ const SESSION_LIST_REQUEST_TIMEOUT_MS = 60_000
46
+
47
+ export type {
48
+ ActionResponse,
49
+ ActionStatusResponse,
50
+ AnalyticsDailyEntry,
51
+ AnalyticsModelEntry,
52
+ AnalyticsResponse,
53
+ AnalyticsSkillEntry,
54
+ AnalyticsSkillsSummary,
55
+ AnalyticsTotals,
56
+ AudioSpeakResponse,
57
+ AudioTranscriptionResponse,
58
+ AuxiliaryModelsResponse,
59
+ ConfigFieldSchema,
60
+ ConfigSchemaResponse,
61
+ CronJob,
62
+ CronJobCreatePayload,
63
+ CronJobSchedule,
64
+ CronJobUpdates,
65
+ ElevenLabsVoice,
66
+ ElevenLabsVoicesResponse,
67
+ EnvVarInfo,
68
+ GatewayReadyPayload,
69
+ NasTechConfig,
70
+ NasTechConfigRecord,
71
+ LogsResponse,
72
+ MessagingEnvVarInfo,
73
+ MessagingHomeChannel,
74
+ MessagingPlatformInfo,
75
+ MessagingPlatformsResponse,
76
+ MessagingPlatformTestResponse,
77
+ MessagingPlatformUpdate,
78
+ ModelAssignmentRequest,
79
+ ModelAssignmentResponse,
80
+ ModelInfoResponse,
81
+ ModelOptionProvider,
82
+ ModelOptionsResponse,
83
+ PaginatedSessions,
84
+ ProfileCreatePayload,
85
+ ProfileInfo,
86
+ ProfileSetupCommand,
87
+ ProfileSoul,
88
+ ProfilesResponse,
89
+ RpcEvent,
90
+ SessionCreateResponse,
91
+ SessionInfo,
92
+ SessionMessage,
93
+ SessionMessagesResponse,
94
+ SessionResumeResponse,
95
+ SessionRuntimeInfo,
96
+ SessionSearchResponse,
97
+ SessionSearchResult,
98
+ SkillInfo,
99
+ StaleAuxAssignment,
100
+ StatusResponse,
101
+ ToolsetConfig,
102
+ ToolsetInfo
103
+ } from '@/types/nastech'
104
+
105
+ export class NasTechGateway extends JsonRpcGatewayClient {
106
+ constructor() {
107
+ super({
108
+ closedErrorMessage: 'NasTech gateway connection closed',
109
+ connectErrorMessage: 'Could not connect to NasTech gateway',
110
+ createRequestId: nextId => nextId,
111
+ notConnectedErrorMessage: 'NasTech gateway is not connected',
112
+ requestTimeoutMs: DEFAULT_GATEWAY_REQUEST_TIMEOUT_MS
113
+ })
114
+ }
115
+ }
116
+
117
+ // Profile that profile-scoped REST settings (config/env/skills/tools/model/…)
118
+ // should target. Mirrors $activeGatewayProfile, pushed in from the store via
119
+ // setApiRequestProfile so this module needs no store import (avoids a cycle).
120
+ // Electron main consumes request.profile to pick which backend *process* serves
121
+ // the call; each pooled backend already has its own NASTECH_HOME, so no backend
122
+ // change is needed. Null → primary, so single-profile users are unaffected.
123
+ let _apiProfile: null | string = null
124
+
125
+ export function setApiRequestProfile(profile: null | string): void {
126
+ _apiProfile = profile || null
127
+ }
128
+
129
+ function profileScoped(): { profile?: string } {
130
+ return _apiProfile ? { profile: _apiProfile } : {}
131
+ }
132
+
133
+ export async function listSessions(
134
+ limit = 40,
135
+ minMessages = 0,
136
+ archived: 'exclude' | 'include' | 'only' = 'exclude',
137
+ order: 'created' | 'recent' = 'recent'
138
+ ): Promise<PaginatedSessions> {
139
+ const result = await window.NASTECHDesktop.api<PaginatedSessions>({
140
+ path: `/api/sessions?limit=${limit}&offset=0&min_messages=${Math.max(0, minMessages)}&archived=${archived}&order=${order}`,
141
+ timeoutMs: SESSION_LIST_REQUEST_TIMEOUT_MS
142
+ })
143
+
144
+ return {
145
+ ...result,
146
+ sessions: result.sessions.slice(0, limit),
147
+ offset: 0
148
+ }
149
+ }
150
+
151
+ // Unified, read-only session list aggregated across ALL profiles. Served by the
152
+ // primary backend straight off each profile's state.db — no per-profile backend
153
+ // is spawned. Single-profile users get the same rows as listSessions(), tagged
154
+ // profile="default".
155
+ // Source scoping lets callers split the unified list into independent slices:
156
+ // recents pass `excludeSources: ['cron']`, the cron-jobs section passes
157
+ // `source: 'cron'`. Without this a burst of (always-newest) cron sessions
158
+ // consumes the whole recents page and starves real conversations.
159
+ export interface SessionSourceFilter {
160
+ source?: string
161
+ excludeSources?: string[]
162
+ }
163
+
164
+ export async function listAllProfileSessions(
165
+ limit = 40,
166
+ minMessages = 0,
167
+ archived: 'exclude' | 'include' | 'only' = 'exclude',
168
+ order: 'created' | 'recent' = 'recent',
169
+ profile: 'all' | (string & {}) = 'all',
170
+ filter: SessionSourceFilter = {}
171
+ ): Promise<PaginatedSessions> {
172
+ const sourceParam = filter.source ? `&source=${encodeURIComponent(filter.source)}` : ''
173
+
174
+ const excludeParam = filter.excludeSources?.length
175
+ ? `&exclude_sources=${encodeURIComponent(filter.excludeSources.join(','))}`
176
+ : ''
177
+
178
+ const result = await window.NASTECHDesktop.api<PaginatedSessions>({
179
+ path:
180
+ `/api/profiles/sessions?limit=${limit}&offset=0&min_messages=${Math.max(0, minMessages)}` +
181
+ `&archived=${archived}&order=${order}&profile=${encodeURIComponent(profile)}${sourceParam}${excludeParam}`,
182
+ timeoutMs: SESSION_LIST_REQUEST_TIMEOUT_MS
183
+ })
184
+
185
+ return {
186
+ ...result,
187
+ sessions: result.sessions.slice(0, limit),
188
+ offset: 0
189
+ }
190
+ }
191
+
192
+ // Mutations take the owning `profile` so Electron routes them to that profile's
193
+ // backend (remote pool or local primary) via request.profile — matching the
194
+ // read path. A remote session's row lives only on its remote host, so a mutation
195
+ // that hit the local primary would no-op or 404. Omit for the current/default.
196
+ export function setSessionArchived(id: string, archived: boolean, profile?: string | null): Promise<{ ok: boolean }> {
197
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
198
+ ...(profile ? { profile } : {}),
199
+ path: `/api/sessions/${encodeURIComponent(id)}`,
200
+ method: 'PATCH',
201
+ body: { archived }
202
+ })
203
+ }
204
+
205
+ export function searchSessions(query: string): Promise<SessionSearchResponse> {
206
+ return window.NASTECHDesktop.api<SessionSearchResponse>({
207
+ path: `/api/sessions/search?q=${encodeURIComponent(query)}`
208
+ })
209
+ }
210
+
211
+ // Reads another profile's transcript. For a remote profile Electron reroutes
212
+ // this GET to the remote backend (which serves its own state.db); for a local
213
+ // profile the primary opens that profile's state.db via ?profile=. Omit for
214
+ // the current/default profile.
215
+ export function getSessionMessages(id: string, profile?: string | null): Promise<SessionMessagesResponse> {
216
+ const suffix = profile ? `?profile=${encodeURIComponent(profile)}` : ''
217
+
218
+ return window.NASTECHDesktop.api<SessionMessagesResponse>({
219
+ path: `/api/sessions/${encodeURIComponent(id)}/messages${suffix}`
220
+ })
221
+ }
222
+
223
+ export function deleteSession(id: string, profile?: string | null): Promise<{ ok: boolean }> {
224
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
225
+ ...(profile ? { profile } : {}),
226
+ path: `/api/sessions/${encodeURIComponent(id)}`,
227
+ method: 'DELETE'
228
+ })
229
+ }
230
+
231
+ export function renameSession(
232
+ id: string,
233
+ title: string,
234
+ profile?: string | null
235
+ ): Promise<{ ok: boolean; title: string }> {
236
+ return window.NASTECHDesktop.api<{ ok: boolean; title: string }>({
237
+ ...(profile ? { profile } : {}),
238
+ path: `/api/sessions/${encodeURIComponent(id)}`,
239
+ method: 'PATCH',
240
+ body: { title, ...(profile ? { profile } : {}) }
241
+ })
242
+ }
243
+
244
+ export function getGlobalModelInfo(): Promise<ModelInfoResponse> {
245
+ return window.NASTECHDesktop.api<ModelInfoResponse>({
246
+ ...profileScoped(),
247
+ path: '/api/model/info'
248
+ })
249
+ }
250
+
251
+ export function getStatus(): Promise<StatusResponse> {
252
+ return window.NASTECHDesktop.api<StatusResponse>({
253
+ path: '/api/status'
254
+ })
255
+ }
256
+
257
+ export function getLogs(params: {
258
+ component?: string
259
+ file?: string
260
+ level?: string
261
+ lines?: number
262
+ }): Promise<LogsResponse> {
263
+ const query = new URLSearchParams()
264
+
265
+ if (params.file) {
266
+ query.set('file', params.file)
267
+ }
268
+
269
+ if (typeof params.lines === 'number') {
270
+ query.set('lines', String(params.lines))
271
+ }
272
+
273
+ if (params.level && params.level !== 'ALL') {
274
+ query.set('level', params.level)
275
+ }
276
+
277
+ if (params.component && params.component !== 'all') {
278
+ query.set('component', params.component)
279
+ }
280
+
281
+ const suffix = query.toString()
282
+
283
+ return window.NASTECHDesktop.api<LogsResponse>({
284
+ ...profileScoped(),
285
+ path: suffix ? `/api/logs?${suffix}` : '/api/logs'
286
+ })
287
+ }
288
+
289
+ export function getNasTechConfig(): Promise<NasTechConfig> {
290
+ return window.NASTECHDesktop.api<NasTechConfig>({
291
+ ...profileScoped(),
292
+ path: '/api/config'
293
+ })
294
+ }
295
+
296
+ export function getNasTechConfigRecord(): Promise<NasTechConfigRecord> {
297
+ return window.NASTECHDesktop.api<NasTechConfigRecord>({
298
+ ...profileScoped(),
299
+ path: '/api/config'
300
+ })
301
+ }
302
+
303
+ export function getNasTechConfigDefaults(): Promise<NasTechConfigRecord> {
304
+ return window.NASTECHDesktop.api<NasTechConfigRecord>({
305
+ ...profileScoped(),
306
+ path: '/api/config/defaults'
307
+ })
308
+ }
309
+
310
+ export function getNasTechConfigSchema(): Promise<ConfigSchemaResponse> {
311
+ return window.NASTECHDesktop.api<ConfigSchemaResponse>({
312
+ ...profileScoped(),
313
+ path: '/api/config/schema'
314
+ })
315
+ }
316
+
317
+ export function saveNasTechConfig(config: NasTechConfigRecord): Promise<{ ok: boolean }> {
318
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
319
+ ...profileScoped(),
320
+ path: '/api/config',
321
+ method: 'PUT',
322
+ body: { config }
323
+ })
324
+ }
325
+
326
+ export function getEnvVars(): Promise<Record<string, EnvVarInfo>> {
327
+ return window.NASTECHDesktop.api<Record<string, EnvVarInfo>>({
328
+ ...profileScoped(),
329
+ path: '/api/env'
330
+ })
331
+ }
332
+
333
+ export function setEnvVar(key: string, value: string): Promise<{ ok: boolean }> {
334
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
335
+ ...profileScoped(),
336
+ path: '/api/env',
337
+ method: 'PUT',
338
+ body: { key, value }
339
+ })
340
+ }
341
+
342
+ export function validateProviderCredential(
343
+ key: string,
344
+ value: string
345
+ ): Promise<{ ok: boolean; reachable: boolean; message: string; models?: string[] }> {
346
+ return window.NASTECHDesktop.api<{ ok: boolean; reachable: boolean; message: string; models?: string[] }>({
347
+ ...profileScoped(),
348
+ path: '/api/providers/validate',
349
+ method: 'POST',
350
+ body: { key, value }
351
+ })
352
+ }
353
+
354
+ export function deleteEnvVar(key: string): Promise<{ ok: boolean }> {
355
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
356
+ ...profileScoped(),
357
+ path: '/api/env',
358
+ method: 'DELETE',
359
+ body: { key }
360
+ })
361
+ }
362
+
363
+ export function revealEnvVar(key: string): Promise<{ key: string; value: string }> {
364
+ return window.NASTECHDesktop.api<{ key: string; value: string }>({
365
+ ...profileScoped(),
366
+ path: '/api/env/reveal',
367
+ method: 'POST',
368
+ body: { key }
369
+ })
370
+ }
371
+
372
+ export function listOAuthProviders(): Promise<OAuthProvidersResponse> {
373
+ return window.NASTECHDesktop.api<OAuthProvidersResponse>({
374
+ ...profileScoped(),
375
+ path: '/api/providers/oauth'
376
+ })
377
+ }
378
+
379
+ export function startOAuthLogin(providerId: string): Promise<OAuthStartResponse> {
380
+ return window.NASTECHDesktop.api<OAuthStartResponse>({
381
+ ...profileScoped(),
382
+ path: `/api/providers/oauth/${encodeURIComponent(providerId)}/start`,
383
+ method: 'POST',
384
+ body: {}
385
+ })
386
+ }
387
+
388
+ export function submitOAuthCode(providerId: string, sessionId: string, code: string): Promise<OAuthSubmitResponse> {
389
+ return window.NASTECHDesktop.api<OAuthSubmitResponse>({
390
+ ...profileScoped(),
391
+ path: `/api/providers/oauth/${encodeURIComponent(providerId)}/submit`,
392
+ method: 'POST',
393
+ body: { session_id: sessionId, code }
394
+ })
395
+ }
396
+
397
+ export function pollOAuthSession(providerId: string, sessionId: string): Promise<OAuthPollResponse> {
398
+ return window.NASTECHDesktop.api<OAuthPollResponse>({
399
+ ...profileScoped(),
400
+ path: `/api/providers/oauth/${encodeURIComponent(providerId)}/poll/${encodeURIComponent(sessionId)}`
401
+ })
402
+ }
403
+
404
+ export function cancelOAuthSession(sessionId: string): Promise<{ ok: boolean }> {
405
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
406
+ ...profileScoped(),
407
+ path: `/api/providers/oauth/sessions/${encodeURIComponent(sessionId)}`,
408
+ method: 'DELETE'
409
+ })
410
+ }
411
+
412
+ export function getSkills(): Promise<SkillInfo[]> {
413
+ return window.NASTECHDesktop.api<SkillInfo[]>({
414
+ ...profileScoped(),
415
+ path: '/api/skills'
416
+ })
417
+ }
418
+
419
+ export function toggleSkill(name: string, enabled: boolean): Promise<{ ok: boolean; name: string; enabled: boolean }> {
420
+ return window.NASTECHDesktop.api<{ ok: boolean; name: string; enabled: boolean }>({
421
+ ...profileScoped(),
422
+ path: '/api/skills/toggle',
423
+ method: 'PUT',
424
+ body: { name, enabled }
425
+ })
426
+ }
427
+
428
+ export function getToolsets(): Promise<ToolsetInfo[]> {
429
+ return window.NASTECHDesktop.api<ToolsetInfo[]>({
430
+ ...profileScoped(),
431
+ path: '/api/tools/toolsets'
432
+ })
433
+ }
434
+
435
+ export function toggleToolset(
436
+ name: string,
437
+ enabled: boolean
438
+ ): Promise<{ ok: boolean; name: string; enabled: boolean }> {
439
+ return window.NASTECHDesktop.api<{ ok: boolean; name: string; enabled: boolean }>({
440
+ ...profileScoped(),
441
+ path: `/api/tools/toolsets/${encodeURIComponent(name)}`,
442
+ method: 'PUT',
443
+ body: { enabled }
444
+ })
445
+ }
446
+
447
+ export function getToolsetConfig(name: string): Promise<ToolsetConfig> {
448
+ return window.NASTECHDesktop.api<ToolsetConfig>({
449
+ ...profileScoped(),
450
+ path: `/api/tools/toolsets/${encodeURIComponent(name)}/config`
451
+ })
452
+ }
453
+
454
+ export function selectToolsetProvider(
455
+ name: string,
456
+ provider: string
457
+ ): Promise<{ ok: boolean; name: string; provider: string }> {
458
+ return window.NASTECHDesktop.api<{ ok: boolean; name: string; provider: string }>({
459
+ ...profileScoped(),
460
+ path: `/api/tools/toolsets/${encodeURIComponent(name)}/provider`,
461
+ method: 'PUT',
462
+ body: { provider }
463
+ })
464
+ }
465
+
466
+ export function runToolsetPostSetup(name: string, key: string): Promise<ActionResponse & { key: string }> {
467
+ return window.NASTECHDesktop.api<ActionResponse & { key: string }>({
468
+ ...profileScoped(),
469
+ path: `/api/tools/toolsets/${encodeURIComponent(name)}/post-setup`,
470
+ method: 'POST',
471
+ body: { key }
472
+ })
473
+ }
474
+
475
+ export function getMessagingPlatforms(): Promise<MessagingPlatformsResponse> {
476
+ return window.NASTECHDesktop.api<MessagingPlatformsResponse>({
477
+ path: '/api/messaging/platforms'
478
+ })
479
+ }
480
+
481
+ export function updateMessagingPlatform(
482
+ platformId: string,
483
+ body: MessagingPlatformUpdate
484
+ ): Promise<{ ok: boolean; platform: string }> {
485
+ return window.NASTECHDesktop.api<{ ok: boolean; platform: string }>({
486
+ path: `/api/messaging/platforms/${encodeURIComponent(platformId)}`,
487
+ method: 'PUT',
488
+ body
489
+ })
490
+ }
491
+
492
+ export function testMessagingPlatform(platformId: string): Promise<MessagingPlatformTestResponse> {
493
+ return window.NASTECHDesktop.api<MessagingPlatformTestResponse>({
494
+ path: `/api/messaging/platforms/${encodeURIComponent(platformId)}/test`,
495
+ method: 'POST'
496
+ })
497
+ }
498
+
499
+ export function getCronJobs(): Promise<CronJob[]> {
500
+ return window.NASTECHDesktop.api<CronJob[]>({
501
+ path: '/api/cron/jobs'
502
+ })
503
+ }
504
+
505
+ export function getCronJob(jobId: string): Promise<CronJob> {
506
+ return window.NASTECHDesktop.api<CronJob>({
507
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}`
508
+ })
509
+ }
510
+
511
+ export async function getCronJobRuns(jobId: string, limit = 20): Promise<SessionInfo[]> {
512
+ const { runs } = await window.NASTECHDesktop.api<{ runs: SessionInfo[] }>({
513
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}/runs?limit=${limit}`
514
+ })
515
+
516
+ return runs ?? []
517
+ }
518
+
519
+ export function createCronJob(body: CronJobCreatePayload): Promise<CronJob> {
520
+ return window.NASTECHDesktop.api<CronJob>({
521
+ path: '/api/cron/jobs',
522
+ method: 'POST',
523
+ body
524
+ })
525
+ }
526
+
527
+ export function updateCronJob(jobId: string, updates: CronJobUpdates): Promise<CronJob> {
528
+ return window.NASTECHDesktop.api<CronJob>({
529
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}`,
530
+ method: 'PUT',
531
+ body: { updates }
532
+ })
533
+ }
534
+
535
+ export function pauseCronJob(jobId: string): Promise<CronJob> {
536
+ return window.NASTECHDesktop.api<CronJob>({
537
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}/pause`,
538
+ method: 'POST'
539
+ })
540
+ }
541
+
542
+ export function resumeCronJob(jobId: string): Promise<CronJob> {
543
+ return window.NASTECHDesktop.api<CronJob>({
544
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}/resume`,
545
+ method: 'POST'
546
+ })
547
+ }
548
+
549
+ export function triggerCronJob(jobId: string): Promise<CronJob> {
550
+ return window.NASTECHDesktop.api<CronJob>({
551
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}/trigger`,
552
+ method: 'POST'
553
+ })
554
+ }
555
+
556
+ export function deleteCronJob(jobId: string): Promise<{ ok: boolean }> {
557
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
558
+ path: `/api/cron/jobs/${encodeURIComponent(jobId)}`,
559
+ method: 'DELETE'
560
+ })
561
+ }
562
+
563
+ export function getProfiles(): Promise<ProfilesResponse> {
564
+ return window.NASTECHDesktop.api<ProfilesResponse>({
565
+ path: '/api/profiles'
566
+ })
567
+ }
568
+
569
+ export function createProfile(body: ProfileCreatePayload): Promise<{ name: string; ok: boolean; path: string }> {
570
+ return window.NASTECHDesktop.api<{ name: string; ok: boolean; path: string }>({
571
+ path: '/api/profiles',
572
+ method: 'POST',
573
+ body
574
+ })
575
+ }
576
+
577
+ export function renameProfile(name: string, newName: string): Promise<{ name: string; ok: boolean; path: string }> {
578
+ return window.NASTECHDesktop.api<{ name: string; ok: boolean; path: string }>({
579
+ path: `/api/profiles/${encodeURIComponent(name)}`,
580
+ method: 'PATCH',
581
+ body: { new_name: newName }
582
+ })
583
+ }
584
+
585
+ export function deleteProfile(name: string): Promise<{ ok: boolean; path: string }> {
586
+ return window.NASTECHDesktop.api<{ ok: boolean; path: string }>({
587
+ path: `/api/profiles/${encodeURIComponent(name)}`,
588
+ method: 'DELETE'
589
+ })
590
+ }
591
+
592
+ export function getProfileSoul(name: string): Promise<ProfileSoul> {
593
+ return window.NASTECHDesktop.api<ProfileSoul>({
594
+ path: `/api/profiles/${encodeURIComponent(name)}/soul`
595
+ })
596
+ }
597
+
598
+ export function updateProfileSoul(name: string, content: string): Promise<{ ok: boolean }> {
599
+ return window.NASTECHDesktop.api<{ ok: boolean }>({
600
+ path: `/api/profiles/${encodeURIComponent(name)}/soul`,
601
+ method: 'PUT',
602
+ body: { content }
603
+ })
604
+ }
605
+
606
+ export function getProfileSetupCommand(name: string): Promise<ProfileSetupCommand> {
607
+ return window.NASTECHDesktop.api<ProfileSetupCommand>({
608
+ path: `/api/profiles/${encodeURIComponent(name)}/setup-command`
609
+ })
610
+ }
611
+
612
+ export function getUsageAnalytics(days = 30): Promise<AnalyticsResponse> {
613
+ return window.NASTECHDesktop.api<AnalyticsResponse>({
614
+ ...profileScoped(),
615
+ path: `/api/analytics/usage?days=${Math.max(1, Math.floor(days))}`
616
+ })
617
+ }
618
+
619
+ export function getGlobalModelOptions(): Promise<ModelOptionsResponse> {
620
+ return window.NASTECHDesktop.api<ModelOptionsResponse>({
621
+ ...profileScoped(),
622
+ path: '/api/model/options'
623
+ })
624
+ }
625
+
626
+ export interface RecommendedDefaultModel {
627
+ provider: string
628
+ model: string
629
+ /** True/false for NasTech Portal (free vs paid tier); null for other providers. */
630
+ free_tier: boolean | null
631
+ }
632
+
633
+ // Recommended default model for a freshly-authenticated provider. Mirrors the
634
+ // curation `nastech model` does — for NasTech Portal it honors the free/paid tier so a
635
+ // free user gets a free model instead of a paid default.
636
+ export function getRecommendedDefaultModel(provider: string): Promise<RecommendedDefaultModel> {
637
+ return window.NASTECHDesktop.api<RecommendedDefaultModel>({
638
+ ...profileScoped(),
639
+ path: `/api/model/recommended-default?provider=${encodeURIComponent(provider)}`
640
+ })
641
+ }
642
+
643
+ export function setGlobalModel(
644
+ provider: string,
645
+ model: string
646
+ ): Promise<{ ok: boolean; provider: string; model: string }> {
647
+ return window.NASTECHDesktop.api<{ ok: boolean; provider: string; model: string }>({
648
+ ...profileScoped(),
649
+ path: '/api/model/set',
650
+ method: 'POST',
651
+ body: {
652
+ scope: 'main',
653
+ provider,
654
+ model
655
+ }
656
+ })
657
+ }
658
+
659
+ export function getAuxiliaryModels(): Promise<AuxiliaryModelsResponse> {
660
+ return window.NASTECHDesktop.api<AuxiliaryModelsResponse>({
661
+ ...profileScoped(),
662
+ path: '/api/model/auxiliary'
663
+ })
664
+ }
665
+
666
+ export function setModelAssignment(body: ModelAssignmentRequest): Promise<ModelAssignmentResponse> {
667
+ return window.NASTECHDesktop.api<ModelAssignmentResponse>({
668
+ ...profileScoped(),
669
+ path: '/api/model/set',
670
+ method: 'POST',
671
+ body
672
+ })
673
+ }
674
+
675
+ export function restartGateway(): Promise<ActionResponse> {
676
+ return window.NASTECHDesktop.api<ActionResponse>({
677
+ path: '/api/gateway/restart',
678
+ method: 'POST'
679
+ })
680
+ }
681
+
682
+ export function updateNasTech(): Promise<ActionResponse> {
683
+ return window.NASTECHDesktop.api<ActionResponse>({
684
+ path: '/api/nastech/update',
685
+ method: 'POST'
686
+ })
687
+ }
688
+
689
+ export function getActionStatus(name: string, lines = 200): Promise<ActionStatusResponse> {
690
+ return window.NASTECHDesktop.api<ActionStatusResponse>({
691
+ path: `/api/actions/${encodeURIComponent(name)}/status?lines=${Math.max(1, lines)}`
692
+ })
693
+ }
694
+
695
+ export function transcribeAudio(dataUrl: string, mimeType?: string): Promise<AudioTranscriptionResponse> {
696
+ return window.NASTECHDesktop.api<AudioTranscriptionResponse>({
697
+ path: '/api/audio/transcribe',
698
+ method: 'POST',
699
+ body: {
700
+ data_url: dataUrl,
701
+ mime_type: mimeType
702
+ }
703
+ })
704
+ }
705
+
706
+ export function speakText(text: string): Promise<AudioSpeakResponse> {
707
+ return window.NASTECHDesktop.api<AudioSpeakResponse>({
708
+ path: '/api/audio/speak',
709
+ method: 'POST',
710
+ body: { text }
711
+ })
712
+ }
713
+
714
+ export function getElevenLabsVoices(): Promise<ElevenLabsVoicesResponse> {
715
+ return window.NASTECHDesktop.api<ElevenLabsVoicesResponse>({
716
+ path: '/api/audio/elevenlabs/voices'
717
+ })
718
+ }