From 3d0159f21bda77625c4978d1bc130e0a44e49bbc Mon Sep 17 00:00:00 2001 From: jtenniswood Date: Tue, 18 Aug 2026 14:11:50 +0100 Subject: [PATCH 001/103] chore(studio): import Atrium UI (filtered vendor drop) Vendor drop of the Atrium workspace UI from stacklok/enterprise-ui-prototypes @ claude/atrium-ui-updates (649bc1efb91f889e117c79f4189d8abba34c22d4), filtered before import so prototype residue never enters this repo's history. Every imported file is byte-identical to its source. Excluded at import (413 of 572 tracked files): - auth stack (better-auth/pg/OIDC), signin flow, permissions context - legacy ai-sdk assistant sidebar, /api/chat, MCP client wiring - MSW mock server, mock OIDC/registry/user-management routes, hey-api generated clients and their OpenAPI specs - Atrium demo data (features/agent/mock-data.ts, skills fixtures): Studio is daemon-only; probe failure renders offline, never demo data - disk-touching harness routes (skills/agents authoring deferred to a follow-up; transcript route superseded by the daemon transcript API) - prototype deploy/repo infra (Docker, helm, GitHub workflows, husky, renovate, pnpm lockfile/workspace) and residue tests/e2e specs The app does not build at this commit; wiring lands in the commits that follow. The complete filter manifest is recorded in the pull request. Co-Authored-By: Claude Fable 5 --- studio/.env.example | 114 + studio/.gitignore | 54 + studio/.npmrc | 2 + studio/biome.json | 85 + studio/components.json | 20 + studio/knip.ts | 46 + studio/next.config.ts | 87 + studio/package.json | 162 + studio/playwright.config.mts | 112 + studio/postcss.config.mjs | 7 + studio/public/.gitkeep | 0 studio/public/bg-pattern.png | Bin 0 -> 112926 bytes studio/public/signin-pattern.svg | 466 ++ studio/public/stacklok-favicon.png | Bin 0 -> 5699 bytes studio/public/stacklok-logo-mark.svg | 3 + studio/public/stacklok-logo.svg | 11 + studio/src/app/(authenticated)/layout.tsx | 31 + .../workspace/chat/[[...sessionId]]/page.tsx | 17 + .../chat/_components/approval-panel.tsx | 161 + .../workspace/chat/_components/chat-view.tsx | 752 ++++ .../chat/_components/chat-window.tsx | 129 + .../chat/_components/chat-workspace.tsx | 1083 +++++ .../chat/_components/clarification-panel.tsx | 99 + .../chat/_components/code-block.test.tsx | 33 + .../workspace/chat/_components/code-block.tsx | 107 + .../chat/_components/code-highlighter.test.ts | 45 + .../chat/_components/code-highlighter.ts | 145 + .../_components/context-window-indicator.tsx | 96 + .../chat/_components/file-preview.tsx | 97 + .../_components/markdown-canvas-panel.tsx | 438 ++ .../chat/_components/markdown-components.tsx | 80 + .../chat/_components/message-bubble.tsx | 325 ++ .../chat/_components/session-sidebar.tsx | 583 +++ .../workspace/chat/_components/side-panel.tsx | 162 + .../chat/_components/tool-call-list.tsx | 57 + .../workspace/chat/_data/projects.ts | 3846 +++++++++++++++++ .../app/(authenticated)/workspace/layout.tsx | 14 + .../workspace/memory/[memoryId]/page.tsx | 115 + .../(authenticated)/workspace/memory/page.tsx | 101 + .../app/(authenticated)/workspace/page.tsx | 6 + .../workspace/schedules/[scheduleId]/page.tsx | 303 ++ .../_components/create-schedule-dialog.tsx | 296 ++ .../workspace/schedules/page.tsx | 275 ++ .../workspace/settings/page.tsx | 164 + .../(authenticated)/workspace/setup/page.tsx | 10 + .../workspace/shortcuts/page.tsx | 65 + .../workspace/skills/[skillId]/page.tsx | 109 + .../(authenticated)/workspace/skills/page.tsx | 186 + .../api/harness-control/[...path]/route.ts | 99 + studio/src/app/api/harness/[...path]/route.ts | 141 + studio/src/app/brand/logo/route.test.ts | 71 + studio/src/app/brand/logo/route.ts | 30 + studio/src/app/error.tsx | 12 + studio/src/app/global-error.tsx | 40 + studio/src/app/globals.css | 354 ++ studio/src/app/icon.test.ts | 19 + studio/src/app/icon.ts | 35 + studio/src/app/layout.tsx | 58 + studio/src/app/not-found.test.tsx | 42 + studio/src/app/not-found.tsx | 43 + studio/src/app/page.tsx | 7 + studio/src/components/app/nav-items.ts | 61 + studio/src/components/app/section-tabs.tsx | 51 + studio/src/components/client-providers.tsx | 63 + .../error-page/error-page-client.test.tsx | 57 + .../error-page/error-page-client.tsx | 29 + .../components/error-page/error-page.test.tsx | 36 + .../src/components/error-page/error-page.tsx | 29 + .../illustration-empty-inbox.tsx | 50 + .../illustrations/illustration-error.tsx | 68 + .../illustration-no-search-results.tsx | 67 + studio/src/components/server-providers.tsx | 10 + .../shell/atrium-search-data.test.ts | 44 + .../components/shell/atrium-search-data.ts | 95 + studio/src/components/shell/console-shell.tsx | 52 + studio/src/components/shell/global-search.tsx | 128 + studio/src/components/shell/nav-drawer.tsx | 64 + studio/src/components/shell/nav-items.ts | 64 + studio/src/components/shell/navbar.tsx | 36 + .../components/shell/search-static.test.ts | 73 + studio/src/components/shell/search-static.ts | 66 + studio/src/components/shell/search-types.ts | 51 + studio/src/components/shell/shell.tsx | 77 + studio/src/components/shell/sidebar.tsx | 420 ++ studio/src/components/ui/alert-dialog.tsx | 140 + studio/src/components/ui/avatar.tsx | 53 + studio/src/components/ui/badge.tsx | 52 + studio/src/components/ui/button.tsx | 68 + studio/src/components/ui/card.tsx | 92 + studio/src/components/ui/checkbox.tsx | 32 + .../src/components/ui/chevron-indicator.tsx | 16 + studio/src/components/ui/click-boundary.tsx | 18 + studio/src/components/ui/command.tsx | 189 + studio/src/components/ui/dialog.tsx | 143 + studio/src/components/ui/dropdown-menu.tsx | 257 ++ studio/src/components/ui/error-boundary.tsx | 72 + studio/src/components/ui/form.tsx | 167 + studio/src/components/ui/input-search.tsx | 46 + studio/src/components/ui/input.tsx | 21 + studio/src/components/ui/label.tsx | 23 + studio/src/components/ui/pagination.tsx | 125 + studio/src/components/ui/popover.tsx | 48 + studio/src/components/ui/progress.tsx | 43 + studio/src/components/ui/scroll-area.tsx | 58 + studio/src/components/ui/select.tsx | 190 + studio/src/components/ui/separator.tsx | 28 + studio/src/components/ui/sheet.tsx | 140 + studio/src/components/ui/sidebar.tsx | 689 +++ studio/src/components/ui/skeleton.tsx | 13 + studio/src/components/ui/switch.tsx | 31 + studio/src/components/ui/table.tsx | 261 ++ studio/src/components/ui/tabs.tsx | 66 + studio/src/components/ui/textarea.tsx | 18 + studio/src/components/ui/toggle-group.tsx | 82 + studio/src/components/ui/toggle.tsx | 47 + studio/src/components/ui/tooltip.tsx | 147 + .../components/agent-provider-wrapper.tsx | 7 + .../agent/components/agent-sections.tsx | 1867 ++++++++ .../features/agent/components/coming-soon.tsx | 21 + .../agent/components/transcript-dialog.tsx | 97 + .../features/agent/composer-capabilities.ts | 55 + .../features/agent/hooks/use-agent-chat.ts | 289 ++ .../features/agent/hooks/use-agent-cron.ts | 225 + .../features/agent/hooks/use-agent-defs.ts | 155 + .../features/agent/hooks/use-agent-memory.ts | 82 + .../agent/hooks/use-agent-projects.ts | 64 + .../features/agent/hooks/use-agent-roster.ts | 15 + .../features/agent/hooks/use-agent-runs.ts | 163 + .../agent/hooks/use-agent-sessions.ts | 133 + .../features/agent/hooks/use-agent-skills.ts | 141 + .../agent/hooks/use-harness-runtime.ts | 189 + .../agent/hooks/use-refresh-on-focus.ts | 28 + studio/src/features/agent/index.ts | 36 + studio/src/features/agent/types.ts | 265 ++ studio/src/hooks/use-confirm.tsx | 87 + studio/src/hooks/use-is-truncated.ts | 61 + studio/src/hooks/use-mobile.ts | 44 + studio/src/hooks/use-nav-collapsed.ts | 44 + studio/src/hooks/use-nav-reopen-sidebar.ts | 11 + studio/src/hooks/use-prompt.tsx | 100 + studio/src/hooks/use-rail-width.ts | 61 + studio/src/hooks/use-sidebar-width.ts | 40 + studio/src/lib/api-error.ts | 26 + studio/src/lib/feature-flags.ts | 7 + studio/src/lib/formatters.ts | 82 + studio/src/lib/harness/client.ts | 1064 +++++ studio/src/lib/sanitize-url.ts | 31 + studio/src/lib/shortcuts/registry.test.ts | 78 + studio/src/lib/shortcuts/registry.ts | 158 + studio/src/lib/shortcuts/use-shortcuts.tsx | 81 + studio/src/lib/typography.ts | 16 + studio/src/lib/utils.test.ts | 68 + studio/src/lib/utils.ts | 32 + studio/src/types.ts | 8 + studio/src/types/vite.d.ts | 15 + studio/tests/e2e/chat-panels.spec.ts | 62 + studio/tsconfig.json | 37 + studio/vitest.config.mts | 42 + studio/vitest.setup.ts | 163 + 159 files changed, 23366 insertions(+) create mode 100644 studio/.env.example create mode 100644 studio/.gitignore create mode 100644 studio/.npmrc create mode 100644 studio/biome.json create mode 100644 studio/components.json create mode 100644 studio/knip.ts create mode 100644 studio/next.config.ts create mode 100644 studio/package.json create mode 100644 studio/playwright.config.mts create mode 100644 studio/postcss.config.mjs create mode 100644 studio/public/.gitkeep create mode 100644 studio/public/bg-pattern.png create mode 100644 studio/public/signin-pattern.svg create mode 100644 studio/public/stacklok-favicon.png create mode 100644 studio/public/stacklok-logo-mark.svg create mode 100644 studio/public/stacklok-logo.svg create mode 100644 studio/src/app/(authenticated)/layout.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/[[...sessionId]]/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/approval-panel.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/chat-view.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/chat-window.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/chat-workspace.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/clarification-panel.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/code-block.test.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/code-block.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/code-highlighter.test.ts create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/code-highlighter.ts create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/context-window-indicator.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/file-preview.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/markdown-canvas-panel.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/markdown-components.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/message-bubble.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/session-sidebar.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/side-panel.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_components/tool-call-list.tsx create mode 100644 studio/src/app/(authenticated)/workspace/chat/_data/projects.ts create mode 100644 studio/src/app/(authenticated)/workspace/layout.tsx create mode 100644 studio/src/app/(authenticated)/workspace/memory/[memoryId]/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/memory/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/schedules/[scheduleId]/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/schedules/_components/create-schedule-dialog.tsx create mode 100644 studio/src/app/(authenticated)/workspace/schedules/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/settings/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/setup/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/shortcuts/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/skills/[skillId]/page.tsx create mode 100644 studio/src/app/(authenticated)/workspace/skills/page.tsx create mode 100644 studio/src/app/api/harness-control/[...path]/route.ts create mode 100644 studio/src/app/api/harness/[...path]/route.ts create mode 100644 studio/src/app/brand/logo/route.test.ts create mode 100644 studio/src/app/brand/logo/route.ts create mode 100644 studio/src/app/error.tsx create mode 100644 studio/src/app/global-error.tsx create mode 100644 studio/src/app/globals.css create mode 100644 studio/src/app/icon.test.ts create mode 100644 studio/src/app/icon.ts create mode 100644 studio/src/app/layout.tsx create mode 100644 studio/src/app/not-found.test.tsx create mode 100644 studio/src/app/not-found.tsx create mode 100644 studio/src/app/page.tsx create mode 100644 studio/src/components/app/nav-items.ts create mode 100644 studio/src/components/app/section-tabs.tsx create mode 100644 studio/src/components/client-providers.tsx create mode 100644 studio/src/components/error-page/error-page-client.test.tsx create mode 100644 studio/src/components/error-page/error-page-client.tsx create mode 100644 studio/src/components/error-page/error-page.test.tsx create mode 100644 studio/src/components/error-page/error-page.tsx create mode 100644 studio/src/components/illustrations/illustration-empty-inbox.tsx create mode 100644 studio/src/components/illustrations/illustration-error.tsx create mode 100644 studio/src/components/illustrations/illustration-no-search-results.tsx create mode 100644 studio/src/components/server-providers.tsx create mode 100644 studio/src/components/shell/atrium-search-data.test.ts create mode 100644 studio/src/components/shell/atrium-search-data.ts create mode 100644 studio/src/components/shell/console-shell.tsx create mode 100644 studio/src/components/shell/global-search.tsx create mode 100644 studio/src/components/shell/nav-drawer.tsx create mode 100644 studio/src/components/shell/nav-items.ts create mode 100644 studio/src/components/shell/navbar.tsx create mode 100644 studio/src/components/shell/search-static.test.ts create mode 100644 studio/src/components/shell/search-static.ts create mode 100644 studio/src/components/shell/search-types.ts create mode 100644 studio/src/components/shell/shell.tsx create mode 100644 studio/src/components/shell/sidebar.tsx create mode 100644 studio/src/components/ui/alert-dialog.tsx create mode 100644 studio/src/components/ui/avatar.tsx create mode 100644 studio/src/components/ui/badge.tsx create mode 100644 studio/src/components/ui/button.tsx create mode 100644 studio/src/components/ui/card.tsx create mode 100644 studio/src/components/ui/checkbox.tsx create mode 100644 studio/src/components/ui/chevron-indicator.tsx create mode 100644 studio/src/components/ui/click-boundary.tsx create mode 100644 studio/src/components/ui/command.tsx create mode 100644 studio/src/components/ui/dialog.tsx create mode 100644 studio/src/components/ui/dropdown-menu.tsx create mode 100644 studio/src/components/ui/error-boundary.tsx create mode 100644 studio/src/components/ui/form.tsx create mode 100644 studio/src/components/ui/input-search.tsx create mode 100644 studio/src/components/ui/input.tsx create mode 100644 studio/src/components/ui/label.tsx create mode 100644 studio/src/components/ui/pagination.tsx create mode 100644 studio/src/components/ui/popover.tsx create mode 100644 studio/src/components/ui/progress.tsx create mode 100644 studio/src/components/ui/scroll-area.tsx create mode 100644 studio/src/components/ui/select.tsx create mode 100644 studio/src/components/ui/separator.tsx create mode 100644 studio/src/components/ui/sheet.tsx create mode 100644 studio/src/components/ui/sidebar.tsx create mode 100644 studio/src/components/ui/skeleton.tsx create mode 100644 studio/src/components/ui/switch.tsx create mode 100644 studio/src/components/ui/table.tsx create mode 100644 studio/src/components/ui/tabs.tsx create mode 100644 studio/src/components/ui/textarea.tsx create mode 100644 studio/src/components/ui/toggle-group.tsx create mode 100644 studio/src/components/ui/toggle.tsx create mode 100644 studio/src/components/ui/tooltip.tsx create mode 100644 studio/src/features/agent/components/agent-provider-wrapper.tsx create mode 100644 studio/src/features/agent/components/agent-sections.tsx create mode 100644 studio/src/features/agent/components/coming-soon.tsx create mode 100644 studio/src/features/agent/components/transcript-dialog.tsx create mode 100644 studio/src/features/agent/composer-capabilities.ts create mode 100644 studio/src/features/agent/hooks/use-agent-chat.ts create mode 100644 studio/src/features/agent/hooks/use-agent-cron.ts create mode 100644 studio/src/features/agent/hooks/use-agent-defs.ts create mode 100644 studio/src/features/agent/hooks/use-agent-memory.ts create mode 100644 studio/src/features/agent/hooks/use-agent-projects.ts create mode 100644 studio/src/features/agent/hooks/use-agent-roster.ts create mode 100644 studio/src/features/agent/hooks/use-agent-runs.ts create mode 100644 studio/src/features/agent/hooks/use-agent-sessions.ts create mode 100644 studio/src/features/agent/hooks/use-agent-skills.ts create mode 100644 studio/src/features/agent/hooks/use-harness-runtime.ts create mode 100644 studio/src/features/agent/hooks/use-refresh-on-focus.ts create mode 100644 studio/src/features/agent/index.ts create mode 100644 studio/src/features/agent/types.ts create mode 100644 studio/src/hooks/use-confirm.tsx create mode 100644 studio/src/hooks/use-is-truncated.ts create mode 100644 studio/src/hooks/use-mobile.ts create mode 100644 studio/src/hooks/use-nav-collapsed.ts create mode 100644 studio/src/hooks/use-nav-reopen-sidebar.ts create mode 100644 studio/src/hooks/use-prompt.tsx create mode 100644 studio/src/hooks/use-rail-width.ts create mode 100644 studio/src/hooks/use-sidebar-width.ts create mode 100644 studio/src/lib/api-error.ts create mode 100644 studio/src/lib/feature-flags.ts create mode 100644 studio/src/lib/formatters.ts create mode 100644 studio/src/lib/harness/client.ts create mode 100644 studio/src/lib/sanitize-url.ts create mode 100644 studio/src/lib/shortcuts/registry.test.ts create mode 100644 studio/src/lib/shortcuts/registry.ts create mode 100644 studio/src/lib/shortcuts/use-shortcuts.tsx create mode 100644 studio/src/lib/typography.ts create mode 100644 studio/src/lib/utils.test.ts create mode 100644 studio/src/lib/utils.ts create mode 100644 studio/src/types.ts create mode 100644 studio/src/types/vite.d.ts create mode 100644 studio/tests/e2e/chat-panels.spec.ts create mode 100644 studio/tsconfig.json create mode 100644 studio/vitest.config.mts create mode 100644 studio/vitest.setup.ts diff --git a/studio/.env.example b/studio/.env.example new file mode 100644 index 0000000000..29788bea05 --- /dev/null +++ b/studio/.env.example @@ -0,0 +1,114 @@ +# ToolHive Cloud UI - Environment Variables +# Copy this file to .env.local and fill in the values + +# ============================================================================= +# LOCAL AGENT HARNESS (OPTIONAL — LOCAL DEVELOPMENT ONLY) +# ============================================================================= +# Point the workspace chat at a mecatl daemon running on this machine +# (`mecated serve --workspace --store-dir `). When unset or +# unreachable — which is always the case on a deployed instance — the chat falls +# back to simulated responses. +# +# Loopback targets only; a non-loopback MECATL_URL is refused unless +# MECATL_ALLOW_REMOTE=true, because the daemon exposes file, edit and shell tools. +# MECATL_URL=http://127.0.0.1:8081 +# +# Absolute path every file and shell tool is rooted at. Required by the daemon on +# session create; injected server-side so it never reaches the client bundle. +# MECATL_WORKSPACE=/absolute/path/to/your/repo +# +# Only if the daemon was started with --auth-token. +# MECATL_AUTH_TOKEN= +# +# Mecatl Studio's local controller (supervises the daemon; provider credential, +# MCP gateway, model routing). Defaults to its standard loopback port. +# MECATL_CONTROL_URL=http://127.0.0.1:8788 + +# ============================================================================= +# REQUIRED FOR PRODUCTION +# ============================================================================= + +# OIDC Provider Configuration +# Your OIDC provider's issuer URL (e.g., https://your-oidc-provider.com) +OIDC_ISSUER_URL= + +# OAuth2 Client ID from your OIDC provider +OIDC_CLIENT_ID= + +# OAuth2 Client Secret from your OIDC provider +OIDC_CLIENT_SECRET= + +# Better Auth Configuration +# Secret key for token encryption (generate with: openssl rand -base64 32) +BETTER_AUTH_SECRET= + +# Your application's base URL (e.g., https://your-app.example.com) +BETTER_AUTH_URL= + +# Backend API Configuration +# ToolHive Registry Server API URL +API_BASE_URL= + +# ============================================================================= +# OPTIONAL +# ============================================================================= + +# Brand Customization +# Both vars are runtime environment variables — set them via Helm values or +# Kubernetes env vars. No rebuild required to change them. +# +# Display name used as the logo's alt text (visible to screen readers). +# Read at request time in Server Components. Falls back to "ToolHive" in the +# global error boundary (a Client Component) — accessing runtime env vars +# there would require a server roundtrip, which is unacceptable in a +# last-resort error handler. +# If unset, defaults to "ToolHive". +# BRAND_NAME=Acme Corp + +# URL of a custom logo image (SVG, PNG, WebP, etc.). +# Proxied server-side on every request by the /brand/logo route handler — +# the external URL never reaches the browser. +# If unset, the default ToolHive logo is served. +# BRAND_LOGO_URL=https://cdn.example.com/your-logo.svg + +# Trusted Origins (comma-separated list) +# Additional origins allowed for CORS and auth callbacks +# TRUSTED_ORIGINS=http://localhost:3002,http://localhost:3003 + +# Favicon (optional) +# URL of a custom favicon to display in browser tabs. +# If not set, the default Stacklok favicon is used. +# Supported formats: ICO, PNG, SVG, JPEG. +# Next.js recommends a 32x32 ICO for maximum browser compatibility, +# or SVG for a scalable single-format option supported by all modern browsers. +# FAVICON_URL=https://example.com/favicon.ico + +# ============================================================================= +# DEVELOPMENT ONLY (automatically set by dev server) +# ============================================================================= + +# These are set automatically when running 'pnpm dev' +# No need to set them manually for local development + +# NODE_ENV=development +# OIDC_ISSUER_URL=http://localhost:3001 +# OIDC_CLIENT_ID=web-client +# OIDC_CLIENT_SECRET=web-secret +# BETTER_AUTH_URL=http://localhost:3000 +# API_BASE_URL=http://localhost:9090 + +# AI-assistant related tokens +OPENROUTER_API_KEY=my-example-key + +# ============================================================================= +# FEATURE FLAGS +# ============================================================================= +# Atrium workspace-only mode is chosen by the USER: the presentation-mode +# dropdown in the user menu ("Atrium" vs "Gateway") hides the Connectors and AI +# Gateway sidebar sections AND blocks their routes (/gateway, /tools/**, +# /admin/**, /workspace/token-usage), which redirect to /workspace/chat. The +# choice is mirrored into a cookie so src/proxy.ts can enforce it server-side. +# +# This variable only sets the DEFAULT for a visitor who has not chosen yet — an +# explicit selection always wins. Leave unset for the full console by default. +# NEXT_PUBLIC_ATRIUM_WORKSPACE_ONLY=true diff --git a/studio/.gitignore b/studio/.gitignore new file mode 100644 index 0000000000..2a8ac82e33 --- /dev/null +++ b/studio/.gitignore @@ -0,0 +1,54 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage +# Playwright/Cucumber E2E artifacts +test-results/ +playwright-report/ +blob-report/ + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* +!.env.example + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# helm +*.tgz +helm/charts/ +helm/*.lock + +# Claude Code local settings +.claude/settings.local.json diff --git a/studio/.npmrc b/studio/.npmrc new file mode 100644 index 0000000000..acbcba248a --- /dev/null +++ b/studio/.npmrc @@ -0,0 +1,2 @@ +enable-pre-post-scripts=true +min-release-age=3 diff --git a/studio/biome.json b/studio/biome.json new file mode 100644 index 0000000000..301f2eea74 --- /dev/null +++ b/studio/biome.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.10/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "includes": ["**", "!node_modules", "!.next", "!dist", "!build"] + }, + "overrides": [ + { + "includes": [ + "src/generated/**", + "src/generated-config-server/**", + "src/generated-gateway/**" + ], + "linter": { + "enabled": false + } + }, + { + "includes": ["src/components/ui/sidebar.tsx"], + "linter": { + "rules": { + "suspicious": { + "noDocumentCookie": "off" + } + } + } + }, + { + "includes": ["src/mocks/**"], + "linter": { + "rules": { + "suspicious": { + "noConsole": "off" + } + } + } + }, + { + "includes": ["renovate.json"], + "linter": { + "rules": { + "suspicious": { + "noDuplicateObjectKeys": "off" + } + } + } + } + ], + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noUnknownAtRules": "off" + } + }, + "domains": { + "next": "recommended", + "react": "recommended" + } + }, + "css": { + "parser": { + "cssModules": false, + "tailwindDirectives": true + } + }, + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/studio/components.json b/studio/components.json new file mode 100644 index 0000000000..f4fb4bea2d --- /dev/null +++ b/studio/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + } +} diff --git a/studio/knip.ts b/studio/knip.ts new file mode 100644 index 0000000000..845d03c46a --- /dev/null +++ b/studio/knip.ts @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Proprietary +import type { KnipConfig } from "knip"; + +const config: KnipConfig = { + entry: [ + "src/app/**/{page,layout,loading,error,not-found,global-error,route}.{ts,tsx}", + "src/app/**/__tests__/**/*.{ts,tsx}", + "src/components/**/__tests__/**/*.{ts,tsx}", + "src/hooks/**/__tests__/**/*.{ts,tsx}", + "src/**/*.test.{ts,tsx}", + "playwright.config.mts", + ], + project: ["src/**/*.{ts,tsx}"], + paths: { + "@/*": ["src/*"], + "@api/*": ["src/generated/*"], + "@mocks": ["src/mocks"], + "@mocks/*": ["src/mocks/*"], + }, + ignore: [ + // Auto-generated files from hey-api + "src/generated/**", + // shadcn/ui components export all variants by convention — only a subset + // is used at any given time + "src/components/ui/**", + // Reusable AI prompt-input component (same library pattern as shadcn/ui) + "src/components/ai-elements/**", + // MSW mock utilities — consumed dynamically in tests and dev server + "src/mocks/**", + // Context providers export hooks for downstream consumer components + "src/contexts/**", + // Shared lib utilities consumed by feature modules + "src/lib/zod-v4-resolver.ts", + // Feature modules: internal exports consumed within the feature + "src/features/**", + ], + ignoreDependencies: [ + // Tailwind v4 is imported via CSS (@import "tailwindcss"), not JS + "tailwindcss", + // Used by shadcn/ui Form and Label components (in src/components/ui/ which knip ignores) + "react-hook-form", + "@radix-ui/react-label", + ], +}; + +export default config; diff --git a/studio/next.config.ts b/studio/next.config.ts new file mode 100644 index 0000000000..acf09c9284 --- /dev/null +++ b/studio/next.config.ts @@ -0,0 +1,87 @@ +import type { NextConfig } from "next"; + +const isDev = process.env.NODE_ENV !== "production"; + +/** + * Content Security Policy header. + * All API calls (OIDC, backend API) happen server-side, + * so browser CSP only needs 'self'. + */ +const cspHeader = ` + default-src 'self'; + script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ""}; + style-src 'self' 'unsafe-inline'; + img-src 'self' blob: data: https://randomuser.me; + font-src 'self'; + connect-src 'self'; + form-action 'self'; + frame-src *; + frame-ancestors 'none'; + base-uri 'self'; + object-src 'none'; + ${process.env.NODE_ENV === "production" ? "upgrade-insecure-requests;" : ""} +` + .replace(/\s{2,}/g, " ") + .trim(); + +const nextConfig: NextConfig = { + reactCompiler: true, + output: "standalone", + poweredByHeader: false, + // Include OpenAPI schema files in the Vercel/standalone deployment bundle. + // mocker.ts reads them at runtime via fs.readFileSync to generate fixture + // handlers; without this they are absent from /var/task/ on Vercel. + // Include OpenAPI schema files in the Vercel/standalone deployment bundle. + // mocker.ts reads them at runtime via fs.readFileSync. + outputFileTracingIncludes: { + "/api/mock/**": ["./swagger.json", "./user-management-openapi.yaml"], + "/api-docs/**": ["./swagger.json", "./user-management-openapi.yaml"], + }, + async headers() { + return [ + { + // Apply strict security headers to all routes except the proxy endpoint. + // The proxy serves third-party HTML that needs unrestricted resource loading, + // so it gets its own permissive CSP below. + source: "/((?!api/proxy).*)", + headers: [ + { key: "Content-Security-Policy", value: cspHeader }, + { key: "X-Content-Type-Options", value: "nosniff" }, + { key: "X-Frame-Options", value: "DENY" }, + { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }, + { + key: "Permissions-Policy", + value: "camera=(), microphone=(), geolocation=()", + }, + { key: "Cross-Origin-Resource-Policy", value: "same-origin" }, + ], + }, + { + // Proxy endpoint: allow the proxied page's own resources to load freely. + source: "/api/proxy", + headers: [ + { + key: "Content-Security-Policy", + value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;", + }, + { key: "X-Content-Type-Options", value: "nosniff" }, + ], + }, + ]; + }, + async rewrites() { + if (!isDev) return []; + + const apiBaseUrl = process.env.API_BASE_URL || ""; + + return [ + // Proxy registry API in development (to mock server or real backend) + { + source: "/registry/:path*", + destination: `${apiBaseUrl}/registry/:path*`, + }, + ]; + }, +}; + +export default nextConfig; diff --git a/studio/package.json b/studio/package.json new file mode 100644 index 0000000000..8d33e36db1 --- /dev/null +++ b/studio/package.json @@ -0,0 +1,162 @@ +{ + "name": "toolhive-cloud-ui-enterprise", + "version": "0.1.0", + "private": true, + "packageManager": "pnpm@11.7.0+sha512.19cc852c120c7125760f2443ee6be0ca5b40f9f50598de1a09a1f177503e010e57c23c77646e01e761de59bf874fb22a3398c33ab9691fc13eb946b6f0f4d620", + "engines": { + "node": ">=24.0.0 <25.0.0" + }, + "scripts": { + "dev": "concurrently -n \"OIDC,Mock,Next\" -c \"blue,magenta,green\" \"pnpm oidc\" \"pnpm mock:server\" \"pnpm dev:next\"", + "dev:next": "next dev", + "dev:mock-server": "concurrently -n \"Mock,Next\" -c \"magenta,green\" \"pnpm mock:server\" \"pnpm dev:next\"", + "dev:mock-oidc": "concurrently -n \"OIDC,Next\" -c \"blue,green\" \"pnpm oidc\" \"pnpm dev:next\"", + "build": "next build", + "start": "next start", + "lint": "biome check", + "format": "biome format --write", + "test": "vitest", + "test:e2e": "pnpm build && playwright test", + "test:e2e:ui": "pnpm build && playwright test --ui", + "test:e2e:debug": "pnpm build && playwright test --debug", + "start:e2e": "concurrently -n \"OIDC,Mock,Next\" -c \"blue,magenta,green\" \"pnpm oidc\" \"pnpm mock:server\" \"pnpm start\"", + "test:coverage": "vitest run --coverage", + "type-check": "tsc --noEmit", + "prepare": "husky", + "oidc": "node dev-auth/oidc-provider.mjs", + "mock:config-server": "node dev-auth/mock-config-server.mjs", + "generate-client:nofetch": "openapi-ts", + "mock:server": "tsx --watch src/mocks/server.ts", + "knip": "knip", + "knip:fix": "knip --fix" + }, + "dependencies": { + "@ai-sdk/mcp": "^1.0.0", + "@ai-sdk/react": "^3.0.51", + "@modelcontextprotocol/sdk": "^1.27.1", + "@openrouter/ai-sdk-provider": "^2.0.0", + "@openrouter/sdk": "^0.10.0", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-avatar": "^1.1.11", + "@radix-ui/react-checkbox": "^1.1.5", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", + "@radix-ui/react-tabs": "^1.1.13", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@tiptap/extension-mention": "^3.29.2", + "@tiptap/extension-placeholder": "^3.29.2", + "@tiptap/pm": "^3.27.1", + "@tiptap/react": "^3.27.1", + "@tiptap/starter-kit": "^3.27.1", + "@tiptap/suggestion": "^3.29.2", + "ai": "^6.0.0", + "ai-sdk-ollama": "^3.0.0", + "archiver": "^8.0.0", + "better-auth": "^1.6.27", + "class-variance-authority": "0.7.1", + "clsx": "2.1.1", + "cmdk": "^1.1.1", + "date-fns": "^4.1.0", + "dexie": "^4.2.1", + "fuse.js": "^7.4.2", + "ioredis": "^5.10.1", + "lucide-react": "^0.577.0", + "mime-types": "^3.0.2", + "msw": "^2.12.2", + "nanoid": "^5.1.16", + "next": "16.2.11", + "next-themes": "^0.4.6", + "nuqs": "^2.8.1", + "pg": "^8.13.3", + "radix-ui": "^1.5.0", + "react": "19.2.4", + "react-dom": "19.2.4", + "react-hook-form": "^7.72.1", + "react-markdown": "^10.1.0", + "redoc": "^2.5.3", + "remark-gfm": "^4.0.1", + "remark-math": "^6.0.0", + "server-only": "^0.0.1", + "shiki": "^4.4.3", + "simple-icons": "^16.27.0", + "sonner": "^2.0.7", + "streamdown": "^2.0.0", + "tailwind-merge": "3.5.0", + "tar-stream": "^3.2.0", + "tiptap-markdown": "^0.9.0", + "yaml": ">=2.8.3", + "zod": "^4.3.6" + }, + "devDependencies": { + "@biomejs/biome": "2.4.10", + "@hey-api/openapi-ts": "0.94.5", + "@mswjs/http-middleware": "^0.10.2", + "@playwright/test": "^1.56.1", + "@tailwindcss/postcss": "^4", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/archiver": "^7.0.0", + "@types/express": "^5.0.6", + "@types/mime-types": "^3.0.1", + "@types/node": "^24.0.0", + "@types/pg": "^8.11.12", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/tar-stream": "^3.1.4", + "@vitejs/plugin-react": "^6.0.0", + "@vitest/coverage-v8": "^4.0.8", + "babel-plugin-react-compiler": "1.0.0", + "concurrently": "^9.2.1", + "dotenv": "^17.2.3", + "express": "^5.2.1", + "husky": "^9.1.7", + "jsdom": "^29.0.0", + "json-schema-faker": "^0.5.6", + "knip": "^6.1.1", + "lint-staged": "^16.0.0", + "oidc-provider": "^9.5.2", + "postcss": "^8.5.8", + "tailwindcss": "^4", + "tsx": "4.21.0", + "typescript": "^6.0.2", + "vite": "^8.0.16", + "vite-tsconfig-paths": "^6.0.0", + "vitest": "^4.0.8", + "vitest-fail-on-console": "^0.10.1" + }, + "lint-staged": { + "*.{ts,tsx,js,jsx,json,css}": [ + "biome check --write --no-errors-on-unmatched" + ] + }, + "pnpm": { + "overrides": { + "express-rate-limit": ">=8.3.2", + "hono": ">=4.12.21", + "@hono/node-server": ">=1.19.14", + "undici": ">=7.25.0 <8", + "kysely": ">=0.28.16 <0.29.0", + "picomatch": ">=4.0.4", + "qs": ">=6.15.2", + "yaml": ">=2.8.3", + "defu": ">=6.1.5", + "path-to-regexp@>=8.0.0 <8.4.2": "8.4.2", + "path-to-regexp@>=0.1.0 <0.1.13": "0.1.13", + "postcss": ">=8.5.10", + "fast-uri": ">=3.1.2", + "ip-address": ">=10.1.1" + } + } +} diff --git a/studio/playwright.config.mts b/studio/playwright.config.mts new file mode 100644 index 0000000000..59a0e8ac1c --- /dev/null +++ b/studio/playwright.config.mts @@ -0,0 +1,112 @@ +import { defineConfig, devices } from "@playwright/test"; + +// Set E2E defaults so `pnpm exec playwright test` works without manual env vars. +// The package.json test:e2e script also sets these for the build step. +process.env.BETTER_AUTH_SECRET ??= "e2e-test-secret-at-least-32-chars-long"; +process.env.BETTER_AUTH_RATE_LIMIT ??= "100"; + +const BASE_URL = process.env.BASE_URL || "http://localhost:3000"; + +async function isServerRunning(): Promise { + try { + await fetch(BASE_URL, { signal: AbortSignal.timeout(2000) }); + return true; + } catch { + return false; + } +} + +const serverAlreadyRunning = await isServerRunning(); + +// Shared env for all webServer processes. The mock config server is only +// activated when CONFIG_SERVER_URL is set — the DAL returns null when it's +// absent, so tests that don't use the config fixture are unaffected. +const e2eEnv = { + API_BASE_URL: "http://localhost:9090", + OIDC_ISSUER_URL: "http://localhost:4000", + OIDC_CLIENT_ID: "better-auth-dev", + OIDC_CLIENT_SECRET: "dev-secret-change-in-production", + BETTER_AUTH_URL: "http://localhost:3000", + BETTER_AUTH_SECRET: "e2e-test-secret-at-least-32-chars-long", + // Better Auth rate limits sign-in to 3 requests per 10 seconds by default. + // E2E tests with multiple authenticatedPage fixtures exceed this limit, + // causing 429 errors. Set to 100 to allow rapid sequential logins. + BETTER_AUTH_RATE_LIMIT: "100", + // Always use testing model for E2E tests to avoid needing OpenRouter API keys + USE_E2E_MODEL: "true", + E2E_MODEL_NAME: process.env.E2E_MODEL_NAME ?? "qwen2.5:1.5b", + OLLAMA_BASE_URL: process.env.OLLAMA_BASE_URL ?? "http://localhost:11434", + // Point the DAL at the mock config server. This is the only env change needed + // to activate config-server-dependent tests — no DAL code changes required. + CONFIG_SERVER_URL: "http://localhost:4001", +}; + +export default defineConfig({ + testDir: "./tests/e2e", + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + reporter: process.env.CI ? "github" : "list", + timeout: 30_000, + use: { + baseURL: BASE_URL, + trace: "on-first-retry", + screenshot: "only-on-failure", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], + // Start all servers independently so Playwright can wait for each one's + // health check before running tests. Splitting them also means a failure in + // one server shows a clear error instead of a combined process timeout. + webServer: serverAlreadyRunning + ? undefined + : [ + { + command: "pnpm oidc", + url: "http://localhost:4000/.well-known/openid-configuration", + timeout: 30_000, + stdout: "pipe", + stderr: "pipe", + env: { + OIDC_ISSUER_URL: e2eEnv.OIDC_ISSUER_URL, + OIDC_CLIENT_ID: e2eEnv.OIDC_CLIENT_ID, + OIDC_CLIENT_SECRET: e2eEnv.OIDC_CLIENT_SECRET, + }, + }, + { + command: "pnpm mock:config-server", + url: "http://localhost:4001/health", + timeout: 30_000, + stdout: "pipe", + stderr: "pipe", + env: { + OIDC_ISSUER_URL: e2eEnv.OIDC_ISSUER_URL, + OIDC_CLIENT_ID: e2eEnv.OIDC_CLIENT_ID, + OIDC_CLIENT_SECRET: e2eEnv.OIDC_CLIENT_SECRET, + }, + }, + { + command: "pnpm mock:server", + url: "http://localhost:9090/health", + timeout: 30_000, + stdout: "pipe", + stderr: "pipe", + env: { + API_BASE_URL: e2eEnv.API_BASE_URL, + }, + }, + { + // Run against production build - requires `pnpm build` to be run first + command: "pnpm start", + url: BASE_URL, + timeout: 120_000, + stdout: "pipe", + stderr: "pipe", + env: e2eEnv, + }, + ], +}); diff --git a/studio/postcss.config.mjs b/studio/postcss.config.mjs new file mode 100644 index 0000000000..61e36849cf --- /dev/null +++ b/studio/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/studio/public/.gitkeep b/studio/public/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/studio/public/bg-pattern.png b/studio/public/bg-pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..c364ae35b7b43ab548e7925ae6b2cbe07aedde54 GIT binary patch literal 112926 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 q-_uU$v8)7Dv0uKx!jn^5XuvzQD30000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio/public/stacklok-favicon.png b/studio/public/stacklok-favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..d20ed901a29fb15cd2f44cc1e0e7b0742718860d GIT binary patch literal 5699 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 literal 0 HcmV?d00001 diff --git a/studio/public/stacklok-logo-mark.svg b/studio/public/stacklok-logo-mark.svg new file mode 100644 index 0000000000..0ab1ef082f --- /dev/null +++ b/studio/public/stacklok-logo-mark.svg @@ -0,0 +1,3 @@ + + + diff --git a/studio/public/stacklok-logo.svg b/studio/public/stacklok-logo.svg new file mode 100644 index 0000000000..aac75c4535 --- /dev/null +++ b/studio/public/stacklok-logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio/src/app/(authenticated)/layout.tsx b/studio/src/app/(authenticated)/layout.tsx new file mode 100644 index 0000000000..87abb4c802 --- /dev/null +++ b/studio/src/app/(authenticated)/layout.tsx @@ -0,0 +1,31 @@ +import { ConsoleShell } from "@/components/shell/console-shell"; +import { SidebarProvider } from "@/components/ui/sidebar"; +import { PermissionsProvider } from "@/contexts/permissions-context"; +import { AssistantSidebarRoot } from "@/features/assistant"; +import { getPermissions } from "@/lib/authz"; +import { isFeatureEnabled } from "@/lib/config-server-client"; + +export default async function AuthenticatedLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const [permissions, assistantEnabled] = await Promise.all([ + getPermissions(), + isFeatureEnabled("assistant"), + ]); + + return ( + + + {/* Not SidebarInset: the shell renders the page's one
, and + SidebarInset is itself a
, which would nest them. This div + carries the flex sizing the assistant's right-hand sidebar needs. */} +
+ {children} +
+ {assistantEnabled && } + + + ); +} diff --git a/studio/src/app/(authenticated)/workspace/chat/[[...sessionId]]/page.tsx b/studio/src/app/(authenticated)/workspace/chat/[[...sessionId]]/page.tsx new file mode 100644 index 0000000000..56ec9c3f20 --- /dev/null +++ b/studio/src/app/(authenticated)/workspace/chat/[[...sessionId]]/page.tsx @@ -0,0 +1,17 @@ +import { ChatWorkspace } from "../_components/chat-workspace"; + +/** + * `/workspace/chat` (no conversation) and `/workspace/chat/` are + * served by one optional-catch-all route, so moving between them keeps + * `ChatWorkspace` mounted. Its selection and project state survive the + * navigation — switching to the project overview (which drops the sessionId + * from the URL) no longer remounts the tree and re-runs the default-select. + */ +export default async function ChatPage({ + params, +}: { + params: Promise<{ sessionId?: string[] }>; +}) { + const { sessionId } = await params; + return ; +} diff --git a/studio/src/app/(authenticated)/workspace/chat/_components/approval-panel.tsx b/studio/src/app/(authenticated)/workspace/chat/_components/approval-panel.tsx new file mode 100644 index 0000000000..715b44c8a9 --- /dev/null +++ b/studio/src/app/(authenticated)/workspace/chat/_components/approval-panel.tsx @@ -0,0 +1,161 @@ +"use client"; + +import { ShieldAlert } from "lucide-react"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import type { ApprovalChoice, ApprovalRequest } from "@/features/agent"; +import { cn } from "@/lib/utils"; + +const DELETE_WORDS = /\b(delete|remove|drop|revoke|destroy|purge)\b/i; + +/** One line of `details` is "Connector: verb the rest…" — parse it for badges. */ +function parseActions( + details: string, +): { connector: string; verb: string; destructive: boolean }[] { + return details + .split("\n") + .map((line) => line.trim()) + .filter(Boolean) + .map((line) => { + const [rawConnector, ...rest] = line.split(":"); + const action = rest.join(":").trim(); + const connector = rest.length > 0 ? rawConnector.trim() : "Tool"; + const verbMatch = action.match(/[a-zA-Z_]+/); + const verb = (verbMatch ? verbMatch[0] : action) + .toLowerCase() + .replace(/_/g, " "); + return { + connector, + verb, + destructive: DELETE_WORDS.test(line), + }; + }); +} + +export function ApprovalPanel({ + approval, + onRespond, + binaryOnly = false, +}: { + approval: ApprovalRequest; + onRespond: (choice: ApprovalChoice) => void; + /** The live harness verdict is allow-once/deny — offering "for session" or + * "always" would promise a scope the backend does not grant. */ + binaryOnly?: boolean; +}) { + const actions = parseActions(approval.details); + const destructive = actions.some((a) => a.destructive); + + return ( +
+
+ + + Permission required + +
+

{approval.description}

+ {actions.length > 0 && ( +
+ {actions.map((a) => ( + + {a.connector} · {a.verb} + + ))} +
+ )} +

+ This action modifies or deletes data. +

+
+        {approval.details}
+      
+
+ + {!binaryOnly && ( + <> + + + + )} + +
+
+ ); +} diff --git a/studio/src/app/(authenticated)/workspace/chat/_components/chat-view.tsx b/studio/src/app/(authenticated)/workspace/chat/_components/chat-view.tsx new file mode 100644 index 0000000000..360d8d9bc3 --- /dev/null +++ b/studio/src/app/(authenticated)/workspace/chat/_components/chat-view.tsx @@ -0,0 +1,752 @@ +"use client"; + +import { + ArrowLeft, + ChevronRight, + CirclePlus, + Ellipsis, + FileText, + FolderClosed, + Loader2, + MessageCircle, + MessageSquareText, + PanelLeftOpen, + PanelRightOpen, + Pencil, + Trash2, + Wrench, +} from "lucide-react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Sheet, SheetContent, SheetTitle } from "@/components/ui/sheet"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import type { + AgentMessage, + AgentSession, + ApprovalChoice, + ApprovalRequest, + Artifact, + Attachment, + ClarificationRequest, +} from "@/features/agent"; +import { useIsMobile } from "@/hooks/use-mobile"; +import { cn } from "@/lib/utils"; +import { ChatInput } from "../../_components/chat-input"; +import { ApprovalPanel } from "./approval-panel"; +import { ClarificationPanel } from "./clarification-panel"; +import { FilePreview } from "./file-preview"; +import { MarkdownCanvasPanel } from "./markdown-canvas-panel"; +import { BotAvatar, MessageBubble } from "./message-bubble"; +import { SidePanel } from "./side-panel"; + +/** The single right-hand panel: exactly one kind is open at a time, or none. */ +type ActivePanel = + | { kind: "artifact"; artifact: Artifact } + | { kind: "attachment"; attachment: Attachment } + | { kind: "thread"; message: AgentMessage }; + +function MobileChatMenu({ + showActivity, + onToggleActivity, + onRename, + onDelete, + onMove, + projects, + sessionProjectId, +}: { + showActivity: boolean; + onToggleActivity: () => void; + onRename?: () => void; + onDelete?: () => void; + onMove?: (projectId: string | null) => void; + projects?: Array<{ id: string; name: string }>; + sessionProjectId?: string | null; +}) { + const [open, setOpen] = useState(false); + const [showMoveList, setShowMoveList] = useState(false); + + return ( + <> + + + + Chat options + {showMoveList ? ( +
+ +
+ + {projects?.map((p) => ( + + ))} +
+
+ ) : ( +
+ + {onRename && ( + + )} + {onMove && projects && ( + + )} + {onDelete && ( + <> +
+ + + )} +
+ )} + + + + ); +} + +function AttachmentPanel({ + attachment, + onClose, + maximized, + onToggleMaximize, +}: { + attachment: Attachment; + onClose: () => void; + maximized: boolean; + onToggleMaximize: () => void; +}) { + return ( + +
+ +
+
+ ); +} + +/** + * A side-panel thread branched off a single message. The root message is shown + * read-only at the top; replies typed here form a focused side conversation + * without cluttering the main transcript. + */ +function ThreadPanel({ + rootMessage, + botName, + onClose, + maximized, + onToggleMaximize, +}: { + rootMessage: AgentMessage; + botName: string; + onClose: () => void; + maximized: boolean; + onToggleMaximize: () => void; +}) { + const [replies, setReplies] = useState( + rootMessage.replies ?? [], + ); + const endRef = useRef(null); + + useEffect(() => { + endRef.current?.scrollIntoView({ behavior: "smooth" }); + }, []); + + const handleSend = (content: string) => { + const now = Date.now(); + setReplies((prev) => [ + ...prev, + { id: `thread-u-${now}`, role: "user", content, timestamp: now }, + { + id: `thread-a-${now}`, + role: "assistant", + content: + "Picking this up in the thread — I'll keep it scoped to the message above.", + timestamp: now + 1, + }, + ]); + requestAnimationFrame(() => + endRef.current?.scrollIntoView({ behavior: "smooth" }), + ); + }; + + return ( + + {/* Body: root message, replies, composer */} +
+
+
+ +
+ {replies.length > 0 && ( +
+ + {replies.length} {replies.length === 1 ? "reply" : "replies"} + +
+ )} + {replies.map((r) => ( + + ))} +
+
+
+ {}} + placeholder="Reply in thread…" + /> +
+
+ + ); +} + +function TextSelectionToolbar({ + containerRef, + onAddToChat, + onAskInSideChat, +}: { + containerRef: React.RefObject; + onAddToChat: (text: string) => void; + onAskInSideChat: (text: string) => void; +}) { + const [pos, setPos] = useState<{ x: number; y: number } | null>(null); + const [selectedText, setSelectedText] = useState(""); + const toolbarRef = useRef(null); + + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const handleMouseUp = () => { + requestAnimationFrame(() => { + const selection = window.getSelection(); + const text = selection?.toString().trim(); + if (!text || text.length < 3) { + setPos(null); + return; + } + + const range = selection?.getRangeAt(0); + if (!range) return; + + if (!container.contains(range.commonAncestorContainer)) { + setPos(null); + return; + } + + const rect = range.getBoundingClientRect(); + const containerRect = container.getBoundingClientRect(); + + setSelectedText(text); + setPos({ + x: rect.left + rect.width / 2 - containerRect.left, + y: rect.top - containerRect.top - 8, + }); + }); + }; + + const handleMouseDown = (e: MouseEvent) => { + if (toolbarRef.current?.contains(e.target as Node)) return; + setPos(null); + }; + + container.addEventListener("mouseup", handleMouseUp); + document.addEventListener("mousedown", handleMouseDown); + return () => { + container.removeEventListener("mouseup", handleMouseUp); + document.removeEventListener("mousedown", handleMouseDown); + }; + }, [containerRef]); + + if (!pos) return null; + + return ( +
+ +
+ +
+ ); +} + +export function ChatView({ + session, + messages, + isStreaming, + onSend, + botName, + live = false, + liveUsage, + sidebarOpen, + onToggleSidebar, + pendingApproval, + onRespondApproval, + pendingClarification, + onRespondClarification, + onRename, + onDelete, + onMove, + projects, + onSidePanelOpenChange, + initialDraft, + onInitialDraftConsumed, +}: { + session: AgentSession; + messages: AgentMessage[]; + isStreaming: boolean; + onSend: (content: string) => void; + botName: string; + /** True when a local harness is answering — demo chrome must not render. */ + live?: boolean; + liveUsage?: { inputTokens: number; outputTokens: number }; + sidebarOpen: boolean; + onToggleSidebar: () => void; + pendingApproval: ApprovalRequest | null; + onRespondApproval: (choice: ApprovalChoice) => void; + pendingClarification: ClarificationRequest | null; + onRespondClarification: (response: string) => void; + onRename?: () => void; + onDelete?: () => void; + onMove?: (projectId: string | null) => void; + projects?: Array<{ id: string; name: string }>; + /** Fires when the right-hand side panel (artifact/attachment) opens or + closes, so the parent can collapse the chat list while it's open. */ + onSidePanelOpenChange?: (open: boolean) => void; + /** Plain-text prompt to pre-fill the composer with on mount (a "next step" + chip that seeds the message without sending it). */ + initialDraft?: string | null; + onInitialDraftConsumed?: () => void; +}) { + const messagesEndRef = useRef(null); + const messagesContainerRef = useRef(null); + const [showActivity, setShowActivity] = useState(false); + // The single right-hand panel — a discriminated union makes "one panel at a + // time" structural rather than something to coordinate by hand. + const [panel, setPanel] = useState(null); + const [appendText, setAppendText] = useState(null); + // When maximized, the panel fills the pane and the conversation column is + // hidden. Always reset when the panel is closed. + const [panelMaximized, setPanelMaximized] = useState(false); + const isMobile = useIsMobile(); + const handleAppendConsumed = useCallback(() => setAppendText(null), []); + + const closeSidePanel = useCallback(() => { + setPanel(null); + setPanelMaximized(false); + }, []); + const toggleMaximize = useCallback(() => setPanelMaximized((v) => !v), []); + const handleStartThread = useCallback( + (message: AgentMessage) => setPanel({ kind: "thread", message }), + [], + ); + + // Jump to the latest message whenever the active chat changes so users + // always land at the bottom (most-recent) of the conversation. + // biome-ignore lint/correctness/useExhaustiveDependencies: scrolling is intentionally driven by session.id changes + useEffect(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "instant" }); + }, [session.id]); + + // The right-hand panel only renders on non-mobile layouts; let the parent + // collapse the chat list while it's open so both panels fit side by side. + const sidePanelOpen = !isMobile && panel !== null; + useEffect(() => { + onSidePanelOpenChange?.(sidePanelOpen); + }, [sidePanelOpen, onSidePanelOpenChange]); + + return ( +
+
+
+ + + + + + {isMobile + ? "Back to chats" + : sidebarOpen + ? "Hide sidebar" + : "Show sidebar"} + + + {/* biome-ignore lint/a11y/noStaticElementInteractions: rename is also reachable via the header menu */} +

+ {session.title || "Untitled"} +

+ {live && ( + /* Live sessions show what the harness actually reported. */ +
+ + + {liveUsage && liveUsage.inputTokens + liveUsage.outputTokens > 0 + ? `${Math.round(liveUsage.inputTokens / 1000)}k in · ${liveUsage.outputTokens} out tokens` + : "Connected · live agent"} + +
+ )} + {!isMobile && ( + + + + + + setShowActivity((v) => !v)}> + + {showActivity ? "Hide Tools" : "Show Tools"} + + {onRename && ( + + + Rename + + )} + {onMove && projects && ( + + + + Move + + + onMove(null)}> + + Chats + + {projects.map((p) => ( + onMove(p.id)} + > + + {p.name} + + ))} + + + )} + {onDelete && ( + <> + + + + Delete + + + )} + + + )} + {isMobile && ( + setShowActivity((v) => !v)} + onRename={onRename} + onDelete={onDelete} + onMove={onMove} + projects={projects} + sessionProjectId={session.projectId} + /> + )} +
+ +
+
+ setAppendText(text)} + onAskInSideChat={(text) => setAppendText(text)} + /> +
+ {messages.map((msg) => ( + + setPanel({ kind: "artifact", artifact }) + } + onOpenAttachment={(attachment) => + setPanel({ kind: "attachment", attachment }) + } + onStartThread={handleStartThread} + botName={botName} + showActivity={showActivity} + /> + ))} + {pendingApproval && ( + + )} + {isStreaming && + messages[messages.length - 1]?.role !== "assistant" && ( +
+
+ +
+
+ + + Thinking... + +
+
+ )} +
+
+
+
+
+ {pendingClarification ? ( + + ) : ( + {}} + isStreaming={isStreaming} + disabled={!!pendingApproval} + appendText={appendText} + onAppendConsumed={handleAppendConsumed} + initialText={initialDraft} + onInitialTextConsumed={onInitialDraftConsumed} + placeholder={ + isStreaming ? "Queue a message..." : "Send a message..." + } + /> + )} +
+
+
+
+ {!isMobile && panel !== null && ( + + )} +
+ ); +} + +/** Renders the right-hand panel for the active kind. */ +function SidePanelForKind({ + panel, + botName, + onClose, + maximized, + onToggleMaximize, +}: { + panel: ActivePanel; + botName: string; + onClose: () => void; + maximized: boolean; + onToggleMaximize: () => void; +}) { + const shared = { onClose, maximized, onToggleMaximize }; + switch (panel.kind) { + case "artifact": + return ; + case "attachment": + return ; + case "thread": + return ( + + ); + } +} diff --git a/studio/src/app/(authenticated)/workspace/chat/_components/chat-window.tsx b/studio/src/app/(authenticated)/workspace/chat/_components/chat-window.tsx new file mode 100644 index 0000000000..387237b381 --- /dev/null +++ b/studio/src/app/(authenticated)/workspace/chat/_components/chat-window.tsx @@ -0,0 +1,129 @@ +"use client"; + +import { Paperclip, Send, Sparkles, Wrench } from "lucide-react"; +import { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Textarea } from "@/components/ui/textarea"; +import { cn } from "@/lib/utils"; + +interface Message { + id: string; + role: "user" | "agent" | "tool"; + content: string; + tool?: string; +} + +interface ChatWindowProps { + title: string; + seedMessages: Message[]; + attachedSkill?: string; +} + +export function ChatWindow({ + title, + seedMessages, + attachedSkill, +}: ChatWindowProps) { + const [messages, setMessages] = useState(seedMessages); + const [draft, setDraft] = useState(""); + + const handleSend = () => { + if (!draft.trim()) return; + const next: Message = { + id: `u-${Date.now()}`, + role: "user", + content: draft.trim(), + }; + setMessages((prev) => [...prev, next]); + setDraft(""); + setTimeout(() => { + setMessages((prev) => [ + ...prev, + { + id: `a-${Date.now()}`, + role: "agent", + content: + "Working on it — this is a UI-only demo, so no model is actually running.", + }, + ]); + }, 400); + }; + + return ( +
+
+
+ + {title} +
+ {attachedSkill && ( +
+ + {attachedSkill} +
+ )} +
+ +
+ {messages.map((m) => ( + + ))} +
+ +
+
+