{entry.status === "found" ? (
-
+
) : (
-
+
)}
-
-
{entry.name}
-
{formatCliHealth(entry.status)}
+
+
+ {entry.name}
+
+
{formatCliHealth(entry.status)}
-
{entry.detail}
- {entry.path ? (
-
- {entry.path}
-
- ) : null}
+
{entry.detail}
);
});
@@ -40,5 +37,9 @@ function formatCliHealth(status: CliStatus["status"]) {
return "Needs authentication";
}
+ if (status === "unavailable") {
+ return "Unavailable";
+ }
+
return "Missing";
}
diff --git a/src/components/ControlColumn.tsx b/src/components/ControlColumn.tsx
index f7c6f31..a978d64 100644
--- a/src/components/ControlColumn.tsx
+++ b/src/components/ControlColumn.tsx
@@ -378,6 +378,8 @@ function formatMcpStatus(status: string) {
return "Ready";
case "unauthorized":
return "Check";
+ case "unavailable":
+ return "Unavailable";
default:
return status;
}
@@ -389,6 +391,8 @@ function getMcpBadgeClassName(status: string) {
return "shrink-0 rounded-full border border-emerald-400/30 bg-emerald-400/12 px-3 py-1 text-xs font-medium uppercase tracking-[0.08em] text-emerald-100";
case "unauthorized":
return "shrink-0 rounded-full border border-amber-300/30 bg-amber-300/12 px-3 py-1 text-xs font-medium uppercase tracking-[0.08em] text-amber-100";
+ case "unavailable":
+ return "shrink-0 rounded-full border border-amber-300/30 bg-amber-300/12 px-3 py-1 text-xs font-medium uppercase tracking-[0.08em] text-amber-100";
default:
return "shrink-0 rounded-full border border-[var(--border-soft)] bg-white/5 px-3 py-1 text-xs font-medium uppercase tracking-[0.08em] text-[var(--text-subtle)]";
}
diff --git a/src/components/MainWorkspace.tsx b/src/components/MainWorkspace.tsx
index d9add09..0d63854 100644
--- a/src/components/MainWorkspace.tsx
+++ b/src/components/MainWorkspace.tsx
@@ -39,6 +39,8 @@ interface MainWorkspaceProps {
specContent: string;
prdPaneMode: PaneMode;
specPaneMode: PaneMode;
+ hasPrdPreview: boolean;
+ hasSpecPreview: boolean;
isSpecApproved: boolean;
canGeneratePrd: boolean;
canGrillPrd: boolean;
@@ -72,9 +74,13 @@ interface MainWorkspaceProps {
onPrdGenerationPromptChange: (value: string) => void;
onGeneratePrd: () => void;
onGrillPrd: () => void;
+ onSavePrdPreview: () => void;
+ onDiscardPrdPreview: () => void;
onSpecGenerationPromptChange: (value: string) => void;
onGenerateSpec: () => void;
onGrillSpec: () => void;
+ onSaveSpecPreview: () => void;
+ onDiscardSpecPreview: () => void;
onSpecSelect: (event: ChangeEvent
) => void;
onEditorTabClose: (path: string) => void;
onOpenEditorTabExternally: (path: string, editorId: string) => void;
@@ -92,6 +98,8 @@ export const MainWorkspace = memo(function MainWorkspace({
specContent,
prdPaneMode,
specPaneMode,
+ hasPrdPreview,
+ hasSpecPreview,
isSpecApproved,
canGeneratePrd,
canGrillPrd,
@@ -125,9 +133,13 @@ export const MainWorkspace = memo(function MainWorkspace({
onPrdGenerationPromptChange,
onGeneratePrd,
onGrillPrd,
+ onSavePrdPreview,
+ onDiscardPrdPreview,
onSpecGenerationPromptChange,
onGenerateSpec,
onGrillSpec,
+ onSaveSpecPreview,
+ onDiscardSpecPreview,
onSpecSelect,
onEditorTabClose,
onOpenEditorTabExternally,
@@ -217,6 +229,13 @@ export const MainWorkspace = memo(function MainWorkspace({
onModeChange={onPrdPaneModeChange}
showModeButtons={hasPrdContent}
/>
+ {hasPrdPreview ? (
+ onPrdPaneModeChange("edit")}
+ onSave={onSavePrdPreview}
+ />
+ ) : null}
{showPrdEmptyState ? (