@agimon-ai/doompi-git 0.0.1-alpha.4 → 0.0.1-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -1
- package/dist/apiContracts.cjs +387 -0
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/apiContracts.d.mts +53 -0
- package/dist/apiContracts.d.mts.map +1 -0
- package/dist/apiContracts.mjs +382 -0
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/extensions/pi.cjs +105 -1
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.mts +6 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +100 -1
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +1828 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +1820 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +2641 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/gitDependencies-CtVubYvU.mjs +22 -0
- package/dist/gitDependencies-CtVubYvU.mjs.map +1 -0
- package/dist/gitDependencies-Dqsz2HjK.cjs +33 -0
- package/dist/gitDependencies-Dqsz2HjK.cjs.map +1 -0
- package/dist/index-D79MSCee.d.mts +145 -0
- package/dist/index-D79MSCee.d.mts.map +1 -0
- package/dist/index.cjs +4 -1
- package/dist/index.d.mts +2 -5
- package/dist/index.mjs +2 -1
- package/dist/runWorktree-BE795LxL.cjs +374 -0
- package/dist/runWorktree-BE795LxL.cjs.map +1 -0
- package/dist/runWorktree-SPzJvIBt.mjs +303 -0
- package/dist/runWorktree-SPzJvIBt.mjs.map +1 -0
- package/dist/worktreeOperations-BYmVU0UV.cjs +1350 -0
- package/dist/worktreeOperations-BYmVU0UV.cjs.map +1 -0
- package/dist/worktreeOperations-BrWG2muV.mjs +1194 -0
- package/dist/worktreeOperations-BrWG2muV.mjs.map +1 -0
- package/llms.txt +4 -0
- package/package.json +56 -41
- package/src/prompts/doompi-use-git/SKILL.md +26 -3
- package/dist/_virtual/_rolldown/runtime.cjs +0 -1
- package/dist/adapters/channel/worktreeChannel.cjs +0 -2
- package/dist/adapters/channel/worktreeChannel.cjs.map +0 -1
- package/dist/adapters/channel/worktreeChannel.d.cts +0 -40
- package/dist/adapters/channel/worktreeChannel.d.cts.map +0 -1
- package/dist/adapters/channel/worktreeChannel.d.mts +0 -40
- package/dist/adapters/channel/worktreeChannel.d.mts.map +0 -1
- package/dist/adapters/channel/worktreeChannel.mjs +0 -2
- package/dist/adapters/channel/worktreeChannel.mjs.map +0 -1
- package/dist/adapters/filesystem/atomicJson.cjs +0 -2
- package/dist/adapters/filesystem/atomicJson.cjs.map +0 -1
- package/dist/adapters/filesystem/atomicJson.mjs +0 -2
- package/dist/adapters/filesystem/atomicJson.mjs.map +0 -1
- package/dist/adapters/filesystem/paths.cjs +0 -2
- package/dist/adapters/filesystem/paths.cjs.map +0 -1
- package/dist/adapters/filesystem/paths.mjs +0 -2
- package/dist/adapters/filesystem/paths.mjs.map +0 -1
- package/dist/adapters/hub/hubClient.cjs +0 -2
- package/dist/adapters/hub/hubClient.cjs.map +0 -1
- package/dist/adapters/hub/hubClient.d.cts +0 -1
- package/dist/adapters/hub/hubClient.d.mts +0 -1
- package/dist/adapters/hub/hubClient.mjs +0 -2
- package/dist/adapters/hub/hubClient.mjs.map +0 -1
- package/dist/adapters/pi/extension.cjs +0 -2
- package/dist/adapters/pi/extension.cjs.map +0 -1
- package/dist/adapters/pi/extension.d.cts +0 -9
- package/dist/adapters/pi/extension.d.cts.map +0 -1
- package/dist/adapters/pi/extension.d.mts +0 -9
- package/dist/adapters/pi/extension.d.mts.map +0 -1
- package/dist/adapters/pi/extension.mjs +0 -2
- package/dist/adapters/pi/extension.mjs.map +0 -1
- package/dist/adapters/pi/extensions/runWorktreeTool.cjs +0 -15
- package/dist/adapters/pi/extensions/runWorktreeTool.cjs.map +0 -1
- package/dist/adapters/pi/extensions/runWorktreeTool.mjs +0 -15
- package/dist/adapters/pi/extensions/runWorktreeTool.mjs.map +0 -1
- package/dist/adapters/web/worktreesChannel.cjs +0 -2
- package/dist/adapters/web/worktreesChannel.cjs.map +0 -1
- package/dist/adapters/web/worktreesChannel.d.cts +0 -21
- package/dist/adapters/web/worktreesChannel.d.cts.map +0 -1
- package/dist/adapters/web/worktreesChannel.d.mts +0 -21
- package/dist/adapters/web/worktreesChannel.d.mts.map +0 -1
- package/dist/adapters/web/worktreesChannel.mjs +0 -2
- package/dist/adapters/web/worktreesChannel.mjs.map +0 -1
- package/dist/adapters/worktree/dependencyInstall.cjs +0 -2
- package/dist/adapters/worktree/dependencyInstall.cjs.map +0 -1
- package/dist/adapters/worktree/dependencyInstall.mjs +0 -2
- package/dist/adapters/worktree/dependencyInstall.mjs.map +0 -1
- package/dist/adapters/worktree/gitCli.cjs +0 -4
- package/dist/adapters/worktree/gitCli.cjs.map +0 -1
- package/dist/adapters/worktree/gitCli.mjs +0 -4
- package/dist/adapters/worktree/gitCli.mjs.map +0 -1
- package/dist/adapters/worktree/repositoryIdentity.cjs +0 -2
- package/dist/adapters/worktree/repositoryIdentity.cjs.map +0 -1
- package/dist/adapters/worktree/repositoryIdentity.mjs +0 -2
- package/dist/adapters/worktree/repositoryIdentity.mjs.map +0 -1
- package/dist/adapters/worktree/worktreeOperations.cjs +0 -2
- package/dist/adapters/worktree/worktreeOperations.cjs.map +0 -1
- package/dist/adapters/worktree/worktreeOperations.d.cts +0 -32
- package/dist/adapters/worktree/worktreeOperations.d.cts.map +0 -1
- package/dist/adapters/worktree/worktreeOperations.d.mts +0 -32
- package/dist/adapters/worktree/worktreeOperations.d.mts.map +0 -1
- package/dist/adapters/worktree/worktreeOperations.mjs +0 -2
- package/dist/adapters/worktree/worktreeOperations.mjs.map +0 -1
- package/dist/adapters/worktree/worktreeRegistry.cjs +0 -2
- package/dist/adapters/worktree/worktreeRegistry.cjs.map +0 -1
- package/dist/adapters/worktree/worktreeRegistry.mjs +0 -2
- package/dist/adapters/worktree/worktreeRegistry.mjs.map +0 -1
- package/dist/commands/doomGitCommand.cjs +0 -2
- package/dist/commands/doomGitCommand.cjs.map +0 -1
- package/dist/commands/doomGitCommand.mjs +0 -2
- package/dist/commands/doomGitCommand.mjs.map +0 -1
- package/dist/container/index.cjs +0 -2
- package/dist/container/index.cjs.map +0 -1
- package/dist/container/index.d.cts +0 -6
- package/dist/container/index.d.cts.map +0 -1
- package/dist/container/index.d.mts +0 -6
- package/dist/container/index.d.mts.map +0 -1
- package/dist/container/index.mjs +0 -2
- package/dist/container/index.mjs.map +0 -1
- package/dist/extensions/pi.d.cts +0 -2
- package/dist/hubApi.cjs +0 -2
- package/dist/hubApi.cjs.map +0 -1
- package/dist/hubApi.d.cts +0 -6
- package/dist/hubApi.d.cts.map +0 -1
- package/dist/hubApi.d.mts +0 -6
- package/dist/hubApi.d.mts.map +0 -1
- package/dist/hubApi.mjs +0 -2
- package/dist/hubApi.mjs.map +0 -1
- package/dist/index.d.cts +0 -5
- package/dist/schemas/runWorktreeTool.cjs +0 -2
- package/dist/schemas/runWorktreeTool.cjs.map +0 -1
- package/dist/schemas/runWorktreeTool.mjs +0 -2
- package/dist/schemas/runWorktreeTool.mjs.map +0 -1
- package/dist/services/extensionService.cjs +0 -2
- package/dist/services/extensionService.cjs.map +0 -1
- package/dist/services/extensionService.d.cts +0 -8
- package/dist/services/extensionService.d.cts.map +0 -1
- package/dist/services/extensionService.d.mts +0 -8
- package/dist/services/extensionService.d.mts.map +0 -1
- package/dist/services/extensionService.mjs +0 -2
- package/dist/services/extensionService.mjs.map +0 -1
- package/dist/services/support/errors.cjs +0 -2
- package/dist/services/support/errors.cjs.map +0 -1
- package/dist/services/support/errors.mjs +0 -2
- package/dist/services/support/errors.mjs.map +0 -1
- package/dist/services/worktreeNaming.cjs +0 -2
- package/dist/services/worktreeNaming.cjs.map +0 -1
- package/dist/services/worktreeNaming.d.cts +0 -27
- package/dist/services/worktreeNaming.d.cts.map +0 -1
- package/dist/services/worktreeNaming.d.mts +0 -27
- package/dist/services/worktreeNaming.d.mts.map +0 -1
- package/dist/services/worktreeNaming.mjs +0 -2
- package/dist/services/worktreeNaming.mjs.map +0 -1
- package/dist/types/extension.d.cts +0 -17
- package/dist/types/extension.d.cts.map +0 -1
- package/dist/types/extension.d.mts +0 -17
- package/dist/types/extension.d.mts.map +0 -1
- package/dist/types/webWorktrees.cjs +0 -2
- package/dist/types/webWorktrees.cjs.map +0 -1
- package/dist/types/webWorktrees.mjs +0 -2
- package/dist/types/webWorktrees.mjs.map +0 -1
- package/dist/types/worktreeRegistry.d.cts +0 -41
- package/dist/types/worktreeRegistry.d.cts.map +0 -1
- package/dist/types/worktreeRegistry.d.mts +0 -41
- package/dist/types/worktreeRegistry.d.mts.map +0 -1
- package/dist/webHub.cjs +0 -1
- package/dist/webHub.d.cts +0 -2
- package/dist/webHub.d.mts +0 -2
- package/dist/webHub.mjs +0 -1
- package/src/exports/webClient.ts +0 -1
- package/src/types/webWorktrees.ts +0 -55
- package/src/types/worktreeRegistry.ts +0 -69
- package/src/web/components/RunWorktreeToolMessage.tsx +0 -37
- package/src/web/components/WorktreesActivitySection.tsx +0 -64
- package/src/web/components/WorktreesPanel.tsx +0 -125
- package/src/web/components/toolRenderers.ts +0 -7
- package/src/web/index.ts +0 -30
- package/src/web/stores/worktreesActivityStore.ts +0 -124
- package/src/web/tsconfig.json +0 -22
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.mjs","names":["routes","formProblem","errorOf","formProblem","isRecord","optionalText","optionalErrorTarget","isRecord","contribution","fillGitNewSession","repositorySettingsPanelGit","activityGroupGit","channelGitChanges","channelGitWorktrees","fillWorktree","fillWorktreeCreate","fillWorktrees","leaderReview","lifecycleStart","toolRunWorktree"],"sources":["../../src/types/apiRoutes.ts","../../generated/client.ts","../../src/extensions/workspaces/(frontend)/_lib/newSessionForm.ts","../../src/extensions/workspaces/(frontend)/fill/_components/GitNewSessionDialog.tsx","../../src/extensions/workspaces/(frontend)/fill/GitNewSession.new-session.web.tsx","../../src/extensions/workspaces/(frontend)/repository-settings-panel/_lib/gitAuthForm.ts","../../src/extensions/workspaces/(frontend)/repository-settings-panel/_components/GitAuthForm.tsx","../../src/extensions/workspaces/(frontend)/repository-settings-panel/_components/GitAuthPanel.tsx","../../src/extensions/workspaces/(frontend)/repository-settings-panel/git.web.tsx","../../src/types/webWorktrees.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/worktreesActivityStore.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/WorktreesPanel.tsx","../../src/types/gitReview.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/gitChangesStore.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/git.web.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/gitChanges.web.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/gitWorktrees.web.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/WorktreeCreateDialog.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Worktree.session-menu.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/WorktreeCreate.overlay.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/_lib/gitReviewApi.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/gitReviewStore.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/gitReviewView.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/gitReviewTree.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/GitReviewBrowser.tsx","../../src/extensions/workspaces/sessions/(frontend)/_components/GitSyncBar.tsx","../../src/extensions/workspaces/sessions/(frontend)/_components/GitReviewView.tsx","../../src/extensions/workspaces/sessions/(frontend)/_components/GitReviewPanel.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/DiffActivitySection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/WorktreesActivitySection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Worktrees.activity.git.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/leader/review.web.ts","../../src/extensions/workspaces/sessions/(frontend)/lifecycle/_lib/start.web.ts","../../src/extensions/workspaces/sessions/(frontend)/lifecycle/start.web.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/RunWorktreeToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/runWorktree.web.tsx","../../generated/web.ts"],"sourcesContent":["import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-core/web';\n\nimport type { GitAuthView } from './gitAuth';\nimport type { GitReviewFileDiff, GitReviewSummary } from './gitReview';\nimport type { GitBranchesResponse, GitSessionCreated } from './gitSessions';\n\n/**\n * The routes the page calls, as data.\n *\n * No scope and no base path: the build reads both off\n * `src/extensions/(backend)/api/git/`, which mounts at global scope and so\n * answers workspace and session requests too. Each route answers only where it\n * belongs (auth on a workspace mount, the review on a session mount), so a\n * client accessor on the wrong scope gets a 404 rather than a second way in.\n *\n * Only what the browser calls is listed. The worktree routes stay HTTP for\n * other callers, but the dock drives worktrees over its channel.\n */\nexport default defineApiRoutes({\n /** Workspace: the new-session dialog's branch list. */\n branches: {\n method: 'GET',\n path: '/branches',\n response: apiResponse<GitBranchesResponse>(),\n },\n /** Workspace: a top-level worktree session on an existing or new branch. */\n createSession: {\n method: 'POST',\n path: '/sessions',\n response: apiResponse<GitSessionCreated>(),\n },\n /** Workspace: that workspace's saved remote auth, never the token itself. */\n auth: {\n method: 'GET',\n path: '/auth',\n query: ['repositoryId'],\n response: apiResponse<GitAuthView>(),\n },\n /** Workspace: replaces that workspace's remote auth. Passkey step-up gated for remote devices. */\n saveAuth: {\n method: 'PUT',\n path: '/auth',\n query: ['repositoryId'],\n response: apiResponse<GitAuthView>(),\n },\n /** Session: the files this session's checkout changed against its base. */\n review: {\n method: 'GET',\n path: '/review',\n response: apiResponse<GitReviewSummary>(),\n },\n /** Session: one changed file's hunks. */\n reviewFile: {\n method: 'GET',\n path: '/review/file',\n query: ['path'],\n response: apiResponse<GitReviewFileDiff>(),\n },\n});\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { createApiClient, sessionApiAddress } from '@agimon-ai/doompi-core/web';\nimport { sealedTransport } from '@agimon-ai/doompi-web-security/browser';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'git' at. */\nexport const apiScopes = ['global', 'workspace', 'session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'git',\n transport: (input, init) => sealedTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n","import type { GitBranches, GitSessionCreateRequest } from '../../../../types/gitSessions';\n\nexport type NewSessionMode = 'existing' | 'new' | 'plain';\n\n/** One row of the branch picker: a local branch, or a remote-only one. */\nexport interface BranchOption {\n key: string;\n name: string;\n remote?: string;\n current: boolean;\n /** Set when the branch is checked out elsewhere and cannot get a second worktree. */\n busyAt?: string;\n}\n\nexport interface NewSessionFormState {\n mode: NewSessionMode;\n /** The picked existing branch. */\n selected?: BranchOption;\n newBranch: string;\n baseRef: string;\n name: string;\n}\n\nconst MAX_LISTED = 200;\n\n/** Local branches first, then remote-only ones, filtered by a case-insensitive substring. */\nexport function branchOptions(branches: GitBranches, query: string): BranchOption[] {\n const needle = query.trim().toLowerCase();\n const matches = (text: string): boolean => needle === '' || text.toLowerCase().includes(needle);\n const local = branches.local\n .filter((branch) => matches(branch.name))\n .map((branch) => ({\n key: `local:${branch.name}`,\n name: branch.name,\n current: branch.name === branches.current,\n ...(branch.checkedOutAt === undefined ? {} : { busyAt: branch.checkedOutAt }),\n }));\n const remote = branches.remote\n .filter((branch) => matches(`${branch.remote}/${branch.name}`))\n .map((branch) => ({\n key: `remote:${branch.remote}/${branch.name}`,\n name: branch.name,\n remote: branch.remote,\n current: false,\n }));\n return [...local, ...remote].slice(0, MAX_LISTED);\n}\n\n/** Every base a new branch can start from: the default first, then remote-tracking names, then local branches. */\nexport function baseOptions(branches: GitBranches): string[] {\n const names = new Set([\n ...(branches.defaultBase === undefined ? [] : [branches.defaultBase]),\n ...branches.remote.map((branch) => `${branch.remote}/${branch.name}`),\n ...branches.local.map((branch) => branch.name),\n ]);\n return [...names];\n}\n\n/** Why the form cannot be submitted yet, or undefined when it can. */\nexport function formProblem(state: NewSessionFormState): string | undefined {\n if (state.mode === 'existing') {\n if (state.selected === undefined) return 'Pick a branch.';\n if (state.selected.busyAt !== undefined) return `That branch is checked out at ${state.selected.busyAt}.`;\n }\n if (state.mode === 'new' && state.newBranch.trim() === '') return 'Name the new branch.';\n return undefined;\n}\n\n/** The worktree create request for the form, or undefined in plain mode. */\nexport function createRequest(state: NewSessionFormState): GitSessionCreateRequest | undefined {\n const name = state.name.trim();\n const named = name === '' ? {} : { name };\n if (state.mode === 'existing' && state.selected !== undefined)\n return {\n mode: 'existing-branch',\n branch: state.selected.name,\n ...(state.selected.remote === undefined ? {} : { remote: state.selected.remote }),\n ...named,\n };\n if (state.mode === 'new') {\n const baseRef = state.baseRef.trim();\n return {\n mode: 'new-branch',\n branch: state.newBranch.trim(),\n ...(baseRef === '' ? {} : { baseRef }),\n ...named,\n };\n }\n return undefined;\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n OptionRow,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@agimon-ai/doompi-web-components';\nimport { useEffect, useState } from 'react';\n\nimport { api } from '../../../../../../generated/client';\nimport type { GitBranchesResponse, GitSessionCreated } from '../../../../../types/gitSessions';\nimport {\n baseOptions,\n branchOptions,\n createRequest,\n formProblem,\n type NewSessionFormState,\n type NewSessionMode,\n} from '../../_lib/newSessionForm';\n\nconst MODES: readonly { mode: NewSessionMode; label: string }[] = [\n { mode: 'existing', label: 'existing branch' },\n { mode: 'new', label: 'new branch' },\n { mode: 'plain', label: 'no branch' },\n];\n\nfunction errorOf(body: unknown, status: number): string {\n return typeof body === 'object' && body !== null && typeof (body as { error?: unknown }).error === 'string'\n ? (body as { error: string }).error\n : `The cockpit answered ${String(status)}.`;\n}\n\n/**\n * The new-session dialog when git is installed: a worktree on an existing or a\n * new branch, or a plain session in the workspace root. A worktree session\n * starts at the top level of the rail, with no parent.\n */\nexport function GitNewSessionDialog({ newSession }: WebPluginSlotProps) {\n const [branches, setBranches] = useState<GitBranchesResponse | null>(null);\n const [loadError, setLoadError] = useState('');\n const [form, setForm] = useState<NewSessionFormState>({ mode: 'existing', newBranch: '', baseRef: '', name: '' });\n const [query, setQuery] = useState('');\n const [error, setError] = useState('');\n const [busy, setBusy] = useState(false);\n const workspaceId = newSession?.workspaceId;\n const request = newSession?.requestWithStepUp;\n\n useEffect(() => {\n if (workspaceId === undefined || request === undefined) return;\n let stale = false;\n const url = api.workspace(workspaceId).branches.url();\n void request(url)\n .then(async (response) => {\n const body: unknown = await response.json().catch(() => undefined);\n if (stale) return;\n if (!response.ok) {\n setLoadError(errorOf(body, response.status));\n return;\n }\n const loaded = body as GitBranchesResponse;\n setBranches(loaded);\n setForm((current) => ({ ...current, baseRef: loaded.defaultBase ?? '' }));\n })\n .catch(() => {\n if (!stale) setLoadError('The branches could not be loaded.');\n });\n return () => {\n stale = true;\n };\n }, [workspaceId, request]);\n\n if (newSession === undefined) return null;\n\n const gitReady = branches?.repository === true && loadError === '';\n const mode: NewSessionMode = gitReady || branches === null ? form.mode : 'plain';\n const state = { ...form, mode };\n const problem = formProblem(state);\n const options = branches === null ? [] : branchOptions(branches, query);\n const bases = branches === null ? [] : baseOptions(branches);\n const update = (patch: Partial<NewSessionFormState>): void => setForm((current) => ({ ...current, ...patch }));\n\n const submit = async (): Promise<void> => {\n if (busy || problem !== undefined) return;\n setBusy(true);\n setError('');\n const body = createRequest(state);\n let failure: string | undefined;\n if (body === undefined) {\n failure = await newSession.createPlain(state.name);\n } else {\n try {\n const response = await newSession.requestWithStepUp(api.workspace(newSession.workspaceId).createSession.url(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n const answer: unknown = await response.json().catch(() => undefined);\n failure = response.ok\n ? await newSession.openCreated((answer as GitSessionCreated).sessionId)\n : errorOf(answer, response.status);\n } catch {\n failure = 'The cockpit is unreachable.';\n }\n }\n if (failure === undefined) return;\n setError(failure);\n setBusy(false);\n };\n\n return (\n <Dialog open onOpenChange={(next) => !next && !busy && newSession.close()}>\n <DialogContent width=\"md\" data-testid=\"new-session-dialog\" aria-describedby={undefined}>\n <DialogHeader>\n <DialogTitle>new session</DialogTitle>\n </DialogHeader>\n <DialogBody>\n <p className=\"truncate text-xs text-doom-faint\" title={newSession.workspaceRoot}>\n {newSession.workspaceRoot}\n </p>\n {gitReady ? (\n <div role=\"radiogroup\" aria-label=\"session kind\" className=\"flex gap-1\">\n {MODES.map((entry) => (\n <Button\n key={entry.mode}\n role=\"radio\"\n aria-checked={mode === entry.mode}\n variant={mode === entry.mode ? 'outline' : 'ghost'}\n size=\"sm\"\n data-testid={`git-new-session-mode-${entry.mode}`}\n disabled={busy}\n className={mode === entry.mode ? 'border-doom-blue/60 text-doom-hi' : undefined}\n onClick={() => update({ mode: entry.mode })}\n >\n {entry.label}\n </Button>\n ))}\n </div>\n ) : branches === null && loadError === '' ? (\n <p className=\"text-xs text-doom-faint\">reading branches…</p>\n ) : (\n <p data-testid=\"git-new-session-plain-note\" className=\"text-xs text-doom-faint\">\n {loadError || 'This workspace is not a git checkout, so the session starts in its folder.'}\n </p>\n )}\n\n {mode === 'existing' && gitReady ? (\n <div className=\"flex flex-col gap-1\">\n <Input\n data-testid=\"git-new-session-branch-search\"\n aria-label=\"find a branch\"\n value={query}\n autoFocus\n disabled={busy}\n onChange={(event) => setQuery(event.target.value)}\n placeholder=\"find a branch\"\n />\n <div\n role=\"listbox\"\n aria-label=\"branches\"\n className=\"max-h-48 overflow-y-auto rounded border border-doom-border bg-doom-deep p-1\"\n >\n {options.length === 0 ? (\n <p className=\"px-2 py-1 text-2xs text-doom-faint\">no matching branches</p>\n ) : null}\n {options.map((option) => (\n <OptionRow\n key={option.key}\n density=\"compact\"\n active={form.selected?.key === option.key}\n disabled={option.busyAt !== undefined || busy}\n data-testid=\"git-new-session-branch-option\"\n data-branch={option.name}\n data-remote={option.remote}\n onClick={() => update({ selected: option })}\n className={`w-full px-2.5 py-1 text-sm ${option.busyAt !== undefined ? 'opacity-50' : ''}`}\n >\n <span className=\"min-w-0 flex-1 truncate\">\n {option.remote === undefined ? option.name : `${option.remote}/${option.name}`}\n </span>\n <span className=\"shrink-0 text-2xs text-doom-faint\">\n {option.current && option.busyAt !== undefined\n ? 'current · checked out'\n : option.current\n ? 'current'\n : option.busyAt !== undefined\n ? 'checked out'\n : option.remote !== undefined\n ? 'remote'\n : ''}\n </span>\n </OptionRow>\n ))}\n </div>\n </div>\n ) : null}\n\n {mode === 'new' && gitReady ? (\n <div className=\"flex flex-col gap-2\">\n <label htmlFor=\"git-new-session-new-branch\" className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-doom-faint\">new branch</span>\n <Input\n id=\"git-new-session-new-branch\"\n data-testid=\"git-new-session-new-branch\"\n value={form.newBranch}\n autoFocus\n disabled={busy}\n onChange={(event) => update({ newBranch: event.target.value })}\n placeholder=\"feature/my-change\"\n />\n </label>\n <span className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-doom-faint\">from</span>\n <Select value={form.baseRef} onValueChange={(baseRef) => update({ baseRef })} disabled={busy}>\n <SelectTrigger data-testid=\"git-new-session-base\" aria-label=\"base branch\">\n <SelectValue placeholder=\"base branch\" />\n </SelectTrigger>\n <SelectContent>\n {bases.map((base) => (\n <SelectItem key={base} value={base}>\n {base === branches?.current ? `${base} (current)` : base}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </span>\n </div>\n ) : null}\n\n <label htmlFor=\"new-session-name\" className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-doom-faint\">\n name{' '}\n <span className=\"text-doom-faint\">(optional{mode === 'plain' ? '' : '; defaults to the branch'})</span>\n </span>\n <Input\n id=\"new-session-name\"\n data-testid=\"new-session-name\"\n value={form.name}\n autoFocus={mode === 'plain'}\n disabled={busy}\n onChange={(event) => update({ name: event.target.value })}\n onKeyDown={(event) => {\n if (event.key === 'Enter') void submit();\n }}\n placeholder=\"session name\"\n />\n </label>\n {error ? (\n <pre\n data-testid=\"new-session-error\"\n className=\"max-h-28 overflow-y-auto rounded border border-doom-edge-red bg-doom-tint-red/40 px-2.5 py-2 text-xs whitespace-pre-wrap text-doom-red\"\n >\n {error}\n </pre>\n ) : null}\n <DialogFooter>\n <Button\n variant=\"outline\"\n data-testid=\"new-session-cancel\"\n disabled={busy}\n onClick={() => newSession.close()}\n >\n cancel\n </Button>\n <Button\n variant=\"primary\"\n data-testid=\"new-session-create\"\n title={problem}\n disabled={busy || problem !== undefined}\n onClick={() => void submit()}\n >\n {busy ? (mode === 'plain' ? 'creating…' : 'creating worktree…') : 'create'}\n </Button>\n </DialogFooter>\n </DialogBody>\n </DialogContent>\n </Dialog>\n );\n}\n","import { defineFill } from '@agimon-ai/doompi-core/web';\n\nimport { GitNewSessionDialog } from './_components/GitNewSessionDialog';\n\nexport default defineFill({ component: GitNewSessionDialog });\n","import type { GitAuthMethod, GitAuthSaveRequest, GitAuthView } from '../../../../../types/gitAuth';\n\n/**\n * Pure form logic for a workspace's git auth panel: what the fields start as,\n * what is wrong with them, and what a save sends.\n *\n * The server validates again; this only keeps the page from sending what it\n * already knows will be refused, and says why in words next to the field.\n */\n\nexport const DEFAULT_HTTPS_HOST = 'github.com';\n\nexport interface GitAuthFormState {\n method: GitAuthMethod;\n keyPath: string;\n host: string;\n username: string;\n /** Never prefilled. Empty keeps the saved token when there is one for this host. */\n token: string;\n}\n\nexport function formFromView(view: GitAuthView): GitAuthFormState {\n return {\n method: view.method,\n keyPath: view.ssh?.keyPath ?? '',\n host: view.https?.host ?? DEFAULT_HTTPS_HOST,\n username: view.https?.username ?? '',\n token: '',\n };\n}\n\nconst HOST_PATTERN = /^[a-z0-9.-]{1,253}(:\\d{1,5})?$/u;\n/** Whether a value holds an ASCII control character; a newline in a credential field could add a line to git's credential protocol. */\nfunction hasControl(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code < 0x20 || code === 0x7f) return true;\n }\n return false;\n}\n\n/** Whether the saved token can stay: only when one exists and the host has not moved. */\nfunction keepsToken(form: GitAuthFormState, saved: GitAuthView): boolean {\n return saved.https?.hasToken === true && saved.https.host === form.host.trim().toLowerCase();\n}\n\n/** The first thing wrong with the form, in words, or undefined when it can be saved. */\nexport function formProblem(form: GitAuthFormState, saved: GitAuthView): string | undefined {\n if (form.method === 'ssh') {\n const keyPath = form.keyPath.trim();\n if (keyPath === '') return undefined;\n if (hasControl(keyPath)) return 'The key path has a control character in it.';\n if (!keyPath.startsWith('/') && !keyPath.startsWith('~/'))\n return 'Give the key as an absolute path or one under ~/.';\n return undefined;\n }\n if (form.method === 'https') {\n const host = form.host.trim().toLowerCase();\n if (!HOST_PATTERN.test(host)) return 'The host should look like github.com, with an optional :port.';\n if (form.username.trim() === '') return 'A username is required.';\n if (hasControl(form.username) || hasControl(form.token))\n return 'Remove the control character from the username or token.';\n if (form.token === '' && !keepsToken(form, saved)) {\n return saved.https?.hasToken === true\n ? 'The host changed, so enter the token for the new host.'\n : 'A token is required.';\n }\n }\n return undefined;\n}\n\n/** What a save sends. The token goes only when the reader typed one. */\nexport function saveRequestOf(form: GitAuthFormState): GitAuthSaveRequest {\n if (form.method === 'ssh') {\n const keyPath = form.keyPath.trim();\n return keyPath === '' ? { method: 'ssh' } : { method: 'ssh', keyPath };\n }\n if (form.method === 'https') {\n return {\n method: 'https',\n host: form.host.trim().toLowerCase(),\n username: form.username.trim(),\n ...(form.token === '' ? {} : { token: form.token }),\n };\n }\n return { method: 'none' };\n}\n","/**\n * A workspace's git remote panel body: how doompi-git reaches the remote when\n * you pull, push or rebase from this workspace's sessions in the cockpit.\n *\n * DESIGN PATTERNS:\n * - Per workspace. Worktree sessions use the setup of the workspace they\n * belong to. A workspace with nothing set uses this machine's own git.\n * - Three choices as cards, the way the theme picker offers them: this\n * machine's own git, an SSH key, or an HTTPS token.\n * - The token is write-only. The field is never prefilled; a saved token shows\n * as a badge, and leaving the field empty keeps it.\n * - Form state is the reader's until they save. The owner remounts the form\n * after a save so it starts again from what the server now holds.\n *\n * AVOID:\n * - Echoing a token back. The view the server sends has none to echo.\n */\nimport {\n AlertIcon,\n Button,\n Input,\n Label,\n RadioGroup,\n RadioGroupCard,\n ShieldIcon,\n StatusBadge,\n} from '@agimon-ai/doompi-web-components';\nimport { useState } from 'react';\n\nimport type { GitAuthMethod, GitAuthSaveRequest, GitAuthView } from '../../../../../types/gitAuth';\nimport { formFromView, formProblem, saveRequestOf, type GitAuthFormState } from '../_lib/gitAuthForm';\n\nexport interface GitAuthFormProps {\n saved: GitAuthView;\n saving: boolean;\n /** Why the last save was refused. */\n saveError?: string;\n /** The last save went through. */\n savedNotice?: boolean;\n onSave: (request: GitAuthSaveRequest) => void;\n}\n\nconst METHODS: readonly { method: GitAuthMethod; title: string; detail: string }[] = [\n {\n method: 'none',\n title: \"this machine's git\",\n detail: 'use whatever git on this machine already does: your credential helper, ssh config and agent',\n },\n { method: 'ssh', title: 'SSH key', detail: 'a key file on this machine, or your ssh-agent' },\n { method: 'https', title: 'HTTPS token', detail: 'a username and personal access token for one host' },\n];\n\nexport function GitAuthForm({ saved, saving, saveError, savedNotice = false, onSave }: GitAuthFormProps) {\n const [form, setForm] = useState<GitAuthFormState>(() => formFromView(saved));\n const update = (patch: Partial<GitAuthFormState>): void => setForm((current) => ({ ...current, ...patch }));\n const problem = formProblem(form, saved);\n const tokenSaved = saved.https?.hasToken === true && saved.https.host === form.host.trim().toLowerCase();\n\n return (\n <div data-testid=\"git-auth-form\" className=\"flex w-full min-w-0 flex-col gap-4\">\n <RadioGroup\n aria-label=\"how git reaches your remote\"\n value={form.method}\n onValueChange={(value) => update({ method: value as GitAuthMethod })}\n className=\"grid grid-cols-1 gap-2 sm:grid-cols-3\"\n >\n {METHODS.map((choice) => (\n <RadioGroupCard\n key={choice.method}\n value={choice.method}\n data-testid={`git-auth-method-${choice.method}`}\n className=\"p-3\"\n >\n <span className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-bold text-doom-hi\">{choice.title}</span>\n <span className=\"text-2xs text-doom-dim\">{choice.detail}</span>\n </span>\n </RadioGroupCard>\n ))}\n </RadioGroup>\n\n {form.method === 'ssh' ? (\n <div className=\"flex flex-col gap-1.5 rounded-lg border border-doom-border bg-doom-panel p-3\">\n <Label htmlFor=\"git-auth-key-path\" className=\"text-xs text-doom-hi\">\n key path\n </Label>\n <Input\n id=\"git-auth-key-path\"\n data-testid=\"git-auth-key-path\"\n size=\"sm\"\n value={form.keyPath}\n placeholder=\"~/.ssh/id_ed25519\"\n spellCheck={false}\n onChange={(event) => update({ keyPath: event.target.value })}\n />\n <p className=\"text-2xs text-doom-faint\">\n Leave it blank to use your ssh config and ssh-agent. A key with a passphrase works only through ssh-agent.\n An unknown host is refused: run <code className=\"text-doom-dim\">ssh -T git@github.com</code> once in a\n terminal to trust it.\n </p>\n </div>\n ) : null}\n\n {form.method === 'https' ? (\n <div className=\"grid grid-cols-1 gap-3 rounded-lg border border-doom-border bg-doom-panel p-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"git-auth-host\" className=\"text-xs text-doom-hi\">\n host\n </Label>\n <Input\n id=\"git-auth-host\"\n data-testid=\"git-auth-host\"\n size=\"sm\"\n value={form.host}\n spellCheck={false}\n onChange={(event) => update({ host: event.target.value })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"git-auth-username\" className=\"text-xs text-doom-hi\">\n username\n </Label>\n <Input\n id=\"git-auth-username\"\n data-testid=\"git-auth-username\"\n size=\"sm\"\n value={form.username}\n autoComplete=\"username\"\n spellCheck={false}\n onChange={(event) => update({ username: event.target.value })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5 sm:col-span-2\">\n <span className=\"flex items-center gap-2\">\n <Label htmlFor=\"git-auth-token\" className=\"text-xs text-doom-hi\">\n token\n </Label>\n {tokenSaved ? (\n <StatusBadge tone=\"ok\" size=\"xs\" data-testid=\"git-auth-token-saved\">\n token saved\n </StatusBadge>\n ) : null}\n </span>\n <Input\n id=\"git-auth-token\"\n data-testid=\"git-auth-token\"\n size=\"sm\"\n type=\"password\"\n value={form.token}\n autoComplete=\"new-password\"\n placeholder={tokenSaved ? 'leave blank to keep the saved token' : 'personal access token'}\n onChange={(event) => update({ token: event.target.value })}\n />\n <p className=\"text-2xs text-doom-faint\">\n Sent only to {form.host.trim() === '' ? 'this host' : form.host.trim()}. A remote on any other host keeps\n using this machine's own git credentials.\n </p>\n </div>\n </div>\n ) : null}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"primary\"\n size=\"sm\"\n data-testid=\"git-auth-save\"\n disabled={problem !== undefined || saving}\n loading={saving}\n loadingLabel=\"saving\"\n onClick={() => onSave(saveRequestOf(form))}\n >\n save\n </Button>\n {problem !== undefined ? (\n <span data-testid=\"git-auth-problem\" className=\"text-2xs text-doom-yellow\">\n {problem}\n </span>\n ) : saveError !== undefined ? (\n <span role=\"alert\" data-testid=\"git-auth-error\" className=\"flex items-center gap-1 text-2xs text-doom-red\">\n <AlertIcon aria-hidden className=\"h-3 w-3\" />\n {saveError}\n </span>\n ) : savedNotice ? (\n <span data-testid=\"git-auth-saved\" className=\"text-2xs text-doom-green\">\n saved\n </span>\n ) : null}\n </div>\n\n <p className=\"flex items-start gap-1.5 text-2xs text-doom-faint\">\n <ShieldIcon aria-hidden className=\"mt-px h-3 w-3 shrink-0\" />\n <span>\n Used only when you pull, push or rebase from this workspace's sessions in the cockpit, worktrees included. The\n agent's own git commands never see these credentials. Stored outside the repository in\n ~/.pi/.doom/git/credentials.json, readable only by you, and never in the system keychain.\n </span>\n </p>\n </div>\n );\n}\n","import type { RepositorySettingsPanelProps } from '@agimon-ai/doompi-core/web';\n/**\n * A workspace's git remote panel: loads that workspace's saved auth and saves a\n * new one. Lives under settings, in the repository section the host scopes.\n *\n * DESIGN PATTERNS:\n * - Per workspace. The host hands the selected repository; its opaque id is\n * the only thing sent, and the hub resolves it to an admitted root. A\n * browser never names a path.\n * - Reads through the host's sealed request and writes through its step-up\n * request, so a remote device proves itself with a passkey before it can\n * change credentials. The URLs come from the generated client.\n * - After a save the form remounts from what the server returned, which is how\n * the token field empties and the \"token saved\" badge appears.\n */\nimport { EmptyState, Spinner } from '@agimon-ai/doompi-web-components';\nimport { useEffect, useState } from 'react';\n\nimport { api } from '../../../../../../generated/client';\nimport type { GitAuthSaveRequest, GitAuthView } from '../../../../../types/gitAuth';\nimport { GitAuthForm } from './GitAuthForm';\n\nfunction isAuthView(value: unknown): value is GitAuthView {\n return (\n typeof value === 'object' &&\n value !== null &&\n ['none', 'ssh', 'https'].includes(String((value as { method?: unknown }).method))\n );\n}\n\nfunction errorOf(body: unknown, status: number): string {\n return typeof body === 'object' && body !== null && typeof (body as { error?: unknown }).error === 'string'\n ? (body as { error: string }).error\n : `The cockpit answered ${String(status)}.`;\n}\n\nexport function GitAuthPanel({ repository, request, requestWithStepUp }: RepositorySettingsPanelProps) {\n const repositoryId = repository?.id;\n const [loaded, setLoaded] = useState<{ repositoryId: string; saved: GitAuthView }>();\n const [loadError, setLoadError] = useState<{ repositoryId: string; error: string }>();\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string>();\n const [savedNotice, setSavedNotice] = useState(false);\n const [generation, setGeneration] = useState(0);\n\n useEffect(() => {\n if (repositoryId === undefined) return;\n let stale = false;\n request(api.workspace(repositoryId).auth.url({ query: { repositoryId } }))\n .then(async (response) => {\n const body: unknown = await response.json().catch(() => undefined);\n if (stale) return;\n if (response.ok && isAuthView(body)) setLoaded({ repositoryId, saved: body });\n else setLoadError({ repositoryId, error: errorOf(body, response.status) });\n })\n .catch(() => {\n if (!stale) setLoadError({ repositoryId, error: 'The cockpit is unreachable.' });\n });\n return () => {\n stale = true;\n };\n }, [repositoryId, request]);\n\n if (repository === null || repositoryId === undefined) {\n return (\n <EmptyState\n data-testid=\"git-auth-no-repository\"\n className=\"py-6\"\n title=\"pick a repository\"\n description=\"git remote auth is set per workspace; choose one above.\"\n />\n );\n }\n\n const save = async (next: GitAuthSaveRequest): Promise<void> => {\n setSaving(true);\n setSaveError(undefined);\n setSavedNotice(false);\n try {\n const response = await requestWithStepUp(api.workspace(repositoryId).saveAuth.url({ query: { repositoryId } }), {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(next),\n });\n const body: unknown = await response.json().catch(() => undefined);\n if (response.ok && isAuthView(body)) {\n setLoaded({ repositoryId, saved: body });\n setGeneration((current) => current + 1);\n setSavedNotice(true);\n } else {\n setSaveError(errorOf(body, response.status));\n }\n } catch {\n setSaveError('The cockpit is unreachable.');\n } finally {\n setSaving(false);\n }\n };\n\n if (loadError?.repositoryId === repositoryId) {\n return (\n <p role=\"alert\" data-testid=\"git-auth-load-error\" className=\"text-xs text-doom-red\">\n {loadError.error}\n </p>\n );\n }\n if (loaded?.repositoryId !== repositoryId) {\n return (\n <span data-testid=\"git-auth-loading\" className=\"flex items-center gap-2\">\n <Spinner className=\"h-3 w-3 text-doom-faint\" label=\"loading git settings\" />\n <span className=\"text-xs text-doom-dim\">loading…</span>\n </span>\n );\n }\n return (\n <GitAuthForm\n key={`${repositoryId}-${String(generation)}`}\n saved={loaded.saved}\n saving={saving}\n savedNotice={savedNotice}\n onSave={(next) => void save(next)}\n {...(saveError === undefined ? {} : { saveError })}\n />\n );\n}\n","import { defineRepositorySettingsPanel } from '@agimon-ai/doompi-core/web';\n\nimport { GitAuthPanel } from './_components/GitAuthPanel';\n\nexport default defineRepositorySettingsPanel({\n label: 'git remote',\n detail: \"how this workspace's sessions reach the remote when you pull, push or rebase from the cockpit\",\n order: 50,\n component: GitAuthPanel,\n});\n","/**\n * The cockpit's view of this session's worktrees.\n *\n * DESIGN PATTERNS:\n * - Declarations only. The channel frame type is a constant so the hub and the\n * page cannot drift apart on a string.\n * - A view is the subset of a record the dock needs, not the record. The\n * registry may hold paths and provenance the page has no business rendering.\n *\n * AVOID:\n * - Adding behaviour here. This file is imported by browser code, so it must\n * stay free of node builtins.\n */\n\n/** The data channel carrying one session's worktrees to the page. */\nexport const GIT_WORKTREES_TYPE = 'git_worktrees';\n\n/** One worktree, as the activity dock and its panel render it. */\nexport interface WorktreeView {\n id: string;\n branch: string;\n path: string;\n /** The session the hub started for this worktree, when it is still live. */\n sessionId: string | null;\n /** True once the directory the record names has gone missing. */\n orphaned: boolean;\n /**\n * True when the session that asked for this worktree is gone.\n *\n * An owned worktree is only ever shown to its own session. This flag marks\n * the exception: once the parent is dead nobody would see the worktree at\n * all, so every session in the repository does, and may close it.\n */\n unowned: boolean;\n}\n\n/**\n * What the panel asks the hub channel to do.\n *\n * The dock acts through its own channel rather than through the agent: a\n * worktree made from the panel and one made by the tool take the same\n * `worktreeOperations` path, but the panel no longer has to spend a turn of\n * the conversation to get there.\n */\nexport type GitWorktreesCommand =\n | { action: 'create'; branch: string; baseRef?: string; reservationId?: string }\n | { action: 'close'; id: string; force?: boolean };\n\nexport type WorktreeErrorTarget = { action: 'create' } | { action: 'close'; id: string };\n\nexport interface GitWorktreesPayload {\n worktrees: WorktreeView[];\n /** Label of the operation in flight, absent when the session is idle. */\n pending?: string;\n /** The last failure, cleared when the next command starts. */\n error?: string;\n /** The operation that produced the last failure, when known. */\n errorTarget?: WorktreeErrorTarget;\n}\n","/**\n * The dock's view of this session's worktrees, and the commands it sends.\n *\n * DESIGN PATTERNS:\n * - Session-scoped store fed by one hub channel. The hub is authoritative; the\n * page never reads a registry and never guesses.\n * - Actions are channel frames, not prompts. The hub half owns the tool's\n * operations, so the panel names the work and the hub performs it; a\n * worktree made from the dock is the same object the tool makes, without\n * spending a turn of the conversation to ask for it.\n * - The sender lives in a store rather than a module variable, because a web\n * plugin keeps no mutable module state and the page may reconnect.\n *\n * AVOID:\n * - Calling the hub package API from here. A dock slot gets no sealed request\n * transport, and raw fetch breaks the remote cockpit.\n * - `sendSessionFrame` for a command. It envelopes the frame as a session\n * command bound for the agent, which never reaches a channel's `receive`.\n */\nimport { defineGlobalStore, defineSessionStore, type WebPluginRuntime } from '@agimon-ai/doompi-core/web';\n\nimport {\n GIT_WORKTREES_TYPE,\n type GitWorktreesCommand,\n type WorktreeErrorTarget,\n type WorktreeView,\n} from '../../../../../types/webWorktrees';\n\nexport interface WorktreesSession {\n /** The worktrees the hub last reported for this session's repository. */\n worktrees: WorktreeView[];\n /** Label of the operation the hub is running for this session. */\n pending: string | undefined;\n /** The last failure the hub reported, shown until the next command. */\n error: string | undefined;\n /** The operation that produced the last failure, when known. */\n errorTarget?: WorktreeErrorTarget;\n}\n\nexport const worktreeActivity = defineSessionStore<WorktreesSession>({\n worktrees: [],\n pending: undefined,\n error: undefined,\n errorTarget: undefined,\n});\n\n/** Captures the clicked card, so a focus change cannot retarget an open dialog. */\nexport const worktreeCreateDialog = defineGlobalStore<{ sessionId: string; reservationId?: string } | null>(null);\n/**\n * The page's hub socket sender, held for as long as the plugin runs.\n *\n * Undefined before `startWorktreeRuntime` and after it disposes; a command\n * sent in that window is dropped rather than queued, because a queue would\n * replay a worktree create against a socket that has since changed sessions.\n */\nconst worktreeSender = defineGlobalStore<WebPluginRuntime['sendHubFrame'] | undefined>(undefined);\n\n/** Binds the page's hub socket. The plugin host calls this once per page. */\nexport function startWorktreeRuntime(runtime: WebPluginRuntime): () => void {\n // Wrapped rather than referenced: an unbound method would lose the runtime\n // it belongs to the moment the store hands it back.\n const send = (frame: Record<string, unknown>): void => {\n runtime.sendHubFrame(frame);\n };\n worktreeSender.update(() => send);\n return () => {\n worktreeSender.update((current) => (current === send ? undefined : current));\n worktreeCreateDialog.update(() => null);\n };\n}\n\n/**\n * Whether this session has worktree work in flight.\n *\n * A standing worktree is state, not work: it sits there until someone closes\n * it, so counting it would leave the session reading as busy forever, with a\n * \"background work is still running\" notice under a conversation where\n * nothing is running. Only a create or close actually in progress counts.\n *\n * The group stays visible either way. Declaring an active source at all is\n * what keeps it in the dock; this answers how it is drawn, not whether it is\n * there.\n */\nexport const worktreeActivitySource = {\n subscribe(listener: () => void) {\n const subscription = worktreeActivity.store.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n isActive(sessionId: string | null) {\n return worktreeActivity.select(worktreeActivity.store.state, sessionId).pending !== undefined;\n },\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction optionalText(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction optionalErrorTarget(value: unknown): WorktreeErrorTarget | undefined {\n if (!isRecord(value)) return undefined;\n if (value.action === 'create') return { action: 'create' };\n if (value.action === 'close' && typeof value.id === 'string' && value.id !== '') {\n return { action: 'close', id: value.id };\n }\n return undefined;\n}\n\n/** The plugin's session data channel: 'git_worktrees' payloads into the store. */\nexport const worktreesChannel = worktreeActivity.channel<WorktreesSession>({\n channel: GIT_WORKTREES_TYPE,\n parse(input) {\n if (!isRecord(input) || !Array.isArray(input.worktrees)) return null;\n return {\n worktrees: input.worktrees.filter(isRecord) as unknown as WorktreeView[],\n pending: optionalText(input.pending),\n error: optionalText(input.error),\n errorTarget: optionalErrorTarget(input.errorTarget),\n };\n },\n reduce(_current, next) {\n return next;\n },\n});\n\n/** Sends one command to the session's worktrees channel. */\nfunction command(sessionId: string, payload: GitWorktreesCommand): void {\n worktreeSender.store.state?.({ type: GIT_WORKTREES_TYPE, sessionId, payload });\n}\n\n/** Asks the hub for a worktree. The hub answers on the same channel. */\nexport function requestWorktreeCreate(\n sessionId: string,\n branch: string,\n baseRef: string,\n reservationId?: string,\n): void {\n const trimmedBase = baseRef.trim();\n command(sessionId, {\n action: 'create',\n branch: branch.trim(),\n ...(trimmedBase === '' ? {} : { baseRef: trimmedBase }),\n ...(reservationId === undefined ? {} : { reservationId }),\n });\n}\n\n/** Asks the hub to close one worktree. Refusal on a dirty tree stays the hub's call. */\nexport function requestWorktreeClose(sessionId: string, id: string): void {\n command(sessionId, { action: 'close', id });\n}\n","import type { TransientTab, WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\n/**\n * The '# git' group's tab: this session's worktrees, and the form that makes one.\n *\n * DESIGN PATTERNS:\n * - Lives in the activity dock, opened by the group's name. A worktree is work\n * in progress belonging to the session that started it, so it sits beside\n * agents, runners and workflows rather than in a settings screen.\n * - Header, form, then cards, the same rhythm the runners and workflows panels\n * use. A worktree row is a card because it carries three facts and two\n * actions, which a single line cannot hold without becoming a puzzle.\n * - Local form state is never reset by a data refresh. Direct lifecycle events\n * update the list without discarding a half-typed branch name.\n * - Acts through the plugin's own hub channel, so a worktree made here and one\n * made by the tool take exactly the same path.\n * - Creating waits on the cockpit starting a session, so the hub reports each\n * phase on that channel and the header shows it turning. A button that looks\n * idle for two minutes reads as broken.\n *\n * AVOID:\n * - Deriving form state from refreshed store data instead of the user's input.\n * - Colour classes outside the token set. `doom-error`, `doom-line` and\n * `doom-bright` are not tokens: they compile to nothing and the row silently\n * loses its border.\n */\nimport { Button, Dot, EmptyState, Input, Spinner, StatusBadge } from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\nimport { useState } from 'react';\n\nimport type { WorktreeView } from '../../../../../types/webWorktrees';\nimport { requestWorktreeClose, requestWorktreeCreate, worktreeActivity } from '../_lib/worktreesActivityStore';\n\nconst WORKTREES_TAB_ID = 'git-worktrees';\n\nexport function worktreesTab(): TransientTab {\n return { id: WORKTREES_TAB_ID, label: 'worktrees', panel: WorktreesPanel };\n}\n\nexport function WorktreesPanel({ sessionId, sessionReservationId }: WebPluginSlotProps) {\n const session = useStore(worktreeActivity.store, (state) => worktreeActivity.select(state, sessionId));\n const [branch, setBranch] = useState('');\n const [baseRef, setBaseRef] = useState('');\n\n const busy = session.pending !== undefined;\n const canCreate = sessionId !== null && branch.trim() !== '' && !busy;\n const createError = session.errorTarget?.action === 'create' ? session.error : undefined;\n const closeErrorId = session.errorTarget?.action === 'close' ? session.errorTarget.id : undefined;\n const panelError =\n session.error !== undefined &&\n (session.errorTarget === undefined ||\n (closeErrorId !== undefined && !session.worktrees.some((worktree) => worktree.id === closeErrorId)));\n\n const create = (): void => {\n if (sessionId === null || !canCreate) return;\n requestWorktreeCreate(sessionId, branch, baseRef, sessionReservationId);\n // A reserved setup must be retried with the same branch after a partial failure.\n if (sessionReservationId === undefined) {\n setBranch('');\n setBaseRef('');\n }\n };\n\n return (\n <div data-testid=\"git-worktrees-panel\" className=\"flex min-h-0 flex-1 flex-col overflow-auto\">\n <div className=\"flex min-h-11 shrink-0 items-center gap-2.5 border-b border-doom-border-soft px-3 sm:px-[26px]\">\n <span className=\"text-sm font-bold text-doom-hi\">worktrees</span>\n <span data-testid=\"git-worktrees-count\" className=\"text-xs text-doom-faint\">\n {session.worktrees.length === 0 ? 'none yet' : `${String(session.worktrees.length)} open`}\n </span>\n <span className=\"min-w-0 flex-1\" />\n {session.pending === undefined ? null : (\n <span data-testid=\"git-worktree-pending\" className=\"flex min-w-0 items-center gap-1.5\">\n <Spinner className=\"h-3 w-3 shrink-0 text-doom-faint\" label={session.pending} />\n <span className=\"min-w-0 truncate text-xs text-doom-dim\">{session.pending}</span>\n </span>\n )}\n </div>\n\n <div className=\"flex shrink-0 flex-col gap-1.5 border-b border-doom-border-soft px-3 py-2.5 sm:px-[26px]\">\n <div className=\"flex items-center gap-2\">\n <Input\n data-testid=\"git-worktree-branch\"\n aria-label=\"Branch\"\n size=\"sm\"\n className=\"min-w-0 flex-1\"\n placeholder=\"wt/fix-auth\"\n value={branch}\n onChange={(event) => setBranch(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') create();\n }}\n />\n <Input\n data-testid=\"git-worktree-base\"\n aria-label=\"Base ref\"\n size=\"sm\"\n placeholder=\"base (current)\"\n value={baseRef}\n onChange={(event) => setBaseRef(event.target.value)}\n className=\"w-32 shrink-0\"\n />\n <Button data-testid=\"git-worktree-create\" size=\"sm\" disabled={!canCreate} onClick={create}>\n Create\n </Button>\n </div>\n {createError === undefined ? (\n <p className=\"text-2xs text-doom-faint\">\n Creates the worktree outside the repository and starts a session nested under this one.\n </p>\n ) : (\n <p role=\"alert\" data-testid=\"git-worktree-error\" className=\"text-2xs text-doom-red\">\n {createError}\n </p>\n )}\n </div>\n\n {panelError ? (\n <p role=\"alert\" data-testid=\"git-worktree-error\" className=\"px-3 pt-2 text-2xs text-doom-red sm:px-[26px]\">\n {session.error}\n </p>\n ) : null}\n\n {session.worktrees.length === 0 ? (\n <EmptyState\n data-testid=\"git-worktrees-empty\"\n className=\"px-4 py-8\"\n title=\"no worktrees yet\"\n description=\"a worktree is its own checkout on its own branch, with its own session nested under this one.\"\n />\n ) : (\n <ul data-testid=\"git-worktrees-list\" className=\"flex flex-col gap-2.5 px-3 py-3 sm:px-[26px]\">\n {session.worktrees.map((worktree: WorktreeView) => (\n <WorktreeCard\n key={worktree.id}\n worktree={worktree}\n sessionId={sessionId}\n busy={busy}\n error={closeErrorId === worktree.id ? session.error : undefined}\n />\n ))}\n </ul>\n )}\n </div>\n );\n}\n\n/** One worktree: what it is, where it is, and the one thing you can do to it. */\nfunction WorktreeCard({\n worktree,\n sessionId,\n busy,\n error,\n}: {\n worktree: WorktreeView;\n busy: boolean;\n error?: string;\n} & Pick<WebPluginSlotProps, 'sessionId'>) {\n return (\n <li\n data-testid={`git-worktree-${worktree.id}`}\n className=\"flex min-w-0 flex-col gap-1.5 rounded-md border border-doom-border-soft bg-doom-panel p-2.5\"\n >\n <div className=\"flex min-w-0 items-center gap-1.5\">\n <Dot tone={worktree.orphaned ? 'red' : worktree.sessionId === null ? 'muted' : 'blue'} />\n <span className=\"min-w-0 flex-1 truncate text-sm font-bold text-doom-hi\">{worktree.branch}</span>\n {worktree.orphaned ? (\n <StatusBadge tone=\"error\" size=\"xs\">\n orphaned\n </StatusBadge>\n ) : null}\n {worktree.unowned ? (\n <StatusBadge tone=\"info\" size=\"xs\">\n unowned\n </StatusBadge>\n ) : null}\n </div>\n\n <span className=\"min-w-0 truncate text-2xs text-doom-faint\">{worktree.path}</span>\n\n <div className=\"flex items-center gap-1.5 pt-0.5\">\n <span className=\"min-w-0 flex-1\" />\n {sessionId === null ? null : (\n <Button\n variant=\"danger-outline\"\n size=\"xs\"\n disabled={busy}\n data-testid={`git-worktree-close-${worktree.id}`}\n className=\"px-2 text-2xs font-bold\"\n onClick={() => requestWorktreeClose(sessionId, worktree.id)}\n >\n close\n </Button>\n )}\n </div>\n {error === undefined ? null : (\n <p role=\"alert\" data-testid=\"git-worktree-error\" className=\"text-2xs text-doom-red\">\n {error}\n </p>\n )}\n </li>\n );\n}\n","/**\n * The cockpit's view of what this session changed against its base: the counts\n * the '# diff' group shows, what the review tab lists and draws, and the manual\n * sync that sits beside them.\n *\n * DESIGN PATTERNS:\n * - Declarations only, shared by the hub and the page.\n * - Its own channel, apart from worktrees. Worktrees are repository\n * management; the diff is this session's code change.\n * - A diff row carries one line number whose file follows from its marker: the\n * new file's for context and additions, the old file's for removals. It is\n * the same shape the shared DiffView draws.\n *\n * AVOID:\n * - Behaviour or node builtins. Browser code imports this file.\n */\n\n/** The session channel carrying this checkout's changes and the sync around them. */\nexport const GIT_CHANGES_TYPE = 'git_changes';\n\n/** The sync actions the review tab offers. */\nexport type GitSyncAction = 'pull' | 'push' | 'rebase' | 'abort-rebase';\n\n/** What the review tab asks the hub to run. `force` only follows a confirmed rejected push. */\nexport type GitChangesCommand =\n | { action: 'pull' }\n | { action: 'push'; force?: true }\n | { action: 'rebase' }\n | { action: 'abort-rebase' };\n\nexport type GitSyncErrorTarget =\n | { action: 'pull' | 'rebase' | 'abort-rebase' }\n /** A push the remote rejected as non-fast-forward; the tab offers a lease force after a confirm. */\n | { action: 'push'; forceRequired?: true };\n\nexport interface GitChangesPayload {\n /** Absent outside a git checkout. */\n changes?: GitChangesView;\n /** Label of the sync command in flight. */\n pending?: string;\n /** The last sync failure, cleared when the next command starts. */\n error?: string;\n errorTarget?: GitSyncErrorTarget;\n}\n\n/** What the session changed since its base, as the '# diff' lane and the review header show it. */\nexport interface GitChangesView {\n /** The checked-out branch; absent on a detached HEAD. */\n branch?: string;\n /** The ref the changes are measured against; absent when none resolved, so only uncommitted work counts. */\n base?: string;\n added: number;\n removed: number;\n files: number;\n /** More files changed than were counted. */\n truncated?: boolean;\n /** The branch's upstream and how far apart the two are. */\n upstream?: { ref: string; ahead: number; behind: number };\n /** Present while a rebase is paused on conflicts. */\n rebase?: { conflicts: string[] };\n}\n\nexport type GitReviewFileStatus = 'added' | 'modified' | 'deleted' | 'untracked' | 'conflicted';\n\n/** One changed file in the review list. */\nexport interface GitReviewFileEntry {\n /** Repository-relative, forward slashes. */\n path: string;\n status: GitReviewFileStatus;\n added: number;\n removed: number;\n binary?: boolean;\n}\n\n/** The review tab's file list. */\nexport interface GitReviewSummary {\n /** False when the session's directory is not a git checkout. */\n repository: boolean;\n branch?: string;\n base?: string;\n /** Short sha of the commit the diff starts from. */\n mergeBase?: string;\n files: GitReviewFileEntry[];\n truncated?: boolean;\n}\n\nexport interface GitDiffRow {\n marker: '+' | '-' | ' ';\n line: number;\n content: string;\n}\n\nexport interface GitDiffHunk {\n start: number;\n rows: GitDiffRow[];\n}\n\n/** One file's hunks, fetched when the reader expands it. */\nexport interface GitReviewFileDiff {\n path: string;\n hunks: GitDiffHunk[];\n binary?: true;\n /** The diff was past the size cap and is not drawn. */\n tooLarge?: true;\n}\n","/**\n * This session's code change against its base, and the manual sync beside it.\n *\n * DESIGN PATTERNS:\n * - Its own session store and hub channel, apart from worktrees. Worktrees are\n * repository management; this is the session's diff.\n * - The hub is authoritative: it computes the counts, runs pull, push and\n * rebase one at a time, and reports pending, errors and a paused rebase here.\n * - The sender lives in a store rather than a module variable, because a web\n * plugin keeps no mutable module state and the page may reconnect.\n *\n * AVOID:\n * - `sendSessionFrame` for a sync command. That frame is bound for the agent\n * and never reaches a channel's `receive`.\n */\nimport { defineGlobalStore, defineSessionStore, type WebPluginRuntime } from '@agimon-ai/doompi-core/web';\n\nimport {\n GIT_CHANGES_TYPE,\n type GitChangesCommand,\n type GitChangesView,\n type GitSyncAction,\n type GitSyncErrorTarget,\n} from '../../../../../types/gitReview';\n\nexport interface GitChangesSession {\n /** Absent until the hub reports, and outside a git checkout. */\n changes: GitChangesView | undefined;\n pending: string | undefined;\n error: string | undefined;\n errorTarget: GitSyncErrorTarget | undefined;\n}\n\nexport const gitChanges = defineSessionStore<GitChangesSession>({\n changes: undefined,\n pending: undefined,\n error: undefined,\n errorTarget: undefined,\n});\n\n/** The page's hub socket sender; undefined before start and after dispose, when a command is dropped. */\nconst changesSender = defineGlobalStore<WebPluginRuntime['sendHubFrame'] | undefined>(undefined);\n\n/** Binds the page's hub socket for sync commands. The plugin host calls this once per page. */\nexport function startGitChangesRuntime(runtime: WebPluginRuntime): () => void {\n const send = (frame: Record<string, unknown>): void => {\n runtime.sendHubFrame(frame);\n };\n changesSender.update(() => send);\n return () => {\n changesSender.update((current) => (current === send ? undefined : current));\n };\n}\n\n/** Whether a sync command is running for this session. */\nexport const gitChangesActivitySource = {\n subscribe(listener: () => void) {\n const subscription = gitChanges.store.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n isActive(sessionId: string | null) {\n return gitChanges.select(gitChanges.store.state, sessionId).pending !== undefined;\n },\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction optionalText(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction count(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0 ? value : undefined;\n}\n\n/** The page never trusts a frame's shape: a malformed field drops, the rest still renders. */\nconst MAX_CONFLICTS = 100;\n\nfunction optionalChanges(value: unknown): GitChangesView | undefined {\n if (!isRecord(value)) return undefined;\n const added = count(value.added);\n const removed = count(value.removed);\n const files = count(value.files);\n if (added === undefined || removed === undefined || files === undefined) return undefined;\n const branch = optionalText(value.branch);\n const base = optionalText(value.base);\n const upstream = isRecord(value.upstream) ? value.upstream : undefined;\n const ahead = count(upstream?.ahead);\n const behind = count(upstream?.behind);\n const upstreamRef = optionalText(upstream?.ref);\n const conflicts =\n isRecord(value.rebase) && Array.isArray(value.rebase.conflicts)\n ? value.rebase.conflicts.filter((file): file is string => typeof file === 'string').slice(0, MAX_CONFLICTS)\n : undefined;\n return {\n added,\n removed,\n files,\n ...(branch === undefined ? {} : { branch }),\n ...(base === undefined ? {} : { base }),\n ...(value.truncated === true ? { truncated: true } : {}),\n ...(upstreamRef === undefined || ahead === undefined || behind === undefined\n ? {}\n : { upstream: { ref: upstreamRef, ahead, behind } }),\n ...(conflicts === undefined ? {} : { rebase: { conflicts } }),\n };\n}\n\nfunction optionalErrorTarget(value: unknown): GitSyncErrorTarget | undefined {\n if (!isRecord(value)) return undefined;\n if (value.action === 'pull' || value.action === 'rebase' || value.action === 'abort-rebase')\n return { action: value.action };\n if (value.action === 'push')\n return value.forceRequired === true ? { action: 'push', forceRequired: true } : { action: 'push' };\n return undefined;\n}\n\n/** The session data channel: 'git_changes' payloads into the store. */\nexport const gitChangesChannel = gitChanges.channel<GitChangesSession>({\n channel: GIT_CHANGES_TYPE,\n parse(input) {\n if (!isRecord(input)) return null;\n return {\n changes: optionalChanges(input.changes),\n pending: optionalText(input.pending),\n error: optionalText(input.error),\n errorTarget: optionalErrorTarget(input.errorTarget),\n };\n },\n reduce(_current, next) {\n return next;\n },\n});\n\n/**\n * Asks the hub to pull, push, rebase or abort a paused rebase. `force` is only\n * ever sent after the reader confirmed a lease force for a rejected push.\n */\nexport function requestGitSync(sessionId: string, action: GitSyncAction, force = false): void {\n const payload: GitChangesCommand = action === 'push' && force ? { action: 'push', force: true } : { action };\n changesSender.store.state?.({ type: GIT_CHANGES_TYPE, sessionId, payload });\n}\n","import { defineActivityGroup } from '@agimon-ai/doompi-core/web';\n\nimport { worktreesTab } from '../_components/WorktreesPanel';\nimport { gitChangesActivitySource } from '../_lib/gitChangesStore';\nimport { worktreeActivitySource } from '../_lib/worktreesActivityStore';\n\nexport default defineActivityGroup({\n keys: 'g w',\n activeSource: {\n subscribe(listener) {\n const stopWorktrees = worktreeActivitySource.subscribe(listener);\n const stopChanges = gitChangesActivitySource.subscribe(listener);\n return () => {\n stopWorktrees();\n stopChanges();\n };\n },\n isActive(sessionId) {\n return worktreeActivitySource.isActive(sessionId) || gitChangesActivitySource.isActive(sessionId);\n },\n },\n marksBackgroundWork: false,\n transientTab: worktreesTab,\n order: 30,\n});\n","import { defineChannelFile } from '@agimon-ai/doompi-core/web';\n\nimport { gitChangesChannel } from '../_lib/gitChangesStore';\n\nexport default defineChannelFile(gitChangesChannel);\n","import { defineChannelFile } from '@agimon-ai/doompi-core/web';\n\nimport { worktreesChannel } from '../_lib/worktreesActivityStore';\n\nexport default defineChannelFile(worktreesChannel);\n","import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\nimport {\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DropdownMenuItem,\n} from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\nimport { useEffect } from 'react';\n\nimport { WorktreesPanel } from '../../_components/WorktreesPanel';\nimport { worktreeCreateDialog, worktreesChannel } from '../../_lib/worktreesActivityStore';\n\nexport function WorktreeSessionMenu({ sessionId, sessionReservationId }: WebPluginSlotProps) {\n return (\n <DropdownMenuItem\n disabled={sessionId === null}\n data-testid={`session-worktree-${sessionReservationId ?? sessionId}`}\n onSelect={() => {\n if (sessionId !== null)\n worktreeCreateDialog.update(() => ({\n sessionId,\n ...(sessionReservationId === undefined ? {} : { reservationId: sessionReservationId }),\n }));\n }}\n >\n create worktree session…\n </DropdownMenuItem>\n );\n}\n\nexport function WorktreeCreateOverlay(props: WebPluginSlotProps) {\n const target = useStore(worktreeCreateDialog.store);\n const { holdSessionChannels } = props;\n useEffect(() => {\n if (target === null) return;\n return holdSessionChannels?.(target.sessionId, (frame) => {\n if (frame.type !== worktreesChannel.channel) return;\n const payload = worktreesChannel.parse(frame.payload);\n if (payload !== null) worktreesChannel.apply(target.sessionId, payload);\n });\n }, [target, holdSessionChannels]);\n if (target === null) return null;\n return (\n <Dialog\n open\n onOpenChange={(open) => {\n if (!open) worktreeCreateDialog.update(() => null);\n }}\n >\n <DialogContent width=\"lg\" data-testid=\"session-worktree-dialog\">\n <DialogHeader>\n <DialogTitle>create worktree session</DialogTitle>\n </DialogHeader>\n <DialogBody>\n <DialogDescription>\n Creates a separate checkout and a new session. Existing sessions stay in their current directories.\n </DialogDescription>\n <WorktreesPanel\n {...props}\n key={`${target.sessionId}:${target.reservationId ?? ''}`}\n sessionId={target.sessionId}\n sessionReservationId={target.reservationId}\n />\n </DialogBody>\n </DialogContent>\n </Dialog>\n );\n}\n","import { defineFill } from '@agimon-ai/doompi-core/web';\n\nimport { WorktreeSessionMenu } from './_components/WorktreeCreateDialog';\n\nexport default defineFill({ component: WorktreeSessionMenu });\n","import { defineFill } from '@agimon-ai/doompi-core/web';\n\nimport { WorktreeCreateOverlay } from './_components/WorktreeCreateDialog';\n\nexport default defineFill({ component: WorktreeCreateOverlay });\n","import { api } from '../../../../../../generated/client';\nimport type { GitReviewFileDiff, GitReviewSummary } from '../../../../../types/gitReview';\n\n/**\n * The review tab's half of the session API: the changed-file list and one\n * file's hunks.\n *\n * The generated client owns the URL and the sealed transport, so nothing here\n * spells a route or reaches for `fetch`. What travels is file contents, which a\n * tunnel's relay must never see in the clear.\n */\n\nconst UNREACHABLE = 'The session is unreachable.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The message a reader is shown: the route's own words, or why there were none. */\nfunction messageOf(result: { status: number; error: string }): string {\n if (result.status === 0) return UNREACHABLE;\n return result.error === '' ? `The session answered ${String(result.status)}.` : result.error;\n}\n\nexport type ReviewSummaryResult = { ok: true; summary: GitReviewSummary } | { ok: false; error: string };\n\nexport async function fetchReviewSummary(sessionId: string, signal?: AbortSignal): Promise<ReviewSummaryResult> {\n const result = await api.session(sessionId).review(signal === undefined ? {} : { signal });\n if (!result.ok) return { ok: false, error: messageOf(result) };\n if (!isRecord(result.data) || !Array.isArray(result.data.files)) {\n return { ok: false, error: 'The session answered with no file list.' };\n }\n return { ok: true, summary: result.data };\n}\n\nexport type ReviewFileResult = { ok: true; diff: GitReviewFileDiff } | { ok: false; error: string };\n\nexport async function fetchReviewFile(\n sessionId: string,\n path: string,\n signal?: AbortSignal,\n): Promise<ReviewFileResult> {\n const result = await api\n .session(sessionId)\n .reviewFile({ query: { path }, ...(signal === undefined ? {} : { signal }) });\n if (!result.ok) return { ok: false, error: messageOf(result) };\n if (!isRecord(result.data) || !Array.isArray(result.data.hunks)) {\n return { ok: false, error: 'The session answered with no diff.' };\n }\n return { ok: true, diff: result.data };\n}\n","import { defineSessionStore } from '@agimon-ai/doompi-core/web';\n/**\n * Review comments queued on this session, waiting to go to the agent as one\n * message.\n *\n * DESIGN PATTERNS:\n * - Session-scoped and in memory: comments survive closing and reopening the\n * review tab, not a page reload. The same trade the files tab makes.\n * - Comments are cleared only after a send the host accepted, never before.\n */\nimport type { ReviewComment } from '@agimon-ai/doompi-web-components';\n\nexport interface GitReviewSession {\n comments: ReviewComment[];\n}\n\nexport const gitReview = defineSessionStore<GitReviewSession>({ comments: [] });\n\nexport function addReviewComment(sessionId: string, comment: Omit<ReviewComment, 'id'>): void {\n const id = globalThis.crypto.randomUUID();\n gitReview.update(sessionId, (current) => ({ comments: [...current.comments, { ...comment, id }] }));\n}\n\nexport function removeReviewComment(sessionId: string, id: string): void {\n gitReview.update(sessionId, (current) => ({ comments: current.comments.filter((comment) => comment.id !== id) }));\n}\n\nexport function clearReviewComments(sessionId: string): void {\n gitReview.update(sessionId, () => ({ comments: [] }));\n}\n","import type { SessionFrameSender } from '@agimon-ai/doompi-core/web';\n\n/**\n * Pure wording for what the review tab sends the agent, and the one send.\n *\n * Both messages go as `enqueue_automatic`: the host stores it and starts a turn\n * at once when the agent is idle, or after the current one. A `prompt` frame\n * instead fails while a turn runs, and a review lost to that is the worst kind\n * of lost work.\n */\n\n/** The opening line of a review, naming what was reviewed. */\nexport function reviewHeading(count: number, branch: string | undefined, base: string | undefined): string {\n const what = branch === undefined ? 'this checkout' : `branch ${branch}`;\n const against = base === undefined ? 'its uncommitted changes' : `its changes against ${base}`;\n const comments = count === 1 ? 'one review comment' : `${String(count)} review comments`;\n const address = count === 1 ? 'Please address it.' : 'Please address them all.';\n return `I reviewed ${what} (${against}) and left ${comments}. ${address}`;\n}\n\n/** What \"ask agent to resolve\" sends: the files, and the steps that finish a paused rebase. */\nexport function conflictPrompt(branch: string | undefined, conflicts: readonly string[]): string {\n const files =\n conflicts.length === 0 ? '- (git reports no unmerged paths yet)' : conflicts.map((file) => `- ${file}`).join('\\n');\n return [\n `A rebase of ${branch ?? 'this checkout'} stopped on conflicts in:`,\n '',\n files,\n '',\n 'Please resolve them:',\n '1. Fix the conflict markers in each file, keeping the intent of both sides.',\n '2. `git add` each resolved file.',\n '3. Run `GIT_EDITOR=true git rebase --continue`, and repeat if it stops again.',\n '',\n 'Do not push. I will push from the cockpit once the rebase is done.',\n ].join('\\n');\n}\n\n/**\n * Hands one message to the session's queue. Returns the reason it failed, or\n * undefined once the host took it. The sender throws when the session is not\n * connected, which is the only failure a caller can still act on.\n */\nexport function deliverToAgent(send: SessionFrameSender, sessionId: string, message: string): string | undefined {\n try {\n send(sessionId, { type: 'enqueue_automatic', message });\n return undefined;\n } catch (error) {\n return error instanceof Error ? error.message : 'The session did not take the message.';\n }\n}\n","/**\n * The review browser's folder tree: changed files nested by directory, with\n * single-child folder chains compacted into one row like VS Code's explorer.\n */\nimport type { GitReviewFileEntry } from '../../../../../types/gitReview';\n\ninterface TreeDir {\n path: string;\n dirs: Map<string, TreeDir>;\n files: GitReviewFileEntry[];\n}\n\nexport type TreeRow =\n | { kind: 'dir'; path: string; name: string; depth: number; open: boolean }\n | { kind: 'file'; file: GitReviewFileEntry; depth: number };\n\nfunction buildTree(files: readonly GitReviewFileEntry[]): TreeDir {\n const root: TreeDir = { path: '', dirs: new Map(), files: [] };\n for (const file of files) {\n const parts = file.path.split('/');\n parts.pop();\n let dir = root;\n for (const part of parts) {\n let next = dir.dirs.get(part);\n if (next === undefined) {\n next = { path: dir.path === '' ? part : `${dir.path}/${part}`, dirs: new Map(), files: [] };\n dir.dirs.set(part, next);\n }\n dir = next;\n }\n dir.files.push(file);\n }\n return root;\n}\n\n/** Folders first, then files, each alphabetical; single-child folder chains render as one row. */\nexport function flattenTree(files: readonly GitReviewFileEntry[], isOpen: (dirPath: string) => boolean): TreeRow[] {\n const rows: TreeRow[] = [];\n const walk = (dir: TreeDir, depth: number): void => {\n for (const [segment, child] of [...dir.dirs].sort(([left], [right]) => left.localeCompare(right))) {\n let name = segment;\n let node = child;\n while (node.files.length === 0 && node.dirs.size === 1) {\n const [[nextName, next]] = [...node.dirs] as [[string, TreeDir]];\n name = `${name}/${nextName}`;\n node = next;\n }\n const open = isOpen(node.path);\n rows.push({ kind: 'dir', path: node.path, name, depth, open });\n if (open) walk(node, depth + 1);\n }\n for (const file of [...dir.files].sort((left, right) => left.path.localeCompare(right.path))) {\n rows.push({ kind: 'file', file, depth });\n }\n };\n walk(buildTree(files), 0);\n return rows;\n}\n","/**\n * The review tab's file list: every changed file as a folder tree (the VS Code\n * explorer shape), with its status, its line counts and its comments.\n *\n * DESIGN PATTERNS:\n * - Picking a row scrolls the diff pane to that file; the list never opens a\n * tab of its own. One tab holds the whole review.\n * - Rows show only the file name, so a long path never truncates away the part\n * that tells files apart. Folders say the rest; the full path is the tooltip.\n * - Folder chains with a single child collapse into one row (`src/web/lib`),\n * like VS Code's compact folders, so deep trees stay shallow.\n * - Folders fold on click; a search shows every match with its folders open.\n * - Each row is a button, reachable with Tab; arrow keys move and pick in one\n * step across the visible files, so the diff follows the cursor.\n *\n * AVOID:\n * - Colour classes outside the token set.\n */\nimport { Button, ChevronDownIcon, ChevronRightIcon, Input, MessageIcon } from '@agimon-ai/doompi-web-components';\nimport { useEffect, useRef, useState, type KeyboardEvent } from 'react';\n\nimport type { GitReviewFileEntry, GitReviewFileStatus } from '../../../../../types/gitReview';\nimport { flattenTree } from '../_lib/gitReviewTree';\n\nconst STATUS_MARK: Readonly<Record<GitReviewFileStatus, { letter: string; tone: string; label: string }>> = {\n added: { letter: 'A', tone: 'text-doom-green', label: 'added' },\n modified: { letter: 'M', tone: 'text-doom-yellow', label: 'modified' },\n deleted: { letter: 'D', tone: 'text-doom-red', label: 'deleted' },\n untracked: { letter: 'U', tone: 'text-doom-blue', label: 'untracked' },\n conflicted: { letter: 'C', tone: 'text-doom-red', label: 'conflicted' },\n};\n\nconst baseName = (path: string): string => path.slice(path.lastIndexOf('/') + 1);\n/** Left padding per depth level; tight so deep files keep room for their names. */\nconst indent = (depth: number): { paddingLeft: string } => ({ paddingLeft: `${String(0.75 + depth * 0.5)}rem` });\n\nexport interface GitReviewBrowserProps {\n files: readonly GitReviewFileEntry[];\n /** The file the diff pane is showing, highlighted here. */\n activePath?: string;\n commentCounts: Readonly<Record<string, number>>;\n onPick: (path: string) => void;\n}\n\nexport function GitReviewBrowser({ files, activePath, commentCounts, onPick }: GitReviewBrowserProps) {\n const [query, setQuery] = useState('');\n const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(new Set());\n const needle = query.trim().toLocaleLowerCase();\n const shown = needle === '' ? files : files.filter((file) => file.path.toLocaleLowerCase().includes(needle));\n const rows = flattenTree(shown, (dirPath) => needle !== '' || !collapsed.has(dirPath));\n const ordered = rows.flatMap((row) => (row.kind === 'file' ? [row.file] : []));\n const listRef = useRef<HTMLDivElement>(null);\n\n // Keep the file the diff is showing in view as the reader scrolls the diff.\n useEffect(() => {\n if (activePath === undefined) return;\n const row = listRef.current?.querySelector<HTMLElement>(`[data-path=\"${CSS.escape(activePath)}\"]`);\n row?.scrollIntoView({ block: 'nearest' });\n }, [activePath]);\n\n const toggle = (dirPath: string): void => {\n setCollapsed((prev) => {\n const next = new Set(prev);\n if (!next.delete(dirPath)) next.add(dirPath);\n return next;\n });\n };\n const allDirs = (): Set<string> =>\n new Set(flattenTree(files, () => true).flatMap((row) => (row.kind === 'dir' ? [row.path] : [])));\n\n /** Arrow keys pick the neighbouring row and move focus with it, so the diff follows the cursor. */\n const onKeyDown = (event: KeyboardEvent<HTMLButtonElement>): void => {\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n if (ordered.length === 0) return;\n event.preventDefault();\n const current = ordered.findIndex((file) => file.path === activePath);\n const step = event.key === 'ArrowDown' ? 1 : -1;\n const next = current === -1 ? 0 : (current + step + ordered.length) % ordered.length;\n const file = ordered[next];\n if (file === undefined) return;\n onPick(file.path);\n const list = event.currentTarget.closest('[data-git-review-list]');\n list?.querySelectorAll<HTMLButtonElement>('[data-git-review-row]')[next]?.focus();\n };\n\n return (\n <nav\n data-testid=\"git-review-browser\"\n aria-label=\"changed files\"\n className=\"flex min-h-0 w-64 shrink-0 flex-col border-r border-doom-border-soft\"\n >\n <div className=\"flex shrink-0 flex-col gap-1 px-3 pt-2.5 pb-1.5\">\n <Input\n data-testid=\"git-review-search\"\n aria-label=\"search changed file paths\"\n size=\"sm\"\n value={query}\n placeholder=\"search paths…\"\n onChange={(event) => setQuery(event.target.value)}\n />\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-2xs text-doom-faint\">\n {needle === ''\n ? `${String(files.length)} changed`\n : `${String(shown.length)} of ${String(files.length)} match`}\n </span>\n {needle === '' ? (\n <Button\n variant=\"link\"\n size=\"xs\"\n data-testid=\"git-review-fold-all\"\n className=\"h-auto px-0\"\n onClick={() => setCollapsed(collapsed.size === 0 ? allDirs() : new Set())}\n >\n {collapsed.size === 0 ? 'collapse all' : 'expand all'}\n </Button>\n ) : null}\n </div>\n </div>\n <div ref={listRef} data-git-review-list className=\"min-h-0 flex-1 overflow-y-auto pb-2\">\n {rows.map((row) => {\n if (row.kind === 'dir') {\n const Chevron = row.open ? ChevronDownIcon : ChevronRightIcon;\n return (\n <Button\n key={`dir:${row.path}`}\n variant=\"ghost\"\n size=\"card\"\n aria-expanded={row.open}\n data-testid={`git-review-browser-dir-${row.path}`}\n title={row.path}\n onClick={() => toggle(row.path)}\n style={indent(row.depth)}\n className=\"min-w-0 flex-row items-center gap-1 rounded-none border-l-2 border-transparent py-1 pr-3 hover:bg-doom-panel/60\"\n >\n <Chevron aria-hidden className=\"h-3 w-3 shrink-0 text-doom-faint\" />\n <span className=\"min-w-0 flex-1 truncate text-xs text-doom-dim\">{row.name}</span>\n </Button>\n );\n }\n const { file } = row;\n const mark = STATUS_MARK[file.status];\n const comments = commentCounts[file.path] ?? 0;\n const active = file.path === activePath;\n return (\n <Button\n key={file.path}\n variant=\"ghost\"\n size=\"card\"\n data-git-review-row\n data-path={file.path}\n aria-current={active ? 'true' : undefined}\n data-testid={`git-review-browser-file-${file.path}`}\n title={`${file.path} (${mark.label})`}\n onClick={() => onPick(file.path)}\n onKeyDown={onKeyDown}\n style={indent(row.depth)}\n className={`min-w-0 flex-row items-center gap-1.5 rounded-none border-l-2 py-1 pr-3 ${\n active ? 'border-doom-blue bg-doom-panel' : 'border-transparent hover:bg-doom-panel/60'\n }`}\n >\n <span aria-label={mark.label} className={`w-3 shrink-0 text-center text-2xs font-bold ${mark.tone}`}>\n {mark.letter}\n </span>\n <span\n className={`min-w-0 flex-1 truncate text-xs text-doom-hi ${active ? 'font-bold' : ''} ${\n file.status === 'deleted' ? 'line-through opacity-70' : ''\n }`}\n >\n {baseName(file.path)}\n </span>\n {comments === 0 ? null : (\n <span\n className=\"flex shrink-0 items-center gap-0.5 text-2xs text-doom-blue\"\n title={`${String(comments)} comments`}\n >\n <MessageIcon aria-hidden className=\"h-2.5 w-2.5\" />\n {comments}\n </span>\n )}\n {file.binary ? (\n <span className=\"shrink-0 text-2xs text-doom-faint\">binary</span>\n ) : (\n <span className=\"shrink-0 text-2xs\">\n <span className=\"text-doom-green\">+{file.added}</span>{' '}\n <span className=\"text-doom-red\">-{file.removed}</span>\n </span>\n )}\n </Button>\n );\n })}\n {ordered.length === 0 ? <p className=\"px-3 py-2 text-2xs text-doom-faint\">no path matches</p> : null}\n </div>\n </nav>\n );\n}\n","/**\n * The review tab's header: what is being reviewed, and the manual sync that\n * goes with it.\n *\n * DESIGN PATTERNS:\n * - Everything here is a report or a request. The hub runs the git, one\n * command per session, and answers on the channel: pending while it runs,\n * an error target when it fails, a paused rebase when it stops on conflicts.\n * - A push the remote rejects is not an error to shrug at: the strip asks\n * before forcing, and the force it sends is a lease, which git refuses if\n * the remote holds commits this branch never fetched and integrated.\n * - A paused rebase blocks the sync buttons. The two ways out are named on the\n * banner, and abort says what it throws away.\n *\n * AVOID:\n * - Colour classes outside the token set.\n */\nimport { AlertIcon, BranchIcon, Button, Spinner, StatusBadge } from '@agimon-ai/doompi-web-components';\n\nimport type { GitChangesView, GitSyncAction, GitSyncErrorTarget } from '../../../../../types/gitReview';\n\nexport interface GitSyncBarProps {\n /** Absent until the hub has reported this session's checkout. */\n changes?: GitChangesView;\n /** Short sha the review diff starts from. */\n mergeBase?: string;\n /** Label of the command the hub is running. */\n pending?: string;\n error?: string;\n errorTarget?: GitSyncErrorTarget;\n onSync: (action: GitSyncAction) => void;\n onForcePush: () => void;\n onAskAgent: () => void;\n onDismissError: () => void;\n}\n\nexport function GitSyncBar({\n changes,\n mergeBase,\n pending,\n error,\n errorTarget,\n onSync,\n onForcePush,\n onAskAgent,\n onDismissError,\n}: GitSyncBarProps) {\n const busy = pending !== undefined;\n const paused = changes?.rebase !== undefined;\n const forceRequired =\n errorTarget?.action === 'push' && 'forceRequired' in errorTarget && errorTarget.forceRequired === true;\n const syncError = error !== undefined && !forceRequired ? error : undefined;\n const upstream = changes?.upstream;\n\n return (\n <div\n data-testid=\"git-sync-bar\"\n className=\"flex shrink-0 flex-col gap-2 border-b border-doom-border-soft px-3 py-2.5 sm:px-[26px]\"\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1.5\">\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <BranchIcon aria-hidden className=\"h-3.5 w-3.5 shrink-0 text-doom-faint\" />\n <span data-testid=\"git-review-branch\" className=\"truncate text-sm font-bold text-doom-hi\">\n {changes?.branch ?? 'detached HEAD'}\n </span>\n <span className=\"shrink-0 text-xs text-doom-faint\">\n {changes?.base === undefined ? 'uncommitted changes' : `vs ${changes.base}`}\n </span>\n {mergeBase === undefined ? null : <span className=\"shrink-0 text-2xs text-doom-faint\">from {mergeBase}</span>}\n </span>\n {changes === undefined ? null : (\n <span data-testid=\"git-review-totals\" className=\"flex shrink-0 items-center gap-1.5 text-xs\">\n <span className=\"font-bold text-doom-green\">+{changes.added}</span>\n <span className=\"font-bold text-doom-red\">-{changes.removed}</span>\n <span className=\"text-doom-faint\">\n {changes.files}\n {changes.truncated ? '+' : ''} {changes.files === 1 ? 'file' : 'files'}\n </span>\n </span>\n )}\n <span className=\"min-w-0 flex-1\" />\n {upstream === undefined ? (\n <span className=\"shrink-0 text-2xs text-doom-faint\">no upstream yet</span>\n ) : (\n <span className=\"shrink-0 text-2xs text-doom-faint\" title={upstream.ref}>\n ↑{upstream.ahead} ↓{upstream.behind} {upstream.ref}\n </span>\n )}\n <span className=\"flex shrink-0 items-center gap-1.5\">\n <Button\n size=\"xs\"\n data-testid=\"git-sync-pull\"\n disabled={busy || paused || upstream === undefined}\n title={upstream === undefined ? 'push once to set an upstream' : `fetch, then rebase onto ${upstream.ref}`}\n onClick={() => onSync('pull')}\n >\n pull\n </Button>\n <Button\n size=\"xs\"\n data-testid=\"git-sync-push\"\n disabled={busy || paused || changes?.branch === undefined}\n title={upstream === undefined ? 'push and set the upstream' : `push to ${upstream.ref}`}\n onClick={() => onSync('push')}\n >\n push\n </Button>\n <Button\n size=\"xs\"\n data-testid=\"git-sync-rebase\"\n disabled={busy || paused || changes?.base === undefined}\n title={\n changes?.base === undefined ? 'no base branch to rebase onto' : `fetch, then rebase onto ${changes.base}`\n }\n onClick={() => onSync('rebase')}\n >\n rebase\n </Button>\n </span>\n </div>\n\n {pending === undefined ? null : (\n <span data-testid=\"git-sync-pending\" className=\"flex min-w-0 items-center gap-1.5\">\n <Spinner className=\"h-3 w-3 shrink-0 text-doom-faint\" label={pending} />\n <span className=\"min-w-0 truncate text-xs text-doom-dim\">{pending}</span>\n </span>\n )}\n\n {syncError === undefined ? null : (\n <div\n role=\"alert\"\n data-testid=\"git-sync-error\"\n className=\"flex min-w-0 items-start gap-1.5 text-2xs text-doom-red\"\n >\n <AlertIcon aria-hidden className=\"mt-px h-3 w-3 shrink-0\" />\n <span className=\"min-w-0 flex-1\">{syncError}</span>\n <Button variant=\"ghost\" size=\"xs\" className=\"h-auto min-h-0 px-1 py-0 text-2xs\" onClick={onDismissError}>\n dismiss\n </Button>\n </div>\n )}\n\n {forceRequired ? (\n <div\n data-testid=\"git-push-force-confirm\"\n className=\"flex min-w-0 flex-wrap items-center gap-2 rounded-md border border-doom-edge-yellow bg-doom-tint-yellow px-2.5 py-2\"\n >\n <span className=\"min-w-0 flex-1 text-xs text-doom-hi\">\n The remote branch has commits yours replaced, usually after a rebase. Force push with lease? It is refused\n if the remote holds commits you never fetched and integrated.\n </span>\n <Button variant=\"danger-outline\" size=\"xs\" data-testid=\"git-push-force\" disabled={busy} onClick={onForcePush}>\n force push\n </Button>\n <Button variant=\"ghost\" size=\"xs\" data-testid=\"git-push-force-cancel\" onClick={onDismissError}>\n cancel\n </Button>\n </div>\n ) : null}\n\n {changes?.rebase === undefined ? null : (\n <div\n data-testid=\"git-rebase-banner\"\n className=\"flex min-w-0 flex-col gap-1.5 rounded-md border border-doom-edge-red bg-doom-tint-red px-2.5 py-2\"\n >\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <StatusBadge tone=\"error\" size=\"xs\">\n rebase paused\n </StatusBadge>\n <span className=\"text-xs text-doom-hi\">\n {changes.rebase.conflicts.length === 0\n ? 'git stopped the rebase'\n : `conflicts in ${String(changes.rebase.conflicts.length)} ${changes.rebase.conflicts.length === 1 ? 'file' : 'files'}`}\n </span>\n </span>\n {changes.rebase.conflicts.length === 0 ? null : (\n <ul className=\"flex flex-col gap-0.5 pl-1\">\n {changes.rebase.conflicts.map((file) => (\n <li key={file} className=\"truncate font-mono text-2xs text-doom-dim\">\n {file}\n </li>\n ))}\n </ul>\n )}\n <span className=\"flex flex-wrap items-center gap-1.5\">\n <Button variant=\"primary\" size=\"xs\" data-testid=\"git-rebase-ask-agent\" disabled={busy} onClick={onAskAgent}>\n ask agent to resolve\n </Button>\n <Button\n variant=\"danger-outline\"\n size=\"xs\"\n data-testid=\"git-rebase-abort\"\n disabled={busy}\n onClick={() => onSync('abort-rebase')}\n >\n abort rebase\n </Button>\n <span className=\"text-2xs text-doom-faint\">abort discards any conflict resolution in progress</span>\n </span>\n </div>\n )}\n </div>\n );\n}\n","/**\n * The review tab, drawn from what it is handed: the sync header, the changed\n * files on the left, every diff stacked on the right, and one footer that\n * sends every comment as a single message.\n *\n * DESIGN PATTERNS:\n * - Like a pull request's file view. Picking a file in the list scrolls to it;\n * each file's header stays pinned while its diff scrolls past.\n * - The first files load at once and the rest load when opened, so a branch\n * with hundreds of changed files does not fetch hundreds of diffs up front.\n * - A comment is drawn under the line it is about, on the side it is about.\n * The open draft sits in the same place, so writing happens in context.\n * - Only UI state lives here (the open draft, which files are collapsed, which\n * is active). Data and comments come in as props; the panel owns fetching.\n *\n * AVOID:\n * - Clearing comments here. The owner clears them once the host took the send.\n */\nimport {\n Button,\n ChevronDownIcon,\n ChevronRightIcon,\n CloseIcon,\n DiffView,\n EmptyState,\n MessageIcon,\n ReviewCommentDraft,\n Spinner,\n reviewCommentAnchor,\n type DiffRow,\n type DiffSelection,\n type ReviewComment,\n} from '@agimon-ai/doompi-web-components';\nimport { useEffect, useState } from 'react';\n\nimport type { GitReviewFileDiff, GitReviewFileEntry, GitReviewSummary } from '../../../../../types/gitReview';\nimport { GitReviewBrowser } from './GitReviewBrowser';\nimport { GitSyncBar, type GitSyncBarProps } from './GitSyncBar';\n\n/** How many files load their diff before the reader asks for more. */\nexport const EAGER_FILES = 20;\n\nconst NO_FILES: readonly GitReviewFileEntry[] = [];\n\nexport type ReviewSummaryState =\n | { state: 'loading' }\n | { state: 'error'; error: string }\n | { state: 'ready'; summary: GitReviewSummary };\n\nexport type ReviewFileState =\n | { state: 'loading' }\n | { state: 'error'; error: string }\n | { state: 'ready'; diff: GitReviewFileDiff };\n\nexport interface GitReviewViewProps {\n sync: GitSyncBarProps;\n summary: ReviewSummaryState;\n files: Readonly<Record<string, ReviewFileState | undefined>>;\n comments: readonly ReviewComment[];\n onLoadFile: (path: string) => void;\n onAddComment: (comment: Omit<ReviewComment, 'id'>) => void;\n onRemoveComment: (id: string) => void;\n onSendReview: () => void;\n onDiscard: () => void;\n /** Why the last send did not reach the session; the comments are still here. */\n sendError?: string;\n /** Opens with this draft already raised. Stories use it; the panel never does. */\n initialDraft?: { path: string; selection: DiffSelection };\n}\n\n/** Stable, URL-safe element id for one file's section. */\nfunction sectionId(index: number): string {\n return `git-review-file-${String(index)}`;\n}\n\nfunction sideOf(row: DiffRow): 'old' | 'new' {\n return row.marker === '-' ? 'old' : 'new';\n}\n\nexport function GitReviewView({\n sync,\n summary,\n files,\n comments,\n onLoadFile,\n onAddComment,\n onRemoveComment,\n onSendReview,\n onDiscard,\n sendError,\n initialDraft,\n}: GitReviewViewProps) {\n const entries = summary.state === 'ready' ? summary.summary.files : NO_FILES;\n // A file is open by default when it is among the first EAGER_FILES; the\n // reader's own toggles override that, so a list that arrives later still\n // opens exactly the files that load.\n const [openOverride, setOpenOverride] = useState<Readonly<Record<string, boolean>>>({});\n const [picked, setPicked] = useState<string | undefined>();\n const activePath = picked ?? entries[0]?.path;\n const [draft, setDraft] = useState<{ path: string; selection: DiffSelection } | undefined>(initialDraft);\n\n // The eager slice loads as soon as the list arrives; anything already asked\n // for is left alone, so a re-render never refetches.\n useEffect(() => {\n for (const file of entries.slice(0, EAGER_FILES)) {\n if (files[file.path] === undefined) onLoadFile(file.path);\n }\n }, [entries, files, onLoadFile]);\n\n const commentCounts: Record<string, number> = {};\n for (const comment of comments) commentCounts[comment.path] = (commentCounts[comment.path] ?? 0) + 1;\n\n const isOpen = (path: string, index: number): boolean => openOverride[path] ?? index < EAGER_FILES;\n\n const open = (path: string): void => {\n setOpenOverride((current) => (current[path] === true ? current : { ...current, [path]: true }));\n if (files[path] === undefined) onLoadFile(path);\n };\n\n const pick = (path: string): void => {\n setPicked(path);\n open(path);\n const index = entries.findIndex((file) => file.path === path);\n globalThis.document?.getElementById(sectionId(index))?.scrollIntoView({ block: 'start' });\n };\n\n const toggle = (path: string, index: number): void => {\n if (isOpen(path, index)) setOpenOverride((current) => ({ ...current, [path]: false }));\n else open(path);\n };\n\n const submitDraft = (body: string): void => {\n if (draft === undefined) return;\n onAddComment({\n path: draft.path,\n relPath: draft.path,\n side: draft.selection.side,\n startLine: draft.selection.startLine,\n endLine: draft.selection.endLine,\n snippet: draft.selection.snippet,\n body: body.trim(),\n });\n setDraft(undefined);\n };\n\n return (\n <div data-testid=\"git-review-panel\" className=\"flex min-h-0 flex-1 flex-col\">\n <GitSyncBar\n {...sync}\n {...(summary.state === 'ready' && summary.summary.mergeBase !== undefined\n ? { mergeBase: summary.summary.mergeBase }\n : {})}\n />\n\n {summary.state === 'loading' ? (\n <div data-testid=\"git-review-loading\" className=\"flex flex-1 items-start gap-2 px-4 py-6\">\n <Spinner className=\"h-3 w-3 text-doom-faint\" label=\"reading changes\" />\n <span className=\"text-xs text-doom-dim\">reading changes…</span>\n </div>\n ) : summary.state === 'error' ? (\n <p role=\"alert\" data-testid=\"git-review-error\" className=\"flex-1 px-4 py-6 text-xs text-doom-red\">\n {summary.error}\n </p>\n ) : !summary.summary.repository ? (\n <EmptyState\n data-testid=\"git-review-no-repository\"\n className=\"px-4 py-8\"\n title=\"not a git checkout\"\n description=\"this session's folder is not inside a git repository, so there is nothing to review.\"\n />\n ) : entries.length === 0 ? (\n <EmptyState\n data-testid=\"git-review-empty\"\n className=\"px-4 py-8\"\n title=\"no changes\"\n description={\n summary.summary.base === undefined\n ? 'nothing uncommitted in this checkout.'\n : `nothing differs from ${summary.summary.base}, committed or not.`\n }\n />\n ) : (\n <div className=\"flex min-h-0 flex-1\">\n <GitReviewBrowser\n files={entries}\n commentCounts={commentCounts}\n onPick={pick}\n {...(activePath === undefined ? {} : { activePath })}\n />\n <div data-testid=\"git-review-diffs\" className=\"min-h-0 min-w-0 flex-1 overflow-y-auto\">\n {summary.summary.truncated ? (\n <p className=\"px-4 pt-2 text-2xs text-doom-faint\">\n more files changed than the review lists; the rest are left out.\n </p>\n ) : null}\n {entries.map((file, index) => (\n <FileSection\n key={file.path}\n id={sectionId(index)}\n entry={file}\n state={files[file.path]}\n collapsed={!isOpen(file.path, index)}\n comments={comments.filter((comment) => comment.path === file.path)}\n draft={draft?.path === file.path ? draft.selection : undefined}\n onToggle={() => toggle(file.path, index)}\n onSelect={(selection) => {\n setPicked(file.path);\n setDraft({ path: file.path, selection });\n }}\n onSubmitDraft={submitDraft}\n onCancelDraft={() => setDraft(undefined)}\n onRemoveComment={onRemoveComment}\n onRetry={() => onLoadFile(file.path)}\n />\n ))}\n </div>\n </div>\n )}\n\n <div\n data-testid=\"git-review-footer\"\n className=\"flex shrink-0 flex-wrap items-center gap-2 border-t border-doom-border-soft bg-doom-panel px-3 py-2 sm:px-[26px]\"\n >\n <MessageIcon aria-hidden className=\"h-3 w-3 text-doom-faint\" />\n <span data-testid=\"git-review-comment-count\" className=\"text-xs text-doom-dim\">\n {comments.length === 0\n ? 'no comments yet: select lines or click a line number'\n : `${String(comments.length)} ${comments.length === 1 ? 'comment' : 'comments'}`}\n </span>\n <span className=\"min-w-0 flex-1\" />\n {sendError === undefined ? null : (\n <span role=\"alert\" data-testid=\"git-review-send-error\" className=\"min-w-0 truncate text-2xs text-doom-red\">\n {sendError}\n </span>\n )}\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-testid=\"git-review-discard\"\n disabled={comments.length === 0}\n onClick={onDiscard}\n >\n discard\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n data-testid=\"git-review-send\"\n disabled={comments.length === 0}\n onClick={onSendReview}\n >\n send review\n </Button>\n </div>\n </div>\n );\n}\n\nconst STATUS_WORD: Readonly<Record<GitReviewFileEntry['status'], string>> = {\n added: 'added',\n modified: 'modified',\n deleted: 'deleted',\n untracked: 'new, untracked',\n conflicted: 'conflicted',\n};\n\n/** One file: a pinned header, then its diff with comments drawn under the lines they are about. */\nfunction FileSection({\n id,\n entry,\n state,\n collapsed,\n comments,\n draft,\n onToggle,\n onSelect,\n onSubmitDraft,\n onCancelDraft,\n onRemoveComment,\n onRetry,\n}: {\n id: string;\n entry: GitReviewFileEntry;\n state: ReviewFileState | undefined;\n collapsed: boolean;\n comments: readonly ReviewComment[];\n draft: DiffSelection | undefined;\n onToggle: () => void;\n onSelect: (selection: DiffSelection) => void;\n onSubmitDraft: (body: string) => void;\n onCancelDraft: () => void;\n onRemoveComment: (id: string) => void;\n onRetry: () => void;\n}) {\n const renderAfterRow = (row: DiffRow) => {\n const side = sideOf(row);\n const here = comments.filter(\n (comment) => (comment.side ?? 'new') === side && (comment.endLine ?? comment.startLine) === row.line,\n );\n const drafting = draft !== undefined && draft.side === side && draft.endLine === row.line;\n if (here.length === 0 && !drafting) return null;\n return (\n <div className=\"flex flex-col gap-1.5 border-y border-doom-border-soft bg-doom-bg px-2 py-1.5 whitespace-normal\">\n {here.map((comment) => (\n <div\n key={comment.id}\n data-testid={`git-review-comment-${comment.id}`}\n className=\"flex min-w-0 items-start gap-2 rounded-md border border-doom-border-soft bg-doom-panel px-2 py-1.5\"\n >\n <MessageIcon aria-hidden className=\"mt-0.5 h-3 w-3 shrink-0 text-doom-blue\" />\n <span className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"text-2xs text-doom-faint\">{reviewCommentAnchor(comment)}</span>\n <span className=\"text-xs whitespace-pre-wrap text-doom-hi\">{comment.body}</span>\n </span>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"remove comment\"\n title=\"remove comment\"\n onClick={() => onRemoveComment(comment.id)}\n >\n <CloseIcon className=\"h-3 w-3\" />\n </Button>\n </div>\n ))}\n {drafting ? (\n <div className=\"rounded-md border border-doom-border bg-doom-panel\">\n <ReviewCommentDraft\n snippet={draft.snippet}\n startLine={draft.startLine}\n endLine={draft.endLine}\n side={draft.side}\n testIdPrefix=\"git-review-comment\"\n onSubmit={onSubmitDraft}\n onCancel={onCancelDraft}\n />\n </div>\n ) : null}\n </div>\n );\n };\n\n return (\n <section id={id} data-testid={`git-review-file-${entry.path}`} className=\"border-b border-doom-border-soft\">\n <Button\n variant=\"ghost\"\n size=\"card\"\n aria-expanded={!collapsed}\n onClick={onToggle}\n className=\"sticky top-0 z-10 flex-row items-center gap-1.5 rounded-none border-b border-doom-border-soft bg-doom-rail px-3 py-1.5 hover:bg-doom-panel sm:px-4\"\n >\n {collapsed ? (\n <ChevronRightIcon aria-hidden className=\"h-3 w-3 shrink-0 text-doom-faint\" />\n ) : (\n <ChevronDownIcon aria-hidden className=\"h-3 w-3 shrink-0 text-doom-faint\" />\n )}\n <span className=\"min-w-0 flex-1 truncate font-mono text-xs font-bold text-doom-hi\">{entry.path}</span>\n <span className=\"shrink-0 text-2xs text-doom-faint\">{STATUS_WORD[entry.status]}</span>\n {comments.length === 0 ? null : (\n <span className=\"flex shrink-0 items-center gap-0.5 text-2xs text-doom-blue\">\n <MessageIcon aria-hidden className=\"h-2.5 w-2.5\" />\n {comments.length}\n </span>\n )}\n {entry.binary ? null : (\n <span className=\"shrink-0 text-2xs\">\n <span className=\"text-doom-green\">+{entry.added}</span>{' '}\n <span className=\"text-doom-red\">-{entry.removed}</span>\n </span>\n )}\n </Button>\n {collapsed ? null : state === undefined || state.state === 'loading' ? (\n <div className=\"flex items-center gap-2 px-4 py-3\">\n <Spinner className=\"h-3 w-3 text-doom-faint\" label={`loading ${entry.path}`} />\n <span className=\"text-2xs text-doom-faint\">loading diff…</span>\n </div>\n ) : state.state === 'error' ? (\n <div className=\"flex items-center gap-2 px-4 py-3\">\n <span role=\"alert\" className=\"text-2xs text-doom-red\">\n {state.error}\n </span>\n <Button variant=\"ghost\" size=\"xs\" onClick={onRetry}>\n retry\n </Button>\n </div>\n ) : state.diff.binary ? (\n <p className=\"px-4 py-3 text-2xs text-doom-faint\">binary file, not drawn</p>\n ) : state.diff.tooLarge ? (\n <p className=\"px-4 py-3 text-2xs text-doom-faint\">this diff is too large to draw here</p>\n ) : (\n <DiffView\n hunks={state.diff.hunks}\n testId={`git-review-diff-${id}`}\n onSelect={onSelect}\n renderAfterRow={renderAfterRow}\n className=\"py-1\"\n />\n )}\n </section>\n );\n}\n","import type { TransientTab, WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\n/**\n * The review tab: this session's changes against its base, the comments on\n * them, and the manual sync beside them.\n *\n * DESIGN PATTERNS:\n * - Opened from the '# diff' group as a transient tab, one per session.\n * - The hub's channel says when something changed (counts, base, a paused\n * rebase); the panel refetches the file list then, and each file's hunks\n * when it is opened. Nothing polls.\n * - Comments live in a session store and are cleared only after the host took\n * the message. Both messages go as `enqueue_automatic`, which queues behind a\n * running turn instead of failing.\n *\n * AVOID:\n * - Sending sync as a session frame. Sync is a channel command; the hub runs\n * it with the configured auth, one command per session.\n */\nimport { buildReviewPrompt } from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { gitChanges, requestGitSync } from '../_lib/gitChangesStore';\nimport { fetchReviewFile, fetchReviewSummary } from '../_lib/gitReviewApi';\nimport { clearReviewComments, addReviewComment, gitReview, removeReviewComment } from '../_lib/gitReviewStore';\nimport { conflictPrompt, deliverToAgent, reviewHeading } from '../_lib/gitReviewView';\nimport { GitReviewView, type ReviewFileState, type ReviewSummaryState } from './GitReviewView';\n\nconst REVIEW_TAB_ID = 'git-review';\n\nexport function reviewTab(): TransientTab {\n return { id: REVIEW_TAB_ID, label: 'review', panel: GitReviewPanel };\n}\n\nexport function GitReviewPanel({ sessionId, sendSessionFrame }: WebPluginSlotProps) {\n const activity = useStore(gitChanges.store, (state) => gitChanges.select(state, sessionId));\n const comments = useStore(gitReview.store, (state) => gitReview.select(state, sessionId).comments);\n const [summary, setSummary] = useState<ReviewSummaryState>({ state: 'loading' });\n const [files, setFiles] = useState<Record<string, ReviewFileState | undefined>>({});\n const [sendError, setSendError] = useState<string>();\n const [dismissedError, setDismissedError] = useState<string>();\n const changes = activity.changes;\n\n // What the hub reported, reduced to the facts that move the file list. A new\n // value means the list and every loaded hunk may be stale.\n const fingerprint = JSON.stringify([\n changes?.branch,\n changes?.base,\n changes?.added,\n changes?.removed,\n changes?.files,\n changes?.rebase?.conflicts.length,\n ]);\n\n useEffect(() => {\n if (sessionId === null) return;\n const controller = new AbortController();\n fetchReviewSummary(sessionId, controller.signal)\n .then((result) => {\n if (controller.signal.aborted) return;\n setSummary(result.ok ? { state: 'ready', summary: result.summary } : { state: 'error', error: result.error });\n setFiles({});\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted) return;\n setSummary({\n state: 'error',\n error: error instanceof Error ? error.message : 'The changes could not be read.',\n });\n });\n return () => controller.abort();\n }, [sessionId, fingerprint]);\n\n const loadFile = useCallback(\n (path: string): void => {\n if (sessionId === null) return;\n setFiles((current) => ({ ...current, [path]: { state: 'loading' } }));\n const settle = (state: ReviewFileState): void => setFiles((current) => ({ ...current, [path]: state }));\n fetchReviewFile(sessionId, path)\n .then((result) =>\n settle(result.ok ? { state: 'ready', diff: result.diff } : { state: 'error', error: result.error }),\n )\n .catch((error: unknown) =>\n settle({ state: 'error', error: error instanceof Error ? error.message : 'The diff could not be read.' }),\n );\n },\n [sessionId],\n );\n\n if (sessionId === null) return null;\n\n const branch = summary.state === 'ready' ? summary.summary.branch : changes?.branch;\n const base = summary.state === 'ready' ? summary.summary.base : changes?.base;\n const error = activity.error === dismissedError ? undefined : activity.error;\n\n const send = (message: string, onSent?: () => void): void => {\n const failure = deliverToAgent(sendSessionFrame, sessionId, message);\n setSendError(failure);\n if (failure === undefined) onSent?.();\n };\n\n return (\n <GitReviewView\n sync={{\n ...(changes === undefined ? {} : { changes }),\n ...(activity.pending === undefined ? {} : { pending: activity.pending }),\n ...(error === undefined ? {} : { error }),\n ...(activity.errorTarget === undefined || error === undefined ? {} : { errorTarget: activity.errorTarget }),\n onSync: (action) => requestGitSync(sessionId, action),\n onForcePush: () => requestGitSync(sessionId, 'push', true),\n onAskAgent: () => send(conflictPrompt(branch, changes?.rebase?.conflicts ?? [])),\n onDismissError: () => setDismissedError(activity.error),\n }}\n summary={summary}\n files={files}\n comments={comments}\n onLoadFile={loadFile}\n onAddComment={(comment) => addReviewComment(sessionId, comment)}\n onRemoveComment={(id) => removeReviewComment(sessionId, id)}\n onSendReview={() =>\n send(buildReviewPrompt(comments, reviewHeading(comments.length, branch, base)), () =>\n clearReviewComments(sessionId),\n )\n }\n onDiscard={() => clearReviewComments(sessionId)}\n {...(sendError === undefined ? {} : { sendError })}\n />\n );\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\n/**\n * The '# git' group's branch row: this session's code change against its base.\n *\n * DESIGN PATTERNS:\n * - One lane, branch and `+A -R`. Files, base, upstream and a paused rebase live\n * in the review tab's header, which this lane opens.\n * - Stays clickable at zero, because the review tab is also where pull, push\n * and rebase live.\n * - Reads the focused session's checkout, whether it is a worktree or not.\n *\n * AVOID:\n * - Doing work here. This section reports and opens the tab.\n */\nimport { Button, Spinner } from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\n\nimport { reviewTab } from '../../_components/GitReviewPanel';\nimport { gitChanges } from '../../_lib/gitChangesStore';\n\nexport function DiffActivitySection({ sessionId, openTransientTab }: WebPluginSlotProps) {\n const session = useStore(gitChanges.store, (state) => gitChanges.select(state, sessionId));\n const changes = session.changes;\n\n if (sessionId === null || changes === undefined) return null;\n\n const zero = changes.added === 0 && changes.removed === 0;\n const against = changes.base === undefined ? 'uncommitted' : `vs ${changes.base}`;\n return (\n <div className=\"flex min-w-0 items-center gap-2 px-1\">\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-testid=\"activity-diff-changes\"\n aria-label={`review ${changes.branch ?? 'detached HEAD'} changes: ${String(changes.added)} added, ${String(changes.removed)} removed ${against}`}\n title={`${String(changes.files)} ${changes.files === 1 ? 'file' : 'files'} ${against}`}\n className={`min-w-0 flex-1 shrink gap-1.5 px-1 text-xs font-bold ${zero ? 'text-doom-faint' : ''}`}\n onClick={() => openTransientTab(reviewTab())}\n >\n <span className=\"min-w-0 flex-1 truncate text-left text-doom-hi\">{changes.branch ?? 'detached HEAD'}</span>\n <span className={zero ? '' : 'text-doom-green'}>+{changes.added}</span>\n <span className={zero ? '' : 'text-doom-red'}>-{changes.removed}</span>\n </Button>\n {session.pending === undefined ? null : (\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <Spinner className=\"h-3 w-3 shrink-0 text-doom-faint\" label={session.pending} />\n <span className=\"min-w-0 truncate text-xs text-doom-dim\">{session.pending}</span>\n </span>\n )}\n </div>\n );\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\n/**\n * The '# git' group's body in the activity dock.\n *\n * DESIGN PATTERNS:\n * - The focused checkout's branch and diff stay visible, even with no child worktrees.\n * - One line per worktree, the same rule the runners rail follows: enough to\n * notice it, not enough to work with it. The group's own name opens the tab\n * that has room.\n * - Idle still shows the launcher. A repository with no worktrees is the state\n * where someone most wants to make one.\n *\n * AVOID:\n * - Doing work here. This section reports and launches; the panel and the tool\n * own everything else.\n */\nimport { Button, Dot, Spinner, StatusBadge } from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\n\nimport type { WorktreeView } from '../../../../../../types/webWorktrees';\nimport { worktreesTab } from '../../_components/WorktreesPanel';\nimport { worktreeActivity } from '../../_lib/worktreesActivityStore';\nimport { DiffActivitySection } from './DiffActivitySection';\n\nexport function WorktreesActivitySection(props: WebPluginSlotProps) {\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <DiffActivitySection {...props} />\n <WorktreesSummary {...props} />\n </div>\n );\n}\n\nfunction WorktreesSummary({ sessionId, openTransientTab }: WebPluginSlotProps) {\n const session = useStore(worktreeActivity.store, (state) => worktreeActivity.select(state, sessionId));\n // A top-level worktree can include itself in the channel's list. Its branch is already above.\n const worktrees = session.worktrees.filter((worktree) => worktree.sessionId !== sessionId);\n\n if (worktrees.length === 0 && session.pending === undefined) {\n return (\n <div className=\"flex items-center gap-2 px-1\">\n <p data-testid=\"activity-summary-git\" className=\"px-1 text-xs text-doom-faint\">\n idle\n </p>\n {sessionId === null ? null : (\n <Button\n variant=\"link\"\n size=\"xs\"\n data-testid=\"activity-git-create\"\n className=\"px-0\"\n onClick={() => openTransientTab(worktreesTab())}\n >\n create a worktree\n </Button>\n )}\n </div>\n );\n }\n\n return (\n <div data-testid=\"activity-git-worktrees\" className=\"flex flex-col gap-0.5\">\n {session.pending === undefined ? null : (\n <span className=\"flex min-w-0 items-center gap-1.5 px-1\">\n <Spinner className=\"h-3 w-3 shrink-0 text-doom-faint\" label={session.pending} />\n <span className=\"min-w-0 truncate text-xs text-doom-dim\">{session.pending}</span>\n </span>\n )}\n {worktrees.map((worktree: WorktreeView) => (\n <Button\n key={worktree.id}\n variant=\"ghost\"\n size=\"card\"\n data-testid={`activity-git-worktree-${worktree.id}`}\n className=\"min-w-0 gap-1.5 px-1\"\n onClick={() => openTransientTab(worktreesTab())}\n >\n <span className=\"flex w-full min-w-0 items-center gap-1.5\">\n <Dot tone={worktree.orphaned ? 'red' : worktree.sessionId === null ? 'muted' : 'blue'} />\n <span className=\"min-w-0 flex-1 truncate text-left text-xs font-bold text-doom-hi\">{worktree.branch}</span>\n {worktree.orphaned ? (\n <StatusBadge tone=\"error\" size=\"xs\">\n orphaned\n </StatusBadge>\n ) : null}\n {worktree.unowned ? (\n <StatusBadge tone=\"info\" size=\"xs\">\n unowned\n </StatusBadge>\n ) : null}\n </span>\n </Button>\n ))}\n </div>\n );\n}\n","import { defineFill } from '@agimon-ai/doompi-core/web';\n\nimport { WorktreesActivitySection } from './_components/WorktreesActivitySection';\n\nexport default defineFill({ component: WorktreesActivitySection });\n","import { defineLeaderBinding } from '@agimon-ai/doompi-core/web';\n\nimport { reviewTab } from '../_components/GitReviewPanel';\n\nexport default defineLeaderBinding({\n path: [\n // The shared g prefix must keep the existing Goal group's label.\n { key: 'g', label: 'goal' },\n { key: 'd', label: 'diff', detail: 'review this checkout’s changes' },\n ],\n run: (context) => context.openTransientTab(reviewTab()),\n});\n","import type { WebPluginRuntime } from '@agimon-ai/doompi-core/web';\n\nimport { startGitChangesRuntime } from '../../_lib/gitChangesStore';\nimport { startWorktreeRuntime } from '../../_lib/worktreesActivityStore';\n\n/** Binds both hub channels' senders: worktrees, and this session's diff and sync. */\nexport default function startGitRuntime(runtime: WebPluginRuntime): () => void {\n const stopWorktrees = startWorktreeRuntime(runtime);\n const stopChanges = startGitChangesRuntime(runtime);\n return () => {\n stopChanges();\n stopWorktrees();\n };\n}\n","import { defineWebLifecycle } from '@agimon-ai/doompi-core/web';\n\nimport contribution from './_lib/start.web';\n\nexport default defineWebLifecycle(contribution);\n","import type { ToolMessageRenderProps } from '@agimon-ai/doompi-core/web';\nimport { MessageItem, MessageItemBody, MessageItemHeader, toolTone } from '@agimon-ai/doompi-web-components';\n\nconst ACTION_LABEL: Readonly<Record<string, string>> = {\n spawn_worktree: 'Create worktree',\n close_worktree: 'Close worktree',\n list: 'List worktrees',\n status: 'Worktree status',\n merge: 'Merge worktree',\n prune: 'Prune worktrees',\n send: 'Message worktree',\n messages: 'Read worktree messages',\n};\n\n/**\n * The timeline item for `run_worktree`.\n *\n * DESIGN PATTERNS:\n * - Built on MessageItem, like every other tool renderer in the cockpit. That\n * is what gives it the shared collapse toggle and the RUNNING/OK/ERROR badge\n * rather than a hand-rolled ellipsis that never resolves.\n * - The action and its subject go in the heading because that is what a reader\n * scanning a transcript needs: \"close_worktree a1b2c3d4\" answers the question\n * the raw JSON arguments make them decode.\n * - A create takes as long as the cockpit needs to start a session, and the\n * tool streams each phase into `output`, so the body is where the wait is\n * visible.\n */\nexport function RunWorktreeToolMessage({ args, output, running, isError }: ToolMessageRenderProps) {\n const action = typeof args.action === 'string' ? args.action : '';\n const subject = typeof args.branch === 'string' ? args.branch : typeof args.id === 'string' ? args.id : '';\n\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={output !== ''}>\n <MessageItemHeader title={ACTION_LABEL[action] ?? 'Worktree'}>\n {subject === '' ? null : <span className=\"min-w-0 truncate text-doom-dim\">{subject}</span>}\n </MessageItemHeader>\n {output === '' ? null : (\n <MessageItemBody>\n <pre className={`whitespace-pre-wrap text-xs ${isError ? 'text-doom-red' : 'text-doom-dim'}`}>{output}</pre>\n </MessageItemBody>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/doompi-core/web';\n\nimport { RunWorktreeToolMessage } from './_components/RunWorktreeToolMessage';\n\nexport default defineToolRenderer({ message: RunWorktreeToolMessage });\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/doompi-core/web';\n\nimport fillGitNewSession from '../src/extensions/workspaces/(frontend)/fill/GitNewSession.new-session.web';\nimport repositorySettingsPanelGit from '../src/extensions/workspaces/(frontend)/repository-settings-panel/git.web';\nimport activityGroupGit from '../src/extensions/workspaces/sessions/(frontend)/activity-group/git.web';\nimport channelGitChanges from '../src/extensions/workspaces/sessions/(frontend)/channel/gitChanges.web';\nimport channelGitWorktrees from '../src/extensions/workspaces/sessions/(frontend)/channel/gitWorktrees.web';\nimport fillWorktree from '../src/extensions/workspaces/sessions/(frontend)/fill/Worktree.session-menu.web';\nimport fillWorktreeCreate from '../src/extensions/workspaces/sessions/(frontend)/fill/WorktreeCreate.overlay.web';\nimport fillWorktrees from '../src/extensions/workspaces/sessions/(frontend)/fill/Worktrees.activity.git.web';\nimport leaderReview from '../src/extensions/workspaces/sessions/(frontend)/leader/review.web';\nimport lifecycleStart from '../src/extensions/workspaces/sessions/(frontend)/lifecycle/start.web';\nimport toolRunWorktree from '../src/extensions/workspaces/sessions/(frontend)/tool/runWorktree.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'git',\n workspace: {\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'new-session', id: 'git-new-session' }, fillGitNewSession)]; },\n get repositorySettingsPanel(): WebPluginContributions['repositorySettingsPanel'] { return repositorySettingsPanelGit; },\n },\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'git' }, activityGroupGit)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'git_changes' }, channelGitChanges), via({ channel: 'git_worktrees' }, channelGitWorktrees)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'session-menu', id: 'worktree' }, fillWorktree), via({ slot: 'overlay', id: 'worktree-create' }, fillWorktreeCreate), via({ slot: 'activity.git', id: 'worktrees' }, fillWorktrees)]; },\n get leaderBindings(): WebPluginContributions['leaderBindings'] { return [via({ id: 'git.review' }, leaderReview)]; },\n get start(): WebPluginContributions['start'] { return lifecycleStart; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['run_worktree'] }, toolRunWorktree)]; },\n },\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { b as createWorktreeGit, t as createWorktreeOperations } from "./worktreeOperations-BrWG2muV.mjs";
|
|
2
|
+
//#region src/services/extensionService/index.ts
|
|
3
|
+
var DefaultGitExtensionService = class {
|
|
4
|
+
async execute() {
|
|
5
|
+
return {
|
|
6
|
+
message: "Show git worktrees owned by this session",
|
|
7
|
+
level: "info"
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/services/gitDependencies/index.ts
|
|
13
|
+
function createGitDependencies(overrides = {}) {
|
|
14
|
+
return {
|
|
15
|
+
service: overrides.service ?? new DefaultGitExtensionService(),
|
|
16
|
+
operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() })
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { DefaultGitExtensionService as n, createGitDependencies as t };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=gitDependencies-CtVubYvU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitDependencies-CtVubYvU.mjs","names":[],"sources":["../src/services/extensionService/index.ts","../src/services/gitDependencies/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n","import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":";;AAGA,IAAa,6BAAb,MAAuE;CACrE,MAAM,UAAuC;EAC3C,OAAO;GAAE,SAAS;GAA4C,OAAO;EAAO;CAC9E;AACF;;;ACDA,SAAgB,sBAAsB,YAA+C,CAAC,GAA6B;CACjH,OAAO;EACL,SAAS,UAAU,WAAW,IAAI,2BAA2B;EAC7D,YAAY,UAAU,cAAc,yBAAyB,EAAE,KAAK,kBAAkB,EAAE,CAAC;CAC3F;AACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_worktreeOperations = require("./worktreeOperations-BYmVU0UV.cjs");
|
|
2
|
+
//#region src/services/extensionService/index.ts
|
|
3
|
+
var DefaultGitExtensionService = class {
|
|
4
|
+
async execute() {
|
|
5
|
+
return {
|
|
6
|
+
message: "Show git worktrees owned by this session",
|
|
7
|
+
level: "info"
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/services/gitDependencies/index.ts
|
|
13
|
+
function createGitDependencies(overrides = {}) {
|
|
14
|
+
return {
|
|
15
|
+
service: overrides.service ?? new DefaultGitExtensionService(),
|
|
16
|
+
operations: overrides.operations ?? require_worktreeOperations.createWorktreeOperations({ git: require_worktreeOperations.createWorktreeGit() })
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
Object.defineProperty(exports, "DefaultGitExtensionService", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function() {
|
|
23
|
+
return DefaultGitExtensionService;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(exports, "createGitDependencies", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function() {
|
|
29
|
+
return createGitDependencies;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=gitDependencies-Dqsz2HjK.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitDependencies-Dqsz2HjK.cjs","names":["createWorktreeOperations","createWorktreeGit"],"sources":["../src/services/extensionService/index.ts","../src/services/gitDependencies/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n","import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":";;AAGA,IAAa,6BAAb,MAAuE;CACrE,MAAM,UAAuC;EAC3C,OAAO;GAAE,SAAS;GAA4C,OAAO;EAAO;CAC9E;AACF;;;ACDA,SAAgB,sBAAsB,YAA+C,CAAC,GAA6B;CACjH,OAAO;EACL,SAAS,UAAU,WAAW,IAAI,2BAA2B;EAC7D,YAAY,UAAU,cAAcA,2BAAAA,yBAAyB,EAAE,KAAKC,2BAAAA,kBAAkB,EAAE,CAAC;CAC3F;AACF"}
|