From 4a8cec9dc21407301482d2389727af2a9499549d Mon Sep 17 00:00:00 2001 From: 777genius Date: Mon, 18 May 2026 01:54:05 +0300 Subject: [PATCH] chore: checkpoint frontend workspace updates --- .github/workflows/release.yml | 96 +- .gitignore | 1 + electron.vite.config.ts | 50 +- landing/assets/styles/cyberpunk-hero.scss | 12 +- .../components/common/RobotSpeechBubble.vue | 99 ++ .../components/hero/CyberHeroFeatureStrip.vue | 6 +- landing/components/layout/AppFooter.vue | 65 +- .../components/sections/ComparisonSection.vue | 58 +- .../components/sections/DownloadSection.vue | 65 +- scripts/ci/verify-sentry-release.cjs | 131 ++ .../main/composition/runtimeSupport.ts | 2 +- src/features/tmux-installer/main/index.ts | 2 +- src/main/ipc/cliInstaller.ts | 32 +- src/main/ipc/handlers.ts | 3 + src/main/ipc/telemetry.ts | 24 + src/main/sentry.ts | 143 +- .../infrastructure/CliInstallerService.ts | 135 +- .../runtime/ClaudeMultimodelBridgeService.ts | 281 +++- .../runtime/ProviderConnectionService.ts | 16 +- .../services/team/TeamLaunchStateEvaluator.ts | 3 + .../team/TeamMemberRuntimeAdvisoryService.ts | 91 +- .../services/team/TeamProvisioningService.ts | 955 ++++++++++++-- .../OpenCodeManagedHostProcessCleanup.ts | 7 +- .../OpenCodeRuntimeDeliveryAdvisoryPolicy.ts | 9 + .../OpenCodeRuntimeDeliveryDiagnostics.ts | 17 +- .../runtime/RuntimeDiagnosticClassifier.ts | 3 + src/preload/constants/ipcChannels.ts | 7 + src/preload/index.ts | 4 + src/renderer/api/httpClient.ts | 3 + .../components/dashboard/CliStatusBanner.tsx | 11 +- .../settings/sections/CliStatusSection.tsx | 21 +- .../components/sidebar/GlobalTaskList.tsx | 94 ++ .../components/sidebar/SidebarTaskItem.tsx | 6 +- .../components/team/TeamChangesSection.tsx | 29 +- .../components/team/TeamDetailView.tsx | 44 +- .../useTeamChangesSummaries.test.tsx | 142 ++ .../ProvisioningProviderStatusList.tsx | 19 + .../team/dialogs/TeamModelSelector.tsx | 75 +- .../dialogs/providerPrepareDiagnostics.ts | 24 + .../team/members/CurrentTaskIndicator.tsx | 6 +- .../components/team/members/MemberCard.tsx | 548 +++++++- .../components/team/members/MemberList.tsx | 187 ++- .../team/messages/MessagesPanel.tsx | 4 +- .../team/review/ScopeWarningBanner.tsx | 16 +- src/renderer/components/ui/SyncedLoader2.tsx | 6 +- src/renderer/main.tsx | 2 +- src/renderer/sentry.ts | 108 +- .../store/slices/cliInstallerSlice.ts | 171 ++- src/renderer/store/slices/teamSlice.ts | 58 +- src/renderer/utils/memberHelpers.ts | 77 +- src/renderer/utils/memberLaunchDiagnostics.ts | 51 +- src/renderer/utils/memberRuntimeSummary.ts | 3 + src/renderer/vendor/radixComposeRefs.ts | 73 + src/shared/types/api.ts | 14 + src/shared/types/cliInstaller.ts | 1 + src/shared/types/team.ts | 22 + .../utils/__tests__/sentryConfig.test.ts | 41 + src/shared/utils/sentryConfig.ts | 93 +- test/main/ipc/cliInstaller.test.ts | 175 +++ test/main/sentry.test.ts | 83 ++ .../CliInstallerService.test.ts | 101 +- .../ClaudeMultimodelBridgeService.test.ts | 879 ++++++++++++- .../runtime/ProviderConnectionService.test.ts | 66 + ...OpenCodeRuntimeDeliveryDiagnostics.test.ts | 34 + .../team/RuntimeDiagnosticClassifier.test.ts | 14 + .../TeamMemberRuntimeAdvisoryService.test.ts | 101 ++ .../team/TeamProvisioningService.test.ts | 1171 ++++++++++++++++- .../TeamProvisioningServicePrepare.test.ts | 16 +- .../components/sidebar/GlobalTaskList.test.ts | 41 +- .../sidebar/SidebarTaskItem.test.ts | 20 + .../TeamModelSelectorDisabledState.test.ts | 57 + .../ProvisioningProviderStatusList.test.ts | 36 + .../providerPrepareDiagnostics.test.ts | 55 + .../team/members/CurrentTaskIndicator.test.ts | 25 + .../team/members/MemberCard.test.ts | 330 ++++- .../team/messages/MessagesPanel.test.ts | 30 +- .../team/review/ScopeWarningBanner.test.ts | 18 + .../ui/DialogContentFocusScope.test.tsx | 40 +- test/renderer/store/cliInstallerSlice.test.ts | 259 +++- test/renderer/store/teamSlice.test.ts | 96 ++ test/renderer/utils/memberHelpers.test.ts | 25 + .../utils/memberLaunchDiagnostics.test.ts | 24 + test/setup.ts | 3 +- vitest.config.ts | 4 + 84 files changed, 7300 insertions(+), 669 deletions(-) create mode 100644 landing/components/common/RobotSpeechBubble.vue create mode 100644 scripts/ci/verify-sentry-release.cjs create mode 100644 src/main/ipc/telemetry.ts create mode 100644 src/renderer/vendor/radixComposeRefs.ts create mode 100644 src/shared/utils/__tests__/sentryConfig.test.ts create mode 100644 test/main/ipc/cliInstaller.test.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d64a1bcc..c27ee080 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,14 +42,32 @@ jobs: VERSION="${GITHUB_REF#refs/tags/v}" pnpm pkg set version="$VERSION" + - name: Verify Sentry release env + if: startsWith(github.ref, 'refs/tags/v') + env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs prebuild + - name: Build app env: NODE_OPTIONS: '--max-old-space-size=8192' + SENTRY_DSN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_DSN || '' }} + SENTRY_AUTH_TOKEN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_AUTH_TOKEN || '' }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: pnpm build + + - name: Verify Sentry source map upload + if: startsWith(github.ref, 'refs/tags/v') + env: SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: quant-jump-pro - SENTRY_PROJECT: electron - run: pnpm build + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs postbuild - name: Create GitHub Release if: startsWith(github.ref, 'refs/tags/v') @@ -282,14 +300,32 @@ jobs: node ./scripts/stage-runtime.mjs --platform "darwin-${{ matrix.arch }}" fi + - name: Verify Sentry release env (macOS ${{ matrix.arch }}) + if: startsWith(github.ref, 'refs/tags/v') + env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs prebuild + - name: Build app (macOS ${{ matrix.arch }}) env: NODE_OPTIONS: '--max-old-space-size=8192' + SENTRY_DSN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_DSN || '' }} + SENTRY_AUTH_TOKEN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_AUTH_TOKEN || '' }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: pnpm build + + - name: Verify Sentry source map upload (macOS ${{ matrix.arch }}) + if: startsWith(github.ref, 'refs/tags/v') + env: SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: quant-jump-pro - SENTRY_PROJECT: electron - run: pnpm build + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs postbuild - name: Verify packaged inputs (macOS ${{ matrix.arch }}) run: | @@ -381,14 +417,32 @@ jobs: node ./scripts/stage-runtime.mjs --platform win32-x64 } + - name: Verify Sentry release env (Windows) + if: startsWith(github.ref, 'refs/tags/v') + env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs prebuild + - name: Build app (Windows) env: NODE_OPTIONS: '--max-old-space-size=8192' + SENTRY_DSN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_DSN || '' }} + SENTRY_AUTH_TOKEN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_AUTH_TOKEN || '' }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: pnpm build + + - name: Verify Sentry source map upload (Windows) + if: startsWith(github.ref, 'refs/tags/v') + env: SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: quant-jump-pro - SENTRY_PROJECT: electron - run: pnpm build + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs postbuild - name: Verify packaged inputs (Windows) shell: bash @@ -483,14 +537,32 @@ jobs: node ./scripts/stage-runtime.mjs --platform linux-x64 fi + - name: Verify Sentry release env (Linux) + if: startsWith(github.ref, 'refs/tags/v') + env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs prebuild + - name: Build app (Linux) env: NODE_OPTIONS: '--max-old-space-size=8192' + SENTRY_DSN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_DSN || '' }} + SENTRY_AUTH_TOKEN: ${{ startsWith(github.ref, 'refs/tags/v') && secrets.SENTRY_AUTH_TOKEN || '' }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: pnpm build + + - name: Verify Sentry source map upload (Linux) + if: startsWith(github.ref, 'refs/tags/v') + env: SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: quant-jump-pro - SENTRY_PROJECT: electron - run: pnpm build + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + run: node ./scripts/ci/verify-sentry-release.cjs postbuild - name: Verify packaged inputs (Linux) run: | diff --git a/.gitignore b/.gitignore index c0876432..16f34a19 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,4 @@ remotion/* # Local reference captures /agent-teams-reference-fix-*.png +/.tmp-* diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 9b69acad..1c6486c5 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -44,30 +44,42 @@ function nativeModuleStub(): Plugin { } } -// Sentry source map upload — only active in CI when SENTRY_AUTH_TOKEN is set. -const sentryPlugins = process.env.SENTRY_AUTH_TOKEN - ? [ - sentryVitePlugin({ - org: process.env.SENTRY_ORG ?? 'quant-jump-pro', - project: process.env.SENTRY_PROJECT ?? 'electron', - authToken: process.env.SENTRY_AUTH_TOKEN, - release: { name: `agent-teams-ai@${pkg.version}` }, - sourcemaps: { - filesToDeleteAfterUpload: ['./out/renderer/**/*.map', './dist-electron/**/*.map'], - }, - }), - ] - : [] +const sentrySourceMapTargets = { + main: { + assets: ['./dist-electron/main/**/*.{js,cjs,mjs,map}'], + filesToDeleteAfterUpload: ['./dist-electron/main/**/*.map'], + }, + renderer: { + assets: ['./out/renderer/**/*.{js,cjs,mjs,map}'], + filesToDeleteAfterUpload: ['./out/renderer/**/*.map'], + }, +} as const + +// Sentry source map upload - only active in CI when SENTRY_AUTH_TOKEN is set. +function createSentryPlugins(target: keyof typeof sentrySourceMapTargets): Plugin[] { + if (!process.env.SENTRY_AUTH_TOKEN) return [] + + return [ + sentryVitePlugin({ + org: process.env.SENTRY_ORG ?? 'quant-jump-pro', + project: process.env.SENTRY_PROJECT ?? 'electron', + authToken: process.env.SENTRY_AUTH_TOKEN, + telemetry: false, + release: { name: `agent-teams-ai@${pkg.version}` }, + sourcemaps: sentrySourceMapTargets[target], + }) as Plugin, + ] +} export default defineConfig({ main: { plugins: [ nativeModuleStub(), - ...sentryPlugins, + ...createSentryPlugins('main'), ], define: { __APP_VERSION__: JSON.stringify(pkg.version), - // Inject DSN at compile time — process.env.SENTRY_DSN is NOT available + // Inject DSN at compile time - process.env.SENTRY_DSN is NOT available // at runtime in packaged Electron apps (only during CI build). 'process.env.SENTRY_DSN': JSON.stringify(process.env.SENTRY_DSN ?? ''), }, @@ -148,10 +160,14 @@ export default defineConfig({ '@renderer': resolve(__dirname, 'src/renderer'), '@shared': resolve(__dirname, 'src/shared'), '@main': resolve(__dirname, 'src/main'), + '@radix-ui/react-compose-refs': resolve( + __dirname, + 'src/renderer/vendor/radixComposeRefs.ts' + ), '@claude-teams/agent-graph': resolve(__dirname, 'packages/agent-graph/src/index.ts') } }, - plugins: [react(), ...sentryPlugins], + plugins: [react(), ...createSentryPlugins('renderer')], build: { sourcemap: 'hidden', rollupOptions: { diff --git a/landing/assets/styles/cyberpunk-hero.scss b/landing/assets/styles/cyberpunk-hero.scss index 41b6bdf0..cc3ebccd 100644 --- a/landing/assets/styles/cyberpunk-hero.scss +++ b/landing/assets/styles/cyberpunk-hero.scss @@ -1259,17 +1259,17 @@ .cyber-feature-rail__reviewer-bubble { --reviewer-bubble-center-shift: 3px; + --robot-bubble-position: absolute; + --robot-bubble-min-width: 112px; + --robot-bubble-max-width: 184px; + --robot-bubble-min-height: 46px; + --robot-bubble-font-size: 0.64rem; + --robot-bubble-padding: 8px 14px 16px; left: auto; top: auto; right: calc(var(--reviewer-robot-width) / 2); bottom: calc(100% + 10px); - z-index: 6; - width: max-content; - max-width: 158px; - white-space: normal; - overflow-wrap: anywhere; - text-wrap: balance; transform: translateX(calc(50% + var(--reviewer-bubble-center-shift))) translate3d(0, 0, 0) rotate(-4deg); transform-origin: center bottom; animation: cyberFeatureReviewerSpeechFloat 2.8s ease-in-out 0.45s infinite; diff --git a/landing/components/common/RobotSpeechBubble.vue b/landing/components/common/RobotSpeechBubble.vue new file mode 100644 index 00000000..f8974ab5 --- /dev/null +++ b/landing/components/common/RobotSpeechBubble.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/landing/components/hero/CyberHeroFeatureStrip.vue b/landing/components/hero/CyberHeroFeatureStrip.vue index f29ca237..33e75cd5 100644 --- a/landing/components/hero/CyberHeroFeatureStrip.vue +++ b/landing/components/hero/CyberHeroFeatureStrip.vue @@ -67,13 +67,13 @@ const reviewerBubbleText = computed(() => { aria-hidden="true" > - {{ reviewerBubbleText }} - +
{{ heroReviewerFeatureCard.label }}
diff --git a/landing/components/layout/AppFooter.vue b/landing/components/layout/AppFooter.vue index 17222bfc..396acddd 100644 --- a/landing/components/layout/AppFooter.vue +++ b/landing/components/layout/AppFooter.vue @@ -14,20 +14,9 @@ const docsHref = computed(() => {