diff --git a/.eslintrc.js b/.eslintrc.js index 0482cc6fbc..5d98cfc588 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -119,5 +119,43 @@ module.exports = { "Do not namespace-import lucide-react; use named imports or a finite typed icon registry so icons remain tree-shakeable.", }, ], + + // Tripwire for dissolved global hook groups. src/hooks/ is for genuinely + // cross-cutting hooks; module-owned hooks live next to their consumers. + // Kept so in-flight branches get a pointer to the new homes on rebase. + "no-restricted-imports": [ + "error", + { + patterns: [ + { + group: ["@src/hooks/workStation", "@src/hooks/workStation/*"], + message: + "hooks/workStation was dissolved. Tab-host hooks: @src/hooks/tabHost/*; editor hooks: @src/modules/WorkStation/CodeEditor/hooks/*; browser hooks: @src/modules/WorkStation/Browser/hooks/*; session capture: @src/features/SessionSetup/hooks/*; context menu: @src/scaffold/ContextMenu/*.", + }, + { + group: ["@src/hooks/dependencies", "@src/hooks/dependencies/*"], + message: + "Moved to @src/modules/MainApp/Integrations/hooks/* (usePostPaintGitProbe -> @src/app/root/usePostPaintGitProbe).", + }, + { + group: [ + "@src/hooks/git/sourceControl", + "@src/hooks/git/sourceControl/*", + ], + message: + "Moved to @src/modules/WorkStation/CodeEditor/hooks/sourceControl/* (generateCommitMessage -> @src/api/tauri/git/commitMessage).", + }, + { + group: ["@src/hooks/testRunner", "@src/hooks/testRunner/*"], + message: + "Moved to @src/modules/WorkStation/CodeEditor/hooks/useTestRunner.", + }, + { + group: ["@src/hooks/benchmark", "@src/hooks/benchmark/*"], + message: "Moved to @src/features/BenchmarkPanel/hooks/*.", + }, + ], + }, + ], }, }; diff --git a/src/hooks/git/sourceControl/commitMessageGeneration.ts b/src/api/tauri/git/commitMessage.ts similarity index 100% rename from src/hooks/git/sourceControl/commitMessageGeneration.ts rename to src/api/tauri/git/commitMessage.ts diff --git a/src/app/root/AppBootstrap.tsx b/src/app/root/AppBootstrap.tsx index b7a751275b..0ce5c8adb7 100644 --- a/src/app/root/AppBootstrap.tsx +++ b/src/app/root/AppBootstrap.tsx @@ -22,7 +22,6 @@ import { MultiRepoGitStatusProvider, } from "@src/contexts/git"; import { useDiagnosticsBootstrap } from "@src/diagnostics"; -import { usePostPaintGitProbe } from "@src/hooks/dependencies/usePostPaintGitProbe"; import { useGlobalFlowTracker } from "@src/hooks/flowAwareness"; import { useModelAliasRegistry } from "@src/hooks/models"; import { @@ -46,6 +45,7 @@ import { E2EBootstrap } from "./E2EBootstrap"; import { useAppDeferredInitialization } from "./useAppDeferredInitialization"; import { useAppShellEffects } from "./useAppShellEffects"; import { useFirstPaintSignal } from "./useFirstPaintSignal"; +import { usePostPaintGitProbe } from "./usePostPaintGitProbe"; export const AppBootstrap: FC = () => { const deferredComponentsReady = useAppDeferredInitialization(); diff --git a/src/hooks/dependencies/usePostPaintGitProbe.ts b/src/app/root/usePostPaintGitProbe.ts similarity index 100% rename from src/hooks/dependencies/usePostPaintGitProbe.ts rename to src/app/root/usePostPaintGitProbe.ts diff --git a/src/engines/ChatPanel/InputArea/hooks/__tests__/gitDiffActions.test.ts b/src/engines/ChatPanel/InputArea/hooks/__tests__/gitDiffActions.test.ts index a2863f7857..ce4713b6e3 100644 --- a/src/engines/ChatPanel/InputArea/hooks/__tests__/gitDiffActions.test.ts +++ b/src/engines/ChatPanel/InputArea/hooks/__tests__/gitDiffActions.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { generateCommitMessage } from "@src/hooks/git/sourceControl/commitMessageGeneration"; +import { generateCommitMessage } from "@src/api/tauri/git/commitMessage"; import { GIT_DIFF_COMMIT_PROMPT, diff --git a/src/engines/ChatPanel/blocks/ToolCallBlock/cards/OrgtrackEnvelopeCard.tsx b/src/engines/ChatPanel/blocks/ToolCallBlock/cards/OrgtrackEnvelopeCard.tsx index 5ba6bbcee3..be6f242eff 100644 --- a/src/engines/ChatPanel/blocks/ToolCallBlock/cards/OrgtrackEnvelopeCard.tsx +++ b/src/engines/ChatPanel/blocks/ToolCallBlock/cards/OrgtrackEnvelopeCard.tsx @@ -4,7 +4,7 @@ import React, { useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { parseCloudOrgSelectorValue } from "@src/features/Org2Cloud/org2CloudOrgsAtom"; -import { useWorkStationTabs } from "@src/hooks/workStation/tabs"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { activeStationChatVisibleAtom } from "@src/store/ui/chatPanelAtom"; import { stationModeAtom } from "@src/store/ui/simulatorAtom"; import { createWorkItemDetailTab } from "@src/store/workstation"; diff --git a/src/engines/ChatPanel/hooks/useAiWorkItemCreator.ts b/src/engines/ChatPanel/hooks/useAiWorkItemCreator.ts index d0654aeb96..4384b0f992 100644 --- a/src/engines/ChatPanel/hooks/useAiWorkItemCreator.ts +++ b/src/engines/ChatPanel/hooks/useAiWorkItemCreator.ts @@ -13,7 +13,7 @@ import { allocateCloudAwareStandaloneWorkItemId, allocateCloudAwareWorkItemId, } from "@src/features/Org2Cloud/cloudShortId"; -import { useWorkStationTabs } from "@src/hooks/workStation"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import i18n from "@src/i18n"; import type { AgentDefinition } from "@src/modules/MainApp/AgentOrgs/types"; import { openSessionInNewChatTabAtom } from "@src/store/chatPanel/chatPanelTabsAtom"; diff --git a/src/engines/GitWorkflow/GitHubDiff/index.tsx b/src/engines/GitWorkflow/GitHubDiff/index.tsx index 16a5be40fd..cffe6f20f8 100644 --- a/src/engines/GitWorkflow/GitHubDiff/index.tsx +++ b/src/engines/GitWorkflow/GitHubDiff/index.tsx @@ -22,12 +22,12 @@ import React, { import DiffStatsBadge from "@src/components/DiffStatsBadge"; import { getLanguageFromPath } from "@src/config/languageMap"; -import { useDiff } from "@src/hooks/workStation/git/useDiff"; import { SplitDiffRowComponent, UnifiedDiffRow } from "./DiffRow"; import { DEFAULT_PROPS } from "./config"; import "./index.scss"; import type { DiffHunk, DiffLine, GitHubDiffProps } from "./types"; +import { useDiff } from "./useDiff"; // ============================================ // Main Component diff --git a/src/hooks/workStation/git/useDiff.ts b/src/engines/GitWorkflow/GitHubDiff/useDiff.ts similarity index 100% rename from src/hooks/workStation/git/useDiff.ts rename to src/engines/GitWorkflow/GitHubDiff/useDiff.ts diff --git a/src/engines/Simulator/apps/canvas/CanvasApp.share.test.ts b/src/engines/Simulator/apps/canvas/CanvasApp.share.test.ts index 57c47fabbf..34fd2a2a5b 100644 --- a/src/engines/Simulator/apps/canvas/CanvasApp.share.test.ts +++ b/src/engines/Simulator/apps/canvas/CanvasApp.share.test.ts @@ -71,7 +71,7 @@ vi.mock("../core/useSimulatorAppState", () => ({ }), })); vi.mock("./canvasConfig", () => ({ CANVAS_APP_CONFIG: {} })); -vi.mock("@src/hooks/workStation", () => ({ +vi.mock("@src/hooks/tabHost/useWorkstationTabHeader", () => ({ usePublishWorkstationTabHeader: ({ content }: { content: ReactNode }) => { testState.publishedHeader = content; }, diff --git a/src/engines/Simulator/apps/canvas/CanvasApp.test.ts b/src/engines/Simulator/apps/canvas/CanvasApp.test.ts index d188598827..d3cd83434e 100644 --- a/src/engines/Simulator/apps/canvas/CanvasApp.test.ts +++ b/src/engines/Simulator/apps/canvas/CanvasApp.test.ts @@ -92,7 +92,7 @@ vi.mock("../core/useSimulatorAppState", () => ({ useSimulatorAppState: () => ({ appEvents: testState.appEvents }), })); vi.mock("./canvasConfig", () => ({ CANVAS_APP_CONFIG: {} })); -vi.mock("@src/hooks/workStation", () => ({ +vi.mock("@src/hooks/tabHost/useWorkstationTabHeader", () => ({ usePublishWorkstationTabHeader: ({ content }: { content: ReactNode }) => { testState.publishedHeader = content; }, diff --git a/src/engines/Simulator/apps/canvas/CanvasApp.tsx b/src/engines/Simulator/apps/canvas/CanvasApp.tsx index d2e7b80970..e7b4268d77 100644 --- a/src/engines/Simulator/apps/canvas/CanvasApp.tsx +++ b/src/engines/Simulator/apps/canvas/CanvasApp.tsx @@ -36,7 +36,7 @@ import { getCanvasShareAvailability, useCanvasShareDialog, } from "@src/features/CanvasShare"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { SessionReplayCodeMirrorViewer } from "@src/modules/WorkStation/CodeEditor/SessionReplay/CodePanel/SessionReplayCodeMirrorViewer"; import { PrimarySidebarLayoutWithSections, diff --git a/src/hooks/benchmark/useBenchmarkAgentBatchRun.ts b/src/features/BenchmarkPanel/hooks/useBenchmarkAgentBatchRun.ts similarity index 100% rename from src/hooks/benchmark/useBenchmarkAgentBatchRun.ts rename to src/features/BenchmarkPanel/hooks/useBenchmarkAgentBatchRun.ts diff --git a/src/hooks/benchmark/useBenchmarkTasks.ts b/src/features/BenchmarkPanel/hooks/useBenchmarkTasks.ts similarity index 100% rename from src/hooks/benchmark/useBenchmarkTasks.ts rename to src/features/BenchmarkPanel/hooks/useBenchmarkTasks.ts diff --git a/src/features/BenchmarkPanel/index.tsx b/src/features/BenchmarkPanel/index.tsx index 5df7b7a2e7..742cf10001 100644 --- a/src/features/BenchmarkPanel/index.tsx +++ b/src/features/BenchmarkPanel/index.tsx @@ -21,9 +21,7 @@ import TabPill from "@src/components/TabPill"; import { SURFACE_TOKENS } from "@src/config/surfaceTokens"; import BenchmarkTaskSelector from "@src/features/BenchmarkPanel/BenchmarkTaskSelector"; import { CodeMirrorEditor } from "@src/features/CodeMirror"; -import { useBenchmarkAgentBatchRun } from "@src/hooks/benchmark/useBenchmarkAgentBatchRun"; -import { useBenchmarkTasks } from "@src/hooks/benchmark/useBenchmarkTasks"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { Placeholder, SessionGroupPage, @@ -50,6 +48,9 @@ import { } from "@src/util/data/formatters/date"; import { formatModelNameFull } from "@src/util/formatModelName"; +import { useBenchmarkAgentBatchRun } from "./hooks/useBenchmarkAgentBatchRun"; +import { useBenchmarkTasks } from "./hooks/useBenchmarkTasks"; + type BenchmarkPanelSurface = "taskInfo" | "runList"; interface BenchmarkPanelProps { diff --git a/src/features/SessionSetup/components/ClaudeCodeSessionSetup/index.tsx b/src/features/SessionSetup/components/ClaudeCodeSessionSetup/index.tsx index 4e2ad6f96a..30425cc5f1 100644 --- a/src/features/SessionSetup/components/ClaudeCodeSessionSetup/index.tsx +++ b/src/features/SessionSetup/components/ClaudeCodeSessionSetup/index.tsx @@ -13,10 +13,8 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import InlineAlert from "@src/components/InlineAlert"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; -import { - useClaudeCodeOAuthCapture, - useWebviewPositionSync, -} from "@src/hooks/workStation/sessionCapture"; +import { useClaudeCodeOAuthCapture } from "@src/features/SessionSetup/hooks/useClaudeCodeOAuthCapture"; +import { useWebviewPositionSync } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; import { SectionContainer, SectionRow, diff --git a/src/features/SessionSetup/components/CodexSessionSetup/index.tsx b/src/features/SessionSetup/components/CodexSessionSetup/index.tsx index a16616b720..9ba1492c34 100644 --- a/src/features/SessionSetup/components/CodexSessionSetup/index.tsx +++ b/src/features/SessionSetup/components/CodexSessionSetup/index.tsx @@ -13,10 +13,8 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import InlineAlert from "@src/components/InlineAlert"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; -import { - useCodexOAuthCapture, - useWebviewPositionSync, -} from "@src/hooks/workStation/sessionCapture"; +import { useCodexOAuthCapture } from "@src/features/SessionSetup/hooks/useCodexOAuthCapture"; +import { useWebviewPositionSync } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; import { SectionContainer, SectionRow, diff --git a/src/features/SessionSetup/components/CopilotSessionSetup/index.tsx b/src/features/SessionSetup/components/CopilotSessionSetup/index.tsx index 6d266d3b32..8e4eac5d26 100644 --- a/src/features/SessionSetup/components/CopilotSessionSetup/index.tsx +++ b/src/features/SessionSetup/components/CopilotSessionSetup/index.tsx @@ -19,7 +19,7 @@ import { v4 as uuidv4 } from "uuid"; import Button from "@src/components/Button"; import InlineAlert from "@src/components/InlineAlert"; import Input from "@src/components/Input"; -import { useWebviewPositionSync } from "@src/hooks/workStation/sessionCapture/useWebviewPositionSync"; +import { useWebviewPositionSync } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; import { SectionContainer, SectionRow, diff --git a/src/features/SessionSetup/components/CursorSessionSetup/index.tsx b/src/features/SessionSetup/components/CursorSessionSetup/index.tsx index 6c25973ee0..1b641191e9 100644 --- a/src/features/SessionSetup/components/CursorSessionSetup/index.tsx +++ b/src/features/SessionSetup/components/CursorSessionSetup/index.tsx @@ -19,8 +19,8 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; -import { useCursorSessionCapture } from "@src/hooks/workStation/sessionCapture/useCursorSessionCapture"; -import { useWebviewPositionSync } from "@src/hooks/workStation/sessionCapture/useWebviewPositionSync"; +import { useCursorSessionCapture } from "@src/features/SessionSetup/hooks/useCursorSessionCapture"; +import { useWebviewPositionSync } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; import { SECTION_GAP_CLASSES, SectionContainer, diff --git a/src/features/SessionSetup/components/KiroSessionSetup/index.tsx b/src/features/SessionSetup/components/KiroSessionSetup/index.tsx index d2ba06de5f..a3c83c303c 100644 --- a/src/features/SessionSetup/components/KiroSessionSetup/index.tsx +++ b/src/features/SessionSetup/components/KiroSessionSetup/index.tsx @@ -33,8 +33,8 @@ import InlineAlert from "@src/components/InlineAlert"; import Input from "@src/components/Input"; import Select from "@src/components/Select"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; -import { useKiroSessionCapture } from "@src/hooks/workStation/sessionCapture/useKiroSessionCapture"; -import { useWebviewPositionSync } from "@src/hooks/workStation/sessionCapture/useWebviewPositionSync"; +import { useKiroSessionCapture } from "@src/features/SessionSetup/hooks/useKiroSessionCapture"; +import { useWebviewPositionSync } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; import { SECTION_CONTROL_STYLE, SECTION_GAP_CLASSES, diff --git a/src/hooks/workStation/sessionCapture/__tests__/TEST_CASES.md b/src/features/SessionSetup/hooks/__tests__/TEST_CASES.md similarity index 100% rename from src/hooks/workStation/sessionCapture/__tests__/TEST_CASES.md rename to src/features/SessionSetup/hooks/__tests__/TEST_CASES.md diff --git a/src/hooks/workStation/sessionCapture/__tests__/useOAuthCapture.test.ts b/src/features/SessionSetup/hooks/__tests__/useOAuthCapture.test.ts similarity index 99% rename from src/hooks/workStation/sessionCapture/__tests__/useOAuthCapture.test.ts rename to src/features/SessionSetup/hooks/__tests__/useOAuthCapture.test.ts index 6f7d96b332..8f4443d149 100644 --- a/src/hooks/workStation/sessionCapture/__tests__/useOAuthCapture.test.ts +++ b/src/features/SessionSetup/hooks/__tests__/useOAuthCapture.test.ts @@ -10,7 +10,7 @@ import { isOAuthE2EMockEnabled, parseOAuthCallback, shouldNavigateInWebview, -} from "../useOAuthCapture"; +} from "@src/features/SessionSetup/hooks/useOAuthCapture"; // --------------------------------------------------------------------------- // isOAuthE2EMockEnabled diff --git a/src/hooks/workStation/sessionCapture/__tests__/useWebviewPositionSync.test.ts b/src/features/SessionSetup/hooks/__tests__/useWebviewPositionSync.test.ts similarity index 98% rename from src/hooks/workStation/sessionCapture/__tests__/useWebviewPositionSync.test.ts rename to src/features/SessionSetup/hooks/__tests__/useWebviewPositionSync.test.ts index 41c8de5ba0..abd247fbf7 100644 --- a/src/hooks/workStation/sessionCapture/__tests__/useWebviewPositionSync.test.ts +++ b/src/features/SessionSetup/hooks/__tests__/useWebviewPositionSync.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { PositionSyncHandlers } from "../useWebviewPositionSync"; -import { attachWebviewPositionSync } from "../useWebviewPositionSync"; +import type { PositionSyncHandlers } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; +import { attachWebviewPositionSync } from "@src/features/SessionSetup/hooks/useWebviewPositionSync"; // --------------------------------------------------------------------------- // Fake RAF / timer environment diff --git a/src/hooks/workStation/sessionCapture/useClaudeCodeOAuthCapture.ts b/src/features/SessionSetup/hooks/useClaudeCodeOAuthCapture.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useClaudeCodeOAuthCapture.ts rename to src/features/SessionSetup/hooks/useClaudeCodeOAuthCapture.ts diff --git a/src/hooks/workStation/sessionCapture/useCodexOAuthCapture.ts b/src/features/SessionSetup/hooks/useCodexOAuthCapture.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useCodexOAuthCapture.ts rename to src/features/SessionSetup/hooks/useCodexOAuthCapture.ts diff --git a/src/hooks/workStation/sessionCapture/useCursorSessionCapture.ts b/src/features/SessionSetup/hooks/useCursorSessionCapture.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useCursorSessionCapture.ts rename to src/features/SessionSetup/hooks/useCursorSessionCapture.ts diff --git a/src/hooks/workStation/sessionCapture/useEmbeddedWebview.test.ts b/src/features/SessionSetup/hooks/useEmbeddedWebview.test.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useEmbeddedWebview.test.ts rename to src/features/SessionSetup/hooks/useEmbeddedWebview.test.ts diff --git a/src/hooks/workStation/sessionCapture/useEmbeddedWebview.ts b/src/features/SessionSetup/hooks/useEmbeddedWebview.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useEmbeddedWebview.ts rename to src/features/SessionSetup/hooks/useEmbeddedWebview.ts diff --git a/src/hooks/workStation/sessionCapture/useKiroSessionCapture.ts b/src/features/SessionSetup/hooks/useKiroSessionCapture.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useKiroSessionCapture.ts rename to src/features/SessionSetup/hooks/useKiroSessionCapture.ts diff --git a/src/hooks/workStation/sessionCapture/useOAuthCapture.ts b/src/features/SessionSetup/hooks/useOAuthCapture.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useOAuthCapture.ts rename to src/features/SessionSetup/hooks/useOAuthCapture.ts diff --git a/src/hooks/workStation/sessionCapture/useWebviewPositionSync.ts b/src/features/SessionSetup/hooks/useWebviewPositionSync.ts similarity index 100% rename from src/hooks/workStation/sessionCapture/useWebviewPositionSync.ts rename to src/features/SessionSetup/hooks/useWebviewPositionSync.ts diff --git a/src/features/TaskKanban/hooks/useTaskKanbanHeader.tsx b/src/features/TaskKanban/hooks/useTaskKanbanHeader.tsx index 11208c7e5d..61c95aff35 100644 --- a/src/features/TaskKanban/hooks/useTaskKanbanHeader.tsx +++ b/src/features/TaskKanban/hooks/useTaskKanbanHeader.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from "react"; import type { KanbanTask } from "@src/features/KanbanBoard"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import DiaryDateControls from "../components/DiaryDateControls"; import type { FactoryViewMode } from "../components/FactoryViewPill"; diff --git a/src/hooks/benchmark/useBenchmarkRun.ts b/src/hooks/benchmark/useBenchmarkRun.ts deleted file mode 100644 index 94d44fc975..0000000000 --- a/src/hooks/benchmark/useBenchmarkRun.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { useAtom, useAtomValue } from "jotai"; -import { useCallback, useEffect } from "react"; - -import { - BENCHMARK_EVALUATION_MODE, - BENCHMARK_RUN_STATUS, - benchmarkApi, -} from "@src/api/tauri/benchmark"; -import { - benchmarkEvaluationModeAtom, - benchmarkKindAtom, - benchmarkPatchTextAtom, - benchmarkPreflightAtom, - benchmarkRunErrorAtom, - benchmarkRunLoadingAtom, - benchmarkRunPlanAtom, - benchmarkRunStatusAtom, - benchmarkSelectedTaskIdAtom, - benchmarkSourcePathAtom, - benchmarkTargetRepoPathAtom, -} from "@src/store/benchmark"; - -const RUN_STATUS_POLL_INTERVAL_MS = 2_000; - -export function useBenchmarkRun() { - const kind = useAtomValue(benchmarkKindAtom); - const sourcePath = useAtomValue(benchmarkSourcePathAtom); - const selectedTaskId = useAtomValue(benchmarkSelectedTaskIdAtom); - const [evaluationMode, setEvaluationMode] = useAtom( - benchmarkEvaluationModeAtom - ); - const [targetRepoPath, setTargetRepoPath] = useAtom( - benchmarkTargetRepoPathAtom - ); - const [patchText, setPatchText] = useAtom(benchmarkPatchTextAtom); - const [preflight, setPreflight] = useAtom(benchmarkPreflightAtom); - const [runPlan, setRunPlan] = useAtom(benchmarkRunPlanAtom); - const [runStatus, setRunStatus] = useAtom(benchmarkRunStatusAtom); - const [isRunLoading, setIsRunLoading] = useAtom(benchmarkRunLoadingAtom); - const [runError, setRunError] = useAtom(benchmarkRunErrorAtom); - - const refreshPreflight = useCallback(async () => { - setRunError(null); - const result = await benchmarkApi.preflight({ - kind, - sourcePath, - evaluationMode, - taskId: selectedTaskId ?? undefined, - repoPath: - evaluationMode === BENCHMARK_EVALUATION_MODE.PATCH_ONLY - ? targetRepoPath - : undefined, - }); - setPreflight(result); - return result; - }, [ - evaluationMode, - kind, - selectedTaskId, - setPreflight, - setRunError, - sourcePath, - targetRepoPath, - ]); - - const createRunPlan = useCallback(async () => { - if (!selectedTaskId) { - throw new Error("Select a benchmark task before creating a run plan."); - } - setIsRunLoading(true); - setRunError(null); - try { - const plan = await benchmarkApi.createRunPlan({ - kind, - sourcePath, - taskId: selectedTaskId, - patch: patchText, - evaluationMode, - repoPath: - evaluationMode === BENCHMARK_EVALUATION_MODE.PATCH_ONLY - ? targetRepoPath - : undefined, - }); - setRunPlan(plan); - setPreflight(plan.preflight); - return plan; - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - setRunError(message); - throw error; - } finally { - setIsRunLoading(false); - } - }, [ - evaluationMode, - kind, - patchText, - selectedTaskId, - setIsRunLoading, - setPreflight, - setRunError, - setRunPlan, - sourcePath, - targetRepoPath, - ]); - - const startRun = useCallback(async () => { - if (!selectedTaskId) { - throw new Error( - "Select a benchmark task before starting a benchmark run." - ); - } - setIsRunLoading(true); - setRunError(null); - try { - const status = await benchmarkApi.startRun({ - kind, - sourcePath, - taskId: selectedTaskId, - patch: patchText, - evaluationMode, - repoPath: - evaluationMode === BENCHMARK_EVALUATION_MODE.PATCH_ONLY - ? targetRepoPath - : undefined, - }); - setRunStatus(status); - return status; - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - setRunError(message); - throw error; - } finally { - setIsRunLoading(false); - } - }, [ - evaluationMode, - kind, - patchText, - selectedTaskId, - setIsRunLoading, - setRunError, - setRunStatus, - sourcePath, - targetRepoPath, - ]); - - const cancelRun = useCallback(async () => { - if (!runStatus?.runId) return; - setIsRunLoading(true); - setRunError(null); - try { - const status = await benchmarkApi.cancelRun({ runId: runStatus.runId }); - setRunStatus(status); - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - setRunError(message); - } finally { - setIsRunLoading(false); - } - }, [runStatus?.runId, setIsRunLoading, setRunError, setRunStatus]); - - useEffect(() => { - if ( - !runStatus?.runId || - runStatus.status !== BENCHMARK_RUN_STATUS.RUNNING - ) { - return; - } - - let cancelled = false; - const intervalId = window.setInterval(() => { - benchmarkApi - .getRunStatus({ runId: runStatus.runId }) - .then((status) => { - if (!cancelled) { - setRunStatus(status); - } - }) - .catch((error) => { - if (!cancelled) { - setRunError(error instanceof Error ? error.message : String(error)); - } - }); - }, RUN_STATUS_POLL_INTERVAL_MS); - - return () => { - cancelled = true; - window.clearInterval(intervalId); - }; - }, [runStatus?.runId, runStatus?.status, setRunError, setRunStatus]); - - return { - cancelRun, - createRunPlan, - evaluationMode, - isRunLoading, - patchText, - preflight, - refreshPreflight, - runError, - runPlan, - runStatus, - setEvaluationMode, - setPatchText, - setTargetRepoPath, - startRun, - targetRepoPath, - }; -} diff --git a/src/hooks/dependencies/index.ts b/src/hooks/dependencies/index.ts deleted file mode 100644 index 86bbdfd552..0000000000 --- a/src/hooks/dependencies/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./useSystemDependencies"; -export * from "./usePrerequisiteCheck"; diff --git a/src/hooks/git/index.ts b/src/hooks/git/index.ts index a755173832..cfbea67ef8 100644 --- a/src/hooks/git/index.ts +++ b/src/hooks/git/index.ts @@ -49,4 +49,3 @@ export { useGitBlame } from "./useGitBlame"; export type { UseGitBlameOptions, UseGitBlameReturn } from "./useGitBlame"; // Source control hooks (for git file list, diff caching, commit form) -export { useCommitForm, useFileSelection, useGitFiles } from "./sourceControl"; diff --git a/src/hooks/git/sourceControl/index.ts b/src/hooks/git/sourceControl/index.ts deleted file mode 100644 index 44664bc9dc..0000000000 --- a/src/hooks/git/sourceControl/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Source Control Hooks - * - * Hooks for git source control state management. - * Used by useSourceControlState in the CodeEditor. - */ - -export { useCommitForm } from "./useCommitForm"; -export type { - UseCommitFormOptions, - UseCommitFormResult, -} from "./useCommitForm"; - -export { useFileSelection } from "./useFileSelection"; -export type { - UseFileSelectionOptions, - UseFileSelectionResult, -} from "./useFileSelection"; - -export { useGitFiles } from "./useGitFiles"; -export type { UseGitFilesOptions, UseGitFilesResult } from "./useGitFiles"; - -export { buildContentFromHunks } from "@src/util/git/buildContentFromHunks"; diff --git a/src/hooks/index.ts b/src/hooks/index.ts deleted file mode 100644 index 57757a0ccc..0000000000 --- a/src/hooks/index.ts +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Hooks Index - * - * Centralized exports for all custom hooks organized by category. - * All hooks have been reorganized into logical categories for better maintainability. - */ - -// ============================================ -// Async Data Utilities -// ============================================ -export * from "./async"; - -// ============================================ -// Session Management -// ============================================ -export * from "@src/engines/SessionCore/hooks"; - -// ============================================ -// Workflow Management -// ============================================ -// Note: workflow hooks removed - module does not exist - -// ============================================ -// Git Operations -// ============================================ -export * from "./git"; - -// ============================================ -// Workstation (Editor, Database, Browser) -// ============================================ -export * from "./workStation"; - -// ============================================ -// UI Components -// ============================================ -export * from "./ui"; - -// ============================================ -// Theme & Visual -// ============================================ -export * from "./theme"; - -// ============================================ -// Skills hub / editor (Tauri — not marketplace UI) -// ============================================ -export * from "./skills"; - -// ============================================ -// Configuration & Settings -// ============================================ -export * from "./config"; - -// ============================================ -// Navigation & Shortcuts -// ============================================ -export * from "./navigation"; - -// ============================================ -// Keyboard Utilities -// ============================================ -export * from "./keyboard"; - -// ============================================ -// Search & Filtering -// ============================================ -export * from "./search"; - -// ============================================ -// Platform Integration -// ============================================ -export * from "./platform"; - -// ============================================ -// Activity Simulator -// ============================================ -// Note: simulator hooks removed - module does not exist - -// ============================================ -// Dropdown Utilities -// ============================================ -export * from "./dropdown"; - -// ============================================ -// Performance Monitoring -// ============================================ -export * from "./perf"; - -// ============================================ -// Flow Awareness (User Activity Tracking) -// ============================================ -export * from "./flowAwareness"; diff --git a/src/hooks/workStation/tabs/useCloseTabWithGuard.ts b/src/hooks/tabHost/useCloseTabWithGuard.ts similarity index 100% rename from src/hooks/workStation/tabs/useCloseTabWithGuard.ts rename to src/hooks/tabHost/useCloseTabWithGuard.ts diff --git a/src/hooks/workStation/tabs/useFocusTab.ts b/src/hooks/tabHost/useFocusTab.ts similarity index 100% rename from src/hooks/workStation/tabs/useFocusTab.ts rename to src/hooks/tabHost/useFocusTab.ts diff --git a/src/hooks/workStation/tabs/usePinnedTabs.ts b/src/hooks/tabHost/usePinnedTabs.ts similarity index 100% rename from src/hooks/workStation/tabs/usePinnedTabs.ts rename to src/hooks/tabHost/usePinnedTabs.ts diff --git a/src/hooks/workStation/tabs/useSelectedFile.ts b/src/hooks/tabHost/useSelectedFile.ts similarity index 100% rename from src/hooks/workStation/tabs/useSelectedFile.ts rename to src/hooks/tabHost/useSelectedFile.ts diff --git a/src/hooks/workStation/tabs/useUrlPreviewEvents.ts b/src/hooks/tabHost/useUrlPreviewEvents.ts similarity index 100% rename from src/hooks/workStation/tabs/useUrlPreviewEvents.ts rename to src/hooks/tabHost/useUrlPreviewEvents.ts diff --git a/src/hooks/workStation/panels/useWorkStationPanels.ts b/src/hooks/tabHost/useWorkStationPanels.ts similarity index 100% rename from src/hooks/workStation/panels/useWorkStationPanels.ts rename to src/hooks/tabHost/useWorkStationPanels.ts diff --git a/src/hooks/workStation/useWorkStationTabShortcutBridge.ts b/src/hooks/tabHost/useWorkStationTabShortcutBridge.ts similarity index 100% rename from src/hooks/workStation/useWorkStationTabShortcutBridge.ts rename to src/hooks/tabHost/useWorkStationTabShortcutBridge.ts diff --git a/src/hooks/workStation/tabs/__tests__/useWorkStationTabs.test.ts b/src/hooks/tabHost/useWorkStationTabs.test.ts similarity index 100% rename from src/hooks/workStation/tabs/__tests__/useWorkStationTabs.test.ts rename to src/hooks/tabHost/useWorkStationTabs.test.ts diff --git a/src/hooks/workStation/tabs/useWorkStationTabs.ts b/src/hooks/tabHost/useWorkStationTabs.ts similarity index 100% rename from src/hooks/workStation/tabs/useWorkStationTabs.ts rename to src/hooks/tabHost/useWorkStationTabs.ts diff --git a/src/hooks/workStation/useWorkstationTabHeader.ts b/src/hooks/tabHost/useWorkstationTabHeader.ts similarity index 100% rename from src/hooks/workStation/useWorkstationTabHeader.ts rename to src/hooks/tabHost/useWorkstationTabHeader.ts diff --git a/src/hooks/testRunner/index.ts b/src/hooks/testRunner/index.ts deleted file mode 100644 index ad8b24d30f..0000000000 --- a/src/hooks/testRunner/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Test Runner Hooks Exports - */ -export { - useTestRunner, - type UseTestRunnerOptions, - type UseTestRunnerReturn, -} from "./useTestRunner"; diff --git a/src/hooks/workStation/browser/index.ts b/src/hooks/workStation/browser/index.ts deleted file mode 100644 index 84a907bec5..0000000000 --- a/src/hooks/workStation/browser/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Browser-specific hooks for WorkStation - * - * These hooks are specific to the Browser tool (web browser, designer). - * Note: useBrowserPaneState is exported first to avoid circular dependency issues - */ -export { useBrowserPaneState } from "./useBrowserPaneState"; -export type { UseBrowserPaneStateReturn } from "./useBrowserPaneState"; - -// useBrowserSessions has external dependencies, exported last -export { useBrowserSessions } from "./useBrowserSessions"; -export type { UseBrowserSessionsReturn } from "./useBrowserSessions"; diff --git a/src/hooks/workStation/database/index.ts b/src/hooks/workStation/database/index.ts deleted file mode 100644 index c3142d259b..0000000000 --- a/src/hooks/workStation/database/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useDbPreview } from "./useDbPreview"; diff --git a/src/hooks/workStation/diagnostics/index.ts b/src/hooks/workStation/diagnostics/index.ts deleted file mode 100644 index 8810858ef3..0000000000 --- a/src/hooks/workStation/diagnostics/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { useDiagnostics } from "./useDiagnostics"; -export { useDiagnosticHealth } from "./useDiagnosticHealth"; -export type { SourceStatusMessage } from "./useDiagnosticHealth"; -export { useLspDiagnostics } from "./useLspDiagnostics"; diff --git a/src/hooks/workStation/editor/index.ts b/src/hooks/workStation/editor/index.ts deleted file mode 100644 index 2180303841..0000000000 --- a/src/hooks/workStation/editor/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Editor-specific hooks for WorkStation - * - * These hooks are specific to the CodeEditor (code editor). - */ -export { useCodeEditorEvents } from "./useCodeEditorEvents"; -export type { CodeEditorEventsOptions } from "./useCodeEditorEvents"; - -export { useCodeEditorHandlers } from "./useCodeEditorHandlers"; -export { useFileContent } from "./useFileContent"; -export type { - FileError, - UseFileContentOptions, - UseFileContentReturn, -} from "./useFileContent"; -export { - clearFileCache, - clearUnsavedContentCache, - invalidateFileCache, - onExternalFileChange, - subscribeToFileChanges, - updateCachedFileMtime, -} from "./useFileContent"; -export { useOpenEditorFiles } from "./useOpenEditorFiles"; -export type { UseOpenEditorFilesResult } from "./useOpenEditorFiles"; diff --git a/src/hooks/workStation/fileContent/index.ts b/src/hooks/workStation/fileContent/index.ts deleted file mode 100644 index 0c6882b19c..0000000000 --- a/src/hooks/workStation/fileContent/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -export { - cacheFileMetadata, - cacheUnsavedContent, - clearFileCache, - clearUnsavedContentCache, - getCachedBinaryStatus, - getCachedFileMetadata, - hasLoadedFileThisSession, - invalidateFileCache, - markFileLoadedThisSession, - onExternalFileChange, - popUnsavedContent, - subscribeToFileChanges, - updateCachedFileMtime, -} from "./cache"; -export { MAX_EDIT_LOG_SIZE } from "./constants"; -export { classifyFileError } from "./errors"; -export { fetchFileMtime } from "./mtime"; -export type { - FileError, - UnsavedContentCache, - UseFileContentOptions, - UseFileContentReturn, -} from "./types"; diff --git a/src/hooks/workStation/git/index.ts b/src/hooks/workStation/git/index.ts deleted file mode 100644 index c7314c209a..0000000000 --- a/src/hooks/workStation/git/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { useDiff } from "./useDiff"; -export type { - DiffHunk, - SplitDiffRow, - UseDiffReturn, -} from "@src/engines/GitWorkflow/GitHubDiff/types"; - -export { useGitDiffState } from "./useGitDiffState"; -export type { UseGitDiffStateReturn } from "./useGitDiffState"; diff --git a/src/hooks/workStation/index.ts b/src/hooks/workStation/index.ts deleted file mode 100644 index 6abb0127d1..0000000000 --- a/src/hooks/workStation/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -// Editor & Code Hooks -export { useDiff } from "./git/useDiff"; -export { useContextMenu } from "./panels/useContextMenu"; -export { useCodeSearch } from "./search/useCodeSearch"; -export type { CodeSearchMode, CodeSearchResult } from "./search/useCodeSearch"; - -// Incremental Indexing -export { useIncrementalIndexing } from "./indexing/useIncrementalIndexing"; -export type { - UseIncrementalIndexingOptions, - UseIncrementalIndexingReturn, -} from "./indexing/useIncrementalIndexing"; -export { useFileWatchIndexing } from "./indexing/useFileWatchIndexing"; -export type { - UseFileWatchIndexingOptions, - UseFileWatchIndexingReturn, -} from "./indexing/useFileWatchIndexing"; - -export { useCursorSessionCapture } from "./sessionCapture/useCursorSessionCapture"; -export { - useWorkStationPanels, - usePrimarySidebarState, - useBottomPanelState, -} from "./panels/useWorkStationPanels"; -export { usePanelResize } from "./panels/usePanelResize"; -export { useTabSwitchVerification } from "./tabs/useTabSwitchVerification"; -export { useSelectedFile } from "./tabs/useSelectedFile"; - -// Unified tab management -export { - useWorkStationTabs, - useCloseTabWithGuard, - useFocusTab, - usePinnedTabs, -} from "./tabs"; -export type { UseWorkStationTabsReturn } from "./tabs"; - -// Browser-specific hooks - import directly from files to avoid circular dependencies -// DO NOT re-export from ./browser index due to circular dependency issues -// Import directly: import { useBrowserPaneState } from "@src/hooks/workStation/browser/useBrowserPaneState" -// Import directly: import { useBrowserSessions } from "@src/hooks/workStation/browser/useBrowserSessions" - -// Editor-specific hooks -export { useCodeEditorEvents } from "./editor/useCodeEditorEvents"; -export type { CodeEditorEventsOptions } from "./editor/useCodeEditorEvents"; - -export { useWorkStationTabShortcutBridge } from "./useWorkStationTabShortcutBridge"; -export type { WorkStationTabShortcutBridgeOptions } from "./useWorkStationTabShortcutBridge"; - -export { usePublishWorkstationTabHeader } from "./useWorkstationTabHeader"; -export type { WorkstationTabHeaderHost } from "./useWorkstationTabHeader"; - -export { - useNarrowChatFocus, - NARROW_CHAT_FOCUS_BREAKPOINT_PX, -} from "./useNarrowChatFocus"; diff --git a/src/hooks/workStation/indexing/index.ts b/src/hooks/workStation/indexing/index.ts deleted file mode 100644 index 183ac615f7..0000000000 --- a/src/hooks/workStation/indexing/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export { useIncrementalIndexing } from "./useIncrementalIndexing"; -export type { - UseIncrementalIndexingOptions, - UseIncrementalIndexingReturn, -} from "./useIncrementalIndexing"; - -export { useFileWatchIndexing } from "./useFileWatchIndexing"; -export type { - UseFileWatchIndexingOptions, - UseFileWatchIndexingReturn, -} from "./useFileWatchIndexing"; diff --git a/src/hooks/workStation/indexing/useFileWatchIndexing.ts b/src/hooks/workStation/indexing/useFileWatchIndexing.ts deleted file mode 100644 index aec6c0bab1..0000000000 --- a/src/hooks/workStation/indexing/useFileWatchIndexing.ts +++ /dev/null @@ -1,297 +0,0 @@ -/** - * useFileWatchIndexing Hook - * - * Integrates file watching events with incremental indexing. - * Listens for file changes and triggers re-indexing of modified files. - */ -import { useCallback, useEffect, useRef } from "react"; - -import { getCodeEditorWebSocket } from "@src/api/realtime/codeEditorWebSocket"; - -import { useIncrementalIndexing } from "./useIncrementalIndexing"; - -// ============================================ -// Types -// ============================================ - -export interface UseFileWatchIndexingOptions { - /** Repository ID */ - repoId: string; - /** Repository path */ - repoPath: string; - /** Whether file watch indexing is enabled (default: true) */ - enabled?: boolean; - /** File extensions to index (default: common code files) */ - indexExtensions?: string[]; - /** Directories to exclude from indexing */ - excludeDirs?: string[]; - /** Callback when a file is marked dirty */ - onFileDirty?: ( - filePath: string, - changeType: "modify" | "create" | "delete" - ) => void; - /** Callback when incremental indexing completes */ - onIndexComplete?: (filesUpdated: number) => void; -} - -export interface UseFileWatchIndexingReturn { - /** Number of files pending re-indexing */ - pendingCount: number; - /** Whether incremental indexing is in progress */ - isIndexing: boolean; - /** Manually trigger re-indexing of pending files */ - flushPendingFiles: () => Promise; - /** Clear pending files without indexing */ - clearPendingFiles: () => void; -} - -// ============================================ -// Constants -// ============================================ - -const DEFAULT_INDEX_EXTENSIONS = [ - ".ts", - ".tsx", - ".js", - ".jsx", - ".py", - ".rs", - ".go", - ".java", - ".c", - ".cpp", - ".h", - ".hpp", - ".cs", - ".rb", - ".php", - ".swift", - ".kt", - ".scala", - ".md", - ".json", - ".yaml", - ".yml", - ".toml", - ".xml", - ".html", - ".css", - ".scss", - ".less", - ".sql", - ".sh", - ".bash", - ".zsh", -]; - -const DEFAULT_EXCLUDE_DIRS = [ - "node_modules", - ".git", - "dist", - "build", - ".next", - "target", - ".cache", - "coverage", - "__pycache__", - ".venv", - "venv", -]; - -// ============================================ -// Hook Implementation -// ============================================ - -export function useFileWatchIndexing( - options: UseFileWatchIndexingOptions -): UseFileWatchIndexingReturn { - const { - repoId, - repoPath, - enabled = true, - indexExtensions = DEFAULT_INDEX_EXTENSIONS, - excludeDirs = DEFAULT_EXCLUDE_DIRS, - onFileDirty, - onIndexComplete, - } = options; - - // Use incremental indexing hook - const { - markDirty, - flushDirtyFiles, - dirtyCount, - isIndexing, - clearDirtyFiles, - } = useIncrementalIndexing({ - repoId, - repoPath, - enabled, - onIndexComplete: (result) => { - onIndexComplete?.(result.filesUpdated); - }, - }); - - // Track previous files for change detection - const previousFilesRef = useRef< - Map - >(new Map()); - - // Check if a file should be indexed based on extension and path - const shouldIndexFile = useCallback( - (filePath: string): boolean => { - // Check exclusions - for (const excludeDir of excludeDirs) { - if ( - filePath.includes(`/${excludeDir}/`) || - filePath.startsWith(`${excludeDir}/`) - ) { - return false; - } - } - - // Check extension - const extension = filePath.substring(filePath.lastIndexOf(".")); - return indexExtensions.includes(extension.toLowerCase()); - }, - [indexExtensions, excludeDirs] - ); - - // Main effect: Set up WebSocket event listeners for file changes - useEffect(() => { - if (!enabled || !repoId) return; - - const ws = getCodeEditorWebSocket(); - if (!ws) return; - - let mounted = true; - const unsubscribeFns: Array<() => void> = []; - - // Reset previous files when repo changes - previousFilesRef.current.clear(); - - // Listen to repo:status_updated events for file changes - const unsubscribe1 = ws.on("repo:status_updated", (data) => { - if (!mounted) return; - - const payload = data as { - type: string; - repo_id: string; - status: { - files?: Array<{ - path: string; - status: string; - staged: boolean; - }>; - }; - }; - - if (payload.repo_id !== repoId) return; - - const files = payload.status?.files || []; - const currentFiles = new Map< - string, - { status: string; staged: boolean } - >(); - - // Build current state - for (const file of files) { - currentFiles.set(file.path, { - status: file.status, - staged: file.staged, - }); - } - - // Compare with previous state to detect changes - const previousFiles = previousFilesRef.current; - - // Find new or modified files - for (const [path, file] of currentFiles) { - const prev = previousFiles.get(path); - // Remove leading slash if present - const relativePath = path.replace(/^\//, ""); - - if (!shouldIndexFile(relativePath)) continue; - - if (!prev) { - // New file in git status - const changeType = file.status === "?" ? "create" : "modify"; - markDirty(relativePath, changeType); - onFileDirty?.(relativePath, changeType); - } else if (prev.status !== file.status) { - // Status changed - file was modified - markDirty(relativePath, "modify"); - onFileDirty?.(relativePath, "modify"); - } - } - - // Find removed files (were in git status, now clean or deleted) - for (const [path] of previousFiles) { - if (!currentFiles.has(path)) { - const relativePath = path.replace(/^\//, ""); - if (shouldIndexFile(relativePath)) { - // File is now clean or was deleted - // We can't easily distinguish, so treat as modify - // (if deleted, the index update will handle it) - markDirty(relativePath, "modify"); - onFileDirty?.(relativePath, "modify"); - } - } - } - - // Update previous state - previousFilesRef.current = currentFiles; - }); - unsubscribeFns.push(unsubscribe1); - - return () => { - mounted = false; - for (const fn of unsubscribeFns) { - try { - fn(); - } catch (_e) { - // Ignore cleanup errors - } - } - }; - }, [enabled, repoId, markDirty, shouldIndexFile, onFileDirty]); - - // Listen for manual file save events (editor internal saves) - useEffect(() => { - if (!enabled) return; - - const handleFileSaved = (event: Event) => { - const customEvent = event as CustomEvent<{ path: string }>; - const filePath = customEvent.detail.path; - const relativePath = filePath.replace(repoPath, "").replace(/^[/\\]/, ""); - - if (shouldIndexFile(relativePath)) { - markDirty(relativePath, "modify"); - onFileDirty?.(relativePath, "modify"); - } - }; - - window.addEventListener("filesync:file-saved", handleFileSaved); - - return () => { - window.removeEventListener("filesync:file-saved", handleFileSaved); - }; - }, [enabled, repoPath, markDirty, shouldIndexFile, onFileDirty]); - - // Public methods - const flushPendingFiles = useCallback(async () => { - await flushDirtyFiles(); - }, [flushDirtyFiles]); - - const clearPendingFiles = useCallback(() => { - clearDirtyFiles(); - }, [clearDirtyFiles]); - - return { - pendingCount: dirtyCount, - isIndexing, - flushPendingFiles, - clearPendingFiles, - }; -} - -export default useFileWatchIndexing; diff --git a/src/hooks/workStation/indexing/useIncrementalIndexing.ts b/src/hooks/workStation/indexing/useIncrementalIndexing.ts deleted file mode 100644 index 0358e35e6c..0000000000 --- a/src/hooks/workStation/indexing/useIncrementalIndexing.ts +++ /dev/null @@ -1,293 +0,0 @@ -/** - * useIncrementalIndexing Hook - * - * Manages incremental re-indexing of files that have changed since last index. - * Listens for file change events and queues files for re-indexing with debouncing. - */ -import { useAtomValue, useSetAtom } from "jotai"; -import { useCallback, useEffect, useRef } from "react"; - -import { invalidateRepoCacheAtom } from "@src/store/workstation/codeEditor/search/cacheAtom"; -import { - type DirtyFile, - type IncrementalIndexResult, - MAX_BATCH_SIZE, - MIN_REINDEX_INTERVAL_MS, - REINDEX_DEBOUNCE_MS, - clearAllDirtyFilesAtom, - clearDirtyFilesAtom, - getDirtyFilesAtom, - isIncrementalIndexingAtom, - markFileDirtyAtom, - setIncrementalIndexingAtom, - updateFileTrackingAtom, -} from "@src/store/workstation/codeEditor/search/fileTrackingAtom"; - -// ============================================ -// Types -// ============================================ - -export interface UseIncrementalIndexingOptions { - /** Repository ID */ - repoId: string; - /** Repository path */ - repoPath: string; - /** Whether incremental indexing is enabled (default: true) */ - enabled?: boolean; - /** Custom debounce delay in ms (default: 2000) */ - debounceMs?: number; - /** Callback when indexing starts */ - onIndexStart?: () => void; - /** Callback when indexing completes */ - onIndexComplete?: (result: IncrementalIndexResult) => void; - /** Callback when indexing fails */ - onIndexError?: (error: Error) => void; -} - -export interface UseIncrementalIndexingReturn { - /** Mark a file as needing re-indexing */ - markDirty: ( - filePath: string, - changeType: "modify" | "create" | "delete" - ) => void; - /** Trigger immediate re-indexing of dirty files */ - flushDirtyFiles: () => Promise; - /** Get current dirty files */ - dirtyFiles: DirtyFile[]; - /** Number of dirty files */ - dirtyCount: number; - /** Whether incremental indexing is in progress */ - isIndexing: boolean; - /** Clear all dirty files without indexing */ - clearDirtyFiles: () => void; - /** Force full re-index (clears tracking; caller owns rebuild trigger) */ - forceFullReindex: () => void; -} - -// ============================================ -// Hook Implementation -// ============================================ - -export function useIncrementalIndexing( - options: UseIncrementalIndexingOptions -): UseIncrementalIndexingReturn { - const { - repoId, - repoPath, - enabled = true, - debounceMs = REINDEX_DEBOUNCE_MS, - onIndexStart, - onIndexComplete, - onIndexError, - } = options; - - // Atoms - const getDirtyFiles = useAtomValue(getDirtyFilesAtom); - const markFileDirty = useSetAtom(markFileDirtyAtom); - const clearDirtyFilesAction = useSetAtom(clearDirtyFilesAtom); - const clearAllDirtyFiles = useSetAtom(clearAllDirtyFilesAtom); - const updateFileTracking = useSetAtom(updateFileTrackingAtom); - const setIncrementalIndexing = useSetAtom(setIncrementalIndexingAtom); - const isIndexingMap = useAtomValue(isIncrementalIndexingAtom); - const invalidateRepoCache = useSetAtom(invalidateRepoCacheAtom); - - // Derived state - const dirtyFiles = getDirtyFiles(repoId); - const dirtyCount = dirtyFiles.length; - const isIndexing = isIndexingMap.get(repoId) || false; - - // Refs - const debounceTimerRef = useRef(null); - const lastIndexTimeRef = useRef(0); - const flushDirtyFilesInternalRef = useRef< - (() => Promise) | undefined - >(undefined); - - // Internal flush function (used by debounce timer) - const flushDirtyFilesInternal = useCallback(async () => { - if (!enabled || !repoId || isIndexing) return null; - - // Check minimum interval - const timeSinceLastIndex = Date.now() - lastIndexTimeRef.current; - if (timeSinceLastIndex < MIN_REINDEX_INTERVAL_MS) { - // Reschedule for later - const delay = MIN_REINDEX_INTERVAL_MS - timeSinceLastIndex; - debounceTimerRef.current = setTimeout(() => { - flushDirtyFilesInternalRef.current?.(); - }, delay); - return null; - } - - const currentDirtyFiles = getDirtyFiles(repoId); - if (currentDirtyFiles.length === 0) return null; - - // Batch files (limit size) - const filesToIndex = currentDirtyFiles.slice(0, MAX_BATCH_SIZE); - const modifyOrCreate = filesToIndex.filter( - (file) => file.changeType !== "delete" - ); - const deleted = filesToIndex.filter((file) => file.changeType === "delete"); - - setIncrementalIndexing({ repoId, isIndexing: true }); - onIndexStart?.(); - lastIndexTimeRef.current = Date.now(); - - const startTime = Date.now(); - - try { - const result = { - files_updated: modifyOrCreate.length, - files_failed: 0, - failed_paths: [] as string[], - }; - - const durationMs = Date.now() - startTime; - - // Update file tracking - const now = Date.now(); - updateFileTracking({ - repoId, - indexedFiles: modifyOrCreate - .filter((file) => !result.failed_paths.includes(file.path)) - .map((file) => ({ - path: file.path, - lastModified: now, - })), - deletedFiles: deleted.map((file) => file.path), - }); - - // Clear successfully indexed files from dirty list - const successfulPaths = filesToIndex - .map((file) => file.path) - .filter((path) => !result.failed_paths.includes(path)); - - clearDirtyFilesAction({ - repoId, - filePaths: successfulPaths, - }); - - // Invalidate search cache for this repo - invalidateRepoCache(repoPath); - - const indexResult: IncrementalIndexResult = { - filesUpdated: result.files_updated, - filesFailed: result.files_failed, - failedPaths: result.failed_paths, - durationMs, - }; - - onIndexComplete?.(indexResult); - return indexResult; - } catch (error) { - const err = error instanceof Error ? error : new Error(String(error)); - onIndexError?.(err); - return null; - } finally { - setIncrementalIndexing({ repoId, isIndexing: false }); - - // Check if there are more dirty files to process - const remainingDirty = getDirtyFiles(repoId); - if (remainingDirty.length > 0) { - // Schedule next batch - debounceTimerRef.current = setTimeout(() => { - flushDirtyFilesInternalRef.current?.(); - }, MIN_REINDEX_INTERVAL_MS); - } - } - }, [ - enabled, - repoId, - repoPath, - isIndexing, - getDirtyFiles, - setIncrementalIndexing, - updateFileTracking, - clearDirtyFilesAction, - invalidateRepoCache, - onIndexStart, - onIndexComplete, - onIndexError, - ]); - - // Keep ref updated with latest callback - flushDirtyFilesInternalRef.current = flushDirtyFilesInternal; - - // Mark a file as dirty - const markDirty = useCallback( - (filePath: string, changeType: "modify" | "create" | "delete") => { - if (!enabled || !repoId) return; - - markFileDirty({ - repoId, - filePath, - changeType, - }); - - // Schedule debounced re-index - if (debounceTimerRef.current) { - clearTimeout(debounceTimerRef.current); - } - - debounceTimerRef.current = setTimeout(() => { - flushDirtyFilesInternalRef.current?.(); - }, debounceMs); - }, - [enabled, repoId, markFileDirty, debounceMs] - ); - - // Public flush function - const flushDirtyFiles = useCallback(async () => { - // Cancel any pending debounce timer - if (debounceTimerRef.current) { - clearTimeout(debounceTimerRef.current); - debounceTimerRef.current = null; - } - return flushDirtyFilesInternal(); - }, [flushDirtyFilesInternal]); - - // Clear dirty files without indexing - const clearDirtyFiles = useCallback(() => { - if (debounceTimerRef.current) { - clearTimeout(debounceTimerRef.current); - debounceTimerRef.current = null; - } - clearAllDirtyFiles(repoId); - }, [repoId, clearAllDirtyFiles]); - - // Force full re-index - const forceFullReindex = useCallback(() => { - // Clear tracking to force full re-index next time - clearDirtyFiles(); - // The actual full re-index should be triggered by the caller. - }, [clearDirtyFiles]); - - // Cleanup on unmount - useEffect(() => { - return () => { - if (debounceTimerRef.current) { - clearTimeout(debounceTimerRef.current); - } - }; - }, []); - - // Reset when repo changes - useEffect(() => { - if (debounceTimerRef.current) { - clearTimeout(debounceTimerRef.current); - debounceTimerRef.current = null; - } - lastIndexTimeRef.current = 0; - }, [repoId]); - - return { - markDirty, - flushDirtyFiles, - dirtyFiles, - dirtyCount, - isIndexing, - clearDirtyFiles, - forceFullReindex, - }; -} - -export default useIncrementalIndexing; diff --git a/src/hooks/workStation/output/index.ts b/src/hooks/workStation/output/index.ts deleted file mode 100644 index 3945163b9a..0000000000 --- a/src/hooks/workStation/output/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { useOutputChannels } from "./useOutputChannels"; -export type { UseOutputChannelsReturn } from "./useOutputChannels"; - -export { useFileWatchOutputIntegration } from "./useFileWatchOutputIntegration"; -export { useTaskOutputIntegration } from "./useTaskOutputIntegration"; -export type { UseTaskOutputIntegrationReturn } from "./useTaskOutputIntegration"; diff --git a/src/hooks/workStation/panels/index.ts b/src/hooks/workStation/panels/index.ts deleted file mode 100644 index 0b6c8ce887..0000000000 --- a/src/hooks/workStation/panels/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { - useWorkStationPanels, - usePrimarySidebarState, - useBottomPanelState, -} from "./useWorkStationPanels"; -export type { UseWorkStationPanelsReturn } from "./useWorkStationPanels"; - -export { usePanelResize } from "./usePanelResize"; -export { useContextMenu } from "./useContextMenu"; diff --git a/src/hooks/workStation/panels/usePanelResize.ts b/src/hooks/workStation/panels/usePanelResize.ts deleted file mode 100644 index 95af6c7a36..0000000000 --- a/src/hooks/workStation/panels/usePanelResize.ts +++ /dev/null @@ -1,106 +0,0 @@ -/** - * usePanelResize Hook - * - * Reusable resize logic for panels (eliminates duplicate code) - */ -import { - type MouseEvent as ReactMouseEvent, - type RefObject, - useCallback, - useEffect, - useRef, - useState, -} from "react"; - -export interface UsePanelResizeOptions { - /** Minimum size (width or height) */ - minSize: number; - /** Maximum size (width or height) */ - maxSize: number; - /** Initial size */ - initialSize: number; - /** Resize direction */ - direction: "horizontal" | "vertical"; - /** Callback when size changes */ - onSizeChange: (size: number) => void; -} - -export interface UsePanelResizeReturn { - /** Current size */ - size: number; - /** Whether currently resizing */ - isResizing: boolean; - /** Mouse down handler for resize handle */ - handleMouseDown: (event: ReactMouseEvent) => void; - /** Ref for the panel element */ - panelRef: RefObject; -} - -export function usePanelResize({ - minSize, - maxSize, - initialSize, - direction, - onSizeChange, -}: UsePanelResizeOptions): UsePanelResizeReturn { - const [size, setSize] = useState(initialSize); - const [isResizing, setIsResizing] = useState(false); - const panelRef = useRef(null); - - // Cache container rect at drag-start so mousemove never touches parentElement. - const containerRectRef = useRef(null); - - const handleMouseDown = useCallback((event: ReactMouseEvent) => { - event.preventDefault(); - containerRectRef.current = - panelRef.current?.parentElement?.getBoundingClientRect() ?? null; - setIsResizing(true); - }, []); - - useEffect(() => { - const handleMouseMove = (event: globalThis.MouseEvent) => { - if (!isResizing) return; - - const containerRect = containerRectRef.current; - if (!containerRect) return; - - let newSize: number; - if (direction === "vertical") { - newSize = containerRect.bottom - event.clientY; - } else { - newSize = containerRect.right - event.clientX; - } - - const clampedSize = Math.min(maxSize, Math.max(minSize, newSize)); - setSize(clampedSize); - onSizeChange(clampedSize); - }; - - const handleMouseUp = () => { - setIsResizing(false); - containerRectRef.current = null; - }; - - if (isResizing) { - document.addEventListener("mousemove", handleMouseMove); - document.addEventListener("mouseup", handleMouseUp); - document.body.style.cursor = - direction === "vertical" ? "row-resize" : "col-resize"; - document.body.style.userSelect = "none"; - } - - return () => { - document.removeEventListener("mousemove", handleMouseMove); - document.removeEventListener("mouseup", handleMouseUp); - document.body.style.cursor = ""; - document.body.style.userSelect = ""; - }; - }, [isResizing, direction, minSize, maxSize, onSizeChange]); - - return { - size, - isResizing, - handleMouseDown, - panelRef, - }; -} diff --git a/src/hooks/workStation/search/__tests__/latestRequestGuard.test.ts b/src/hooks/workStation/search/__tests__/latestRequestGuard.test.ts deleted file mode 100644 index b54f65590e..0000000000 --- a/src/hooks/workStation/search/__tests__/latestRequestGuard.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { LatestRequestGuard } from "../latestRequestGuard"; - -describe("LatestRequestGuard", () => { - it("allows only the newest issued request to commit", () => { - const guard = new LatestRequestGuard(); - const first = guard.issue(); - const second = guard.issue(); - - expect(guard.isCurrent(first)).toBe(false); - expect(guard.isCurrent(second)).toBe(true); - }); - - it("invalidates an in-flight request when search is cleared", () => { - const guard = new LatestRequestGuard(); - const request = guard.issue(); - - guard.invalidate(); - - expect(guard.isCurrent(request)).toBe(false); - }); -}); diff --git a/src/hooks/workStation/search/index.ts b/src/hooks/workStation/search/index.ts deleted file mode 100644 index a6e370f9d2..0000000000 --- a/src/hooks/workStation/search/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { useCodeSearch } from "./useCodeSearch"; -export type { CodeSearchMode, CodeSearchResult } from "./useCodeSearch"; diff --git a/src/hooks/workStation/search/latestRequestGuard.ts b/src/hooks/workStation/search/latestRequestGuard.ts deleted file mode 100644 index 79bce1ab2a..0000000000 --- a/src/hooks/workStation/search/latestRequestGuard.ts +++ /dev/null @@ -1,16 +0,0 @@ -export class LatestRequestGuard { - private generation = 0; - - issue(): number { - this.generation += 1; - return this.generation; - } - - invalidate(): void { - this.generation += 1; - } - - isCurrent(generation: number): boolean { - return generation === this.generation; - } -} diff --git a/src/hooks/workStation/search/useCodeSearch.ts b/src/hooks/workStation/search/useCodeSearch.ts deleted file mode 100644 index 56edb415aa..0000000000 --- a/src/hooks/workStation/search/useCodeSearch.ts +++ /dev/null @@ -1,307 +0,0 @@ -/** - * useCodeSearch Hook - * - * Manages regex code search state with query debouncing, repository filtering, - * pagination, history, and result caching. - */ -import { useAtomValue, useSetAtom } from "jotai"; -import { useCallback, useEffect, useRef, useState } from "react"; - -import { type CodeSearchResult, searchCodeRegex } from "@src/api/tauri/search"; -import { useDebouncedCallback } from "@src/hooks/perf/useDebouncedCallback"; -import { - addToCacheAtom, - getCachedResultAtom, - recordCacheHitAtom, - recordCacheMissAtom, -} from "@src/store/workstation/codeEditor/search/cacheAtom"; - -import { LatestRequestGuard } from "./latestRequestGuard"; - -export type { CodeSearchResult } from "@src/api/tauri/search"; - -export type CodeSearchMode = "regex" | "semantic" | "hybrid"; - -export interface UseCodeSearchOptions { - /** Auto-execute search on query change */ - autoSearch?: boolean; - /** Debounce delay in ms */ - debounceMs?: number; - /** Maximum number of results */ - maxResults?: number; - /** Initial search mode */ - initialMode?: CodeSearchMode; -} - -export interface UseCodeSearchReturn { - query: string; - setQuery: (query: string) => void; - searchMode: CodeSearchMode; - toggleSearchMode: () => void; - setSearchMode: (mode: CodeSearchMode) => void; - results: CodeSearchResult[]; - loading: boolean; - error: string | null; - totalResults: number; - fromCache: boolean; - currentPage: number; - hasNextPage: boolean; - hasPrevPage: boolean; - goToNextPage: () => void; - goToPrevPage: () => void; - goToPage: (page: number) => void; - fileTypes: string[]; - setFileTypes: (types: string[]) => void; - repoFilter: string; - setRepoFilter: (repo: string) => void; - search: () => Promise; - clearResults: () => void; - clearError: () => void; - searchHistory: string[]; - clearHistory: () => void; -} - -const DEFAULT_OPTIONS: Required = { - autoSearch: false, - debounceMs: 300, - maxResults: 50, - initialMode: "regex", -}; - -export function useCodeSearch( - options: UseCodeSearchOptions = {} -): UseCodeSearchReturn { - const opts = { ...DEFAULT_OPTIONS, ...options }; - - const [query, setQuery] = useState(""); - const [searchMode, setSearchMode] = useState( - opts.initialMode - ); - const [results, setResults] = useState([]); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(null); - const [fileTypes, setFileTypes] = useState([]); - const [currentPage, setCurrentPage] = useState(1); - const [hasMore, setHasMore] = useState(false); - const [repoFilter, setRepoFilter] = useState(""); - const [searchHistory, setSearchHistory] = useState([]); - const [fromCache, setFromCache] = useState(false); - - const getCachedResult = useAtomValue(getCachedResultAtom); - const addToCache = useSetAtom(addToCacheAtom); - const recordCacheHit = useSetAtom(recordCacheHitAtom); - const recordCacheMiss = useSetAtom(recordCacheMissAtom); - const abortControllerRef = useRef(null); - // The Tauri search API does not currently accept an AbortSignal, so only the - // latest request generation is allowed to commit results or loading state. - const latestRequestGuardRef = useRef(null); - if (latestRequestGuardRef.current === null) { - latestRequestGuardRef.current = new LatestRequestGuard(); - } - - const toggleSearchMode = useCallback(() => { - setSearchMode((currentMode) => { - if (currentMode === "regex") return "semantic"; - if (currentMode === "semantic") return "hybrid"; - return "regex"; - }); - setResults([]); - }, []); - - const search = useCallback(async () => { - const latestRequestGuard = latestRequestGuardRef.current!; - const searchGeneration = latestRequestGuard.issue(); - const isLatestSearch = () => latestRequestGuard.isCurrent(searchGeneration); - const trimmedQuery = query.trim(); - - if (!trimmedQuery) { - setResults([]); - setFromCache(false); - return; - } - - if (currentPage === 1 && fileTypes.length === 0) { - const cached = getCachedResult(trimmedQuery, searchMode, repoFilter); - if (cached) { - setResults(cached.results); - setHasMore(cached.results.length >= opts.maxResults); - setFromCache(true); - recordCacheHit(); - - if (!searchHistory.includes(trimmedQuery)) { - setSearchHistory((prev) => [trimmedQuery, ...prev.slice(0, 9)]); - } - return; - } - } - - abortControllerRef.current?.abort(); - abortControllerRef.current = new AbortController(); - - setLoading(true); - setError(null); - setFromCache(false); - - try { - const regexResults = await searchCodeRegex( - trimmedQuery, - repoFilter ? [repoFilter] : [], - { max_results: opts.maxResults + 1 } - ); - if (!isLatestSearch()) return; - - const hasMoreResults = regexResults.length > opts.maxResults; - let searchResults = hasMoreResults - ? regexResults.slice(0, opts.maxResults) - : regexResults; - setHasMore(hasMoreResults); - - if (fileTypes.length > 0) { - searchResults = searchResults.filter((result) => { - const extension = - result.file_path.split(".").pop()?.toLowerCase() || ""; - return fileTypes.some((type) => type.split(",").includes(extension)); - }); - } - - setResults(searchResults); - - if (currentPage === 1 && fileTypes.length === 0) { - addToCache({ - query: trimmedQuery, - mode: searchMode, - repoFilter, - results: searchResults, - totalCount: searchResults.length, - }); - recordCacheMiss(); - } - - if (!searchHistory.includes(trimmedQuery)) { - setSearchHistory((prev) => [trimmedQuery, ...prev.slice(0, 9)]); - } - } catch (err: unknown) { - if (!isLatestSearch()) return; - if (err instanceof Error && err.name === "AbortError") return; - const errorMsg = - typeof err === "string" - ? err - : err instanceof Error - ? err.message - : "Failed to search code"; - setError(errorMsg); - setResults([]); - } finally { - if (isLatestSearch()) { - setLoading(false); - abortControllerRef.current = null; - } - } - }, [ - query, - searchMode, - repoFilter, - fileTypes, - opts.maxResults, - searchHistory, - currentPage, - getCachedResult, - addToCache, - recordCacheHit, - recordCacheMiss, - ]); - - const clearResults = useCallback(() => { - latestRequestGuardRef.current?.invalidate(); - abortControllerRef.current?.abort(); - abortControllerRef.current = null; - setResults([]); - setLoading(false); - setError(null); - setCurrentPage(1); - setHasMore(false); - setFromCache(false); - }, []); - - const clearError = useCallback(() => { - setError(null); - }, []); - - const clearHistory = useCallback(() => { - setSearchHistory([]); - }, []); - - const debouncedSearch = useDebouncedCallback(() => { - search(); - }, opts.debounceMs); - - useEffect(() => { - if (!opts.autoSearch) return; - - if (query.trim()) { - debouncedSearch(); - } else { - debouncedSearch.cancel(); - latestRequestGuardRef.current?.invalidate(); - abortControllerRef.current?.abort(); - abortControllerRef.current = null; - setResults([]); - setLoading(false); - } - }, [query, opts.autoSearch, debouncedSearch, search]); - - useEffect(() => { - return () => { - latestRequestGuardRef.current?.invalidate(); - abortControllerRef.current?.abort(); - }; - }, []); - - const goToNextPage = useCallback(() => { - if (hasMore) setCurrentPage((prev) => prev + 1); - }, [hasMore]); - - const goToPrevPage = useCallback(() => { - if (currentPage > 1) setCurrentPage((prev) => prev - 1); - }, [currentPage]); - - const goToPage = useCallback((page: number) => { - if (page >= 1) setCurrentPage(page); - }, []); - - useEffect(() => { - if (currentPage > 1 && query.trim()) { - search(); - } - }, [currentPage, query, search]); - - return { - query, - setQuery, - searchMode, - toggleSearchMode, - setSearchMode, - results, - loading, - error, - totalResults: results.length, - fromCache, - currentPage, - hasNextPage: hasMore, - hasPrevPage: currentPage > 1, - goToNextPage, - goToPrevPage, - goToPage, - fileTypes, - setFileTypes, - repoFilter, - setRepoFilter, - search, - clearResults, - clearError, - searchHistory, - clearHistory, - }; -} - -export default useCodeSearch; diff --git a/src/hooks/workStation/sessionCapture/index.ts b/src/hooks/workStation/sessionCapture/index.ts deleted file mode 100644 index 24a3a900cd..0000000000 --- a/src/hooks/workStation/sessionCapture/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export { useClaudeCodeOAuthCapture } from "./useClaudeCodeOAuthCapture"; -export { useCodexOAuthCapture } from "./useCodexOAuthCapture"; -export { useCursorSessionCapture } from "./useCursorSessionCapture"; -export { useEmbeddedWebview } from "./useEmbeddedWebview"; -export { useKiroSessionCapture } from "./useKiroSessionCapture"; -export type { - OAuthCaptureConfig, - UseOAuthCaptureOptions, - UseOAuthCaptureReturn, -} from "./useOAuthCapture"; -export { useOAuthCapture } from "./useOAuthCapture"; -export { useWebviewPositionSync } from "./useWebviewPositionSync"; diff --git a/src/hooks/workStation/tabs/index.ts b/src/hooks/workStation/tabs/index.ts deleted file mode 100644 index e1cd5b6c33..0000000000 --- a/src/hooks/workStation/tabs/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { useWorkStationTabs } from "./useWorkStationTabs"; -export { useCloseTabWithGuard } from "./useCloseTabWithGuard"; -export { useFocusTab } from "./useFocusTab"; -export { usePinnedTabs } from "./usePinnedTabs"; -export type { UseWorkStationTabsReturn } from "./useWorkStationTabs"; - -export { useSelectedFile } from "./useSelectedFile"; -export { useTabSwitchVerification } from "./useTabSwitchVerification"; -export { useUrlPreviewEvents } from "./useUrlPreviewEvents"; diff --git a/src/hooks/workStation/tabs/useTabSwitchVerification.ts b/src/hooks/workStation/tabs/useTabSwitchVerification.ts deleted file mode 100644 index f0adb76221..0000000000 --- a/src/hooks/workStation/tabs/useTabSwitchVerification.ts +++ /dev/null @@ -1,127 +0,0 @@ -/** - * useTabSwitchVerification Hook - * - * VSCode-style on-tab-switch verification using `git ls-files --stage`. - * Checks file staleness and git status when a tab becomes active. - * - * Benefits: - * - Lightweight: Only checks on tab switch, not continuous watching - * - Catches external changes: Git operations, other editors, build tools - * - No backend file watcher needed: Uses existing git infrastructure - * - VSCode-proven: Same approach used by VSCode - * - * Uses IDE Server HTTP endpoints on port 13847 (not Tauri invoke). - */ -import { useCallback, useEffect, useState } from "react"; - -import { createLogger } from "@src/hooks/logger"; - -import { FILE_API_BASE_URL } from "../fileContent/constants"; - -const log = createLogger("TabSwitchVerification"); - -// ============================================ -// Types -// ============================================ - -export interface GitFileStatus { - /** Whether the file is tracked in git */ - isTracked: boolean; - /** Whether the file is staged */ - isStaged: boolean; - /** Git blob hash (if tracked) */ - blobHash: string | null; - /** File modification time (milliseconds since UNIX epoch) */ - mtime: number; - /** Git conflict stage (0=normal, 1=base, 2=ours, 3=theirs) */ - conflictStage: number; -} - -export interface UseTabSwitchVerificationOptions { - /** File path to verify */ - filePath: string | null; - /** Repository path */ - repoPath: string; - /** Last known modification time */ - lastKnownMtime: number | null; - /** Callback when stale file is detected */ - onStaleDetected: () => void; - /** Callback when git status changes */ - onGitStatusChanged: (status: GitFileStatus) => void; -} - -export interface UseTabSwitchVerificationReturn { - /** Set whether this tab is active */ - setTabActive: (active: boolean) => void; - /** Manually trigger verification now */ - verifyNow: () => Promise; -} - -// ============================================ -// Main Hook -// ============================================ - -export function useTabSwitchVerification( - options: UseTabSwitchVerificationOptions -): UseTabSwitchVerificationReturn { - const { - filePath, - repoPath, - lastKnownMtime, - onStaleDetected, - onGitStatusChanged, - } = options; - - // Track if this tab is active - const [isActive, setIsActive] = useState(false); - - // Verify file status on tab activation - const verifyFile = useCallback(async () => { - if (!filePath || !repoPath) return; - - try { - // Call IDE Server HTTP endpoint - const params = new URLSearchParams({ - repo_path: repoPath, - file_path: filePath, - }); - - const response = await fetch( - `${FILE_API_BASE_URL}/git-status?${params.toString()}` - ); - - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - - const result = await response.json(); - const status: GitFileStatus = result.data; - - // Check staleness (file modified on disk since we loaded it) - if (lastKnownMtime && status.mtime > lastKnownMtime) { - onStaleDetected(); - } - - // Update git status (for decorations, merge conflict detection, etc.) - onGitStatusChanged(status); - } catch (error) { - throw new Error( - `[TabSwitchVerification] Failed to verify ${filePath}: ${error instanceof Error ? error.message : String(error)}` - ); - } - }, [filePath, repoPath, lastKnownMtime, onStaleDetected, onGitStatusChanged]); - - // Call verify when tab becomes active - useEffect(() => { - if (isActive && filePath) { - verifyFile().catch((error) => { - log.warn("[TabSwitchVerification]", error); - }); - } - }, [isActive, filePath, verifyFile]); - - return { - setTabActive: setIsActive, - verifyNow: verifyFile, - }; -} diff --git a/src/hooks/workStation/useGitOutputIntegration/index.ts b/src/hooks/workStation/useGitOutputIntegration/index.ts deleted file mode 100644 index c5c7d3cfd4..0000000000 --- a/src/hooks/workStation/useGitOutputIntegration/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Git Output Integration - * - * Re-exports for the git output integration hook. - */ - -// Main hook -export { useGitOutputIntegration } from "./useGitOutputIntegration"; - -// Types -export type { - GitOperationResult, - UseGitOutputIntegrationOptions, - UseGitOutputIntegrationReturn, -} from "./types"; - -// Sub-hooks (for advanced usage) -export { useGitOperations } from "./useGitOperations"; -export { useGitStagingOperations } from "./useGitStagingOperations"; -export { useFileWatchHeartbeat } from "./useFileWatchHeartbeat"; - -// Utilities (for testing/extension) -export { formatTimestamp, formatTimestampFromDate } from "./formatters"; diff --git a/src/modules/MainApp/Integrations/Databases/DbClientsPage/Table/DbClientsTable.tsx b/src/modules/MainApp/Integrations/Databases/DbClientsPage/Table/DbClientsTable.tsx index 65031d538f..426c292b05 100644 --- a/src/modules/MainApp/Integrations/Databases/DbClientsPage/Table/DbClientsTable.tsx +++ b/src/modules/MainApp/Integrations/Databases/DbClientsPage/Table/DbClientsTable.tsx @@ -13,7 +13,7 @@ import SettingsTable, { SETTINGS_TABLE_COL, type SettingsTableColumn, } from "@src/components/SettingsTable"; -import type { DependencyStatus } from "@src/hooks/dependencies"; +import type { DependencyStatus } from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { StatusDot, selectedRowClassName } from "../../../Tables/shared"; diff --git a/src/modules/MainApp/Integrations/Databases/DbClientsPage/index.tsx b/src/modules/MainApp/Integrations/Databases/DbClientsPage/index.tsx index 6ad78219d7..3717ab4255 100644 --- a/src/modules/MainApp/Integrations/Databases/DbClientsPage/index.tsx +++ b/src/modules/MainApp/Integrations/Databases/DbClientsPage/index.tsx @@ -10,11 +10,11 @@ import React from "react"; import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; +import { useRefreshSpin } from "@src/hooks/ui"; import { type DependencyStatus, useSystemDependencies, -} from "@src/hooks/dependencies"; -import { useRefreshSpin } from "@src/hooks/ui"; +} from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import { PANEL_HEADER_TOKENS, PanelHeader, diff --git a/src/modules/MainApp/Integrations/Databases/Table/DatabasesTable.tsx b/src/modules/MainApp/Integrations/Databases/Table/DatabasesTable.tsx index 683201c6ed..a3d77ece69 100644 --- a/src/modules/MainApp/Integrations/Databases/Table/DatabasesTable.tsx +++ b/src/modules/MainApp/Integrations/Databases/Table/DatabasesTable.tsx @@ -10,7 +10,7 @@ import SettingsTable, { type SettingsTableColumn, } from "@src/components/SettingsTable"; import TabPill from "@src/components/TabPill"; -import type { DependencyStatus } from "@src/hooks/dependencies"; +import type { DependencyStatus } from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import { DETAIL_PANEL_TOKENS, DetailPanelContainer, diff --git a/src/modules/MainApp/Integrations/DevTools/DependenciesPage/Table/DependenciesTable.tsx b/src/modules/MainApp/Integrations/DevTools/DependenciesPage/Table/DependenciesTable.tsx index 3e16d1a186..172a4251fc 100644 --- a/src/modules/MainApp/Integrations/DevTools/DependenciesPage/Table/DependenciesTable.tsx +++ b/src/modules/MainApp/Integrations/DevTools/DependenciesPage/Table/DependenciesTable.tsx @@ -14,7 +14,7 @@ import SettingsTable, { SETTINGS_TABLE_COL, type SettingsTableColumn, } from "@src/components/SettingsTable"; -import type { DependencyStatus } from "@src/hooks/dependencies"; +import type { DependencyStatus } from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { InfoRow } from "@src/modules/shared/layouts/blocks/InfoRow"; diff --git a/src/modules/MainApp/Integrations/DevTools/DependenciesPage/index.tsx b/src/modules/MainApp/Integrations/DevTools/DependenciesPage/index.tsx index 70bd521d3f..273fc5ad0f 100644 --- a/src/modules/MainApp/Integrations/DevTools/DependenciesPage/index.tsx +++ b/src/modules/MainApp/Integrations/DevTools/DependenciesPage/index.tsx @@ -8,11 +8,11 @@ */ import React, { useEffect } from "react"; -import type { DependencyStatus } from "@src/hooks/dependencies"; +import type { DependencyStatus } from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import { NON_DB_CATEGORIES, useSystemDependencies, -} from "@src/hooks/dependencies"; +} from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import DependenciesTable from "./Table/DependenciesTable"; diff --git a/src/modules/MainApp/Integrations/DevTools/LanguageServersPage/Table/LanguageServerInlineExpandedCard.tsx b/src/modules/MainApp/Integrations/DevTools/LanguageServersPage/Table/LanguageServerInlineExpandedCard.tsx index 0d98f14164..aa451e7f23 100644 --- a/src/modules/MainApp/Integrations/DevTools/LanguageServersPage/Table/LanguageServerInlineExpandedCard.tsx +++ b/src/modules/MainApp/Integrations/DevTools/LanguageServersPage/Table/LanguageServerInlineExpandedCard.tsx @@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import { requiredBinaryFromHint } from "@src/config/prerequisites"; -import { usePrerequisiteCheck } from "@src/hooks/dependencies/usePrerequisiteCheck"; +import { usePrerequisiteCheck } from "@src/modules/MainApp/Integrations/hooks/usePrerequisiteCheck"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { InfoRow } from "@src/modules/shared/layouts/blocks/InfoRow"; import { openExternalLink } from "@src/util/platform/ipcRenderer"; diff --git a/src/modules/MainApp/Integrations/DevTools/LintToolsPage/Table/LintToolInlineExpandedCard.tsx b/src/modules/MainApp/Integrations/DevTools/LintToolsPage/Table/LintToolInlineExpandedCard.tsx index 4d4d6cd078..57b0e08679 100644 --- a/src/modules/MainApp/Integrations/DevTools/LintToolsPage/Table/LintToolInlineExpandedCard.tsx +++ b/src/modules/MainApp/Integrations/DevTools/LintToolsPage/Table/LintToolInlineExpandedCard.tsx @@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import { requiredBinaryFromHint } from "@src/config/prerequisites"; -import { usePrerequisiteCheck } from "@src/hooks/dependencies/usePrerequisiteCheck"; +import { usePrerequisiteCheck } from "@src/modules/MainApp/Integrations/hooks/usePrerequisiteCheck"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { InfoRow } from "@src/modules/shared/layouts/blocks/InfoRow"; import { openExternalLink } from "@src/util/platform/ipcRenderer"; diff --git a/src/modules/MainApp/Integrations/KeyVault/CliClients/Preview/CliClientSection.tsx b/src/modules/MainApp/Integrations/KeyVault/CliClients/Preview/CliClientSection.tsx index 75f6119b81..c879a98b6d 100644 --- a/src/modules/MainApp/Integrations/KeyVault/CliClients/Preview/CliClientSection.tsx +++ b/src/modules/MainApp/Integrations/KeyVault/CliClients/Preview/CliClientSection.tsx @@ -11,7 +11,7 @@ import PrerequisiteAlert from "@src/components/PrerequisiteAlert"; import TabPill from "@src/components/TabPill"; import type { InstallMethod } from "@src/config/cliAgents"; import { INSTALL_METHOD_PREREQUISITES } from "@src/config/prerequisites"; -import { usePrerequisiteCheck } from "@src/hooks/dependencies/usePrerequisiteCheck"; +import { usePrerequisiteCheck } from "@src/modules/MainApp/Integrations/hooks/usePrerequisiteCheck"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { diff --git a/src/modules/MainApp/Integrations/Tables/CategoryTableContent.tsx b/src/modules/MainApp/Integrations/Tables/CategoryTableContent.tsx index cde0524493..f86a397bb0 100644 --- a/src/modules/MainApp/Integrations/Tables/CategoryTableContent.tsx +++ b/src/modules/MainApp/Integrations/Tables/CategoryTableContent.tsx @@ -4,7 +4,6 @@ import type { SyncConnection } from "@src/api/http/integrations"; import type { RoutineDefinition } from "@src/api/http/project"; import type { McpConfigScope } from "@src/api/tauri/rpc/schemas/mcp"; import type { AvailableAgent } from "@src/config/cliAgents"; -import type { DependencyStatus } from "@src/hooks/dependencies"; import type { KeyVaultAccount } from "@src/hooks/keyVault"; import type { CursorRepo, PolicyInfo } from "@src/hooks/policies"; import type { @@ -12,6 +11,7 @@ import type { McpServerStatus, McpToolDef, } from "@src/modules/MainApp/AgentOrgs/config/mcp/useMcpServers"; +import type { DependencyStatus } from "@src/modules/MainApp/Integrations/hooks/useSystemDependencies"; import type { HubSkillDetail, InstalledSkill } from "@src/types/extensions"; import type { ChannelInstance } from "../Connections/Channels"; diff --git a/src/hooks/dependencies/usePrerequisiteCheck.ts b/src/modules/MainApp/Integrations/hooks/usePrerequisiteCheck.ts similarity index 100% rename from src/hooks/dependencies/usePrerequisiteCheck.ts rename to src/modules/MainApp/Integrations/hooks/usePrerequisiteCheck.ts diff --git a/src/hooks/dependencies/useSystemDependencies.ts b/src/modules/MainApp/Integrations/hooks/useSystemDependencies.ts similarity index 100% rename from src/hooks/dependencies/useSystemDependencies.ts rename to src/modules/MainApp/Integrations/hooks/useSystemDependencies.ts diff --git a/src/modules/MainApp/Integrations/useIntegrationsCategoryTableProps.tsx b/src/modules/MainApp/Integrations/useIntegrationsCategoryTableProps.tsx index cce8845f29..ef531e15a2 100644 --- a/src/modules/MainApp/Integrations/useIntegrationsCategoryTableProps.tsx +++ b/src/modules/MainApp/Integrations/useIntegrationsCategoryTableProps.tsx @@ -1,7 +1,5 @@ import { type Dispatch, type SetStateAction, useMemo } from "react"; -import type { DependencyStatus } from "@src/hooks/dependencies"; - import type { useCliAgents } from "./KeyVault/CliClients/hooks/useCliAgents"; import type { useKeyVaultPage } from "./KeyVault/hooks/useKeyVaultPage"; import type { CategoryTableContentProps } from "./Tables"; @@ -11,6 +9,7 @@ import type { useDatabasesState } from "./hooks/useDatabasesState"; import type { useExtensionsState } from "./hooks/useExtensionsState"; import type { useRoutinesState } from "./hooks/useRoutinesState"; import type { useRulesMemoryEvolutionState } from "./hooks/useRulesMemoryEvolutionState"; +import type { DependencyStatus } from "./hooks/useSystemDependencies"; import type { AddAction, DetailMode, IntegrationCategory } from "./types"; export interface UseIntegrationsCategoryTablePropsParams { diff --git a/src/modules/MainApp/Integrations/useIntegrationsPage.tsx b/src/modules/MainApp/Integrations/useIntegrationsPage.tsx index 24cfa0b26e..07ba6b4246 100644 --- a/src/modules/MainApp/Integrations/useIntegrationsPage.tsx +++ b/src/modules/MainApp/Integrations/useIntegrationsPage.tsx @@ -12,7 +12,6 @@ import { parseExternalSkillsetsTab, parseIntegrationsPath, } from "@src/config/mainAppPaths"; -import type { DependencyStatus } from "@src/hooks/dependencies"; import { integrationsAddSignalAtom, integrationsToolbarAtom, @@ -28,6 +27,7 @@ import { useDatabasesState } from "./hooks/useDatabasesState"; import { useExtensionsState } from "./hooks/useExtensionsState"; import { useRoutinesState } from "./hooks/useRoutinesState"; import { useRulesMemoryEvolutionState } from "./hooks/useRulesMemoryEvolutionState"; +import type { DependencyStatus } from "./hooks/useSystemDependencies"; import { getHasIntegrationsFullPageDetail } from "./integrationsFullPageDetail"; import { VALID_MODELS_TABS } from "./integrationsPageConstants"; import type { AddAction, DetailMode, IntegrationCategory } from "./types"; diff --git a/src/modules/MainApp/WorkManagement/WorkManagementProjectsSurface.tsx b/src/modules/MainApp/WorkManagement/WorkManagementProjectsSurface.tsx index 0b0172e48a..6f35475ec1 100644 --- a/src/modules/MainApp/WorkManagement/WorkManagementProjectsSurface.tsx +++ b/src/modules/MainApp/WorkManagement/WorkManagementProjectsSurface.tsx @@ -9,7 +9,7 @@ import React, { } from "react"; import { useTranslation } from "react-i18next"; -import { useWorkStationTabs } from "@src/hooks/workStation/tabs"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import type { LinearProjectSelection } from "@src/modules/ProjectManager/Panels/ProjectManagerSidebar/content/WorkspaceTreeContent"; import type { ProjectWorkItemSelection } from "@src/modules/ProjectManager/ProjectManagerLayout/components/ProjectWorkItemsTabContent"; import type { ActiveRepoView } from "@src/modules/ProjectManager/ProjectManagerLayout/types"; diff --git a/src/modules/MainApp/WorkManagement/index.tsx b/src/modules/MainApp/WorkManagement/index.tsx index ff74ffeca2..d72adbf32e 100644 --- a/src/modules/MainApp/WorkManagement/index.tsx +++ b/src/modules/MainApp/WorkManagement/index.tsx @@ -18,7 +18,7 @@ import React from "react"; import { usePublishChatPanelHeader } from "@src/engines/ChatPanel/header"; import FactoryViewPill from "@src/features/TaskKanban/components/FactoryViewPill"; import KanbanOrgScopeSelect from "@src/features/TaskKanban/components/KanbanOrgScopeSelect"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { WorkstationHeaderSectionSeparator } from "@src/modules/WorkStation/shared"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { diff --git a/src/modules/MainApp/WorkManagement/useGitHubWorkItemActions.ts b/src/modules/MainApp/WorkManagement/useGitHubWorkItemActions.ts index d8ea778083..a1fb23d5ad 100644 --- a/src/modules/MainApp/WorkManagement/useGitHubWorkItemActions.ts +++ b/src/modules/MainApp/WorkManagement/useGitHubWorkItemActions.ts @@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"; import type { GitHubIssue } from "@src/api/tauri/github"; import Message from "@src/components/Message"; -import { useWorkStationTabs } from "@src/hooks/workStation/tabs"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { githubIssueResourceKey, loadGitHubIssueTimeline, diff --git a/src/modules/ProjectManager/LinearProjects/LinearProjectsPageSections.tsx b/src/modules/ProjectManager/LinearProjects/LinearProjectsPageSections.tsx index 2a0d420132..59fc104ccd 100644 --- a/src/modules/ProjectManager/LinearProjects/LinearProjectsPageSections.tsx +++ b/src/modules/ProjectManager/LinearProjects/LinearProjectsPageSections.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useTranslation } from "react-i18next"; import type { LinearProjectSummary } from "@src/api/http/integrations"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { ProjectRow, ProjectsPageHeader, diff --git a/src/modules/ProjectManager/LinearProjects/index.tsx b/src/modules/ProjectManager/LinearProjects/index.tsx index d8a678d059..75a666befe 100644 --- a/src/modules/ProjectManager/LinearProjects/index.tsx +++ b/src/modules/ProjectManager/LinearProjects/index.tsx @@ -8,7 +8,7 @@ import React, { import { useTranslation } from "react-i18next"; import Select from "@src/components/Select"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import WorkItemDetail, { WORK_ITEM_DETAIL_SURFACE, } from "@src/modules/ProjectManager/WorkItems/components/WorkItemDetail"; diff --git a/src/modules/ProjectManager/ProjectManagerLayout/components/ProjectWorkItemsTabContentTypes.ts b/src/modules/ProjectManager/ProjectManagerLayout/components/ProjectWorkItemsTabContentTypes.ts index 16dcf85431..21c5b6d31d 100644 --- a/src/modules/ProjectManager/ProjectManagerLayout/components/ProjectWorkItemsTabContentTypes.ts +++ b/src/modules/ProjectManager/ProjectManagerLayout/components/ProjectWorkItemsTabContentTypes.ts @@ -9,7 +9,7 @@ import type { WorkItemReadBucket, WorkspaceWorkItemsData, } from "@src/api/http/project"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import type { LinearProjectSelection } from "@src/modules/ProjectManager/Panels/ProjectManagerSidebar/content/WorkspaceTreeContent"; import type { ProjectManagerBreadcrumbSegment } from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import type { WorkspaceWorkItem } from "@src/modules/ProjectManager/workspaceAggregate"; diff --git a/src/modules/ProjectManager/ProjectManagerLayout/index.tsx b/src/modules/ProjectManager/ProjectManagerLayout/index.tsx index f3bb8849c1..c0309e9be3 100644 --- a/src/modules/ProjectManager/ProjectManagerLayout/index.tsx +++ b/src/modules/ProjectManager/ProjectManagerLayout/index.tsx @@ -9,11 +9,9 @@ import { buildIntegrationsPath, buildWizardPath, } from "@src/config/mainAppPaths"; -import { - usePrimarySidebarState, - useWorkStationTabShortcutBridge, - useWorkStationTabs, -} from "@src/hooks/workStation"; +import { usePrimarySidebarState } from "@src/hooks/tabHost/useWorkStationPanels"; +import { useWorkStationTabShortcutBridge } from "@src/hooks/tabHost/useWorkStationTabShortcutBridge"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { WorkStationShell } from "@src/modules/WorkStation/shared"; import { openCreateTargetInChatPanelStartPageAtom } from "@src/store/chatPanel/chatPanelTabsAtom"; import { projectListRefreshAtom } from "@src/store/project/projectAtom"; diff --git a/src/modules/ProjectManager/ProjectManagerShell.tsx b/src/modules/ProjectManager/ProjectManagerShell.tsx index 8668155865..38c0c44204 100644 --- a/src/modules/ProjectManager/ProjectManagerShell.tsx +++ b/src/modules/ProjectManager/ProjectManagerShell.tsx @@ -8,7 +8,7 @@ import { useAtomValue, useSetAtom } from "jotai"; import React, { memo, useCallback, useEffect, useMemo } from "react"; import SimulatorFrame from "@src/engines/Simulator/components/SimulatorFrame"; -import { useWorkStationTabs } from "@src/hooks/workStation"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { perAppStatusBarCallbacksAtom, workStationTitleBarHiddenAtom, diff --git a/src/modules/ProjectManager/Projects/components/ProjectsPageHeader/index.tsx b/src/modules/ProjectManager/Projects/components/ProjectsPageHeader/index.tsx index cc4f6a1f13..5fe7a34a93 100644 --- a/src/modules/ProjectManager/Projects/components/ProjectsPageHeader/index.tsx +++ b/src/modules/ProjectManager/Projects/components/ProjectsPageHeader/index.tsx @@ -19,11 +19,11 @@ import { HEADER_CLASSES, HEADER_ICON_SIZE, } from "@src/config/workstation/tokens"; -import { useRefreshSpin } from "@src/hooks/ui"; import { type WorkstationTabHeaderHost, usePublishWorkstationTabHeader, -} from "@src/hooks/workStation"; +} from "@src/hooks/tabHost/useWorkstationTabHeader"; +import { useRefreshSpin } from "@src/hooks/ui"; import ProjectManagerBreadcrumb from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import type { ProjectManagerBreadcrumbSegment } from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import { WorkstationHeaderSectionSeparator } from "@src/modules/WorkStation/shared"; diff --git a/src/modules/ProjectManager/WorkItems/components/EmbeddedWorkItemDetail/index.tsx b/src/modules/ProjectManager/WorkItems/components/EmbeddedWorkItemDetail/index.tsx index 28bd58320a..b30ce54fd5 100644 --- a/src/modules/ProjectManager/WorkItems/components/EmbeddedWorkItemDetail/index.tsx +++ b/src/modules/ProjectManager/WorkItems/components/EmbeddedWorkItemDetail/index.tsx @@ -1,6 +1,6 @@ import React, { Suspense, useCallback } from "react"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import type { ProjectManagerBreadcrumbSegment } from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import type { Person } from "@src/types/core/shared"; diff --git a/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/index.tsx b/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/index.tsx index d056eb9f27..2ebe41af4f 100644 --- a/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/index.tsx +++ b/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/index.tsx @@ -9,10 +9,8 @@ import { useTranslation } from "react-i18next"; import type { WorkItemData as WorkItemDataPayload } from "@src/api/http/project"; import { HEADER_CLASSES } from "@src/config/workstation/tokens"; -import { - usePublishWorkstationTabHeader, - useWorkStationTabs, -} from "@src/hooks/workStation"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { useAgentDefinitions } from "@src/modules/MainApp/AgentOrgs/hooks/useAgentDefinitions"; import { useAgentOrgs } from "@src/modules/MainApp/AgentOrgs/hooks/useAgentOrgs"; import { createWorkItemDetailTab } from "@src/store/workstation/tabs"; diff --git a/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/types.ts b/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/types.ts index 6688b7102c..d39a143b83 100644 --- a/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/types.ts +++ b/src/modules/ProjectManager/WorkItems/components/WorkItemDetail/types.ts @@ -1,6 +1,6 @@ import type { ReactNode } from "react"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import type { ProjectManagerBreadcrumbSegment } from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import type { Person } from "@src/types/core/shared"; import type { diff --git a/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/index.tsx b/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/index.tsx index d2e8b784e1..453cf63cb0 100644 --- a/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/index.tsx +++ b/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/index.tsx @@ -6,8 +6,8 @@ import { HEADER_CLASSES, HEADER_ICON_SIZE, } from "@src/config/workstation/tokens"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { useRefreshSpin } from "@src/hooks/ui"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; import { WorkItemsHeaderContent } from "./WorkItemsHeaderContent"; import type { WorkItemsPageHeaderProps } from "./types"; diff --git a/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/types.ts b/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/types.ts index e5502bba33..7686ffa72d 100644 --- a/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/types.ts +++ b/src/modules/ProjectManager/WorkItems/components/WorkItemsPageHeader/types.ts @@ -1,6 +1,6 @@ import type React from "react"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import type { ProjectManagerBreadcrumbSegment } from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import type { diff --git a/src/modules/ProjectManager/WorkItems/index.tsx b/src/modules/ProjectManager/WorkItems/index.tsx index d4a6be7b85..c632af3923 100644 --- a/src/modules/ProjectManager/WorkItems/index.tsx +++ b/src/modules/ProjectManager/WorkItems/index.tsx @@ -17,7 +17,7 @@ import type { TabPillItem } from "@src/components/TabPill"; import { HEADER_ICON_SIZE } from "@src/config/workstation/tokens"; import { useProjectOrgCloudPermissions } from "@src/features/Org2Cloud/useProjectOrgCloudPermissions"; import { useCurrentUserMemberIds } from "@src/hooks/project/useCurrentUserMemberId"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import type { LinkedRepoOption } from "@src/modules/ProjectManager/shared"; import type { ProjectManagerBreadcrumbSegment } from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; diff --git a/src/modules/ProjectManager/shared/components/DetailSplitLayout/index.tsx b/src/modules/ProjectManager/shared/components/DetailSplitLayout/index.tsx index ad6c4740a4..eb78573631 100644 --- a/src/modules/ProjectManager/shared/components/DetailSplitLayout/index.tsx +++ b/src/modules/ProjectManager/shared/components/DetailSplitLayout/index.tsx @@ -21,8 +21,8 @@ import { HEADER_CLASSES, HEADER_ICON_SIZE, } from "@src/config/workstation/tokens"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { useResizeHandle } from "@src/hooks/ui/useResizeHandle"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; import ProjectManagerBreadcrumb from "@src/modules/ProjectManager/shared/components/ProjectManagerBreadcrumb"; import { PANEL_FOOTER_TOKENS } from "@src/modules/shared/layouts/blocks"; import { VerticalResizeHandle } from "@src/scaffold/Resize"; diff --git a/src/modules/WorkStation/AppShell/hooks/useAppShellSimulatorPanelSync.ts b/src/modules/WorkStation/AppShell/hooks/useAppShellSimulatorPanelSync.ts index 7814928b0f..a82dda7adb 100644 --- a/src/modules/WorkStation/AppShell/hooks/useAppShellSimulatorPanelSync.ts +++ b/src/modules/WorkStation/AppShell/hooks/useAppShellSimulatorPanelSync.ts @@ -1,7 +1,7 @@ import { useSetAtom } from "jotai"; import { useEffect } from "react"; -import { useWorkStationPanels } from "@src/hooks/workStation"; +import { useWorkStationPanels } from "@src/hooks/tabHost/useWorkStationPanels"; import { simulatorPrimarySidebarPositionAtom } from "@src/store/ui/simulatorAtom"; export function useAppShellSimulatorPanelSync({ diff --git a/src/modules/WorkStation/AppShell/hooks/useAppShellStatusBar.ts b/src/modules/WorkStation/AppShell/hooks/useAppShellStatusBar.ts index eb99385288..50ba8080b7 100644 --- a/src/modules/WorkStation/AppShell/hooks/useAppShellStatusBar.ts +++ b/src/modules/WorkStation/AppShell/hooks/useAppShellStatusBar.ts @@ -1,7 +1,7 @@ import { useSetAtom } from "jotai"; import { useEffect } from "react"; -import { useWorkStationPanels } from "@src/hooks/workStation"; +import { useWorkStationPanels } from "@src/hooks/tabHost/useWorkStationPanels"; import { perAppStatusBarCallbacksAtom } from "@src/store/ui/workStationAtom"; interface UseAppShellStatusBarOptions { diff --git a/src/modules/WorkStation/AppShell/index.tsx b/src/modules/WorkStation/AppShell/index.tsx index f04a6cf91c..90d83891e7 100644 --- a/src/modules/WorkStation/AppShell/index.tsx +++ b/src/modules/WorkStation/AppShell/index.tsx @@ -2,7 +2,7 @@ import { useAtomValue } from "jotai"; import React from "react"; import { useCurrentTurnLastAgentMessage } from "@src/engines/Simulator/hooks/useCurrentTurnLastAgentMessage"; -import { useWorkStationPanels } from "@src/hooks/workStation"; +import { useWorkStationPanels } from "@src/hooks/tabHost/useWorkStationPanels"; import { GUIDE_TARGETS } from "@src/scaffold/Tutorials/guideTargets"; import { workstationActiveSessionIdAtom } from "@src/store/session"; import { simulatorCaptionBarEnabledAtom } from "@src/store/ui/simulatorAtom"; diff --git a/src/modules/WorkStation/AppShell/useWorkstationTabList.ts b/src/modules/WorkStation/AppShell/useWorkstationTabList.ts index 543d7df7d4..7e6ddb800d 100644 --- a/src/modules/WorkStation/AppShell/useWorkstationTabList.ts +++ b/src/modules/WorkStation/AppShell/useWorkstationTabList.ts @@ -14,8 +14,8 @@ import { useAtomValue, useSetAtom } from "jotai"; import { useCallback, useMemo } from "react"; -import { useCloseTabWithGuard } from "@src/hooks/workStation/tabs/useCloseTabWithGuard"; -import { useFocusTab } from "@src/hooks/workStation/tabs/useFocusTab"; +import { useCloseTabWithGuard } from "@src/hooks/tabHost/useCloseTabWithGuard"; +import { useFocusTab } from "@src/hooks/tabHost/useFocusTab"; import { closeOtherTabsAtom, closeSavedTabsAtom, diff --git a/src/modules/WorkStation/Browser/BrowserLayout/useBrowserLayoutState.ts b/src/modules/WorkStation/Browser/BrowserLayout/useBrowserLayoutState.ts index e46f4dc768..2bd6ba8f2c 100644 --- a/src/modules/WorkStation/Browser/BrowserLayout/useBrowserLayoutState.ts +++ b/src/modules/WorkStation/Browser/BrowserLayout/useBrowserLayoutState.ts @@ -16,9 +16,9 @@ import { useLocation, useNavigate } from "react-router-dom"; import Message from "@src/components/Message"; import { ROUTES } from "@src/config/routes"; import { useBrowserAutomation } from "@src/engines/BrowserCore/hooks/useBrowserAutomation"; -import { useWorkStationTabShortcutBridge } from "@src/hooks/workStation"; -import { useBrowserPaneState } from "@src/hooks/workStation/browser/useBrowserPaneState"; -import { useBrowserSessions } from "@src/hooks/workStation/browser/useBrowserSessions"; +import { useWorkStationTabShortcutBridge } from "@src/hooks/tabHost/useWorkStationTabShortcutBridge"; +import { useBrowserPaneState } from "@src/modules/WorkStation/Browser/hooks/useBrowserPaneState"; +import { useBrowserSessions } from "@src/modules/WorkStation/Browser/hooks/useBrowserSessions"; import { addToAgentAtom } from "@src/store/ui/addToAgentAtom"; import { workStationDevToolsCollapsedPersistAtom } from "@src/store/ui/workStationAtom"; import { diff --git a/src/modules/WorkStation/Browser/Panels/BrowserMainPane/components/WebUrlBar/index.tsx b/src/modules/WorkStation/Browser/Panels/BrowserMainPane/components/WebUrlBar/index.tsx index 96e04f76d1..e8ac371be1 100644 --- a/src/modules/WorkStation/Browser/Panels/BrowserMainPane/components/WebUrlBar/index.tsx +++ b/src/modules/WorkStation/Browser/Panels/BrowserMainPane/components/WebUrlBar/index.tsx @@ -29,7 +29,7 @@ import { useTauriSelectAllShortcut } from "@src/hooks/keyboard"; import { type WorkstationTabHeaderHost, usePublishWorkstationTabHeader, -} from "@src/hooks/workStation"; +} from "@src/hooks/tabHost/useWorkstationTabHeader"; import { WorkstationToolbarTooltip } from "@src/modules/WorkStation/shared"; import { FILE_BAR_ROW_CLASSES, diff --git a/src/modules/WorkStation/Browser/Panels/BrowserMainPane/content/WebViewportContent/index.tsx b/src/modules/WorkStation/Browser/Panels/BrowserMainPane/content/WebViewportContent/index.tsx index 15dca8fef7..664e4948c1 100644 --- a/src/modules/WorkStation/Browser/Panels/BrowserMainPane/content/WebViewportContent/index.tsx +++ b/src/modules/WorkStation/Browser/Panels/BrowserMainPane/content/WebViewportContent/index.tsx @@ -13,7 +13,7 @@ import React, { memo, useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { EDITOR_TAB_CANVAS_BG_CLASS } from "@src/config/workstation/tokens"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { getSiteNameFromUrl } from "@src/store/ui/navigationSidebarTabsAtom"; import { closeBrowserTabAtom, diff --git a/src/modules/WorkStation/Browser/SessionReplay/index.tsx b/src/modules/WorkStation/Browser/SessionReplay/index.tsx index 4714d241c6..ac4b086f5a 100644 --- a/src/modules/WorkStation/Browser/SessionReplay/index.tsx +++ b/src/modules/WorkStation/Browser/SessionReplay/index.tsx @@ -8,10 +8,10 @@ import { SIMULATOR_PRIMARY_SIDEBAR } from "@src/config/simulatorPrimarySidebar"; import { useBrowserAutomation } from "@src/engines/BrowserCore/hooks/useBrowserAutomation"; import EventWrapper from "@src/engines/ChatPanel/adapters/EventWrapper"; import { AppType } from "@src/engines/Simulator/types/appTypes"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; -import { useBrowserSessions } from "@src/hooks/workStation/browser/useBrowserSessions"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { buildSelectedElementLabel } from "@src/modules/WorkStation/Browser/BrowserLayout/browserLayoutUtils"; import { buildDomComponentJsonFromElementInfo } from "@src/modules/WorkStation/Browser/BrowserLayout/buildDomComponentJson"; +import { useBrowserSessions } from "@src/modules/WorkStation/Browser/hooks/useBrowserSessions"; import { NoTabsPlaceholder, SimulatorReplayChrome, diff --git a/src/modules/WorkStation/Browser/context/browserHostContext.tsx b/src/modules/WorkStation/Browser/context/browserHostContext.tsx index 2905962eca..5d1e3fcad2 100644 --- a/src/modules/WorkStation/Browser/context/browserHostContext.tsx +++ b/src/modules/WorkStation/Browser/context/browserHostContext.tsx @@ -27,7 +27,7 @@ import { type ReactNode, createContext, useContext } from "react"; import type { UseBrowserStateReturn } from "@src/engines/BrowserCore/hooks/useBrowserState"; -import type { UseBrowserSessionsReturn } from "@src/hooks/workStation/browser/useBrowserSessions"; +import type { UseBrowserSessionsReturn } from "@src/modules/WorkStation/Browser/hooks/useBrowserSessions"; import type { SecondaryPanelPosition } from "@src/store/ui/workStationAtom"; export interface BrowserHostContextValue { diff --git a/src/hooks/workStation/browser/browserDiagnosticsPolicy.test.ts b/src/modules/WorkStation/Browser/hooks/browserDiagnosticsPolicy.test.ts similarity index 100% rename from src/hooks/workStation/browser/browserDiagnosticsPolicy.test.ts rename to src/modules/WorkStation/Browser/hooks/browserDiagnosticsPolicy.test.ts diff --git a/src/hooks/workStation/browser/browserDiagnosticsPolicy.ts b/src/modules/WorkStation/Browser/hooks/browserDiagnosticsPolicy.ts similarity index 100% rename from src/hooks/workStation/browser/browserDiagnosticsPolicy.ts rename to src/modules/WorkStation/Browser/hooks/browserDiagnosticsPolicy.ts diff --git a/src/hooks/workStation/browser/useBrowserPaneState.ts b/src/modules/WorkStation/Browser/hooks/useBrowserPaneState.ts similarity index 100% rename from src/hooks/workStation/browser/useBrowserPaneState.ts rename to src/modules/WorkStation/Browser/hooks/useBrowserPaneState.ts diff --git a/src/hooks/workStation/browser/useBrowserSessions.ts b/src/modules/WorkStation/Browser/hooks/useBrowserSessions.ts similarity index 95% rename from src/hooks/workStation/browser/useBrowserSessions.ts rename to src/modules/WorkStation/Browser/hooks/useBrowserSessions.ts index 86b7bdfde8..9f31ec5168 100644 --- a/src/hooks/workStation/browser/useBrowserSessions.ts +++ b/src/modules/WorkStation/Browser/hooks/useBrowserSessions.ts @@ -13,11 +13,7 @@ import { useAtomValue, useSetAtom } from "jotai"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { createLogger } from "@src/hooks/logger"; -import { shouldEnableBrowserLogPolling } from "@src/hooks/workStation/browser/browserDiagnosticsPolicy"; -import { useWorkStationPanels } from "@src/hooks/workStation/panels/useWorkStationPanels"; -import { useBrowserConsole } from "@src/modules/WorkStation/Browser/hooks/useBrowserConsole"; -import { useBrowserNetworkLogs } from "@src/modules/WorkStation/Browser/hooks/useBrowserNetworkLogs"; -import { useWebviewInspector } from "@src/modules/WorkStation/Browser/hooks/useWebviewInspector"; +import { useWorkStationPanels } from "@src/hooks/tabHost/useWorkStationPanels"; import { browserDevToolsPositionAtom, browserDevToolsPositionPersistAtom, @@ -30,6 +26,11 @@ import { } from "@src/store/ui/workStationAtom"; import type { SecondaryPanelPosition } from "@src/store/ui/workStationAtom"; +import { shouldEnableBrowserLogPolling } from "./browserDiagnosticsPolicy"; +import { useBrowserConsole } from "./useBrowserConsole"; +import { useBrowserNetworkLogs } from "./useBrowserNetworkLogs"; +import { useWebviewInspector } from "./useWebviewInspector"; + const log = createLogger("Browser"); // Delay before starting polling hooks to avoid IPC pressure during app switching diff --git a/src/modules/WorkStation/Browser/shared/SharedBrowserWorkspace.tsx b/src/modules/WorkStation/Browser/shared/SharedBrowserWorkspace.tsx index 482bb40fa0..210fd7c9ed 100644 --- a/src/modules/WorkStation/Browser/shared/SharedBrowserWorkspace.tsx +++ b/src/modules/WorkStation/Browser/shared/SharedBrowserWorkspace.tsx @@ -2,7 +2,7 @@ import type { FC } from "react"; import type { UseBrowserStateReturn } from "@src/engines/BrowserCore/hooks/useBrowserState"; import { BROWSER_WEBVIEW_FRAME_ANCHOR_SELECTOR } from "@src/engines/BrowserCore/nativeFrameAnchor"; -import type { WorkstationTabHeaderHost } from "@src/hooks/workStation"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { NoTabsPlaceholder, type QuickAction, diff --git a/src/modules/WorkStation/CodeEditor/EditorLayout/components/EditorIntegrations/index.tsx b/src/modules/WorkStation/CodeEditor/EditorLayout/components/EditorIntegrations/index.tsx index 9326f8ff02..c2d7281398 100644 --- a/src/modules/WorkStation/CodeEditor/EditorLayout/components/EditorIntegrations/index.tsx +++ b/src/modules/WorkStation/CodeEditor/EditorLayout/components/EditorIntegrations/index.tsx @@ -13,16 +13,15 @@ * By isolating these in a separate component, we prevent unnecessary re-renders * of the main editor when integration state changes. */ -import { useLspDiagnostics } from "@/src/hooks/workStation/diagnostics/useLspDiagnostics"; import { useSetAtom } from "jotai"; import { type FC, memo, useCallback, useEffect } from "react"; import { ACTION_ID, useActionSystem } from "@src/ActionSystem"; -import { useTestRunner } from "@src/hooks/testRunner"; -import { useFileWatchOutputIntegration } from "@src/hooks/workStation/output/useFileWatchOutputIntegration"; -import type { UseOutputChannelsReturn } from "@src/hooks/workStation/output/useOutputChannels"; -import { useTaskOutputIntegration } from "@src/hooks/workStation/output/useTaskOutputIntegration"; -import { useGitOutputIntegration } from "@src/hooks/workStation/useGitOutputIntegration"; +import { useLspDiagnostics } from "@src/modules/WorkStation/CodeEditor/hooks/diagnostics/useLspDiagnostics"; +import { useGitOutputIntegration } from "@src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOutputIntegration"; +import { useFileWatchOutputIntegration } from "@src/modules/WorkStation/CodeEditor/hooks/output/useFileWatchOutputIntegration"; +import { useTaskOutputIntegration } from "@src/modules/WorkStation/CodeEditor/hooks/output/useTaskOutputIntegration"; +import { useTestRunner } from "@src/modules/WorkStation/CodeEditor/hooks/useTestRunner"; import { GUIAgentService } from "@src/services"; import type { BottomPanelTab, @@ -32,6 +31,7 @@ import { gitOutputIntegrationAtom, taskOutputIntegrationAtom, } from "@src/store/workstation/codeEditor/outputIntegration"; +import type { UseOutputChannelsReturn } from "@src/types/workstation/output"; // ============================================ // Types diff --git a/src/modules/WorkStation/CodeEditor/EditorLayout/overlays/FileSearchPanel/BaseFileSearchPanel.tsx b/src/modules/WorkStation/CodeEditor/EditorLayout/overlays/FileSearchPanel/BaseFileSearchPanel.tsx index 3b7fc253fc..3244b59cfb 100644 --- a/src/modules/WorkStation/CodeEditor/EditorLayout/overlays/FileSearchPanel/BaseFileSearchPanel.tsx +++ b/src/modules/WorkStation/CodeEditor/EditorLayout/overlays/FileSearchPanel/BaseFileSearchPanel.tsx @@ -9,7 +9,6 @@ * - FileSearchPanel (sidebar variant) * - SingleFileSearchPanel (with spinner and close button) */ -import type { FileSearchResult } from "@/src/hooks/workStation/useCodeEditor"; import { Loader2, X } from "lucide-react"; import React, { memo, useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -19,6 +18,7 @@ import FolderIcon from "@src/assets/fileTypeIcons/folder-base.svg"; import FileTypeIcon from "@src/components/FileTypeIcon"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; import { useListNavigation } from "@src/hooks/keyboard/useListNavigation"; +import type { FileSearchResult } from "@src/modules/WorkStation/CodeEditor/hooks/useCodeEditor"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { SearchInput } from "../../../Panels/shared"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/content/ProblemsContent/HealthStatusDisplay.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/content/ProblemsContent/HealthStatusDisplay.tsx index cfbe798feb..3dcf165832 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/content/ProblemsContent/HealthStatusDisplay.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/content/ProblemsContent/HealthStatusDisplay.tsx @@ -13,7 +13,7 @@ import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; import { type SourceStatusMessage, useDiagnosticHealth, -} from "@src/hooks/workStation/diagnostics/useDiagnosticHealth"; +} from "@src/modules/WorkStation/CodeEditor/hooks/diagnostics/useDiagnosticHealth"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { triggerLspRetry } from "@src/store/workstation/codeEditor/diagnostics"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/hooks/useBottomPanelTabs.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/hooks/useBottomPanelTabs.ts index 9e48614d48..2bbec1d713 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/hooks/useBottomPanelTabs.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorBottomPanel/hooks/useBottomPanelTabs.ts @@ -6,7 +6,7 @@ import { useCallback } from "react"; import { useActionSystem } from "@src/ActionSystem"; -import { useBottomPanelState } from "@src/hooks/workStation"; +import { useBottomPanelState } from "@src/hooks/tabHost/useWorkStationPanels"; import type { BottomPanelTab } from "@src/store/ui/workStationAtom"; interface UseBottomPanelTabsOptions { diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/CodeViewerContent/types.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/CodeViewerContent/types.ts index 14290bedf8..f47ab033bc 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/CodeViewerContent/types.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/CodeViewerContent/types.ts @@ -5,7 +5,7 @@ import type { ConflictResolutionChoice, CursorPosition, } from "@src/features/CodeMirror"; -import type { FileError } from "@src/hooks/workStation/editor/useFileContent"; +import type { FileError } from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent"; import type { Diagnostic } from "../../../EditorBottomPanel/content/ProblemsContent/types"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/CsvTableView/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/CsvTableView/index.tsx index 79704ee2b0..15a7c0a306 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/CsvTableView/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/CsvTableView/index.tsx @@ -15,7 +15,7 @@ import { saveSpreadsheetCsvPatches, } from "@src/api/tauri/spreadsheetCsv"; import { Message } from "@src/components/Message"; -import { invalidateFileCache } from "@src/hooks/workStation/editor/useFileContent"; +import { invalidateFileCache } from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent"; import { UnsavedChangesBar } from "@src/modules/WorkStation/shared"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; diff --git a/src/hooks/workStation/database/__tests__/dbPreviewUtils.test.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/dbPreviewUtils.test.ts similarity index 98% rename from src/hooks/workStation/database/__tests__/dbPreviewUtils.test.ts rename to src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/dbPreviewUtils.test.ts index 8c4fcb4eb3..8075f1c3f2 100644 --- a/src/hooks/workStation/database/__tests__/dbPreviewUtils.test.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/dbPreviewUtils.test.ts @@ -7,7 +7,7 @@ import { getDbPreviewPageRange, getNextDbPreviewSortState, withUpdatedDbPreviewTableRowCount, -} from "../dbPreviewUtils"; +} from "./dbPreviewUtils"; describe("dbPreviewUtils", () => { describe("getDbPreviewPageRange", () => { diff --git a/src/hooks/workStation/database/dbPreviewUtils.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/dbPreviewUtils.ts similarity index 100% rename from src/hooks/workStation/database/dbPreviewUtils.ts rename to src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/dbPreviewUtils.ts diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/index.tsx index 28cc9d904e..d396b74880 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/index.tsx @@ -5,11 +5,6 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import Select, { type SelectOption } from "@src/components/Select"; import { useRefreshSpin } from "@src/hooks/ui"; -import { - DB_PREVIEW_PAGE_SIZE, - getDbPreviewPageRange, -} from "@src/hooks/workStation/database/dbPreviewUtils"; -import { useDbPreview } from "@src/hooks/workStation/database/useDbPreview"; import { TableSurface, type TableSurfaceColumn, @@ -17,6 +12,9 @@ import { } from "@src/modules/WorkStation/shared/TableSurface"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; +import { DB_PREVIEW_PAGE_SIZE, getDbPreviewPageRange } from "./dbPreviewUtils"; +import { useDbPreview } from "./useDbPreview"; + export interface DbPreviewViewProps { filePath: string; className?: string; diff --git a/src/hooks/workStation/database/useDbPreview.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/useDbPreview.ts similarity index 100% rename from src/hooks/workStation/database/useDbPreview.ts rename to src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/DbPreviewView/useDbPreview.ts diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/XlsxPreview/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/XlsxPreview/index.tsx index d53f28abe2..a02a05e8e1 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/XlsxPreview/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/FilePreviewContent/XlsxPreview/index.tsx @@ -16,7 +16,7 @@ import { saveSpreadsheetXlsxPatches, } from "@src/api/tauri/spreadsheetXlsx"; import Message from "@src/components/Message"; -import { invalidateFileCache } from "@src/hooks/workStation/editor/useFileContent"; +import { invalidateFileCache } from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent"; import { UnsavedChangesBar } from "@src/modules/WorkStation/shared"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { getFileName } from "@src/util/file/pathUtils"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/UrlPreviewContent/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/UrlPreviewContent/index.tsx index 64ee8f3c91..db2b06ec06 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/UrlPreviewContent/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/content/UrlPreviewContent/index.tsx @@ -13,8 +13,8 @@ import { useTranslation } from "react-i18next"; import Button from "@src/components/Button"; import { useInlineWebview } from "@src/hooks/platform/useInlineWebview"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { useRefreshSpin } from "@src/hooks/ui"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { isTauriDesktop } from "@src/util/platform/tauri"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useEditorPaneState.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useEditorPaneState.ts index 50ed417f5a..9dba9dda5e 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useEditorPaneState.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useEditorPaneState.ts @@ -17,7 +17,7 @@ import { type MutableRefObject, useCallback, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { createLogger } from "@src/hooks/logger"; -import { invalidateFileCache } from "@src/hooks/workStation/editor/useFileContent"; +import { invalidateFileCache } from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent"; import { tabToHost } from "@src/store/workstation/tabHost"; import { type PanelState, diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useFileContentManager.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useFileContentManager.ts index 85ae134554..a709165371 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useFileContentManager.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/hooks/useFileContentManager.ts @@ -18,7 +18,7 @@ import { type UseFileContentReturn, invalidateFileCache, useFileContent, -} from "@src/hooks/workStation/editor/useFileContent"; +} from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent"; import type { UseFileContentManagerOptions } from "../types"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/index.tsx index 70cf15b67c..c06a930c2b 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorMainPane/index.tsx @@ -34,10 +34,8 @@ import { useTranslation } from "react-i18next"; import { useActionSystem } from "@src/ActionSystem"; import { useGitStatus } from "@src/contexts/git"; import { useSourceControlAttention } from "@src/hooks/git/useSourceControlAttention"; -import { - usePublishWorkstationTabHeader, - useWorkStationTabShortcutBridge, -} from "@src/hooks/workStation"; +import { useWorkStationTabShortcutBridge } from "@src/hooks/tabHost/useWorkStationTabShortcutBridge"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import UnifiedTabContent from "@src/modules/WorkStation/TabContent/UnifiedTabContent"; import { NoTabsPlaceholder } from "@src/modules/WorkStation/shared"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/GitHistoryContent.remount.test.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/GitHistoryContent.remount.test.ts index 666d41a752..2582fe03e4 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/GitHistoryContent.remount.test.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/GitHistoryContent.remount.test.ts @@ -25,7 +25,7 @@ vi.mock("@src/ActionSystem", () => ({ useActionSystem: () => ({ dispatch: vi.fn() }), })); -vi.mock("@src/hooks/workStation/tabs/useWorkStationTabs", () => ({ +vi.mock("@src/hooks/tabHost/useWorkStationTabs", () => ({ useWorkStationTabs: () => ({ activeTab: { data: {}, type: "source-control" }, openTab: vi.fn(), diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/index.tsx index f62baf4fd0..ae127401c1 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/GitHistoryContent/index.tsx @@ -24,11 +24,11 @@ import { getGitCommits } from "@src/api/http/git/commits"; import type { GitCommitInfo } from "@src/api/http/git/types"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; import { SURFACE_TOKENS } from "@src/config/surfaceTokens"; -import { useImmediateCursorReset } from "@src/hooks/ui/useImmediateCursorReset"; import { type UseWorkStationTabsReturn, useWorkStationTabs, -} from "@src/hooks/workStation/tabs/useWorkStationTabs"; +} from "@src/hooks/tabHost/useWorkStationTabs"; +import { useImmediateCursorReset } from "@src/hooks/ui/useImmediateCursorReset"; import { PRIMARY_SIDEBAR_HOVER } from "@src/modules/WorkStation/shared/tokens"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; import { diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/StashContent/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/StashContent/index.tsx index fc91207046..1315bc6903 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/StashContent/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/StashContent/index.tsx @@ -29,7 +29,7 @@ import { type TreeRowNode, } from "@src/components/TreeRow"; import { SPINNER_TOKENS } from "@src/config/spinnerTokens"; -import { useWorkStationTabs } from "@src/hooks/workStation/tabs/useWorkStationTabs"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { COUNT_BADGE, HEADER_BUTTON, diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/TestingContent/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/TestingContent/index.tsx index febb34b3d0..1673a7f772 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/TestingContent/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/content/TestingContent/index.tsx @@ -31,7 +31,7 @@ import { VirtualizedStickyTree, stickyRowPadding, } from "@src/components/VirtualizedStickyTree"; -import { useTestRunner } from "@src/hooks/testRunner"; +import { useTestRunner } from "@src/modules/WorkStation/CodeEditor/hooks/useTestRunner"; import { HUMANTOOLS_TEXT_KEYS } from "@src/modules/WorkStation/shared"; import { usePrimarySidebarSurface } from "@src/modules/WorkStation/shared/hooks/usePrimarySidebarSurface"; import { Placeholder } from "@src/modules/shared/layouts/blocks"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useDisplayData.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useDisplayData.ts index d180006374..2171ee5ae8 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useDisplayData.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useDisplayData.ts @@ -11,13 +11,13 @@ * * Extracted from EditorPrimarySidebar. */ -import type { - FileNode, - FileSearchResult, -} from "@/src/hooks/workStation/useCodeEditor"; import { useMemo } from "react"; import type { TreePanelNode } from "@src/components/TreePanelSidebar/types"; +import type { + FileNode, + FileSearchResult, +} from "@src/modules/WorkStation/CodeEditor/hooks/useCodeEditor"; import type { EditorPrimarySidebarViewMode } from "../types"; import { buildTreeFromSearchResults, filterTree } from "../utils/filterTree"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/usePerRepoSourceControl.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/usePerRepoSourceControl.ts index 33835f330e..1cc5be59c5 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/usePerRepoSourceControl.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/usePerRepoSourceControl.ts @@ -25,15 +25,15 @@ import { type ScopedGitApi, createScopedGitApi, } from "@src/api/http/git/scopedGitApi"; +import { generateCommitMessage } from "@src/api/tauri/git/commitMessage"; import { normalizeGitStatus } from "@src/config/gitStatus"; -import { useFileSelection } from "@src/hooks/git/sourceControl"; -import { generateCommitMessage } from "@src/hooks/git/sourceControl/commitMessageGeneration"; import { refreshSharedGitStatus, useSharedGitStatus, } from "@src/hooks/git/useSharedGitStatus"; import { useWorkingTreeNumstat } from "@src/hooks/git/useWorkingTreeDiffTotals"; import { createLogger } from "@src/hooks/logger"; +import { useFileSelection } from "@src/modules/WorkStation/CodeEditor/hooks/sourceControl/useFileSelection"; import { gitCommitInstructionsAtom } from "@src/store/ui/editorSettingsAtom"; import type { GitFile } from "@src/types/git/types"; import { confirmDestructiveAction } from "@src/util/dialogs/confirmDestructiveAction"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useSourceControlState/index.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useSourceControlState/index.ts index 6806f20088..58d6397e1f 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useSourceControlState/index.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useSourceControlState/index.ts @@ -13,12 +13,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { DetachedHeadDialog } from "@src/components/GitDialogs"; import { useGitStatus } from "@src/contexts/git"; -import { - useCommitForm, - useFileSelection, - useGitFiles, -} from "@src/hooks/git/sourceControl"; import { useRepoSelection } from "@src/hooks/git/useRepoSelection"; +import { useCommitForm } from "@src/modules/WorkStation/CodeEditor/hooks/sourceControl/useCommitForm"; +import { useFileSelection } from "@src/modules/WorkStation/CodeEditor/hooks/sourceControl/useFileSelection"; +import { useGitFiles } from "@src/modules/WorkStation/CodeEditor/hooks/sourceControl/useGitFiles"; import { gitAutoCreatePrAtom } from "@src/store/ui/editorSettingsAtom"; import { gitReviewNavigationAtom } from "@src/store/workstation/codeEditor/gitReviewNavigationAtom"; import { gitOutputIntegrationAtom } from "@src/store/workstation/codeEditor/outputIntegration"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useTargetDirectory.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useTargetDirectory.ts index 664850bee0..bd092e8d57 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useTargetDirectory.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/hooks/useTargetDirectory.ts @@ -6,9 +6,10 @@ * * Extracted from EditorPrimarySidebar. */ -import type { FileNode } from "@/src/hooks/workStation/useCodeEditor"; import { useCallback } from "react"; +import type { FileNode } from "@src/modules/WorkStation/CodeEditor/hooks/useCodeEditor"; + export interface UseTargetDirectoryOptions { repoPath: string; /** The effective selected path (file or folder) */ diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/index.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/index.tsx index fe819248ba..c3bd4b2fe9 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/index.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/index.tsx @@ -27,7 +27,7 @@ import React, { memo, useCallback, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useSelectedFile } from "@src/hooks/workStation/tabs/useSelectedFile"; +import { useSelectedFile } from "@src/hooks/tabHost/useSelectedFile"; import { HUMANTOOLS_TEXT_KEYS, PrimarySidebarLayoutWithSections, diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/FilesTab.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/FilesTab.tsx index 837b40de2b..e8fb567e60 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/FilesTab.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/FilesTab.tsx @@ -12,7 +12,7 @@ import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import type { SectionHeaderAction } from "@src/components/TreePanelSidebar/types"; -import { useSelectedFile } from "@src/hooks/workStation/tabs/useSelectedFile"; +import { useSelectedFile } from "@src/hooks/tabHost/useSelectedFile"; import type { PrimarySidebarTab } from "@src/modules/WorkStation/shared"; import { ICON_CONFIG, PANEL_CONSTANTS } from "../config"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/SearchTab.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/SearchTab.tsx index 922398e63f..0fa03c095a 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/SearchTab.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/SearchTab.tsx @@ -19,7 +19,7 @@ import React, { import { useTranslation } from "react-i18next"; import type { SectionHeaderAction } from "@src/components/TreePanelSidebar/types"; -import { useOpenEditorFiles } from "@src/hooks/workStation/editor/useOpenEditorFiles"; +import { useOpenEditorFiles } from "@src/modules/WorkStation/CodeEditor/hooks/useOpenEditorFiles"; import type { PrimarySidebarTab } from "@src/modules/WorkStation/shared"; import { ICON_CONFIG, PANEL_CONSTANTS } from "../config"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/TestingTab.tsx b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/TestingTab.tsx index 79eb3a56e8..dfa0168c30 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/TestingTab.tsx +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/tabs/TestingTab.tsx @@ -13,8 +13,8 @@ import { import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; -import { useTestRunner } from "@src/hooks/testRunner"; import { useRefreshSpin } from "@src/hooks/ui"; +import { useTestRunner } from "@src/modules/WorkStation/CodeEditor/hooks/useTestRunner"; import type { PrimarySidebarTab } from "@src/modules/WorkStation/shared"; import { getFrameworkLabel } from "@src/types/testing"; diff --git a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/types.ts b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/types.ts index 9dd340f3b5..9550289919 100644 --- a/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/types.ts +++ b/src/modules/WorkStation/CodeEditor/Panels/EditorPrimarySidebar/types.ts @@ -6,7 +6,7 @@ import type { FileNode, FileSearchResult, -} from "@src/hooks/workStation/useCodeEditor"; +} from "@src/modules/WorkStation/CodeEditor/hooks/useCodeEditor"; import type { PrimarySidebarTabKey } from "@src/store/ui/workStationAtom"; import type { GitFile } from "@src/types/git/types"; diff --git a/src/hooks/workStation/git/__tests__/useGitDiffAdditional.test.ts b/src/modules/WorkStation/CodeEditor/hooks/__tests__/useGitDiffAdditional.test.ts similarity index 98% rename from src/hooks/workStation/git/__tests__/useGitDiffAdditional.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/__tests__/useGitDiffAdditional.test.ts index fc567da13c..0c6311782e 100644 --- a/src/hooks/workStation/git/__tests__/useGitDiffAdditional.test.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/__tests__/useGitDiffAdditional.test.ts @@ -8,13 +8,12 @@ */ import { describe, expect, it } from "vitest"; -import type { GitFile } from "@src/types/git/types"; - import { type GitDiffAction, gitDiffReducer, initialGitDiffState, -} from "../useGitDiffState"; +} from "@src/modules/WorkStation/CodeEditor/hooks/useGitDiffState"; +import type { GitFile } from "@src/types/git/types"; function f(path: string, overrides: Partial = {}): GitFile { return { diff --git a/src/hooks/workStation/git/__tests__/useGitDiffState.test.ts b/src/modules/WorkStation/CodeEditor/hooks/__tests__/useGitDiffState.test.ts similarity index 98% rename from src/hooks/workStation/git/__tests__/useGitDiffState.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/__tests__/useGitDiffState.test.ts index 3dc841e59b..246ca3648f 100644 --- a/src/hooks/workStation/git/__tests__/useGitDiffState.test.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/__tests__/useGitDiffState.test.ts @@ -10,13 +10,12 @@ */ import { describe, expect, it } from "vitest"; -import type { GitFile } from "@src/types/git/types"; - import { type GitDiffAction, gitDiffReducer, initialGitDiffState, -} from "../useGitDiffState"; +} from "@src/modules/WorkStation/CodeEditor/hooks/useGitDiffState"; +import type { GitFile } from "@src/types/git/types"; const HOST = "/repos/yorg_frontend"; const WT_A = "/worktrees/wt-a"; diff --git a/src/hooks/workStation/diagnostics/useDiagnosticHealth.ts b/src/modules/WorkStation/CodeEditor/hooks/diagnostics/useDiagnosticHealth.ts similarity index 100% rename from src/hooks/workStation/diagnostics/useDiagnosticHealth.ts rename to src/modules/WorkStation/CodeEditor/hooks/diagnostics/useDiagnosticHealth.ts diff --git a/src/hooks/workStation/diagnostics/useDiagnostics.ts b/src/modules/WorkStation/CodeEditor/hooks/diagnostics/useDiagnostics.ts similarity index 100% rename from src/hooks/workStation/diagnostics/useDiagnostics.ts rename to src/modules/WorkStation/CodeEditor/hooks/diagnostics/useDiagnostics.ts diff --git a/src/hooks/workStation/diagnostics/useLspDiagnostics.ts b/src/modules/WorkStation/CodeEditor/hooks/diagnostics/useLspDiagnostics.ts similarity index 100% rename from src/hooks/workStation/diagnostics/useLspDiagnostics.ts rename to src/modules/WorkStation/CodeEditor/hooks/diagnostics/useLspDiagnostics.ts diff --git a/src/hooks/workStation/fileContent/__tests__/cache.test.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/__tests__/cache.test.ts similarity index 99% rename from src/hooks/workStation/fileContent/__tests__/cache.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/__tests__/cache.test.ts index c5ca901a58..ec38450148 100644 --- a/src/hooks/workStation/fileContent/__tests__/cache.test.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/fileContent/__tests__/cache.test.ts @@ -17,7 +17,7 @@ import { popUnsavedContent, subscribeToFileChanges, updateCachedFileMtime, -} from "../cache"; +} from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/cache"; describe("fileContent/cache", () => { beforeEach(() => { diff --git a/src/hooks/workStation/fileContent/cache.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/cache.ts similarity index 100% rename from src/hooks/workStation/fileContent/cache.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/cache.ts diff --git a/src/hooks/workStation/fileContent/constants.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/constants.ts similarity index 100% rename from src/hooks/workStation/fileContent/constants.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/constants.ts diff --git a/src/hooks/workStation/fileContent/errors.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/errors.ts similarity index 100% rename from src/hooks/workStation/fileContent/errors.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/errors.ts diff --git a/src/hooks/workStation/fileContent/mtime.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/mtime.ts similarity index 100% rename from src/hooks/workStation/fileContent/mtime.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/mtime.ts diff --git a/src/hooks/workStation/fileContent/types.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/types.ts similarity index 100% rename from src/hooks/workStation/fileContent/types.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/types.ts diff --git a/src/hooks/workStation/editor/useFileContent.ts b/src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent.ts similarity index 98% rename from src/hooks/workStation/editor/useFileContent.ts rename to src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent.ts index 059b54d76e..4a5fb9b51b 100644 --- a/src/hooks/workStation/editor/useFileContent.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent.ts @@ -28,15 +28,15 @@ import { popUnsavedContent, subscribeToFileChanges, updateCachedFileMtime, -} from "../fileContent/cache"; -import { MAX_EDIT_LOG_SIZE } from "../fileContent/constants"; -import { classifyFileError } from "../fileContent/errors"; -import { fetchFileMtime } from "../fileContent/mtime"; +} from "./cache"; +import { MAX_EDIT_LOG_SIZE } from "./constants"; +import { classifyFileError } from "./errors"; +import { fetchFileMtime } from "./mtime"; import type { FileError, UseFileContentOptions, UseFileContentReturn, -} from "../fileContent/types"; +} from "./types"; const log = createLogger("FileContent"); diff --git a/src/hooks/workStation/useGitOutputIntegration/__tests__/formatters.test.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/__tests__/formatters.test.ts similarity index 97% rename from src/hooks/workStation/useGitOutputIntegration/__tests__/formatters.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/__tests__/formatters.test.ts index 34bc6d4c29..1871316c9e 100644 --- a/src/hooks/workStation/useGitOutputIntegration/__tests__/formatters.test.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/__tests__/formatters.test.ts @@ -7,7 +7,7 @@ import { formatSuccessMessage, formatTimestampFromDate, formatWatchMessage, -} from "../formatters"; +} from "@src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/formatters"; describe("formatTimestampFromDate", () => { it("formats fixed date with date, time, ms, and ANSI dim+italic+reset", () => { diff --git a/src/hooks/workStation/useGitOutputIntegration/constants.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/constants.ts similarity index 100% rename from src/hooks/workStation/useGitOutputIntegration/constants.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/constants.ts diff --git a/src/hooks/workStation/useGitOutputIntegration/createGitOperationHandler.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/createGitOperationHandler.ts similarity index 99% rename from src/hooks/workStation/useGitOutputIntegration/createGitOperationHandler.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/createGitOperationHandler.ts index 85cc0a2314..96a5008cfb 100644 --- a/src/hooks/workStation/useGitOutputIntegration/createGitOperationHandler.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/createGitOperationHandler.ts @@ -7,6 +7,11 @@ */ import type { GitErrorType } from "@src/api/http/git/streaming"; import { showGitErrorAndHandle } from "@src/hooks/git/useGitErrorDialog"; +import type { + GitOperationResult, + GitOperationType, + OperationContext, +} from "@src/types/workstation/gitOutputIntegration"; import { formatCommandMessage, @@ -15,11 +20,6 @@ import { formatSuccessMessage, formatTimestamp, } from "./formatters"; -import type { - GitOperationResult, - GitOperationType, - OperationContext, -} from "./types"; // ============================================ // Stream Callback Types diff --git a/src/hooks/workStation/useGitOutputIntegration/formatters.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/formatters.ts similarity index 100% rename from src/hooks/workStation/useGitOutputIntegration/formatters.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/formatters.ts diff --git a/src/hooks/workStation/useGitOutputIntegration/useFileWatchHeartbeat.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useFileWatchHeartbeat.ts similarity index 97% rename from src/hooks/workStation/useGitOutputIntegration/useFileWatchHeartbeat.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useFileWatchHeartbeat.ts index 3f4a7c5dcd..99c2ee9105 100644 --- a/src/hooks/workStation/useGitOutputIntegration/useFileWatchHeartbeat.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useFileWatchHeartbeat.ts @@ -6,8 +6,12 @@ */ import { useCallback, useRef } from "react"; +import type { + OutputChannel, + UseGitOutputIntegrationOptions, +} from "@src/types/workstation/gitOutputIntegration"; + import { formatTimestamp, formatWatchMessage } from "./formatters"; -import type { OutputChannel, UseGitOutputIntegrationOptions } from "./types"; // ============================================ // Hook Options & Return Types diff --git a/src/hooks/workStation/useGitOutputIntegration/useGitOperations.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOperations.ts similarity index 98% rename from src/hooks/workStation/useGitOutputIntegration/useGitOperations.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOperations.ts index 15fb87a0f9..d555afab5f 100644 --- a/src/hooks/workStation/useGitOutputIntegration/useGitOperations.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOperations.ts @@ -11,15 +11,15 @@ import { gitPullStream, gitPushStream, } from "@src/api/http/git/streaming"; - -import { createGitOperationHandler } from "./createGitOperationHandler"; -import { formatTimestamp } from "./formatters"; import type { GitOperationResult, OperationContext, OutputChannel, UseGitOutputIntegrationOptions, -} from "./types"; +} from "@src/types/workstation/gitOutputIntegration"; + +import { createGitOperationHandler } from "./createGitOperationHandler"; +import { formatTimestamp } from "./formatters"; // ============================================ // Operation Handlers (created once via factory) diff --git a/src/hooks/workStation/useGitOutputIntegration/useGitOutputIntegration.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOutputIntegration.ts similarity index 99% rename from src/hooks/workStation/useGitOutputIntegration/useGitOutputIntegration.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOutputIntegration.ts index 1da280f265..872b81f3fc 100644 --- a/src/hooks/workStation/useGitOutputIntegration/useGitOutputIntegration.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitOutputIntegration.ts @@ -15,14 +15,14 @@ import { useAtomValue } from "jotai"; import React, { useCallback, useEffect, useRef } from "react"; import { gitOperationAtom } from "@src/store/git"; - -import { loggedOperationIds, pruneLoggedOperationIds } from "./constants"; -import { ANSI, formatTimestampFromDate } from "./formatters"; import type { OutputChannel, UseGitOutputIntegrationOptions, UseGitOutputIntegrationReturn, -} from "./types"; +} from "@src/types/workstation/gitOutputIntegration"; + +import { loggedOperationIds, pruneLoggedOperationIds } from "./constants"; +import { ANSI, formatTimestampFromDate } from "./formatters"; import { useFileWatchHeartbeat } from "./useFileWatchHeartbeat"; import { useGitOperations } from "./useGitOperations"; import { useGitStagingOperations } from "./useGitStagingOperations"; diff --git a/src/hooks/workStation/useGitOutputIntegration/useGitStagingOperations.ts b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitStagingOperations.ts similarity index 98% rename from src/hooks/workStation/useGitOutputIntegration/useGitStagingOperations.ts rename to src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitStagingOperations.ts index b9c0938a68..f787010f86 100644 --- a/src/hooks/workStation/useGitOutputIntegration/useGitStagingOperations.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/gitOutputIntegration/useGitStagingOperations.ts @@ -11,14 +11,14 @@ import { appendGitCoauthorTrailer, shouldIncludeGitCoauthor, } from "@src/services/git/operations/commitAttribution"; - -import { createGitOperationHandlerWithReject } from "./createGitOperationHandler"; -import { ANSI, formatTimestamp } from "./formatters"; import type { OperationContext, OutputChannel, UseGitOutputIntegrationOptions, -} from "./types"; +} from "@src/types/workstation/gitOutputIntegration"; + +import { createGitOperationHandlerWithReject } from "./createGitOperationHandler"; +import { ANSI, formatTimestamp } from "./formatters"; // ============================================ // Operation Handlers (created once via factory) diff --git a/src/hooks/workStation/output/useFileWatchOutputIntegration.ts b/src/modules/WorkStation/CodeEditor/hooks/output/useFileWatchOutputIntegration.ts similarity index 98% rename from src/hooks/workStation/output/useFileWatchOutputIntegration.ts rename to src/modules/WorkStation/CodeEditor/hooks/output/useFileWatchOutputIntegration.ts index 0d63e14c01..6c5ad78b98 100644 --- a/src/hooks/workStation/output/useFileWatchOutputIntegration.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/output/useFileWatchOutputIntegration.ts @@ -8,9 +8,8 @@ import { useCallback, useEffect, useRef } from "react"; import { getCodeEditorWebSocket } from "@src/api/realtime/codeEditorWebSocket"; - -import { onExternalFileChange } from "../editor/useFileContent"; -import type { UseOutputChannelsReturn } from "./useOutputChannels"; +import { onExternalFileChange } from "@src/modules/WorkStation/CodeEditor/hooks/fileContent/useFileContent"; +import type { UseOutputChannelsReturn } from "@src/types/workstation/output"; interface GitFile { path: string; diff --git a/src/hooks/workStation/output/useOutputChannels.ts b/src/modules/WorkStation/CodeEditor/hooks/output/useOutputChannels.ts similarity index 87% rename from src/hooks/workStation/output/useOutputChannels.ts rename to src/modules/WorkStation/CodeEditor/hooks/output/useOutputChannels.ts index 707d66fca1..2b732d59ff 100644 --- a/src/hooks/workStation/output/useOutputChannels.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/output/useOutputChannels.ts @@ -10,6 +10,7 @@ import React, { useCallback, useState } from "react"; import type { OutputChannel, OutputChannelType, + UseOutputChannelsReturn, } from "@src/types/workstation/output"; // ============================================ @@ -25,33 +26,6 @@ export interface UseOutputChannelsOptions { persistHistory?: boolean; } -export interface UseOutputChannelsReturn { - /** All output channels */ - channels: OutputChannel[]; - /** Currently active channel ID */ - activeChannelId: string | null; - /** Get channel by ID */ - getChannel: (channelId: string) => OutputChannel | undefined; - /** Create a new channel */ - createChannel: ( - name: string, - type: OutputChannelType, - maxChars?: number - ) => string; - /** Delete a channel */ - deleteChannel: (channelId: string) => void; - /** Append text to a channel */ - appendToChannel: (channelId: string, text: string) => void; - /** Clear a channel */ - clearChannel: (channelId: string) => void; - /** Clear all channels */ - clearAllChannels: () => void; - /** Set active channel */ - setActiveChannel: (channelId: string) => void; - /** Set channel active status */ - setChannelActive: (channelId: string, active: boolean) => void; -} - // ============================================ // Hook // ============================================ diff --git a/src/hooks/workStation/output/useTaskOutputIntegration.ts b/src/modules/WorkStation/CodeEditor/hooks/output/useTaskOutputIntegration.ts similarity index 92% rename from src/hooks/workStation/output/useTaskOutputIntegration.ts rename to src/modules/WorkStation/CodeEditor/hooks/output/useTaskOutputIntegration.ts index 00ed115aac..b58489de50 100644 --- a/src/hooks/workStation/output/useTaskOutputIntegration.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/output/useTaskOutputIntegration.ts @@ -7,8 +7,10 @@ import React, { useCallback, useRef } from "react"; import { taskRunStream } from "@src/api/realtime/taskStreaming"; - -import type { UseOutputChannelsReturn } from "./useOutputChannels"; +import type { + UseOutputChannelsReturn, + UseTaskOutputIntegrationReturn, +} from "@src/types/workstation/output"; export interface UseTaskOutputIntegrationOptions { /** Output panel state */ @@ -21,20 +23,6 @@ export interface UseTaskOutputIntegrationOptions { onSwitchToOutput?: () => void; } -export interface UseTaskOutputIntegrationReturn { - /** Run a task with output streaming */ - runTaskWithOutput: (params: { - taskId: string; - command: string; - shell?: string; - }) => Promise<() => void>; - /** Run an npm script with output streaming */ - runNpmScriptWithOutput: (params: { - taskId: string; - script: string; - }) => Promise<() => void>; -} - /** * Hook to integrate task execution with the Output panel * diff --git a/src/hooks/workStation/editor/resolveFileAgainstRoots.test.ts b/src/modules/WorkStation/CodeEditor/hooks/resolveFileAgainstRoots.test.ts similarity index 100% rename from src/hooks/workStation/editor/resolveFileAgainstRoots.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/resolveFileAgainstRoots.test.ts diff --git a/src/hooks/workStation/editor/resolveFileAgainstRoots.ts b/src/modules/WorkStation/CodeEditor/hooks/resolveFileAgainstRoots.ts similarity index 100% rename from src/hooks/workStation/editor/resolveFileAgainstRoots.ts rename to src/modules/WorkStation/CodeEditor/hooks/resolveFileAgainstRoots.ts diff --git a/src/hooks/git/sourceControl/__tests__/TEST_CASES.md b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/__tests__/TEST_CASES.md similarity index 100% rename from src/hooks/git/sourceControl/__tests__/TEST_CASES.md rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/__tests__/TEST_CASES.md diff --git a/src/hooks/git/sourceControl/__tests__/gitFilesDerivation.test.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/__tests__/gitFilesDerivation.test.ts similarity index 96% rename from src/hooks/git/sourceControl/__tests__/gitFilesDerivation.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/__tests__/gitFilesDerivation.test.ts index d22d29bb1d..e1da387d80 100644 --- a/src/hooks/git/sourceControl/__tests__/gitFilesDerivation.test.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/__tests__/gitFilesDerivation.test.ts @@ -1,10 +1,12 @@ import { describe, expect, it } from "vitest"; import type { GitWorkingDirectoryFile } from "@src/api/http/git"; +import { + areBaseFileListsEqual, + deriveBaseFiles, +} from "@src/modules/WorkStation/CodeEditor/hooks/sourceControl/gitFilesDerivation"; import type { GitFile } from "@src/types/git/types"; -import { areBaseFileListsEqual, deriveBaseFiles } from "../gitFilesDerivation"; - function createStatusFile( overrides: Partial = {} ): GitWorkingDirectoryFile { diff --git a/src/hooks/git/sourceControl/commitFormHelpers.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormHelpers.ts similarity index 100% rename from src/hooks/git/sourceControl/commitFormHelpers.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormHelpers.ts diff --git a/src/hooks/git/sourceControl/commitFormOperations.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormOperations.ts similarity index 98% rename from src/hooks/git/sourceControl/commitFormOperations.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormOperations.ts index 4ecdb5fb52..796b06172f 100644 --- a/src/hooks/git/sourceControl/commitFormOperations.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormOperations.ts @@ -1,5 +1,5 @@ -import type { UseGitOutputIntegrationReturn } from "@src/hooks/workStation/useGitOutputIntegration/types"; import type { GitFile } from "@src/types/git/types"; +import type { UseGitOutputIntegrationReturn } from "@src/types/workstation/gitOutputIntegration"; import { showGitActionDialogSafely } from "@src/util/dialogs/gitActionDialog"; import { diff --git a/src/hooks/git/sourceControl/commitFormRemote.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormRemote.ts similarity index 100% rename from src/hooks/git/sourceControl/commitFormRemote.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/commitFormRemote.ts diff --git a/src/hooks/git/sourceControl/gitFilesDerivation.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/gitFilesDerivation.ts similarity index 100% rename from src/hooks/git/sourceControl/gitFilesDerivation.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/gitFilesDerivation.ts diff --git a/src/hooks/git/sourceControl/useCommitForm.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/useCommitForm.ts similarity index 99% rename from src/hooks/git/sourceControl/useCommitForm.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/useCommitForm.ts index 02b614daf9..50b7ba0220 100644 --- a/src/hooks/git/sourceControl/useCommitForm.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/useCommitForm.ts @@ -8,6 +8,7 @@ import { import { useTranslation } from "react-i18next"; import { useActionSystemOptional } from "@src/ActionSystem"; +import { generateCommitMessage } from "@src/api/tauri/git/commitMessage"; import { useGitOperations } from "@src/hooks/git/useGitOperations"; import { gitCommitInstructionsAtom } from "@src/store/ui/editorSettingsAtom"; import { gitOutputIntegrationAtom } from "@src/store/workstation/codeEditor/outputIntegration"; @@ -16,7 +17,6 @@ import { showGitActionDialogSafely } from "@src/util/dialogs/gitActionDialog"; import { runAmendOperation, runCommitOperation } from "./commitFormOperations"; import { hasConfiguredGitRemote } from "./commitFormRemote"; -import { generateCommitMessage } from "./commitMessageGeneration"; export interface CommitSuccessOptions { pushed?: boolean; diff --git a/src/hooks/git/sourceControl/useFileSelection.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/useFileSelection.ts similarity index 100% rename from src/hooks/git/sourceControl/useFileSelection.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/useFileSelection.ts diff --git a/src/hooks/git/sourceControl/useGitFiles.ts b/src/modules/WorkStation/CodeEditor/hooks/sourceControl/useGitFiles.ts similarity index 100% rename from src/hooks/git/sourceControl/useGitFiles.ts rename to src/modules/WorkStation/CodeEditor/hooks/sourceControl/useGitFiles.ts diff --git a/src/hooks/workStation/useCodeEditor/__tests__/helpers.test.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/__tests__/helpers.test.ts similarity index 98% rename from src/hooks/workStation/useCodeEditor/__tests__/helpers.test.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/__tests__/helpers.test.ts index 2b95b77079..b26fdab711 100644 --- a/src/hooks/workStation/useCodeEditor/__tests__/helpers.test.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/__tests__/helpers.test.ts @@ -1,12 +1,11 @@ import { describe, expect, it } from "vitest"; -import type { FileNode } from "@src/store/workstation/codeEditor/file"; - import { findNodeInTree, updateTreeChildren, updateTreeExpansion, -} from "../helpers"; +} from "@src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/helpers"; +import type { FileNode } from "@src/store/workstation/codeEditor/file"; function file(path: string, name: string): FileNode { return { name, path, type: "file", expanded: false }; diff --git a/src/hooks/workStation/useCodeEditor/helpers.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/helpers.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/helpers.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/helpers.ts diff --git a/src/hooks/workStation/useCodeEditor/index.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/index.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/index.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/index.ts diff --git a/src/hooks/workStation/useCodeEditor/types.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/types.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/types.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/types.ts diff --git a/src/hooks/workStation/useCodeEditor/useFileContent.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useFileContent.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/useFileContent.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useFileContent.ts diff --git a/src/hooks/workStation/useCodeEditor/useFileSearch.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useFileSearch.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/useFileSearch.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useFileSearch.ts diff --git a/src/hooks/workStation/useCodeEditor/useFileTree.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useFileTree.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/useFileTree.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useFileTree.ts diff --git a/src/hooks/workStation/useCodeEditor/useMultiRootFileTree.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useMultiRootFileTree.ts similarity index 100% rename from src/hooks/workStation/useCodeEditor/useMultiRootFileTree.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditor/useMultiRootFileTree.ts diff --git a/src/hooks/workStation/editor/useCodeEditorEvents.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditorEvents.ts similarity index 100% rename from src/hooks/workStation/editor/useCodeEditorEvents.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditorEvents.ts diff --git a/src/hooks/workStation/editor/useCodeEditorHandlers.ts b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditorHandlers.ts similarity index 98% rename from src/hooks/workStation/editor/useCodeEditorHandlers.ts rename to src/modules/WorkStation/CodeEditor/hooks/useCodeEditorHandlers.ts index 72f13fc6d2..06ff7abeec 100644 --- a/src/hooks/workStation/editor/useCodeEditorHandlers.ts +++ b/src/modules/WorkStation/CodeEditor/hooks/useCodeEditorHandlers.ts @@ -23,8 +23,8 @@ import { } from "@src/store/workstation/tabs"; import type { GitFile } from "@src/types/git/types"; -import type { UseGitDiffStateReturn } from "../git/useGitDiffState"; -import type { UseCodeEditorReturn } from "../useCodeEditor"; +import type { UseCodeEditorReturn } from "./useCodeEditor"; +import type { UseGitDiffStateReturn } from "./useGitDiffState"; const logger = createLogger("CodeEditorHandlers"); diff --git a/src/hooks/workStation/git/useGitDiffState.ts b/src/modules/WorkStation/CodeEditor/hooks/useGitDiffState.ts similarity index 100% rename from src/hooks/workStation/git/useGitDiffState.ts rename to src/modules/WorkStation/CodeEditor/hooks/useGitDiffState.ts diff --git a/src/hooks/workStation/editor/useOpenEditorFiles.ts b/src/modules/WorkStation/CodeEditor/hooks/useOpenEditorFiles.ts similarity index 100% rename from src/hooks/workStation/editor/useOpenEditorFiles.ts rename to src/modules/WorkStation/CodeEditor/hooks/useOpenEditorFiles.ts diff --git a/src/hooks/testRunner/useTestRunner.ts b/src/modules/WorkStation/CodeEditor/hooks/useTestRunner.ts similarity index 100% rename from src/hooks/testRunner/useTestRunner.ts rename to src/modules/WorkStation/CodeEditor/hooks/useTestRunner.ts diff --git a/src/modules/WorkStation/CodeEditor/index.tsx b/src/modules/WorkStation/CodeEditor/index.tsx index 6da45f65da..65d37c24b9 100644 --- a/src/modules/WorkStation/CodeEditor/index.tsx +++ b/src/modules/WorkStation/CodeEditor/index.tsx @@ -5,22 +5,16 @@ * diagnostics, and more. Extracted from AppContainer for clean separation. */ import { useTerminalState } from "@/src/engines/TerminalCore/hooks/useTerminalState"; -import { useCodeEditorHandlers } from "@/src/hooks/workStation/editor/useCodeEditorHandlers"; -import { useGitDiffState } from "@/src/hooks/workStation/git/useGitDiffState"; -import { useCodeEditor } from "@/src/hooks/workStation/useCodeEditor"; import { invoke } from "@tauri-apps/api/core"; import { useAtomValue, useSetAtom } from "jotai"; import React, { memo, useCallback, useEffect, useMemo, useState } from "react"; import { ActionSystemProvider } from "@src/ActionSystem"; import { useRepoSelection } from "@src/hooks/git/useRepoSelection"; +import { usePinnedTabs } from "@src/hooks/tabHost/usePinnedTabs"; +import { useWorkStationPanels } from "@src/hooks/tabHost/useWorkStationPanels"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { useEditorRepoCacheSync } from "@src/hooks/ui/tabs"; -import { useWorkStationPanels } from "@src/hooks/workStation"; -import { useDiagnostics } from "@src/hooks/workStation/diagnostics/useDiagnostics"; -import { useCodeEditorEvents } from "@src/hooks/workStation/editor/useCodeEditorEvents"; -import { useOutputChannels } from "@src/hooks/workStation/output/useOutputChannels"; -import { useWorkStationTabs } from "@src/hooks/workStation/tabs"; -import { usePinnedTabs } from "@src/hooks/workStation/tabs/usePinnedTabs"; import { CODE_EDITOR_CONFIG } from "@src/modules/WorkStation/CodeEditor/config"; import { type PrimarySidebarTabKey } from "@src/store/ui/workStationAtom"; import { workspaceFoldersAtom } from "@src/store/ui/workspaceFoldersAtom"; @@ -48,6 +42,12 @@ import FileSearchPanel from "./EditorLayout/overlays/FileSearchPanel"; import EditorBottomPanel from "./Panels/EditorBottomPanel"; import EditorContent from "./Panels/EditorMainPane"; import { EditorPrimarySidebar } from "./Panels/EditorPrimarySidebar"; +import { useDiagnostics } from "./hooks/diagnostics/useDiagnostics"; +import { useOutputChannels } from "./hooks/output/useOutputChannels"; +import { useCodeEditor } from "./hooks/useCodeEditor"; +import { useCodeEditorEvents } from "./hooks/useCodeEditorEvents"; +import { useCodeEditorHandlers } from "./hooks/useCodeEditorHandlers"; +import { useGitDiffState } from "./hooks/useGitDiffState"; import { useCodeEditorLocalState } from "./useCodeEditorLocalState"; import { useSourceControlSetup } from "./useSourceControlSetup"; diff --git a/src/modules/WorkStation/CodeEditor/useCodeEditorLocalState.ts b/src/modules/WorkStation/CodeEditor/useCodeEditorLocalState.ts index 6b504f5c5d..3e7ddab077 100644 --- a/src/modules/WorkStation/CodeEditor/useCodeEditorLocalState.ts +++ b/src/modules/WorkStation/CodeEditor/useCodeEditorLocalState.ts @@ -6,11 +6,9 @@ * diagnostics callbacks, terminal helpers, and both status-bar effects. */ import { useTerminalState } from "@/src/engines/TerminalCore/hooks/useTerminalState"; -import { useCodeEditor } from "@/src/hooks/workStation/useCodeEditor"; import { useAtomValue, useSetAtom } from "jotai"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useDiagnostics } from "@src/hooks/workStation/diagnostics/useDiagnostics"; import { createBranchSpotlightRequest, createWorkspaceSpotlightRequest, @@ -38,6 +36,8 @@ import { isPreviewOnlyFile } from "@src/util/file/previewTypes"; import { formatRelativeTime } from "@src/util/time/formatRelativeTime"; import type { CommitInfo, CursorPosition, LspStatus } from "../shared"; +import { useDiagnostics } from "./hooks/diagnostics/useDiagnostics"; +import { useCodeEditor } from "./hooks/useCodeEditor"; // ── Types ───────────────────────────────────────────────────────────────────── diff --git a/src/modules/WorkStation/CodeEditor/useSourceControlSetup.ts b/src/modules/WorkStation/CodeEditor/useSourceControlSetup.ts index e35217d0b2..2791eab633 100644 --- a/src/modules/WorkStation/CodeEditor/useSourceControlSetup.ts +++ b/src/modules/WorkStation/CodeEditor/useSourceControlSetup.ts @@ -5,8 +5,6 @@ import { useTranslation } from "react-i18next"; import type { GitWorktreeEntry } from "@src/api/http/git/types"; import { useGitStatus } from "@src/contexts/git"; import { useRepoGitInitialization } from "@src/hooks/git"; -import { useGitFiles } from "@src/hooks/git/sourceControl"; -import type { UseGitDiffStateReturn } from "@src/hooks/workStation/git/useGitDiffState"; import { sourceControlFilterModeAtom, sourceControlFilterModeHandlerAtom, @@ -37,6 +35,8 @@ import { type ScopePickerWorktreeEntry, resolveScopeRepoRoot, } from "./Panels/EditorPrimarySidebar/tabs/sourceControlScopePickerHelpers"; +import { useGitFiles } from "./hooks/sourceControl/useGitFiles"; +import type { UseGitDiffStateReturn } from "./hooks/useGitDiffState"; import { resolveGitDiffSelection } from "./sourceControlSelection"; import { rememberSourceControlFocusPath } from "./sourceControlStateTransitions"; import { useStashCount } from "./useStashCount"; diff --git a/src/modules/WorkStation/Diff/SessionReplay/index.tsx b/src/modules/WorkStation/Diff/SessionReplay/index.tsx index c46a61cd8d..5c6b8abfe1 100644 --- a/src/modules/WorkStation/Diff/SessionReplay/index.tsx +++ b/src/modules/WorkStation/Diff/SessionReplay/index.tsx @@ -24,7 +24,7 @@ import { SIMULATOR_PRIMARY_SIDEBAR } from "@src/config/simulatorPrimarySidebar"; import { simulatorEventsAtom } from "@src/engines/SessionCore/derived/simulatorEvents"; import type { SimulatorAppProps } from "@src/engines/Simulator/apps/core/types"; import { useFileReviewBatchActions } from "@src/hooks/fileReview/useFileReview"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { NoTabsPlaceholder, SimulatorReplayChrome, diff --git a/src/modules/WorkStation/ProjectManager/SessionReplay/index.tsx b/src/modules/WorkStation/ProjectManager/SessionReplay/index.tsx index 077a825129..b8de1371ec 100644 --- a/src/modules/WorkStation/ProjectManager/SessionReplay/index.tsx +++ b/src/modules/WorkStation/ProjectManager/SessionReplay/index.tsx @@ -11,7 +11,7 @@ import { useTranslation } from "react-i18next"; import type { SessionEvent } from "@src/engines/SessionCore"; import type { SimulatorAppProps } from "@src/engines/Simulator/apps/core/types"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { ProjectRow } from "@src/modules/ProjectManager/Projects/components"; import { WorkItemContent, diff --git a/src/modules/WorkStation/TabContent/renderers/agentConfig.tsx b/src/modules/WorkStation/TabContent/renderers/agentConfig.tsx index c0552dadda..e48ac72358 100644 --- a/src/modules/WorkStation/TabContent/renderers/agentConfig.tsx +++ b/src/modules/WorkStation/TabContent/renderers/agentConfig.tsx @@ -32,7 +32,7 @@ import { rpc } from "@src/api/tauri/rpc"; import { Message } from "@src/components/Message"; import { useKeyVault } from "@src/hooks/keyVault"; import { createLogger } from "@src/hooks/logger"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { BuiltInAgentDetailView } from "@src/modules/MainApp/AgentOrgs/components/BuiltInAgentDetailViews"; import CliAgentDetailView from "@src/modules/MainApp/AgentOrgs/components/CliAgentDetailView"; import CustomAgentDetailView from "@src/modules/MainApp/AgentOrgs/components/CustomAgentDetailView"; diff --git a/src/modules/WorkStation/TabContent/renderers/chatSession.tsx b/src/modules/WorkStation/TabContent/renderers/chatSession.tsx index 2464cd7548..b5f267fa26 100644 --- a/src/modules/WorkStation/TabContent/renderers/chatSession.tsx +++ b/src/modules/WorkStation/TabContent/renderers/chatSession.tsx @@ -22,7 +22,7 @@ import { useSessionActionModals } from "@src/engines/ChatPanel/hooks/useSessionA import { useSessionHeaderActions } from "@src/engines/ChatPanel/hooks/useSessionHeaderActions"; import { useSessionViewMode } from "@src/engines/ChatPanel/hooks/useSessionViewMode"; import SessionViewersIndicator from "@src/features/Org2Cloud/SessionViewersIndicator"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { getChatPanelBackgroundStyle } from "@src/modules/shared/layouts/viewContainerTokens"; import { sessionByIdAtom } from "@src/store/session"; import type { SessionContinuation } from "@src/store/session/sessionTabPlacementAtom"; diff --git a/src/modules/WorkStation/TabContent/renderers/directory.tsx b/src/modules/WorkStation/TabContent/renderers/directory.tsx index 011aaada50..f8b5defcd3 100644 --- a/src/modules/WorkStation/TabContent/renderers/directory.tsx +++ b/src/modules/WorkStation/TabContent/renderers/directory.tsx @@ -7,7 +7,7 @@ * from `tab.data`. * * `directory` is editor-only — tabs are created only from - * `hooks/workStation/editor/useCodeEditorEvents.ts` and recursively from + * `CodeEditor/hooks/useCodeEditorEvents.ts` and recursively from * `DirectoryExplorerContent` itself — so coupling this renderer to the editor * host is safe: it throws if mounted outside an `EditorHostProvider`. */ diff --git a/src/modules/WorkStation/TabContent/renderers/githubIssueDetail.tsx b/src/modules/WorkStation/TabContent/renderers/githubIssueDetail.tsx index 1ae5d1739a..2953eb6d9d 100644 --- a/src/modules/WorkStation/TabContent/renderers/githubIssueDetail.tsx +++ b/src/modules/WorkStation/TabContent/renderers/githubIssueDetail.tsx @@ -7,7 +7,7 @@ */ import React, { memo, useMemo } from "react"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { IssueDetailExternalLinkButton, IssueDetailPanel, diff --git a/src/modules/WorkStation/TabContent/renderers/githubPrDetail.tsx b/src/modules/WorkStation/TabContent/renderers/githubPrDetail.tsx index 2aa796647b..28a438e85e 100644 --- a/src/modules/WorkStation/TabContent/renderers/githubPrDetail.tsx +++ b/src/modules/WorkStation/TabContent/renderers/githubPrDetail.tsx @@ -10,8 +10,8 @@ import { useAtomValue } from "jotai"; import React, { memo, useCallback, useMemo } from "react"; -import { usePublishWorkstationTabHeader } from "@src/hooks/workStation"; -import { useWorkStationTabs } from "@src/hooks/workStation/tabs/useWorkStationTabs"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; +import { usePublishWorkstationTabHeader } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { PrDetailExternalLinkButton, PrDetailHeaderContent, diff --git a/src/modules/WorkStation/shared/SidebarModules/Benchmark/BenchmarkTabSidebar.tsx b/src/modules/WorkStation/shared/SidebarModules/Benchmark/BenchmarkTabSidebar.tsx index 032a4bd492..875797430a 100644 --- a/src/modules/WorkStation/shared/SidebarModules/Benchmark/BenchmarkTabSidebar.tsx +++ b/src/modules/WorkStation/shared/SidebarModules/Benchmark/BenchmarkTabSidebar.tsx @@ -7,7 +7,7 @@ import type { BenchmarkTaskIndexRow } from "@src/api/tauri/benchmark"; import Input from "@src/components/Input"; import type { SectionHeaderAction } from "@src/components/TreePanelSidebar/types"; import { TreeRowBase, type TreeRowNode } from "@src/components/TreeRow"; -import { useBenchmarkTasks } from "@src/hooks/benchmark/useBenchmarkTasks"; +import { useBenchmarkTasks } from "@src/features/BenchmarkPanel/hooks/useBenchmarkTasks"; import { useRefreshSpin } from "@src/hooks/ui"; import { ICON_CONFIG, diff --git a/src/modules/WorkStation/shared/StatusBar/ProjectOrgGitFolderSyncWidget.tsx b/src/modules/WorkStation/shared/StatusBar/ProjectOrgGitFolderSyncWidget.tsx index 4af6de6a75..12ccd4047a 100644 --- a/src/modules/WorkStation/shared/StatusBar/ProjectOrgGitFolderSyncWidget.tsx +++ b/src/modules/WorkStation/shared/StatusBar/ProjectOrgGitFolderSyncWidget.tsx @@ -7,7 +7,7 @@ import { PROJECT_GIT_FOLDER_SYNC_STATUS, projectApi, } from "@src/api/http/project"; -import { useWorkStationTabs } from "@src/hooks/workStation"; +import { useWorkStationTabs } from "@src/hooks/tabHost/useWorkStationTabs"; import { projectGitFolderSyncResultByOrgAtom, projectListRefreshAtom, diff --git a/src/modules/index.tsx b/src/modules/index.tsx index 8fcb126e09..1fc65cdd41 100644 --- a/src/modules/index.tsx +++ b/src/modules/index.tsx @@ -30,10 +30,8 @@ import { BrowserProvider, TerminalProvider } from "@src/contexts/workstation"; import { useViewportWidth } from "@src/engines/ChatPanel/hooks/useViewportWidth"; import { useAgentADEActions } from "@src/engines/SessionCore/hooks/useAgentADEActions"; import { useProjectDataChangedListener } from "@src/hooks/project"; +import { useUrlPreviewEvents } from "@src/hooks/tabHost/useUrlPreviewEvents"; import { useBackgroundImage } from "@src/hooks/theme/useBackgroundImage"; -import { useOpenUrlInBrowser } from "@src/hooks/workStation/browser/useOpenUrlInBrowser"; -import { useUrlPreviewEvents } from "@src/hooks/workStation/tabs"; -import { useNarrowChatFocus } from "@src/hooks/workStation/useNarrowChatFocus"; import { useGlobalBrowserWebviewLayering } from "@src/modules/WorkStation/Browser/hooks"; import { CODE_EDITOR_TOUR_EVENT } from "@src/scaffold/Tutorials/codeEditorTourConfig"; import { @@ -73,6 +71,8 @@ import { FloatingSidebar } from "./shared/components/FloatingSidebar"; import { SidebarSelector } from "./shared/components/SidebarSelector"; import { useRouteLayoutType, useWorkspaceEvents } from "./shared/hooks"; import { AppLayout } from "./shared/layouts"; +import { useNarrowChatFocus } from "./useNarrowChatFocus"; +import { useOpenUrlInBrowser } from "./useOpenUrlInBrowser"; import { useWorkStationPipelineBridge } from "./useWorkStationPipelineBridge"; const WorkStationPage = React.lazy( diff --git a/src/modules/shared/components/FileHeader/FileHeaderShell.tsx b/src/modules/shared/components/FileHeader/FileHeaderShell.tsx index 3605a4d454..08fed43a3b 100644 --- a/src/modules/shared/components/FileHeader/FileHeaderShell.tsx +++ b/src/modules/shared/components/FileHeader/FileHeaderShell.tsx @@ -14,7 +14,7 @@ import { HEADER_CLASSES } from "@src/config/workstation/tokens"; import { type WorkstationTabHeaderHost, usePublishWorkstationTabHeader, -} from "@src/hooks/workStation"; +} from "@src/hooks/tabHost/useWorkstationTabHeader"; export interface FileHeaderShellProps { className?: string; diff --git a/src/modules/shared/components/FileHeader/index.tsx b/src/modules/shared/components/FileHeader/index.tsx index 2d92ad4971..b934cc649d 100644 --- a/src/modules/shared/components/FileHeader/index.tsx +++ b/src/modules/shared/components/FileHeader/index.tsx @@ -25,8 +25,8 @@ import FileTypeIcon from "@src/components/FileTypeIcon"; import Message from "@src/components/Message"; import TabPill from "@src/components/TabPill"; import { HEADER_ICON_SIZE } from "@src/config/workstation/tokens"; +import type { WorkstationTabHeaderHost } from "@src/hooks/tabHost/useWorkstationTabHeader"; import { useRefreshSpin } from "@src/hooks/ui"; -import { type WorkstationTabHeaderHost } from "@src/hooks/workStation"; import { PANEL_HEADER_TOKENS } from "@src/modules/shared/layouts/blocks/PanelHeader"; import type { DiffViewMode } from "@src/types/git/types"; import { copyText } from "@src/util/data/clipboard"; diff --git a/src/modules/shared/layouts/FocusedChatWorkstationRail.tsx b/src/modules/shared/layouts/FocusedChatWorkstationRail.tsx index 30d55c662b..ad89124dd7 100644 --- a/src/modules/shared/layouts/FocusedChatWorkstationRail.tsx +++ b/src/modules/shared/layouts/FocusedChatWorkstationRail.tsx @@ -48,7 +48,7 @@ import { useActiveRepoRef } from "@src/hooks/git/useActiveRepoRef"; import { useBranchPullRequestStatus } from "@src/hooks/git/useBranchPullRequestStatus"; import { useRepoSelection } from "@src/hooks/git/useRepoSelection"; import { useWorkingTreeDiffTotals } from "@src/hooks/git/useWorkingTreeDiffTotals"; -import { useCloseTabWithGuard } from "@src/hooks/workStation/tabs/useCloseTabWithGuard"; +import { useCloseTabWithGuard } from "@src/hooks/tabHost/useCloseTabWithGuard"; import type { BranchCiStatus } from "@src/services/git/branchPullRequestStatus"; import { WorkStationViewService } from "@src/services/workStation/WorkStationViewService"; import { chatPanelMaximizedAtom } from "@src/store/ui/chatPanelAtom"; diff --git a/src/hooks/workStation/useNarrowChatFocus.test.ts b/src/modules/useNarrowChatFocus.test.ts similarity index 100% rename from src/hooks/workStation/useNarrowChatFocus.test.ts rename to src/modules/useNarrowChatFocus.test.ts diff --git a/src/hooks/workStation/useNarrowChatFocus.ts b/src/modules/useNarrowChatFocus.ts similarity index 100% rename from src/hooks/workStation/useNarrowChatFocus.ts rename to src/modules/useNarrowChatFocus.ts diff --git a/src/hooks/workStation/browser/useOpenUrlInBrowser.ts b/src/modules/useOpenUrlInBrowser.ts similarity index 100% rename from src/hooks/workStation/browser/useOpenUrlInBrowser.ts rename to src/modules/useOpenUrlInBrowser.ts diff --git a/src/hooks/workStation/panels/contextMenuSearchHandlers.ts b/src/scaffold/ContextMenu/contextMenuSearchHandlers.ts similarity index 100% rename from src/hooks/workStation/panels/contextMenuSearchHandlers.ts rename to src/scaffold/ContextMenu/contextMenuSearchHandlers.ts diff --git a/src/hooks/workStation/panels/__tests__/contextMenuSearchRoots.test.ts b/src/scaffold/ContextMenu/contextMenuSearchRoots.test.ts similarity index 98% rename from src/hooks/workStation/panels/__tests__/contextMenuSearchRoots.test.ts rename to src/scaffold/ContextMenu/contextMenuSearchRoots.test.ts index 6df78598af..fef9a8cfc4 100644 --- a/src/hooks/workStation/panels/__tests__/contextMenuSearchRoots.test.ts +++ b/src/scaffold/ContextMenu/contextMenuSearchRoots.test.ts @@ -5,7 +5,7 @@ import { buildContextMenuSearchRoots, buildRootSearchResult, mergeSearchResultsByRoot, -} from "../contextMenuSearchRoots"; +} from "./contextMenuSearchRoots"; describe("contextMenuSearchRoots", () => { it("uses all workspace folders before adding a fallback repo path", () => { diff --git a/src/hooks/workStation/panels/contextMenuSearchRoots.ts b/src/scaffold/ContextMenu/contextMenuSearchRoots.ts similarity index 100% rename from src/hooks/workStation/panels/contextMenuSearchRoots.ts rename to src/scaffold/ContextMenu/contextMenuSearchRoots.ts diff --git a/src/scaffold/ContextMenu/index.tsx b/src/scaffold/ContextMenu/index.tsx index 23c12866ec..2e10a94909 100644 --- a/src/scaffold/ContextMenu/index.tsx +++ b/src/scaffold/ContextMenu/index.tsx @@ -17,12 +17,12 @@ import { useTranslation } from "react-i18next"; import { DROPDOWN_CLASSES } from "@src/components/Dropdown/tokens"; import { useMouseMoved } from "@src/hooks/ui/useMouseMoved"; -import { useContextMenu } from "@src/hooks/workStation/panels/useContextMenu"; import { SearchResultsPanel, SecondLayerPanel } from "./MenuSections"; import { MenuItemRow } from "./ResultItems"; import { MENU_ITEMS, STYLE_CONFIG } from "./config"; import type { ContextMenuCustomMentionOption, ContextMenuProps } from "./types"; +import { useContextMenu } from "./useContextMenu"; import { useMenuEffects } from "./useMenuEffects"; interface CustomMentionGroup { diff --git a/src/hooks/workStation/panels/useContextMenu.ts b/src/scaffold/ContextMenu/useContextMenu.ts similarity index 99% rename from src/hooks/workStation/panels/useContextMenu.ts rename to src/scaffold/ContextMenu/useContextMenu.ts index dc044dded2..7d1c2f8278 100644 --- a/src/hooks/workStation/panels/useContextMenu.ts +++ b/src/scaffold/ContextMenu/useContextMenu.ts @@ -42,8 +42,8 @@ import { import { sessionsAtom } from "@src/store/session/sessionAtom"; import { workspaceFoldersAtom } from "@src/store/ui/workspaceFoldersAtom"; import { activeWorkspaceRootAtom } from "@src/store/workspace"; +import { LatestRequestGuard } from "@src/util/core/latestRequestGuard"; -import { LatestRequestGuard } from "../latestRequestGuard"; import { type DrilledProject, searchFiles, diff --git a/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/fileModeSearch.ts b/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/fileModeSearch.ts index d1c7bf140b..06a639b52a 100644 --- a/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/fileModeSearch.ts +++ b/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/fileModeSearch.ts @@ -1,5 +1,5 @@ -import type { ContextMenuSearchRoot } from "@src/hooks/workStation/panels/contextMenuSearchRoots"; -import { normalizeRootPath } from "@src/hooks/workStation/panels/contextMenuSearchRoots"; +import type { ContextMenuSearchRoot } from "@src/scaffold/ContextMenu/contextMenuSearchRoots"; +import { normalizeRootPath } from "@src/scaffold/ContextMenu/contextMenuSearchRoots"; import type { FileSearchResult as NativeFileSearchResult } from "@src/util/platform/tauri/fileSearch"; import type { FileSearchResult } from "../types"; diff --git a/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/useFileMode.ts b/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/useFileMode.ts index 2c528a6ec6..aa67fc2c1c 100644 --- a/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/useFileMode.ts +++ b/src/scaffold/GlobalSpotlight/palettes/EditorPalette/hooks/useFileMode.ts @@ -12,7 +12,7 @@ import { createLogger } from "@src/hooks/logger"; import { type ContextMenuSearchRoot, buildContextMenuSearchRoots, -} from "@src/hooks/workStation/panels/contextMenuSearchRoots"; +} from "@src/scaffold/ContextMenu/contextMenuSearchRoots"; import type { Repo } from "@src/store/repo/types"; import type { WorkspaceFolder } from "@src/types/workspace"; import { diff --git a/src/services/guiAgent/GUIAgentService.ts b/src/services/guiAgent/GUIAgentService.ts index 608bdd6798..1c49d90d8c 100644 --- a/src/services/guiAgent/GUIAgentService.ts +++ b/src/services/guiAgent/GUIAgentService.ts @@ -13,7 +13,7 @@ * GUIAgentService.connect(outputState); */ import type { ActionResult } from "@src/ActionSystem/schema/defineZodAction"; -import type { UseOutputChannelsReturn } from "@src/hooks/workStation/output/useOutputChannels"; +import type { UseOutputChannelsReturn } from "@src/types/workstation/output"; // ============================================ // ANSI Color Codes diff --git a/src/store/workstation/codeEditor/outputIntegration/gitOutputAtom.ts b/src/store/workstation/codeEditor/outputIntegration/gitOutputAtom.ts index a9223fe17c..25bf8e721a 100644 --- a/src/store/workstation/codeEditor/outputIntegration/gitOutputAtom.ts +++ b/src/store/workstation/codeEditor/outputIntegration/gitOutputAtom.ts @@ -6,7 +6,7 @@ */ import { atom } from "jotai"; -import type { UseGitOutputIntegrationReturn } from "@src/hooks/workStation/useGitOutputIntegration/types"; +import type { UseGitOutputIntegrationReturn } from "@src/types/workstation/gitOutputIntegration"; /** * Global git output integration reference diff --git a/src/store/workstation/codeEditor/outputIntegration/taskOutputAtom.ts b/src/store/workstation/codeEditor/outputIntegration/taskOutputAtom.ts index e5a16998cf..6a1276e2c7 100644 --- a/src/store/workstation/codeEditor/outputIntegration/taskOutputAtom.ts +++ b/src/store/workstation/codeEditor/outputIntegration/taskOutputAtom.ts @@ -6,7 +6,7 @@ */ import { atom } from "jotai"; -import type { UseTaskOutputIntegrationReturn } from "@src/hooks/workStation/output/useTaskOutputIntegration"; +import type { UseTaskOutputIntegrationReturn } from "@src/types/workstation/output"; /** * Global atom holding the task output integration instance diff --git a/src/types/git/types.ts b/src/types/git/types.ts index 3520ae04b5..6f6cb6f8a2 100644 --- a/src/types/git/types.ts +++ b/src/types/git/types.ts @@ -4,8 +4,7 @@ * This file contains types used by multiple modules: * - EditorPrimarySidebar (hooks, content) * - EditorContent (GitDiffContent, SourceControlMainContent) - * - @src/hooks/git/sourceControl/ - * - @src/hooks/workStation/ + * - @src/modules/WorkStation/CodeEditor/hooks/ (sourceControl, gitOutputIntegration) * - @src/store/git/gitStatusAtom.ts * - @src/engines/Simulator/ */ diff --git a/src/hooks/workStation/useGitOutputIntegration/types.ts b/src/types/workstation/gitOutputIntegration.ts similarity index 92% rename from src/hooks/workStation/useGitOutputIntegration/types.ts rename to src/types/workstation/gitOutputIntegration.ts index 3a868094b1..3a0e45ef5e 100644 --- a/src/hooks/workStation/useGitOutputIntegration/types.ts +++ b/src/types/workstation/gitOutputIntegration.ts @@ -1,13 +1,15 @@ /** * Git Output Integration Types * - * Types and interfaces for the git output integration hook. + * Contract for the git output-integration hook (CodeEditor/hooks/gitOutputIntegration). + * Lives in src/types so store/ atoms and other consumers can reference the + * contract without importing the hook implementation. */ import type { MutableRefObject } from "react"; import type { GitErrorType } from "@src/api/http/git/streaming"; -import type { UseOutputChannelsReturn } from "../output/useOutputChannels"; +import type { UseOutputChannelsReturn } from "./output"; // ============================================ // Result Types diff --git a/src/types/workstation/output.ts b/src/types/workstation/output.ts index dc27f3621e..a12216992b 100644 --- a/src/types/workstation/output.ts +++ b/src/types/workstation/output.ts @@ -1,9 +1,11 @@ /** * Output channel types shared across the workstation domain. * - * Canonical home for OutputChannel, OutputChannelType, OutputLine, and - * OutputPanelConfig. Lives here so src/store/, src/hooks/, and src/services/ - * do not need to import from a deep CodeEditor panel path. + * Canonical home for OutputChannel, OutputChannelType, OutputLine, + * OutputPanelConfig, and the output-integration hook contracts + * (UseOutputChannelsReturn, UseTaskOutputIntegrationReturn). Lives here so + * src/store/, src/services/, and the CodeEditor hooks that implement the + * contracts can share them without importing each other. */ export type OutputChannelType = @@ -40,3 +42,50 @@ export interface OutputPanelConfig { showTimestamps?: boolean; wordWrap?: boolean; } + +// ============================================ +// Output-integration hook contracts +// ============================================ + +/** Contract implemented by `useOutputChannels` (CodeEditor/hooks/output). */ +export interface UseOutputChannelsReturn { + /** All output channels */ + channels: OutputChannel[]; + /** Currently active channel ID */ + activeChannelId: string | null; + /** Get channel by ID */ + getChannel: (channelId: string) => OutputChannel | undefined; + /** Create a new channel */ + createChannel: ( + name: string, + type: OutputChannelType, + maxChars?: number + ) => string; + /** Delete a channel */ + deleteChannel: (channelId: string) => void; + /** Append text to a channel */ + appendToChannel: (channelId: string, text: string) => void; + /** Clear a channel */ + clearChannel: (channelId: string) => void; + /** Clear all channels */ + clearAllChannels: () => void; + /** Set active channel */ + setActiveChannel: (channelId: string) => void; + /** Set channel active status */ + setChannelActive: (channelId: string, active: boolean) => void; +} + +/** Contract implemented by `useTaskOutputIntegration` (CodeEditor/hooks/output). */ +export interface UseTaskOutputIntegrationReturn { + /** Run a task with output streaming */ + runTaskWithOutput: (params: { + taskId: string; + command: string; + shell?: string; + }) => Promise<() => void>; + /** Run an npm script with output streaming */ + runNpmScriptWithOutput: (params: { + taskId: string; + script: string; + }) => Promise<() => void>; +} diff --git a/src/hooks/workStation/__tests__/latestRequestGuard.test.ts b/src/util/core/latestRequestGuard.test.ts similarity index 96% rename from src/hooks/workStation/__tests__/latestRequestGuard.test.ts rename to src/util/core/latestRequestGuard.test.ts index fafa4dbc6b..1400bba592 100644 --- a/src/hooks/workStation/__tests__/latestRequestGuard.test.ts +++ b/src/util/core/latestRequestGuard.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import { LatestRequestGuard } from "../latestRequestGuard"; +import { LatestRequestGuard } from "./latestRequestGuard"; describe("LatestRequestGuard", () => { it("allows only the latest request to commit", () => { diff --git a/src/hooks/workStation/latestRequestGuard.ts b/src/util/core/latestRequestGuard.ts similarity index 100% rename from src/hooks/workStation/latestRequestGuard.ts rename to src/util/core/latestRequestGuard.ts diff --git a/src/util/util-organization.md b/src/util/util-organization.md index baf2a97cd9..82c94b8fbb 100644 --- a/src/util/util-organization.md +++ b/src/util/util-organization.md @@ -668,7 +668,21 @@ formatDate.ts; // Related to formatSteps? ## Related documentation -- **Hooks:** `src/hooks/hooks-organization.md` +- **Hooks:** `src/hooks/` has no organization doc. Placement rules (2026-08-15, + after `hooks/workStation` was dissolved): + 1. A hook with one consuming area lives next to that consumer — in the module's + own `hooks/` dir (`modules/WorkStation/CodeEditor/hooks/`, + `modules/WorkStation/Browser/hooks/`, `features/SessionSetup/hooks/`, …), + or beside the single file that uses it. + 2. `src/hooks//` is only for hooks consumed from several areas + (e.g. `hooks/tabHost/` — the workstation tab-host contract used by + WorkStation, ProjectManager, MainApp, features and engines). Never name a + global group after a module. + 3. No barrels: import the file, not an `index.ts` (barrels hide who really + depends on what — that is how `hooks/workStation` drifted). + 4. Shared _contracts_ a hook implements go in `src/types/`, so `store/` and + `services/` never import from `src/hooks/`. + `.eslintrc.js` `no-restricted-imports` blocks the dissolved paths. - **Store:** `src/store/store-organization.md` - **API:** `src/api/api_organization.md` @@ -701,3 +715,4 @@ formatDate.ts; // Related to formatSteps? | 2026-01-17 | — | Original V1 document | | 2026-03-12 | script | Migrated to Documentation V2 format | | 2026-03-25 | — | Moved to `src/util/util-organization.md`; related links updated | +| 2026-08-15 | — | Hooks placement rules added; `hooks/workStation` dissolved |