refactor: move ui/src/{components,lib}/agents into features/ layout

Part of the domain-reorg adoption (build plan step C6): fork content,
upstream layout. git mv's all 80 pure-rename files from the move-map
(agent-scoped components/lib -> ui/src/features/{agents,automations,
reviews,settings}/...), including ported/ splitting into
features/agents/experiments/ (still-unintegrated desktop-host ports)
and features/agents/components/chat/ (CloudPromptBar, CodeBlock,
DiffView, Logo, Markdown, ReplyCard, ShellCommand, ToolExecution --
files actually wired into the live dashboard). Fork-diverged files
(PlanReview.tsx, WorkflowApprovalCard.tsx, AgentsSidebar.tsx,
SidebarFilterMenu.tsx, AgentGitPanel.tsx, AutomationEditor.tsx,
DiffView.tsx, CloudPromptBar.tsx) keep fork content -- verified via
diff that only import lines changed.

Rewrote @/components/agents and @/lib/agents imports across all 54
importer files plus the moved files' own internal imports (grep-driven,
85-entry alias map covering every old->new path pair). Two hazards
caught only by the build gate (not tsc, since both files sit under the
new experiments/** tsconfig exclude): ui/src/lib/notifications.ts had
a relative `./agents/types` import (no `@/` alias) that the grep missed;
and features/agents/experiments/index.ts's barrel re-export of the
messages module needed to switch from an `@/` alias to a relative
import (`../components/messages`) after landing inside the newly
tsconfig-excluded experiments/ directory -- vite-tsconfig-paths failed
to resolve it at build time even though tsc stayed silent.

AgentPromptBar.tsx (the 2-line CloudPromptBar re-export shim) moves to
features/agents/components/ with its export path retargeted at
CloudPromptBar's new chat/ location -- a D/A pair, not a content loss,
since the import-path edit drops it below git's rename-similarity
threshold. ported/index.ts is the same D/A story for the same reason.

Swapped the 8-file ported/ exclude lists in tsconfig.json and
eslint.config.js for the single `src/features/agents/experiments/**`
glob (upstream's simplification, no behavior change). Deleted
ui/pnpm-workspace.yaml (lockfile hygiene -- bun stays the toolchain).

Gates: bunx tsc --noEmit (clean), bun run build (clean after the two
notifications.ts / experiments-index.ts fixes above), bun run test
(33/33), and the full Playwright E2E suite against the real langgraph
dev server + built dashboard (9/9).
This commit is contained in:
Adam Moussa 2026-07-17 14:51:12 -04:00
parent ae1f883b4c
commit 4d51410dc8
No known key found for this signature in database
99 changed files with 162 additions and 179 deletions

View file

@ -14,14 +14,7 @@ export default [
// Ported from a desktop host app and excluded from tsconfig (not yet
// integrated), so type-aware linting cannot resolve them. Keep this list
// in sync with the `exclude` entries in tsconfig.json.
"src/components/agents/ported/ChatView.tsx",
"src/components/agents/ported/PromptBar.tsx",
"src/components/agents/ported/BranchSelector.tsx",
"src/components/agents/ported/ContextIndicator.tsx",
"src/components/agents/ported/SourceControlPanel.tsx",
"src/components/agents/ported/SourceControlTile.tsx",
"src/components/agents/ported/Footer.tsx",
"src/components/agents/ported/ThreadPicker.tsx",
"src/features/agents/experiments/**",
],
},
...tanstackConfig,

View file

@ -1,3 +0,0 @@
allowBuilds:
esbuild: true
unrs-resolver: true

View file

@ -1,2 +0,0 @@
export { CloudPromptBar as AgentPromptBar } from "@/components/agents/ported/CloudPromptBar";
export type { CloudPromptBarProps as AgentPromptBarProps } from "@/components/agents/ported/CloudPromptBar";

View file

@ -1,18 +0,0 @@
export { BubblePrefix } from "./BubblePrefix";
export { CloudPromptBar } from "./CloudPromptBar";
export { CodeBlock } from "./CodeBlock";
export { CompactingIndicator } from "./CompactingIndicator";
export { DiffView } from "./DiffView";
export { HeaderBar } from "./HeaderBar";
export { Logo } from "./Logo";
export { Markdown } from "./Markdown";
export { MarkdownTable } from "./MarkdownTable";
export {
Messages,
summarizeChangedFiles,
type MessagesScrollControl,
} from "@/components/agents/messages";
export { PanelResizeHandle } from "./PanelResizeHandle";
export { ShellCommand } from "./ShellCommand";
export { TodoList } from "./TodoList";
export { ToolExecution } from "./ToolExecution";

View file

@ -18,13 +18,13 @@ import {
import type { FileContents } from "@pierre/diffs/react"
import type { GitStatus, GitStatusEntry } from "@pierre/trees"
import type { AgentThread, Message } from "@/lib/agents/types"
import type { ThreadPrDiffFile } from "@/lib/agents/api"
import type { ChangedFileSummaryItem } from "@/components/agents/messages"
import { agentsApi } from "@/lib/agents/api"
import { useAgentThreadPrDiff } from "@/lib/agents/queries"
import { ReviewTab } from "@/components/agents/ReviewTab"
import { PrHeader } from "@/components/agents/PrHeader"
import type { AgentThread, Message } from "@/features/agents/lib/types"
import type { ThreadPrDiffFile } from "@/features/agents/lib/api"
import type { ChangedFileSummaryItem } from "@/features/agents/components/messages"
import { agentsApi } from "@/features/agents/lib/api"
import { useAgentThreadPrDiff } from "@/features/agents/lib/queries"
import { ReviewTab } from "@/features/reviews/components/ReviewTab"
import { PrHeader } from "@/features/reviews/components/PrHeader"
import { buttonVariants } from "@/components/ui/button"
import {
DIFF_VIRTUALIZER_CONFIG,
@ -33,9 +33,9 @@ import {
DIFF_WORKER_POOL_OPTIONS,
fileContentsCacheKey,
useDiffOptions,
} from "@/components/agents/utils/diffUtils"
import { summarizeChangedFiles } from "@/components/agents/ported"
import { Z } from "@/components/agents/z-index"
} from "@/features/agents/utils/diffUtils"
import { summarizeChangedFiles } from "@/features/agents/experiments"
import { Z } from "@/features/agents/components/z-index"
import { useIsMobile } from "@/lib/useIsMobile"
import { cn } from "@/lib/utils"

View file

@ -0,0 +1,2 @@
export { CloudPromptBar as AgentPromptBar } from "@/features/agents/components/chat/CloudPromptBar";
export type { CloudPromptBarProps as AgentPromptBarProps } from "@/features/agents/components/chat/CloudPromptBar";

View file

@ -10,7 +10,7 @@ import { IoLogoGithub, IoLogoSlack } from "react-icons/io5"
import { SiLinear } from "react-icons/si"
import type { ComponentType, SVGProps } from "react"
import type { AgentSource, AgentThread } from "@/lib/agents/types"
import type { AgentSource, AgentThread } from "@/features/agents/lib/types"
import { cn, formatRelativeTime } from "@/lib/utils"
type SourceIcon = ComponentType<SVGProps<SVGSVGElement>>

View file

@ -7,23 +7,23 @@ import type {
AgentThread,
Message,
QueuedThreadMessage,
} from "@/lib/agents/types"
import type { ModelSelection } from "@/lib/agents/provider/useModelOptions"
} from "@/features/agents/lib/types"
import type { ModelSelection } from "@/features/agents/lib/provider/useModelOptions"
import {
AgentGitPanel,
PANEL_MIN_CHAT_WIDTH,
readStoredPanelCollapsed,
writeStoredPanelCollapsed,
} from "@/components/agents/AgentGitPanel"
import { AgentPromptBar } from "@/components/agents/AgentPromptBar"
import { Messages } from "@/components/agents/messages"
import { streamMessagesToUi } from "@/lib/agents/streamMessagesToUi"
import { messageArrivalTimestamp } from "@/lib/agents/messageTimestamps"
import { useSubmitAgentMessage } from "@/lib/agents/provider/useSubmitAgentMessage"
import { useModelOptions } from "@/lib/agents/provider/useModelOptions"
} from "@/features/agents/components/AgentGitPanel"
import { AgentPromptBar } from "@/features/agents/components/AgentPromptBar"
import { Messages } from "@/features/agents/components/messages"
import { streamMessagesToUi } from "@/features/agents/lib/streamMessagesToUi"
import { messageArrivalTimestamp } from "@/features/agents/lib/messageTimestamps"
import { useSubmitAgentMessage } from "@/features/agents/lib/provider/useSubmitAgentMessage"
import { useModelOptions } from "@/features/agents/lib/provider/useModelOptions"
import { useIsMobile } from "@/lib/useIsMobile"
import { cn } from "@/lib/utils"
import { WorkflowApprovalCard } from "@/components/agents/WorkflowApprovalCard"
import { WorkflowApprovalCard } from "@/features/agents/components/WorkflowApprovalCard"
interface AgentThreadViewProps {
thread: AgentThread

View file

@ -3,19 +3,19 @@ import { useStreamContext as useAgentThreadStream } from "@langchain/react"
import { useQueryClient } from "@tanstack/react-query"
import { useNavigate } from "@tanstack/react-router"
import type { ImageChunk } from "@/lib/agents/types"
import type { CreateAgentThreadVariables } from "@/lib/agents/queries"
import type { ModelSelection } from "@/lib/agents/provider/useModelOptions"
import { AgentPromptBar } from "@/components/agents/AgentPromptBar"
import { OnboardingDialog } from "@/components/agents/OnboardingDialog"
import { Logo } from "@/components/agents/ported/Logo"
import type { ImageChunk } from "@/features/agents/lib/types"
import type { CreateAgentThreadVariables } from "@/features/agents/lib/queries"
import type { ModelSelection } from "@/features/agents/lib/provider/useModelOptions"
import { AgentPromptBar } from "@/features/agents/components/AgentPromptBar"
import { OnboardingDialog } from "@/features/agents/components/OnboardingDialog"
import { Logo } from "@/features/agents/components/chat/Logo"
import {
agentThreadKeys,
invalidateAgentThreadLists,
optimisticThread,
seedAgentThreadLists,
} from "@/lib/agents/queries"
import { useModelOptions } from "@/lib/agents/provider/useModelOptions"
} from "@/features/agents/lib/queries"
import { useModelOptions } from "@/features/agents/lib/provider/useModelOptions"
import { useProfile, useRepos } from "@/lib/profile"
import {
requestNotificationPermission,

View file

@ -25,10 +25,10 @@ import { useState } from "react"
import type { ComponentType, SVGProps } from "react"
import type { SessionUser } from "@/lib/api"
import type { AgentSource, AgentThread } from "@/lib/agents/types"
import type { AgentSource, AgentThread } from "@/features/agents/lib/types"
import type { SidebarLayout } from "@/components/sidebar-layout"
import { SidebarUserMenu } from "@/components/SidebarUserMenu"
import { SidebarFilterMenu } from "@/components/agents/SidebarFilterMenu"
import { SidebarFilterMenu } from "@/features/agents/components/SidebarFilterMenu"
import { Button } from "@/components/ui/button"
import {
SidebarCollapseButton,
@ -41,15 +41,15 @@ import {
filterThreads,
groupThreadsByMode,
hasActiveFilters,
} from "@/lib/agents/sidebarFilter"
import { useSidebarPrefs } from "@/lib/agents/sidebarPrefs"
} from "@/features/agents/lib/sidebarFilter"
import { useSidebarPrefs } from "@/features/agents/lib/sidebarPrefs"
import {
useDeleteAgentThread,
useResolveAgentThread,
useSeedAgentThreadDetails,
useSidebarThreads,
} from "@/lib/agents/queries"
import { useRunCompletionNotifier } from "@/lib/agents/useRunCompletionNotifier"
} from "@/features/agents/lib/queries"
import { useRunCompletionNotifier } from "@/features/agents/lib/useRunCompletionNotifier"
import { cn } from "@/lib/utils"
const RESOLVED_SIDEBAR_LIMIT = 20

View file

@ -7,10 +7,10 @@ import {
} from "@phosphor-icons/react"
import { useState } from "react"
import type { AgentSource, AgentStatus, AgentThread } from "@/lib/agents/types"
import type { AgentSource, AgentStatus, AgentThread } from "@/features/agents/lib/types"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { useResolveAgentThread, useThreadsPage } from "@/lib/agents/queries"
import { useResolveAgentThread, useThreadsPage } from "@/features/agents/lib/queries"
import { cn } from "@/lib/utils"
const PAGE_SIZE = 25

View file

@ -11,7 +11,7 @@ import {
updatePlan,
} from "@/lib/plan"
import { Button } from "@/components/ui/button"
import { Markdown } from "@/components/agents/ported"
import { Markdown } from "@/features/agents/experiments"
import { useResolvedTheme } from "@/lib/theme"
const POLL_MS = 4000

View file

@ -1,14 +1,14 @@
import { Menu } from "@base-ui/react/menu"
import { CaretRightIcon, CheckIcon, FunnelIcon } from "@phosphor-icons/react"
import type { AgentSource, AgentStatus } from "@/lib/agents/types"
import type { AgentSource, AgentStatus } from "@/features/agents/lib/types"
import type {
PrFilter,
SidebarFacets,
SidebarFilters,
SidebarGroupMode,
} from "@/lib/agents/sidebarFilter"
import type { SidebarPrefs } from "@/lib/agents/sidebarPrefs"
} from "@/features/agents/lib/sidebarFilter"
import type { SidebarPrefs } from "@/features/agents/lib/sidebarPrefs"
import {
GROUP_MODE_OPTIONS,
OWNERSHIP_OPTIONS,
@ -17,7 +17,7 @@ import {
STATUS_FILTER_OPTIONS,
hasActiveFilters,
toggleArrayValue,
} from "@/lib/agents/sidebarFilter"
} from "@/features/agents/lib/sidebarFilter"
import { cn } from "@/lib/utils"
const POPUP_CLASS =

View file

@ -1,11 +1,11 @@
import { useMemo, useState } from "react"
import { ShieldCheck } from "lucide-react"
import type { WorkflowPushApproval } from "@/lib/agents/api"
import type { WorkflowPushApproval } from "@/features/agents/lib/api"
import {
useWorkflowApprovalDecision,
useWorkflowApprovals,
} from "@/lib/agents/queries"
} from "@/features/agents/lib/queries"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"

View file

@ -20,12 +20,12 @@ import {
} from "react"
import type { ModelOption } from "@/lib/api"
import type { ImageChunk } from "@/lib/agents/types"
import type { ModelSelection } from "@/lib/agents/provider/useModelOptions"
import { RepoSelector } from "@/components/agents/RepoSelector"
import { useIsInAgentThreadStream } from "@/lib/agents/provider/useIsInAgentThreadStream"
import { agentThreadKeys, invalidateAgentThreadLists } from "@/lib/agents/queries"
import { formatModelSelection } from "@/lib/agents/provider/useModelOptions"
import type { ImageChunk } from "@/features/agents/lib/types"
import type { ModelSelection } from "@/features/agents/lib/provider/useModelOptions"
import { RepoSelector } from "@/features/settings/components/RepoSelector"
import { useIsInAgentThreadStream } from "@/features/agents/lib/provider/useIsInAgentThreadStream"
import { agentThreadKeys, invalidateAgentThreadLists } from "@/features/agents/lib/queries"
import { formatModelSelection } from "@/features/agents/lib/provider/useModelOptions"
import { IconButton } from "@/components/ui/button"
import { cn } from "@/lib/utils"

View file

@ -1,8 +1,8 @@
import { useMemo } from "react";
import { MultiFileDiff } from "@pierre/diffs/react";
import type { DiffData } from "@/lib/agents/types";
import { diffOptions } from "@/components/agents/utils/diffUtils";
import { countLineChanges } from "@/components/agents/utils/diffStats";
import type { DiffData } from "@/features/agents/lib/types";
import { diffOptions } from "@/features/agents/utils/diffUtils";
import { countLineChanges } from "@/features/agents/utils/diffStats";
interface DiffViewProps {
diffData: DiffData;

View file

@ -2,7 +2,7 @@ import { memo } from "react"
import { MessageCircle } from "lucide-react"
import { Markdown } from "./Markdown"
import type { ReactNode } from "react"
import type { ToolExecutionChunk } from "@/lib/agents/types"
import type { ToolExecutionChunk } from "@/features/agents/lib/types"
interface ReplyCardProps {
chunk: ToolExecutionChunk

View file

@ -1,5 +1,5 @@
import { memo, useCallback, useLayoutEffect, useRef, useState } from "react";
import type { ToolExecutionChunk } from "@/lib/agents/types";
import type { ToolExecutionChunk } from "@/features/agents/lib/types";
interface ShellCommandProps {
chunk: ToolExecutionChunk;

View file

@ -1,9 +1,9 @@
import { memo, useCallback, useLayoutEffect, useMemo, useRef, useState } from "react";
import { MultiFileDiff } from "@pierre/diffs/react";
import { DiffView } from "./DiffView";
import type { AcpToolKind, ToolExecutionChunk } from "@/lib/agents/types";
import { useDiffOptions } from "@/components/agents/utils/diffUtils";
import { countLineChanges } from "@/components/agents/utils/diffStats";
import type { AcpToolKind, ToolExecutionChunk } from "@/features/agents/lib/types";
import { useDiffOptions } from "@/features/agents/utils/diffUtils";
import { countLineChanges } from "@/features/agents/utils/diffStats";
interface ToolExecutionProps {
chunk: ToolExecutionChunk;

View file

@ -9,13 +9,13 @@ import { TurnChangedFilesCard } from "./TurnChangedFilesCard";
import { WorkSummary } from "./WorkSummary";
import type { ReactNode } from "react";
import type { RenderItem } from "./renderItems";
import type { Message } from "@/lib/agents/types";
import type { Message } from "@/features/agents/lib/types";
import type { ApprovalCallbacks, ChangedFileSummaryItem } from "./types";
import { formatHoverTimestamp } from "@/lib/agents/messageTimestamps";
import { SubagentGroup } from "@/components/agents/subagents";
import { ToolExecution } from "@/components/agents/ported/ToolExecution";
import { ShellCommand } from "@/components/agents/ported/ShellCommand";
import { ReplyCard } from "@/components/agents/ported/ReplyCard";
import { formatHoverTimestamp } from "@/features/agents/lib/messageTimestamps";
import { SubagentGroup } from "@/features/agents/components/subagents";
import { ToolExecution } from "@/features/agents/components/chat/ToolExecution";
import { ShellCommand } from "@/features/agents/components/chat/ShellCommand";
import { ReplyCard } from "@/features/agents/components/chat/ReplyCard";
/**
* Render-item types kept visible (not collapsed) when a turn finishes — the

View file

@ -1,8 +1,8 @@
import type { Chunk } from "@/lib/agents/types";
import type { Chunk } from "@/features/agents/lib/types";
import type { ApprovalCallbacks } from "./types";
import { CodeBlock } from "@/components/agents/ported/CodeBlock";
import { Markdown } from "@/components/agents/ported/Markdown";
import { ToolExecution } from "@/components/agents/ported/ToolExecution";
import { CodeBlock } from "@/features/agents/components/chat/CodeBlock";
import { Markdown } from "@/features/agents/components/chat/Markdown";
import { ToolExecution } from "@/features/agents/components/chat/ToolExecution";
export function ChunkRenderer({
chunk,

View file

@ -5,7 +5,7 @@ import { AgentMessage } from "./AgentMessage";
import { ThinkingSpinner } from "./ThinkingSpinner";
import { UserMessage } from "./UserMessage";
import type { MessagesProps } from "./types";
import { useLiveMarkdownMessageId } from "@/lib/agents/provider/useLiveMarkdownMessageId";
import { useLiveMarkdownMessageId } from "@/features/agents/lib/provider/useLiveMarkdownMessageId";
const BOTTOM_LOCK_THRESHOLD_PX = 24;

View file

@ -3,7 +3,7 @@ import { ChevronDown, ChevronUp } from "lucide-react";
import { MultiFileDiff } from "@pierre/diffs/react";
import type { ChangedFileSummaryItem } from "./types";
import { useDiffOptions, warmDiffHighlighter } from "@/components/agents/utils/diffUtils";
import { useDiffOptions, warmDiffHighlighter } from "@/features/agents/utils/diffUtils";
function stripProjectPathForDisplay(path: string, projectPath?: string): string {
if (!projectPath) return path;

View file

@ -1,7 +1,7 @@
import { useCallback, useLayoutEffect, useRef, useState } from "react";
import { MessageTimestamp } from "./MessageTimestamp";
import type { Message } from "@/lib/agents/types";
import type { Message } from "@/features/agents/lib/types";
export function UserMessage({ message }: { message: Message }) {
const text = message.chunks

View file

@ -1,4 +1,4 @@
import type { Chunk, ToolExecutionChunk } from "@/lib/agents/types";
import type { Chunk, ToolExecutionChunk } from "@/features/agents/lib/types";
export type RenderItem =
| { type: "text-chunk"; key: string; chunk: Chunk }

View file

@ -1,7 +1,7 @@
import type { Chunk } from "@/lib/agents/types";
import type { Chunk } from "@/features/agents/lib/types";
import type { ChangedFileSummaryItem } from "./types";
import { countLineChanges } from "@/components/agents/utils/diffStats";
import { countLineChanges } from "@/features/agents/utils/diffStats";
export function summarizeChangedFiles(chunks: Array<Chunk>): Array<ChangedFileSummaryItem> {
const byFile = new Map<string, { filePath: string; originalContent: string | null; modifiedContent: string }>();

View file

@ -1,4 +1,4 @@
import type { Message, Project, QueuedThreadMessage } from "@/lib/agents/types";
import type { Message, Project, QueuedThreadMessage } from "@/features/agents/lib/types";
export interface ChangedFileSummaryItem {
filePath: string;

View file

@ -2,8 +2,8 @@ import { memo } from "react";
import { Bot, Loader2 } from "lucide-react";
import { SubagentActivity } from "./SubagentActivity";
import type { ToolExecutionChunk } from "@/lib/agents/types";
import { useIsInAgentThreadStream } from "@/lib/agents/provider/useIsInAgentThreadStream";
import type { ToolExecutionChunk } from "@/features/agents/lib/types";
import { useIsInAgentThreadStream } from "@/features/agents/lib/provider/useIsInAgentThreadStream";
/** Coerce an unknown tool-argument value to a trimmed string, or `""`. */
function asString(value: unknown): string {

View file

@ -1,5 +1,5 @@
import { SubagentCard } from "./SubagentCard";
import type { ToolExecutionChunk } from "@/lib/agents/types";
import type { ToolExecutionChunk } from "@/features/agents/lib/types";
/** Maximum number of subagent cards rendered per row. */
const MAX_SUBAGENT_COLUMNS = 4;

View file

@ -1,4 +1,4 @@
import type { Author } from '@/lib/agents/types';
import type { Author } from '@/features/agents/lib/types';
interface BubblePrefixProps {
author: Author;

View file

@ -1,14 +1,14 @@
import { useCallback, useRef, useEffect, useState, forwardRef } from "react";
import { useStore } from "../../store";
import { useShallow } from 'zustand/react/shallow';
import { Messages, summarizeChangedFiles } from "@/components/agents/messages";
import { Messages, summarizeChangedFiles } from "@/features/agents/components/messages";
import { PromptBar } from "./PromptBar";
import { TodoList } from "./TodoList";
import { Logo } from "./Logo";
import { ThreadPicker } from "./ThreadPicker";
import { CompactingIndicator } from "./CompactingIndicator";
import { executeCommand } from "../../commands";
import type { Message, ChatMessage, ChatMessageContentBlock, ImageChunk, Thread, ToolExecutionChunk, ScheduledTask as ScheduledTaskType } from "@/lib/agents/types";
import type { Message, ChatMessage, ChatMessageContentBlock, ImageChunk, Thread, ToolExecutionChunk, ScheduledTask as ScheduledTaskType } from "@/features/agents/lib/types";
const PROMPT_CONTENT_WIDTH = "max-w-[44rem]";
const STACKED_STATUS_WIDTH = PROMPT_CONTENT_WIDTH;

View file

@ -13,7 +13,7 @@ import { getModelsForHarness, MODEL_DISPLAY_NAMES, type ModelOption } from '../.
import { ContextIndicator } from './ContextIndicator';
import { WorktreeSelector } from './WorktreeSelector';
import type { Command } from '../../commands';
import type { ApprovalDecision, DiffData, ImageChunk, ModelConfig, PermissionMode, WorktreeType, AcpToolKind } from '@/lib/agents/types';
import type { ApprovalDecision, DiffData, ImageChunk, ModelConfig, PermissionMode, WorktreeType, AcpToolKind } from '@/features/agents/lib/types';
const PERMISSION_OPTIONS: Array<{ value: PermissionMode; label: string }> = [
{ value: 'default', label: 'Default permissions' },

View file

@ -3,8 +3,8 @@
import { useState, useCallback, useRef, memo, useMemo, useEffect } from "react";
import { MultiFileDiff } from "@pierre/diffs/react";
import type { FileContents } from "@pierre/diffs/react";
import type { GitStatusEntry, GitFileStatus } from "@/lib/agents/types";
import { countLineChanges } from "@/components/agents/utils/diffStats";
import type { GitStatusEntry, GitFileStatus } from "@/features/agents/lib/types";
import { countLineChanges } from "@/features/agents/utils/diffStats";
import {
ChevronDown,
ChevronRight,
@ -23,7 +23,7 @@ import {
X,
Undo2,
} from "lucide-react";
import { useDiffOptions } from "@/components/agents/utils/diffUtils";
import { useDiffOptions } from "@/features/agents/utils/diffUtils";
const STATUS_LABELS: Partial<Record<GitFileStatus, string>> = {
"index-modified": "M",

View file

@ -1,6 +1,6 @@
import { MessageSquare } from 'lucide-react';
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import type { Thread } from '@/lib/agents/types';
import type { Thread } from '@/features/agents/lib/types';
import { useStore } from '../../store';
function getTimeGroup(timestamp: number): string {

View file

@ -7,7 +7,7 @@ import {
ListChecks,
Loader2,
} from "lucide-react";
import type { TodoItem } from "@/lib/agents/types";
import type { TodoItem } from "@/features/agents/lib/types";
interface TodoListProps {
todos: Array<TodoItem>;

View file

@ -0,0 +1,18 @@
export { BubblePrefix } from "./BubblePrefix";
export { CloudPromptBar } from "../components/chat/CloudPromptBar";
export { CodeBlock } from "../components/chat/CodeBlock";
export { CompactingIndicator } from "./CompactingIndicator";
export { DiffView } from "../components/chat/DiffView";
export { HeaderBar } from "./HeaderBar";
export { Logo } from "../components/chat/Logo";
export { Markdown } from "../components/chat/Markdown";
export { MarkdownTable } from "./MarkdownTable";
export {
Messages,
summarizeChangedFiles,
type MessagesScrollControl,
} from "../components/messages";
export { PanelResizeHandle } from "./PanelResizeHandle";
export { ShellCommand } from "../components/chat/ShellCommand";
export { TodoList } from "./TodoList";
export { ToolExecution } from "../components/chat/ToolExecution";

View file

@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from "react";
import type { Message } from "@/lib/agents/types";
import type { Message } from "@/features/agents/lib/types";
/** How long run-idle must persist before clearing the live markdown target. */
const LIVE_MARKDOWN_CLEAR_MS = 2000;

View file

@ -1,13 +1,13 @@
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { useStreamContext as useAgentThreadStream } from "@langchain/react"
import type { SendAgentMessageVariables } from "@/lib/agents/queries"
import type { AgentThread } from "@/lib/agents/types"
import { AgentsApiError, agentsApi } from "@/lib/agents/api"
import type { SendAgentMessageVariables } from "@/features/agents/lib/queries"
import type { AgentThread } from "@/features/agents/lib/types"
import { AgentsApiError, agentsApi } from "@/features/agents/lib/api"
import {
agentThreadKeys,
invalidateAgentThreadLists,
} from "@/lib/agents/queries"
} from "@/features/agents/lib/queries"
/**
* Construct the message content for the LangGraph run.

View file

@ -1,6 +1,6 @@
import { useEffect, useRef } from "react"
import type { AgentThread } from "@/lib/agents/types"
import type { AgentThread } from "@/features/agents/lib/types"
import { showRunNotification } from "@/lib/notifications"
const TERMINAL_STATUSES = new Set(["finished", "error", "interrupted"])

View file

@ -8,23 +8,23 @@ import {
} from "@phosphor-icons/react"
import type { ModelOption } from "@/lib/api"
import type { AgentSchedule } from "@/lib/agents/types"
import type { AutomationTemplate } from "@/lib/agents/automation-templates"
import type { ModelSelection } from "@/lib/agents/provider/useModelOptions"
import { RepoSelector } from "@/components/agents/RepoSelector"
import { ScheduleTriggerPicker } from "@/components/agents/ScheduleTriggerPicker"
import type { AgentSchedule } from "@/features/agents/lib/types"
import type { AutomationTemplate } from "@/features/automations/lib/automation-templates"
import type { ModelSelection } from "@/features/agents/lib/provider/useModelOptions"
import { RepoSelector } from "@/features/settings/components/RepoSelector"
import { ScheduleTriggerPicker } from "@/features/automations/components/ScheduleTriggerPicker"
import { Button } from "@/components/ui/button"
import { Switch } from "@/components/ui/switch"
import { describeCron, isDescribableCron } from "@/lib/agents/cron"
import { describeCron, isDescribableCron } from "@/features/automations/lib/cron"
import {
useCreateAgentSchedule,
useDeleteAgentSchedule,
useUpdateAgentSchedule,
} from "@/lib/agents/queries"
} from "@/features/agents/lib/queries"
import {
formatModelSelection,
useModelOptions,
} from "@/lib/agents/provider/useModelOptions"
} from "@/features/agents/lib/provider/useModelOptions"
import { useRepos } from "@/lib/profile"
import { cn } from "@/lib/utils"

View file

@ -1,8 +1,8 @@
import { Link } from "@tanstack/react-router"
import { ClockIcon } from "@phosphor-icons/react"
import { AUTOMATION_TEMPLATES } from "@/lib/agents/automation-templates"
import { describeCron } from "@/lib/agents/cron"
import { AUTOMATION_TEMPLATES } from "@/features/automations/lib/automation-templates"
import { describeCron } from "@/features/automations/lib/cron"
export function AutomationTemplates() {
return (

View file

@ -8,15 +8,15 @@ import {
WarningCircleIcon,
} from "@phosphor-icons/react"
import type { AgentSchedule } from "@/lib/agents/types"
import { AutomationTemplates } from "@/components/agents/AutomationTemplates"
import type { AgentSchedule } from "@/features/agents/lib/types"
import { AutomationTemplates } from "@/features/automations/components/AutomationTemplates"
import { buttonVariants } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import { describeCron } from "@/lib/agents/cron"
import { describeCron } from "@/features/automations/lib/cron"
import {
useAgentSchedules,
useUpdateAgentSchedule,
} from "@/lib/agents/queries"
} from "@/features/agents/lib/queries"
import { cn } from "@/lib/utils"
function formatDate(value?: string | null): string {

View file

@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from "react"
import { CaretRightIcon, ClockIcon, PlusIcon } from "@phosphor-icons/react"
import { CRON_PRESETS } from "@/lib/agents/cron"
import { CRON_PRESETS } from "@/features/automations/lib/cron"
import { cn } from "@/lib/utils"
interface ScheduleTriggerPickerProps {

View file

@ -25,7 +25,7 @@ import { Menu } from "@base-ui/react/menu"
import type { BaseMessage } from "@langchain/core/messages"
import type { ReviewChatThread } from "@/lib/api"
import { Markdown } from "@/components/agents/ported"
import { Markdown } from "@/features/agents/experiments"
import { IconButton } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { Skeleton } from "@/components/ui/skeleton"

View file

@ -64,20 +64,20 @@ import type {
import type {
ReviewSidebarGroup,
ReviewSidebarView,
} from "@/components/agents/ReviewSidebar"
import type { ChatAttachment } from "@/components/agents/ReviewChat"
import type { DiffStyle } from "@/components/agents/utils/diffUtils"
import { Markdown } from "@/components/agents/ported"
import { PrHeader } from "@/components/agents/PrHeader"
} from "@/features/reviews/components/ReviewSidebar"
import type { ChatAttachment } from "@/features/reviews/components/ReviewChat"
import type { DiffStyle } from "@/features/agents/utils/diffUtils"
import { Markdown } from "@/features/agents/experiments"
import { PrHeader } from "@/features/reviews/components/PrHeader"
import {
ReviewChat,
ReviewChatComposerProvider,
useReviewChatComposer,
} from "@/components/agents/ReviewChat"
} from "@/features/reviews/components/ReviewChat"
import {
ReviewSidebarPanel,
renderInlineCode,
} from "@/components/agents/ReviewSidebar"
} from "@/features/reviews/components/ReviewSidebar"
import {
DIFF_VIRTUALIZER_CONFIG,
DIFF_VIRTUAL_METRICS,
@ -86,7 +86,7 @@ import {
fileContentsCacheKey,
useDiffOptions,
warmDiffHighlighter,
} from "@/components/agents/utils/diffUtils"
} from "@/features/agents/utils/diffUtils"
import { IconButton } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import { Textarea } from "@/components/ui/textarea"

View file

@ -17,7 +17,7 @@ import { Skeleton } from "@/components/ui/skeleton"
import {
TREE_UNSAFE_CSS,
treeThemeStyle,
} from "@/components/agents/AgentGitPanel"
} from "@/features/agents/components/AgentGitPanel"
import { cn } from "@/lib/utils"
function reviewFileGitStatus(status: ReviewDiffFile["status"]): GitStatus {

View file

@ -1,8 +1,8 @@
import { useNavigate } from "@tanstack/react-router"
import { useQuery } from "@tanstack/react-query"
import type { AgentThread } from "@/lib/agents/types"
import { ReviewMainBody } from "@/components/agents/ReviewMainBody"
import type { AgentThread } from "@/features/agents/lib/types"
import { ReviewMainBody } from "@/features/reviews/components/ReviewMainBody"
import { api } from "@/lib/api"
// The git panel's "Review" sub-tab: the PR's Open SWE review rendered inline (no

View file

@ -1,4 +1,4 @@
import type { AgentThread } from "./agents/types"
import type { AgentThread } from "@/features/agents/lib/types"
export const NOTIFICATIONS_PREF_KEY = "open-swe-notifications-enabled"

View file

@ -27,7 +27,7 @@ import { api } from "@/lib/api"
import {
useAdminCancelAgentThread,
useThreadsPage,
} from "@/lib/agents/queries"
} from "@/features/agents/lib/queries"
import { RequireLogin } from "@/lib/auth-redirect"
import { useSession } from "@/lib/session"

View file

@ -1,9 +1,9 @@
import { Outlet, createFileRoute, useRouterState } from "@tanstack/react-router"
import { AgentsShell } from "@/components/agents/AgentsSidebar"
import { AgentsShell } from "@/features/agents/components/AgentsSidebar"
import { Skeleton } from "@/components/ui/skeleton"
import agentsCss from "@/styles/agents.css?url"
import { AgentThreadStreamProvider } from "@/lib/agents/AgentThreadStreamProvider"
import { AgentThreadStreamProvider } from "@/features/agents/lib/AgentThreadStreamProvider"
import { RequireLogin } from "@/lib/auth-redirect"
import { useSession } from "@/lib/session"

View file

@ -1,9 +1,9 @@
import { Navigate, createFileRoute } from "@tanstack/react-router"
import { AgentThreadView } from "@/components/agents/AgentThreadView"
import { AgentThreadView } from "@/features/agents/components/AgentThreadView"
import { Skeleton } from "@/components/ui/skeleton"
import { AgentThreadStreamBoundary } from "@/lib/agents/provider/useIsInAgentThreadStream"
import { useAgentThread } from "@/lib/agents/queries"
import { AgentThreadStreamBoundary } from "@/features/agents/lib/provider/useIsInAgentThreadStream"
import { useAgentThread } from "@/features/agents/lib/queries"
export const Route = createFileRoute("/agents/$threadId")({
component: AgentThreadPage,

View file

@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query"
import { useEffect, useState } from "react"
import { ArrowLeft } from "lucide-react"
import { PlanReview } from "@/components/agents/PlanReview"
import { PlanReview } from "@/features/agents/components/PlanReview"
import { buttonVariants } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import { loginUrl } from "@/lib/api"

View file

@ -1,8 +1,8 @@
import { Link, createFileRoute } from "@tanstack/react-router"
import { AutomationEditor } from "@/components/agents/AutomationEditor"
import { AutomationEditor } from "@/features/automations/components/AutomationEditor"
import { Skeleton } from "@/components/ui/skeleton"
import { useAgentSchedules } from "@/lib/agents/queries"
import { useAgentSchedules } from "@/features/agents/lib/queries"
export const Route = createFileRoute("/agents/automations/$scheduleId")({
component: EditAutomationPage,

View file

@ -1,6 +1,6 @@
import { createFileRoute } from "@tanstack/react-router"
import { AutomationsList } from "@/components/agents/AutomationsList"
import { AutomationsList } from "@/features/automations/components/AutomationsList"
export const Route = createFileRoute("/agents/automations/")({
component: AutomationsIndexPage,

View file

@ -1,7 +1,7 @@
import { createFileRoute } from "@tanstack/react-router"
import { AutomationEditor } from "@/components/agents/AutomationEditor"
import { automationTemplateById } from "@/lib/agents/automation-templates"
import { AutomationEditor } from "@/features/automations/components/AutomationEditor"
import { automationTemplateById } from "@/features/automations/lib/automation-templates"
interface NewAutomationSearch {
template?: string

View file

@ -1,6 +1,6 @@
import { createFileRoute } from "@tanstack/react-router"
import { AgentsHome } from "@/components/agents/AgentsHome"
import { AgentsHome } from "@/features/agents/components/AgentsHome"
export const Route = createFileRoute("/agents/")({
component: AgentsIndexPage,

View file

@ -4,8 +4,8 @@ import { useCallback, useEffect, useRef, useState } from "react"
import { ArrowLeftIcon, GitPullRequestIcon } from "@phosphor-icons/react"
import type { PrReviewComment } from "@/lib/api"
import { ReviewCommentsMenu } from "@/components/agents/ReviewCommentsMenu"
import { ReviewMainBody } from "@/components/agents/ReviewMainBody"
import { ReviewCommentsMenu } from "@/features/reviews/components/ReviewCommentsMenu"
import { ReviewMainBody } from "@/features/reviews/components/ReviewMainBody"
import { useSidebarControls } from "@/components/sidebar-layout"
import { Skeleton } from "@/components/ui/skeleton"
import { api } from "@/lib/api"

View file

@ -1,8 +1,8 @@
import { createFileRoute } from "@tanstack/react-router"
import type { AgentSource, AgentStatus } from "@/lib/agents/types"
import type { ThreadsPageFilters } from "@/components/agents/AgentsThreadsPage";
import { AgentsThreadsPage } from "@/components/agents/AgentsThreadsPage"
import type { AgentSource, AgentStatus } from "@/features/agents/lib/types"
import type { ThreadsPageFilters } from "@/features/agents/components/AgentsThreadsPage";
import { AgentsThreadsPage } from "@/features/agents/components/AgentsThreadsPage"
const SOURCES: ReadonlyArray<AgentSource> = [
"dashboard",

View file

@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from "react"
import type { ModelOption } from "@/lib/api"
import { AppShell, SettingsRow, SettingsSection } from "@/components/AppShell"
import { Button } from "@/components/ui/button"
import { RepoSelector } from "@/components/agents/RepoSelector"
import { RepoSelector } from "@/features/settings/components/RepoSelector"
import { Input } from "@/components/ui/input"
import {
Select,

View file

@ -2,15 +2,8 @@
"include": ["**/*.ts", "**/*.tsx", "eslint.config.js", "prettier.config.js", "vite.config.js"],
"exclude": [
// Ported from a desktop host app; not typechecked until integrated (see file headers).
"src/components/agents/ported/ChatView.tsx",
"src/components/agents/ported/PromptBar.tsx",
"src/components/agents/ported/BranchSelector.tsx",
"src/components/agents/ported/ContextIndicator.tsx",
"src/components/agents/ported/SourceControlPanel.tsx",
// Depends on host-provided window.git; live dashboard uses AgentGitPanel instead.
"src/components/agents/ported/SourceControlTile.tsx",
"src/components/agents/ported/Footer.tsx",
"src/components/agents/ported/ThreadPicker.tsx"
"src/features/agents/experiments/**"
],
"compilerOptions": {