Task 007 add agent job admin runner follow-up
This commit is contained in:
@@ -75,6 +75,18 @@ class SchemaStorageContractsIntegrationTest(unittest.TestCase):
|
|||||||
"transform_script",
|
"transform_script",
|
||||||
}.issubset(repository.schema.list_columns("script_config_versions"))
|
}.issubset(repository.schema.list_columns("script_config_versions"))
|
||||||
)
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
{
|
||||||
|
"parent_job_id",
|
||||||
|
"attempt",
|
||||||
|
"stdout",
|
||||||
|
"stderr",
|
||||||
|
"exit_code",
|
||||||
|
"duration_ms",
|
||||||
|
"workspace_path",
|
||||||
|
"output_files",
|
||||||
|
}.issubset(repository.schema.list_columns("agent_jobs"))
|
||||||
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
{
|
{
|
||||||
"s3_prefix",
|
"s3_prefix",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"test:roles": "node tests/role-navigation.test.mjs",
|
"test:roles": "node tests/role-navigation.test.mjs",
|
||||||
"test:ui": "node tests/role-navigation.test.mjs && node tests/article_dashboard.test.mjs && node tests/article_form_validation.test.mjs && node tests/admin_script_versions.model.test.mjs",
|
"test:ui": "node tests/role-navigation.test.mjs && node tests/article_dashboard.test.mjs && node tests/article_form_validation.test.mjs && node tests/admin_script_versions.model.test.mjs && node tests/agent_jobs.model.test.mjs",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import AdminJobsPage from "@/pages/admin-jobs";
|
||||||
|
|
||||||
|
export default AdminJobsPage;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import type { AgentJobSummary } from "@pipeline/shared";
|
||||||
|
|
||||||
|
export type AgentJobRow = {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
status: string;
|
||||||
|
attempt: number;
|
||||||
|
parentJobId: string | null;
|
||||||
|
workspacePath: string | null;
|
||||||
|
stdout: string;
|
||||||
|
stderr: string;
|
||||||
|
exitCode: number | null;
|
||||||
|
durationMs: number | null;
|
||||||
|
outputFiles: string;
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function buildAgentJobRows(jobs: readonly AgentJobSummary[]): AgentJobRow[] {
|
||||||
|
return jobs.map((job) => ({
|
||||||
|
id: job.id,
|
||||||
|
type: job.job_type,
|
||||||
|
status: job.status,
|
||||||
|
attempt: job.attempt,
|
||||||
|
parentJobId: job.parent_job_id ?? null,
|
||||||
|
workspacePath: job.workspace_path ?? null,
|
||||||
|
stdout: job.stdout,
|
||||||
|
stderr: job.stderr,
|
||||||
|
exitCode: job.exit_code ?? null,
|
||||||
|
durationMs: job.duration_ms ?? null,
|
||||||
|
outputFiles: job.output_files.map((file) => file.path).join(", "),
|
||||||
|
error: job.error_category ?? job.error_message ?? "",
|
||||||
|
}));
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import type { AgentJobRow } from "./model";
|
||||||
|
|
||||||
|
type AgentJobsTableProps = {
|
||||||
|
rows: readonly AgentJobRow[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function AgentJobsTable({ rows }: AgentJobsTableProps) {
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return <p className="emptyState">No agent jobs yet.</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<table className="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Job</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Attempt</th>
|
||||||
|
<th>Runtime</th>
|
||||||
|
<th>Workspace</th>
|
||||||
|
<th>Logs</th>
|
||||||
|
<th>Outputs</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{rows.map((row) => (
|
||||||
|
<tr key={row.id}>
|
||||||
|
<td>
|
||||||
|
<div>{row.type}</div>
|
||||||
|
<small>{row.id}</small>
|
||||||
|
{row.parentJobId ? <div>retry of {row.parentJobId}</div> : null}
|
||||||
|
</td>
|
||||||
|
<td>{row.status}</td>
|
||||||
|
<td>{row.attempt}</td>
|
||||||
|
<td>
|
||||||
|
<div>exit: {row.exitCode ?? "pending"}</div>
|
||||||
|
<div>{row.durationMs ?? 0} ms</div>
|
||||||
|
{row.error ? <div>{row.error}</div> : null}
|
||||||
|
</td>
|
||||||
|
<td>{row.workspacePath ?? "pending"}</td>
|
||||||
|
<td>
|
||||||
|
<pre className="logBlock">{row.stdout || "stdout pending"}</pre>
|
||||||
|
{row.stderr ? <pre className="logBlock">{row.stderr}</pre> : null}
|
||||||
|
</td>
|
||||||
|
<td>{row.outputFiles || "none"}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
import { AgentJobsTable } from "@/features/agent-jobs/ui";
|
||||||
|
import { buildAgentJobRows } from "@/features/agent-jobs/model";
|
||||||
|
import { fetchAgentJobs } from "@/shared/pipeline-api";
|
||||||
|
import { RoleNavigation } from "@/widgets/role-navigation";
|
||||||
|
|
||||||
|
export default async function AdminJobsPage() {
|
||||||
|
const jobs = await fetchAgentJobs();
|
||||||
|
const rows = buildAgentJobRows(jobs.jobs);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<header className="pageHeader">
|
||||||
|
<div>
|
||||||
|
<h1>Agent Jobs</h1>
|
||||||
|
<p>Monitor runner status, logs, outputs, and retry lineage.</p>
|
||||||
|
</div>
|
||||||
|
<Link href="/">Back to dashboard</Link>
|
||||||
|
<span className="roleBadge">Admin demo</span>
|
||||||
|
</header>
|
||||||
|
<RoleNavigation role="ADMIN" />
|
||||||
|
<section className="panel">
|
||||||
|
<AgentJobsTable rows={rows} />
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,6 +2,9 @@ import type {
|
|||||||
ArticleCreateRequest,
|
ArticleCreateRequest,
|
||||||
ArticleCreateResponse,
|
ArticleCreateResponse,
|
||||||
ArticleDetailResponse,
|
ArticleDetailResponse,
|
||||||
|
AgentJobListResponse,
|
||||||
|
AgentJobResponse,
|
||||||
|
AgentJobTestCodexRequest,
|
||||||
ArticleListResponse,
|
ArticleListResponse,
|
||||||
CurrentUserResponse,
|
CurrentUserResponse,
|
||||||
ScriptConfigVersionCreateRequest,
|
ScriptConfigVersionCreateRequest,
|
||||||
@@ -149,6 +152,45 @@ export function fetchCurrentUser(): Promise<CurrentUserResponse> {
|
|||||||
return apiGet<CurrentUserResponse>("/api/me");
|
return apiGet<CurrentUserResponse>("/api/me");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fetchAgentJobs(
|
||||||
|
userEmail = DEMO_ADMIN_EMAIL,
|
||||||
|
): Promise<AgentJobListResponse> {
|
||||||
|
return apiGet<AgentJobListResponse>("/api/agent-jobs", { userEmail });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTestCodexJob(
|
||||||
|
request: AgentJobTestCodexRequest = { fake_result: "valid" },
|
||||||
|
userEmail = DEMO_ADMIN_EMAIL,
|
||||||
|
): Promise<AgentJobResponse> {
|
||||||
|
return apiPost<AgentJobTestCodexRequest, AgentJobResponse>(
|
||||||
|
"/api/agent-jobs/test-codex",
|
||||||
|
request,
|
||||||
|
{ userEmail },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function retryAgentJob(
|
||||||
|
jobId: string,
|
||||||
|
userEmail = DEMO_ADMIN_EMAIL,
|
||||||
|
): Promise<AgentJobResponse> {
|
||||||
|
return apiPost<unknown, AgentJobResponse>(
|
||||||
|
`/api/agent-jobs/${jobId}/retry`,
|
||||||
|
undefined,
|
||||||
|
{ userEmail },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cancelAgentJob(
|
||||||
|
jobId: string,
|
||||||
|
userEmail = DEMO_ADMIN_EMAIL,
|
||||||
|
): Promise<AgentJobResponse> {
|
||||||
|
return apiPost<unknown, AgentJobResponse>(
|
||||||
|
`/api/agent-jobs/${jobId}/cancel`,
|
||||||
|
undefined,
|
||||||
|
{ userEmail },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function fetchTargetSites(): Promise<TargetSiteConfigResponse[]> {
|
export function fetchTargetSites(): Promise<TargetSiteConfigResponse[]> {
|
||||||
return apiGet<TargetSiteConfigResponse[]>("/api/sites");
|
return apiGet<TargetSiteConfigResponse[]>("/api/sites");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ export const ROLE_NAVIGATION_ITEMS = [
|
|||||||
href: "/admin/scripts",
|
href: "/admin/scripts",
|
||||||
roles: ["ADMIN"],
|
roles: ["ADMIN"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "agent-jobs",
|
||||||
|
label: "Agent jobs",
|
||||||
|
href: "/admin/jobs",
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
},
|
||||||
] as const satisfies readonly NavigationItem[];
|
] as const satisfies readonly NavigationItem[];
|
||||||
|
|
||||||
export function getRoleNavigationItems(role: Role): NavigationItem[] {
|
export function getRoleNavigationItems(role: Role): NavigationItem[] {
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
import ts from "typescript";
|
||||||
|
|
||||||
|
const testDir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const sourcePath = path.resolve(testDir, "../src/features/agent-jobs/model.ts");
|
||||||
|
const source = readFileSync(sourcePath, "utf8");
|
||||||
|
const compiled = ts.transpileModule(source, {
|
||||||
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const moduleExports = {};
|
||||||
|
new Function("exports", compiled.outputText)(moduleExports);
|
||||||
|
|
||||||
|
const { buildAgentJobRows } = moduleExports;
|
||||||
|
|
||||||
|
const rows = buildAgentJobRows([
|
||||||
|
{
|
||||||
|
id: "11111111-1111-1111-1111-111111111111",
|
||||||
|
article_id: null,
|
||||||
|
parent_job_id: "00000000-0000-0000-0000-000000000000",
|
||||||
|
attempt: 2,
|
||||||
|
job_type: "TEST_CODEX",
|
||||||
|
agent_profile: "fake-codex",
|
||||||
|
status: "SUCCEEDED",
|
||||||
|
workspace_path: "/tmp/job",
|
||||||
|
input_files: [{ path: "inputs/job.json" }],
|
||||||
|
output_files: [{ path: "outputs/result.json" }],
|
||||||
|
error_category: null,
|
||||||
|
error_message: null,
|
||||||
|
stdout: "done",
|
||||||
|
stderr: "",
|
||||||
|
exit_code: 0,
|
||||||
|
duration_ms: 5,
|
||||||
|
queued_at: "2026-05-21T00:00:00Z",
|
||||||
|
started_at: "2026-05-21T00:00:01Z",
|
||||||
|
finished_at: "2026-05-21T00:00:02Z",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert.equal(rows.length, 1);
|
||||||
|
assert.equal(rows[0].status, "SUCCEEDED");
|
||||||
|
assert.equal(rows[0].attempt, 2);
|
||||||
|
assert.equal(rows[0].parentJobId, "00000000-0000-0000-0000-000000000000");
|
||||||
|
assert.equal(rows[0].outputFiles, "outputs/result.json");
|
||||||
|
assert.equal(rows[0].stdout, "done");
|
||||||
@@ -36,5 +36,9 @@ assert.equal(
|
|||||||
adminItems.some((item) => item.id === "script-versions"),
|
adminItems.some((item) => item.id === "script-versions"),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
assert.equal(
|
||||||
|
adminItems.some((item) => item.id === "agent-jobs"),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
console.log("role navigation hides Admin-only items for Editors");
|
console.log("role navigation hides Admin-only items for Editors");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -90,6 +91,34 @@ def run_fake_runner_once(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_fake_runner_loop(
|
||||||
|
*,
|
||||||
|
backend_url: str,
|
||||||
|
workspace_root: Path,
|
||||||
|
poll_interval_seconds: float,
|
||||||
|
) -> None:
|
||||||
|
backend_client = HttpBackendJobClient(backend_url)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
run_fake_runner_once(backend_client, workspace_root=workspace_root)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
time.sleep(poll_interval_seconds)
|
||||||
|
|
||||||
|
|
||||||
|
def get_backend_url() -> str:
|
||||||
|
backend_url = os.environ.get("BACKEND_URL")
|
||||||
|
if not backend_url:
|
||||||
|
raise RuntimeError("BACKEND_URL is required for fake runner")
|
||||||
|
return backend_url
|
||||||
|
|
||||||
|
|
||||||
|
def get_workspace_root() -> Path:
|
||||||
|
return Path(
|
||||||
|
os.environ.get("RUNNER_WORKSPACE_ROOT", "/tmp/pipeline-runner-workspaces")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def materialize_fake_workspace(
|
def materialize_fake_workspace(
|
||||||
job: dict[str, Any],
|
job: dict[str, Any],
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ import threading
|
|||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||||
|
|
||||||
from src.application.fake_runner import get_backend_url, get_workspace_root, run_fake_runner_loop
|
from src.application.fake_runner import (
|
||||||
|
HttpBackendJobClient,
|
||||||
|
get_backend_url,
|
||||||
|
get_workspace_root,
|
||||||
|
run_fake_runner_loop,
|
||||||
|
run_fake_runner_once,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HealthHandler(BaseHTTPRequestHandler):
|
class HealthHandler(BaseHTTPRequestHandler):
|
||||||
@@ -22,6 +28,32 @@ class HealthHandler(BaseHTTPRequestHandler):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(body)
|
self.wfile.write(body)
|
||||||
|
|
||||||
|
def do_POST(self) -> None:
|
||||||
|
if self.path != "/run-once":
|
||||||
|
self.send_error(HTTPStatus.NOT_FOUND)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = run_fake_runner_once(
|
||||||
|
HttpBackendJobClient(get_backend_url()),
|
||||||
|
workspace_root=get_workspace_root(),
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
|
body = json.dumps({"status": "error", "detail": str(error)}).encode("utf-8")
|
||||||
|
self.send_response(HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
self.send_header("Content-Type", "application/json")
|
||||||
|
self.send_header("Content-Length", str(len(body)))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(body)
|
||||||
|
return
|
||||||
|
|
||||||
|
body = json.dumps({"status": "ok", "job": result}, default=str).encode("utf-8")
|
||||||
|
self.send_response(HTTPStatus.OK)
|
||||||
|
self.send_header("Content-Type", "application/json")
|
||||||
|
self.send_header("Content-Length", str(len(body)))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(body)
|
||||||
|
|
||||||
def log_message(self, format: str, *args: object) -> None:
|
def log_message(self, format: str, *args: object) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import tempfile
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[3]
|
||||||
|
RUNNER_ROOT = REPO_ROOT / "apps" / "runner"
|
||||||
|
sys.path.insert(0, str(RUNNER_ROOT))
|
||||||
|
|
||||||
|
from src.application.fake_runner import run_fake_runner_once
|
||||||
|
|
||||||
|
|
||||||
|
class FakeBackendJobClient:
|
||||||
|
def __init__(self, job: dict[str, Any] | None) -> None:
|
||||||
|
self.job = job
|
||||||
|
self.completed: dict[str, Any] | None = None
|
||||||
|
|
||||||
|
def claim_job(self) -> dict[str, Any] | None:
|
||||||
|
job = self.job
|
||||||
|
self.job = None
|
||||||
|
return job
|
||||||
|
|
||||||
|
def complete_job(self, job_id: str, payload: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
self.completed = {"id": job_id, **payload}
|
||||||
|
return self.completed
|
||||||
|
|
||||||
|
|
||||||
|
class FakeRunnerTest(unittest.TestCase):
|
||||||
|
def test_fake_runner_claims_job_writes_workspace_and_completes(self) -> None:
|
||||||
|
backend = FakeBackendJobClient(
|
||||||
|
{
|
||||||
|
"id": "11111111-1111-1111-1111-111111111111",
|
||||||
|
"agent_profile": "fake-codex",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
result = run_fake_runner_once(
|
||||||
|
backend,
|
||||||
|
workspace_root=Path(temp_dir),
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
assert result is not None
|
||||||
|
workspace_path = Path(result["workspace_path"])
|
||||||
|
self.assertTrue((workspace_path / "inputs" / "job.json").is_file())
|
||||||
|
self.assertTrue((workspace_path / "logs" / "stdout.log").is_file())
|
||||||
|
self.assertTrue((workspace_path / "logs" / "stderr.log").is_file())
|
||||||
|
self.assertTrue((workspace_path / "outputs" / "result.json").is_file())
|
||||||
|
self.assertEqual(0, result["exit_code"])
|
||||||
|
self.assertEqual("SUCCEEDED", result["output"]["status"])
|
||||||
|
self.assertEqual([{"path": "outputs/result.json"}], result["output"]["output_files"])
|
||||||
|
|
||||||
|
def test_fake_runner_can_emit_invalid_schema_fixture(self) -> None:
|
||||||
|
backend = FakeBackendJobClient(
|
||||||
|
{
|
||||||
|
"id": "22222222-2222-2222-2222-222222222222",
|
||||||
|
"agent_profile": "fake-invalid-schema",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
result = run_fake_runner_once(
|
||||||
|
backend,
|
||||||
|
workspace_root=Path(temp_dir),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
assert result is not None
|
||||||
|
self.assertEqual({"status": "NOT_A_STATUS"}, result["output"])
|
||||||
|
|
||||||
|
def test_fake_runner_noops_without_queued_job(self) -> None:
|
||||||
|
backend = FakeBackendJobClient(None)
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
result = run_fake_runner_once(
|
||||||
|
backend,
|
||||||
|
workspace_root=Path(temp_dir),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNone(result)
|
||||||
|
self.assertIsNone(backend.completed)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -41,8 +41,12 @@ services:
|
|||||||
dockerfile: apps/runner/Dockerfile
|
dockerfile: apps/runner/Dockerfile
|
||||||
environment:
|
environment:
|
||||||
RUNNER_MODE: fake
|
RUNNER_MODE: fake
|
||||||
|
BACKEND_URL: http://backend:8000
|
||||||
ports:
|
ports:
|
||||||
- "${RUNNER_PORT:-8010}:8010"
|
- "${RUNNER_PORT:-8010}:8010"
|
||||||
|
depends_on:
|
||||||
|
backend:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
|
|||||||
+417
-21
@@ -19,6 +19,23 @@
|
|||||||
"title": "AgentJobErrorCategory",
|
"title": "AgentJobErrorCategory",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"AgentJobListResponse": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"jobs": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobSummary"
|
||||||
|
},
|
||||||
|
"title": "Jobs",
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"jobs"
|
||||||
|
],
|
||||||
|
"title": "AgentJobListResponse",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AgentJobOutput": {
|
"AgentJobOutput": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -74,6 +91,19 @@
|
|||||||
"title": "AgentJobOutput",
|
"title": "AgentJobOutput",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AgentJobResponse": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"job": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobSummary"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"job"
|
||||||
|
],
|
||||||
|
"title": "AgentJobResponse",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AgentJobStatus": {
|
"AgentJobStatus": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"QUEUED",
|
"QUEUED",
|
||||||
@@ -94,10 +124,37 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"article_id": {
|
"article_id": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"title": "Article Id",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"title": "Article Id"
|
||||||
|
},
|
||||||
|
"attempt": {
|
||||||
|
"default": 1,
|
||||||
|
"minimum": 1,
|
||||||
|
"title": "Attempt",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"duration_ms": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"minimum": 0,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"title": "Duration Ms"
|
||||||
|
},
|
||||||
"error_category": {
|
"error_category": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -121,6 +178,18 @@
|
|||||||
"default": null,
|
"default": null,
|
||||||
"title": "Error Message"
|
"title": "Error Message"
|
||||||
},
|
},
|
||||||
|
"exit_code": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"title": "Exit Code"
|
||||||
|
},
|
||||||
"finished_at": {
|
"finished_at": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -156,6 +225,24 @@
|
|||||||
"title": "Output Files",
|
"title": "Output Files",
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"parent_job_id": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"title": "Parent Job Id"
|
||||||
|
},
|
||||||
|
"queued_at": {
|
||||||
|
"format": "date-time",
|
||||||
|
"title": "Queued At",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"started_at": {
|
"started_at": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -172,6 +259,16 @@
|
|||||||
"status": {
|
"status": {
|
||||||
"$ref": "#/components/schemas/AgentJobStatus"
|
"$ref": "#/components/schemas/AgentJobStatus"
|
||||||
},
|
},
|
||||||
|
"stderr": {
|
||||||
|
"default": "",
|
||||||
|
"title": "Stderr",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"default": "",
|
||||||
|
"title": "Stdout",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"workspace_path": {
|
"workspace_path": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -187,14 +284,27 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"article_id",
|
|
||||||
"job_type",
|
"job_type",
|
||||||
"agent_profile",
|
"agent_profile",
|
||||||
"status"
|
"status",
|
||||||
|
"queued_at"
|
||||||
],
|
],
|
||||||
"title": "AgentJobSummary",
|
"title": "AgentJobSummary",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AgentJobTestCodexRequest": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"fake_result": {
|
||||||
|
"default": "valid",
|
||||||
|
"pattern": "^(valid|invalid_schema)$",
|
||||||
|
"title": "Fake Result",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "AgentJobTestCodexRequest",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AgentJobType": {
|
"AgentJobType": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"BOUNDARY_QUESTIONS",
|
"BOUNDARY_QUESTIONS",
|
||||||
@@ -1563,16 +1673,6 @@
|
|||||||
"ScriptConfigVersionSummary": {
|
"ScriptConfigVersionSummary": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"created_at": {
|
|
||||||
"format": "date-time",
|
|
||||||
"title": "Created At",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"created_by": {
|
|
||||||
"format": "uuid",
|
|
||||||
"title": "Created By",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"activated_at": {
|
"activated_at": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -1583,8 +1683,19 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"default": null,
|
||||||
"title": "Activated At"
|
"title": "Activated At"
|
||||||
},
|
},
|
||||||
|
"created_at": {
|
||||||
|
"format": "date-time",
|
||||||
|
"title": "Created At",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"created_by": {
|
||||||
|
"format": "uuid",
|
||||||
|
"title": "Created By",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"diff": {
|
"diff": {
|
||||||
"additionalProperties": true,
|
"additionalProperties": true,
|
||||||
"title": "Diff",
|
"title": "Diff",
|
||||||
@@ -1600,14 +1711,6 @@
|
|||||||
"title": "Publishing Yaml Hash",
|
"title": "Publishing Yaml Hash",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"status": {
|
|
||||||
"$ref": "#/components/schemas/ScriptConfigVersionStatus"
|
|
||||||
},
|
|
||||||
"target_site_id": {
|
|
||||||
"format": "uuid",
|
|
||||||
"title": "Target Site Id",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"rollback_target_version_id": {
|
"rollback_target_version_id": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -1618,8 +1721,17 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"default": null,
|
||||||
"title": "Rollback Target Version Id"
|
"title": "Rollback Target Version Id"
|
||||||
},
|
},
|
||||||
|
"status": {
|
||||||
|
"$ref": "#/components/schemas/ScriptConfigVersionStatus"
|
||||||
|
},
|
||||||
|
"target_site_id": {
|
||||||
|
"format": "uuid",
|
||||||
|
"title": "Target Site Id",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"transform_script_hash": {
|
"transform_script_hash": {
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"title": "Transform Script Hash",
|
"title": "Transform Script Hash",
|
||||||
@@ -2116,6 +2228,290 @@
|
|||||||
},
|
},
|
||||||
"openapi": "3.1.0",
|
"openapi": "3.1.0",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/api/agent-jobs": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "get_agent_jobs_api_agent_jobs_get",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "header",
|
||||||
|
"name": "X-Demo-User-Email",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "X-Demo-User-Email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobListResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful Response"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Validation Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Get Agent Jobs",
|
||||||
|
"tags": [
|
||||||
|
"agent-jobs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/agent-jobs/test-codex": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "post_test_codex_job_api_agent_jobs_test_codex_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "header",
|
||||||
|
"name": "X-Demo-User-Email",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "X-Demo-User-Email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobTestCodexRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful Response"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Validation Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Post Test Codex Job",
|
||||||
|
"tags": [
|
||||||
|
"agent-jobs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/agent-jobs/{job_id}": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "get_agent_job_route_api_agent_jobs__job_id__get",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "job_id",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"title": "Job Id",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "header",
|
||||||
|
"name": "X-Demo-User-Email",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "X-Demo-User-Email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful Response"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Validation Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Get Agent Job Route",
|
||||||
|
"tags": [
|
||||||
|
"agent-jobs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/agent-jobs/{job_id}/cancel": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "post_cancel_agent_job_api_agent_jobs__job_id__cancel_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "job_id",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"title": "Job Id",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "header",
|
||||||
|
"name": "X-Demo-User-Email",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "X-Demo-User-Email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful Response"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Validation Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Post Cancel Agent Job",
|
||||||
|
"tags": [
|
||||||
|
"agent-jobs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/agent-jobs/{job_id}/retry": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "post_retry_agent_job_api_agent_jobs__job_id__retry_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "job_id",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"title": "Job Id",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "header",
|
||||||
|
"name": "X-Demo-User-Email",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "X-Demo-User-Email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AgentJobResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful Response"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Validation Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Post Retry Agent Job",
|
||||||
|
"tags": [
|
||||||
|
"agent-jobs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/articles": {
|
"/api/articles": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "list_articles_route_api_articles_get",
|
"operationId": "list_articles_route_api_articles_get",
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
export type AgentJobErrorCategory = "FAILED_SCHEMA_VALIDATION" | "CLI_EXIT_CODE_FAILURE" | "TIMEOUT" | "MISSING_OUTPUT_FILE" | "UNSUPPORTED_CLAIMS_FOUND" | "SOURCE_RETRIEVAL_FAILED" | "RESEARCH_ARTIFACT_UPLOAD_FAILED" | "PUBLISH_DRY_RUN_FAILED" | "GIT_CHECKOUT_FAILED" | "GIT_COMMIT_FAILED" | "GIT_PUSH_NON_FAST_FORWARD" | "PUBLISH_VERIFICATION_FAILED";
|
export type AgentJobErrorCategory = "FAILED_SCHEMA_VALIDATION" | "CLI_EXIT_CODE_FAILURE" | "TIMEOUT" | "MISSING_OUTPUT_FILE" | "UNSUPPORTED_CLAIMS_FOUND" | "SOURCE_RETRIEVAL_FAILED" | "RESEARCH_ARTIFACT_UPLOAD_FAILED" | "PUBLISH_DRY_RUN_FAILED" | "GIT_CHECKOUT_FAILED" | "GIT_COMMIT_FAILED" | "GIT_PUSH_NON_FAST_FORWARD" | "PUBLISH_VERIFICATION_FAILED";
|
||||||
|
|
||||||
|
export type AgentJobListResponse = {
|
||||||
|
jobs: AgentJobSummary[];
|
||||||
|
};
|
||||||
|
|
||||||
export type AgentJobOutput = {
|
export type AgentJobOutput = {
|
||||||
artifacts?: ResearchArtifactSummary[];
|
artifacts?: ResearchArtifactSummary[];
|
||||||
error_category?: AgentJobErrorCategory | null;
|
error_category?: AgentJobErrorCategory | null;
|
||||||
@@ -12,23 +16,38 @@ export type AgentJobOutput = {
|
|||||||
status: AgentJobStatus;
|
status: AgentJobStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AgentJobResponse = {
|
||||||
|
job: AgentJobSummary;
|
||||||
|
};
|
||||||
|
|
||||||
export type AgentJobStatus = "QUEUED" | "RUNNING" | "SUCCEEDED" | "FAILED" | "CANCELLED";
|
export type AgentJobStatus = "QUEUED" | "RUNNING" | "SUCCEEDED" | "FAILED" | "CANCELLED";
|
||||||
|
|
||||||
export type AgentJobSummary = {
|
export type AgentJobSummary = {
|
||||||
agent_profile: string;
|
agent_profile: string;
|
||||||
article_id: string;
|
article_id?: string | null;
|
||||||
|
attempt?: number;
|
||||||
|
duration_ms?: number | null;
|
||||||
error_category?: AgentJobErrorCategory | null;
|
error_category?: AgentJobErrorCategory | null;
|
||||||
error_message?: string | null;
|
error_message?: string | null;
|
||||||
|
exit_code?: number | null;
|
||||||
finished_at?: string | null;
|
finished_at?: string | null;
|
||||||
id: string;
|
id: string;
|
||||||
input_files?: RunnerFileRef[];
|
input_files?: RunnerFileRef[];
|
||||||
job_type: AgentJobType;
|
job_type: AgentJobType;
|
||||||
output_files?: RunnerFileRef[];
|
output_files?: RunnerFileRef[];
|
||||||
|
parent_job_id?: string | null;
|
||||||
|
queued_at: string;
|
||||||
started_at?: string | null;
|
started_at?: string | null;
|
||||||
status: AgentJobStatus;
|
status: AgentJobStatus;
|
||||||
|
stderr?: string;
|
||||||
|
stdout?: string;
|
||||||
workspace_path?: string | null;
|
workspace_path?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AgentJobTestCodexRequest = {
|
||||||
|
fake_result?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type AgentJobType = "BOUNDARY_QUESTIONS" | "PLAN_GENERATION" | "RESEARCH" | "EVIDENCE_MATRIX" | "SECTION_SCAFFOLD" | "DRAFT_ASSEMBLY" | "SEO_REVIEW" | "LANGUAGE_REVIEW" | "PUBLISH_DRY_RUN" | "PUBLISH_COMMIT" | "TEST_CODEX";
|
export type AgentJobType = "BOUNDARY_QUESTIONS" | "PLAN_GENERATION" | "RESEARCH" | "EVIDENCE_MATRIX" | "SECTION_SCAFFOLD" | "DRAFT_ASSEMBLY" | "SEO_REVIEW" | "LANGUAGE_REVIEW" | "PUBLISH_DRY_RUN" | "PUBLISH_COMMIT" | "TEST_CODEX";
|
||||||
|
|
||||||
export type ArticleCreateRequest = {
|
export type ArticleCreateRequest = {
|
||||||
@@ -266,15 +285,15 @@ export type ScriptConfigVersionResponse = {
|
|||||||
export type ScriptConfigVersionStatus = "DRAFT" | "ACTIVE" | "DEPRECATED";
|
export type ScriptConfigVersionStatus = "DRAFT" | "ACTIVE" | "DEPRECATED";
|
||||||
|
|
||||||
export type ScriptConfigVersionSummary = {
|
export type ScriptConfigVersionSummary = {
|
||||||
|
activated_at?: string | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
created_by: string;
|
created_by: string;
|
||||||
activated_at?: string | null;
|
diff?: Record<string, unknown>;
|
||||||
diff: Record<string, unknown>;
|
|
||||||
id: string;
|
id: string;
|
||||||
publishing_yaml_hash: string;
|
publishing_yaml_hash: string;
|
||||||
|
rollback_target_version_id?: string | null;
|
||||||
status: ScriptConfigVersionStatus;
|
status: ScriptConfigVersionStatus;
|
||||||
target_site_id: string;
|
target_site_id: string;
|
||||||
rollback_target_version_id?: string | null;
|
|
||||||
transform_script_hash: string;
|
transform_script_hash: string;
|
||||||
version: number;
|
version: number;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user