summaryrefslogblamecommitdiff
path: root/frontend/src/services/directiveApi.ts
blob: 4d1fd8206ff394bebb4c1c36917a189835d9b4bd (plain) (tree)




































                                       
                    

                                           






















































































                                                                                                         
                                                                 



                                                                                 
                                           



                                         


























                                                                                       
// 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',
  })
}