codacle.
DocsIniciá sesión →

Docs · 40

API interna.

Server actions y HTTP endpoints — qué expone hoy y qué shape devuelven.

El modelo de API

Codacle no expone una API pública versionada todavía. Lo que existe son dos superficies internas que pueden usar consumers en el monorepo:

  1. Server actions (Next.js) — funciones marcadas 'use server' invocadas desde formularios o components. Tipadas end-to-end, no se ven como endpoints HTTP separados.
  2. Route handlers (apps/web/app/api/...) — endpoints HTTP reales, usados por componentes client para polling.

Server actions

createWorkspaceAndStart(formData)

Ubicación: apps/web/lib/actions/workspace.ts

Input form fields:

  • kitId (string) — el id del kit del catálogo.

Comportamiento:

  1. Resuelve el kit con getKitById. Throw si no existe o si !isRegistered (sin agents).
  2. Encuentra la versión publicada (o la última registrada) en kits / kit_publications.
  3. INSERT workspaces con kit_id + kit_version pinneados.
  4. redirect a /migrations/new?ws=...&kit=....

publishKitVersion(formData) / unpublishKit(formData)

Ubicación: apps/web/lib/actions/kits.ts

Input form fields:

  • kitId (string)
  • version (string) — sólo para publishKitVersion.

Comportamiento:

  • publishKitVersion: UPSERT en kit_publications. revalidatePath a /kits, /kits/[id], /marketplace.
  • unpublishKit: DELETE de kit_publications para ese kit. Mismo revalidate.

uploadWorkspaceFile(formData) / triggerAnalyze(formData)

Ubicación: apps/web/lib/actions/workspace.ts

Suben archivos a Supabase Storage para el workspace y disparan el job analyze. triggerAnalyze cambia workspace.status a analyzing y encola el job.

Route handlers

GET /api/workspaces/[id]/ops-state

Devuelve el snapshot completo del workspace para el polling de /ops/[id]:

{
  "workspace": { "id": "...", "status": "...", "kit_id": "...", ... },
  "runs": [{ "id": "...", "stage": "analyze", "status": "done", "usage": {...}, ... }],
  "phases": [{ "phase_k": "...", "status": "completed", ... }],
  "jobs": [{ "id": "...", "type": "analyze", "status": "done", ... }]
}

Polling frecuente (5–10s) mientras el workspace está activo.

GET /api/workspaces/[id]/phases

Versión más liviana — sólo workspace_phases. Usado por PipelineLive en el tab /pipeline.

[
  { "phase_k": "extract", "label": "Extraer atoms", "status": "completed",
    "started_at": "...", "completed_at": "...", "updated_at": "..." }
]

GET /api/workspaces/[id]/files

Lista archivos subidos al workspace, con metadata (size, original_path, slot key). Usado por el wizard.

GET /api/workspaces/[id]/vault

Lista de atoms del Vault con filtros por tipo. Usado por /migrations/[id]/vault.

Convenciones

  • Sin auth todavía: las routes usan service-role bypass de RLS. Cuando lleguemos a auth (Slice 5+), agregamos middleware que valida la sesión y el org_id contra el workspace.
  • Tipado: las route handlers exportan el shape como type ... = { ... } desde el mismo archivo para que el client component que pollea pueda importarlo (import type { PhaseRow } from '@/app/api/workspaces/[id]/phases/route').
  • Errores: server actions hacen throw new Error(message) y Next renderiza el error boundary. Las route handlers devuelven { error: string } con status 4xx/5xx.

Webhooks

No hay webhooks externos. La interacción con Anthropic es síncrona dentro de cada job del worker — abrimos session, consumimos stream, cerramos. No hay callback de Anthropic hacia nosotros.

CLI scripts útiles

Todos están en apps/web/scripts/ y se invocan via pnpm:

ScriptPara qué
register-kit --kit-dir <path>Sube un kit a Anthropic + upsertea row en kits.
validate-kit -- --kit-dir <path>Sólo valida schema, sin subir nada.
inspect-run <run_id>Imprime el timeline de un workspace_run con tokens + costo.
cost-report --days <n>Suma USD por kit / modelo / período.
anthropic-resourcesLista recursos en Anthropic (sessions, environments, memory_stores) y cruza contra DB para detectar huérfanos.
cleanup-orphanedBorra recursos de Anthropic que no aparecen en ninguna tabla nuestra.
debug-pricingImprime los rates actuales + un ejemplo de cálculo.