This commit is contained in:
Auto
2025-12-30 11:56:39 +02:00
parent dd7c1ddd82
commit a2efec159d
40 changed files with 9112 additions and 3 deletions

148
ui/src/lib/api.ts Normal file
View File

@@ -0,0 +1,148 @@
/**
* API Client for the Autonomous Coding UI
*/
import type {
ProjectSummary,
ProjectDetail,
ProjectPrompts,
FeatureListResponse,
Feature,
FeatureCreate,
AgentStatusResponse,
AgentActionResponse,
SetupStatus,
} from './types'
const API_BASE = '/api'
async function fetchJSON<T>(url: string, options?: RequestInit): Promise<T> {
const response = await fetch(`${API_BASE}${url}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
})
if (!response.ok) {
const error = await response.json().catch(() => ({ detail: 'Unknown error' }))
throw new Error(error.detail || `HTTP ${response.status}`)
}
return response.json()
}
// ============================================================================
// Projects API
// ============================================================================
export async function listProjects(): Promise<ProjectSummary[]> {
return fetchJSON('/projects')
}
export async function createProject(name: string, specMethod: 'claude' | 'manual' = 'manual'): Promise<ProjectSummary> {
return fetchJSON('/projects', {
method: 'POST',
body: JSON.stringify({ name, spec_method: specMethod }),
})
}
export async function getProject(name: string): Promise<ProjectDetail> {
return fetchJSON(`/projects/${encodeURIComponent(name)}`)
}
export async function deleteProject(name: string): Promise<void> {
await fetchJSON(`/projects/${encodeURIComponent(name)}`, {
method: 'DELETE',
})
}
export async function getProjectPrompts(name: string): Promise<ProjectPrompts> {
return fetchJSON(`/projects/${encodeURIComponent(name)}/prompts`)
}
export async function updateProjectPrompts(
name: string,
prompts: Partial<ProjectPrompts>
): Promise<void> {
await fetchJSON(`/projects/${encodeURIComponent(name)}/prompts`, {
method: 'PUT',
body: JSON.stringify(prompts),
})
}
// ============================================================================
// Features API
// ============================================================================
export async function listFeatures(projectName: string): Promise<FeatureListResponse> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/features`)
}
export async function createFeature(projectName: string, feature: FeatureCreate): Promise<Feature> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/features`, {
method: 'POST',
body: JSON.stringify(feature),
})
}
export async function getFeature(projectName: string, featureId: number): Promise<Feature> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/features/${featureId}`)
}
export async function deleteFeature(projectName: string, featureId: number): Promise<void> {
await fetchJSON(`/projects/${encodeURIComponent(projectName)}/features/${featureId}`, {
method: 'DELETE',
})
}
export async function skipFeature(projectName: string, featureId: number): Promise<void> {
await fetchJSON(`/projects/${encodeURIComponent(projectName)}/features/${featureId}/skip`, {
method: 'PATCH',
})
}
// ============================================================================
// Agent API
// ============================================================================
export async function getAgentStatus(projectName: string): Promise<AgentStatusResponse> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/agent/status`)
}
export async function startAgent(projectName: string): Promise<AgentActionResponse> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/agent/start`, {
method: 'POST',
})
}
export async function stopAgent(projectName: string): Promise<AgentActionResponse> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/agent/stop`, {
method: 'POST',
})
}
export async function pauseAgent(projectName: string): Promise<AgentActionResponse> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/agent/pause`, {
method: 'POST',
})
}
export async function resumeAgent(projectName: string): Promise<AgentActionResponse> {
return fetchJSON(`/projects/${encodeURIComponent(projectName)}/agent/resume`, {
method: 'POST',
})
}
// ============================================================================
// Setup API
// ============================================================================
export async function getSetupStatus(): Promise<SetupStatus> {
return fetchJSON('/setup/status')
}
export async function healthCheck(): Promise<{ status: string }> {
return fetchJSON('/health')
}

112
ui/src/lib/types.ts Normal file
View File

@@ -0,0 +1,112 @@
/**
* TypeScript types for the Autonomous Coding UI
*/
// Project types
export interface ProjectStats {
passing: number
total: number
percentage: number
}
export interface ProjectSummary {
name: string
has_spec: boolean
stats: ProjectStats
}
export interface ProjectDetail extends ProjectSummary {
prompts_dir: string
}
export interface ProjectPrompts {
app_spec: string
initializer_prompt: string
coding_prompt: string
}
// Feature types
export interface Feature {
id: number
priority: number
category: string
name: string
description: string
steps: string[]
passes: boolean
}
export interface FeatureListResponse {
pending: Feature[]
in_progress: Feature[]
done: Feature[]
}
export interface FeatureCreate {
category: string
name: string
description: string
steps: string[]
priority?: number
}
// Agent types
export type AgentStatus = 'stopped' | 'running' | 'paused' | 'crashed'
export interface AgentStatusResponse {
status: AgentStatus
pid: number | null
started_at: string | null
}
export interface AgentActionResponse {
success: boolean
status: AgentStatus
message: string
}
// Setup types
export interface SetupStatus {
claude_cli: boolean
credentials: boolean
node: boolean
npm: boolean
}
// WebSocket message types
export type WSMessageType = 'progress' | 'feature_update' | 'log' | 'agent_status' | 'pong'
export interface WSProgressMessage {
type: 'progress'
passing: number
total: number
percentage: number
}
export interface WSFeatureUpdateMessage {
type: 'feature_update'
feature_id: number
passes: boolean
}
export interface WSLogMessage {
type: 'log'
line: string
timestamp: string
}
export interface WSAgentStatusMessage {
type: 'agent_status'
status: AgentStatus
}
export interface WSPongMessage {
type: 'pong'
}
export type WSMessage =
| WSProgressMessage
| WSFeatureUpdateMessage
| WSLogMessage
| WSAgentStatusMessage
| WSPongMessage