clarc/src/types.ts
Jared Miller 43648f7d60
Add initial_state SSE event for reconnect sync (Phase 3)
When a dashboard connects via SSE, it now receives the current terminal
state for all active sessions. This allows dashboards to immediately
display the full terminal content without waiting for new output.
2026-01-31 09:51:13 -05:00

235 lines
5.1 KiB
TypeScript

// Shared types for clarc
// Database entities
export interface Device {
id: number;
secret: string;
name: string | null;
created_at: number;
last_seen: number;
}
export interface Session {
id: number;
device_id: number;
started_at: number;
ended_at: number | null;
cwd: string | null;
command: string | null;
// Phase 2.3: Session state and stats
state:
| "ready"
| "thinking"
| "permission"
| "question"
| "complete"
| "interrupted";
prompts: number;
completions: number;
tools: number;
compressions: number;
thinking_seconds: number;
work_seconds: number;
mode: "normal" | "auto_accept" | "plan";
model: string | null;
idle_since: number | null;
// Git state (for later phase)
git_branch: string | null;
git_files_json: string | null;
}
export interface Prompt {
id: number;
session_id: number;
created_at: number;
prompt_text: string;
response: string | null;
responded_at: number | null;
}
export interface OutputLog {
id: number;
session_id: number;
timestamp: number;
line: string;
}
// Phase 2: Rich prompt system interfaces
// Represents the structured data format for interactive prompts from Claude Code
export interface PromptOption {
label: string;
value: string;
description?: string;
}
export interface PermissionPrompt {
prompt_type: "permission";
tool_name: string;
tool_input: Record<string, unknown>;
options: PromptOption[];
allows_tab_instructions: boolean;
selected_option: number;
}
export interface QuestionItem {
question: string;
header?: string;
options: PromptOption[];
multi_select: boolean;
allows_other: boolean;
}
export interface QuestionPrompt {
prompt_type: "question";
questions: QuestionItem[];
}
export interface ExitPlanPrompt {
prompt_type: "exit_plan";
options: PromptOption[];
}
export type PromptData =
| PermissionPrompt
| QuestionPrompt
| ExitPlanPrompt
| null;
export type AnswerResponse =
| { type: "option"; value: string }
| { type: "text"; value: string }
| { type: "tab_instructions"; selected_option: number; instruction: string };
// WebSocket messages (CLI <-> Server)
export type ClientMessage =
| { type: "auth"; secret: string; cwd?: string; command?: string }
| { type: "output"; data: string }
| { type: "resize"; cols: number; rows: number }
| { type: "exit"; code: number }
| { type: "prompt"; session_id: number; prompt_text: string }
| {
type: "state";
state:
| "ready"
| "thinking"
| "permission"
| "question"
| "complete"
| "interrupted";
timestamp: number;
}
| {
type: "stats";
prompts: number;
completions: number;
tools: number;
compressions: number;
thinking_seconds: number;
work_seconds: number;
mode: "normal" | "auto_accept" | "plan";
model: string | null;
prompts_changed_at: number;
completions_changed_at: number;
tool_timestamps: number[];
session_start: number;
idle_since: number | null;
}
| {
type: "git";
branch: string;
files: Array<{
path: string;
status: string;
additions: number;
deletions: number;
}>;
};
export type ServerMessage =
| { type: "authenticated"; session_id: number }
| { type: "input"; data: string }
| { type: "resize"; cols: number; rows: number }
| { type: "ping" };
// SSE events (Server -> Dashboard)
export type SSEEvent =
| { type: "initial_state"; session_id: number; html: string }
| {
type: "session_start";
session_id: number;
cwd: string | null;
command: string | null;
}
| { type: "session_end"; session_id: number; exit_code: number }
| { type: "output"; session_id: number; data: string }
| {
type: "prompt";
prompt_id: number;
session_id: number;
prompt_text: string;
prompt_json?: string | null;
}
| {
type: "prompt_response";
prompt_id: number;
response: string;
}
| {
type: "state";
session_id: number;
state:
| "ready"
| "thinking"
| "permission"
| "question"
| "complete"
| "interrupted";
timestamp: number;
}
| {
type: "stats";
session_id: number;
prompts: number;
completions: number;
tools: number;
compressions: number;
thinking_seconds: number;
work_seconds: number;
mode: "normal" | "auto_accept" | "plan";
model: string | null;
idle_since: number | null;
}
| {
type: "git";
session_id: number;
branch: string;
files_json: string;
};
// Session state tracking (in-memory)
export interface SessionState {
state:
| "ready"
| "thinking"
| "permission"
| "question"
| "complete"
| "interrupted";
prompts: number;
completions: number;
tools: number;
compressions: number;
thinking_seconds: number;
work_seconds: number;
mode: "normal" | "auto_accept" | "plan";
model: string | null;
idle_since: number | null;
git_branch: string | null;
git_files_json: string | null;
dirty: boolean;
}