@dendelion/paper-camp 0.24.0 → 0.26.0
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/dist/app/assets/{index-Ddz2TPW1.js → index-CqDZ80wA.js} +3 -3
- package/dist/app/assets/{index-Ddz2TPW1.js.map → index-CqDZ80wA.js.map} +1 -1
- package/dist/app/assets/index-DAhfAB9y.js +3 -0
- package/dist/app/assets/index-DAhfAB9y.js.map +1 -0
- package/dist/app/assets/index-DYGnWiFG.js +2 -0
- package/dist/app/assets/index-DYGnWiFG.js.map +1 -0
- package/dist/app/assets/index-DuhmLhzz.js +2 -0
- package/dist/app/assets/{index-CR8PI9q6.js.map → index-DuhmLhzz.js.map} +1 -1
- package/dist/app/assets/index-HixYRYWW.js +2 -0
- package/dist/app/assets/index-HixYRYWW.js.map +1 -0
- package/dist/app/assets/index-VoRTCwB6.js +2 -0
- package/dist/app/assets/{index-BY8Yo_l0.js.map → index-VoRTCwB6.js.map} +1 -1
- package/dist/app/assets/{index-rxWn42R9.js → index-X5ikcKAy.js} +3 -3
- package/dist/app/assets/{index-rxWn42R9.js.map → index-X5ikcKAy.js.map} +1 -1
- package/dist/app/assets/{index-C1ORGbU3.js → index-sqaNs4DX.js} +2 -2
- package/dist/app/assets/{index-C1ORGbU3.js.map → index-sqaNs4DX.js.map} +1 -1
- package/dist/app/assets/main-BZd2c99C.css +1 -0
- package/dist/app/assets/main-Ceiva0Al.js +425 -0
- package/dist/app/assets/main-Ceiva0Al.js.map +1 -0
- package/dist/app/assets/{sidebar-section-Cqk2bPNP.js → sidebar-section-CW3WaioH.js} +2 -2
- package/dist/app/assets/{sidebar-section-Cqk2bPNP.js.map → sidebar-section-CW3WaioH.js.map} +1 -1
- package/dist/app/index.html +2 -2
- package/dist/app/toolbar.js +1063 -1043
- package/dist/app/toolbar.js.map +1 -1
- package/dist/chunks/dev-port.BHJn90Pm.js +52 -0
- package/dist/chunks/dev-port.BHJn90Pm.js.map +1 -0
- package/dist/chunks/{phase-progress.DvktSTIz.js → machine-registry.DF3kTKHr.js} +1450 -1350
- package/dist/chunks/machine-registry.DF3kTKHr.js.map +1 -0
- package/dist/cli/index.js +7704 -7098
- package/dist/cli/index.js.map +1 -1
- package/dist/core/desk-discovery/evidence.d.ts +21 -0
- package/dist/core/desk-discovery/evidence.d.ts.map +1 -0
- package/dist/core/desk-discovery/evidence.test.d.ts +2 -0
- package/dist/core/desk-discovery/evidence.test.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +123 -114
- package/dist/core/machine-registry/index.d.ts +2 -0
- package/dist/core/machine-registry/index.d.ts.map +1 -0
- package/dist/core/machine-registry/machine-registry.d.ts +39 -0
- package/dist/core/machine-registry/machine-registry.d.ts.map +1 -0
- package/dist/core/machine-registry/machine-registry.test.d.ts +2 -0
- package/dist/core/machine-registry/machine-registry.test.d.ts.map +1 -0
- package/dist/core/parse/schemas.d.ts +8 -0
- package/dist/core/parse/schemas.d.ts.map +1 -1
- package/dist/core/rate-limit.d.ts +8 -0
- package/dist/core/rate-limit.d.ts.map +1 -1
- package/dist/core/stats.d.ts +2 -2
- package/dist/core/stats.d.ts.map +1 -1
- package/dist/core/tailnet.d.ts +14 -0
- package/dist/core/tailnet.d.ts.map +1 -0
- package/dist/core/tailnet.test.d.ts +2 -0
- package/dist/core/tailnet.test.d.ts.map +1 -0
- package/dist/types/index.d.ts +24 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +19 -17
- package/dist/types/index.js.map +1 -1
- package/dist/vite/index.js +44 -51
- package/dist/vite/index.js.map +1 -1
- package/dist/vite/proxy.d.ts +2 -1
- package/dist/vite/proxy.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/app/assets/index-B5TCF8_a.js +0 -2
- package/dist/app/assets/index-B5TCF8_a.js.map +0 -1
- package/dist/app/assets/index-BY8Yo_l0.js +0 -2
- package/dist/app/assets/index-BxRIu8zx.js +0 -3
- package/dist/app/assets/index-BxRIu8zx.js.map +0 -1
- package/dist/app/assets/index-C3R9IAt7.js +0 -2
- package/dist/app/assets/index-C3R9IAt7.js.map +0 -1
- package/dist/app/assets/index-CR8PI9q6.js +0 -2
- package/dist/app/assets/main-DkQCGPBX.js +0 -425
- package/dist/app/assets/main-DkQCGPBX.js.map +0 -1
- package/dist/app/assets/main-o2BbWpF4.css +0 -1
- package/dist/chunks/dev-port.DgdJE2bY.js +0 -43
- package/dist/chunks/dev-port.DgdJE2bY.js.map +0 -1
- package/dist/chunks/phase-progress.DvktSTIz.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-B5TCF8_a.js","sources":["../../../src/app/services/system/merge-policy-api.ts","../../../src/app/features/settings/constants.ts","../../../src/app/features/settings/components/merge-policy-section.tsx","../../../src/app/features/settings/hooks/use-settings-page.ts","../../../src/app/features/settings/hooks/use-setup-section.ts","../../../src/app/features/settings/hooks/use-sign-in-action.ts","../../../src/app/features/settings/components/connect-action-view.tsx","../../../src/app/features/settings/components/relay-fallback-guide.tsx","../../../src/app/features/settings/components/sign-in-action.tsx","../../../src/app/features/settings/components/connection-row.tsx","../../../src/app/features/settings/components/setup-section.tsx","../../../src/app/features/settings/components/subjects-section.tsx","../../../src/app/features/settings/views/agent-task-row.tsx","../../../src/app/features/settings/views/agent-task-row-header.tsx","../../../src/app/features/settings/views/general-section.tsx","../../../src/app/features/settings/settings-page.tsx","../../../src/app/features/settings/components/settings-sidebar.tsx"],"sourcesContent":["import type { MergePolicyResult } from '@/types/index';\nimport { apiUrl } from '../api-base';\n\nexport const fetchMergePolicy = async (): Promise<MergePolicyResult | null> => {\n try {\n const response = await fetch(apiUrl('/api/merge-policy'));\n if (!response.ok) return null;\n return (await response.json()) as MergePolicyResult;\n } catch {\n return null;\n }\n};\n\nexport const applyMergePolicy = async (): Promise<MergePolicyResult | null> => {\n try {\n const response = await fetch(apiUrl('/api/merge-policy/apply'), { method: 'POST' });\n if (!response.ok) return null;\n return (await response.json()) as MergePolicyResult;\n } catch {\n return null;\n }\n};\n","import type { CapabilityStatus } from '@/types/index';\n\nexport const TASK_TYPE_KEYS = [\n 'phase',\n 'planDraft',\n 'ideaExtend',\n 'commitSuggest',\n 'feedback',\n 'codeReview',\n] as const;\nexport type TaskTypeKey = (typeof TASK_TYPE_KEYS)[number];\n\nexport const TASK_TYPE_LABELS: Record<TaskTypeKey, string> = {\n phase: 'Phase run',\n planDraft: 'Plan draft',\n ideaExtend: 'Idea extend',\n commitSuggest: 'Commit suggest',\n feedback: 'Scout chat',\n codeReview: 'Code review',\n};\n\nexport const CAPABILITY_STATUS_STAMP: Record<\n CapabilityStatus,\n { fill: string; text: string; label: string }\n> = {\n ok: { fill: 'rgba(143, 185, 150, 0.25)', text: '#5E8A66', label: 'Ready' },\n warn: { fill: 'rgba(212, 163, 115, 0.25)', text: '#A67B4F', label: 'Needs attention' },\n missing: { fill: 'rgba(201, 139, 139, 0.25)', text: '#6E3A3A', label: 'Missing' },\n};\n\nexport const MERGE_POLICY_STAMP: Record<'upToDate' | 'outdated', { fill: string; text: string }> = {\n upToDate: { fill: 'rgba(143, 185, 150, 0.25)', text: '#5E8A66' },\n outdated: { fill: 'rgba(212, 163, 115, 0.25)', text: '#A67B4F' },\n};\n\nexport const VERSION_STAMP_FILL = 'rgba(143, 185, 150, 0.25)';\n","import { applyMergePolicy, fetchMergePolicy } from '@/app/services/system';\nimport type { MergePolicy, MergePolicyResult } from '@/types/index';\nimport { Alert, Button, Card, Divider, Stamp, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\nimport { MERGE_POLICY_STAMP } from '../constants';\n\nconst RECOMMENDED: MergePolicy = {\n allowSquashMerge: true,\n allowMergeCommit: false,\n allowRebaseMerge: false,\n squashMergeCommitTitle: 'PR_TITLE',\n squashMergeCommitMessage: 'PR_BODY',\n};\n\nconst POLICY_ROWS: { key: keyof MergePolicy; label: string }[] = [\n { key: 'allowSquashMerge', label: 'Allow squash merge' },\n { key: 'allowMergeCommit', label: 'Allow merge commit' },\n { key: 'allowRebaseMerge', label: 'Allow rebase merge' },\n { key: 'squashMergeCommitTitle', label: 'Squash commit title' },\n { key: 'squashMergeCommitMessage', label: 'Squash commit message' },\n];\n\nfunction formatValue(value: boolean | string): string {\n return typeof value === 'boolean' ? (value ? 'Yes' : 'No') : value;\n}\n\nfunction matchesRecommended(policy: MergePolicy): boolean {\n return POLICY_ROWS.every((row) => policy[row.key] === RECOMMENDED[row.key]);\n}\n\ninterface PolicyRowProps {\n label: string;\n current: boolean | string;\n recommended: boolean | string;\n isLast: boolean;\n}\n\nconst PolicyRow = ({ label, current, recommended, isLast }: PolicyRowProps) => {\n const matches = current === recommended;\n return (\n <>\n <div className=\"flex items-center gap-3 pb-2 pt-2\">\n <span className=\"flex-1\">{label}</span>\n <span className={matches ? 'opacity-[0.65] font-normal' : 'font-semibold'}>\n {formatValue(current)}\n </span>\n {!matches && <span className=\"opacity-[0.45]\">→ {formatValue(recommended)}</span>}\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const MergePolicySection = () => {\n const [result, setResult] = useState<MergePolicyResult | null | undefined>(undefined);\n const [applying, setApplying] = useState(false);\n const { toast } = useToast();\n\n useEffect(() => {\n fetchMergePolicy().then(setResult);\n }, []);\n\n const handleApply = async () => {\n setApplying(true);\n const applied = await applyMergePolicy();\n setApplying(false);\n if (applied?.status === 'ok') {\n setResult(applied);\n toast({ title: 'Merge policy applied', variant: 'success' });\n } else {\n toast({\n title: 'Failed to apply merge policy',\n description: applied?.status === 'unavailable' ? applied.reason : undefined,\n variant: 'error',\n });\n }\n };\n\n const upToDate = result?.status === 'ok' && matchesRecommended(result.policy);\n\n return (\n <div>\n <div className=\"mb-6\">\n <h2 className=\"m-0\">Merge Policy</h2>\n <p className=\"opacity-50 mt-1\">\n Paper Camp's canonical policy: squash-only merges, with the commit title and body taken\n from the PR.\n </p>\n </div>\n {result === undefined && <p>Loading…</p>}\n {result === null && <Alert variant=\"warning\">Failed to load merge policy.</Alert>}\n {result?.status === 'unavailable' && <Alert variant=\"warning\">{result.reason}</Alert>}\n {result?.status === 'ok' && (\n <>\n <div className=\"flex items-center gap-3 mb-3\">\n <span className=\"font-medium\">{result.repo}</span>\n <Stamp\n size=\"small\"\n fillColor={\n upToDate ? MERGE_POLICY_STAMP.upToDate.fill : MERGE_POLICY_STAMP.outdated.fill\n }\n textColor={\n upToDate ? MERGE_POLICY_STAMP.upToDate.text : MERGE_POLICY_STAMP.outdated.text\n }\n >\n {upToDate ? 'Matches recommended policy' : 'Differs from recommended policy'}\n </Stamp>\n </div>\n <Card size=\"small\" texture=\"kraft\">\n {POLICY_ROWS.map((row, idx) => (\n <PolicyRow\n key={row.key}\n label={row.label}\n current={result.policy[row.key]}\n recommended={RECOMMENDED[row.key]}\n isLast={idx === POLICY_ROWS.length - 1}\n />\n ))}\n </Card>\n <div className=\"mt-4\">\n <Button size=\"small\" onClick={handleApply} disabled={applying || upToDate}>\n {applying ? 'Applying…' : 'Apply recommended policy'}\n </Button>\n </div>\n </>\n )}\n </div>\n );\n};\n","import { useProjectIdentity } from '@/app/hooks';\nimport { fetchConfig, saveConfig, uploadIcon } from '@/app/services/system';\nimport {\n type AgentConfig,\n DEFAULT_AGENTS,\n type DefaultAgentsMap,\n type PaperCampConfig,\n agentConfigsEqual,\n} from '@/types/index';\nimport { useToast } from '@dendelion/paper-ui';\nimport { useEffect, useRef, useState } from 'react';\nimport type { TaskTypeKey } from '../constants';\n\nexport const useSettingsPage = () => {\n const fileRef = useRef<HTMLInputElement>(null);\n const [config, setConfig] = useState<PaperCampConfig | null | undefined>(undefined);\n const { iconDataUri: fetchedIconDataUri, loading: identityLoading } = useProjectIdentity();\n const [uploadedIconDataUri, setUploadedIconDataUri] = useState<string | null>(null);\n const iconDataUri = uploadedIconDataUri ?? fetchedIconDataUri;\n const [uploading, setUploading] = useState(false);\n const [portInput, setPortInput] = useState('');\n const [nameInput, setNameInput] = useState('');\n const { toast } = useToast();\n\n useEffect(() => {\n fetchConfig().then((c) => {\n setConfig(c);\n if (c?.port !== undefined) setPortInput(String(c.port));\n if (c?.projectName !== undefined) setNameInput(c.projectName);\n });\n }, []);\n\n const handleSaveAgentConfig = async (key: TaskTypeKey, newEntry: AgentConfig) => {\n const current = config?.defaultAgents;\n const updated: DefaultAgentsMap = {\n phase: current?.phase ?? DEFAULT_AGENTS.phase,\n planDraft: current?.planDraft ?? DEFAULT_AGENTS.planDraft,\n ideaExtend: current?.ideaExtend ?? DEFAULT_AGENTS.ideaExtend,\n commitSuggest: current?.commitSuggest ?? DEFAULT_AGENTS.commitSuggest,\n feedback: current?.feedback ?? DEFAULT_AGENTS.feedback,\n codeReview: current?.codeReview ?? DEFAULT_AGENTS.codeReview,\n [key]: newEntry,\n };\n if (key === 'codeReview' && agentConfigsEqual(newEntry, updated.phase)) {\n toast({\n title: 'Failed to save',\n description: 'Code review must use a different model than Phase run.',\n variant: 'error',\n });\n return;\n }\n const { ok, error } = await saveConfig({ defaultAgents: updated });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, defaultAgents: updated } : prev));\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleSavePort = async () => {\n const port = Number(portInput);\n if (!config || !Number.isInteger(port) || port <= 0 || port === config.port) return;\n const { ok, error } = await saveConfig({ port });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, port } : prev));\n toast({\n title: 'Saved',\n description: 'Restart `paper-camp dev` to apply the new port.',\n variant: 'success',\n });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleToggleIntegration = async () => {\n if (!config) return;\n const next = !(config.integration?.toolbar?.enabled ?? true);\n const integration = {\n ...config.integration,\n toolbar: { ...config.integration?.toolbar, enabled: next },\n };\n const { ok, error } = await saveConfig({ integration });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, integration } : prev));\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleSaveName = async () => {\n const projectName = nameInput.trim();\n if (!config || !projectName || projectName === config.projectName) return;\n const { ok, error } = await saveConfig({ projectName });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, projectName } : prev));\n setNameInput(projectName);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploading(true);\n const reader = new FileReader();\n reader.onloadend = async () => {\n const dataUri = reader.result as string;\n const ok = await uploadIcon(dataUri);\n setUploading(false);\n if (ok) {\n setUploadedIconDataUri(dataUri);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', variant: 'error' });\n }\n };\n reader.readAsDataURL(file);\n };\n\n return {\n fileRef,\n config,\n identityLoading,\n iconDataUri,\n uploading,\n portInput,\n setPortInput,\n nameInput,\n setNameInput,\n handleSaveAgentConfig,\n handleSavePort,\n handleToggleIntegration,\n handleSaveName,\n handleFile,\n };\n};\n","import { connectService, fetchConfig, fetchConnections, saveConfig } from '@/app/services/system';\nimport type { ConnectionResult } from '@/types/index';\nimport { useToast } from '@dendelion/paper-ui';\nimport { useCallback, useEffect, useState } from 'react';\n\nexport const useSetupSection = () => {\n const [connections, setConnections] = useState<ConnectionResult[] | null>(null);\n const [loadFailed, setLoadFailed] = useState(false);\n const [reloadingId, setReloadingId] = useState<string | null>(null);\n const [connectingId, setConnectingId] = useState<string | null>(null);\n const [setupDismissed, setSetupDismissed] = useState(false);\n const { toast } = useToast();\n\n const applyConnections = useCallback((result: ConnectionResult[] | null) => {\n if (result === null) {\n setLoadFailed(true);\n return;\n }\n setLoadFailed(false);\n setConnections(result);\n }, []);\n\n useEffect(() => {\n fetchConnections().then(applyConnections);\n fetchConfig().then((c) => setSetupDismissed(c?.setupDismissed ?? false));\n }, [applyConnections]);\n\n const handleRecheck = async (id: string) => {\n setReloadingId(id);\n applyConnections(await fetchConnections());\n setReloadingId(null);\n };\n\n const handleConnect = async (id: string) => {\n setConnectingId(id);\n const updated = await connectService(id);\n if (updated) {\n setConnections((prev) => prev?.map((c) => (c.id === id ? updated : c)) ?? prev);\n } else {\n toast({ title: 'Failed to connect', variant: 'error' });\n }\n setConnectingId(null);\n };\n\n const handleDismissToggle = async () => {\n const next = !setupDismissed;\n const { ok } = await saveConfig({ setupDismissed: next });\n if (ok) {\n setSetupDismissed(next);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', variant: 'error' });\n }\n };\n\n const allOk = connections?.every((c) => c.status === 'ok') ?? true;\n const externalConnections = connections?.filter((c) => c.kind === 'external') ?? [];\n const localConnections = connections?.filter((c) => c.kind === 'local') ?? [];\n\n return {\n connections,\n loadFailed,\n reloadingId,\n connectingId,\n setupDismissed,\n handleRecheck,\n handleConnect,\n handleDismissToggle,\n allOk,\n externalConnections,\n localConnections,\n };\n};\n","import { useAppStore } from '@/app/stores/app-store';\nimport { useToast } from '@dendelion/paper-ui';\nimport { useEffect, useRef } from 'react';\n\nconst RELAY_POLL_MS = 2000;\n\nexport const useSignInAction = (onSignedIn: () => void) => {\n const loginRelay = useAppStore((s) => s.loginRelay);\n const startLoginRelay = useAppStore((s) => s.startLoginRelay);\n const loadLoginRelayStatus = useAppStore((s) => s.loadLoginRelayStatus);\n const cancelLoginRelay = useAppStore((s) => s.cancelLoginRelay);\n const { toast } = useToast();\n const openedUrlRef = useRef<string | null>(null);\n const phase = loginRelay?.phase;\n\n useEffect(() => {\n if (phase !== 'starting' && phase !== 'awaiting-authorization') return;\n const id = window.setInterval(() => loadLoginRelayStatus(), RELAY_POLL_MS);\n return () => window.clearInterval(id);\n }, [phase, loadLoginRelayStatus]);\n\n useEffect(() => {\n const url = loginRelay?.authorizeUrl;\n if (phase !== 'awaiting-authorization' || !url || openedUrlRef.current === url) return;\n openedUrlRef.current = url;\n window.open(url, '_blank', 'noopener,noreferrer');\n }, [phase, loginRelay?.authorizeUrl]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: keyed on phase transitions only — toast/onSignedIn aren't stable across renders, and including them would refire on every relay poll\n useEffect(() => {\n if (phase === 'success') {\n toast({ title: 'Signed in', variant: 'success' });\n onSignedIn();\n } else if (phase === 'error') {\n toast({ title: 'Sign-in failed', description: loginRelay?.error, variant: 'error' });\n }\n }, [phase]);\n\n return {\n phase,\n authorizeUrl: loginRelay?.authorizeUrl,\n startLoginRelay,\n cancelLoginRelay,\n };\n};\n","import type { ConnectionResult } from '@/types/index';\nimport { Button, CodeBlock } from '@dendelion/paper-ui';\n\ninterface ConnectActionViewProps {\n connection: ConnectionResult;\n onConnect: (id: string) => void;\n connecting: boolean;\n}\n\nexport const ConnectActionView = ({\n connection,\n onConnect,\n connecting,\n}: ConnectActionViewProps) => {\n const { connect } = connection;\n if (!connect) return null;\n if (connect.kind === 'command' && connect.runnable) {\n return (\n <Button size=\"small\" onClick={() => onConnect(connection.id)} disabled={connecting}>\n {connecting ? 'Running…' : `Run \\`${connect.command}\\``}\n </Button>\n );\n }\n if (connect.kind === 'command') {\n return (\n <div className=\"mt-2\">\n <CodeBlock code={connect.command} />\n </div>\n );\n }\n if (connect.kind === 'link') {\n return (\n <Button\n size=\"small\"\n onClick={() => window.open(connect.url, '_blank', 'noopener,noreferrer')}\n >\n {connect.label}\n </Button>\n );\n }\n return <p className=\"opacity-[0.65] text-sm mt-2 mx-0 mb-0\">{connect.message}</p>;\n};\n","import { CodeBlock } from '@dendelion/paper-ui';\n\n// Same two commands the relay drives interactively — shown as copy-paste fallback\n// when the relay itself can't run (no PTY, offline, unsupported CLI version).\nconst AUTH_FIX_COMMANDS = ['claude auth login', 'claude setup-token'] as const;\n\nexport const RelayFallbackGuide = () => (\n <div className=\"mt-2 flex flex-col gap-2\">\n <p className=\"opacity-[0.65] text-sm m-0\">\n The in-app relay couldn't complete. Run one of these in a terminal instead:\n </p>\n {AUTH_FIX_COMMANDS.map((cmd) => (\n <CodeBlock key={cmd} code={cmd} />\n ))}\n <p className=\"opacity-50 text-sm m-0\">\n {/* paper-ui has no inline-code component, only the block-level CodeBlock */}\n Alternatively, set <code>ANTHROPIC_API_KEY</code> in the server's environment — that bills as\n API usage rather than your Max subscription, so treat it as a fallback, not the default.\n </p>\n </div>\n);\n","import { Button } from '@dendelion/paper-ui';\nimport { useSignInAction } from '../hooks';\nimport { RelayFallbackGuide } from './relay-fallback-guide';\n\ninterface SignInActionProps {\n onSignedIn: () => void;\n}\n\nexport const SignInAction = ({ onSignedIn }: SignInActionProps) => {\n const { phase, authorizeUrl, startLoginRelay, cancelLoginRelay } = useSignInAction(onSignedIn);\n\n if (phase === 'starting') {\n return (\n <Button size=\"small\" disabled>\n Starting…\n </Button>\n );\n }\n if (phase === 'awaiting-authorization') {\n return (\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"small\"\n onClick={() => authorizeUrl && window.open(authorizeUrl, '_blank', 'noopener,noreferrer')}\n >\n Reopen sign-in tab\n </Button>\n <Button size=\"small\" onClick={() => cancelLoginRelay()}>\n Cancel\n </Button>\n </div>\n );\n }\n return (\n <div>\n <Button size=\"small\" onClick={() => startLoginRelay()}>\n Sign in\n </Button>\n {phase === 'error' && <RelayFallbackGuide />}\n </div>\n );\n};\n","import type { ConnectionResult } from '@/types/index';\nimport { Button, Divider, Stamp, Tooltip } from '@dendelion/paper-ui';\nimport { CAPABILITY_STATUS_STAMP } from '../constants';\nimport { ConnectActionView } from './connect-action-view';\nimport { SignInAction } from './sign-in-action';\n\n// Only claude-code exposes `auth login`/`auth status` (see agentAuthenticated in server/services.ts).\nconst RELAY_CONNECTION_ID: ConnectionResult['id'] = 'agent:claude-code';\n\ninterface ConnectionRowProps {\n connection: ConnectionResult;\n isLast: boolean;\n onRecheck: (id: string) => void;\n rechecking: boolean;\n onConnect: (id: string) => void;\n connecting: boolean;\n}\n\nexport const ConnectionRow = ({\n connection,\n isLast,\n onRecheck,\n rechecking,\n onConnect,\n connecting,\n}: ConnectionRowProps) => {\n const stamp = CAPABILITY_STATUS_STAMP[connection.status];\n return (\n <>\n <div className=\"pb-3 pt-3\">\n <div className=\"flex items-center gap-3\">\n <span className=\"flex-1 font-medium\">{connection.label}</span>\n {connection.authenticated === false && (\n <Tooltip content=\"Installed, but not signed in\">\n <Stamp size=\"small\" variant=\"warning\">\n Not signed in\n </Stamp>\n </Tooltip>\n )}\n <Stamp size=\"small\" fillColor={stamp.fill} textColor={stamp.text}>\n {stamp.label}\n </Stamp>\n <Button size=\"small\" onClick={() => onRecheck(connection.id)} disabled={rechecking}>\n {rechecking ? 'Checking…' : 'Recheck'}\n </Button>\n </div>\n <p className=\"opacity-[0.65] text-sm mt-1 mx-0 mb-0\">Unlocks: {connection.unlocks}</p>\n <p className=\"opacity-50 text-sm mt-1 mx-0 mb-0\">{connection.detail}</p>\n <div className=\"mt-2\">\n {connection.id === RELAY_CONNECTION_ID && connection.authenticated === false ? (\n <SignInAction onSignedIn={() => onRecheck(connection.id)} />\n ) : (\n <ConnectActionView\n connection={connection}\n onConnect={onConnect}\n connecting={connecting}\n />\n )}\n </div>\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n","import { Alert, Button, Card } from '@dendelion/paper-ui';\nimport { useSetupSection } from '../hooks';\nimport { ConnectionRow } from './connection-row';\n\nexport const SetupSection = () => {\n const {\n connections,\n loadFailed,\n reloadingId,\n connectingId,\n setupDismissed,\n handleRecheck,\n handleConnect,\n handleDismissToggle,\n allOk,\n externalConnections,\n localConnections,\n } = useSetupSection();\n\n return (\n <div>\n <div className=\"mb-6\">\n <h2 className=\"m-0\">Setup</h2>\n </div>\n {connections === null && !loadFailed && <p>Loading…</p>}\n {loadFailed && (\n <div className=\"mb-4\">\n <Alert variant=\"warning\">Failed to load connections. Try refreshing.</Alert>\n </div>\n )}\n {connections && (\n <>\n {!allOk && (\n <div className=\"mb-4\">\n <Alert variant=\"warning\">\n Some connections are incomplete — features that depend on them stay disabled until\n fixed. Run the connect command below, then recheck.\n </Alert>\n </div>\n )}\n {externalConnections.length > 0 && (\n <div className=\"mb-4\">\n <p className=\"opacity-[0.45] text-sm mt-0 mb-2\">\n External services — reached on your behalf with their own remote credential.\n </p>\n <Card size=\"small\" texture=\"kraft\">\n {externalConnections.map((c, idx) => (\n <ConnectionRow\n key={c.id}\n connection={c}\n isLast={idx === externalConnections.length - 1}\n onRecheck={handleRecheck}\n rechecking={reloadingId === c.id}\n onConnect={handleConnect}\n connecting={connectingId === c.id}\n />\n ))}\n </Card>\n </div>\n )}\n {localConnections.length > 0 && (\n <div className=\"mb-4\">\n <p className=\"opacity-[0.45] text-sm mt-0 mb-2\">\n Local adapters — driven on this machine with their own local session.\n </p>\n <Card size=\"small\" texture=\"kraft\">\n {localConnections.map((c, idx) => (\n <ConnectionRow\n key={c.id}\n connection={c}\n isLast={idx === localConnections.length - 1}\n onRecheck={handleRecheck}\n rechecking={reloadingId === c.id}\n onConnect={handleConnect}\n connecting={connectingId === c.id}\n />\n ))}\n </Card>\n </div>\n )}\n <div className=\"mt-4\">\n <Button size=\"small\" onClick={handleDismissToggle}>\n {setupDismissed ? 'Show Setup on open again' : \"Don't show Setup on open\"}\n </Button>\n </div>\n </>\n )}\n </div>\n );\n};\n","import { useSubjectVocabulary } from '@/app/hooks';\nimport { Button, Card, Divider } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\n\nexport const SubjectsSection = () => {\n const { subjects, loading, available } = useSubjectVocabulary();\n const navigate = useNavigate();\n\n return (\n <div>\n <div className=\"mb-6\">\n <h2 className=\"m-0\">Subjects</h2>\n <p className=\"opacity-50 mt-1\">\n Subjects are the roadmap's bets and standing concerns. Edit the vocabulary on the Roadmap\n page.\n </p>\n </div>\n {loading && <p>Loading…</p>}\n {!loading && !available && (\n <p className=\"opacity-60 m-0\">Couldn't load subjects — check the server config.</p>\n )}\n {!loading && available && (\n <Card size=\"small\" texture=\"kraft\">\n {subjects.length === 0 && <p className=\"opacity-[0.45] m-0 pb-2\">No subjects yet.</p>}\n {subjects.map((name, idx) => (\n <div key={name}>\n <div className=\"pb-2 pt-2\">{name}</div>\n {idx < subjects.length - 1 && <Divider />}\n </div>\n ))}\n {subjects.length > 0 && <Divider />}\n <div className=\"pt-3\">\n <Button size=\"small\" onClick={() => navigate({ to: '/roadmap' })}>\n Go to Roadmap\n </Button>\n </div>\n </Card>\n )}\n </div>\n );\n};\n","import {\n AGENT_IDS,\n AGENT_LABELS,\n AGENT_OPTIONS,\n type AgentConfig,\n type AgentId,\n} from '@/types/index';\nimport { Divider, Input, Select } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\nimport { TASK_TYPE_LABELS, type TaskTypeKey } from '../constants';\n\nconst AGENT_COLUMN_WIDTH = 140;\nconst MODEL_COLUMN_WIDTH = 160;\nconst EFFORT_COLUMN_WIDTH = 110;\n\ninterface AgentTaskRowProps {\n taskKey: TaskTypeKey;\n agentConfig: AgentConfig;\n isLast: boolean;\n onSave: (key: TaskTypeKey, config: AgentConfig) => Promise<void>;\n // The code-authoring task's config — codeReview's model must never match it (IDEA-170).\n authorConfig?: AgentConfig;\n}\n\nexport const AgentTaskRow = ({\n taskKey,\n agentConfig,\n isLast,\n onSave,\n authorConfig,\n}: AgentTaskRowProps) => {\n // Fall back if the config carries an unknown agent id — never white-screen the page.\n const opts = AGENT_OPTIONS[agentConfig.agent] ?? AGENT_OPTIONS['claude-code'];\n const excludedModel =\n authorConfig && authorConfig.agent === agentConfig.agent\n ? (authorConfig.model ?? '')\n : undefined;\n const modelOpts = Array.isArray(opts.model)\n ? opts.model.filter((m) => m !== excludedModel)\n : opts.model;\n const effortOpts = opts.effort;\n const [localModel, setLocalModel] = useState(agentConfig.model ?? '');\n\n useEffect(() => {\n setLocalModel(agentConfig.model ?? '');\n }, [agentConfig.model]);\n\n const handleAgentChange = (v: string) => {\n const newId = v as AgentId;\n const newOpts = AGENT_OPTIONS[newId];\n const newConfig: AgentConfig = { agent: newId };\n // Only carry the model over if the new agent accepts it — otherwise a claude\n // model like 'opus' would leak into opencode and fail at launch.\n if (\n agentConfig.model &&\n (newOpts.model === null || newOpts.model?.includes(agentConfig.model))\n ) {\n newConfig.model = agentConfig.model;\n }\n if (agentConfig.effort && Array.isArray(newOpts.effort)) newConfig.effort = agentConfig.effort;\n onSave(taskKey, newConfig);\n };\n\n const handleModelSelectChange = (v: string) => {\n onSave(taskKey, { ...agentConfig, model: v || undefined });\n };\n\n const handleModelInputBlur = () => {\n onSave(taskKey, { ...agentConfig, model: localModel || undefined });\n };\n\n const handleEffortChange = (v: string) => {\n onSave(taskKey, { ...agentConfig, effort: v || undefined });\n };\n\n return (\n <>\n <div className=\"flex items-center gap-3 pb-2 pt-2\">\n <span className=\"w-[110px] shrink-0 text-sm opacity-[0.65]\">\n {TASK_TYPE_LABELS[taskKey]}\n </span>\n <Select\n size=\"small\"\n width={AGENT_COLUMN_WIDTH}\n value={agentConfig.agent}\n onChange={handleAgentChange}\n options={AGENT_IDS.map((id) => ({ value: id, label: AGENT_LABELS[id] }))}\n />\n {Array.isArray(modelOpts) ? (\n <Select\n size=\"small\"\n width={MODEL_COLUMN_WIDTH}\n value={agentConfig.model ?? ''}\n onChange={handleModelSelectChange}\n options={[\n ...(excludedModel === '' ? [] : [{ value: '', label: 'Default' }]),\n ...modelOpts.map((m) => ({ value: m, label: m })),\n ]}\n />\n ) : modelOpts === null ? (\n <Input\n size=\"small\"\n className=\"w-[160px]\"\n value={localModel}\n placeholder=\"Default model\"\n onChange={(e) => setLocalModel(e.target.value)}\n onBlur={handleModelInputBlur}\n />\n ) : null}\n {/* Reserve the effort slot even when the agent has no effort options, so\n switching agents doesn't change the control count and shift the row. */}\n <div className={Array.isArray(effortOpts) ? 'visible' : 'invisible'}>\n <Select\n size=\"small\"\n width={EFFORT_COLUMN_WIDTH}\n value={agentConfig.effort ?? ''}\n onChange={handleEffortChange}\n options={[\n { value: '', label: 'Default' },\n ...(Array.isArray(effortOpts) ? effortOpts : []).map((e) => ({ value: e, label: e })),\n ]}\n />\n </div>\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n","export const AgentTaskRowHeader = () => (\n <div className=\"flex items-center gap-3 pb-1\">\n <span className=\"w-[110px] shrink-0 text-sm opacity-[0.45]\">Task</span>\n <span className=\"w-[140px] shrink-0 text-sm opacity-[0.45]\">Agent</span>\n <span className=\"w-[160px] shrink-0 text-sm opacity-[0.45]\">Model</span>\n <span className=\"w-[110px] shrink-0 text-sm opacity-[0.45]\">Effort</span>\n </div>\n);\n","import { color } from '@/app/styles/tokens';\nimport { DEFAULT_AGENTS } from '@/types/index';\nimport { Alert, Button, Card, Divider, Input, Stamp } from '@dendelion/paper-ui';\nimport { TASK_TYPE_KEYS, VERSION_STAMP_FILL } from '../constants';\nimport { useSettingsPage } from '../hooks';\nimport { AgentTaskRow } from './agent-task-row';\nimport { AgentTaskRowHeader } from './agent-task-row-header';\n\nexport const GeneralSection = () => {\n const {\n fileRef,\n config,\n identityLoading,\n iconDataUri,\n uploading,\n portInput,\n setPortInput,\n nameInput,\n setNameInput,\n handleSaveAgentConfig,\n handleSavePort,\n handleToggleIntegration,\n handleSaveName,\n handleFile,\n } = useSettingsPage();\n\n return (\n <div>\n <div className=\"mb-6\">\n <h2 className=\"m-0\">Project Info</h2>\n </div>\n {config === undefined && <p>Loading…</p>}\n {config === null && (\n <Alert variant=\"warning\">\n No papercamp/config.json found — run <code>paper-camp init</code> in this directory first.\n </Alert>\n )}\n {config && (\n <Card size=\"small\" texture=\"kraft\">\n <div className=\"flex items-end gap-3 pb-3\">\n <Input\n value={nameInput}\n onChange={(e) => setNameInput(e.target.value)}\n onBlur={handleSaveName}\n label=\"Project Name\"\n />\n <Stamp size=\"small\" fillColor={VERSION_STAMP_FILL} textColor={color.accentGreenDark}>\n v{config.version}\n </Stamp>\n </div>\n <Divider />\n\n <div className=\"flex items-center gap-3 pb-3 pt-3\">\n {iconDataUri && (\n <img\n src={iconDataUri}\n alt=\"Project icon\"\n className=\"w-10 h-10 object-contain shrink-0 rounded\"\n />\n )}\n <div>\n {/* paper-ui has no file-input component, so this raw input is intentional */}\n <input\n ref={fileRef}\n type=\"file\"\n accept=\".svg,.png,.jpg,.jpeg,.gif,.webp\"\n onChange={handleFile}\n className=\"hidden\"\n />\n <Button size=\"small\" onClick={() => fileRef.current?.click()} disabled={uploading}>\n {uploading ? 'Uploading…' : 'Choose File'}\n </Button>\n {identityLoading && <p className=\"text-sm opacity-50 mt-1 mx-0 mb-0\">Loading…</p>}\n {!identityLoading && !iconDataUri && !uploading && (\n <p className=\"text-sm opacity-[0.45] mt-1 mx-0 mb-0\">No icon set.</p>\n )}\n </div>\n </div>\n <Divider />\n\n <div className=\"flex items-end gap-3 pb-3 pt-3\">\n <Input\n type=\"number\"\n value={portInput}\n onChange={(e) => setPortInput(e.target.value)}\n onBlur={handleSavePort}\n label=\"Port\"\n helperText=\"Default for `paper-camp dev`. Restart the server to apply a change.\"\n />\n </div>\n <Divider />\n\n <div className=\"flex items-center justify-between gap-3 pb-3 pt-3\">\n <div>\n <p className=\"m-0\">In-app dev toolbar</p>\n <p className=\"opacity-[0.45] text-sm mt-1 mx-0 mb-0\">\n Inject the paper-camp toolbar into this project's dev server via the Vite plugin.\n </p>\n </div>\n <Button size=\"small\" onClick={handleToggleIntegration}>\n {(config.integration?.toolbar?.enabled ?? true) ? 'Disable' : 'Enable'}\n </Button>\n </div>\n <Divider />\n\n <AgentTaskRowHeader />\n {TASK_TYPE_KEYS.map((key, idx) => (\n <AgentTaskRow\n key={key}\n taskKey={key}\n agentConfig={config.defaultAgents?.[key] ?? DEFAULT_AGENTS[key]}\n isLast={idx === TASK_TYPE_KEYS.length - 1}\n onSave={handleSaveAgentConfig}\n authorConfig={\n key === 'codeReview'\n ? (config.defaultAgents?.phase ?? DEFAULT_AGENTS.phase)\n : undefined\n }\n />\n ))}\n </Card>\n )}\n\n <p className=\"opacity-[0.45] text-sm mt-4\">\n <strong>Initialized:</strong>{' '}\n {config ? new Date(config.initializedAt).toLocaleString() : '—'}\n </p>\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useActiveSettingsSection } from '@/app/hooks';\nimport { MergePolicySection } from './components/merge-policy-section';\nimport { SetupSection } from './components/setup-section';\nimport { SubjectsSection } from './components/subjects-section';\nimport { GeneralSection } from './views';\n\nexport const SettingsPage = () => {\n const section = useActiveSettingsSection();\n return (\n <div>\n <PageTitle>Settings</PageTitle>\n {section === 'subjects' ? (\n <SubjectsSection />\n ) : section === 'setup' ? (\n <SetupSection />\n ) : section === 'merge-policy' ? (\n <MergePolicySection />\n ) : (\n <GeneralSection />\n )}\n </div>\n );\n};\n","import { useActiveSettingsSection } from '@/app/hooks';\nimport { ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nexport const SettingsSidebar = () => {\n const section = useActiveSettingsSection();\n const navigate = useNavigate();\n\n return (\n <>\n <SidebarSection label=\"General\">\n <ListItem\n size=\"small\"\n className=\"pc-row text-xs\"\n active={section === null}\n onClick={() => navigate({ to: '/settings' })}\n >\n Project Info\n </ListItem>\n <ListItem\n size=\"small\"\n className=\"pc-row text-xs\"\n active={section === 'setup'}\n onClick={() => navigate({ to: '/settings/$section', params: { section: 'setup' } })}\n >\n Setup\n </ListItem>\n <ListItem\n size=\"small\"\n className=\"pc-row text-xs\"\n active={section === 'merge-policy'}\n onClick={() =>\n navigate({ to: '/settings/$section', params: { section: 'merge-policy' } })\n }\n >\n Merge Policy\n </ListItem>\n </SidebarSection>\n <SidebarSection label=\"Ideas\">\n <ListItem\n size=\"small\"\n className=\"pc-row text-xs\"\n active={section === 'subjects'}\n onClick={() => navigate({ to: '/settings/$section', params: { section: 'subjects' } })}\n >\n Subjects\n </ListItem>\n </SidebarSection>\n </>\n );\n};\n"],"names":["fetchMergePolicy","response","apiUrl","applyMergePolicy","TASK_TYPE_KEYS","TASK_TYPE_LABELS","CAPABILITY_STATUS_STAMP","MERGE_POLICY_STAMP","VERSION_STAMP_FILL","RECOMMENDED","POLICY_ROWS","formatValue","value","matchesRecommended","policy","row","PolicyRow","label","current","recommended","isLast","matches","jsxs","Fragment","jsx","Divider","MergePolicySection","result","setResult","useState","applying","setApplying","toast","useToast","useEffect","handleApply","applied","upToDate","Alert","Stamp","Card","idx","Button","useSettingsPage","fileRef","useRef","config","setConfig","fetchedIconDataUri","identityLoading","useProjectIdentity","uploadedIconDataUri","setUploadedIconDataUri","iconDataUri","uploading","setUploading","portInput","setPortInput","nameInput","setNameInput","fetchConfig","c","key","newEntry","updated","DEFAULT_AGENTS","agentConfigsEqual","ok","error","saveConfig","prev","port","next","_b","_a","integration","_c","projectName","e","file","reader","dataUri","uploadIcon","useSetupSection","connections","setConnections","loadFailed","setLoadFailed","reloadingId","setReloadingId","connectingId","setConnectingId","setupDismissed","setSetupDismissed","applyConnections","useCallback","fetchConnections","handleRecheck","id","handleConnect","connectService","handleDismissToggle","allOk","externalConnections","localConnections","RELAY_POLL_MS","useSignInAction","onSignedIn","loginRelay","useAppStore","s","startLoginRelay","loadLoginRelayStatus","cancelLoginRelay","openedUrlRef","phase","url","ConnectActionView","connection","onConnect","connecting","connect","CodeBlock","AUTH_FIX_COMMANDS","RelayFallbackGuide","cmd","SignInAction","authorizeUrl","RELAY_CONNECTION_ID","ConnectionRow","onRecheck","rechecking","stamp","Tooltip","SetupSection","SubjectsSection","subjects","loading","available","useSubjectVocabulary","navigate","useNavigate","name","AGENT_COLUMN_WIDTH","MODEL_COLUMN_WIDTH","EFFORT_COLUMN_WIDTH","AgentTaskRow","taskKey","agentConfig","onSave","authorConfig","opts","AGENT_OPTIONS","excludedModel","modelOpts","effortOpts","localModel","setLocalModel","handleAgentChange","v","newId","newOpts","newConfig","handleModelSelectChange","handleModelInputBlur","handleEffortChange","Select","AGENT_IDS","AGENT_LABELS","Input","AgentTaskRowHeader","GeneralSection","handleSaveAgentConfig","handleSavePort","handleToggleIntegration","handleSaveName","handleFile","color","SettingsPage","section","useActiveSettingsSection","PageTitle","SettingsSidebar","SidebarSection","ListItem"],"mappings":"sTAGO,MAAMA,GAAmB,SAA+C,CAC7E,GAAI,CACF,MAAMC,EAAW,MAAM,MAAMC,EAAO,mBAAmB,CAAC,EACxD,OAAKD,EAAS,GACN,MAAMA,EAAS,KAAA,EADE,IAE3B,MAAQ,CACN,OAAO,IACT,CACF,EAEaE,GAAmB,SAA+C,CAC7E,GAAI,CACF,MAAMF,EAAW,MAAM,MAAMC,EAAO,yBAAyB,EAAG,CAAE,OAAQ,OAAQ,EAClF,OAAKD,EAAS,GACN,MAAMA,EAAS,KAAA,EADE,IAE3B,MAAQ,CACN,OAAO,IACT,CACF,ECnBaG,EAAiB,CAC5B,QACA,YACA,aACA,gBACA,WACA,YACF,EAGaC,GAAgD,CAC3D,MAAO,YACP,UAAW,aACX,WAAY,cACZ,cAAe,iBACf,SAAU,aACV,WAAY,aACd,EAEaC,GAGT,CACF,GAAI,CAAE,KAAM,4BAA6B,KAAM,UAAW,MAAO,OAAA,EACjE,KAAM,CAAE,KAAM,4BAA6B,KAAM,UAAW,MAAO,iBAAA,EACnE,QAAS,CAAE,KAAM,4BAA6B,KAAM,UAAW,MAAO,SAAA,CACxE,EAEaC,EAAsF,CACjG,SAAU,CAAE,KAAM,4BAA6B,KAAM,SAAA,EACrD,SAAU,CAAE,KAAM,4BAA6B,KAAM,SAAA,CACvD,EAEaC,GAAqB,4BC7B5BC,GAA2B,CAC/B,iBAAkB,GAClB,iBAAkB,GAClB,iBAAkB,GAClB,uBAAwB,WACxB,yBAA0B,SAC5B,EAEMC,EAA2D,CAC/D,CAAE,IAAK,mBAAoB,MAAO,oBAAA,EAClC,CAAE,IAAK,mBAAoB,MAAO,oBAAA,EAClC,CAAE,IAAK,mBAAoB,MAAO,oBAAA,EAClC,CAAE,IAAK,yBAA0B,MAAO,qBAAA,EACxC,CAAE,IAAK,2BAA4B,MAAO,uBAAA,CAC5C,EAEA,SAASC,EAAYC,EAAiC,CACpD,OAAO,OAAOA,GAAU,UAAaA,EAAQ,MAAQ,KAAQA,CAC/D,CAEA,SAASC,GAAmBC,EAA8B,CACxD,OAAOJ,EAAY,MAAOK,GAAQD,EAAOC,EAAI,GAAG,IAAMN,GAAYM,EAAI,GAAG,CAAC,CAC5E,CASA,MAAMC,GAAY,CAAC,CAAE,MAAAC,EAAO,QAAAC,EAAS,YAAAC,EAAa,OAAAC,KAA6B,CAC7E,MAAMC,EAAUH,IAAYC,EAC5B,OACEG,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAD,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,SAAU,SAAAP,EAAM,EAChCO,EAAAA,IAAC,QAAK,UAAWH,EAAU,6BAA+B,gBACvD,SAAAV,EAAYO,CAAO,EACtB,EACC,CAACG,GAAWC,EAAAA,KAAC,OAAA,CAAK,UAAU,iBAAiB,SAAA,CAAA,KAAGX,EAAYQ,CAAW,CAAA,CAAA,CAAE,CAAA,EAC5E,EACC,CAACC,GAAUI,MAACC,EAAA,CAAA,CAAQ,CAAA,EACvB,CAEJ,EAEaC,GAAqB,IAAM,CACtC,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAA+C,MAAS,EAC9E,CAACC,EAAUC,CAAW,EAAIF,EAAAA,SAAS,EAAK,EACxC,CAAE,MAAAG,CAAA,EAAUC,EAAA,EAElBC,EAAAA,UAAU,IAAM,CACdlC,GAAA,EAAmB,KAAK4B,CAAS,CACnC,EAAG,CAAA,CAAE,EAEL,MAAMO,EAAc,SAAY,CAC9BJ,EAAY,EAAI,EAChB,MAAMK,EAAU,MAAMjC,GAAA,EACtB4B,EAAY,EAAK,GACbK,GAAA,YAAAA,EAAS,UAAW,MACtBR,EAAUQ,CAAO,EACjBJ,EAAM,CAAE,MAAO,uBAAwB,QAAS,UAAW,GAE3DA,EAAM,CACJ,MAAO,+BACP,aAAaI,GAAA,YAAAA,EAAS,UAAW,cAAgBA,EAAQ,OAAS,OAClE,QAAS,OAAA,CACV,CAEL,EAEMC,GAAWV,GAAA,YAAAA,EAAQ,UAAW,MAAQd,GAAmBc,EAAO,MAAM,EAE5E,cACG,MAAA,CACC,SAAA,CAAAL,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAE,EAAAA,IAAC,KAAA,CAAG,UAAU,MAAM,SAAA,eAAY,EAChCA,EAAAA,IAAC,IAAA,CAAE,UAAU,kBAAkB,SAAA,sGAAA,CAG/B,CAAA,EACF,EACCG,IAAW,QAAaH,EAAAA,IAAC,IAAA,CAAE,SAAA,WAAQ,EACnCG,IAAW,MAAQH,EAAAA,IAACc,EAAA,CAAM,QAAQ,UAAU,SAAA,+BAA4B,GACxEX,GAAA,YAAAA,EAAQ,UAAW,eAAiBH,EAAAA,IAACc,GAAM,QAAQ,UAAW,WAAO,MAAA,CAAO,GAC5EX,GAAA,YAAAA,EAAQ,UAAW,MAClBL,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAD,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,cAAe,SAAAG,EAAO,KAAK,EAC3CH,EAAAA,IAACe,EAAA,CACC,KAAK,QACL,UACEF,EAAW9B,EAAmB,SAAS,KAAOA,EAAmB,SAAS,KAE5E,UACE8B,EAAW9B,EAAmB,SAAS,KAAOA,EAAmB,SAAS,KAG3E,WAAW,6BAA+B,iCAAA,CAAA,CAC7C,EACF,EACAiB,EAAAA,IAACgB,EAAA,CAAK,KAAK,QAAQ,QAAQ,QACxB,SAAA9B,EAAY,IAAI,CAACK,EAAK0B,IACrBjB,EAAAA,IAACR,GAAA,CAEC,MAAOD,EAAI,MACX,QAASY,EAAO,OAAOZ,EAAI,GAAG,EAC9B,YAAaN,GAAYM,EAAI,GAAG,EAChC,OAAQ0B,IAAQ/B,EAAY,OAAS,CAAA,EAJhCK,EAAI,GAAA,CAMZ,EACH,QACC,MAAA,CAAI,UAAU,OACb,SAAAS,EAAAA,IAACkB,GAAO,KAAK,QAAQ,QAASP,EAAa,SAAUL,GAAYO,EAC9D,SAAAP,EAAW,YAAc,2BAC5B,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EAEJ,CAEJ,ECnHaa,GAAkB,IAAM,CACnC,MAAMC,EAAUC,EAAAA,OAAyB,IAAI,EACvC,CAACC,EAAQC,CAAS,EAAIlB,EAAAA,SAA6C,MAAS,EAC5E,CAAE,YAAamB,EAAoB,QAASC,CAAA,EAAoBC,GAAA,EAChE,CAACC,EAAqBC,CAAsB,EAAIvB,EAAAA,SAAwB,IAAI,EAC5EwB,EAAcF,GAAuBH,EACrC,CAACM,EAAWC,CAAY,EAAI1B,EAAAA,SAAS,EAAK,EAC1C,CAAC2B,EAAWC,CAAY,EAAI5B,EAAAA,SAAS,EAAE,EACvC,CAAC6B,EAAWC,CAAY,EAAI9B,EAAAA,SAAS,EAAE,EACvC,CAAE,MAAAG,CAAA,EAAUC,EAAA,EAElBC,OAAAA,EAAAA,UAAU,IAAM,CACd0B,EAAA,EAAc,KAAMC,GAAM,CACxBd,EAAUc,CAAC,GACPA,GAAA,YAAAA,EAAG,QAAS,UAAwB,OAAOA,EAAE,IAAI,CAAC,GAClDA,GAAA,YAAAA,EAAG,eAAgB,QAAWF,EAAaE,EAAE,WAAW,CAC9D,CAAC,CACH,EAAG,CAAA,CAAE,EA8FE,CACL,QAAAjB,EACA,OAAAE,EACA,gBAAAG,EACA,YAAAI,EACA,UAAAC,EACA,UAAAE,EACA,aAAAC,EACA,UAAAC,EACA,aAAAC,EACA,sBAtG4B,MAAOG,EAAkBC,IAA0B,CAC/E,MAAM7C,EAAU4B,GAAA,YAAAA,EAAQ,cAClBkB,EAA4B,CAChC,OAAO9C,GAAA,YAAAA,EAAS,QAAS+C,EAAe,MACxC,WAAW/C,GAAA,YAAAA,EAAS,YAAa+C,EAAe,UAChD,YAAY/C,GAAA,YAAAA,EAAS,aAAc+C,EAAe,WAClD,eAAe/C,GAAA,YAAAA,EAAS,gBAAiB+C,EAAe,cACxD,UAAU/C,GAAA,YAAAA,EAAS,WAAY+C,EAAe,SAC9C,YAAY/C,GAAA,YAAAA,EAAS,aAAc+C,EAAe,WAClD,CAACH,CAAG,EAAGC,CAAA,EAET,GAAID,IAAQ,cAAgBI,GAAkBH,EAAUC,EAAQ,KAAK,EAAG,CACtEhC,EAAM,CACJ,MAAO,iBACP,YAAa,yDACb,QAAS,OAAA,CACV,EACD,MACF,CACA,KAAM,CAAE,GAAAmC,EAAI,MAAAC,CAAA,EAAU,MAAMC,EAAW,CAAE,cAAeL,EAAS,EAC7DG,GACFpB,EAAWuB,GAAUA,GAAO,CAAE,GAAGA,EAAM,cAAeN,CAAA,CAAiB,EACvEhC,EAAM,CAAE,MAAO,QAAS,QAAS,UAAW,GAE5CA,EAAM,CAAE,MAAO,iBAAkB,YAAaoC,EAAO,QAAS,QAAS,CAE3E,EA6EE,eA3EqB,SAAY,CACjC,MAAMG,EAAO,OAAOf,CAAS,EAC7B,GAAI,CAACV,GAAU,CAAC,OAAO,UAAUyB,CAAI,GAAKA,GAAQ,GAAKA,IAASzB,EAAO,KAAM,OAC7E,KAAM,CAAE,GAAAqB,EAAI,MAAAC,CAAA,EAAU,MAAMC,EAAW,CAAE,KAAAE,EAAM,EAC3CJ,GACFpB,EAAWuB,GAAUA,GAAO,CAAE,GAAGA,EAAM,KAAAC,CAAA,CAAc,EACrDvC,EAAM,CACJ,MAAO,QACP,YAAa,kDACb,QAAS,SAAA,CACV,GAEDA,EAAM,CAAE,MAAO,iBAAkB,YAAaoC,EAAO,QAAS,QAAS,CAE3E,EA8DE,wBA5D8B,SAAY,WAC1C,GAAI,CAACtB,EAAQ,OACb,MAAM0B,EAAO,IAAEC,GAAAC,EAAA5B,EAAO,cAAP,YAAA4B,EAAoB,UAApB,YAAAD,EAA6B,UAAW,IACjDE,EAAc,CAClB,GAAG7B,EAAO,YACV,QAAS,CAAE,IAAG8B,EAAA9B,EAAO,cAAP,YAAA8B,EAAoB,QAAS,QAASJ,CAAA,CAAK,EAErD,CAAE,GAAAL,EAAI,MAAAC,CAAA,EAAU,MAAMC,EAAW,CAAE,YAAAM,EAAa,EAClDR,GACFpB,EAAWuB,GAAUA,GAAO,CAAE,GAAGA,EAAM,YAAAK,CAAA,CAAqB,EAC5D3C,EAAM,CAAE,MAAO,QAAS,QAAS,UAAW,GAE5CA,EAAM,CAAE,MAAO,iBAAkB,YAAaoC,EAAO,QAAS,QAAS,CAE3E,EA+CE,eA7CqB,SAAY,CACjC,MAAMS,EAAcnB,EAAU,KAAA,EAC9B,GAAI,CAACZ,GAAU,CAAC+B,GAAeA,IAAgB/B,EAAO,YAAa,OACnE,KAAM,CAAE,GAAAqB,EAAI,MAAAC,CAAA,EAAU,MAAMC,EAAW,CAAE,YAAAQ,EAAa,EAClDV,GACFpB,EAAWuB,GAAUA,GAAO,CAAE,GAAGA,EAAM,YAAAO,CAAA,CAAqB,EAC5DlB,EAAakB,CAAW,EACxB7C,EAAM,CAAE,MAAO,QAAS,QAAS,UAAW,GAE5CA,EAAM,CAAE,MAAO,iBAAkB,YAAaoC,EAAO,QAAS,QAAS,CAE3E,EAmCE,WAjCiB,MAAOU,GAA2C,OACnE,MAAMC,GAAOL,EAAAI,EAAE,OAAO,QAAT,YAAAJ,EAAiB,GAC9B,GAAI,CAACK,EAAM,OACXxB,EAAa,EAAI,EACjB,MAAMyB,EAAS,IAAI,WACnBA,EAAO,UAAY,SAAY,CAC7B,MAAMC,EAAUD,EAAO,OACjBb,EAAK,MAAMe,GAAWD,CAAO,EACnC1B,EAAa,EAAK,EACdY,GACFf,EAAuB6B,CAAO,EAC9BjD,EAAM,CAAE,MAAO,QAAS,QAAS,UAAW,GAE5CA,EAAM,CAAE,MAAO,iBAAkB,QAAS,QAAS,CAEvD,EACAgD,EAAO,cAAcD,CAAI,CAC3B,CAgBE,CAEJ,ECvIaI,GAAkB,IAAM,CACnC,KAAM,CAACC,EAAaC,CAAc,EAAIxD,EAAAA,SAAoC,IAAI,EACxE,CAACyD,EAAYC,CAAa,EAAI1D,EAAAA,SAAS,EAAK,EAC5C,CAAC2D,EAAaC,CAAc,EAAI5D,EAAAA,SAAwB,IAAI,EAC5D,CAAC6D,EAAcC,CAAe,EAAI9D,EAAAA,SAAwB,IAAI,EAC9D,CAAC+D,EAAgBC,CAAiB,EAAIhE,EAAAA,SAAS,EAAK,EACpD,CAAE,MAAAG,CAAA,EAAUC,EAAA,EAEZ6D,EAAmBC,cAAapE,GAAsC,CAC1E,GAAIA,IAAW,KAAM,CACnB4D,EAAc,EAAI,EAClB,MACF,CACAA,EAAc,EAAK,EACnBF,EAAe1D,CAAM,CACvB,EAAG,CAAA,CAAE,EAELO,EAAAA,UAAU,IAAM,CACd8D,EAAA,EAAmB,KAAKF,CAAgB,EACxClC,EAAA,EAAc,KAAM,GAAMiC,GAAkB,iBAAG,iBAAkB,EAAK,CAAC,CACzE,EAAG,CAACC,CAAgB,CAAC,EAErB,MAAMG,EAAgB,MAAOC,GAAe,CAC1CT,EAAeS,CAAE,EACjBJ,EAAiB,MAAME,GAAkB,EACzCP,EAAe,IAAI,CACrB,EAEMU,EAAgB,MAAOD,GAAe,CAC1CP,EAAgBO,CAAE,EAClB,MAAMlC,EAAU,MAAMoC,GAAeF,CAAE,EACnClC,EACFqB,EAAgBf,IAASA,GAAA,YAAAA,EAAM,IAAKT,GAAOA,EAAE,KAAOqC,EAAKlC,EAAUH,KAAOS,CAAI,EAE9EtC,EAAM,CAAE,MAAO,oBAAqB,QAAS,QAAS,EAExD2D,EAAgB,IAAI,CACtB,EAEMU,EAAsB,SAAY,CACtC,MAAM7B,EAAO,CAACoB,EACR,CAAE,GAAAzB,GAAO,MAAME,EAAW,CAAE,eAAgBG,EAAM,EACpDL,GACF0B,EAAkBrB,CAAI,EACtBxC,EAAM,CAAE,MAAO,QAAS,QAAS,UAAW,GAE5CA,EAAM,CAAE,MAAO,iBAAkB,QAAS,QAAS,CAEvD,EAEMsE,GAAQlB,GAAA,YAAAA,EAAa,MAAO,GAAM,EAAE,SAAW,QAAS,GACxDmB,GAAsBnB,GAAA,YAAAA,EAAa,OAAQ,GAAM,EAAE,OAAS,cAAe,CAAA,EAC3EoB,GAAmBpB,GAAA,YAAAA,EAAa,OAAQ,GAAM,EAAE,OAAS,WAAY,CAAA,EAE3E,MAAO,CACL,YAAAA,EACA,WAAAE,EACA,YAAAE,EACA,aAAAE,EACA,eAAAE,EACA,cAAAK,EACA,cAAAE,EACA,oBAAAE,EACA,MAAAC,EACA,oBAAAC,EACA,iBAAAC,CAAA,CAEJ,ECpEMC,GAAgB,IAETC,GAAmBC,GAA2B,CACzD,MAAMC,EAAaC,EAAaC,GAAMA,EAAE,UAAU,EAC5CC,EAAkBF,EAAaC,GAAMA,EAAE,eAAe,EACtDE,EAAuBH,EAAaC,GAAMA,EAAE,oBAAoB,EAChEG,EAAmBJ,EAAaC,GAAMA,EAAE,gBAAgB,EACxD,CAAE,MAAA9E,CAAA,EAAUC,EAAA,EACZiF,EAAerE,EAAAA,OAAsB,IAAI,EACzCsE,EAAQP,GAAA,YAAAA,EAAY,MAE1B1E,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIiF,IAAU,YAAcA,IAAU,yBAA0B,OAChE,MAAMjB,EAAK,OAAO,YAAY,IAAMc,EAAA,EAAwBP,EAAa,EACzE,MAAO,IAAM,OAAO,cAAcP,CAAE,CACtC,EAAG,CAACiB,EAAOH,CAAoB,CAAC,EAEhC9E,EAAAA,UAAU,IAAM,CACd,MAAMkF,EAAMR,GAAA,YAAAA,EAAY,aACpBO,IAAU,0BAA4B,CAACC,GAAOF,EAAa,UAAYE,IAC3EF,EAAa,QAAUE,EACvB,OAAO,KAAKA,EAAK,SAAU,qBAAqB,EAClD,EAAG,CAACD,EAAOP,GAAA,YAAAA,EAAY,YAAY,CAAC,EAGpC1E,EAAAA,UAAU,IAAM,CACViF,IAAU,WACZnF,EAAM,CAAE,MAAO,YAAa,QAAS,UAAW,EAChD2E,EAAA,GACSQ,IAAU,SACnBnF,EAAM,CAAE,MAAO,iBAAkB,YAAa4E,GAAA,YAAAA,EAAY,MAAO,QAAS,QAAS,CAEvF,EAAG,CAACO,CAAK,CAAC,EAEH,CACL,MAAAA,EACA,aAAcP,GAAA,YAAAA,EAAY,aAC1B,gBAAAG,EACA,iBAAAE,CAAA,CAEJ,ECnCaI,GAAoB,CAAC,CAChC,WAAAC,EACA,UAAAC,EACA,WAAAC,CACF,IAA8B,CAC5B,KAAM,CAAE,QAAAC,GAAYH,EACpB,OAAKG,EACDA,EAAQ,OAAS,WAAaA,EAAQ,eAErC/E,EAAA,CAAO,KAAK,QAAQ,QAAS,IAAM6E,EAAUD,EAAW,EAAE,EAAG,SAAUE,EACrE,SAAAA,EAAa,WAAa,SAASC,EAAQ,OAAO,KACrD,EAGAA,EAAQ,OAAS,UAEjBjG,EAAAA,IAAC,OAAI,UAAU,OACb,eAACkG,EAAA,CAAU,KAAMD,EAAQ,OAAA,CAAS,CAAA,CACpC,EAGAA,EAAQ,OAAS,OAEjBjG,EAAAA,IAACkB,EAAA,CACC,KAAK,QACL,QAAS,IAAM,OAAO,KAAK+E,EAAQ,IAAK,SAAU,qBAAqB,EAEtE,SAAAA,EAAQ,KAAA,CAAA,EAIRjG,EAAAA,IAAC,IAAA,CAAE,UAAU,wCAAyC,WAAQ,QAAQ,EAzBxD,IA0BvB,ECrCMmG,GAAoB,CAAC,oBAAqB,oBAAoB,EAEvDC,GAAqB,IAChCtG,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACb,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,8EAE1C,EACCmG,GAAkB,IAAKE,SACrBH,EAAA,CAAoB,KAAMG,GAAXA,CAAgB,CACjC,EACDvG,EAAAA,KAAC,IAAA,CAAE,UAAU,yBACkE,SAAA,CAAA,sBAC1DE,EAAAA,IAAC,QAAK,SAAA,mBAAA,CAAiB,EAAO,uIAAA,CAAA,CAEnD,CAAA,EACF,ECXWsG,GAAe,CAAC,CAAE,WAAAnB,KAAoC,CACjE,KAAM,CAAE,MAAAQ,EAAO,aAAAY,EAAc,gBAAAhB,EAAiB,iBAAAE,CAAA,EAAqBP,GAAgBC,CAAU,EAE7F,OAAIQ,IAAU,iBAETzE,EAAA,CAAO,KAAK,QAAQ,SAAQ,GAAC,SAAA,YAE9B,EAGAyE,IAAU,yBAEV7F,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAE,EAAAA,IAACkB,EAAA,CACC,KAAK,QACL,QAAS,IAAMqF,GAAgB,OAAO,KAAKA,EAAc,SAAU,qBAAqB,EACzF,SAAA,oBAAA,CAAA,EAGDvG,MAACkB,GAAO,KAAK,QAAQ,QAAS,IAAMuE,EAAA,EAAoB,SAAA,QAAA,CAExD,CAAA,EACF,SAID,MAAA,CACC,SAAA,CAAAzF,MAACkB,GAAO,KAAK,QAAQ,QAAS,IAAMqE,EAAA,EAAmB,SAAA,UAEvD,EACCI,IAAU,SAAW3F,MAACoG,GAAA,CAAA,CAAmB,CAAA,EAC5C,CAEJ,EClCMI,GAA8C,oBAWvCC,EAAgB,CAAC,CAC5B,WAAAX,EACA,OAAAlG,EACA,UAAA8G,EACA,WAAAC,EACA,UAAAZ,EACA,WAAAC,CACF,IAA0B,CACxB,MAAMY,EAAQ9H,GAAwBgH,EAAW,MAAM,EACvD,OACEhG,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAD,EAAAA,KAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,qBAAsB,SAAA8F,EAAW,MAAM,EACtDA,EAAW,gBAAkB,IAC5B9F,EAAAA,IAAC6G,IAAQ,QAAQ,+BACf,SAAA7G,EAAAA,IAACe,EAAA,CAAM,KAAK,QAAQ,QAAQ,UAAU,yBAEtC,EACF,EAEFf,EAAAA,IAACe,EAAA,CAAM,KAAK,QAAQ,UAAW6F,EAAM,KAAM,UAAWA,EAAM,KACzD,SAAAA,EAAM,KAAA,CACT,EACA5G,EAAAA,IAACkB,EAAA,CAAO,KAAK,QAAQ,QAAS,IAAMwF,EAAUZ,EAAW,EAAE,EAAG,SAAUa,EACrE,SAAAA,EAAa,YAAc,SAAA,CAC9B,CAAA,EACF,EACA7G,EAAAA,KAAC,IAAA,CAAE,UAAU,wCAAwC,SAAA,CAAA,YAAUgG,EAAW,OAAA,EAAQ,EAClF9F,EAAAA,IAAC,IAAA,CAAE,UAAU,oCAAqC,WAAW,OAAO,QACnE,MAAA,CAAI,UAAU,OACZ,SAAA8F,EAAW,KAAOU,IAAuBV,EAAW,gBAAkB,GACrE9F,EAAAA,IAACsG,IAAa,WAAY,IAAMI,EAAUZ,EAAW,EAAE,EAAG,EAE1D9F,EAAAA,IAAC6F,GAAA,CACC,WAAAC,EACA,UAAAC,EACA,WAAAC,CAAA,CAAA,CACF,CAEJ,CAAA,EACF,EACC,CAACpG,GAAUI,MAACC,EAAA,CAAA,CAAQ,CAAA,EACvB,CAEJ,EC3Da6G,GAAe,IAAM,CAChC,KAAM,CACJ,YAAAlD,EACA,WAAAE,EACA,YAAAE,EACA,aAAAE,EACA,eAAAE,EACA,cAAAK,EACA,cAAAE,EACA,oBAAAE,EACA,MAAAC,EACA,oBAAAC,EACA,iBAAAC,CAAA,EACErB,GAAA,EAEJ,cACG,MAAA,CACC,SAAA,CAAA3D,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,SAAAA,EAAAA,IAAC,MAAG,UAAU,MAAM,iBAAK,CAAA,CAC3B,EACC4D,IAAgB,MAAQ,CAACE,GAAc9D,EAAAA,IAAC,KAAE,SAAA,WAAQ,EAClD8D,GACC9D,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,eAACc,EAAA,CAAM,QAAQ,UAAU,SAAA,6CAAA,CAA2C,CAAA,CACtE,EAED8C,GACC9D,EAAAA,KAAAC,WAAA,CACG,SAAA,CAAA,CAAC+E,GACA9E,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,eAACc,EAAA,CAAM,QAAQ,UAAU,SAAA,wIAAA,CAGzB,EACF,EAEDiE,EAAoB,OAAS,GAC5BjF,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,SAAA,+EAEhD,EACAA,EAAAA,IAACgB,EAAA,CAAK,KAAK,QAAQ,QAAQ,QACxB,SAAA+D,EAAoB,IAAI,CAAC1C,EAAGpB,IAC3BjB,EAAAA,IAACyG,EAAA,CAEC,WAAYpE,EACZ,OAAQpB,IAAQ8D,EAAoB,OAAS,EAC7C,UAAWN,EACX,WAAYT,IAAgB3B,EAAE,GAC9B,UAAWsC,EACX,WAAYT,IAAiB7B,EAAE,EAAA,EAN1BA,EAAE,EAAA,CAQV,CAAA,CACH,CAAA,EACF,EAED2C,EAAiB,OAAS,GACzBlF,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,SAAA,wEAEhD,EACAA,EAAAA,IAACgB,EAAA,CAAK,KAAK,QAAQ,QAAQ,QACxB,SAAAgE,EAAiB,IAAI,CAAC3C,EAAGpB,IACxBjB,EAAAA,IAACyG,EAAA,CAEC,WAAYpE,EACZ,OAAQpB,IAAQ+D,EAAiB,OAAS,EAC1C,UAAWP,EACX,WAAYT,IAAgB3B,EAAE,GAC9B,UAAWsC,EACX,WAAYT,IAAiB7B,EAAE,EAAA,EAN1BA,EAAE,EAAA,CAQV,CAAA,CACH,CAAA,EACF,EAEFrC,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,SAAAA,EAAAA,IAACkB,EAAA,CAAO,KAAK,QAAQ,QAAS2D,EAC3B,SAAAT,EAAiB,2BAA6B,2BACjD,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EAEJ,CAEJ,ECrFa2C,GAAkB,IAAM,CACnC,KAAM,CAAE,SAAAC,EAAU,QAAAC,EAAS,UAAAC,CAAA,EAAcC,GAAA,EACnCC,EAAWC,EAAA,EAEjB,cACG,MAAA,CACC,SAAA,CAAAvH,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAE,EAAAA,IAAC,KAAA,CAAG,UAAU,MAAM,SAAA,WAAQ,EAC5BA,EAAAA,IAAC,IAAA,CAAE,UAAU,kBAAkB,SAAA,iGAAA,CAG/B,CAAA,EACF,EACCiH,GAAWjH,EAAAA,IAAC,IAAA,CAAE,SAAA,UAAA,CAAQ,EACtB,CAACiH,GAAW,CAACC,SACX,IAAA,CAAE,UAAU,iBAAiB,SAAA,oDAAiD,EAEhF,CAACD,GAAWC,GACXpH,EAAAA,KAACkB,GAAK,KAAK,QAAQ,QAAQ,QACxB,SAAA,CAAAgG,EAAS,SAAW,GAAKhH,MAAC,IAAA,CAAE,UAAU,0BAA0B,SAAA,mBAAgB,EAChFgH,EAAS,IAAI,CAACM,EAAMrG,WAClB,MAAA,CACC,SAAA,CAAAjB,EAAAA,IAAC,MAAA,CAAI,UAAU,YAAa,SAAAsH,EAAK,EAChCrG,EAAM+F,EAAS,OAAS,SAAM/G,EAAA,CAAA,CAAQ,CAAA,CAAA,EAF/BqH,CAGV,CACD,EACAN,EAAS,OAAS,GAAKhH,EAAAA,IAACC,EAAA,CAAA,CAAQ,QAChC,MAAA,CAAI,UAAU,OACb,SAAAD,EAAAA,IAACkB,GAAO,KAAK,QAAQ,QAAS,IAAMkG,EAAS,CAAE,GAAI,WAAY,EAAG,yBAElE,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EAEJ,CAEJ,EC7BMG,GAAqB,IACrBC,GAAqB,IACrBC,GAAsB,IAWfC,GAAe,CAAC,CAC3B,QAAAC,EACA,YAAAC,EACA,OAAAhI,EACA,OAAAiI,EACA,aAAAC,CACF,IAAyB,CAEvB,MAAMC,EAAOC,EAAcJ,EAAY,KAAK,GAAKI,EAAc,aAAa,EACtEC,EACJH,GAAgBA,EAAa,QAAUF,EAAY,MAC9CE,EAAa,OAAS,GACvB,OACAI,EAAY,MAAM,QAAQH,EAAK,KAAK,EACtCA,EAAK,MAAM,OAAQ,GAAM,IAAME,CAAa,EAC5CF,EAAK,MACHI,EAAaJ,EAAK,OAClB,CAACK,EAAYC,CAAa,EAAIhI,EAAAA,SAASuH,EAAY,OAAS,EAAE,EAEpElH,EAAAA,UAAU,IAAM,CACd2H,EAAcT,EAAY,OAAS,EAAE,CACvC,EAAG,CAACA,EAAY,KAAK,CAAC,EAEtB,MAAMU,EAAqBC,GAAc,OACvC,MAAMC,EAAQD,EACRE,EAAUT,EAAcQ,CAAK,EAC7BE,EAAyB,CAAE,MAAOF,CAAA,EAItCZ,EAAY,QACXa,EAAQ,QAAU,OAAQvF,EAAAuF,EAAQ,QAAR,MAAAvF,EAAe,SAAS0E,EAAY,UAE/Dc,EAAU,MAAQd,EAAY,OAE5BA,EAAY,QAAU,MAAM,QAAQa,EAAQ,MAAM,IAAGC,EAAU,OAASd,EAAY,QACxFC,EAAOF,EAASe,CAAS,CAC3B,EAEMC,EAA2BJ,GAAc,CAC7CV,EAAOF,EAAS,CAAE,GAAGC,EAAa,MAAOW,GAAK,OAAW,CAC3D,EAEMK,EAAuB,IAAM,CACjCf,EAAOF,EAAS,CAAE,GAAGC,EAAa,MAAOQ,GAAc,OAAW,CACpE,EAEMS,EAAsBN,GAAc,CACxCV,EAAOF,EAAS,CAAE,GAAGC,EAAa,OAAQW,GAAK,OAAW,CAC5D,EAEA,OACEzI,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAD,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAE,MAAC,OAAA,CAAK,UAAU,4CACb,SAAAnB,GAAiB8I,CAAO,EAC3B,EACA3H,EAAAA,IAAC8I,EAAA,CACC,KAAK,QACL,MAAOvB,GACP,MAAOK,EAAY,MACnB,SAAUU,EACV,QAASS,GAAU,IAAKrE,IAAQ,CAAE,MAAOA,EAAI,MAAOsE,GAAatE,CAAE,CAAA,EAAI,CAAA,CAAA,EAExE,MAAM,QAAQwD,CAAS,EACtBlI,EAAAA,IAAC8I,EAAA,CACC,KAAK,QACL,MAAOtB,GACP,MAAOI,EAAY,OAAS,GAC5B,SAAUe,EACV,QAAS,CACP,GAAIV,IAAkB,GAAK,GAAK,CAAC,CAAE,MAAO,GAAI,MAAO,UAAW,EAChE,GAAGC,EAAU,IAAK,IAAO,CAAE,MAAO,EAAG,MAAO,GAAI,CAAA,CAClD,CAAA,EAEAA,IAAc,KAChBlI,EAAAA,IAACiJ,EAAA,CACC,KAAK,QACL,UAAU,YACV,MAAOb,EACP,YAAY,gBACZ,SAAW9E,GAAM+E,EAAc/E,EAAE,OAAO,KAAK,EAC7C,OAAQsF,CAAA,CAAA,EAER,KAGJ5I,EAAAA,IAAC,OAAI,UAAW,MAAM,QAAQmI,CAAU,EAAI,UAAY,YACtD,SAAAnI,EAAAA,IAAC8I,EAAA,CACC,KAAK,QACL,MAAOrB,GACP,MAAOG,EAAY,QAAU,GAC7B,SAAUiB,EACV,QAAS,CACP,CAAE,MAAO,GAAI,MAAO,SAAA,EACpB,IAAI,MAAM,QAAQV,CAAU,EAAIA,EAAa,CAAA,GAAI,IAAK7E,IAAO,CAAE,MAAOA,EAAG,MAAOA,GAAI,CAAA,CACtF,CAAA,CACF,CACF,CAAA,EACF,EACC,CAAC1D,GAAUI,MAACC,EAAA,CAAA,CAAQ,CAAA,EACvB,CAEJ,EC/HaiJ,GAAqB,IAChCpJ,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,4CAA4C,SAAA,OAAI,EAChEA,EAAAA,IAAC,OAAA,CAAK,UAAU,4CAA4C,SAAA,QAAK,EACjEA,EAAAA,IAAC,OAAA,CAAK,UAAU,4CAA4C,SAAA,QAAK,EACjEA,EAAAA,IAAC,OAAA,CAAK,UAAU,4CAA4C,SAAA,QAAA,CAAM,CAAA,EACpE,ECEWmJ,GAAiB,IAAM,SAClC,KAAM,CACJ,QAAA/H,EACA,OAAAE,EACA,gBAAAG,EACA,YAAAI,EACA,UAAAC,EACA,UAAAE,EACA,aAAAC,EACA,UAAAC,EACA,aAAAC,EACA,sBAAAiH,EACA,eAAAC,EACA,wBAAAC,EACA,eAAAC,EACA,WAAAC,CAAA,EACErI,GAAA,EAEJ,cACG,MAAA,CACC,SAAA,CAAAnB,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,SAAAA,EAAAA,IAAC,MAAG,UAAU,MAAM,wBAAY,CAAA,CAClC,EACCsB,IAAW,QAAatB,EAAAA,IAAC,IAAA,CAAE,SAAA,WAAQ,EACnCsB,IAAW,MACVxB,OAACgB,EAAA,CAAM,QAAQ,UAAU,SAAA,CAAA,wCACcd,EAAAA,IAAC,QAAK,SAAA,iBAAA,CAAe,EAAO,2BAAA,EACnE,EAEDsB,GACCxB,EAAAA,KAACkB,EAAA,CAAK,KAAK,QAAQ,QAAQ,QACzB,SAAA,CAAAlB,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACb,SAAA,CAAAE,EAAAA,IAACiJ,EAAA,CACC,MAAO/G,EACP,SAAWoB,GAAMnB,EAAamB,EAAE,OAAO,KAAK,EAC5C,OAAQiG,EACR,MAAM,cAAA,CAAA,EAERzJ,EAAAA,KAACiB,GAAM,KAAK,QAAQ,UAAW/B,GAAoB,UAAWyK,GAAM,gBAAiB,SAAA,CAAA,IACjFnI,EAAO,OAAA,CAAA,CACX,CAAA,EACF,QACCrB,EAAA,EAAQ,EAETH,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACZ,SAAA,CAAA+B,GACC7B,EAAAA,IAAC,MAAA,CACC,IAAK6B,EACL,IAAI,eACJ,UAAU,2CAAA,CAAA,SAGb,MAAA,CAEC,SAAA,CAAA7B,EAAAA,IAAC,QAAA,CACC,IAAKoB,EACL,KAAK,OACL,OAAO,kCACP,SAAUoI,EACV,UAAU,QAAA,CAAA,EAEZxJ,EAAAA,IAACkB,EAAA,CAAO,KAAK,QAAQ,QAAS,IAAA,OAAM,OAAAgC,EAAA9B,EAAQ,UAAR,YAAA8B,EAAiB,SAAS,SAAUpB,EACrE,SAAAA,EAAY,aAAe,cAC9B,EACCL,GAAmBzB,EAAAA,IAAC,IAAA,CAAE,UAAU,oCAAoC,SAAA,WAAQ,EAC5E,CAACyB,GAAmB,CAACI,GAAe,CAACC,GACpC9B,EAAAA,IAAC,IAAA,CAAE,UAAU,wCAAwC,SAAA,cAAA,CAAY,CAAA,CAAA,CAErE,CAAA,EACF,QACCC,EAAA,EAAQ,EAETD,EAAAA,IAAC,MAAA,CAAI,UAAU,iCACb,SAAAA,EAAAA,IAACiJ,EAAA,CACC,KAAK,SACL,MAAOjH,EACP,SAAWsB,GAAMrB,EAAaqB,EAAE,OAAO,KAAK,EAC5C,OAAQ+F,EACR,MAAM,OACN,WAAW,qEAAA,CAAA,EAEf,QACCpJ,EAAA,EAAQ,EAETH,EAAAA,KAAC,MAAA,CAAI,UAAU,oDACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,MAAM,SAAA,qBAAkB,EACrCA,EAAAA,IAAC,IAAA,CAAE,UAAU,wCAAwC,SAAA,mFAAA,CAErD,CAAA,EACF,EACAA,EAAAA,IAACkB,EAAA,CAAO,KAAK,QAAQ,QAASoI,EAC1B,WAAArG,GAAAC,EAAA5B,EAAO,cAAP,YAAA4B,EAAoB,UAApB,YAAAD,EAA6B,UAAW,GAAQ,UAAY,QAAA,CAChE,CAAA,EACF,QACChD,EAAA,EAAQ,QAERiJ,GAAA,EAAmB,EACnBtK,EAAe,IAAI,CAAC0D,EAAKrB,IAAA,SACxBjB,OAAAA,EAAAA,IAAC0H,GAAA,CAEC,QAASpF,EACT,cAAaY,EAAA5B,EAAO,gBAAP,YAAA4B,EAAuBZ,KAAQG,EAAeH,CAAG,EAC9D,OAAQrB,IAAQrC,EAAe,OAAS,EACxC,OAAQwK,EACR,aACE9G,IAAQ,eACHW,EAAA3B,EAAO,gBAAP,YAAA2B,EAAsB,QAASR,EAAe,MAC/C,MAAA,EARDH,CAAA,EAWR,CAAA,EACH,EAGFxC,EAAAA,KAAC,IAAA,CAAE,UAAU,8BACX,SAAA,CAAAE,EAAAA,IAAC,UAAO,SAAA,cAAA,CAAY,EAAU,IAC7BsB,EAAS,IAAI,KAAKA,EAAO,aAAa,EAAE,iBAAmB,GAAA,CAAA,CAC9D,CAAA,EACF,CAEJ,EC1HaoI,GAAe,IAAM,CAChC,MAAMC,EAAUC,GAAA,EAChB,cACG,MAAA,CACC,SAAA,CAAA5J,EAAAA,IAAC6J,IAAU,SAAA,UAAA,CAAQ,EAClBF,IAAY,WACX3J,EAAAA,IAAC+G,GAAA,CAAA,CAAgB,EACf4C,IAAY,QACd3J,MAAC8G,GAAA,CAAA,CAAa,EACZ6C,IAAY,eACd3J,EAAAA,IAACE,GAAA,EAAmB,QAEnBiJ,GAAA,CAAA,CAAe,CAAA,EAEpB,CAEJ,EClBaW,GAAkB,IAAM,CACnC,MAAMH,EAAUC,GAAA,EACVxC,EAAWC,EAAA,EAEjB,OACEvH,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAD,EAAAA,KAACiK,EAAA,CAAe,MAAM,UACpB,SAAA,CAAA/J,EAAAA,IAACgK,EAAA,CACC,KAAK,QACL,UAAU,iBACV,OAAQL,IAAY,KACpB,QAAS,IAAMvC,EAAS,CAAE,GAAI,YAAa,EAC5C,SAAA,cAAA,CAAA,EAGDpH,EAAAA,IAACgK,EAAA,CACC,KAAK,QACL,UAAU,iBACV,OAAQL,IAAY,QACpB,QAAS,IAAMvC,EAAS,CAAE,GAAI,qBAAsB,OAAQ,CAAE,QAAS,OAAA,EAAW,EACnF,SAAA,OAAA,CAAA,EAGDpH,EAAAA,IAACgK,EAAA,CACC,KAAK,QACL,UAAU,iBACV,OAAQL,IAAY,eACpB,QAAS,IACPvC,EAAS,CAAE,GAAI,qBAAsB,OAAQ,CAAE,QAAS,cAAA,EAAkB,EAE7E,SAAA,cAAA,CAAA,CAED,EACF,EACApH,EAAAA,IAAC+J,EAAA,CAAe,MAAM,QACpB,SAAA/J,EAAAA,IAACgK,EAAA,CACC,KAAK,QACL,UAAU,iBACV,OAAQL,IAAY,WACpB,QAAS,IAAMvC,EAAS,CAAE,GAAI,qBAAsB,OAAQ,CAAE,QAAS,UAAA,EAAc,EACtF,SAAA,UAAA,CAAA,CAED,CACF,CAAA,EACF,CAEJ"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{an as E,r as g,u as c,a2 as L,G as $,ao as R,j as r,ag as C,ak as S,J as b,ac as w,P as K}from"./main-DkQCGPBX.js";const D=(n,e)=>{const t=n.entityId?e.find(s=>s.id===n.entityId):void 0;return t?E(t)?"Promote to fix":`Add to ${t.id}'s fixes`:"Promote to idea"},M=n=>{if(!n)return"";const e=Math.floor((Date.now()-Date.parse(n))/864e5);return Number.isFinite(e)?e<=0?"today":e===1?"1 day ago":`${e} days ago`:""},F="9999-12-31T23:59:59.999Z",z=n=>[...n].sort((e,t)=>(e.occurredAt??F).localeCompare(t.occurredAt??F)),j=(n,e)=>`${n}:${e}`;function O(n){return n.filter(e=>e.outcome==="error").map(e=>{const t=e.planId??e.id;return{id:j("agent-run",t),sourceKind:"agent-run",sourceKey:t,entityId:e.planId,entityTitle:e.planTitle,title:`${e.planTitle} — ${e.taskKind} failed`,reason:e.reason??"The run ended in error with no reason recorded.",occurredAt:e.endedAt,thread:[],status:"open"}})}function q(n){return n.filter(e=>e.status==="fail").map(e=>({id:j("check",e.name),sourceKind:"check",sourceKey:e.name,title:`"${e.name}" check is failing`,reason:`The command was \`${e.cmd}\`.`,output:e.output||void 0,occurredAt:e.lastRun??void 0,thread:[],status:"open"}))}function J(n){return n.filter(e=>{var t;return((t=e.pr)==null?void 0:t.reviewDecision)==="changes-requested"}).map(e=>{const t=e.pr,s=`${t.number}:${t.headSha??"unknown"}`;return{id:j("pr-review",s),sourceKind:"pr-review",sourceKey:s,entityId:e.id,entityTitle:e.title,title:`${e.title} — PR review requested changes`,reason:`PR #${t.number} has unresolved change requests.`,thread:[],status:"open"}})}function B(n,e){return n.map(t=>{var l;const s=e.find(i=>i.issueSource===t.id);if(s!=null&&s.id)return{...t,promotedFixId:s.id};const d=t.entityId?e.find(i=>i.id===t.entityId):void 0;return((l=d==null?void 0:d.fixes)==null?void 0:l.some(i=>i.source==="issue"&&i.text===t.title))&&(d!=null&&d.id)?{...t,promotedFixId:d.id}:t}).filter(t=>{const s=t.promotedFixId&&e.find(d=>d.id===t.promotedFixId);return!(s&&s.status==="done")})}function G(n,e){return e.filter(t=>t.issueId===n.id).sort((t,s)=>t.endedAt.localeCompare(s.endedAt)).map(t=>({kind:"log",date:t.endedAt.slice(0,10),from:"agent",text:t.outcome==="done"?"Ran a fix agent — finished.":t.outcome==="error"?`Ran a fix agent — failed: ${t.reason??"no reason recorded"}`:"Ran a fix agent — superseded by a newer run."}))}const U=()=>{var P;const[n,e]=g.useState(null),[t,s]=g.useState(null),d=c(o=>o.taskLog),m=c(o=>o.taskLogLoading),l=c(o=>o.loadTaskLog),i=c(o=>o.plans),p=c(o=>o.ideaEntries),f=c(o=>o.agentStatus),a=c(o=>o.launchIssueFix),h=c(o=>o.loadPlans),x=c(o=>o.loadIdeas),{checks:u}=L(),I=$();g.useEffect(()=>{l()},[l]);const k=g.useMemo(()=>((i==null?void 0:i.entries)??[]).filter(o=>o.id!=null),[i]),y=g.useMemo(()=>[...k,...p].filter(o=>o.id!=null),[k,p]),T=g.useMemo(()=>{const o=z([...O(d),...q(u),...J(y)]);return B(o,y).map(v=>({...v,thread:G(v,d)}))},[d,u,y]),A=async o=>{s(o.id);try{await R(o),await Promise.all([h(),x()])}finally{s(null)}},N=(P=f.find(o=>o.taskKind==="issue-fix"&&o.status!=="done"&&o.status!=="error"&&o.status!=="superseded"))==null?void 0:P.issueId;return{issues:T,entities:y,taskLogLoading:m,expandedId:n,setExpandedId:e,openEntity:I,fixingIssueId:N,launchIssueFix:a,promotingId:t,handlePromote:A}},V=({issue:n,expanded:e,onToggle:t,onOpen:s,fixing:d,fixDisabled:m,onFix:l,promoteLabel:i,promoting:p,promoteDisabled:f,onPromote:a,onOpenPromoted:h})=>{const x=async()=>{try{await l()}catch(I){alert(I.message)}},u=async()=>{try{await a()}catch(I){alert(I.message)}};return r.jsxs("div",{className:"border-b border-black/10 last:border-b-0",children:[r.jsxs("div",{className:"flex items-center gap-3 py-2.5",children:[s&&r.jsx("button",{type:"button",onClick:s,"aria-label":`Open ${n.entityTitle}`,className:"bg-transparent border-none p-0 cursor-pointer",children:r.jsx(C,{id:n.entityId})}),r.jsx("button",{type:"button",onClick:t,"aria-expanded":e,className:"flex-1 min-w-0 truncate text-left bg-transparent border-none p-0 cursor-pointer",children:n.title}),r.jsx("span",{className:"opacity-50 text-xs whitespace-nowrap",children:M(n.occurredAt)})]}),e&&r.jsxs("div",{className:"flex flex-col gap-3 pb-4",children:[r.jsx("p",{children:n.reason}),n.output&&r.jsx("pre",{className:"max-h-48 overflow-auto whitespace-pre-wrap text-left font-mono text-2xs opacity-70",children:n.output}),n.thread.length>0&&r.jsx(S,{messages:n.thread,undo:null,undoing:!1,onUndo:()=>{}}),r.jsx("div",{className:"flex items-center gap-3",children:n.promotedFixId?r.jsxs(b,{size:"small",onClick:h,children:["View ",n.promotedFixId]}):r.jsxs(r.Fragment,{children:[r.jsx(b,{size:"small",onClick:x,disabled:m,children:d?"Fixing…":"Fix it here"}),d&&r.jsx(w,{size:"small",label:"Agent fixing…"}),r.jsx(b,{size:"small",onClick:u,disabled:f,children:p?"Promoting…":i}),p&&r.jsx(w,{size:"small",label:"Promoting…"})]})})]})]})},_=()=>{const{issues:n,entities:e,taskLogLoading:t,expandedId:s,setExpandedId:d,openEntity:m,fixingIssueId:l,launchIssueFix:i,promotingId:p,handlePromote:f}=U();return r.jsxs("div",{children:[r.jsx(K,{children:"Issues"}),r.jsx("p",{className:"opacity-50 mb-6",children:"Every failing agent run, red check, and PR review, oldest first."}),t&&n.length===0&&r.jsx("p",{className:"opacity-50",children:"Loading…"}),!t&&n.length===0&&r.jsx("p",{className:"opacity-50",children:"Nothing broken right now."}),n.length>0&&r.jsx("div",{className:"flex flex-col",children:n.map(a=>{var x;const h=a.promotedFixId?((x=e.find(u=>u.id===a.promotedFixId))==null?void 0:x.title)??a.promotedFixId:void 0;return r.jsx(V,{issue:a,expanded:s===a.id,onToggle:()=>d(u=>u===a.id?null:a.id),onOpen:a.entityId&&a.entityTitle?()=>m(a.entityId,a.entityTitle):void 0,fixing:l===a.id,fixDisabled:l!==void 0,onFix:()=>i(a.id,a.title,a.reason,a.output),promoteLabel:D(a,e),promoting:p===a.id,promoteDisabled:p!==null,onPromote:()=>f(a),onOpenPromoted:a.promotedFixId?()=>m(a.promotedFixId,h):void 0},a.id)})})]})};export{_ as IssuesPage};
|
|
2
|
-
//# sourceMappingURL=index-BY8Yo_l0.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{u as h,E as L,r as i,j as e,F as v,J as S,R as u,y as T,g as y,z as f,P as A}from"./main-DkQCGPBX.js";const m=s=>String(s).padStart(2,"0"),_=s=>{const a=new Date(s);return`${a.getFullYear()}-${m(a.getMonth()+1)}-${m(a.getDate())}`},b=s=>new Date(s).toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}),j=s=>{const a=new Date(s);return`${m(a.getHours())}:${m(a.getMinutes())}:${m(a.getSeconds())}`},R=()=>{const s=h(t=>t.taskLog),a=h(t=>t.taskLogLoading),n=h(t=>t.loadTaskLog),{taskId:o}=L({from:"/tasks"}),l=i.useRef(null);i.useEffect(()=>{n()},[n]),i.useEffect(()=>{var c;if(!o)return;const t=(c=l.current)==null?void 0:c.querySelector(".task-row-highlighted");t==null||t.scrollIntoView({behavior:"smooth",block:"center"})},[o]);const r=[...s].sort((t,c)=>c.endedAt.localeCompare(t.endedAt)),x=[];for(const t of r){const c=_(t.endedAt),d=x.at(-1);(d==null?void 0:d.key)===c?d.entries.push(t):x.push({key:c,entries:[t]})}return{taskLogLoading:a,groups:x,taskId:o,containerRef:l}},E="outline-[rgba(200,154,90,0.5)]",D={done:"rgba(143, 185, 150, 0.25)",superseded:"rgba(212, 163, 115, 0.25)",error:"rgba(201, 139, 139, 0.25)"},I=({id:s})=>{const[a,n]=i.useState(null),[o,l]=i.useState(!1),[r,x]=i.useState(0);i.useEffect(()=>{let c=!1,d;n(null),l(!1);const g=k=>{v(s).then(w=>{c||n(w.lines??[])}).catch(()=>{if(!c){if(k>0){d=setTimeout(()=>g(k-1),700);return}l(!0),n([])}})};return g(3),()=>{c=!0,d&&clearTimeout(d)}},[s,r]);const t=e.jsx(S,{variant:"ghost",size:"small",onClick:()=>x(c=>c+1),children:"Retry"});return a===null?e.jsx("p",{className:"opacity-50 m-0",children:"Loading…"}):o?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"opacity-50 m-0",children:"Couldn't load this task's output."}),t]}):a.length===0?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"opacity-50 m-0",children:"No output recorded."}),t]}):e.jsx("pre",{className:"font-mono text-xs m-0 max-h-[320px] overflow-y-auto whitespace-pre-wrap",children:a.join(`
|
|
2
|
-
`)})},C={phase:"Phase run",audit:"Audit","batch-reconcile":"Batch reconcile","batch-draft":"Batch draft","run-all":"Run all phases",draft:"Draft",extend:"Extend",suggest:"Suggest ideas","commit-suggest":"Commit suggest","overlap-check":"Overlap check",prioritise:"Prioritise queue",sync:"Sync",reconcile:"Reconcile","fix-review":"Fix review","resolve-conflict":"Resolve conflict",feedback:"Feedback reply","pr-review":"PR review","issue-fix":"Issue fix"},N="grid grid-cols-[20px_116px_minmax(0,1fr)_88px_150px_72px] gap-2.5 items-center max-lg:grid-cols-[20px_116px_minmax(0,1fr)_88px_72px] max-[480px]:grid-cols-1 max-[480px]:gap-1",$=({size:s=14,className:a})=>e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",className:a,children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),P=({entry:s,highlighted:a})=>{const[n,o]=i.useState(a);i.useEffect(()=>{a&&o(!0)},[a]);const l=()=>o(r=>!r);return e.jsxs("div",{className:a?`task-row-highlighted flex flex-col gap-1 rounded-[10px] outline outline-2 outline-offset-[-2px] ${E}`:"flex flex-col gap-1 rounded-[10px]",children:[e.jsx("div",{role:"button",tabIndex:0,"aria-expanded":n,onClick:l,onKeyDown:r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),l())},className:"group cursor-pointer rounded-[10px]",children:e.jsx(u,{size:"small",texture:"canvas",className:"plan-row-card",children:e.jsxs("div",{className:N,children:[e.jsx("span",{className:"inline-flex items-center opacity-50",children:e.jsx($,{className:"group-aria-expanded:rotate-90"})}),e.jsx("span",{className:"font-semibold whitespace-nowrap overflow-hidden",children:C[s.taskKind]??s.taskKind}),e.jsx("span",{className:"overflow-hidden text-ellipsis whitespace-nowrap opacity-70",children:s.planTitle}),e.jsx("span",{className:"text-sm opacity-50 whitespace-nowrap",children:T[s.agentId]}),e.jsxs("span",{className:"max-lg:hidden font-mono text-xs opacity-[0.55] whitespace-nowrap",children:[j(s.startedAt),"–",j(s.endedAt)]}),e.jsx("div",{className:"flex items-center",children:e.jsx(y,{size:"small",fillColor:D[s.outcome],textColor:s.outcome==="done"?f.accentGreenDark:s.outcome==="superseded"?f.accentAmberDark:f.accentRoseDark,children:s.outcome})})]})})}),n&&e.jsxs(u,{size:"small",texture:"kraft",className:"plan-row-card",children:[s.outcome==="error"&&s.reason&&e.jsx("p",{className:"m-0 mb-2 text-sm text-state-danger",children:s.reason}),e.jsx(I,{id:s.id})]})]})},p="text-sm font-semibold whitespace-nowrap overflow-hidden",K=({groups:s,highlightedId:a})=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(u,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:N,children:[e.jsx("span",{}),e.jsx("span",{className:`${p} opacity-60`,children:"Task"}),e.jsx("span",{className:`${p} opacity-60`,children:"Plan"}),e.jsx("span",{className:`${p} opacity-60`,children:"Agent"}),e.jsx("span",{className:`max-lg:hidden ${p} opacity-60`,children:"Time"}),e.jsx("span",{className:`${p} opacity-60`,children:"Outcome"})]})}),s.map(n=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(u,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx("span",{className:`${p} opacity-75`,children:b(n.entries[0].endedAt)})}),n.entries.map(o=>e.jsx(P,{entry:o,highlighted:o.id===a},o.id))]},n.key))]}),F=()=>{const{taskLogLoading:s,groups:a,taskId:n,containerRef:o}=R();return e.jsxs("div",{ref:o,children:[e.jsx(A,{children:"Tasks"}),s&&e.jsx("p",{className:"opacity-50",children:"Loading…"}),!s&&a.length===0&&e.jsx("p",{className:"opacity-50",children:"No tasks have run yet."}),!s&&a.length>0&&e.jsx(K,{groups:a,highlightedId:n})]})};export{F as TasksPage};
|
|
3
|
-
//# sourceMappingURL=index-BxRIu8zx.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BxRIu8zx.js","sources":["../../../src/app/features/tasks/helpers/format-task-log.ts","../../../src/app/features/tasks/hooks/use-tasks-page.ts","../../../src/app/features/tasks/constants.ts","../../../src/app/features/tasks/views/task-log-lines.tsx","../../../src/app/features/tasks/views/task-row.tsx","../../../src/app/features/tasks/views/task-list.tsx","../../../src/app/features/tasks/tasks-page.tsx"],"sourcesContent":["import type { TaskLogEntry } from '@/types/index';\n\nexport interface TaskGroup {\n key: string;\n entries: TaskLogEntry[];\n}\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\nexport const dayKey = (iso: string) => {\n const d = new Date(iso);\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n};\n\nexport const formatDayHeader = (iso: string) =>\n new Date(iso).toLocaleDateString(undefined, {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\nexport const formatTime = (iso: string) => {\n const d = new Date(iso);\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n};\n","import { useAppStore } from '@/app/stores/app-store';\nimport { useSearch } from '@tanstack/react-router';\nimport { useEffect, useRef } from 'react';\nimport { type TaskGroup, dayKey } from '../helpers';\n\nexport const useTasksPage = () => {\n const taskLog = useAppStore((s) => s.taskLog);\n const taskLogLoading = useAppStore((s) => s.taskLogLoading);\n const loadTaskLog = useAppStore((s) => s.loadTaskLog);\n const { taskId } = useSearch({ from: '/tasks' });\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n loadTaskLog();\n }, [loadTaskLog]);\n\n useEffect(() => {\n if (!taskId) return;\n const row = containerRef.current?.querySelector('.task-row-highlighted');\n row?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, [taskId]);\n\n const sorted = [...taskLog].sort((a, b) => b.endedAt.localeCompare(a.endedAt));\n\n const groups: TaskGroup[] = [];\n for (const entry of sorted) {\n const key = dayKey(entry.endedAt);\n const group = groups.at(-1);\n if (group?.key === key) group.entries.push(entry);\n else groups.push({ key, entries: [entry] });\n }\n\n return { taskLogLoading, groups, taskId, containerRef };\n};\n","import type { TaskLogEntry } from '@/types/index';\n\nexport const HIGHLIGHT_OUTLINE_CLASS = 'outline-[rgba(200,154,90,0.5)]';\n\nexport const TASK_OUTCOME_STAMP_FILL: Record<TaskLogEntry['outcome'], string> = {\n done: 'rgba(143, 185, 150, 0.25)',\n superseded: 'rgba(212, 163, 115, 0.25)',\n error: 'rgba(201, 139, 139, 0.25)',\n};\n","import { fetchTaskLogLines } from '@/app/services/content/docs-api';\nimport { Button } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\n\nexport interface TaskLogLinesProps {\n id: string;\n}\n\nexport const TaskLogLines = ({ id }: TaskLogLinesProps) => {\n const [lines, setLines] = useState<string[] | null>(null);\n const [failed, setFailed] = useState(false);\n const [attempt, setAttempt] = useState(0);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: attempt is the retry trigger (re-runs the fetch), not a value read in the body.\n useEffect(() => {\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n setLines(null);\n setFailed(false);\n // Auto-retry first (dev server briefly drops requests on hot reload); manual Retry only if it stays down.\n const load = (remaining: number) => {\n fetchTaskLogLines(id)\n .then((data) => {\n if (cancelled) return;\n setLines(data.lines ?? []);\n })\n .catch(() => {\n if (cancelled) return;\n if (remaining > 0) {\n timer = setTimeout(() => load(remaining - 1), 700);\n return;\n }\n setFailed(true);\n setLines([]);\n });\n };\n load(3);\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [id, attempt]);\n\n const retry = (\n <Button variant=\"ghost\" size=\"small\" onClick={() => setAttempt((n) => n + 1)}>\n Retry\n </Button>\n );\n\n if (lines === null) return <p className=\"opacity-50 m-0\">Loading…</p>;\n if (failed)\n return (\n <div className=\"flex items-center gap-2\">\n <p className=\"opacity-50 m-0\">Couldn't load this task's output.</p>\n {retry}\n </div>\n );\n if (lines.length === 0)\n return (\n <div className=\"flex items-center gap-2\">\n <p className=\"opacity-50 m-0\">No output recorded.</p>\n {retry}\n </div>\n );\n return (\n <pre className=\"font-mono text-xs m-0 max-h-[320px] overflow-y-auto whitespace-pre-wrap\">\n {lines.join('\\n')}\n </pre>\n );\n};\n","import { color } from '@/app/styles/tokens';\nimport { AGENT_LABELS, type TaskKind, type TaskLogEntry } from '@/types/index';\nimport { Card, Stamp } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\nimport { HIGHLIGHT_OUTLINE_CLASS, TASK_OUTCOME_STAMP_FILL } from '../constants';\nimport { formatTime } from '../helpers';\nimport { TaskLogLines } from './task-log-lines';\n\nconst TASK_KIND_LABELS: Record<TaskKind, string> = {\n phase: 'Phase run',\n audit: 'Audit',\n 'batch-reconcile': 'Batch reconcile',\n 'batch-draft': 'Batch draft',\n 'run-all': 'Run all phases',\n draft: 'Draft',\n extend: 'Extend',\n suggest: 'Suggest ideas',\n 'commit-suggest': 'Commit suggest',\n 'overlap-check': 'Overlap check',\n prioritise: 'Prioritise queue',\n sync: 'Sync',\n reconcile: 'Reconcile',\n 'fix-review': 'Fix review',\n 'resolve-conflict': 'Resolve conflict',\n feedback: 'Feedback reply',\n 'pr-review': 'PR review',\n 'issue-fix': 'Issue fix',\n};\n\nexport const TASK_ROWS_GRID_CLASS =\n 'grid grid-cols-[20px_116px_minmax(0,1fr)_88px_150px_72px] gap-2.5 items-center max-lg:grid-cols-[20px_116px_minmax(0,1fr)_88px_72px] max-[480px]:grid-cols-1 max-[480px]:gap-1';\n\nconst ChevronRightIcon = ({ size = 14, className }: { size?: number; className?: string }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={className}\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nexport interface TaskRowProps {\n entry: TaskLogEntry;\n highlighted: boolean;\n}\n\nexport const TaskRow = ({ entry, highlighted }: TaskRowProps) => {\n const [expanded, setExpanded] = useState(highlighted);\n useEffect(() => {\n if (highlighted) setExpanded(true);\n }, [highlighted]);\n const toggle = () => setExpanded((v) => !v);\n\n return (\n <div\n className={\n highlighted\n ? `task-row-highlighted flex flex-col gap-1 rounded-[10px] outline outline-2 outline-offset-[-2px] ${HIGHLIGHT_OUTLINE_CLASS}`\n : 'flex flex-col gap-1 rounded-[10px]'\n }\n >\n {/* biome-ignore lint/a11y/useSemanticElements: the clickable row wraps a Card whose block layout a native <button> would break; keyboard toggling is wired on the div. */}\n <div\n role=\"button\"\n tabIndex={0}\n aria-expanded={expanded}\n onClick={toggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n }}\n className=\"group cursor-pointer rounded-[10px]\"\n >\n <Card size=\"small\" texture=\"canvas\" className=\"plan-row-card\">\n <div className={TASK_ROWS_GRID_CLASS}>\n <span className=\"inline-flex items-center opacity-50\">\n <ChevronRightIcon className=\"group-aria-expanded:rotate-90\" />\n </span>\n <span className=\"font-semibold whitespace-nowrap overflow-hidden\">\n {TASK_KIND_LABELS[entry.taskKind] ?? entry.taskKind}\n </span>\n <span className=\"overflow-hidden text-ellipsis whitespace-nowrap opacity-70\">\n {entry.planTitle}\n </span>\n <span className=\"text-sm opacity-50 whitespace-nowrap\">\n {AGENT_LABELS[entry.agentId]}\n </span>\n <span className=\"max-lg:hidden font-mono text-xs opacity-[0.55] whitespace-nowrap\">\n {formatTime(entry.startedAt)}–{formatTime(entry.endedAt)}\n </span>\n <div className=\"flex items-center\">\n <Stamp\n size=\"small\"\n fillColor={TASK_OUTCOME_STAMP_FILL[entry.outcome]}\n textColor={\n entry.outcome === 'done'\n ? color.accentGreenDark\n : entry.outcome === 'superseded'\n ? color.accentAmberDark\n : color.accentRoseDark\n }\n >\n {entry.outcome}\n </Stamp>\n </div>\n </div>\n </Card>\n </div>\n {expanded && (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n {entry.outcome === 'error' && entry.reason && (\n <p className=\"m-0 mb-2 text-sm text-state-danger\">{entry.reason}</p>\n )}\n <TaskLogLines id={entry.id} />\n </Card>\n )}\n </div>\n );\n};\n","import { Card } from '@dendelion/paper-ui';\nimport { type TaskGroup, formatDayHeader } from '../helpers';\nimport { TASK_ROWS_GRID_CLASS, TaskRow } from './task-row';\n\nconst headerLabelClassName = 'text-sm font-semibold whitespace-nowrap overflow-hidden';\n\nexport interface TaskListProps {\n groups: TaskGroup[];\n highlightedId: string | undefined;\n}\n\nexport const TaskList = ({ groups, highlightedId }: TaskListProps) => (\n <div className=\"flex flex-col gap-1\">\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className={TASK_ROWS_GRID_CLASS}>\n <span />\n <span className={`${headerLabelClassName} opacity-60`}>Task</span>\n <span className={`${headerLabelClassName} opacity-60`}>Plan</span>\n <span className={`${headerLabelClassName} opacity-60`}>Agent</span>\n <span className={`max-lg:hidden ${headerLabelClassName} opacity-60`}>Time</span>\n <span className={`${headerLabelClassName} opacity-60`}>Outcome</span>\n </div>\n </Card>\n {groups.map((group) => (\n <div key={group.key} className=\"flex flex-col gap-1\">\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <span className={`${headerLabelClassName} opacity-75`}>\n {formatDayHeader(group.entries[0].endedAt)}\n </span>\n </Card>\n {group.entries.map((entry) => (\n <TaskRow key={entry.id} entry={entry} highlighted={entry.id === highlightedId} />\n ))}\n </div>\n ))}\n </div>\n);\n","import { PageTitle } from '@/app/components/page-title';\nimport { useTasksPage } from './hooks';\nimport { TaskList } from './views';\n\nexport const TasksPage = () => {\n const { taskLogLoading, groups, taskId, containerRef } = useTasksPage();\n\n return (\n <div ref={containerRef}>\n <PageTitle>Tasks</PageTitle>\n {taskLogLoading && <p className=\"opacity-50\">Loading…</p>}\n {!taskLogLoading && groups.length === 0 && (\n <p className=\"opacity-50\">No tasks have run yet.</p>\n )}\n {!taskLogLoading && groups.length > 0 && <TaskList groups={groups} highlightedId={taskId} />}\n </div>\n );\n};\n"],"names":["pad","n","dayKey","iso","d","formatDayHeader","formatTime","useTasksPage","taskLog","useAppStore","s","taskLogLoading","loadTaskLog","taskId","useSearch","containerRef","useRef","useEffect","row","_a","sorted","a","b","groups","entry","key","group","HIGHLIGHT_OUTLINE_CLASS","TASK_OUTCOME_STAMP_FILL","TaskLogLines","id","lines","setLines","useState","failed","setFailed","attempt","setAttempt","cancelled","timer","load","remaining","fetchTaskLogLines","data","retry","jsx","Button","jsxs","TASK_KIND_LABELS","TASK_ROWS_GRID_CLASS","ChevronRightIcon","size","className","TaskRow","highlighted","expanded","setExpanded","toggle","v","e","Card","AGENT_LABELS","Stamp","color","headerLabelClassName","TaskList","highlightedId","TasksPage","PageTitle"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{c as m,r as o,X as u,U as h,j as e,R as j,g as d,Y as g,Z as v,_ as p,a0 as i,z as c,a1 as r,P as N}from"./main-DkQCGPBX.js";const f=async()=>{const s=await fetch(m("/api/stats"));if(!s.ok)throw new Error(`Failed to fetch stats: ${s.status}`);return s.json()},y=()=>{const[s,a]=o.useState(null),[t,x]=o.useState(!1);return o.useEffect(()=>{f().then(a).catch(()=>x(!0))},[]),{stats:s,loadFailed:t}},T=["open",...u],S={...h,open:"Open"},b={allowed:"success",warning:"warning",rejected:"error"},l=({title:s,children:a})=>e.jsx("div",{className:"flex-[1_1_260px] max-w-[360px] max-[480px]:flex-[1_1_100%] max-[480px]:max-w-none",children:e.jsx(j,{size:"small",texture:"kraft",className:"h-full",children:e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx("span",{className:"font-handwritten text-xs font-semibold opacity-[0.55]",children:s}),a]})})}),n=({label:s,value:a})=>e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"opacity-70",children:s}),e.jsx("span",{className:"font-semibold",children:a})]}),C=({capacity:s})=>{const[a,t]=o.useState(()=>Date.now());return o.useEffect(()=>{const x=setInterval(()=>t(Date.now()),3e4);return()=>clearInterval(x)},[]),e.jsx(l,{title:"Claude capacity",children:s===null?e.jsx("p",{className:"opacity-50 m-0",children:"No agent run has reported capacity yet."}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(d,{size:"small",variant:b[g(s.snapshot.status)],children:s.snapshot.status}),s.snapshot.overage&&e.jsx(d,{size:"small",variant:"warning",children:"overage"})]}),s.snapshot.rateLimitType&&e.jsx(n,{label:"Window",value:s.snapshot.rateLimitType}),s.snapshot.resetsAt!==void 0&&e.jsx(n,{label:"Resets",value:new Date(v(s.snapshot.resetsAt)).toLocaleTimeString()}),e.jsxs("span",{className:"text-2xs opacity-50",children:["as of last agent run,"," ",p(Math.max(0,a-Date.parse(s.capturedAt)))," ago"]})]})})},L=({sourceLines:s,testLines:a})=>e.jsxs(l,{title:"Codebase size",children:[e.jsx(n,{label:"Source lines",value:s}),e.jsx(n,{label:"Test lines",value:a})]}),w=s=>`${Math.round(s*100)}%`,A=({comments:s})=>e.jsxs(l,{title:"Comment ratio",children:[e.jsx(i,{value:s.ratio*100,color:c.accentSlate}),e.jsx(n,{label:"Ratio",value:w(s.ratio)}),e.jsx(n,{label:"Comment lines",value:s.commentLines}),e.jsx(n,{label:"Source lines",value:s.sourceLines})]}),M=({entitiesByStatus:s})=>e.jsxs(l,{title:"Entities by status",children:[T.filter(a=>s[a]).map(a=>e.jsx(n,{label:S[a],value:s[a]},a)),Object.keys(s).length===0&&e.jsx("p",{className:"opacity-50 m-0",children:"No entities yet."})]}),E=({medianPhaseDurationMs:s})=>e.jsx(l,{title:"Median phase duration",children:s===null?e.jsx("p",{className:"opacity-50 m-0",children:"No phase runs recorded yet."}):e.jsx(n,{label:"Median",value:p(s)})}),k=({mostExpensiveIdeas:s})=>e.jsxs(l,{title:"Most expensive ideas",children:[s.length===0&&e.jsx("p",{className:"opacity-50 m-0",children:"No usage recorded yet."}),s.map(a=>e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsx(n,{label:a.planId,value:`${r(a.inputTokens)} in · ${r(a.outputTokens)} out`}),e.jsx("span",{className:"text-2xs opacity-50 truncate",children:a.planTitle})]},a.planId))]}),_=({openQuestions:s,decisions:a})=>e.jsxs(l,{title:"Notes",children:[e.jsx(n,{label:"Open questions",value:s}),e.jsx(n,{label:"Decisions",value:a})]}),P=({tasksPerWeek:s})=>{const a=Math.max(1,...s.map(t=>t.count));return e.jsxs(l,{title:"Tasks per week",children:[s.length===0&&e.jsx("p",{className:"opacity-50 m-0",children:"No tasks run yet."}),s.map(t=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(n,{label:t.week,value:t.count}),e.jsx(i,{value:t.count,max:a,color:c.accentAmber,height:4})]},t.week))]})},D=({testCoveragePct:s})=>e.jsx(l,{title:"Test coverage",children:s===null?e.jsx("p",{className:"opacity-50 m-0",children:"Run `pnpm test` to generate a coverage report."}):e.jsxs(e.Fragment,{children:[e.jsx(i,{value:s,color:c.accentGreen}),e.jsx(n,{label:"Line coverage",value:`${Math.round(s)}%`})]})}),R=({usagePerWeek:s})=>{const a=Math.max(1,...s.map(t=>t.agentMinutes));return e.jsxs(l,{title:"Usage per week",children:[s.length===0&&e.jsx("p",{className:"opacity-50 m-0",children:"No usage recorded yet."}),s.map(t=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(n,{label:t.week,value:`${t.agentMinutes}m`}),e.jsx(i,{value:t.agentMinutes,max:a,color:c.accentAmber,height:4}),e.jsxs("span",{className:"text-2xs opacity-50",children:[r(t.inputTokens)," in · ",r(t.outputTokens)," out"]})]},t.week))]})},I=({stats:s})=>e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-wrap items-start gap-2.5",children:[e.jsx(A,{comments:s.comments}),e.jsx(D,{testCoveragePct:s.testCoveragePct}),e.jsx(L,{sourceLines:s.comments.sourceLines,testLines:s.testLines}),e.jsx(M,{entitiesByStatus:s.entitiesByStatus}),e.jsx(_,{openQuestions:s.openQuestions,decisions:s.decisions}),e.jsx(P,{tasksPerWeek:s.tasksPerWeek}),e.jsx(R,{usagePerWeek:s.usagePerWeek}),e.jsx(E,{medianPhaseDurationMs:s.medianPhaseDurationMs}),e.jsx(k,{mostExpensiveIdeas:s.mostExpensiveIdeas}),e.jsx(C,{capacity:s.capacity})]}),e.jsxs("p",{className:"opacity-[0.4] text-2xs mt-6",children:["Generated ",new Date(s.generatedAt).toLocaleString()]})]}),F=()=>{const{stats:s,loadFailed:a}=y();return e.jsxs("div",{children:[e.jsx(N,{children:"Stats"}),e.jsx("p",{className:"opacity-50 mb-6",children:"A read-only look at project health — every number here is informational, none of them gate anything."}),a&&e.jsx("p",{className:"opacity-50",children:"Couldn't load stats."}),!a&&!s&&e.jsx("p",{className:"opacity-50",children:"Loading…"}),s&&e.jsx(I,{stats:s})]})};export{F as StatsPage};
|
|
2
|
-
//# sourceMappingURL=index-C3R9IAt7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-C3R9IAt7.js","sources":["../../../src/app/services/content/stats-api.ts","../../../src/app/features/stats/hooks/use-stats-page.ts","../../../src/app/features/stats/constants.ts","../../../src/app/features/stats/views/stat-card.tsx","../../../src/app/features/stats/views/claude-capacity-card.tsx","../../../src/app/features/stats/views/codebase-size-card.tsx","../../../src/app/features/stats/helpers/format-stats.ts","../../../src/app/features/stats/views/comment-ratio-card.tsx","../../../src/app/features/stats/views/entities-by-status-card.tsx","../../../src/app/features/stats/views/median-phase-duration-card.tsx","../../../src/app/features/stats/views/most-expensive-ideas-card.tsx","../../../src/app/features/stats/views/notes-card.tsx","../../../src/app/features/stats/views/tasks-per-week-card.tsx","../../../src/app/features/stats/views/test-coverage-card.tsx","../../../src/app/features/stats/views/usage-per-week-card.tsx","../../../src/app/features/stats/views/stats-grid.tsx","../../../src/app/features/stats/stats-page.tsx"],"sourcesContent":["import type { ProjectStats } from '@/types/index';\nimport { apiUrl } from '../api-base';\n\nexport const fetchStats = async () => {\n const res = await fetch(apiUrl('/api/stats'));\n if (!res.ok) throw new Error(`Failed to fetch stats: ${res.status}`);\n return res.json() as Promise<ProjectStats>;\n};\n","import { fetchStats } from '@/app/services/content';\nimport type { ProjectStats } from '@/types/index';\nimport { useEffect, useState } from 'react';\n\nexport const useStatsPage = () => {\n const [stats, setStats] = useState<ProjectStats | null>(null);\n const [loadFailed, setLoadFailed] = useState(false);\n\n useEffect(() => {\n fetchStats()\n .then(setStats)\n .catch(() => setLoadFailed(true));\n }, []);\n\n return { stats, loadFailed };\n};\n","import { STATUS_LABEL } from '@/app/features/plans/constants';\nimport { type EntityStatus, PLAN_STATUSES } from '@/types/index';\n\nexport const ENTITY_STATUS_ORDER: EntityStatus[] = ['open', ...PLAN_STATUSES];\n\nexport const ENTITY_STATUS_LABEL: Record<EntityStatus, string> = { ...STATUS_LABEL, open: 'Open' };\n\nexport const CAPACITY_STAMP = {\n allowed: 'success',\n warning: 'warning',\n rejected: 'error',\n} as const;\n","import { Card } from '@dendelion/paper-ui';\nimport type { ReactNode } from 'react';\n\nexport interface StatCardProps {\n title: string;\n children: ReactNode;\n}\n\nexport const StatCard = ({ title, children }: StatCardProps) => (\n <div className=\"flex-[1_1_260px] max-w-[360px] max-[480px]:flex-[1_1_100%] max-[480px]:max-w-none\">\n <Card size=\"small\" texture=\"kraft\" className=\"h-full\">\n <div className=\"flex flex-col gap-3\">\n <span className=\"font-handwritten text-xs font-semibold opacity-[0.55]\">{title}</span>\n {children}\n </div>\n </Card>\n </div>\n);\n\nexport interface StatRowProps {\n label: string;\n value: ReactNode;\n}\n\nexport const StatRow = ({ label, value }: StatRowProps) => (\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"opacity-70\">{label}</span>\n <span className=\"font-semibold\">{value}</span>\n </div>\n);\n","import { formatDuration } from '@/core/phase-run';\nimport { capacityLevel, resetsAtMs } from '@/core/rate-limit';\nimport type { ProjectStats } from '@/types/index';\nimport { Stamp } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\nimport { CAPACITY_STAMP } from '../constants';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface ClaudeCapacityCardProps {\n capacity: ProjectStats['capacity'];\n}\n\nexport const ClaudeCapacityCard = ({ capacity }: ClaudeCapacityCardProps) => {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), 30_000);\n return () => clearInterval(id);\n }, []);\n return (\n <StatCard title=\"Claude capacity\">\n {capacity === null ? (\n <p className=\"opacity-50 m-0\">No agent run has reported capacity yet.</p>\n ) : (\n <>\n <div className=\"flex items-center gap-2\">\n <Stamp size=\"small\" variant={CAPACITY_STAMP[capacityLevel(capacity.snapshot.status)]}>\n {capacity.snapshot.status}\n </Stamp>\n {capacity.snapshot.overage && (\n <Stamp size=\"small\" variant=\"warning\">\n overage\n </Stamp>\n )}\n </div>\n {capacity.snapshot.rateLimitType && (\n <StatRow label=\"Window\" value={capacity.snapshot.rateLimitType} />\n )}\n {capacity.snapshot.resetsAt !== undefined && (\n <StatRow\n label=\"Resets\"\n value={new Date(resetsAtMs(capacity.snapshot.resetsAt)).toLocaleTimeString()}\n />\n )}\n <span className=\"text-2xs opacity-50\">\n as of last agent run,{' '}\n {formatDuration(Math.max(0, now - Date.parse(capacity.capturedAt)))} ago\n </span>\n </>\n )}\n </StatCard>\n );\n};\n","import { StatCard, StatRow } from './stat-card';\n\nexport interface CodebaseSizeCardProps {\n sourceLines: number;\n testLines: number;\n}\n\nexport const CodebaseSizeCard = ({ sourceLines, testLines }: CodebaseSizeCardProps) => (\n <StatCard title=\"Codebase size\">\n <StatRow label=\"Source lines\" value={sourceLines} />\n <StatRow label=\"Test lines\" value={testLines} />\n </StatCard>\n);\n","export const pct = (value: number) => `${Math.round(value * 100)}%`;\n","import { color } from '@/app/styles/tokens';\nimport type { ProjectStats } from '@/types/index';\nimport { Progress } from '@dendelion/paper-ui';\nimport { pct } from '../helpers';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface CommentRatioCardProps {\n comments: ProjectStats['comments'];\n}\n\nexport const CommentRatioCard = ({ comments }: CommentRatioCardProps) => (\n <StatCard title=\"Comment ratio\">\n <Progress value={comments.ratio * 100} color={color.accentSlate} />\n <StatRow label=\"Ratio\" value={pct(comments.ratio)} />\n <StatRow label=\"Comment lines\" value={comments.commentLines} />\n <StatRow label=\"Source lines\" value={comments.sourceLines} />\n </StatCard>\n);\n","import type { ProjectStats } from '@/types/index';\nimport { ENTITY_STATUS_LABEL, ENTITY_STATUS_ORDER } from '../constants';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface EntitiesByStatusCardProps {\n entitiesByStatus: ProjectStats['entitiesByStatus'];\n}\n\nexport const EntitiesByStatusCard = ({ entitiesByStatus }: EntitiesByStatusCardProps) => (\n <StatCard title=\"Entities by status\">\n {ENTITY_STATUS_ORDER.filter((status) => entitiesByStatus[status]).map((status) => (\n <StatRow key={status} label={ENTITY_STATUS_LABEL[status]} value={entitiesByStatus[status]} />\n ))}\n {Object.keys(entitiesByStatus).length === 0 && (\n <p className=\"opacity-50 m-0\">No entities yet.</p>\n )}\n </StatCard>\n);\n","import { formatDuration } from '@/core/phase-run';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface MedianPhaseDurationCardProps {\n medianPhaseDurationMs: number | null;\n}\n\nexport const MedianPhaseDurationCard = ({\n medianPhaseDurationMs,\n}: MedianPhaseDurationCardProps) => (\n <StatCard title=\"Median phase duration\">\n {medianPhaseDurationMs === null ? (\n <p className=\"opacity-50 m-0\">No phase runs recorded yet.</p>\n ) : (\n <StatRow label=\"Median\" value={formatDuration(medianPhaseDurationMs)} />\n )}\n </StatCard>\n);\n","import { formatTokens } from '@/core/phase-run';\nimport type { ProjectStats } from '@/types/index';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface MostExpensiveIdeasCardProps {\n mostExpensiveIdeas: ProjectStats['mostExpensiveIdeas'];\n}\n\nexport const MostExpensiveIdeasCard = ({ mostExpensiveIdeas }: MostExpensiveIdeasCardProps) => (\n <StatCard title=\"Most expensive ideas\">\n {mostExpensiveIdeas.length === 0 && <p className=\"opacity-50 m-0\">No usage recorded yet.</p>}\n {mostExpensiveIdeas.map((idea) => (\n <div key={idea.planId} className=\"flex flex-col gap-0.5\">\n <StatRow\n label={idea.planId}\n value={`${formatTokens(idea.inputTokens)} in · ${formatTokens(idea.outputTokens)} out`}\n />\n <span className=\"text-2xs opacity-50 truncate\">{idea.planTitle}</span>\n </div>\n ))}\n </StatCard>\n);\n","import { StatCard, StatRow } from './stat-card';\n\nexport interface NotesCardProps {\n openQuestions: number;\n decisions: number;\n}\n\nexport const NotesCard = ({ openQuestions, decisions }: NotesCardProps) => (\n <StatCard title=\"Notes\">\n <StatRow label=\"Open questions\" value={openQuestions} />\n <StatRow label=\"Decisions\" value={decisions} />\n </StatCard>\n);\n","import { color } from '@/app/styles/tokens';\nimport type { ProjectStats } from '@/types/index';\nimport { Progress } from '@dendelion/paper-ui';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface TasksPerWeekCardProps {\n tasksPerWeek: ProjectStats['tasksPerWeek'];\n}\n\nexport const TasksPerWeekCard = ({ tasksPerWeek }: TasksPerWeekCardProps) => {\n const max = Math.max(1, ...tasksPerWeek.map((w) => w.count));\n return (\n <StatCard title=\"Tasks per week\">\n {tasksPerWeek.length === 0 && <p className=\"opacity-50 m-0\">No tasks run yet.</p>}\n {tasksPerWeek.map((week) => (\n <div key={week.week} className=\"flex flex-col gap-1\">\n <StatRow label={week.week} value={week.count} />\n <Progress value={week.count} max={max} color={color.accentAmber} height={4} />\n </div>\n ))}\n </StatCard>\n );\n};\n","import { color } from '@/app/styles/tokens';\nimport { Progress } from '@dendelion/paper-ui';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface TestCoverageCardProps {\n testCoveragePct: number | null;\n}\n\nexport const TestCoverageCard = ({ testCoveragePct }: TestCoverageCardProps) => (\n <StatCard title=\"Test coverage\">\n {testCoveragePct === null ? (\n <p className=\"opacity-50 m-0\">Run `pnpm test` to generate a coverage report.</p>\n ) : (\n <>\n <Progress value={testCoveragePct} color={color.accentGreen} />\n <StatRow label=\"Line coverage\" value={`${Math.round(testCoveragePct)}%`} />\n </>\n )}\n </StatCard>\n);\n","import { color } from '@/app/styles/tokens';\nimport { formatTokens } from '@/core/phase-run';\nimport type { ProjectStats } from '@/types/index';\nimport { Progress } from '@dendelion/paper-ui';\nimport { StatCard, StatRow } from './stat-card';\n\nexport interface UsagePerWeekCardProps {\n usagePerWeek: ProjectStats['usagePerWeek'];\n}\n\nexport const UsagePerWeekCard = ({ usagePerWeek }: UsagePerWeekCardProps) => {\n const max = Math.max(1, ...usagePerWeek.map((w) => w.agentMinutes));\n return (\n <StatCard title=\"Usage per week\">\n {usagePerWeek.length === 0 && <p className=\"opacity-50 m-0\">No usage recorded yet.</p>}\n {usagePerWeek.map((week) => (\n <div key={week.week} className=\"flex flex-col gap-1\">\n <StatRow label={week.week} value={`${week.agentMinutes}m`} />\n <Progress value={week.agentMinutes} max={max} color={color.accentAmber} height={4} />\n <span className=\"text-2xs opacity-50\">\n {formatTokens(week.inputTokens)} in · {formatTokens(week.outputTokens)} out\n </span>\n </div>\n ))}\n </StatCard>\n );\n};\n","import type { ProjectStats } from '@/types/index';\nimport { ClaudeCapacityCard } from './claude-capacity-card';\nimport { CodebaseSizeCard } from './codebase-size-card';\nimport { CommentRatioCard } from './comment-ratio-card';\nimport { EntitiesByStatusCard } from './entities-by-status-card';\nimport { MedianPhaseDurationCard } from './median-phase-duration-card';\nimport { MostExpensiveIdeasCard } from './most-expensive-ideas-card';\nimport { NotesCard } from './notes-card';\nimport { TasksPerWeekCard } from './tasks-per-week-card';\nimport { TestCoverageCard } from './test-coverage-card';\nimport { UsagePerWeekCard } from './usage-per-week-card';\n\nexport interface StatsGridProps {\n stats: ProjectStats;\n}\n\nexport const StatsGrid = ({ stats }: StatsGridProps) => (\n <>\n <div className=\"flex flex-wrap items-start gap-2.5\">\n <CommentRatioCard comments={stats.comments} />\n <TestCoverageCard testCoveragePct={stats.testCoveragePct} />\n <CodebaseSizeCard sourceLines={stats.comments.sourceLines} testLines={stats.testLines} />\n <EntitiesByStatusCard entitiesByStatus={stats.entitiesByStatus} />\n <NotesCard openQuestions={stats.openQuestions} decisions={stats.decisions} />\n <TasksPerWeekCard tasksPerWeek={stats.tasksPerWeek} />\n <UsagePerWeekCard usagePerWeek={stats.usagePerWeek} />\n <MedianPhaseDurationCard medianPhaseDurationMs={stats.medianPhaseDurationMs} />\n <MostExpensiveIdeasCard mostExpensiveIdeas={stats.mostExpensiveIdeas} />\n <ClaudeCapacityCard capacity={stats.capacity} />\n </div>\n <p className=\"opacity-[0.4] text-2xs mt-6\">\n Generated {new Date(stats.generatedAt).toLocaleString()}\n </p>\n </>\n);\n","import { PageTitle } from '@/app/components/page-title';\nimport { useStatsPage } from './hooks';\nimport { StatsGrid } from './views';\n\nexport const StatsPage = () => {\n const { stats, loadFailed } = useStatsPage();\n\n return (\n <div>\n <PageTitle>Stats</PageTitle>\n <p className=\"opacity-50 mb-6\">\n A read-only look at project health — every number here is informational, none of them gate\n anything.\n </p>\n {loadFailed && <p className=\"opacity-50\">Couldn't load stats.</p>}\n {!loadFailed && !stats && <p className=\"opacity-50\">Loading…</p>}\n {stats && <StatsGrid stats={stats} />}\n </div>\n );\n};\n"],"names":["fetchStats","res","apiUrl","useStatsPage","stats","setStats","useState","loadFailed","setLoadFailed","useEffect","ENTITY_STATUS_ORDER","PLAN_STATUSES","ENTITY_STATUS_LABEL","STATUS_LABEL","CAPACITY_STAMP","StatCard","title","children","jsx","Card","jsxs","StatRow","label","value","ClaudeCapacityCard","capacity","now","setNow","id","Fragment","Stamp","capacityLevel","resetsAtMs","formatDuration","CodebaseSizeCard","sourceLines","testLines","pct","CommentRatioCard","comments","Progress","color","EntitiesByStatusCard","entitiesByStatus","status","MedianPhaseDurationCard","medianPhaseDurationMs","MostExpensiveIdeasCard","mostExpensiveIdeas","idea","formatTokens","NotesCard","openQuestions","decisions","TasksPerWeekCard","tasksPerWeek","max","w","week","TestCoverageCard","testCoveragePct","UsagePerWeekCard","usagePerWeek","StatsGrid","StatsPage","PageTitle"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as d,u as c,G as k,j as e,ag as h,C as w,ah as v,ai as E,aj as I,ak as C,al as D,ac as R,J as $,am as P,P as T}from"./main-DkQCGPBX.js";function S(t){return Math.floor((Date.now()-Date.parse(t))/864e5)}function K(t){return t.kind==="question"?t.ageDays:S(t.date)}const j=t=>Number.isFinite(t)?t<=0?"today":t===1?"1 day ago":`${t} days ago`:"age unknown",L=()=>{const[t,i]=d.useState(null),n=c(s=>s.notifications),p=c(s=>s.notificationsError!==null),x=c(s=>s.plans),u=c(s=>s.loadPlans),o=c(s=>s.loadNotifications),a=c(s=>s.markRead),l=k();return d.useEffect(()=>{o()},[o]),d.useEffect(()=>{if(n)for(const s of n)s.kind!=="question"&&!s.read&&a(s.id)},[n,a]),{notifications:n,loadFailed:p,plans:x,expandedKey:t,setExpandedKey:i,openEntity:l,reload:async()=>{await Promise.all([u(),o()])}}},A={completed:"Completed",reply:"Reply"},F=({notification:t,ageDays:i,onOpen:n})=>e.jsxs("div",{className:"flex items-center gap-3 py-2.5 border-b border-black/10 last:border-b-0",children:[e.jsx("button",{type:"button",onClick:n,"aria-label":`Open ${t.entityTitle}`,className:"bg-transparent border-none p-0 cursor-pointer",children:e.jsx(h,{id:t.entityId})}),e.jsx("span",{className:"text-xs uppercase tracking-wide opacity-40 whitespace-nowrap",children:A[t.kind]}),e.jsx("span",{className:"flex-1 min-w-0 truncate",children:t.text}),e.jsx("span",{className:"opacity-50 text-xs whitespace-nowrap",children:j(i)})]}),O=({question:t,plan:i,expanded:n,onToggle:p,onOpen:x,reload:u})=>{const{toast:o}=w(),[a,l]=d.useState(""),{sending:r,send:s,undo:b,undoing:y,undoEdit:g}=v(i,{reload:u,notify:o}),m=`question-reply:${t.entityId}`;d.useEffect(()=>{const f=E(m);f&&l(f)},[m]),d.useEffect(()=>{a&&I(m,a)},[m,a]);const N=async()=>{a.trim()&&await s(a.trim())&&(l(""),P(m))};return e.jsxs("div",{className:"border-b border-black/10 last:border-b-0",children:[e.jsxs("div",{className:"flex items-center gap-3 py-2.5",children:[e.jsx("button",{type:"button",onClick:x,"aria-label":`Open ${t.entityTitle}`,className:"bg-transparent border-none p-0 cursor-pointer",children:e.jsx(h,{id:t.entityId})}),e.jsx("button",{type:"button",onClick:p,"aria-expanded":n,className:"flex-1 min-w-0 truncate text-left bg-transparent border-none p-0 cursor-pointer",children:t.text}),e.jsx("span",{className:"opacity-50 text-xs whitespace-nowrap",children:j(t.ageDays)})]}),n&&e.jsxs("div",{className:"flex flex-col gap-3 pb-4",children:[e.jsx(C,{messages:i.thread??[],undo:b,undoing:y,onUndo:g}),e.jsx(D,{value:a,onChange:f=>l(f.target.value),"aria-label":`Reply to ${t.entityTitle}`,placeholder:"Reply to resolve and resume…",rows:2,disabled:r}),e.jsxs("div",{className:"flex justify-end items-center gap-3",children:[e.jsx("span",{className:r?"visible":"invisible",children:e.jsx(R,{size:"small",label:"Agent replying…"})}),e.jsx($,{size:"small",onClick:N,disabled:r||!a.trim(),children:"Reply"})]})]})]})},z=()=>{const{notifications:t,loadFailed:i,plans:n,expandedKey:p,setExpandedKey:x,openEntity:u,reload:o}=L();return e.jsxs("div",{children:[e.jsx(T,{children:"Inbox"}),e.jsx("p",{className:"opacity-50 mb-6",children:"Every parked question, completed run, and agent reply, oldest first."}),i&&e.jsx("p",{className:"opacity-50",children:"Couldn't load notifications."}),!i&&!t&&e.jsx("p",{className:"opacity-50",children:"Loading…"}),t&&t.length===0&&e.jsx("p",{className:"opacity-50",children:"Nothing here — no parked questions or recent activity."}),t&&t.length>0&&e.jsx("div",{className:"flex flex-col",children:t.map((a,l)=>{const r=`${a.entityId}-${a.kind}-${l}`,s=()=>u(a.entityId,a.entityTitle);if(a.kind!=="question")return e.jsx(F,{notification:a,ageDays:K(a),onOpen:s},r);const b=n==null?void 0:n.entries.find(y=>y.id===a.entityId);return b?e.jsx(O,{question:a,plan:b,expanded:p===r,onToggle:()=>x(y=>y===r?null:r),onOpen:s,reload:o},r):e.jsxs("div",{className:"flex items-center gap-3 py-2.5 border-b border-black/10 last:border-b-0",children:[e.jsx("button",{type:"button",onClick:s,"aria-label":`Open ${a.entityTitle}`,className:"bg-transparent border-none p-0 cursor-pointer",children:e.jsx(h,{id:a.entityId})}),e.jsx("span",{className:"flex-1 min-w-0 truncate",children:a.text}),e.jsx("span",{className:"opacity-50 text-xs whitespace-nowrap",children:j(a.ageDays)})]},r)})})]})};export{z as InboxPage};
|
|
2
|
-
//# sourceMappingURL=index-CR8PI9q6.js.map
|