feat: add conversation management, persistence, and mobile app spec
Major enhancements to voice assistant with conversation persistence and mobile app planning: - Add conversation management with multiple active conversations - Implement conversation persistence (save/load from disk) - Add conversation selector UI for switching between conversations - Enhance agent prompt with per-conversation tmux sessions - Add mobile app technical specification (React Native + Expo) - Improve UI with active processes view and agent stream - Add ACP (Agent Control Protocol) server implementation Mobile spec details: - React Native with Expo SDK 54+ - NativeWind v5 for styling - Share Zod schemas/types from server - Android in-call experience (InCallManager) - Direct WebSocket connection via Tailscale - Same audio quality as web prototype 🤖 Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
co-authored by
Claude
Happy
parent
37a363da6d
commit
4f2c2fc14a
@@ -0,0 +1,102 @@
|
||||
import { Terminal, Bot } from "lucide-react";
|
||||
import type { AgentStatus } from "../../server/acp/types.js";
|
||||
|
||||
export interface ActiveProcessesProps {
|
||||
terminals: Array<{ id: string; name: string }>;
|
||||
agents: Array<{ id: string; status: AgentStatus; type: "claude" }>;
|
||||
activeProcessId: string | null;
|
||||
activeProcessType: "terminal" | "agent" | null;
|
||||
onSelectProcess: (id: string, type: "terminal" | "agent") => void;
|
||||
onBackToOrchestrator: () => void;
|
||||
}
|
||||
|
||||
function getAgentStatusColor(status: AgentStatus): string {
|
||||
switch (status) {
|
||||
case "initializing":
|
||||
return "#f59e0b"; // orange
|
||||
case "ready":
|
||||
return "#3b82f6"; // blue
|
||||
case "processing":
|
||||
return "#fbbf24"; // yellow
|
||||
case "completed":
|
||||
return "#22c55e"; // green
|
||||
case "failed":
|
||||
return "#ef4444"; // red
|
||||
case "killed":
|
||||
return "#9ca3af"; // gray
|
||||
default:
|
||||
return "#9ca3af";
|
||||
}
|
||||
}
|
||||
|
||||
function getAgentStatusLabel(status: AgentStatus): string {
|
||||
return status;
|
||||
}
|
||||
|
||||
export function ActiveProcesses({
|
||||
terminals,
|
||||
agents,
|
||||
activeProcessId,
|
||||
activeProcessType,
|
||||
onSelectProcess,
|
||||
onBackToOrchestrator,
|
||||
}: ActiveProcessesProps) {
|
||||
const hasActiveProcess = activeProcessId !== null && activeProcessType !== null;
|
||||
|
||||
return (
|
||||
<div className="active-processes-bar">
|
||||
{hasActiveProcess && (
|
||||
<button
|
||||
className="back-to-orchestrator-button"
|
||||
onClick={onBackToOrchestrator}
|
||||
type="button"
|
||||
>
|
||||
Back to Chat
|
||||
</button>
|
||||
)}
|
||||
|
||||
<div className="processes-pills">
|
||||
{terminals.map((terminal) => (
|
||||
<button
|
||||
key={`terminal-${terminal.id}`}
|
||||
className={`process-pill terminal ${
|
||||
activeProcessType === "terminal" && activeProcessId === terminal.id
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => onSelectProcess(terminal.id, "terminal")}
|
||||
type="button"
|
||||
>
|
||||
<Terminal size={14} />
|
||||
<span className="process-name">{terminal.name}</span>
|
||||
<span className="process-status-indicator running" />
|
||||
</button>
|
||||
))}
|
||||
|
||||
{agents.map((agent) => (
|
||||
<button
|
||||
key={`agent-${agent.id}`}
|
||||
className={`process-pill agent ${
|
||||
activeProcessType === "agent" && activeProcessId === agent.id
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => onSelectProcess(agent.id, "agent")}
|
||||
type="button"
|
||||
data-status={agent.status}
|
||||
>
|
||||
<Bot size={14} />
|
||||
<span className="process-name">
|
||||
{agent.id.substring(0, 8)}
|
||||
</span>
|
||||
<span
|
||||
className={`process-status-indicator ${agent.status}`}
|
||||
style={{ backgroundColor: getAgentStatusColor(agent.status) }}
|
||||
title={getAgentStatusLabel(agent.status)}
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user