From 4f608567062a14aba377311e98c34bee6dc91d7e Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Mon, 7 Sep 2026 22:40:50 +0200 Subject: [PATCH] refactor: remove unused UI and runtime scaffolding --- .github/workflows/docker-build.yml | 4 - apps/web/package.json | 3 +- apps/web/src/dialogs/api-key/schema.ts | 3 - apps/web/src/dialogs/auth/schema.ts | 7 - apps/web/src/dialogs/resume/schema.ts | 152 ------------------ apps/web/src/dialogs/schemas.ts | 63 ++++++-- apps/web/src/dialogs/store.test.ts | 8 - .../routes/agent/-components/agent-chat.tsx | 45 ++---- packages/ui/src/components/attachment.tsx | 68 +------- packages/ui/src/components/bubble.tsx | 46 +----- packages/ui/src/components/combobox.tsx | 33 ---- packages/ui/src/components/command.tsx | 38 ----- packages/ui/src/components/message.tsx | 45 +----- packages/ui/src/components/questionnaire.tsx | 110 ------------- packages/utils/src/rate-limit.ts | 2 - pnpm-lock.yaml | 18 --- 16 files changed, 72 insertions(+), 573 deletions(-) delete mode 100644 apps/web/src/dialogs/api-key/schema.ts delete mode 100644 apps/web/src/dialogs/auth/schema.ts delete mode 100644 apps/web/src/dialogs/resume/schema.ts diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 88a66a97f..1cdbc8a8d 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -59,10 +59,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@v6 - - name: Get version from package.json - id: version - run: echo "version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT" - - name: Setup Docker Buildx uses: docker/setup-buildx-action@v4 diff --git a/apps/web/package.json b/apps/web/package.json index e1d9675c6..de8224c51 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -4,7 +4,7 @@ "type": "module", "private": true, "scripts": { - "build": "rimraf dist && vite build", + "build": "vite build", "dev": "vite dev", "serve": "vite preview", "start": "vite preview", @@ -118,7 +118,6 @@ "@vitejs/plugin-react": "^6.1.1", "babel-plugin-macros": "^3.1.0", "babel-plugin-react-compiler": "^1.0.0", - "rimraf": "^6.1.3", "typescript": "^7.0.2", "vite": "^8.2.2" } diff --git a/apps/web/src/dialogs/api-key/schema.ts b/apps/web/src/dialogs/api-key/schema.ts deleted file mode 100644 index bbb3f5ccc..000000000 --- a/apps/web/src/dialogs/api-key/schema.ts +++ /dev/null @@ -1,3 +0,0 @@ -import z from "zod"; - -export const apiKeyDialogSchemas = [z.object({ type: z.literal("api-key.create"), data: z.undefined() })] as const; diff --git a/apps/web/src/dialogs/auth/schema.ts b/apps/web/src/dialogs/auth/schema.ts deleted file mode 100644 index 8ece3d2bb..000000000 --- a/apps/web/src/dialogs/auth/schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -import z from "zod"; - -export const authDialogSchemas = [ - z.object({ type: z.literal("auth.change-password"), data: z.undefined() }), - z.object({ type: z.literal("auth.two-factor.enable"), data: z.undefined() }), - z.object({ type: z.literal("auth.two-factor.disable"), data: z.undefined() }), -] as const; diff --git a/apps/web/src/dialogs/resume/schema.ts b/apps/web/src/dialogs/resume/schema.ts deleted file mode 100644 index 3ef2d7e78..000000000 --- a/apps/web/src/dialogs/resume/schema.ts +++ /dev/null @@ -1,152 +0,0 @@ -import z from "zod"; -import { - awardItemSchema, - certificationItemSchema, - coverLetterItemSchema, - customSectionSchema, - educationItemSchema, - experienceItemSchema, - interestItemSchema, - languageItemSchema, - profileItemSchema, - projectItemSchema, - publicationItemSchema, - referenceItemSchema, - skillItemSchema, - summaryItemSchema, - volunteerItemSchema, -} from "@reactive-resume/schema/resume/data"; - -export const resumeDialogSchemas = [ - z.object({ type: z.literal("resume.create"), data: z.undefined() }), - z.object({ - type: z.literal("resume.update"), - data: z.object({ id: z.string(), name: z.string(), slug: z.string(), tags: z.array(z.string()) }), - }), - z.object({ type: z.literal("resume.import"), data: z.undefined() }), - z.object({ - type: z.literal("resume.duplicate"), - data: z.object({ - id: z.string(), - name: z.string(), - slug: z.string(), - tags: z.array(z.string()), - shouldRedirect: z.boolean().optional(), - }), - }), - z.object({ type: z.literal("resume.template.gallery"), data: z.undefined() }), - z.object({ - type: z.literal("resume.sections.profiles.create"), - data: z.object({ item: profileItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.profiles.update"), - data: z.object({ item: profileItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.experience.create"), - data: z.object({ item: experienceItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.experience.update"), - data: z.object({ item: experienceItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.education.create"), - data: z.object({ item: educationItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.education.update"), - data: z.object({ item: educationItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.projects.create"), - data: z.object({ item: projectItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.projects.update"), - data: z.object({ item: projectItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.skills.create"), - data: z.object({ item: skillItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.skills.update"), - data: z.object({ item: skillItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.languages.create"), - data: z.object({ item: languageItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.languages.update"), - data: z.object({ item: languageItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.awards.create"), - data: z.object({ item: awardItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.awards.update"), - data: z.object({ item: awardItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.certifications.create"), - data: z.object({ item: certificationItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.certifications.update"), - data: z.object({ item: certificationItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.publications.create"), - data: z.object({ item: publicationItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.publications.update"), - data: z.object({ item: publicationItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.interests.create"), - data: z.object({ item: interestItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.interests.update"), - data: z.object({ item: interestItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.volunteer.create"), - data: z.object({ item: volunteerItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.volunteer.update"), - data: z.object({ item: volunteerItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.references.create"), - data: z.object({ item: referenceItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.references.update"), - data: z.object({ item: referenceItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.summary.create"), - data: z.object({ item: summaryItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.summary.update"), - data: z.object({ item: summaryItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ - type: z.literal("resume.sections.cover-letter.create"), - data: z.object({ item: coverLetterItemSchema.optional(), customSectionId: z.string().optional() }).optional(), - }), - z.object({ - type: z.literal("resume.sections.cover-letter.update"), - data: z.object({ item: coverLetterItemSchema, customSectionId: z.string().optional() }), - }), - z.object({ type: z.literal("resume.sections.custom.create"), data: customSectionSchema.optional() }), - z.object({ type: z.literal("resume.sections.custom.update"), data: customSectionSchema }), -] as const; diff --git a/apps/web/src/dialogs/schemas.ts b/apps/web/src/dialogs/schemas.ts index f1b29a0d7..a86778d6b 100644 --- a/apps/web/src/dialogs/schemas.ts +++ b/apps/web/src/dialogs/schemas.ts @@ -1,19 +1,58 @@ -import z from "zod"; -import { apiKeyDialogSchemas } from "./api-key/schema"; -import { authDialogSchemas } from "./auth/schema"; -import { resumeDialogSchemas } from "./resume/schema"; +import type { CoverLetterItem, CustomSection, SectionItem, SummaryItem } from "@reactive-resume/schema/resume/data"; -export const dialogSchemaRegistries = [ - { domain: "auth", schemas: authDialogSchemas }, - { domain: "api-key", schemas: apiKeyDialogSchemas }, - { domain: "resume", schemas: resumeDialogSchemas }, -] as const; +type EmptyDialog = { [K in T]: { type: K; data?: undefined } }[T]; -const dialogSchemaEntries = [...authDialogSchemas, ...apiKeyDialogSchemas, ...resumeDialogSchemas] as const; +type SectionItems = { + profiles: SectionItem<"profiles">; + experience: SectionItem<"experience">; + education: SectionItem<"education">; + projects: SectionItem<"projects">; + skills: SectionItem<"skills">; + languages: SectionItem<"languages">; + interests: SectionItem<"interests">; + awards: SectionItem<"awards">; + certifications: SectionItem<"certifications">; + publications: SectionItem<"publications">; + volunteer: SectionItem<"volunteer">; + references: SectionItem<"references">; + summary: SummaryItem; + "cover-letter": CoverLetterItem; +}; -export const dialogTypeSchema = z.discriminatedUnion("type", dialogSchemaEntries); +type SectionDialog = { + [T in keyof SectionItems]: + | { + type: `resume.sections.${T}.create`; + data?: { item?: SectionItems[T]; customSectionId?: string }; + } + | { + type: `resume.sections.${T}.update`; + data: { item: SectionItems[T]; customSectionId?: string }; + }; +}[keyof SectionItems]; + +export type DialogSchema = + | EmptyDialog< + | "auth.change-password" + | "auth.two-factor.enable" + | "auth.two-factor.disable" + | "api-key.create" + | "resume.create" + | "resume.import" + | "resume.template.gallery" + > + | { + type: "resume.update"; + data: { id: string; name: string; slug: string; tags: string[] }; + } + | { + type: "resume.duplicate"; + data: { id: string; name: string; slug: string; tags: string[]; shouldRedirect?: boolean }; + } + | SectionDialog + | { type: "resume.sections.custom.create"; data?: CustomSection } + | { type: "resume.sections.custom.update"; data: CustomSection }; -export type DialogSchema = z.infer; export type DialogType = DialogSchema["type"]; export type DialogData = Extract["data"]; diff --git a/apps/web/src/dialogs/store.test.ts b/apps/web/src/dialogs/store.test.ts index a15afeebb..370a9d34d 100644 --- a/apps/web/src/dialogs/store.test.ts +++ b/apps/web/src/dialogs/store.test.ts @@ -1,5 +1,4 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { dialogSchemaRegistries, dialogTypeSchema } from "./schemas"; import { useDialogStore } from "./store"; describe("useDialogStore", () => { @@ -14,13 +13,6 @@ describe("useDialogStore", () => { }); describe("openDialog", () => { - it("uses schema entries from domain registries", () => { - expect(dialogSchemaRegistries.map((registry) => registry.domain)).toEqual(["auth", "api-key", "resume"]); - expect(dialogTypeSchema.options).toHaveLength( - dialogSchemaRegistries.reduce((total, registry) => total + registry.schemas.length, 0), - ); - }); - it("opens a dialog and sets activeDialog", () => { useDialogStore.getState().openDialog("api-key.create", undefined); diff --git a/apps/web/src/routes/agent/-components/agent-chat.tsx b/apps/web/src/routes/agent/-components/agent-chat.tsx index 378c30861..74e87855d 100644 --- a/apps/web/src/routes/agent/-components/agent-chat.tsx +++ b/apps/web/src/routes/agent/-components/agent-chat.tsx @@ -1,5 +1,5 @@ import type { AgentUIMessage } from "@reactive-resume/ai/tools/agent-tool-contracts"; -import type { UIMessage, UIMessageChunk } from "ai"; +import type { UIMessage } from "ai"; import type * as React from "react"; import type { RouterOutput } from "@/libs/orpc/client"; import type { PatchApprovalResponse } from "./patch-approval-card"; @@ -25,7 +25,12 @@ import { } from "@phosphor-icons/react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "@tanstack/react-router"; -import { lastAssistantMessageIsCompleteWithApprovalResponses, lastAssistantMessageIsCompleteWithToolCalls } from "ai"; +import { + lastAssistantMessageIsCompleteWithApprovalResponses, + lastAssistantMessageIsCompleteWithToolCalls, + parseJsonEventStream, + uiMessageChunkSchema, +} from "ai"; import { m } from "motion/react"; import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react"; import ReactMarkdown from "react-markdown"; @@ -348,34 +353,18 @@ function textFromMessage(message: UIMessage) { } function parseAgentSseStream(stream: ReadableStream) { - let buffer = ""; - const eventBoundary = /\r?\n\r?\n/; - - return stream.pipeThrough( - new TransformStream({ + return parseJsonEventStream({ + stream: stream.pipeThrough(new TextEncoderStream()), + schema: uiMessageChunkSchema, + }).pipeThrough( + new TransformStream({ transform(chunk, controller) { - buffer += chunk; - - let boundary = eventBoundary.exec(buffer); - while (boundary) { - const event = buffer.slice(0, boundary.index); - buffer = buffer.slice(boundary.index + boundary[0].length); - - for (const line of event.split(/\r?\n/)) { - if (!line.startsWith("data:")) continue; - - const data = line.slice("data:".length).trimStart(); - if (!data || data === "[DONE]") continue; - - try { - controller.enqueue(JSON.parse(data) as UIMessageChunk); - } catch (error) { - console.warn("[agent] dropping malformed SSE frame", error); - } - } - - boundary = eventBoundary.exec(buffer); + if (!chunk.success) { + console.warn("[agent] dropping malformed SSE frame", chunk.error); + return; } + + controller.enqueue(chunk.value); }, }), ); diff --git a/packages/ui/src/components/attachment.tsx b/packages/ui/src/components/attachment.tsx index a2047b2b2..269206887 100644 --- a/packages/ui/src/components/attachment.tsx +++ b/packages/ui/src/components/attachment.tsx @@ -1,10 +1,7 @@ import type { VariantProps } from "class-variance-authority"; import type * as React from "react"; -import { mergeProps } from "@base-ui/react/merge-props"; -import { useRender } from "@base-ui/react/use-render"; import { cva } from "class-variance-authority"; import { cn } from "@reactive-resume/utils/style"; -import { Button } from "./button"; const attachmentVariants = cva( "group/attachment relative flex w-fit min-w-0 max-w-full shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed", @@ -103,59 +100,6 @@ function AttachmentTitle({ className, ...props }: React.ComponentProps<"span">) ); } -function AttachmentDescription({ className, ...props }: React.ComponentProps<"span">) { - return ( - - ); -} - -function AttachmentActions({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ); -} - -function AttachmentAction({ className, variant, size = "icon-xs", ...props }: React.ComponentProps) { - return ( -