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:
commit
f3a2fe3816
62 files changed
+21835
No files matched your search
@@ -0,0 +1,35 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { get } from "./api";
|
||||
import type { AgentInfo, ProviderModels } from "./types";
|
||||
|
||||
/** Fetch JSON and refetch on demand. */
|
||||
export function useFetch<T>(path: string | null) {
|
||||
const [data, setData] = useState<T | undefined>();
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
const [tick, setTick] = useState(0);
|
||||
useEffect(() => {
|
||||
if (!path) return;
|
||||
let alive = true;
|
||||
get<T>(path)
|
||||
.then((d) => alive && (setData(d), setError(undefined)))
|
||||
.catch((e) => alive && setError(String(e.message ?? e)));
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, [path, tick]);
|
||||
const reload = useCallback(() => setTick((x) => x + 1), []);
|
||||
return { data, error, reload };
|
||||
}
|
||||
|
||||
export function useModels() {
|
||||
return useFetch<ProviderModels[]>("/models").data ?? [];
|
||||
}
|
||||
|
||||
export function useAgents(cwd?: string) {
|
||||
const q = cwd ? `?cwd=${encodeURIComponent(cwd)}` : "";
|
||||
return useFetch<AgentInfo[]>(`/agents${q}`).data ?? [];
|
||||
}
|
||||
|
||||
export function modelOptions(models: ProviderModels[]): { value: string; label: string }[] {
|
||||
return models.flatMap((p) => p.models.map((m) => ({ value: `${p.provider}/${m.id}`, label: `${p.provider} · ${m.name}` })));
|
||||
}
|
||||
Reference in new issue
Block a user