Initial CodeCraft: web-based coding harness for AI models

Rust backend (axum/tokio): agent loop with streaming, tools (fs, bash,
web_fetch, todo, ask_user, subagents, skills, craft snapshots/compare),
permissions with modes and rules, Anthropic + OpenAI-compatible providers,
MCP client (stdio/HTTP, elicitation), SQLite sessions, usage statistics,
compaction, commented TOML config editable via toml_edit.

React PWA: chat with live streaming, permission/question cards, modes
(build/plan/craft), settings for providers/models/prices/MCP/permissions,
raw config editor, statistics dashboard, i18n (en/de). Docker setup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-08 14:39:24 +01:00
commit f3a2fe3816
62 files changed
+21835

No files matched your search

+147
View File
@@ -0,0 +1,147 @@
// Mirrors server/src/types.rs
export interface ImageData {
media_type: string;
data: string;
}
export type Part =
| { type: "text"; text: string }
| { type: "image"; image: ImageData }
| { type: "reasoning"; text: string; signature?: string }
| { type: "tool_call"; id: string; name: string; input: any }
| {
type: "tool_result";
call_id: string;
name: string;
content: string;
images?: ImageData[];
is_error: boolean;
meta?: any;
}
| { type: "summary"; text: string };
export interface Usage {
input_tokens: number;
output_tokens: number;
cache_read_tokens: number;
cache_write_tokens: number;
}
export interface Message {
id: string;
role: "user" | "assistant";
parts: Part[];
model?: string;
usage?: Usage;
created_at: number;
}
export interface Todo {
content: string;
status: "pending" | "in_progress" | "completed";
}
export interface Session {
id: string;
title: string;
cwd: string;
model: string;
agent: string;
permission_mode: "default" | "accept_edits" | "bypass";
parent_id?: string;
created_at: number;
updated_at: number;
todos: Todo[] | null;
last_usage?: Usage | null;
busy?: boolean;
}
export interface QuestionOption {
label: string;
description?: string;
}
export interface Question {
question: string;
header?: string;
options: QuestionOption[];
multi_select?: boolean;
}
export interface PermissionRequest {
type: "permission_request";
id: string;
session_id: string;
root_session_id?: string;
tool: string;
title: string;
input: any;
diff?: string;
}
export interface QuestionRequest {
type: "question_request";
id: string;
session_id: string;
root_session_id?: string;
source: string;
questions: Question[];
}
export type ServerEvent =
| { type: "session_updated"; session: Session }
| { type: "session_deleted"; session_id: string }
| { type: "session_status"; session_id: string; busy: boolean }
| { type: "message_added"; session_id: string; message: Message }
| { type: "text_delta"; session_id: string; message_id: string; text: string }
| { type: "reasoning_delta"; session_id: string; message_id: string; text: string }
| { type: "tool_started"; session_id: string; message_id: string; call_id: string; name: string; input: any }
| { type: "tool_progress"; session_id: string; call_id: string; output: string }
| PermissionRequest
| { type: "permission_resolved"; id: string; session_id: string }
| QuestionRequest
| { type: "question_resolved"; id: string; session_id: string }
| { type: "error"; session_id: string; message: string }
| { type: "mcp_status"; servers: Record<string, McpServerStatus> }
| { type: "resync" };
export interface McpServerStatus {
status: { state: "disabled" | "connecting" | "connected" | "failed"; tools?: number; error?: string };
tools: { name: string; description: string }[];
}
export interface ModelInfo {
id: string;
name: string;
context?: number;
reasoning: boolean;
vision: boolean;
}
export interface ProviderModels {
provider: string;
models: ModelInfo[];
}
export interface AgentInfo {
name: string;
description: string;
mode: "primary" | "subagent";
read_only: boolean;
}
export interface Aggregate {
requests: number;
input_tokens: number;
output_tokens: number;
cache_read_tokens: number;
cache_write_tokens: number;
cost: number;
errors: number;
avg_ttft_ms: number;
output_tps: number;
prefill_tps: number;
cache_hit_rate: number;
duration_ms: number;
}