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.
- package/.prettierrc +11 -0
- package/DESIGN.md +167 -0
- package/README.md +141 -0
- package/assets/icon.icns +0 -0
- package/assets/icon.ico +0 -0
- package/assets/icon.png +0 -0
- package/components.json +21 -0
- package/electron/backend-env.cjs +112 -0
- package/electron/backend-env.test.cjs +111 -0
- package/electron/backend-probes.cjs +106 -0
- package/electron/backend-probes.test.cjs +82 -0
- package/electron/backend-ready.cjs +66 -0
- package/electron/bootstrap-platform.cjs +91 -0
- package/electron/bootstrap-platform.test.cjs +111 -0
- package/electron/bootstrap-runner.cjs +720 -0
- package/electron/bootstrap-runner.test.cjs +138 -0
- package/electron/connection-config.cjs +254 -0
- package/electron/connection-config.test.cjs +329 -0
- package/electron/dashboard-token.cjs +99 -0
- package/electron/dashboard-token.test.cjs +142 -0
- package/electron/desktop-uninstall.cjs +232 -0
- package/electron/desktop-uninstall.test.cjs +246 -0
- package/electron/entitlements.mac.inherit.plist +14 -0
- package/electron/entitlements.mac.plist +14 -0
- package/electron/fs-read-dir.cjs +109 -0
- package/electron/fs-read-dir.test.cjs +364 -0
- package/electron/gateway-ws-probe.cjs +188 -0
- package/electron/gateway-ws-probe.test.cjs +122 -0
- package/electron/git-root.cjs +54 -0
- package/electron/git-root.test.cjs +40 -0
- package/electron/git-worktrees.cjs +174 -0
- package/electron/hardening.cjs +184 -0
- package/electron/hardening.test.cjs +116 -0
- package/electron/main.cjs +5762 -0
- package/electron/oauth-net-request.cjs +20 -0
- package/electron/oauth-net-request.test.cjs +34 -0
- package/electron/preload.cjs +135 -0
- package/electron/session-windows.cjs +99 -0
- package/electron/session-windows.test.cjs +177 -0
- package/electron/update-remote.cjs +56 -0
- package/electron/update-remote.test.cjs +78 -0
- package/electron/vscode-marketplace.cjs +331 -0
- package/electron/vscode-marketplace.test.cjs +113 -0
- package/electron/windows-child-process.test.cjs +57 -0
- package/electron/windows-user-env.cjs +76 -0
- package/electron/windows-user-env.test.cjs +90 -0
- package/electron/workspace-cwd.cjs +38 -0
- package/electron/workspace-cwd.test.cjs +45 -0
- package/eslint.config.mjs +122 -0
- package/index.html +17 -0
- package/package.json +254 -0
- package/pr-assets/session-source-folders.png +0 -0
- package/preview-demo.html +65 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/ds-assets/filler-bg0.jpg +0 -0
- package/public/nastech-frames/nastech-frame-0.png +0 -0
- package/public/nastech-frames/nastech-frame-1.png +0 -0
- package/public/nastech-frames/nastech-frame-2.png +0 -0
- package/public/nastech-frames/nastech-frame-3.png +0 -0
- package/public/nastech-frames/nastech-frame-4.png +0 -0
- package/public/nastech-frames/nastech-frame-5.png +0 -0
- package/public/nastech-frames/nastech-frame-6.png +0 -0
- package/public/nastech-frames/nastech-frame-7.png +0 -0
- package/public/nastech-girl.jpg +0 -0
- package/public/nastech-sprite.png +0 -0
- package/public/nastech.png +0 -0
- package/scripts/after-pack.cjs +41 -0
- package/scripts/assert-dist-built.cjs +70 -0
- package/scripts/assert-dist-built.test.cjs +84 -0
- package/scripts/assert-root-install.cjs +13 -0
- package/scripts/before-build.cjs +11 -0
- package/scripts/before-pack.cjs +78 -0
- package/scripts/before-pack.test.cjs +53 -0
- package/scripts/click-session.mjs +51 -0
- package/scripts/dev-no-hmr.mjs +22 -0
- package/scripts/diag-jump.mjs +115 -0
- package/scripts/diag-scroll-reset.mjs +229 -0
- package/scripts/eval.mjs +21 -0
- package/scripts/leak-typing.mjs +222 -0
- package/scripts/measure-jump.mjs +108 -0
- package/scripts/measure-latency.mjs +184 -0
- package/scripts/measure-real-stream.mjs +252 -0
- package/scripts/measure-submit.mjs +179 -0
- package/scripts/measure-synthetic-stream.mjs +322 -0
- package/scripts/notarize-artifact.cjs +77 -0
- package/scripts/notarize.cjs +100 -0
- package/scripts/patch-electron-builder-mac-binary.cjs +59 -0
- package/scripts/probe-renderer.mjs +38 -0
- package/scripts/probe-thread.mjs +40 -0
- package/scripts/profile-long-stream.mjs +191 -0
- package/scripts/profile-real-stream.mjs +137 -0
- package/scripts/profile-synth-stream.mjs +103 -0
- package/scripts/profile-typing-lag.md +381 -0
- package/scripts/profile-typing.mjs +260 -0
- package/scripts/reload-renderer.mjs +25 -0
- package/scripts/reload.mjs +36 -0
- package/scripts/set-exe-identity.cjs +94 -0
- package/scripts/stage-native-deps.cjs +159 -0
- package/scripts/test-desktop.mjs +425 -0
- package/scripts/write-build-stamp.cjs +126 -0
- package/src/app/agents/index.tsx +398 -0
- package/src/app/artifacts/index.test.ts +62 -0
- package/src/app/artifacts/index.tsx +906 -0
- package/src/app/chat/chat-drop-overlay.tsx +48 -0
- package/src/app/chat/chat-swap-overlay.tsx +47 -0
- package/src/app/chat/composer/attachments.tsx +114 -0
- package/src/app/chat/composer/completion-drawer.tsx +63 -0
- package/src/app/chat/composer/context-menu.tsx +172 -0
- package/src/app/chat/composer/controls.tsx +289 -0
- package/src/app/chat/composer/drop-affordance.ts +2 -0
- package/src/app/chat/composer/enter-submit-dom-race.test.tsx +218 -0
- package/src/app/chat/composer/focus.ts +134 -0
- package/src/app/chat/composer/help-hint.tsx +59 -0
- package/src/app/chat/composer/hooks/use-at-completions.ts +141 -0
- package/src/app/chat/composer/hooks/use-live-completion-adapter.ts +119 -0
- package/src/app/chat/composer/hooks/use-mic-recorder.ts +291 -0
- package/src/app/chat/composer/hooks/use-slash-completions.ts +114 -0
- package/src/app/chat/composer/hooks/use-voice-conversation.ts +390 -0
- package/src/app/chat/composer/hooks/use-voice-recorder.ts +116 -0
- package/src/app/chat/composer/ime-composition-dom-repro.test.tsx +108 -0
- package/src/app/chat/composer/index.tsx +1611 -0
- package/src/app/chat/composer/inline-refs.ts +138 -0
- package/src/app/chat/composer/model-pill.tsx +86 -0
- package/src/app/chat/composer/queue-panel.tsx +130 -0
- package/src/app/chat/composer/rich-editor.test.ts +18 -0
- package/src/app/chat/composer/rich-editor.ts +165 -0
- package/src/app/chat/composer/skin-slash-popover.tsx +61 -0
- package/src/app/chat/composer/slash-nav-dom-repro.test.tsx +186 -0
- package/src/app/chat/composer/status-stack/index.tsx +202 -0
- package/src/app/chat/composer/status-stack/status-row.tsx +155 -0
- package/src/app/chat/composer/text-utils.test.ts +77 -0
- package/src/app/chat/composer/text-utils.ts +107 -0
- package/src/app/chat/composer/trigger-popover.test.tsx +42 -0
- package/src/app/chat/composer/trigger-popover.tsx +116 -0
- package/src/app/chat/composer/types.ts +64 -0
- package/src/app/chat/composer/url-dialog.tsx +82 -0
- package/src/app/chat/composer/voice-activity.tsx +252 -0
- package/src/app/chat/hooks/use-composer-actions.test.ts +57 -0
- package/src/app/chat/hooks/use-composer-actions.ts +525 -0
- package/src/app/chat/hooks/use-file-drop-zone.ts +118 -0
- package/src/app/chat/index.tsx +390 -0
- package/src/app/chat/perf-probe.tsx +269 -0
- package/src/app/chat/right-rail/index.ts +1 -0
- package/src/app/chat/right-rail/preview-console-state.ts +82 -0
- package/src/app/chat/right-rail/preview-console.tsx +290 -0
- package/src/app/chat/right-rail/preview-file.tsx +559 -0
- package/src/app/chat/right-rail/preview-pane.test.tsx +43 -0
- package/src/app/chat/right-rail/preview-pane.tsx +657 -0
- package/src/app/chat/right-rail/preview.tsx +171 -0
- package/src/app/chat/scroll-to-bottom-button.test.tsx +67 -0
- package/src/app/chat/scroll-to-bottom-button.tsx +74 -0
- package/src/app/chat/sidebar/cron-jobs-section.tsx +325 -0
- package/src/app/chat/sidebar/index.tsx +1219 -0
- package/src/app/chat/sidebar/load-more-row.tsx +30 -0
- package/src/app/chat/sidebar/order.test.ts +21 -0
- package/src/app/chat/sidebar/order.ts +17 -0
- package/src/app/chat/sidebar/profile-switcher.tsx +516 -0
- package/src/app/chat/sidebar/session-actions-menu.tsx +264 -0
- package/src/app/chat/sidebar/session-row.tsx +257 -0
- package/src/app/chat/sidebar/virtual-session-list.tsx +154 -0
- package/src/app/chat/sidebar/workspace-groups.test.ts +149 -0
- package/src/app/chat/sidebar/workspace-groups.ts +326 -0
- package/src/app/chat/thread-loading.test.ts +34 -0
- package/src/app/chat/thread-loading.ts +26 -0
- package/src/app/command-center/index.tsx +654 -0
- package/src/app/command-palette/index.tsx +513 -0
- package/src/app/command-palette/marketplace-theme-page.tsx +157 -0
- package/src/app/cron/index.tsx +942 -0
- package/src/app/cron/job-state.ts +29 -0
- package/src/app/desktop-controller.tsx +938 -0
- package/src/app/floating-hud.ts +22 -0
- package/src/app/gateway/hooks/use-gateway-boot.test.tsx +265 -0
- package/src/app/gateway/hooks/use-gateway-boot.ts +387 -0
- package/src/app/gateway/hooks/use-gateway-request.ts +138 -0
- package/src/app/hooks/use-keybinds.ts +186 -0
- package/src/app/hooks/use-refresh-hotkey.ts +45 -0
- package/src/app/hooks/use-route-enum-param.ts +38 -0
- package/src/app/index.tsx +1 -0
- package/src/app/layout-constants.ts +13 -0
- package/src/app/messaging/index.tsx +648 -0
- package/src/app/messaging/platform-icon.tsx +93 -0
- package/src/app/model-picker-overlay.tsx +42 -0
- package/src/app/model-visibility-overlay.tsx +31 -0
- package/src/app/overlays/overlay-chrome.tsx +66 -0
- package/src/app/overlays/overlay-search-input.tsx +33 -0
- package/src/app/overlays/overlay-split-layout.tsx +130 -0
- package/src/app/overlays/overlay-view.tsx +91 -0
- package/src/app/page-search-shell.tsx +75 -0
- package/src/app/profiles/create-profile-dialog.tsx +154 -0
- package/src/app/profiles/delete-profile-dialog.tsx +65 -0
- package/src/app/profiles/index.tsx +671 -0
- package/src/app/profiles/rename-profile-dialog.tsx +125 -0
- package/src/app/right-sidebar/files/dnd-manager.ts +27 -0
- package/src/app/right-sidebar/files/ipc.test.ts +100 -0
- package/src/app/right-sidebar/files/ipc.ts +161 -0
- package/src/app/right-sidebar/files/remote-picker.tsx +177 -0
- package/src/app/right-sidebar/files/tree.tsx +224 -0
- package/src/app/right-sidebar/files/use-project-tree.test.ts +190 -0
- package/src/app/right-sidebar/files/use-project-tree.ts +268 -0
- package/src/app/right-sidebar/index.test.tsx +75 -0
- package/src/app/right-sidebar/index.tsx +395 -0
- package/src/app/right-sidebar/store.ts +15 -0
- package/src/app/right-sidebar/terminal/buffer.ts +65 -0
- package/src/app/right-sidebar/terminal/index.tsx +98 -0
- package/src/app/right-sidebar/terminal/persistent.tsx +122 -0
- package/src/app/right-sidebar/terminal/selection.ts +75 -0
- package/src/app/right-sidebar/terminal/use-terminal-session.ts +504 -0
- package/src/app/routes.ts +88 -0
- package/src/app/session/hooks/use-context-suggestions.ts +58 -0
- package/src/app/session/hooks/use-cwd-actions.ts +109 -0
- package/src/app/session/hooks/use-message-stream.ts +957 -0
- package/src/app/session/hooks/use-model-controls.test.tsx +198 -0
- package/src/app/session/hooks/use-model-controls.ts +106 -0
- package/src/app/session/hooks/use-nastech-config.ts +74 -0
- package/src/app/session/hooks/use-preview-routing.test.tsx +168 -0
- package/src/app/session/hooks/use-preview-routing.ts +223 -0
- package/src/app/session/hooks/use-prompt-actions.test.tsx +316 -0
- package/src/app/session/hooks/use-prompt-actions.ts +1030 -0
- package/src/app/session/hooks/use-route-resume.test.tsx +136 -0
- package/src/app/session/hooks/use-route-resume.ts +115 -0
- package/src/app/session/hooks/use-session-actions.test.tsx +119 -0
- package/src/app/session/hooks/use-session-actions.ts +885 -0
- package/src/app/session/hooks/use-session-state-cache.test.tsx +118 -0
- package/src/app/session/hooks/use-session-state-cache.ts +191 -0
- package/src/app/session-picker-overlay.tsx +32 -0
- package/src/app/session-switcher.tsx +107 -0
- package/src/app/settings/about-settings.tsx +173 -0
- package/src/app/settings/appearance-settings.tsx +162 -0
- package/src/app/settings/config-settings.tsx +384 -0
- package/src/app/settings/constants.ts +545 -0
- package/src/app/settings/credential-key-ui.tsx +373 -0
- package/src/app/settings/env-credentials.tsx +198 -0
- package/src/app/settings/env-var-actions-menu.tsx +136 -0
- package/src/app/settings/field-copy.ts +56 -0
- package/src/app/settings/gateway-settings.tsx +620 -0
- package/src/app/settings/helpers.test.ts +138 -0
- package/src/app/settings/helpers.ts +151 -0
- package/src/app/settings/index.tsx +237 -0
- package/src/app/settings/keys-settings.tsx +96 -0
- package/src/app/settings/mcp-settings.tsx +271 -0
- package/src/app/settings/model-settings.test.tsx +157 -0
- package/src/app/settings/model-settings.tsx +559 -0
- package/src/app/settings/notifications-settings.tsx +150 -0
- package/src/app/settings/primitives.tsx +115 -0
- package/src/app/settings/providers-settings.test.tsx +100 -0
- package/src/app/settings/providers-settings.tsx +258 -0
- package/src/app/settings/sessions-settings.tsx +276 -0
- package/src/app/settings/toolset-config-panel.test.tsx +289 -0
- package/src/app/settings/toolset-config-panel.tsx +449 -0
- package/src/app/settings/types.ts +42 -0
- package/src/app/settings/uninstall-section.tsx +185 -0
- package/src/app/settings/use-deep-link-highlight.ts +60 -0
- package/src/app/shell/app-shell.tsx +167 -0
- package/src/app/shell/gateway-menu-panel.tsx +150 -0
- package/src/app/shell/hooks/use-overlay-routing.ts +71 -0
- package/src/app/shell/hooks/use-status-snapshot.ts +57 -0
- package/src/app/shell/hooks/use-statusbar-items.tsx +403 -0
- package/src/app/shell/keybind-panel.tsx +220 -0
- package/src/app/shell/model-edit-submenu.test.tsx +84 -0
- package/src/app/shell/model-edit-submenu.tsx +245 -0
- package/src/app/shell/model-menu-panel.tsx +295 -0
- package/src/app/shell/sidebar-label.tsx +22 -0
- package/src/app/shell/statusbar-controls.tsx +185 -0
- package/src/app/shell/titlebar-controls.tsx +244 -0
- package/src/app/shell/titlebar.test.ts +26 -0
- package/src/app/shell/titlebar.ts +45 -0
- package/src/app/shell/use-group-registry.ts +39 -0
- package/src/app/skills/index.test.tsx +103 -0
- package/src/app/skills/index.tsx +371 -0
- package/src/app/types.ts +99 -0
- package/src/app/updates-overlay.tsx +369 -0
- package/src/components/Backdrop.tsx +114 -0
- package/src/components/assistant-ui/ansi-text.tsx +34 -0
- package/src/components/assistant-ui/clarify-tool.tsx +281 -0
- package/src/components/assistant-ui/directive-text.test.ts +39 -0
- package/src/components/assistant-ui/directive-text.tsx +389 -0
- package/src/components/assistant-ui/markdown-text.test.ts +204 -0
- package/src/components/assistant-ui/markdown-text.tsx +497 -0
- package/src/components/assistant-ui/message-render-boundary.test.tsx +80 -0
- package/src/components/assistant-ui/message-render-boundary.tsx +48 -0
- package/src/components/assistant-ui/streaming.test.tsx +739 -0
- package/src/components/assistant-ui/thread-list.tsx +307 -0
- package/src/components/assistant-ui/thread-virtualizer.tsx +512 -0
- package/src/components/assistant-ui/thread.tsx +1474 -0
- package/src/components/assistant-ui/todo-tool.tsx +109 -0
- package/src/components/assistant-ui/tool-approval-group.test.tsx +158 -0
- package/src/components/assistant-ui/tool-approval.test.tsx +81 -0
- package/src/components/assistant-ui/tool-approval.tsx +209 -0
- package/src/components/assistant-ui/tool-fallback-model.test.ts +66 -0
- package/src/components/assistant-ui/tool-fallback-model.ts +1368 -0
- package/src/components/assistant-ui/tool-fallback.tsx +466 -0
- package/src/components/assistant-ui/tooltip-icon-button.tsx +33 -0
- package/src/components/assistant-ui/user-message-edit.test.tsx +141 -0
- package/src/components/assistant-ui/user-message-text.tsx +150 -0
- package/src/components/boot-failure-overlay.tsx +246 -0
- package/src/components/boot-failure-reauth.test.ts +100 -0
- package/src/components/boot-failure-reauth.ts +81 -0
- package/src/components/brand-mark.tsx +19 -0
- package/src/components/chat/activity-timer-text.tsx +24 -0
- package/src/components/chat/activity-timer.test.tsx +43 -0
- package/src/components/chat/activity-timer.ts +64 -0
- package/src/components/chat/code-card.tsx +78 -0
- package/src/components/chat/compact-markdown.tsx +113 -0
- package/src/components/chat/composer-dock.ts +31 -0
- package/src/components/chat/diff-lines.tsx +54 -0
- package/src/components/chat/disclosure-row.tsx +63 -0
- package/src/components/chat/generated-image-context.tsx +19 -0
- package/src/components/chat/generated-image-result.tsx +174 -0
- package/src/components/chat/image-generation-placeholder.tsx +279 -0
- package/src/components/chat/intro-copy.jsonl +75 -0
- package/src/components/chat/intro.tsx +182 -0
- package/src/components/chat/preview-attachment.tsx +125 -0
- package/src/components/chat/shiki-highlighter.tsx +107 -0
- package/src/components/chat/status-row.tsx +70 -0
- package/src/components/chat/status-section.tsx +42 -0
- package/src/components/chat/terminal-output.tsx +50 -0
- package/src/components/chat/zoomable-image.tsx +177 -0
- package/src/components/desktop-install-overlay.tsx +595 -0
- package/src/components/desktop-onboarding-overlay.test.tsx +100 -0
- package/src/components/desktop-onboarding-overlay.tsx +1286 -0
- package/src/components/error-boundary.tsx +77 -0
- package/src/components/gateway-connecting-overlay.test.tsx +143 -0
- package/src/components/gateway-connecting-overlay.tsx +183 -0
- package/src/components/haptics-provider.tsx +19 -0
- package/src/components/language-switcher.test.tsx +53 -0
- package/src/components/language-switcher.tsx +175 -0
- package/src/components/model-picker.tsx +340 -0
- package/src/components/model-visibility-dialog.tsx +155 -0
- package/src/components/notifications.tsx +196 -0
- package/src/components/page-loader.tsx +34 -0
- package/src/components/pane-shell/context.ts +14 -0
- package/src/components/pane-shell/index.ts +4 -0
- package/src/components/pane-shell/pane-shell.test.tsx +333 -0
- package/src/components/pane-shell/pane-shell.tsx +330 -0
- package/src/components/prompt-overlays.tsx +234 -0
- package/src/components/session-picker.tsx +108 -0
- package/src/components/status-dot.tsx +26 -0
- package/src/components/ui/action-status.tsx +25 -0
- package/src/components/ui/alert.tsx +53 -0
- package/src/components/ui/badge.tsx +35 -0
- package/src/components/ui/braille-spinner.tsx +61 -0
- package/src/components/ui/button.tsx +81 -0
- package/src/components/ui/checkbox.tsx +27 -0
- package/src/components/ui/codicon.tsx +20 -0
- package/src/components/ui/command.tsx +111 -0
- package/src/components/ui/confirm-dialog.tsx +109 -0
- package/src/components/ui/context-menu.tsx +141 -0
- package/src/components/ui/control.ts +25 -0
- package/src/components/ui/copy-button.test.tsx +36 -0
- package/src/components/ui/copy-button.tsx +229 -0
- package/src/components/ui/dialog.tsx +152 -0
- package/src/components/ui/disclosure-caret.tsx +20 -0
- package/src/components/ui/dropdown-menu.tsx +291 -0
- package/src/components/ui/error-state.tsx +50 -0
- package/src/components/ui/fade-text.tsx +110 -0
- package/src/components/ui/glyph-spinner.tsx +63 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/kbd.tsx +37 -0
- package/src/components/ui/loader.tsx +558 -0
- package/src/components/ui/log-view.tsx +17 -0
- package/src/components/ui/pagination.tsx +114 -0
- package/src/components/ui/popover.tsx +44 -0
- package/src/components/ui/scroll-area.tsx +43 -0
- package/src/components/ui/search-field.tsx +80 -0
- package/src/components/ui/segmented-control.tsx +51 -0
- package/src/components/ui/select.tsx +92 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/sheet.tsx +116 -0
- package/src/components/ui/sidebar.tsx +674 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/switch.tsx +49 -0
- package/src/components/ui/tabs.tsx +36 -0
- package/src/components/ui/text-tab.tsx +43 -0
- package/src/components/ui/textarea.tsx +11 -0
- package/src/components/ui/tool-icon.tsx +65 -0
- package/src/components/ui/tooltip.tsx +69 -0
- package/src/fonts/JetBrainsMono-Bold.woff2 +0 -0
- package/src/fonts/JetBrainsMono-Italic.woff2 +0 -0
- package/src/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/src/global.d.ts +457 -0
- package/src/hooks/use-image-download.ts +85 -0
- package/src/hooks/use-media-query.ts +24 -0
- package/src/hooks/use-mobile.ts +3 -0
- package/src/hooks/use-resize-observer.ts +38 -0
- package/src/hooks/use-worktree-info.ts +68 -0
- package/src/i18n/catalog.ts +12 -0
- package/src/i18n/context.test.tsx +232 -0
- package/src/i18n/context.tsx +183 -0
- package/src/i18n/define-locale.ts +41 -0
- package/src/i18n/en.ts +1779 -0
- package/src/i18n/index.ts +20 -0
- package/src/i18n/ja.ts +1890 -0
- package/src/i18n/languages.test.ts +43 -0
- package/src/i18n/languages.ts +86 -0
- package/src/i18n/runtime.test.ts +75 -0
- package/src/i18n/runtime.ts +53 -0
- package/src/i18n/types.ts +1452 -0
- package/src/i18n/zh-hant.ts +1849 -0
- package/src/i18n/zh.ts +1923 -0
- package/src/lib/ansi.test.ts +123 -0
- package/src/lib/ansi.ts +175 -0
- package/src/lib/chat-messages.test.ts +708 -0
- package/src/lib/chat-messages.ts +885 -0
- package/src/lib/chat-runtime.test.ts +18 -0
- package/src/lib/chat-runtime.ts +335 -0
- package/src/lib/clipboard.ts +28 -0
- package/src/lib/commit-changelog.test.ts +114 -0
- package/src/lib/commit-changelog.ts +177 -0
- package/src/lib/completion-sound.ts +519 -0
- package/src/lib/desktop-fs.test.ts +116 -0
- package/src/lib/desktop-fs.ts +113 -0
- package/src/lib/desktop-slash-commands.test.ts +126 -0
- package/src/lib/desktop-slash-commands.ts +286 -0
- package/src/lib/embedded-images.test.ts +35 -0
- package/src/lib/embedded-images.ts +60 -0
- package/src/lib/external-link.test.tsx +168 -0
- package/src/lib/external-link.tsx +303 -0
- package/src/lib/gateway-events.test.ts +27 -0
- package/src/lib/gateway-events.ts +49 -0
- package/src/lib/gateway-ws-url.test.ts +78 -0
- package/src/lib/gateway-ws-url.ts +91 -0
- package/src/lib/generated-images.test.ts +97 -0
- package/src/lib/generated-images.ts +116 -0
- package/src/lib/haptics.ts +129 -0
- package/src/lib/icons.ts +203 -0
- package/src/lib/incremental-external-store-runtime.ts +188 -0
- package/src/lib/katex-memo.ts +260 -0
- package/src/lib/keybinds/actions.ts +125 -0
- package/src/lib/keybinds/combo.test.ts +86 -0
- package/src/lib/keybinds/combo.ts +169 -0
- package/src/lib/local-preview.ts +126 -0
- package/src/lib/markdown-code.test.ts +23 -0
- package/src/lib/markdown-code.ts +195 -0
- package/src/lib/markdown-preprocess.ts +386 -0
- package/src/lib/media.remote.test.ts +58 -0
- package/src/lib/media.ts +111 -0
- package/src/lib/model-status-label.test.ts +31 -0
- package/src/lib/model-status-label.ts +103 -0
- package/src/lib/mutable-ref.ts +6 -0
- package/src/lib/preview-targets.test.ts +27 -0
- package/src/lib/preview-targets.ts +63 -0
- package/src/lib/profile-color.ts +58 -0
- package/src/lib/provider-setup-errors.test.ts +26 -0
- package/src/lib/provider-setup-errors.ts +12 -0
- package/src/lib/query-client.ts +13 -0
- package/src/lib/remend-tail.test.ts +105 -0
- package/src/lib/remend-tail.ts +108 -0
- package/src/lib/runtime-readiness.test.ts +65 -0
- package/src/lib/runtime-readiness.ts +147 -0
- package/src/lib/session-export.ts +57 -0
- package/src/lib/session-search.test.ts +58 -0
- package/src/lib/session-search.ts +19 -0
- package/src/lib/session-source.ts +62 -0
- package/src/lib/speech-text.ts +35 -0
- package/src/lib/statusbar.ts +91 -0
- package/src/lib/storage.test.ts +25 -0
- package/src/lib/storage.ts +107 -0
- package/src/lib/todos.test.ts +35 -0
- package/src/lib/todos.ts +51 -0
- package/src/lib/tool-result-summary.test.ts +106 -0
- package/src/lib/tool-result-summary.ts +467 -0
- package/src/lib/update-copy.test.ts +38 -0
- package/src/lib/update-copy.ts +44 -0
- package/src/lib/use-enter-animation.ts +100 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/voice-playback.ts +128 -0
- package/src/lib/yolo-session.ts +26 -0
- package/src/main.tsx +43 -0
- package/src/nastech.test.ts +49 -0
- package/src/nastech.ts +718 -0
- package/src/store/activity.ts +100 -0
- package/src/store/boot.ts +91 -0
- package/src/store/clarify.test.ts +81 -0
- package/src/store/clarify.ts +69 -0
- package/src/store/command-palette.ts +20 -0
- package/src/store/compaction.test.ts +53 -0
- package/src/store/compaction.ts +38 -0
- package/src/store/completion-sound.ts +32 -0
- package/src/store/composer-input-history.test.ts +147 -0
- package/src/store/composer-input-history.ts +158 -0
- package/src/store/composer-queue.test.ts +148 -0
- package/src/store/composer-queue.ts +239 -0
- package/src/store/composer-status.test.ts +99 -0
- package/src/store/composer-status.ts +277 -0
- package/src/store/composer.test.ts +106 -0
- package/src/store/composer.ts +184 -0
- package/src/store/cron.ts +19 -0
- package/src/store/gateway.ts +290 -0
- package/src/store/haptics.ts +17 -0
- package/src/store/keybinds.ts +139 -0
- package/src/store/layout.ts +176 -0
- package/src/store/model-presets.test.ts +51 -0
- package/src/store/model-presets.ts +86 -0
- package/src/store/model-visibility.test.ts +37 -0
- package/src/store/model-visibility.ts +108 -0
- package/src/store/native-notifications.test.ts +192 -0
- package/src/store/native-notifications.ts +203 -0
- package/src/store/notifications.ts +165 -0
- package/src/store/onboarding.test.ts +372 -0
- package/src/store/onboarding.ts +866 -0
- package/src/store/panes.test.ts +146 -0
- package/src/store/panes.ts +145 -0
- package/src/store/preview.test.ts +135 -0
- package/src/store/preview.ts +466 -0
- package/src/store/profile.test.ts +89 -0
- package/src/store/profile.ts +365 -0
- package/src/store/prompts.test.ts +121 -0
- package/src/store/prompts.ts +115 -0
- package/src/store/session-switcher.test.ts +115 -0
- package/src/store/session-switcher.ts +128 -0
- package/src/store/session-sync.ts +25 -0
- package/src/store/session.test.ts +131 -0
- package/src/store/session.ts +255 -0
- package/src/store/subagents.test.ts +111 -0
- package/src/store/subagents.ts +260 -0
- package/src/store/thread-scroll.ts +46 -0
- package/src/store/todos.test.ts +47 -0
- package/src/store/todos.ts +64 -0
- package/src/store/tool-diffs.ts +23 -0
- package/src/store/tool-dismiss.ts +45 -0
- package/src/store/tool-view.ts +91 -0
- package/src/store/translucency.ts +38 -0
- package/src/store/updates.test.ts +77 -0
- package/src/store/updates.ts +315 -0
- package/src/store/voice-playback.ts +24 -0
- package/src/store/windows.test.ts +143 -0
- package/src/store/windows.ts +77 -0
- package/src/styles.css +1235 -0
- package/src/themes/color.ts +142 -0
- package/src/themes/context.tsx +339 -0
- package/src/themes/index.ts +3 -0
- package/src/themes/install.test.ts +119 -0
- package/src/themes/install.ts +95 -0
- package/src/themes/presets.test.ts +33 -0
- package/src/themes/presets.ts +293 -0
- package/src/themes/profile-theme.test.ts +41 -0
- package/src/themes/types.ts +66 -0
- package/src/themes/use-skin-command.ts +60 -0
- package/src/themes/user-themes.test.ts +63 -0
- package/src/themes/user-themes.ts +122 -0
- package/src/themes/vscode.test.ts +171 -0
- package/src/themes/vscode.ts +343 -0
- package/src/types/nastech.ts +646 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +25 -0
- package/vite.config.ts +56 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for electron/backend-probes.cjs.
|
|
3
|
+
*
|
|
4
|
+
* Run with: node --test electron/backend-probes.test.cjs
|
|
5
|
+
* (Wired into npm test:desktop:platforms in package.json.)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const test = require('node:test')
|
|
9
|
+
const assert = require('node:assert/strict')
|
|
10
|
+
const fs = require('node:fs')
|
|
11
|
+
const os = require('node:os')
|
|
12
|
+
const path = require('node:path')
|
|
13
|
+
|
|
14
|
+
const { canImportNastechCli, verifyNastechCli } = require('./backend-probes.cjs')
|
|
15
|
+
|
|
16
|
+
// Resolve the host's own Node binary -- guaranteed to be on disk and
|
|
17
|
+
// runnable. We use it as both a stand-in for "a python that doesn't
|
|
18
|
+
// have nastech_cli" (since `node -c "import nastech_cli"` will exit
|
|
19
|
+
// non-zero) and as a way to script verifyNastechCli's success path
|
|
20
|
+
// (a tiny script we write to disk that exits 0 on --version).
|
|
21
|
+
const NODE_BIN = process.execPath
|
|
22
|
+
|
|
23
|
+
test('canImportNastechCli returns false when path is falsy', () => {
|
|
24
|
+
assert.equal(canImportNastechCli(''), false)
|
|
25
|
+
assert.equal(canImportNastechCli(null), false)
|
|
26
|
+
assert.equal(canImportNastechCli(undefined), false)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('canImportNastechCli returns false when interpreter cannot run -c', () => {
|
|
30
|
+
// node IS an interpreter, but `node -c "import nastech_cli"` is a
|
|
31
|
+
// SyntaxError -- different exit reason from a real Python's
|
|
32
|
+
// ModuleNotFoundError, but the predicate is "exit 0 or not" and
|
|
33
|
+
// both land on "not", which is exactly what we want for the
|
|
34
|
+
// resolver fall-through.
|
|
35
|
+
assert.equal(canImportNastechCli(NODE_BIN), false)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('canImportNastechCli returns false when binary does not exist', () => {
|
|
39
|
+
const ghost = path.join(os.tmpdir(), 'nastech-probes-ghost-' + Date.now() + '.exe')
|
|
40
|
+
assert.equal(canImportNastechCli(ghost), false)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('verifyNastechCli returns false when command is falsy', () => {
|
|
44
|
+
assert.equal(verifyNastechCli(''), false)
|
|
45
|
+
assert.equal(verifyNastechCli(null), false)
|
|
46
|
+
assert.equal(verifyNastechCli(undefined), false)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('verifyNastechCli returns false when binary does not exist', () => {
|
|
50
|
+
const ghost = path.join(os.tmpdir(), 'nastech-probes-ghost-' + Date.now() + '.exe')
|
|
51
|
+
assert.equal(verifyNastechCli(ghost), false)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('verifyNastechCli returns true when --version exits 0', () => {
|
|
55
|
+
// Write a tiny script that exits 0 regardless of args, then invoke
|
|
56
|
+
// it through node. This stands in for a working nastech binary --
|
|
57
|
+
// verifyNastechCli only cares about the exit code.
|
|
58
|
+
const scriptPath = path.join(os.tmpdir(), `nastech-probes-ok-${Date.now()}-${process.pid}.cjs`)
|
|
59
|
+
fs.writeFileSync(scriptPath, 'process.exit(0)\n')
|
|
60
|
+
try {
|
|
61
|
+
// Use node as the launcher and our script as the "command". Pass
|
|
62
|
+
// shell:false (default) -- node is a real binary, no shim.
|
|
63
|
+
// execFileSync passes ['--version'] as args, which node ignores
|
|
64
|
+
// gracefully (well, it prints its version and exits 0, which is
|
|
65
|
+
// perfect -- exit code 0 is the only signal we read).
|
|
66
|
+
assert.equal(verifyNastechCli(NODE_BIN), true)
|
|
67
|
+
} finally {
|
|
68
|
+
try {
|
|
69
|
+
fs.unlinkSync(scriptPath)
|
|
70
|
+
} catch {
|
|
71
|
+
void 0
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('verifyNastechCli swallows timeouts (does not throw)', () => {
|
|
77
|
+
// We can't easily provoke a real 5s hang in CI without slowing the
|
|
78
|
+
// suite, but we CAN confirm that an invocation that DOES throw
|
|
79
|
+
// (because the binary is missing) returns false rather than
|
|
80
|
+
// propagating. Same code path the timeout case takes.
|
|
81
|
+
assert.equal(verifyNastechCli('/definitely/not/a/real/binary/anywhere'), false)
|
|
82
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const _READY_RE = /^NASTECH_DASHBOARD_READY port=(\d+)/m
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Watch a child process's stdout for the `NASTECH_DASHBOARD_READY port=<N>`
|
|
5
|
+
* line that web_server.py prints after uvicorn binds its socket.
|
|
6
|
+
*
|
|
7
|
+
* Returns the parsed port. Rejects if:
|
|
8
|
+
* - the child exits before emitting the line
|
|
9
|
+
* - the child emits an `error` event
|
|
10
|
+
* - no line arrives within the timeout
|
|
11
|
+
*
|
|
12
|
+
* A single `cleanup()` tears down every listener (data/exit/error/timeout)
|
|
13
|
+
* on every terminal path — resolve, reject, or timeout — so repeated
|
|
14
|
+
* backend spawns don't leak listener slots on the child.
|
|
15
|
+
*/
|
|
16
|
+
function waitForDashboardPort(child, timeoutMs = 45_000) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
let buf = ''
|
|
19
|
+
let done = false
|
|
20
|
+
|
|
21
|
+
function cleanup() {
|
|
22
|
+
if (done) return
|
|
23
|
+
done = true
|
|
24
|
+
clearTimeout(timer)
|
|
25
|
+
child.stdout.off('data', onData)
|
|
26
|
+
child.off('exit', onExit)
|
|
27
|
+
child.off('error', onError)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function onData(chunk) {
|
|
31
|
+
buf += chunk.toString()
|
|
32
|
+
let nl
|
|
33
|
+
while ((nl = buf.indexOf('\n')) !== -1) {
|
|
34
|
+
const line = buf.slice(0, nl)
|
|
35
|
+
buf = buf.slice(nl + 1)
|
|
36
|
+
const m = line.match(_READY_RE)
|
|
37
|
+
if (m) {
|
|
38
|
+
cleanup()
|
|
39
|
+
resolve(parseInt(m[1], 10))
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function onExit(code, signal) {
|
|
46
|
+
cleanup()
|
|
47
|
+
reject(new Error(`NasTech backend: exited before port announcement (${signal || code})`))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function onError(err) {
|
|
51
|
+
cleanup()
|
|
52
|
+
reject(err)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const timer = setTimeout(() => {
|
|
56
|
+
cleanup()
|
|
57
|
+
reject(new Error(`Timed out waiting for NasTech backend port announcement (${timeoutMs}ms)`))
|
|
58
|
+
}, timeoutMs)
|
|
59
|
+
|
|
60
|
+
child.stdout.on('data', onData)
|
|
61
|
+
child.on('exit', onExit)
|
|
62
|
+
child.on('error', onError)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = { waitForDashboardPort }
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const fs = require('node:fs')
|
|
2
|
+
|
|
3
|
+
function isWslEnvironment(env = process.env, platform = process.platform, kernelRelease = null) {
|
|
4
|
+
if (platform !== 'linux') return false
|
|
5
|
+
if (env.WSL_DISTRO_NAME || env.WSL_INTEROP) return true
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const release = kernelRelease ?? fs.readFileSync('/proc/sys/kernel/osrelease', 'utf8')
|
|
9
|
+
return /microsoft|wsl/i.test(release)
|
|
10
|
+
} catch {
|
|
11
|
+
return false
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isWindowsBinaryPathInWsl(filePath, options = {}) {
|
|
16
|
+
const isWsl = options.isWsl ?? isWslEnvironment(options.env, options.platform)
|
|
17
|
+
if (!isWsl) return false
|
|
18
|
+
|
|
19
|
+
const normalized = String(filePath || '')
|
|
20
|
+
.replace(/\\/g, '/')
|
|
21
|
+
.toLowerCase()
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
normalized.endsWith('.exe') ||
|
|
25
|
+
normalized.endsWith('.cmd') ||
|
|
26
|
+
normalized.endsWith('.bat') ||
|
|
27
|
+
normalized.endsWith('.ps1')
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bundledRuntimeImportCheck(platform = process.platform) {
|
|
32
|
+
return platform === 'win32' ? 'import fastapi, uvicorn, winpty' : 'import fastapi, uvicorn, ptyprocess'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const GPU_OVERRIDE_ON = new Set(['1', 'true', 'yes', 'on'])
|
|
36
|
+
const GPU_OVERRIDE_OFF = new Set(['0', 'false', 'no', 'off'])
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Decide whether the app is being shown over a remote/forwarded display, where
|
|
40
|
+
* Chromium's GPU compositor produces an unstable, flickering surface (it can't
|
|
41
|
+
* present accelerated layers cleanly over the wire). Native local Windows/macOS
|
|
42
|
+
* sessions composite locally and never hit this, so we only fall back to
|
|
43
|
+
* software rendering when a remote display is detected.
|
|
44
|
+
*
|
|
45
|
+
* Returns a short reason string when GPU acceleration should be disabled, or
|
|
46
|
+
* null to keep it enabled. `NASTECH_DESKTOP_DISABLE_GPU` overrides detection
|
|
47
|
+
* both ways (1/true/yes/on → always disable, 0/false/no/off → never disable).
|
|
48
|
+
*
|
|
49
|
+
* Pure + dependency-free so it can be unit-tested and called before app ready.
|
|
50
|
+
*/
|
|
51
|
+
function detectRemoteDisplay(options = {}) {
|
|
52
|
+
const env = options.env ?? process.env
|
|
53
|
+
const platform = options.platform ?? process.platform
|
|
54
|
+
|
|
55
|
+
const override = String(env.NASTECH_DESKTOP_DISABLE_GPU || '')
|
|
56
|
+
.trim()
|
|
57
|
+
.toLowerCase()
|
|
58
|
+
if (GPU_OVERRIDE_ON.has(override)) return 'override (NASTECH_DESKTOP_DISABLE_GPU)'
|
|
59
|
+
if (GPU_OVERRIDE_OFF.has(override)) return null
|
|
60
|
+
|
|
61
|
+
// Launched from an SSH session → the display is X11-forwarded or otherwise
|
|
62
|
+
// remote. Covers the common `ssh user@box` + GUI-forwarding case.
|
|
63
|
+
if (env.SSH_CONNECTION || env.SSH_CLIENT || env.SSH_TTY) return 'ssh-session'
|
|
64
|
+
|
|
65
|
+
if (platform === 'linux') {
|
|
66
|
+
// X11 forwarding sets DISPLAY to "<host>:N" (e.g. "localhost:10.0"); a
|
|
67
|
+
// local X server is ":0"/":1" with no host part before the colon.
|
|
68
|
+
// NB: WSLg deliberately isn't treated as remote — it reports
|
|
69
|
+
// GPU-accelerated vGPU surfaces locally and doesn't show the flicker.
|
|
70
|
+
const display = String(env.DISPLAY || '')
|
|
71
|
+
if (display.includes(':') && display.split(':')[0]) {
|
|
72
|
+
return `x11-forwarding (DISPLAY=${display})`
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (platform === 'win32') {
|
|
77
|
+
// RDP sessions report SESSIONNAME like "RDP-Tcp#7"; the local console is
|
|
78
|
+
// "Console".
|
|
79
|
+
const sessionName = String(env.SESSIONNAME || '')
|
|
80
|
+
if (/^rdp-/i.test(sessionName)) return `rdp (SESSIONNAME=${sessionName})`
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
bundledRuntimeImportCheck,
|
|
88
|
+
detectRemoteDisplay,
|
|
89
|
+
isWindowsBinaryPathInWsl,
|
|
90
|
+
isWslEnvironment
|
|
91
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const assert = require('node:assert/strict')
|
|
2
|
+
const fs = require('node:fs')
|
|
3
|
+
const path = require('node:path')
|
|
4
|
+
const test = require('node:test')
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
bundledRuntimeImportCheck,
|
|
8
|
+
detectRemoteDisplay,
|
|
9
|
+
isWindowsBinaryPathInWsl,
|
|
10
|
+
isWslEnvironment
|
|
11
|
+
} = require('./bootstrap-platform.cjs')
|
|
12
|
+
|
|
13
|
+
test('isWslEnvironment detects WSL2 env vars on linux', () => {
|
|
14
|
+
assert.equal(isWslEnvironment({ WSL_DISTRO_NAME: 'Ubuntu' }, 'linux'), true)
|
|
15
|
+
assert.equal(isWslEnvironment({ WSL_INTEROP: '/run/WSL/123_interop' }, 'linux'), true)
|
|
16
|
+
assert.equal(isWslEnvironment({}, 'linux', '6.6.87.2-microsoft-standard-WSL2'), true)
|
|
17
|
+
assert.equal(isWslEnvironment({}, 'linux', '6.6.87-generic'), false)
|
|
18
|
+
assert.equal(isWslEnvironment({ WSL_DISTRO_NAME: 'Ubuntu' }, 'darwin'), false)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('isWindowsBinaryPathInWsl blocks Windows binary types on WSL', () => {
|
|
22
|
+
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/nastech.exe', { isWsl: true }), true)
|
|
23
|
+
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/nastech.cmd', { isWsl: true }), true)
|
|
24
|
+
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/nastech.bat', { isWsl: true }), true)
|
|
25
|
+
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/install.ps1', { isWsl: true }), true)
|
|
26
|
+
assert.equal(isWindowsBinaryPathInWsl('/usr/local/bin/nastech', { isWsl: true }), false)
|
|
27
|
+
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/nastech.exe', { isWsl: false }), false)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('bundledRuntimeImportCheck selects platform-specific import checks', () => {
|
|
31
|
+
assert.equal(bundledRuntimeImportCheck('win32'), 'import fastapi, uvicorn, winpty')
|
|
32
|
+
assert.equal(bundledRuntimeImportCheck('darwin'), 'import fastapi, uvicorn, ptyprocess')
|
|
33
|
+
assert.equal(bundledRuntimeImportCheck('linux'), 'import fastapi, uvicorn, ptyprocess')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('detectRemoteDisplay keeps GPU on for local sessions', () => {
|
|
37
|
+
// Plain local X11, Wayland, native Windows, native macOS — no remote signal.
|
|
38
|
+
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':0' }, platform: 'linux' }), null)
|
|
39
|
+
assert.equal(detectRemoteDisplay({ env: { WAYLAND_DISPLAY: 'wayland-0' }, platform: 'linux' }), null)
|
|
40
|
+
assert.equal(detectRemoteDisplay({ env: { SESSIONNAME: 'Console' }, platform: 'win32' }), null)
|
|
41
|
+
assert.equal(detectRemoteDisplay({ env: {}, platform: 'darwin' }), null)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('detectRemoteDisplay does not treat WSLg as remote', () => {
|
|
45
|
+
// WSLg renders locally via vGPU and doesn't show the flicker, so a WSL
|
|
46
|
+
// session with a local DISPLAY keeps hardware acceleration on.
|
|
47
|
+
assert.equal(detectRemoteDisplay({ env: { WSL_DISTRO_NAME: 'Ubuntu', DISPLAY: ':0' }, platform: 'linux' }), null)
|
|
48
|
+
assert.equal(
|
|
49
|
+
detectRemoteDisplay({ env: { WSL_INTEROP: '/run/WSL/1_interop', DISPLAY: ':0' }, platform: 'linux' }),
|
|
50
|
+
null
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('detectRemoteDisplay flags SSH sessions on any platform', () => {
|
|
55
|
+
assert.equal(
|
|
56
|
+
detectRemoteDisplay({ env: { SSH_CONNECTION: '1.2.3.4 5 6.7.8.9 22' }, platform: 'linux' }),
|
|
57
|
+
'ssh-session'
|
|
58
|
+
)
|
|
59
|
+
assert.equal(detectRemoteDisplay({ env: { SSH_CLIENT: '1.2.3.4 5 22' }, platform: 'darwin' }), 'ssh-session')
|
|
60
|
+
assert.equal(detectRemoteDisplay({ env: { SSH_TTY: '/dev/pts/0' }, platform: 'win32' }), 'ssh-session')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('detectRemoteDisplay flags forwarded X11 displays but not local ones', () => {
|
|
64
|
+
assert.match(String(detectRemoteDisplay({ env: { DISPLAY: 'localhost:10.0' }, platform: 'linux' })), /x11-forwarding/)
|
|
65
|
+
assert.match(String(detectRemoteDisplay({ env: { DISPLAY: '192.168.1.5:0' }, platform: 'linux' })), /x11-forwarding/)
|
|
66
|
+
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':1' }, platform: 'linux' }), null)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('detectRemoteDisplay flags RDP sessions', () => {
|
|
70
|
+
assert.match(String(detectRemoteDisplay({ env: { SESSIONNAME: 'RDP-Tcp#7' }, platform: 'win32' })), /^rdp/)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('detectRemoteDisplay honors the NASTECH_DESKTOP_DISABLE_GPU override both ways', () => {
|
|
74
|
+
// Force-on even on a local display.
|
|
75
|
+
assert.match(
|
|
76
|
+
String(detectRemoteDisplay({ env: { NASTECH_DESKTOP_DISABLE_GPU: '1', DISPLAY: ':0' }, platform: 'linux' })),
|
|
77
|
+
/override/
|
|
78
|
+
)
|
|
79
|
+
// Force-off even over SSH (escape hatch when a remote display has working accel).
|
|
80
|
+
assert.equal(
|
|
81
|
+
detectRemoteDisplay({
|
|
82
|
+
env: { NASTECH_DESKTOP_DISABLE_GPU: 'false', SSH_CONNECTION: '1.2.3.4 5 6.7.8.9 22' },
|
|
83
|
+
platform: 'linux'
|
|
84
|
+
}),
|
|
85
|
+
null
|
|
86
|
+
)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('packaged electron entrypoints do not require unpackaged npm modules', () => {
|
|
90
|
+
const electronDir = __dirname
|
|
91
|
+
const entrypoints = ['main.cjs', 'preload.cjs', 'bootstrap-platform.cjs']
|
|
92
|
+
// - electron: provided by the electron runtime, always resolvable in packaged builds.
|
|
93
|
+
// - node-pty: hoisted by workspace dedup AND shipped via extraResources to
|
|
94
|
+
// resources/native-deps/node-pty (see scripts/stage-native-deps.cjs). main.cjs
|
|
95
|
+
// has a try/catch fallback at line ~38 that resolves the staged copy when the
|
|
96
|
+
// bare require fails in the packaged asar, so the bare require itself is by
|
|
97
|
+
// design rather than an oversight.
|
|
98
|
+
const allowedBareRequires = new Set(['electron', 'node-pty'])
|
|
99
|
+
const requirePattern = /require\(['"]([^'"]+)['"]\)/g
|
|
100
|
+
|
|
101
|
+
for (const entrypoint of entrypoints) {
|
|
102
|
+
const source = fs.readFileSync(path.join(electronDir, entrypoint), 'utf8')
|
|
103
|
+
const bareRequires = Array.from(source.matchAll(requirePattern))
|
|
104
|
+
.map(match => match[1])
|
|
105
|
+
.filter(specifier => !specifier.startsWith('node:'))
|
|
106
|
+
.filter(specifier => !specifier.startsWith('.'))
|
|
107
|
+
.filter(specifier => !allowedBareRequires.has(specifier))
|
|
108
|
+
|
|
109
|
+
assert.deepEqual(bareRequires, [], `${entrypoint} has unpackaged runtime requires`)
|
|
110
|
+
}
|
|
111
|
+
})
|