// API service for directive operations
export interface DirectiveStepCounts {
pending: number
ready: number
running: number
completed: number
failed: number
skipped: number
}
export interface DirectiveSummary {
id: string
title: string
goal: string
status: string
repositoryUrl: string
prUrl: string
prBranch: string
createdAt: string
updatedAt: string
goalUpdatedAt: string
stepCounts: DirectiveStepCounts
version?: number
pr_branch?: string | null
}
export interface DirectiveStep {
id: string
directiveId: string
directive_id?: string
name: string
title?: string
description: string | null
taskPlan: string
dependsOn: string[]
status: string
contractId: string
/** @deprecated Use contractId instead */
taskId: string
orderIndex: number
sort_order?: number
completedAt: string
}
export interface DirectiveWithSteps extends DirectiveSummary {
steps: DirectiveStep[]
reconcileMode: string
}
// Alias for compatibility with context-menu branch types
export type Directive = DirectiveSummary
async function apiFetch(path: string, options?: RequestInit): Promise<Response> {
const response = await fetch(path, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
})
if (!response.ok) {
const body = await response.json().catch(() => ({ message: response.statusText }))
throw new Error(body.message ?? body.error ?? `API error ${response.status}: ${response.statusText}`)
}
return response
}
export async function listDirectives(): Promise<DirectiveSummary[]> {
const response = await apiFetch('/api/v1/directives')
const data = await response.json()
return data.directives || []
}
export async function getDirective(id: string): Promise<DirectiveWithSteps> {
const response = await apiFetch(`/api/v1/directives/${id}`)
return response.json()
}
export async function getDirectiveSteps(id: string): Promise<DirectiveStep[]> {
const response = await apiFetch(`/api/v1/directives/${id}/steps`)
return response.json()
}
export async function updateGoal(id: string, goal: string): Promise<DirectiveWithSteps> {
const response = await apiFetch(`/api/v1/directives/${id}/goal`, {
method: 'PUT',
body: JSON.stringify({ goal }),
})
return response.json()
}
export async function updateDirective(
id: string,
updates: { title?: string; goal?: string; version?: number },
): Promise<DirectiveWithSteps> {
const response = await apiFetch(`/api/v1/directives/${id}`, {
method: 'PUT',
body: JSON.stringify(updates),
})
return response.json()
}
export async function cleanupDirective(id: string): Promise<void> {
await apiFetch(`/api/v1/directives/${id}/cleanup`, { method: 'POST' })
}
export async function createPr(id: string): Promise<{ prUrl: string }> {
const response = await apiFetch(`/api/v1/directives/${id}/create-pr`, { method: 'POST' })
return response.json()
}
export async function pickUpOrders(id: string): Promise<void> {
await apiFetch(`/api/v1/directives/${id}/pick-up-orders`, { method: 'POST' })
}
export async function startDirective(id: string): Promise<DirectiveWithSteps> {
const response = await apiFetch(`/api/v1/directives/${id}/start`, { method: 'POST' })
return response.json()
}
export async function pauseDirective(id: string): Promise<DirectiveWithSteps> {
const response = await apiFetch(`/api/v1/directives/${id}/pause`, { method: 'POST' })
return response.json()
}
export async function getUserSetting(key: string): Promise<any> {
const response = await apiFetch(`/api/v1/user-settings/${key}`)
return response.json()
}
export async function upsertUserSetting(key: string, value: any): Promise<void> {
await apiFetch('/api/v1/user-settings', {
method: 'PUT',
body: JSON.stringify({ key, value }),
})
}
// ---- Task control APIs ----
export async function sendTaskMessage(taskId: string, message: string): Promise<void> {
await apiFetch(`/api/v1/mesh/tasks/${taskId}/message`, {
method: 'POST',
body: JSON.stringify({ message }),
})
}
export async function stopTask(taskId: string): Promise<void> {
await apiFetch(`/api/v1/mesh/tasks/${taskId}/stop`, {
method: 'POST',
})
}
export async function continueTask(taskId: string): Promise<void> {
await apiFetch(`/api/v1/mesh/tasks/${taskId}/continue`, {
method: 'POST',
})
}
export async function startTask(taskId: string): Promise<void> {
await apiFetch(`/api/v1/mesh/tasks/${taskId}/start`, {
method: 'POST',
})
}