Complete frontend migration to unified Pi harness (Phase 7 + Phase 9)

- Delete legacy hooks: useClaude.ts, useOpenCode.ts, usePiMono.ts, App.backup.tsx
- Update all components to use usePi instead of legacy hooks
- Replace useVisiblePiMonoModels/useClaudeModels/useOpenCodeModels with useVisiblePiModels
- Migrate from LegacyChatMessage to ChatMessage type throughout
- Update SessionBar to remove provider and archive props
- Simplify ChatDetailPanel to Pi-only (remove Claude/OpenCode components)
- Fix useChatSessions calls (remove provider parameter)
- Update user-settings types: provider now only 'pi' instead of legacy values
- Update PI_HARNESS_REBUILD.md to mark phases complete
This commit is contained in:
2026-02-20 21:42:26 +00:00
parent 92f4b2be8e
commit ba51ee0320
31 changed files with 225 additions and 1176 deletions
+3 -5
View File
@@ -1,7 +1,7 @@
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import type { LegacyChatMessage } from './types';
import type { ChatMessage } from './types';
import { ToolActivity } from './ToolActivity';
import { QuestionActivity } from './QuestionActivity';
@@ -21,7 +21,7 @@ const CollapsibleBlock = ({ label, content }: { label: string; content: string }
);
type MessageBubbleProps = {
message: LegacyChatMessage;
message: ChatMessage;
onAnswer?: (text: string) => void;
};
@@ -73,9 +73,7 @@ export const MessageBubble = ({ message, onAnswer }: MessageBubbleProps) => {
return (
<div className="flex justify-center py-1">
<span className="text-xs text-duck-dark/40">
Done · ${message.costUsd.toFixed(3)} · {(message.durationMs / 1000).toFixed(1)}s · {message.numTurns} turn
{message.numTurns !== 1 ? 's' : ''}
{message.isError ? ' (with errors)' : ''}
Done · ${message.cost.totalUSD.toFixed(3)} · {message.cost.inputTokens + message.cost.outputTokens} tokens
</span>
</div>
);
+2 -2
View File
@@ -1,10 +1,10 @@
import type { RefObject } from 'react';
import { ArrowDown } from 'lucide-react';
import type { LegacyChatMessage } from './types';
import type { ChatMessage } from './types';
import { MessageBubble, StreamingBubble } from './MessageBubble';
type MessageListProps = {
messages: LegacyChatMessage[];
messages: ChatMessage[];
streamingText: string;
isGenerating: boolean;
showJumpToBottom: boolean;
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { MessageCircleQuestion, Check } from 'lucide-react';
import type { LegacyChatMessage } from './types';
import type { ChatMessage } from './types';
type ToolMessage = Extract<LegacyChatMessage, { role: 'tool' }>;
type ToolMessage = Extract<ChatMessage, { role: 'tool' }>;
type QuestionOption = {
label: string;
+2 -2
View File
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { FileText, Terminal, Pencil, Search, Globe, Wrench, ChevronRight } from 'lucide-react';
import type { LegacyChatMessage } from './types';
import type { ChatMessage } from './types';
type ToolMessage = Extract<LegacyChatMessage, { role: 'tool' }>;
type ToolMessage = Extract<ChatMessage, { role: 'tool' }>;
type ToolActivityProps = {
message: ToolMessage;
+1
View File
@@ -10,6 +10,7 @@ export type {
ServerMessage,
Message,
MessageCost,
ModelOption,
TaskInfo,
LegacyChatMessage,
LegacySessionEntry,
+8
View File
@@ -4,6 +4,14 @@ export type MessageCost = {
totalUSD: number;
};
export type ModelOption = {
id: string;
name: string;
provider: string;
contextWindow: number;
maxTokens: number;
};
export type SessionEntry = {
id: string;
title: string;
+1 -13
View File
@@ -1,26 +1,22 @@
import { Link } from 'react-router';
import { ArrowLeft, Archive, Trash2, Maximize2, Minimize2 } from 'lucide-react';
import { ArrowLeft, Trash2, Maximize2, Minimize2 } from 'lucide-react';
type SessionBarProps = {
listPath: string;
provider: 'claude' | 'opencode' | 'pi-mono';
sessionTitle: string | undefined;
isConnected: boolean;
isGenerating: boolean;
fullscreen: boolean;
onArchive: (() => void) | undefined;
onDelete: () => void;
onToggleFullscreen: () => void;
};
export const SessionBar = ({
listPath,
provider,
sessionTitle,
isConnected,
isGenerating,
fullscreen,
onArchive,
onDelete,
onToggleFullscreen,
}: SessionBarProps) => (
@@ -29,14 +25,6 @@ export const SessionBar = ({
<Link to={listPath} className="p-1 text-duck-dark/40 hover:text-duck-dark transition-colors">
<ArrowLeft className="h-4 w-4" />
</Link>
{provider === 'claude' && onArchive && (
<button
onClick={onArchive}
className="p-1 text-duck-dark/40 hover:text-duck-teal transition-colors cursor-pointer"
>
<Archive className="h-4 w-4" />
</button>
)}
<button onClick={onDelete} className="p-1 text-duck-dark/40 hover:text-red-500 transition-colors cursor-pointer">
<Trash2 className="h-4 w-4" />
</button>