Respawn Tech Dev

Extrator de erro de CI

Extraia de um log de CI só as linhas que explicam a falha.

Envie o log completo de um job de CI e receba apenas as linhas do erro, sem o ruído do restante. Ideal para agentes e bots que precisam entender por que um build falhou sem gastar contexto com milhares de linhas.

Base path
/v1/tools/ci
Escopos
tools:ci:readtools:readtools:manage

Visão geral

Envie o log de um job de CI e receba apenas as linhas do erro. Serve para agentes e bots que precisam entender por que um build falhou sem carregar milhares de linhas no contexto. Também está disponível no MCP como ci_error_extract.

OperaçãoRota
Extrair o erro de um logPOST/extract

Custos

Cada extração é uma leitura medida: entra na franquia diária e, depois dela, debita o valor indicado no endpoint. A cobrança vale só para chaves de API.

Endpoints

Extrair o erro de um log

POST/v1/tools/ci/extract
Custo
Franquia diária, depois 0,01 crédito/leitura via API
Dry-run
Suportado (X-Dry-Run: true)
Autenticação
qualquer um detools:ci:readtools:readtools:manage

log (obrigatório) é o texto do log. max_lines (opcional, padrão 40, máximo 200) limita quantas linhas do erro voltam.

curl -sS -X POST 'https://api.respawntech.dev/v1/tools/ci/extract' \
  -H "X-API-Token: $RESPAWN_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "log": "npm ERR! code ELIFECYCLE\nnpm ERR! errno 1\nFAIL src/app.test.ts", "max_lines": 40 }'
const response = await fetch('https://api.respawntech.dev/v1/tools/ci/extract', {
  method: 'POST',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ "log": "npm ERR! code ELIFECYCLE\nnpm ERR! errno 1\nFAIL src/app.test.ts", "max_lines": 40 }),
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.post(
    "https://api.respawntech.dev/v1/tools/ci/extract",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    json={ "log": "npm ERR! code ELIFECYCLE\nnpm ERR! errno 1\nFAIL src/app.test.ts", "max_lines": 40 },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/ci/extract');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{ "log": "npm ERR! code ELIFECYCLE\nnpm ERR! errno 1\nFAIL src/app.test.ts", "max_lines": 40 }
JSON,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/ci/extract", strings.NewReader(`{ "log": "npm ERR! code ELIFECYCLE\nnpm ERR! errno 1\nFAIL src/app.test.ts", "max_lines": 40 }`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "lines": [
      "npm ERR! code ELIFECYCLE",
      "npm ERR! errno 1",
      "FAIL src/app.test.ts"
    ]
  }
}

Erros

CódigoHTTPQuando
tools.ci.log_required400Campo log ausente ou vazio.
tools.ci.log_too_large413Log acima do tamanho máximo aceito.

Atualizado em