@agent-native/core 0.79.16 → 0.79.18
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/docs/content/file-uploads.md +11 -4
- package/corpus/core/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/template-clips.md +14 -5
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/builder-engine.ts +8 -3
- package/corpus/core/src/cli/mcp.ts +11 -6
- package/corpus/core/src/client/AssistantChat.tsx +6 -2
- package/corpus/core/src/client/chat/markdown-renderer.tsx +1 -0
- package/corpus/core/src/client/index.ts +7 -1
- package/corpus/core/src/client/org/OrgSwitcher.tsx +5 -5
- package/corpus/core/src/client/org/TeamPage.tsx +11 -3
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +216 -0
- package/corpus/core/src/client/settings/index.ts +5 -0
- package/corpus/core/src/file-upload/index.ts +1 -0
- package/corpus/core/src/file-upload/registry.ts +22 -6
- package/corpus/core/src/file-upload/types.ts +6 -1
- package/corpus/core/src/integrations/adapters/email.ts +26 -18
- package/corpus/core/src/integrations/adapters/slack.ts +8 -7
- package/corpus/core/src/integrations/adapters/telegram.ts +9 -11
- package/corpus/core/src/integrations/adapters/whatsapp.ts +12 -9
- package/corpus/core/src/integrations/plugin.ts +79 -13
- package/corpus/core/src/onboarding/default-steps.ts +6 -3
- package/corpus/core/src/onboarding/types.ts +1 -1
- package/corpus/core/src/org/handlers.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +4 -7
- package/corpus/core/src/server/better-auth-instance.ts +19 -62
- package/corpus/core/src/server/core-routes-plugin.ts +93 -180
- package/corpus/core/src/server/create-server.ts +55 -116
- package/corpus/core/src/server/email-actions.ts +3 -6
- package/corpus/core/src/server/email.ts +52 -17
- package/corpus/core/src/server/index.ts +2 -1
- package/corpus/core/src/server/scoped-key-storage.ts +223 -0
- package/corpus/core/src/shared/agent-env.ts +3 -3
- package/corpus/core/src/sharing/actions/share-resource.ts +1 -1
- package/corpus/core/src/styles/agent-native.css +55 -3
- package/corpus/core/src/templates/workspace-root/AGENTS.md +3 -2
- package/corpus/core/src/templates/workspace-root/README.md +1 -1
- package/corpus/core/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/terminal/pty-server.ts +3 -38
- package/corpus/core/src/triggers/dispatcher.ts +1 -2
- package/corpus/templates/.retired/issues/package.json +7 -0
- package/corpus/templates/.retired/meeting-notes/package.json +7 -0
- package/corpus/templates/.retired/recruiting/package.json +7 -0
- package/corpus/templates/.retired/scheduling/package.json +7 -0
- package/corpus/templates/.retired/voice/package.json +7 -0
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +0 -17
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +7 -1
- package/corpus/templates/analytics/app/i18n-data.ts +71 -2
- package/corpus/templates/analytics/app/pages/Settings.tsx +120 -73
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +0 -11
- package/corpus/templates/analytics/app/routes/catalog.tsx +33 -176
- package/corpus/templates/analytics/app/routes/team.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-06-26-dashboard-templates-are-tucked-into-settings-and-show-simple.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-sessions-page-shows-a-single-page-title-instead-of-repea.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +37 -28
- package/corpus/templates/assets/app/routes/settings.tsx +65 -43
- package/corpus/templates/assets/app/routes/team.tsx +2 -10
- package/corpus/templates/brain/app/routes/settings.tsx +390 -358
- package/corpus/templates/brain/app/routes/team.tsx +2 -8
- package/corpus/templates/calendar/actions/db-connect.ts +5 -29
- package/corpus/templates/calendar/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +4 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/calendar/app/pages/Settings.tsx +304 -271
- package/corpus/templates/calendar/app/routes/_app.team.tsx +2 -17
- package/corpus/templates/calendar/server/handlers/google-auth.ts +22 -9
- package/corpus/templates/calendar/server/lib/booking-emails.ts +1 -1
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +1 -1
- package/corpus/templates/calendar/server/lib/google-calendar.ts +48 -28
- package/corpus/templates/chat/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/chat/app/routes/settings.tsx +54 -54
- package/corpus/templates/chat/app/routes/team.tsx +2 -10
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +7 -2
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +8 -0
- package/corpus/templates/clips/actions/invite-member.ts +1 -1
- package/corpus/templates/clips/actions/request-transcript.ts +1 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +629 -643
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +219 -155
- package/corpus/templates/clips/changelog/2026-06-26-long-desktop-recordings-are-checkpointed-so-macos-finalizati.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-non-mac-desktop-recordings-wait-for-upload-transcription.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-s3-compatible-storage-keys-now-save-securely-from-clips-sett.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-shared-clip-links-guide-agents-through-processing-transcripts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-clip-details-sidebar-now-collapses-into-a-slide-out-pane.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-clips-library-now-matches-the-shared-recessed-shell-styl.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +55 -3
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +217 -5
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +176 -5
- package/corpus/templates/clips/server/lib/public-agent-context.ts +31 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +60 -14
- package/corpus/templates/clips/server/lib/video-storage.ts +37 -9
- package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +5 -0
- package/corpus/templates/content/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +54 -55
- package/corpus/templates/content/app/routes/_app.team.tsx +2 -28
- package/corpus/templates/content/server/lib/notion.ts +43 -11
- package/corpus/templates/content/server/routes/api/notion/auth-url.get.ts +2 -2
- package/corpus/templates/content/server/routes/api/notion/status.get.ts +3 -3
- package/corpus/templates/design/app/routes/settings.tsx +60 -38
- package/corpus/templates/design/app/routes/team.tsx +2 -10
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/dispatch/app/routes/settings.tsx +70 -55
- package/corpus/templates/dispatch/app/routes/team.tsx +5 -1
- package/corpus/templates/forms/actions/db-connect.ts +7 -36
- package/corpus/templates/forms/actions/navigate.ts +2 -2
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +8 -47
- package/corpus/templates/forms/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/forms/app/components/layout/Layout.tsx +42 -25
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -76
- package/corpus/templates/forms/app/global.css +9 -25
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +4 -4
- package/corpus/templates/forms/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +1 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/forms/app/lib/route-prewarm.ts +9 -8
- package/corpus/templates/forms/app/pages/AskPage.tsx +70 -0
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +74 -81
- package/corpus/templates/forms/app/root.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.ask.tsx +14 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +54 -54
- package/corpus/templates/forms/app/routes/_app.team.tsx +2 -9
- package/corpus/templates/forms/app/routes/_index.tsx +21 -130
- package/corpus/templates/forms/changelog/2026-06-26-ask-forms-opens-as-a-standard-app-tab-with-a-simpler-sidebar.md +6 -0
- package/corpus/templates/forms/changelog/2026-06-26-forms-are-shown-in-a-tighter-row-list-with-a-denser-sidebar.md +6 -0
- package/corpus/templates/forms/shared/navigation.ts +4 -2
- package/corpus/templates/macros/app/routes/settings.tsx +54 -54
- package/corpus/templates/macros/app/routes/team.tsx +2 -10
- package/corpus/templates/mail/actions/helpers.ts +2 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +5 -5
- package/corpus/templates/mail/app/routes/team.tsx +3 -2
- package/corpus/templates/mail/server/handlers/emails.ts +3 -2
- package/corpus/templates/mail/server/handlers/google-auth.ts +19 -12
- package/corpus/templates/mail/server/lib/automation-engine.ts +3 -2
- package/corpus/templates/mail/server/lib/email-state.ts +2 -3
- package/corpus/templates/mail/server/lib/google-auth.ts +28 -11
- package/corpus/templates/mail/server/lib/jobs.ts +3 -2
- package/corpus/templates/mail/server/onboarding.ts +9 -6
- package/corpus/templates/mail/server/routes/api/attachments.get.ts +3 -3
- package/corpus/templates/plan/actions/request-plan-access.ts +1 -1
- package/corpus/templates/plan/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/plan/app/lib/route-prewarm.ts +0 -4
- package/corpus/templates/plan/app/routes/settings.tsx +75 -73
- package/corpus/templates/plan/app/routes/team.tsx +2 -8
- package/corpus/templates/plan/server/lib/comment-notifications.ts +1 -1
- package/corpus/templates/slides/actions/check-image-gen.ts +2 -1
- package/corpus/templates/slides/actions/db-connect.ts +7 -45
- package/corpus/templates/slides/actions/edit-image.ts +6 -3
- package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
- package/corpus/templates/slides/actions/generate-image.ts +2 -2
- package/corpus/templates/slides/actions/generate-slides-ai.ts +5 -3
- package/corpus/templates/slides/actions/image-gen-status.ts +4 -3
- package/corpus/templates/slides/actions/image-search.ts +6 -3
- package/corpus/templates/slides/actions/search-images.ts +6 -3
- package/corpus/templates/slides/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/slides/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/slides/app/routes/settings.tsx +54 -54
- package/corpus/templates/slides/app/routes/team.tsx +2 -12
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +9 -9
- package/corpus/templates/slides/server/handlers/image-gen.ts +5 -1
- package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +9 -1
- package/corpus/templates/slides/server/handlers/image-providers/index.ts +18 -8
- package/corpus/templates/slides/server/handlers/image-providers/openai.ts +10 -4
- package/corpus/templates/slides/server/handlers/image-providers/types.ts +1 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +59 -34
- package/corpus/templates/slides/server/register-secrets.ts +60 -0
- package/corpus/templates/videos/actions/db-connect.ts +7 -45
- package/corpus/templates/videos/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/videos/app/components/Sidebar.tsx +1 -9
- package/corpus/templates/videos/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -3
- package/corpus/templates/videos/app/routes/settings.tsx +54 -54
- package/corpus/templates/videos/app/routes/team.tsx +2 -8
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +8 -3
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +3 -4
- package/dist/cli/mcp.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +6 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +1 -0
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +3 -3
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +6 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +2 -2
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +27 -0
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -0
- package/dist/client/settings/SettingsTabsPage.js +108 -0
- package/dist/client/settings/SettingsTabsPage.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/index.d.ts +1 -1
- package/dist/file-upload/index.d.ts.map +1 -1
- package/dist/file-upload/index.js +1 -1
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/registry.d.ts +1 -0
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +24 -6
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/file-upload/types.d.ts +6 -1
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +18 -18
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +8 -7
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +9 -9
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +10 -9
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +47 -13
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +6 -5
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/types.d.ts +1 -1
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/onboarding/types.js.map +1 -1
- package/dist/org/handlers.js +1 -1
- package/dist/org/handlers.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +4 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +17 -56
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +67 -153
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts +3 -9
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +37 -91
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/email-actions.d.ts +2 -3
- package/dist/server/email-actions.d.ts.map +1 -1
- package/dist/server/email-actions.js +3 -6
- package/dist/server/email-actions.js.map +1 -1
- package/dist/server/email.d.ts +3 -3
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +40 -19
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/scoped-key-storage.d.ts +22 -0
- package/dist/server/scoped-key-storage.d.ts.map +1 -0
- package/dist/server/scoped-key-storage.js +152 -0
- package/dist/server/scoped-key-storage.js.map +1 -0
- package/dist/shared/agent-env.d.ts +3 -3
- package/dist/shared/agent-env.d.ts.map +1 -1
- package/dist/shared/agent-env.js +3 -3
- package/dist/shared/agent-env.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +1 -1
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/styles/agent-native.css +55 -3
- package/dist/templates/workspace-root/AGENTS.md +3 -2
- package/dist/templates/workspace-root/README.md +1 -1
- package/dist/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +3 -36
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/triggers/dispatcher.js +1 -1
- package/dist/triggers/dispatcher.js.map +1 -1
- package/docs/content/file-uploads.md +11 -4
- package/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/docs/content/multi-app-workspace.md +3 -3
- package/docs/content/template-clips.md +14 -5
- package/package.json +1 -1
- package/src/templates/workspace-root/AGENTS.md +3 -2
- package/src/templates/workspace-root/README.md +1 -1
- package/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/server/env-var-writes.ts +0 -16
- package/corpus/templates/analytics/app/pages/Team.tsx +0 -9
- package/corpus/templates/calendar/app/pages/Team.tsx +0 -12
- package/corpus/templates/mail/app/pages/Team.tsx +0 -17
- package/dist/server/env-var-writes.d.ts +0 -10
- package/dist/server/env-var-writes.d.ts.map +0 -1
- package/dist/server/env-var-writes.js +0 -18
- package/dist/server/env-var-writes.js.map +0 -1
|
@@ -55,6 +55,8 @@
|
|
|
55
55
|
--agent-native-lower-surface: hsl(
|
|
56
56
|
var(--sidebar-background, var(--background))
|
|
57
57
|
);
|
|
58
|
+
--agent-native-raised-surface: hsl(var(--background));
|
|
59
|
+
--agent-native-card-surface: hsl(var(--card));
|
|
58
60
|
--agent-native-raised-border: hsl(var(--border));
|
|
59
61
|
--agent-native-raised-radius: 8px;
|
|
60
62
|
--agent-native-raised-shadow-left: -1px 0 3px rgb(0 0 0 / 0.018);
|
|
@@ -86,6 +88,16 @@
|
|
|
86
88
|
hsl(var(--sidebar-background, var(--background))) 94%,
|
|
87
89
|
black
|
|
88
90
|
);
|
|
91
|
+
--agent-native-raised-surface: color-mix(
|
|
92
|
+
in srgb,
|
|
93
|
+
hsl(var(--background)) 78%,
|
|
94
|
+
hsl(var(--muted)) 22%
|
|
95
|
+
);
|
|
96
|
+
--agent-native-card-surface: color-mix(
|
|
97
|
+
in srgb,
|
|
98
|
+
var(--agent-native-raised-surface) 88%,
|
|
99
|
+
hsl(var(--muted)) 12%
|
|
100
|
+
);
|
|
89
101
|
}
|
|
90
102
|
}
|
|
91
103
|
|
|
@@ -107,6 +119,13 @@
|
|
|
107
119
|
border-inline-end-color: transparent !important;
|
|
108
120
|
}
|
|
109
121
|
|
|
122
|
+
.agent-layout-shell
|
|
123
|
+
.agent-layout-left-drawer
|
|
124
|
+
> :where(.border-e, .border-r):first-child {
|
|
125
|
+
border-inline-end-color: transparent !important;
|
|
126
|
+
border-right-color: transparent !important;
|
|
127
|
+
}
|
|
128
|
+
|
|
110
129
|
.agent-sidebar-panel > .agent-sidebar-panel-inner {
|
|
111
130
|
background: inherit;
|
|
112
131
|
}
|
|
@@ -119,26 +138,59 @@
|
|
|
119
138
|
.agent-sidebar-main-surface {
|
|
120
139
|
position: relative;
|
|
121
140
|
z-index: 1;
|
|
122
|
-
background:
|
|
141
|
+
background: var(--agent-native-raised-surface);
|
|
123
142
|
transition:
|
|
124
143
|
border-radius 260ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
144
|
+
border-color 260ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
125
145
|
box-shadow 260ms cubic-bezier(0.32, 0.72, 0, 1);
|
|
126
146
|
}
|
|
127
147
|
|
|
128
148
|
.agent-layout-shell
|
|
129
149
|
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
130
150
|
> :first-child
|
|
131
|
-
> :where(header, div).border-b
|
|
151
|
+
> :where(header, div).border-b,
|
|
132
152
|
.agent-layout-shell
|
|
133
153
|
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
134
|
-
> :where(header, div).border-b
|
|
154
|
+
> :where(header, div).border-b,
|
|
135
155
|
.agent-layout-shell
|
|
136
156
|
.agent-layout-left-drawer
|
|
137
157
|
> :where(header, div).border-b:first-child,
|
|
158
|
+
.agent-layout-shell
|
|
159
|
+
.agent-layout-left-drawer
|
|
160
|
+
> :first-child
|
|
161
|
+
> :where(header, div).border-b,
|
|
138
162
|
.agent-layout-shell .agent-native-shell-topbar {
|
|
139
163
|
border-bottom-color: transparent !important;
|
|
140
164
|
}
|
|
141
165
|
|
|
166
|
+
.agent-layout-shell
|
|
167
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
168
|
+
> :first-child
|
|
169
|
+
> :where(header, div).border-b,
|
|
170
|
+
.agent-layout-shell
|
|
171
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
172
|
+
> :where(header, div).border-b {
|
|
173
|
+
background-color: var(--agent-native-raised-surface) !important;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.agent-layout-shell
|
|
177
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
178
|
+
> :first-child
|
|
179
|
+
> :where(header, div).border-b.h-12,
|
|
180
|
+
.agent-layout-shell
|
|
181
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
182
|
+
> :where(header, div).border-b.h-12 {
|
|
183
|
+
min-height: 4rem;
|
|
184
|
+
height: 4rem;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.dark
|
|
188
|
+
.agent-layout-shell
|
|
189
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
190
|
+
:where(.bg-card) {
|
|
191
|
+
background-color: var(--agent-native-card-surface) !important;
|
|
192
|
+
}
|
|
193
|
+
|
|
142
194
|
@media (min-width: 768px) {
|
|
143
195
|
.agent-layout-main-surface,
|
|
144
196
|
.agent-layout-shell > .agent-sidebar-shell > .agent-sidebar-main-surface {
|
|
@@ -170,7 +170,8 @@ Use the workspace root `.env` for shared identity and cross-app trust settings:
|
|
|
170
170
|
- `WORKSPACE_OWNER_EMAIL` — initial owner/admin email for repairs and
|
|
171
171
|
integration defaults.
|
|
172
172
|
- `A2A_SECRET` — shared secret for cross-app A2A signing. Generate with
|
|
173
|
-
`openssl rand -hex 32`
|
|
173
|
+
`openssl rand -hex 32` and configure through your deployment/scoped secret
|
|
174
|
+
manager.
|
|
174
175
|
|
|
175
176
|
`DISPATCH_DEFAULT_OWNER_EMAIL` is optional. Set it only for trusted,
|
|
176
177
|
single-workspace deployments where unlinked integration requests should run as
|
|
@@ -183,7 +184,7 @@ When asked to repair workspace org or A2A configuration:
|
|
|
183
184
|
1. Read `.env` first. Do not infer the organization, domain, owner email, or
|
|
184
185
|
secret from old examples.
|
|
185
186
|
2. Run `pnpm repair:workspace-org -- --name "<org>" --domain example.com --owner-email owner@example.com`
|
|
186
|
-
to
|
|
187
|
+
to validate generic workspace identity values without writing `.env`.
|
|
187
188
|
3. Prefer the app's organization settings UI or authenticated org routes for
|
|
188
189
|
changing `allowed_domain` and `a2a_secret`.
|
|
189
190
|
4. If direct SQL is unavoidable, inspect the live schema first and use only
|
|
@@ -97,7 +97,7 @@ cross-app trust:
|
|
|
97
97
|
- `A2A_SECRET` — shared signing secret for cross-app A2A calls.
|
|
98
98
|
|
|
99
99
|
Run `pnpm repair:workspace-org -- --name "<org>" --domain example.com --owner-email owner@example.com`
|
|
100
|
-
to
|
|
100
|
+
to validate those values without writing env files. Existing
|
|
101
101
|
organization rows should still be repaired through the app's org settings UI or
|
|
102
102
|
authenticated org routes whenever possible.
|
|
103
103
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
|
|
3
|
-
import crypto from "node:crypto";
|
|
4
3
|
import fs from "node:fs";
|
|
5
4
|
import path from "node:path";
|
|
6
5
|
|
|
@@ -10,8 +9,6 @@ interface Options {
|
|
|
10
9
|
ownerEmail?: string;
|
|
11
10
|
a2aSecret?: string;
|
|
12
11
|
envPath: string;
|
|
13
|
-
force: boolean;
|
|
14
|
-
dryRun: boolean;
|
|
15
12
|
setDispatchDefaultOwner: boolean;
|
|
16
13
|
}
|
|
17
14
|
|
|
@@ -22,10 +19,10 @@ Options:
|
|
|
22
19
|
--name <value> Sets WORKSPACE_ORG_NAME
|
|
23
20
|
--domain <value> Sets WORKSPACE_ORG_DOMAIN
|
|
24
21
|
--owner-email <value> Sets WORKSPACE_OWNER_EMAIL
|
|
25
|
-
--a2a-secret <value>
|
|
26
|
-
--env <path> Env file to
|
|
27
|
-
--force
|
|
28
|
-
--dry-run
|
|
22
|
+
--a2a-secret <value> Reads A2A_SECRET for validation
|
|
23
|
+
--env <path> Env file to read for fallback values (default: .env)
|
|
24
|
+
--force Accepted for compatibility; no file is written
|
|
25
|
+
--dry-run Accepted for compatibility; no file is written
|
|
29
26
|
--set-dispatch-default-owner Also set DISPATCH_DEFAULT_OWNER_EMAIL
|
|
30
27
|
`;
|
|
31
28
|
|
|
@@ -41,8 +38,6 @@ type RequiredKey = (typeof REQUIRED_KEYS)[number];
|
|
|
41
38
|
function parseArgs(argv: string[]): Options {
|
|
42
39
|
const opts: Options = {
|
|
43
40
|
envPath: ".env",
|
|
44
|
-
force: false,
|
|
45
|
-
dryRun: false,
|
|
46
41
|
setDispatchDefaultOwner: false,
|
|
47
42
|
};
|
|
48
43
|
|
|
@@ -78,10 +73,8 @@ function parseArgs(argv: string[]): Options {
|
|
|
78
73
|
opts.envPath = value();
|
|
79
74
|
break;
|
|
80
75
|
case "--force":
|
|
81
|
-
opts.force = true;
|
|
82
76
|
break;
|
|
83
77
|
case "--dry-run":
|
|
84
|
-
opts.dryRun = true;
|
|
85
78
|
break;
|
|
86
79
|
case "--set-dispatch-default-owner":
|
|
87
80
|
opts.setDispatchDefaultOwner = true;
|
|
@@ -147,47 +140,6 @@ function validateEmail(email: string): void {
|
|
|
147
140
|
}
|
|
148
141
|
}
|
|
149
142
|
|
|
150
|
-
function formatEnvValue(value: string): string {
|
|
151
|
-
if (/^[A-Za-z0-9_@./:+-]+$/.test(value)) return value;
|
|
152
|
-
return JSON.stringify(value);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function upsertEnvValue(
|
|
156
|
-
content: string,
|
|
157
|
-
key: string,
|
|
158
|
-
value: string,
|
|
159
|
-
force: boolean,
|
|
160
|
-
): { content: string; changed: boolean; skipped: boolean } {
|
|
161
|
-
const lines = content.length > 0 ? content.split(/\r?\n/) : [];
|
|
162
|
-
let found = false;
|
|
163
|
-
let changed = false;
|
|
164
|
-
let skipped = false;
|
|
165
|
-
|
|
166
|
-
const next = lines.map((line) => {
|
|
167
|
-
const match = line.match(/^(\s*)([A-Z0-9_]+)(\s*=\s*)(.*)$/);
|
|
168
|
-
if (!match || match[2] !== key) return line;
|
|
169
|
-
|
|
170
|
-
found = true;
|
|
171
|
-
const existing = unquote(match[4]);
|
|
172
|
-
if (existing && !force) {
|
|
173
|
-
skipped = true;
|
|
174
|
-
return line;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const replacement = `${match[1]}${key}${match[3]}${formatEnvValue(value)}`;
|
|
178
|
-
if (replacement !== line) changed = true;
|
|
179
|
-
return replacement;
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
if (!found) {
|
|
183
|
-
if (next.length > 0 && next[next.length - 1] !== "") next.push("");
|
|
184
|
-
next.push(`${key}=${formatEnvValue(value)}`);
|
|
185
|
-
changed = true;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return { content: next.join("\n"), changed, skipped };
|
|
189
|
-
}
|
|
190
|
-
|
|
191
143
|
function firstValue(...values: Array<string | undefined>): string | undefined {
|
|
192
144
|
return values.map((v) => v?.trim()).find(Boolean);
|
|
193
145
|
}
|
|
@@ -213,13 +165,21 @@ function main(): void {
|
|
|
213
165
|
process.env.WORKSPACE_OWNER_EMAIL,
|
|
214
166
|
current.WORKSPACE_OWNER_EMAIL,
|
|
215
167
|
)?.toLowerCase();
|
|
216
|
-
const a2aSecret =
|
|
217
|
-
|
|
218
|
-
|
|
168
|
+
const a2aSecret = firstValue(
|
|
169
|
+
opts.a2aSecret,
|
|
170
|
+
process.env.A2A_SECRET,
|
|
171
|
+
current.A2A_SECRET,
|
|
172
|
+
);
|
|
219
173
|
|
|
220
174
|
if (!name) fail("--name or WORKSPACE_ORG_NAME is required.");
|
|
221
175
|
if (!rawDomain) fail("--domain or WORKSPACE_ORG_DOMAIN is required.");
|
|
222
176
|
if (!ownerEmail) fail("--owner-email or WORKSPACE_OWNER_EMAIL is required.");
|
|
177
|
+
if (!a2aSecret) {
|
|
178
|
+
fail(
|
|
179
|
+
"--a2a-secret or A2A_SECRET is required. This script reads existing " +
|
|
180
|
+
"configuration but does not write env files.",
|
|
181
|
+
);
|
|
182
|
+
}
|
|
223
183
|
|
|
224
184
|
const domain = normalizeDomain(rawDomain);
|
|
225
185
|
validateDomain(domain);
|
|
@@ -232,52 +192,31 @@ function main(): void {
|
|
|
232
192
|
A2A_SECRET: a2aSecret,
|
|
233
193
|
};
|
|
234
194
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
for (const key of REQUIRED_KEYS) {
|
|
240
|
-
const result = upsertEnvValue(next, key, desired[key], opts.force);
|
|
241
|
-
next = result.content;
|
|
242
|
-
if (result.changed) changed.push(key);
|
|
243
|
-
if (result.skipped) skipped.push(key);
|
|
244
|
-
}
|
|
245
|
-
|
|
195
|
+
const displayEntries: Array<[string, string]> = REQUIRED_KEYS.map((key) => [
|
|
196
|
+
key,
|
|
197
|
+
key === "A2A_SECRET" ? "[configured]" : desired[key],
|
|
198
|
+
]);
|
|
246
199
|
if (opts.setDispatchDefaultOwner) {
|
|
247
|
-
|
|
248
|
-
next,
|
|
249
|
-
"DISPATCH_DEFAULT_OWNER_EMAIL",
|
|
250
|
-
ownerEmail,
|
|
251
|
-
opts.force,
|
|
252
|
-
);
|
|
253
|
-
next = result.content;
|
|
254
|
-
if (result.changed) changed.push("DISPATCH_DEFAULT_OWNER_EMAIL");
|
|
255
|
-
if (result.skipped) skipped.push("DISPATCH_DEFAULT_OWNER_EMAIL");
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
next = next.trimEnd() + "\n";
|
|
259
|
-
|
|
260
|
-
if (opts.dryRun) {
|
|
261
|
-
console.log(next);
|
|
262
|
-
} else {
|
|
263
|
-
fs.writeFileSync(envPath, next);
|
|
200
|
+
displayEntries.push(["DISPATCH_DEFAULT_OWNER_EMAIL", ownerEmail]);
|
|
264
201
|
}
|
|
265
202
|
|
|
266
203
|
console.log(
|
|
267
|
-
|
|
204
|
+
`Validated workspace org settings from ${path.relative(process.cwd(), envPath) || envPath}.`,
|
|
268
205
|
);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
);
|
|
206
|
+
console.log("No env files were written.");
|
|
207
|
+
console.log("");
|
|
208
|
+
console.log("Resolved configuration:");
|
|
209
|
+
for (const [key, value] of displayEntries) {
|
|
210
|
+
console.log(`- ${key}: ${value}`);
|
|
274
211
|
}
|
|
275
212
|
console.log("");
|
|
276
213
|
console.log("Next steps:");
|
|
277
214
|
console.log("1. Sign in as WORKSPACE_OWNER_EMAIL.");
|
|
278
215
|
console.log("2. Create or select the org named by WORKSPACE_ORG_NAME.");
|
|
279
216
|
console.log("3. Set the org allowed domain to WORKSPACE_ORG_DOMAIN.");
|
|
280
|
-
console.log(
|
|
217
|
+
console.log(
|
|
218
|
+
"4. Configure A2A_SECRET through the scoped secret/deployment secret manager for apps that need cross-app A2A.",
|
|
219
|
+
);
|
|
281
220
|
}
|
|
282
221
|
|
|
283
222
|
main();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-server.d.ts","sourceRoot":"","sources":["../../src/terminal/pty-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,MAAM,IAAI,UAAU,EAC1B,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"pty-server.d.ts","sourceRoot":"","sources":["../../src/terminal/pty-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,MAAM,IAAI,UAAU,EAC1B,MAAM,MAAM,CAAC;AAmFd,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA4Q1B"}
|
|
@@ -18,13 +18,6 @@ async function getChildProcess() {
|
|
|
18
18
|
}
|
|
19
19
|
return _cp;
|
|
20
20
|
}
|
|
21
|
-
let _fs;
|
|
22
|
-
async function getFs() {
|
|
23
|
-
if (!_fs) {
|
|
24
|
-
_fs = await import("node:fs");
|
|
25
|
-
}
|
|
26
|
-
return _fs;
|
|
27
|
-
}
|
|
28
21
|
/**
|
|
29
22
|
* Kill a process and all its descendants.
|
|
30
23
|
* node-pty's kill() only sends a signal to the shell, but child processes
|
|
@@ -241,9 +234,9 @@ export async function createPtyWebSocketServer(options = {}) {
|
|
|
241
234
|
const msg = JSON.parse(str);
|
|
242
235
|
if (msg.type === "agentNative.setEnvVars" &&
|
|
243
236
|
Array.isArray(msg.data?.vars)) {
|
|
244
|
-
const envPath = path.join(resolvedAppDir, ".env");
|
|
245
237
|
const vars = msg.data.vars;
|
|
246
|
-
//
|
|
238
|
+
// Legacy bridge message. Keep validating the keys, but do not persist
|
|
239
|
+
// them to .env or process.env; key storage is DB-scoped.
|
|
247
240
|
const validKeyPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
248
241
|
const sanitizedVars = vars.filter(({ key }) => {
|
|
249
242
|
if (!validKeyPattern.test(key)) {
|
|
@@ -252,37 +245,11 @@ export async function createPtyWebSocketServer(options = {}) {
|
|
|
252
245
|
}
|
|
253
246
|
return true;
|
|
254
247
|
});
|
|
255
|
-
const fs = await getFs();
|
|
256
|
-
let lines = [];
|
|
257
|
-
try {
|
|
258
|
-
lines = fs.readFileSync(envPath, "utf-8").split("\n");
|
|
259
|
-
}
|
|
260
|
-
catch { }
|
|
261
|
-
for (const { key, value } of sanitizedVars) {
|
|
262
|
-
// Strip newlines/null bytes to prevent line injection
|
|
263
|
-
const safeValue = value.replace(/[\r\n\0]/g, "");
|
|
264
|
-
// Quote values containing #, spaces, or quotes so dotenv parses correctly
|
|
265
|
-
const needsQuoting = /[# "']/.test(safeValue);
|
|
266
|
-
const quotedValue = needsQuoting
|
|
267
|
-
? `"${safeValue.replace(/"/g, '\\"')}"`
|
|
268
|
-
: safeValue;
|
|
269
|
-
const idx = lines.findIndex((l) => l.startsWith(`${key}=`));
|
|
270
|
-
const entry = `${key}=${quotedValue}`;
|
|
271
|
-
if (idx !== -1) {
|
|
272
|
-
lines[idx] = entry;
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
lines.push(entry);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
while (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
279
|
-
lines.pop();
|
|
280
|
-
}
|
|
281
|
-
fs.writeFileSync(envPath, lines.join("\n") + "\n", "utf-8");
|
|
282
248
|
if (ws.readyState === WebSocket.OPEN) {
|
|
283
249
|
ws.send(JSON.stringify({
|
|
284
250
|
type: "env-vars-saved",
|
|
285
251
|
keys: sanitizedVars.map((v) => v.key),
|
|
252
|
+
storage: "scoped-secrets",
|
|
286
253
|
}));
|
|
287
254
|
}
|
|
288
255
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-server.js","sourceRoot":"","sources":["../../src/terminal/pty-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PTY WebSocket Server\n *\n * Creates an HTTP server with WebSocket support that spawns PTY processes\n * for AI CLI tools. Each WebSocket connection gets its own PTY.\n *\n * Used by both the embedded AgentTerminal component and the CLI frame.\n */\n\nimport {\n createServer as createHttpServer,\n type IncomingMessage,\n type Server as HttpServer,\n} from \"http\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport {\n CLI_REGISTRY,\n commandExists,\n isAllowedCommand,\n} from \"./cli-registry.js\";\n\n// Lazy singletons for Node-only modules (only available in Node.js)\nlet _cp: typeof import(\"child_process\") | undefined;\nasync function getChildProcess(): Promise<typeof import(\"child_process\")> {\n if (!_cp) {\n _cp = await import(\"node:child_process\");\n }\n return _cp;\n}\n\nlet _fs: typeof import(\"fs\") | undefined;\nasync function getFs(): Promise<typeof import(\"fs\")> {\n if (!_fs) {\n _fs = await import(\"node:fs\");\n }\n return _fs;\n}\n\n/**\n * Kill a process and all its descendants.\n * node-pty's kill() only sends a signal to the shell, but child processes\n * (like `builder`) may be in their own process group and survive as orphans.\n */\nasync function killProcessTree(pid: number, _logPrefix: string): Promise<void> {\n const cp = await getChildProcess();\n\n if (os.platform() === \"win32\") {\n try {\n cp.execSync(`taskkill /pid ${pid} /T /F`, { stdio: \"ignore\" });\n } catch {}\n return;\n }\n\n // Find all descendant PIDs (children, grandchildren, etc.)\n const descendants: number[] = [];\n function findDescendants(parentPid: number) {\n try {\n const output = cp\n .execSync(`pgrep -P ${parentPid}`, {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n })\n .trim();\n if (output) {\n for (const line of output.split(\"\\n\")) {\n const childPid = parseInt(line, 10);\n if (childPid && !isNaN(childPid)) {\n descendants.push(childPid);\n findDescendants(childPid);\n }\n }\n }\n } catch {\n // pgrep returns non-zero when no children found\n }\n }\n findDescendants(pid);\n\n // Kill descendants first (deepest first), then the parent\n for (const childPid of descendants.reverse()) {\n try {\n process.kill(childPid, \"SIGTERM\");\n } catch {}\n }\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {}\n\n // Force-kill any survivors after a short delay\n setTimeout(() => {\n for (const childPid of descendants) {\n try {\n process.kill(childPid, \"SIGKILL\");\n } catch {}\n }\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {}\n }, 500);\n}\n\nexport interface PtyServerOptions {\n /** Working directory for PTY processes. Defaults to process.cwd() */\n appDir?: string;\n /** Default CLI command. Defaults to 'claude' */\n command?: string;\n /** Port to listen on. Defaults to 0 (random available port) */\n port?: number;\n /** Auth check for WebSocket upgrade requests. Return false to reject. */\n authCheck?: (req: IncomingMessage) => boolean | Promise<boolean>;\n /** Log prefix for console output. Defaults to '[terminal]' */\n logPrefix?: string;\n}\n\nexport interface PtyServerResult {\n /** The underlying HTTP server */\n server: HttpServer;\n /** The actual port the server is listening on */\n port: number;\n /** Shut down the server and kill all PTY processes */\n close: () => void;\n}\n\nexport async function createPtyWebSocketServer(\n options: PtyServerOptions = {},\n): Promise<PtyServerResult> {\n const {\n appDir = process.cwd(),\n command: defaultCommand = \"claude\",\n port = 0,\n authCheck,\n logPrefix = \"[terminal]\",\n } = options;\n\n // Dynamic imports for optional native dependencies\n const { WebSocketServer, WebSocket } = await import(\"ws\");\n const pty = await import(\"node-pty\");\n\n const resolvedAppDir = path.resolve(appDir);\n const shell =\n os.platform() === \"win32\" ? \"cmd.exe\" : process.env.SHELL || \"/bin/zsh\";\n\n const server = createHttpServer((req, res) => {\n // CORS headers\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n const wss = new WebSocketServer({ noServer: true });\n\n // Handle WebSocket upgrades with optional auth\n server.on(\"upgrade\", async (req, socket, head) => {\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n if (url.pathname !== \"/ws\") {\n socket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n if (authCheck) {\n try {\n const allowed = await authCheck(req);\n if (!allowed) {\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n } catch {\n socket.write(\"HTTP/1.1 500 Internal Server Error\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n });\n\n // Track active PTY processes for cleanup\n const activePtys = new Set<ReturnType<typeof pty.spawn>>();\n\n wss.on(\"connection\", async (ws: InstanceType<typeof WebSocket>, req) => {\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const command = url.searchParams.get(\"command\") || defaultCommand;\n const extraFlags = url.searchParams.get(\"flags\") || \"\";\n console.log(`${logPrefix} WebSocket connected for command: ${command}`);\n\n const sendStatus = (status: string, message: string) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"setup-status\", status, message }));\n }\n };\n\n // Validate command against allowlist to prevent injection\n if (!isAllowedCommand(command)) {\n sendStatus(\n \"not-found\",\n `\"${command}\" is not a recognized CLI. Allowed: ${Object.keys(CLI_REGISTRY).join(\", \")}`,\n );\n if (ws.readyState === WebSocket.OPEN) ws.close();\n return;\n }\n\n // Reject flags containing shell metacharacters\n if (extraFlags && /[;&|`$(){}\\n\\r<>]/.test(extraFlags)) {\n sendStatus(\"failed\", \"Invalid flags: shell metacharacters not allowed\");\n if (ws.readyState === WebSocket.OPEN) ws.close();\n return;\n }\n\n // Check if CLI is installed; if not, use npx to run it\n let useNpx = false;\n if (!(await commandExists(command))) {\n const registry = CLI_REGISTRY[command];\n if (registry?.installPackage) {\n console.log(`${logPrefix} ${command} CLI not found, will use npx`);\n useNpx = true;\n } else {\n sendStatus(\n \"not-found\",\n `\"${command}\" not found on PATH. Please install it manually.`,\n );\n if (ws.readyState === WebSocket.OPEN) ws.close();\n return;\n }\n }\n\n // Build the command — use npx if CLI not found locally\n const baseCommand = useNpx\n ? `npx --yes ${CLI_REGISTRY[command].installPackage}`\n : command;\n const fullCommand = extraFlags\n ? `${baseCommand} ${extraFlags}`\n : baseCommand;\n console.log(`${logPrefix} Spawning PTY: ${fullCommand}`);\n\n // Build env, stripping CLI-specific nesting vars\n const registry = CLI_REGISTRY[command];\n const env: Record<string, string | undefined> = {\n ...process.env,\n TERM: \"xterm-256color\",\n };\n if (registry) {\n for (const v of registry.stripEnv) delete env[v];\n }\n\n let ptyProcess: ReturnType<typeof pty.spawn>;\n try {\n ptyProcess = pty.spawn(shell, [\"-l\", \"-c\", fullCommand], {\n name: \"xterm-256color\",\n cols: 120,\n rows: 40,\n cwd: resolvedAppDir,\n env: env as Record<string, string>,\n });\n } catch (err) {\n console.error(`${logPrefix} Failed to spawn PTY:`, err);\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(\n `\\r\\n\\x1b[31m${logPrefix} Failed to spawn PTY: ${err}\\x1b[0m\\r\\n`,\n );\n ws.close();\n }\n return;\n }\n\n activePtys.add(ptyProcess);\n console.log(`${logPrefix} PTY spawned (pid: ${ptyProcess.pid})`);\n\n ptyProcess.onData((data: string) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(data);\n }\n });\n\n ptyProcess.onExit(({ exitCode }) => {\n console.log(`${logPrefix} PTY exited with code ${exitCode}`);\n activePtys.delete(ptyProcess);\n if (exitCode === 127 && ws.readyState === WebSocket.OPEN) {\n ws.send(\n JSON.stringify({\n type: \"setup-status\",\n status: \"not-found\",\n message: `Command \"${command}\" not found. Please install it first.`,\n }),\n );\n }\n if (ws.readyState === WebSocket.OPEN) {\n ws.close();\n }\n });\n\n ws.on(\"message\", async (data: Buffer | string) => {\n const str = typeof data === \"string\" ? data : data.toString();\n\n try {\n const msg = JSON.parse(str);\n\n if (\n msg.type === \"agentNative.setEnvVars\" &&\n Array.isArray(msg.data?.vars)\n ) {\n const envPath = path.join(resolvedAppDir, \".env\");\n const vars: Array<{ key: string; value: string }> = msg.data.vars;\n\n // Validate env var names and sanitize values\n const validKeyPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\n const sanitizedVars = vars.filter(({ key }) => {\n if (!validKeyPattern.test(key)) {\n console.warn(`${logPrefix} Rejected invalid env var key: ${key}`);\n return false;\n }\n return true;\n });\n\n const fs = await getFs();\n let lines: string[] = [];\n try {\n lines = fs.readFileSync(envPath, \"utf-8\").split(\"\\n\");\n } catch {}\n\n for (const { key, value } of sanitizedVars) {\n // Strip newlines/null bytes to prevent line injection\n const safeValue = value.replace(/[\\r\\n\\0]/g, \"\");\n // Quote values containing #, spaces, or quotes so dotenv parses correctly\n const needsQuoting = /[# \"']/.test(safeValue);\n const quotedValue = needsQuoting\n ? `\"${safeValue.replace(/\"/g, '\\\\\"')}\"`\n : safeValue;\n const idx = lines.findIndex((l) => l.startsWith(`${key}=`));\n const entry = `${key}=${quotedValue}`;\n if (idx !== -1) {\n lines[idx] = entry;\n } else {\n lines.push(entry);\n }\n }\n\n while (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n fs.writeFileSync(envPath, lines.join(\"\\n\") + \"\\n\", \"utf-8\");\n\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(\n JSON.stringify({\n type: \"env-vars-saved\",\n keys: sanitizedVars.map((v) => v.key),\n }),\n );\n }\n return;\n }\n\n if (msg.type === \"resize\" && msg.cols != null && msg.rows != null) {\n const cols = Math.max(\n 1,\n Math.min(65535, Math.trunc(Number(msg.cols))),\n );\n const rows = Math.max(\n 1,\n Math.min(65535, Math.trunc(Number(msg.rows))),\n );\n if (!Number.isFinite(cols) || !Number.isFinite(rows)) return;\n ptyProcess.resize(cols, rows);\n return;\n }\n } catch {\n // Not JSON — regular terminal input\n }\n\n ptyProcess.write(str);\n });\n\n ws.on(\"close\", () => {\n console.log(\n `${logPrefix} WebSocket closed, killing PTY tree (pid: ${ptyProcess.pid})`,\n );\n activePtys.delete(ptyProcess);\n killProcessTree(ptyProcess.pid, logPrefix);\n });\n });\n\n return new Promise((resolve, reject) => {\n server.once(\"error\", (err) => {\n reject(err);\n });\n server.listen(port, \"127.0.0.1\", () => {\n const addr = server.address();\n const actualPort = typeof addr === \"object\" && addr ? addr.port : port;\n if (process.env.DEBUG)\n console.log(\n `${logPrefix} PTY WebSocket server on ws://localhost:${actualPort}/ws`,\n );\n\n resolve({\n server,\n port: actualPort,\n close: () => {\n for (const p of activePtys) {\n killProcessTree(p.pid, logPrefix);\n }\n activePtys.clear();\n wss.close();\n server.close();\n },\n });\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pty-server.js","sourceRoot":"","sources":["../../src/terminal/pty-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,IAAI,gBAAgB,GAGjC,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,oEAAoE;AACpE,IAAI,GAA+C,CAAC;AACpD,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,UAAkB;IAC5D,MAAM,EAAE,GAAG,MAAM,eAAe,EAAE,CAAC;IAEnC,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,EAAE,CAAC,QAAQ,CAAC,iBAAiB,GAAG,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,OAAO;IACT,CAAC;IAED,2DAA2D;IAC3D,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,SAAS,eAAe,CAAC,SAAiB;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,EAAE;iBACd,QAAQ,CAAC,YAAY,SAAS,EAAE,EAAE;gBACjC,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;aAClC,CAAC;iBACD,IAAI,EAAE,CAAC;YACV,IAAI,MAAM,EAAE,CAAC;gBACX,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACpC,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACjC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC3B,eAAe,CAAC,QAAQ,CAAC,CAAC;oBAC5B,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;QAClD,CAAC;IACH,CAAC;IACD,eAAe,CAAC,GAAG,CAAC,CAAC;IAErB,0DAA0D;IAC1D,KAAK,MAAM,QAAQ,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,+CAA+C;IAC/C,UAAU,CAAC,GAAG,EAAE;QACd,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC;AAwBD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAO,GAAqB,EAAE;IAE9B,MAAM,EACJ,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,EACtB,OAAO,EAAE,cAAc,GAAG,QAAQ,EAClC,IAAI,GAAG,CAAC,EACR,SAAS,EACT,SAAS,GAAG,YAAY,GACzB,GAAG,OAAO,CAAC;IAEZ,mDAAmD;IACnD,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAErC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,KAAK,GACT,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,UAAU,CAAC;IAE1E,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3C,eAAe;QACf,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;QACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;QAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpD,+CAA+C;IAC/C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC/C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAC/C,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;oBAClD,MAAM,CAAC,OAAO,EAAE,CAAC;oBACjB,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;gBAC3D,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;QACH,CAAC;QAED,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;YAC1C,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,yCAAyC;IACzC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE3D,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,EAAkC,EAAE,GAAG,EAAE,EAAE;QACrE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACjE,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,cAAc,CAAC;QAClE,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,qCAAqC,OAAO,EAAE,CAAC,CAAC;QAExE,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,OAAe,EAAE,EAAE;YACrD,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACrC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC,CAAC;QAEF,0DAA0D;QAC1D,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,UAAU,CACR,WAAW,EACX,IAAI,OAAO,uCAAuC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;YACF,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;gBAAE,EAAE,CAAC,KAAK,EAAE,CAAC;YACjD,OAAO;QACT,CAAC;QAED,+CAA+C;QAC/C,IAAI,UAAU,IAAI,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACvD,UAAU,CAAC,QAAQ,EAAE,iDAAiD,CAAC,CAAC;YACxE,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;gBAAE,EAAE,CAAC,KAAK,EAAE,CAAC;YACjD,OAAO;QACT,CAAC;QAED,uDAAuD;QACvD,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,CAAC,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,QAAQ,EAAE,cAAc,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,IAAI,OAAO,8BAA8B,CAAC,CAAC;gBACnE,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,UAAU,CACR,WAAW,EACX,IAAI,OAAO,kDAAkD,CAC9D,CAAC;gBACF,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;oBAAE,EAAE,CAAC,KAAK,EAAE,CAAC;gBACjD,OAAO;YACT,CAAC;QACH,CAAC;QAED,uDAAuD;QACvD,MAAM,WAAW,GAAG,MAAM;YACxB,CAAC,CAAC,aAAa,YAAY,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE;YACrD,CAAC,CAAC,OAAO,CAAC;QACZ,MAAM,WAAW,GAAG,UAAU;YAC5B,CAAC,CAAC,GAAG,WAAW,IAAI,UAAU,EAAE;YAChC,CAAC,CAAC,WAAW,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,kBAAkB,WAAW,EAAE,CAAC,CAAC;QAEzD,iDAAiD;QACjD,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,GAAG,GAAuC;YAC9C,GAAG,OAAO,CAAC,GAAG;YACd,IAAI,EAAE,gBAAgB;SACvB,CAAC;QACF,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ;gBAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,UAAwC,CAAC;QAC7C,IAAI,CAAC;YACH,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE;gBACvD,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,GAAG;gBACT,IAAI,EAAE,EAAE;gBACR,GAAG,EAAE,cAAc;gBACnB,GAAG,EAAE,GAA6B;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,SAAS,uBAAuB,EAAE,GAAG,CAAC,CAAC;YACxD,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACrC,EAAE,CAAC,IAAI,CACL,eAAe,SAAS,yBAAyB,GAAG,aAAa,CAClE,CAAC;gBACF,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,CAAC;YACD,OAAO;QACT,CAAC;QAED,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,sBAAsB,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC;QAEjE,UAAU,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;YACjC,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACrC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACjC,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,yBAAyB,QAAQ,EAAE,CAAC,CAAC;YAC7D,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC9B,IAAI,QAAQ,KAAK,GAAG,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACzD,EAAE,CAAC,IAAI,CACL,IAAI,CAAC,SAAS,CAAC;oBACb,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,WAAW;oBACnB,OAAO,EAAE,YAAY,OAAO,uCAAuC;iBACpE,CAAC,CACH,CAAC;YACJ,CAAC;YACD,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACrC,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,IAAqB,EAAE,EAAE;YAC/C,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAE9D,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAE5B,IACE,GAAG,CAAC,IAAI,KAAK,wBAAwB;oBACrC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAC7B,CAAC;oBACD,MAAM,IAAI,GAA0C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;oBAElE,sEAAsE;oBACtE,yDAAyD;oBACzD,MAAM,eAAe,GAAG,0BAA0B,CAAC;oBACnD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;wBAC5C,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;4BAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,kCAAkC,GAAG,EAAE,CAAC,CAAC;4BAClE,OAAO,KAAK,CAAC;wBACf,CAAC;wBACD,OAAO,IAAI,CAAC;oBACd,CAAC,CAAC,CAAC;oBAEH,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;wBACrC,EAAE,CAAC,IAAI,CACL,IAAI,CAAC,SAAS,CAAC;4BACb,IAAI,EAAE,gBAAgB;4BACtB,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;4BACrC,OAAO,EAAE,gBAAgB;yBAC1B,CAAC,CACH,CAAC;oBACJ,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;oBAClE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAC9C,CAAC;oBACF,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAC9C,CAAC;oBACF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;wBAAE,OAAO;oBAC7D,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC9B,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;YAED,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAClB,OAAO,CAAC,GAAG,CACT,GAAG,SAAS,6CAA6C,UAAU,CAAC,GAAG,GAAG,CAC3E,CAAC;YACF,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC9B,eAAe,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;YACpC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACvE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;gBACnB,OAAO,CAAC,GAAG,CACT,GAAG,SAAS,2CAA2C,UAAU,KAAK,CACvE,CAAC;YAEJ,OAAO,CAAC;gBACN,MAAM;gBACN,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,GAAG,EAAE;oBACV,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;wBAC3B,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;oBACpC,CAAC;oBACD,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,GAAG,CAAC,KAAK,EAAE,CAAC;oBACZ,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,CAAC;aACF,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * PTY WebSocket Server\n *\n * Creates an HTTP server with WebSocket support that spawns PTY processes\n * for AI CLI tools. Each WebSocket connection gets its own PTY.\n *\n * Used by both the embedded AgentTerminal component and the CLI frame.\n */\n\nimport {\n createServer as createHttpServer,\n type IncomingMessage,\n type Server as HttpServer,\n} from \"http\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport {\n CLI_REGISTRY,\n commandExists,\n isAllowedCommand,\n} from \"./cli-registry.js\";\n\n// Lazy singletons for Node-only modules (only available in Node.js)\nlet _cp: typeof import(\"child_process\") | undefined;\nasync function getChildProcess(): Promise<typeof import(\"child_process\")> {\n if (!_cp) {\n _cp = await import(\"node:child_process\");\n }\n return _cp;\n}\n\n/**\n * Kill a process and all its descendants.\n * node-pty's kill() only sends a signal to the shell, but child processes\n * (like `builder`) may be in their own process group and survive as orphans.\n */\nasync function killProcessTree(pid: number, _logPrefix: string): Promise<void> {\n const cp = await getChildProcess();\n\n if (os.platform() === \"win32\") {\n try {\n cp.execSync(`taskkill /pid ${pid} /T /F`, { stdio: \"ignore\" });\n } catch {}\n return;\n }\n\n // Find all descendant PIDs (children, grandchildren, etc.)\n const descendants: number[] = [];\n function findDescendants(parentPid: number) {\n try {\n const output = cp\n .execSync(`pgrep -P ${parentPid}`, {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n })\n .trim();\n if (output) {\n for (const line of output.split(\"\\n\")) {\n const childPid = parseInt(line, 10);\n if (childPid && !isNaN(childPid)) {\n descendants.push(childPid);\n findDescendants(childPid);\n }\n }\n }\n } catch {\n // pgrep returns non-zero when no children found\n }\n }\n findDescendants(pid);\n\n // Kill descendants first (deepest first), then the parent\n for (const childPid of descendants.reverse()) {\n try {\n process.kill(childPid, \"SIGTERM\");\n } catch {}\n }\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {}\n\n // Force-kill any survivors after a short delay\n setTimeout(() => {\n for (const childPid of descendants) {\n try {\n process.kill(childPid, \"SIGKILL\");\n } catch {}\n }\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {}\n }, 500);\n}\n\nexport interface PtyServerOptions {\n /** Working directory for PTY processes. Defaults to process.cwd() */\n appDir?: string;\n /** Default CLI command. Defaults to 'claude' */\n command?: string;\n /** Port to listen on. Defaults to 0 (random available port) */\n port?: number;\n /** Auth check for WebSocket upgrade requests. Return false to reject. */\n authCheck?: (req: IncomingMessage) => boolean | Promise<boolean>;\n /** Log prefix for console output. Defaults to '[terminal]' */\n logPrefix?: string;\n}\n\nexport interface PtyServerResult {\n /** The underlying HTTP server */\n server: HttpServer;\n /** The actual port the server is listening on */\n port: number;\n /** Shut down the server and kill all PTY processes */\n close: () => void;\n}\n\nexport async function createPtyWebSocketServer(\n options: PtyServerOptions = {},\n): Promise<PtyServerResult> {\n const {\n appDir = process.cwd(),\n command: defaultCommand = \"claude\",\n port = 0,\n authCheck,\n logPrefix = \"[terminal]\",\n } = options;\n\n // Dynamic imports for optional native dependencies\n const { WebSocketServer, WebSocket } = await import(\"ws\");\n const pty = await import(\"node-pty\");\n\n const resolvedAppDir = path.resolve(appDir);\n const shell =\n os.platform() === \"win32\" ? \"cmd.exe\" : process.env.SHELL || \"/bin/zsh\";\n\n const server = createHttpServer((req, res) => {\n // CORS headers\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n const wss = new WebSocketServer({ noServer: true });\n\n // Handle WebSocket upgrades with optional auth\n server.on(\"upgrade\", async (req, socket, head) => {\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n if (url.pathname !== \"/ws\") {\n socket.write(\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n if (authCheck) {\n try {\n const allowed = await authCheck(req);\n if (!allowed) {\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n } catch {\n socket.write(\"HTTP/1.1 500 Internal Server Error\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n });\n\n // Track active PTY processes for cleanup\n const activePtys = new Set<ReturnType<typeof pty.spawn>>();\n\n wss.on(\"connection\", async (ws: InstanceType<typeof WebSocket>, req) => {\n const url = new URL(req.url || \"\", `http://${req.headers.host}`);\n const command = url.searchParams.get(\"command\") || defaultCommand;\n const extraFlags = url.searchParams.get(\"flags\") || \"\";\n console.log(`${logPrefix} WebSocket connected for command: ${command}`);\n\n const sendStatus = (status: string, message: string) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"setup-status\", status, message }));\n }\n };\n\n // Validate command against allowlist to prevent injection\n if (!isAllowedCommand(command)) {\n sendStatus(\n \"not-found\",\n `\"${command}\" is not a recognized CLI. Allowed: ${Object.keys(CLI_REGISTRY).join(\", \")}`,\n );\n if (ws.readyState === WebSocket.OPEN) ws.close();\n return;\n }\n\n // Reject flags containing shell metacharacters\n if (extraFlags && /[;&|`$(){}\\n\\r<>]/.test(extraFlags)) {\n sendStatus(\"failed\", \"Invalid flags: shell metacharacters not allowed\");\n if (ws.readyState === WebSocket.OPEN) ws.close();\n return;\n }\n\n // Check if CLI is installed; if not, use npx to run it\n let useNpx = false;\n if (!(await commandExists(command))) {\n const registry = CLI_REGISTRY[command];\n if (registry?.installPackage) {\n console.log(`${logPrefix} ${command} CLI not found, will use npx`);\n useNpx = true;\n } else {\n sendStatus(\n \"not-found\",\n `\"${command}\" not found on PATH. Please install it manually.`,\n );\n if (ws.readyState === WebSocket.OPEN) ws.close();\n return;\n }\n }\n\n // Build the command — use npx if CLI not found locally\n const baseCommand = useNpx\n ? `npx --yes ${CLI_REGISTRY[command].installPackage}`\n : command;\n const fullCommand = extraFlags\n ? `${baseCommand} ${extraFlags}`\n : baseCommand;\n console.log(`${logPrefix} Spawning PTY: ${fullCommand}`);\n\n // Build env, stripping CLI-specific nesting vars\n const registry = CLI_REGISTRY[command];\n const env: Record<string, string | undefined> = {\n ...process.env,\n TERM: \"xterm-256color\",\n };\n if (registry) {\n for (const v of registry.stripEnv) delete env[v];\n }\n\n let ptyProcess: ReturnType<typeof pty.spawn>;\n try {\n ptyProcess = pty.spawn(shell, [\"-l\", \"-c\", fullCommand], {\n name: \"xterm-256color\",\n cols: 120,\n rows: 40,\n cwd: resolvedAppDir,\n env: env as Record<string, string>,\n });\n } catch (err) {\n console.error(`${logPrefix} Failed to spawn PTY:`, err);\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(\n `\\r\\n\\x1b[31m${logPrefix} Failed to spawn PTY: ${err}\\x1b[0m\\r\\n`,\n );\n ws.close();\n }\n return;\n }\n\n activePtys.add(ptyProcess);\n console.log(`${logPrefix} PTY spawned (pid: ${ptyProcess.pid})`);\n\n ptyProcess.onData((data: string) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(data);\n }\n });\n\n ptyProcess.onExit(({ exitCode }) => {\n console.log(`${logPrefix} PTY exited with code ${exitCode}`);\n activePtys.delete(ptyProcess);\n if (exitCode === 127 && ws.readyState === WebSocket.OPEN) {\n ws.send(\n JSON.stringify({\n type: \"setup-status\",\n status: \"not-found\",\n message: `Command \"${command}\" not found. Please install it first.`,\n }),\n );\n }\n if (ws.readyState === WebSocket.OPEN) {\n ws.close();\n }\n });\n\n ws.on(\"message\", async (data: Buffer | string) => {\n const str = typeof data === \"string\" ? data : data.toString();\n\n try {\n const msg = JSON.parse(str);\n\n if (\n msg.type === \"agentNative.setEnvVars\" &&\n Array.isArray(msg.data?.vars)\n ) {\n const vars: Array<{ key: string; value: string }> = msg.data.vars;\n\n // Legacy bridge message. Keep validating the keys, but do not persist\n // them to .env or process.env; key storage is DB-scoped.\n const validKeyPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\n const sanitizedVars = vars.filter(({ key }) => {\n if (!validKeyPattern.test(key)) {\n console.warn(`${logPrefix} Rejected invalid env var key: ${key}`);\n return false;\n }\n return true;\n });\n\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(\n JSON.stringify({\n type: \"env-vars-saved\",\n keys: sanitizedVars.map((v) => v.key),\n storage: \"scoped-secrets\",\n }),\n );\n }\n return;\n }\n\n if (msg.type === \"resize\" && msg.cols != null && msg.rows != null) {\n const cols = Math.max(\n 1,\n Math.min(65535, Math.trunc(Number(msg.cols))),\n );\n const rows = Math.max(\n 1,\n Math.min(65535, Math.trunc(Number(msg.rows))),\n );\n if (!Number.isFinite(cols) || !Number.isFinite(rows)) return;\n ptyProcess.resize(cols, rows);\n return;\n }\n } catch {\n // Not JSON — regular terminal input\n }\n\n ptyProcess.write(str);\n });\n\n ws.on(\"close\", () => {\n console.log(\n `${logPrefix} WebSocket closed, killing PTY tree (pid: ${ptyProcess.pid})`,\n );\n activePtys.delete(ptyProcess);\n killProcessTree(ptyProcess.pid, logPrefix);\n });\n });\n\n return new Promise((resolve, reject) => {\n server.once(\"error\", (err) => {\n reject(err);\n });\n server.listen(port, \"127.0.0.1\", () => {\n const addr = server.address();\n const actualPort = typeof addr === \"object\" && addr ? addr.port : port;\n if (process.env.DEBUG)\n console.log(\n `${logPrefix} PTY WebSocket server on ws://localhost:${actualPort}/ws`,\n );\n\n resolve({\n server,\n port: actualPort,\n close: () => {\n for (const p of activePtys) {\n killProcessTree(p.pid, logPrefix);\n }\n activePtys.clear();\n wss.close();\n server.close();\n },\n });\n });\n });\n}\n"]}
|
|
@@ -209,7 +209,7 @@ async function handleEvent(eventName, payload, eventMeta) {
|
|
|
209
209
|
// Resolve API key for condition evaluation
|
|
210
210
|
const owner = meta.createdBy || resource.owner;
|
|
211
211
|
const userApiKey = await getOwnerActiveApiKey(owner);
|
|
212
|
-
const apiKey = userApiKey || _deps.apiKey
|
|
212
|
+
const apiKey = userApiKey || _deps.apiKey;
|
|
213
213
|
if (!apiKey) {
|
|
214
214
|
console.warn(`[triggers] No API key for trigger "${resource.path}" — skipping`);
|
|
215
215
|
continue;
|