From a60927daeb75423eb13f12c7b9599d2564fdbada Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Sat, 25 Apr 2026 02:44:21 -0500 Subject: [PATCH 1/2] Prune SME UI and add project chat thread support - remove unused marketing and SME UI layers - add thread kind through orchestration, projections, and tests - introduce project chat routes and ws split handlers --- apps/marketing/components/ui/button-group.tsx | 78 - apps/marketing/components/ui/calendar.tsx | 177 - apps/marketing/components/ui/drawer.tsx | 124 - apps/marketing/components/ui/input-group.tsx | 157 - apps/marketing/components/ui/pagination.tsx | 106 - apps/marketing/components/ui/spinner.tsx | 16 - .../orchestrationEngine.integration.test.ts | 2 + .../Layers/CheckpointDiffQuery.test.ts | 1 + .../Layers/CheckpointReactor.test.ts | 1 + .../Layers/OrchestrationEngine.test.ts | 10 + .../Layers/ProjectionOverviewQuery.ts | 2 + .../Layers/ProjectionPipeline.ts | 1 + .../Layers/ProjectionSnapshotQuery.test.ts | 1 + .../Layers/ProjectionSnapshotQuery.ts | 2 + .../Layers/ProjectionThreadDetailQuery.ts | 2 + .../Layers/ProviderCommandReactor.test.ts | 1 + .../Layers/ProviderRuntimeIngestion.test.ts | 6 + .../orchestration/commandInvariants.test.ts | 58 + .../src/orchestration/commandInvariants.ts | 20 + .../src/orchestration/decider.limits.test.ts | 1 + apps/server/src/orchestration/decider.ts | 9 + .../src/orchestration/projector.test.ts | 1 + apps/server/src/orchestration/projector.ts | 1 + .../persistence/Layers/ProjectionThreads.ts | 7 +- .../persistence/Layers/SmeConversations.ts | 149 - .../Layers/SmeKnowledgeDocuments.ts | 162 - .../src/persistence/Layers/SmeMessages.ts | 93 - apps/server/src/persistence/Migrations.ts | 2 + .../persistence/Migrations/005_Projections.ts | 1 + .../Migrations/028_ProjectionThreadKind.ts | 17 + .../persistence/Services/ProjectionThreads.ts | 2 + .../persistence/Services/SmeConversations.ts | 64 - .../Services/SmeKnowledgeDocuments.ts | 60 - .../src/persistence/Services/SmeMessages.ts | 48 - apps/server/src/serverLayers.ts | 112 +- .../src/sme/Layers/SmeChatServiceLive.test.ts | 198 - .../src/sme/Layers/SmeChatServiceLive.ts | 536 -- .../server/src/sme/Services/SmeChatService.ts | 89 - apps/server/src/sme/authValidation.test.ts | 77 - apps/server/src/sme/authValidation.ts | 466 -- apps/server/src/sme/backends/anthropic.ts | 96 - .../src/sme/backends/providerRuntime.ts | 201 - apps/server/src/sme/promptBuilder.ts | 67 - .../src/terminal/Layers/runtimePtyAdapter.ts | 20 + .../Services/RuntimeEnvResolver.test.ts | 1 + apps/server/src/wsServer.test.ts | 2 + apps/server/src/wsServer.ts | 1081 +-- apps/server/src/wsServer/routes/git.ts | 284 + apps/server/src/wsServer/routes/github.ts | 29 + .../src/wsServer/routes/orchestration.ts | 64 + apps/server/src/wsServer/routes/prReview.ts | 135 + apps/server/src/wsServer/routes/server.ts | 218 + apps/server/src/wsServer/routes/shared.ts | 22 + apps/server/src/wsServer/routes/shell.ts | 22 + apps/server/src/wsServer/routes/skills.ts | 65 + apps/server/src/wsServer/routes/terminal.ts | 89 + apps/server/src/wsServer/routes/workspace.ts | 187 + apps/web/src/components/ChatView.browser.tsx | 2 + apps/web/src/components/ChatView.tsx | 5 +- .../components/KeybindingsToast.browser.tsx | 1 + apps/web/src/components/Sidebar.logic.test.ts | 23 + apps/web/src/components/Sidebar.logic.ts | 18 + apps/web/src/components/Sidebar.tsx | 184 +- apps/web/src/components/SpotifyPlayer.tsx | 276 - apps/web/src/components/chat/ChatHeader.tsx | 55 +- .../settings/ProviderCapabilityMatrix.tsx | 163 + apps/web/src/components/skills/SkillsPage.tsx | 28 +- apps/web/src/components/sme/SmeChatShell.tsx | 104 - .../src/components/sme/SmeChatWorkspace.tsx | 315 - .../components/sme/SmeConversationDialog.tsx | 353 - .../components/sme/SmeConversationRail.tsx | 130 - .../src/components/sme/SmeKnowledgePanel.tsx | 164 - .../src/components/sme/SmeMessageBubble.tsx | 66 - .../web/src/components/sme/SmeMessageList.tsx | 100 - .../sme/smeConversationConfig.test.ts | 16 - .../components/sme/smeConversationConfig.ts | 64 - apps/web/src/draftThreads.ts | 1 + .../hooks/useAutoDeleteMergedThreads.test.tsx | 2 + apps/web/src/lib/projectChat.test.ts | 84 + apps/web/src/lib/projectChat.ts | 57 + apps/web/src/lib/settingsProviderMetadata.tsx | 40 + apps/web/src/routeTree.gen.ts | 63 +- apps/web/src/routes/_chat.$threadId.tsx | 23 +- apps/web/src/routes/_chat.plugins.tsx | 58 - .../src/routes/_chat.project.$projectId.tsx | 162 + apps/web/src/routes/_chat.settings.index.tsx | 249 +- apps/web/src/routes/_chat.sme-chat.tsx | 28 - apps/web/src/routes/_chat.tsx | 48 +- apps/web/src/smeStore.ts | 158 - apps/web/src/spotifyPlayerStore.ts | 164 - apps/web/src/store.test.ts | 17 + apps/web/src/store.ts | 1 + apps/web/src/types.ts | 2 + .../vscode-icons-language-associations.json | 2 +- apps/web/src/vscode-icons-lookup.json | 6004 +++++++++++++++++ apps/web/src/vscode-icons.ts | 92 +- apps/web/src/worktreeCleanup.test.ts | 1 + apps/web/src/wsNativeApi.ts | 47 - bun.lock | 11 +- docs/product-scope.md | 120 + docs/route-3-playbook.md | 92 + packages/contracts/src/index.ts | 1 - packages/contracts/src/ipc.ts | 58 - packages/contracts/src/orchestration.test.ts | 48 + packages/contracts/src/orchestration.ts | 6 + packages/contracts/src/sme.ts | 221 - packages/contracts/src/ws.test.ts | 82 - packages/contracts/src/ws.ts | 102 - scripts/sync-vscode-icons.mjs | 73 + 109 files changed, 8668 insertions(+), 6959 deletions(-) delete mode 100644 apps/marketing/components/ui/button-group.tsx delete mode 100644 apps/marketing/components/ui/calendar.tsx delete mode 100644 apps/marketing/components/ui/drawer.tsx delete mode 100644 apps/marketing/components/ui/input-group.tsx delete mode 100644 apps/marketing/components/ui/pagination.tsx delete mode 100644 apps/marketing/components/ui/spinner.tsx delete mode 100644 apps/server/src/persistence/Layers/SmeConversations.ts delete mode 100644 apps/server/src/persistence/Layers/SmeKnowledgeDocuments.ts delete mode 100644 apps/server/src/persistence/Layers/SmeMessages.ts create mode 100644 apps/server/src/persistence/Migrations/028_ProjectionThreadKind.ts delete mode 100644 apps/server/src/persistence/Services/SmeConversations.ts delete mode 100644 apps/server/src/persistence/Services/SmeKnowledgeDocuments.ts delete mode 100644 apps/server/src/persistence/Services/SmeMessages.ts delete mode 100644 apps/server/src/sme/Layers/SmeChatServiceLive.test.ts delete mode 100644 apps/server/src/sme/Layers/SmeChatServiceLive.ts delete mode 100644 apps/server/src/sme/Services/SmeChatService.ts delete mode 100644 apps/server/src/sme/authValidation.test.ts delete mode 100644 apps/server/src/sme/authValidation.ts delete mode 100644 apps/server/src/sme/backends/anthropic.ts delete mode 100644 apps/server/src/sme/backends/providerRuntime.ts delete mode 100644 apps/server/src/sme/promptBuilder.ts create mode 100644 apps/server/src/terminal/Layers/runtimePtyAdapter.ts create mode 100644 apps/server/src/wsServer/routes/git.ts create mode 100644 apps/server/src/wsServer/routes/github.ts create mode 100644 apps/server/src/wsServer/routes/orchestration.ts create mode 100644 apps/server/src/wsServer/routes/prReview.ts create mode 100644 apps/server/src/wsServer/routes/server.ts create mode 100644 apps/server/src/wsServer/routes/shared.ts create mode 100644 apps/server/src/wsServer/routes/shell.ts create mode 100644 apps/server/src/wsServer/routes/skills.ts create mode 100644 apps/server/src/wsServer/routes/terminal.ts create mode 100644 apps/server/src/wsServer/routes/workspace.ts delete mode 100644 apps/web/src/components/SpotifyPlayer.tsx create mode 100644 apps/web/src/components/settings/ProviderCapabilityMatrix.tsx delete mode 100644 apps/web/src/components/sme/SmeChatShell.tsx delete mode 100644 apps/web/src/components/sme/SmeChatWorkspace.tsx delete mode 100644 apps/web/src/components/sme/SmeConversationDialog.tsx delete mode 100644 apps/web/src/components/sme/SmeConversationRail.tsx delete mode 100644 apps/web/src/components/sme/SmeKnowledgePanel.tsx delete mode 100644 apps/web/src/components/sme/SmeMessageBubble.tsx delete mode 100644 apps/web/src/components/sme/SmeMessageList.tsx delete mode 100644 apps/web/src/components/sme/smeConversationConfig.test.ts delete mode 100644 apps/web/src/components/sme/smeConversationConfig.ts create mode 100644 apps/web/src/lib/projectChat.test.ts create mode 100644 apps/web/src/lib/projectChat.ts delete mode 100644 apps/web/src/routes/_chat.plugins.tsx create mode 100644 apps/web/src/routes/_chat.project.$projectId.tsx delete mode 100644 apps/web/src/routes/_chat.sme-chat.tsx delete mode 100644 apps/web/src/smeStore.ts delete mode 100644 apps/web/src/spotifyPlayerStore.ts create mode 100644 apps/web/src/vscode-icons-lookup.json create mode 100644 docs/product-scope.md create mode 100644 docs/route-3-playbook.md delete mode 100644 packages/contracts/src/sme.ts diff --git a/apps/marketing/components/ui/button-group.tsx b/apps/marketing/components/ui/button-group.tsx deleted file mode 100644 index 9261afefa..000000000 --- a/apps/marketing/components/ui/button-group.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; -import { Separator } from "@/components/ui/separator"; - -const buttonGroupVariants = cva( - "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2", - { - variants: { - orientation: { - horizontal: - "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none", - vertical: - "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none", - }, - }, - defaultVariants: { - orientation: "horizontal", - }, - }, -); - -function ButtonGroup({ - className, - orientation, - ...props -}: React.ComponentProps<"div"> & VariantProps) { - return ( -
- ); -} - -function ButtonGroupText({ - className, - asChild = false, - ...props -}: React.ComponentProps<"div"> & { - asChild?: boolean; -}) { - const Comp = asChild ? Slot : "div"; - - return ( - - ); -} - -function ButtonGroupSeparator({ - className, - orientation = "vertical", - ...props -}: React.ComponentProps) { - return ( - - ); -} - -export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants }; diff --git a/apps/marketing/components/ui/calendar.tsx b/apps/marketing/components/ui/calendar.tsx deleted file mode 100644 index 91e83108b..000000000 --- a/apps/marketing/components/ui/calendar.tsx +++ /dev/null @@ -1,177 +0,0 @@ -"use client"; - -import * as React from "react"; -import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; -import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"; - -import { cn } from "@/lib/utils"; -import { Button, buttonVariants } from "@/components/ui/button"; - -function Calendar({ - className, - classNames, - showOutsideDays = true, - captionLayout = "label", - buttonVariant = "ghost", - formatters, - components, - ...props -}: React.ComponentProps & { - buttonVariant?: React.ComponentProps["variant"]; -}) { - const defaultClassNames = getDefaultClassNames(); - - return ( - svg]:rotate-180`, - String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, - className, - )} - captionLayout={captionLayout} - formatters={{ - formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }), - ...formatters, - }} - classNames={{ - root: cn("w-fit", defaultClassNames.root), - months: cn("flex gap-4 flex-col md:flex-row relative", defaultClassNames.months), - month: cn("flex flex-col w-full gap-4", defaultClassNames.month), - nav: cn( - "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between", - defaultClassNames.nav, - ), - button_previous: cn( - buttonVariants({ variant: buttonVariant }), - "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", - defaultClassNames.button_previous, - ), - button_next: cn( - buttonVariants({ variant: buttonVariant }), - "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", - defaultClassNames.button_next, - ), - month_caption: cn( - "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)", - defaultClassNames.month_caption, - ), - dropdowns: cn( - "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5", - defaultClassNames.dropdowns, - ), - dropdown_root: cn( - "relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md", - defaultClassNames.dropdown_root, - ), - dropdown: cn("absolute bg-popover inset-0 opacity-0", defaultClassNames.dropdown), - caption_label: cn( - "select-none font-medium", - captionLayout === "label" - ? "text-sm" - : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5", - defaultClassNames.caption_label, - ), - table: "w-full border-collapse", - weekdays: cn("flex", defaultClassNames.weekdays), - weekday: cn( - "text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none", - defaultClassNames.weekday, - ), - week: cn("flex w-full mt-2", defaultClassNames.week), - week_number_header: cn("select-none w-(--cell-size)", defaultClassNames.week_number_header), - week_number: cn( - "text-[0.8rem] select-none text-muted-foreground", - defaultClassNames.week_number, - ), - day: cn( - "relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none", - defaultClassNames.day, - ), - range_start: cn("rounded-l-md bg-accent", defaultClassNames.range_start), - range_middle: cn("rounded-none", defaultClassNames.range_middle), - range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end), - today: cn( - "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none", - defaultClassNames.today, - ), - outside: cn( - "text-muted-foreground aria-selected:text-muted-foreground", - defaultClassNames.outside, - ), - disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled), - hidden: cn("invisible", defaultClassNames.hidden), - ...classNames, - }} - components={{ - Root: ({ className, rootRef, ...props }) => { - return
; - }, - Chevron: ({ className, orientation, ...props }) => { - if (orientation === "left") { - return ; - } - - if (orientation === "right") { - return ; - } - - return ; - }, - DayButton: CalendarDayButton, - WeekNumber: ({ children, ...props }) => { - return ( - -
- {children} -
- - ); - }, - ...components, - }} - {...props} - /> - ); -} - -function CalendarDayButton({ - className, - day, - modifiers, - ...props -}: React.ComponentProps) { - const defaultClassNames = getDefaultClassNames(); - - const ref = React.useRef(null); - React.useEffect(() => { - if (modifiers.focused) ref.current?.focus(); - }, [modifiers.focused]); - - return ( -