feat: add task workflow and asset downloads
This commit is contained in:
26
app/api/v1/jobs/[id]/cancel/route.ts
Normal file
26
app/api/v1/jobs/[id]/cancel/route.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { clearGenerationJobLock, getGenerationJob, updateGenerationJob } from "@/lib/server/data-store";
|
||||
import { jsonError, jsonOk } from "@/lib/server/api";
|
||||
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
|
||||
import { publicApiError } from "@/lib/server/public-api-response";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
export async function POST(request: Request, context: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const client = authenticatePublicApiRequest(request);
|
||||
const { id } = await context.params;
|
||||
const job = await getGenerationJob(id);
|
||||
if (!job || job.externalClientId !== client.id) return jsonError("Job not found.", 404);
|
||||
if (["succeeded", "failed", "expired", "cancelled"].includes(job.status)) {
|
||||
return jsonOk({ job });
|
||||
}
|
||||
await updateGenerationJob(id, {
|
||||
status: "cancelled",
|
||||
completedAt: new Date().toISOString()
|
||||
});
|
||||
const cancelled = await clearGenerationJobLock(id);
|
||||
return jsonOk({ job: cancelled });
|
||||
} catch (error) {
|
||||
return publicApiError(error);
|
||||
}
|
||||
}
|
||||
18
app/api/v1/jobs/[id]/route.ts
Normal file
18
app/api/v1/jobs/[id]/route.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { getGenerationJob } from "@/lib/server/data-store";
|
||||
import { jsonError, jsonOk } from "@/lib/server/api";
|
||||
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
|
||||
import { publicApiError } from "@/lib/server/public-api-response";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
export async function GET(request: Request, context: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const client = authenticatePublicApiRequest(request);
|
||||
const { id } = await context.params;
|
||||
const job = await getGenerationJob(id);
|
||||
if (!job || job.externalClientId !== client.id) return jsonError("Job not found.", 404);
|
||||
return jsonOk({ job });
|
||||
} catch (error) {
|
||||
return publicApiError(error);
|
||||
}
|
||||
}
|
||||
65
app/api/v1/jobs/route.ts
Normal file
65
app/api/v1/jobs/route.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { listGenerationJobsFiltered } from "@/lib/server/data-store";
|
||||
import { jsonOk, readJsonBody } from "@/lib/server/api";
|
||||
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
|
||||
import { createPublicGenerationJob, type PublicJobCreateBody } from "@/lib/server/public-api-jobs";
|
||||
import { publicApiError } from "@/lib/server/public-api-response";
|
||||
import { DEFAULT_OWNER_ID, requestOrigin } from "@/lib/server/runtime";
|
||||
import type { GenerationCapability, GenerationStatus } from "@/lib/types";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const client = authenticatePublicApiRequest(request);
|
||||
const url = new URL(request.url);
|
||||
const jobs = await listGenerationJobsFiltered({
|
||||
ownerId: DEFAULT_OWNER_ID,
|
||||
externalClientId: client.id,
|
||||
status: parseStatus(url.searchParams.get("status")),
|
||||
capability: parseCapability(url.searchParams.get("capability")),
|
||||
limit: parseLimit(url.searchParams.get("limit")),
|
||||
before: url.searchParams.get("before") || undefined
|
||||
});
|
||||
return jsonOk({ jobs });
|
||||
} catch (error) {
|
||||
return publicApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const client = authenticatePublicApiRequest(request);
|
||||
const body = await readJsonBody<PublicJobCreateBody>(request);
|
||||
const result = await createPublicGenerationJob({
|
||||
client,
|
||||
body,
|
||||
request,
|
||||
origin: requestOrigin(request)
|
||||
});
|
||||
return jsonOk({ job: result.job, reused: result.reused }, { status: result.reused ? 200 : 202 });
|
||||
} catch (error) {
|
||||
return publicApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
function parseStatus(value: string | null): GenerationStatus | undefined {
|
||||
if (!value) return undefined;
|
||||
if (["queued", "running", "succeeded", "failed", "expired", "cancelled"].includes(value)) {
|
||||
return value as GenerationStatus;
|
||||
}
|
||||
throw new Error(`Unsupported status filter: ${value}`);
|
||||
}
|
||||
|
||||
function parseCapability(value: string | null): GenerationCapability | undefined {
|
||||
if (!value) return undefined;
|
||||
if (["image.generate", "image.inpaint", "image.upscale", "video.generate"].includes(value)) {
|
||||
return value as GenerationCapability;
|
||||
}
|
||||
throw new Error(`Unsupported capability filter: ${value}`);
|
||||
}
|
||||
|
||||
function parseLimit(value: string | null): number {
|
||||
const parsed = Number(value || 50);
|
||||
if (!Number.isFinite(parsed)) return 50;
|
||||
return Math.max(1, Math.min(200, Math.trunc(parsed)));
|
||||
}
|
||||
Reference in New Issue
Block a user