@mevdragon/vidfarm-devcli 0.20.0 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.director.md +79 -7
- package/SKILL.platform.md +2 -2
- package/demo/dist/app.css +1 -1
- package/demo/dist/app.js +75 -75
- package/dist/src/app.js +306 -18
- package/dist/src/cli.js +247 -23
- package/dist/src/devcli/sync.js +66 -9
- package/dist/src/editor-chat.js +1 -1
- package/dist/src/frontend/file-directory.js +41 -18
- package/dist/src/reskin/theme.js +7 -4
- package/dist/src/services/hyperframes.js +2 -2
- package/package.json +1 -1
- package/public/assets/file-directory-app.js +3 -2
package/dist/src/app.js
CHANGED
|
@@ -24,6 +24,7 @@ import { writeForkManifest } from "./services/fork-manifest.js";
|
|
|
24
24
|
import { renderHelpPage } from "./help-page.js";
|
|
25
25
|
import { renderHomepage } from "./homepage.js";
|
|
26
26
|
import { renderLandingPage } from "./landing-page.js";
|
|
27
|
+
import { createTemplateJobContext } from "./context.js";
|
|
27
28
|
import { renderReskinIndex } from "./reskin/index-page.js";
|
|
28
29
|
import { renderReskinSettings } from "./reskin/settings-page.js";
|
|
29
30
|
import { renderReskinLibrary } from "./reskin/library-page.js";
|
|
@@ -7805,7 +7806,7 @@ async function publishCompositionToRenderer(input) {
|
|
|
7805
7806
|
fps: 30,
|
|
7806
7807
|
chunk_size: 240,
|
|
7807
7808
|
max_parallel_chunks: 8,
|
|
7808
|
-
output_key:
|
|
7809
|
+
output_key: "output.mp4",
|
|
7809
7810
|
project_files: projectFiles,
|
|
7810
7811
|
composition_data: compositionData ?? undefined
|
|
7811
7812
|
});
|
|
@@ -7894,6 +7895,48 @@ async function runPrimitiveJobInProcess(jobId) {
|
|
|
7894
7895
|
throw error;
|
|
7895
7896
|
}
|
|
7896
7897
|
}
|
|
7898
|
+
async function runTemplateJobInProcess(jobId) {
|
|
7899
|
+
const job = await jobs.getJobAsync(jobId);
|
|
7900
|
+
if (!job)
|
|
7901
|
+
throw new Error(`Job not found: ${jobId}`);
|
|
7902
|
+
const failContract = async (message) => {
|
|
7903
|
+
await jobs.failJob(job.id, { message, type: "local_runner_contract_error" });
|
|
7904
|
+
throw new Error(message);
|
|
7905
|
+
};
|
|
7906
|
+
const customer = await serverlessRecords.getCustomerById(job.customerId);
|
|
7907
|
+
if (!customer)
|
|
7908
|
+
return failContract(`Customer not found: ${job.customerId}`);
|
|
7909
|
+
const template = await templateRegistry.getExecutable(job.templateId);
|
|
7910
|
+
if (!template)
|
|
7911
|
+
return failContract(`Template not found: ${job.templateId}`);
|
|
7912
|
+
const workflow = template.jobs[job.workflowName];
|
|
7913
|
+
if (!workflow)
|
|
7914
|
+
return failContract(`Template workflow not found: ${job.workflowName}`);
|
|
7915
|
+
const workerId = createId("local_worker");
|
|
7916
|
+
try {
|
|
7917
|
+
await jobs.markRunning(job.id);
|
|
7918
|
+
const ctx = createTemplateJobContext({
|
|
7919
|
+
customer,
|
|
7920
|
+
job,
|
|
7921
|
+
template,
|
|
7922
|
+
workerId,
|
|
7923
|
+
storage,
|
|
7924
|
+
jobs,
|
|
7925
|
+
billing,
|
|
7926
|
+
providers,
|
|
7927
|
+
hyperframes
|
|
7928
|
+
});
|
|
7929
|
+
const result = await workflow(ctx, job.payload);
|
|
7930
|
+
await jobs.succeedJob(job.id, result.output ?? {}, result.progress ?? 1);
|
|
7931
|
+
}
|
|
7932
|
+
catch (error) {
|
|
7933
|
+
await jobs.failJob(job.id, {
|
|
7934
|
+
message: error instanceof Error ? error.message : "Local template job failed",
|
|
7935
|
+
type: "local_render_failed"
|
|
7936
|
+
});
|
|
7937
|
+
throw error;
|
|
7938
|
+
}
|
|
7939
|
+
}
|
|
7897
7940
|
function mapJobStatusToPublishPhase(status) {
|
|
7898
7941
|
const normalized = String(status ?? "").toLowerCase();
|
|
7899
7942
|
if (normalized === "completed" || normalized === "succeeded")
|
|
@@ -7977,6 +8020,7 @@ function adaptJobToPublishStatus(job, fallbackTitle) {
|
|
|
7977
8020
|
cost,
|
|
7978
8021
|
outputS3Uri: readNonEmptyString(asRecord(result.output)?.s3_uri) ?? readNonEmptyString(renderBlock.output_s3_uri),
|
|
7979
8022
|
outputUrl,
|
|
8023
|
+
expectedOutputPublicUrl: readNonEmptyString(record.expected_output_public_url) ?? expectedHyperframesRenderOutputPublicUrl(job),
|
|
7980
8024
|
title: readNonEmptyString(asRecord(record.payload)?.title) ?? fallbackTitle,
|
|
7981
8025
|
fatalErrorEncountered: Boolean(publishErrorMessage),
|
|
7982
8026
|
errors: publishErrorMessage ? [{ error: publishErrorMessage }] : []
|
|
@@ -16449,8 +16493,10 @@ async function serializeJob(job) {
|
|
|
16449
16493
|
customerId: job.customerId,
|
|
16450
16494
|
templateId: job.templateId
|
|
16451
16495
|
});
|
|
16496
|
+
const expectedOutputPublicUrl = expectedHyperframesRenderOutputPublicUrl(job);
|
|
16452
16497
|
return {
|
|
16453
16498
|
job_id: job.id,
|
|
16499
|
+
customer_id: job.customerId,
|
|
16454
16500
|
template_id: job.templateId,
|
|
16455
16501
|
operation_name: job.operationName,
|
|
16456
16502
|
workflow_name: job.workflowName,
|
|
@@ -16466,6 +16512,7 @@ async function serializeJob(job) {
|
|
|
16466
16512
|
event_count: jobBilling.eventCount,
|
|
16467
16513
|
consumed_usd: jobBilling.totalChargeUsd
|
|
16468
16514
|
},
|
|
16515
|
+
expected_output_public_url: expectedOutputPublicUrl,
|
|
16469
16516
|
parent_job_id: job.parentJobId,
|
|
16470
16517
|
created_at: job.createdAt,
|
|
16471
16518
|
updated_at: job.updatedAt,
|
|
@@ -16485,6 +16532,19 @@ function serializeArtifact(artifact) {
|
|
|
16485
16532
|
created_at: artifact.createdAt
|
|
16486
16533
|
};
|
|
16487
16534
|
}
|
|
16535
|
+
function expectedHyperframesRenderOutputPublicUrl(job) {
|
|
16536
|
+
const record = asRecord(job);
|
|
16537
|
+
if (!record)
|
|
16538
|
+
return null;
|
|
16539
|
+
const templateId = readNonEmptyString(record.templateId) ?? readNonEmptyString(record.template_id);
|
|
16540
|
+
const customerId = readNonEmptyString(record.customerId) ?? readNonEmptyString(record.customer_id);
|
|
16541
|
+
const jobId = readNonEmptyString(record.id) ?? readNonEmptyString(record.job_id);
|
|
16542
|
+
if (templateId !== "primitive:hyperframes_render" || !customerId || !jobId)
|
|
16543
|
+
return null;
|
|
16544
|
+
const outputKey = readNonEmptyString(asRecord(record.payload)?.output_key) ?? "output.mp4";
|
|
16545
|
+
const storageKey = storage.primitiveJobKey(templateId, customerId, jobId, outputKey);
|
|
16546
|
+
return storage.getPublicUrl(storageKey);
|
|
16547
|
+
}
|
|
16488
16548
|
async function buildJobDebugBundle(input) {
|
|
16489
16549
|
const job = input.job;
|
|
16490
16550
|
const startTime = input.startTime ?? offsetIso(job.createdAt, -60_000);
|
|
@@ -17020,7 +17080,7 @@ async function deriveProviderHint(input) {
|
|
|
17020
17080
|
];
|
|
17021
17081
|
return useHintIfAvailable(configCandidates.find(isProviderType));
|
|
17022
17082
|
}
|
|
17023
|
-
async function
|
|
17083
|
+
async function listJobsForCustomerByTemplateId(input) {
|
|
17024
17084
|
const target = clampPageLimit(input.limit, 100) + 1;
|
|
17025
17085
|
const collected = [];
|
|
17026
17086
|
let cursor = input.cursor ?? null;
|
|
@@ -17037,7 +17097,8 @@ async function listPrimitiveJobsForCustomer(input) {
|
|
|
17037
17097
|
break;
|
|
17038
17098
|
}
|
|
17039
17099
|
for (const job of batch) {
|
|
17040
|
-
if (
|
|
17100
|
+
if ((!input.templateId || job.templateId === input.templateId) &&
|
|
17101
|
+
(!input.templateIdPrefix || job.templateId.startsWith(input.templateIdPrefix))) {
|
|
17041
17102
|
collected.push(job);
|
|
17042
17103
|
if (collected.length >= target) {
|
|
17043
17104
|
break;
|
|
@@ -17058,6 +17119,16 @@ async function listPrimitiveJobsForCustomer(input) {
|
|
|
17058
17119
|
}
|
|
17059
17120
|
return collected;
|
|
17060
17121
|
}
|
|
17122
|
+
async function getJobForCustomerByTemplateId(input) {
|
|
17123
|
+
const job = await jobs.getJobAsync(input.jobId);
|
|
17124
|
+
if (!job || job.customerId !== input.customerId) {
|
|
17125
|
+
return null;
|
|
17126
|
+
}
|
|
17127
|
+
if (input.templateId && job.templateId !== input.templateId) {
|
|
17128
|
+
return null;
|
|
17129
|
+
}
|
|
17130
|
+
return job;
|
|
17131
|
+
}
|
|
17061
17132
|
async function createPrimitiveJob(c, input) {
|
|
17062
17133
|
const customer = requireCustomer(c);
|
|
17063
17134
|
const primitive = primitiveRegistry.get(input.primitiveId);
|
|
@@ -17145,6 +17216,90 @@ async function createPrimitiveJob(c, input) {
|
|
|
17145
17216
|
operation_name: input.operationName
|
|
17146
17217
|
}, 202);
|
|
17147
17218
|
}
|
|
17219
|
+
async function createTemplateJob(c, input) {
|
|
17220
|
+
const customer = requireCustomer(c);
|
|
17221
|
+
const template = await templateRegistry.getExecutable(input.templateId);
|
|
17222
|
+
if (!template) {
|
|
17223
|
+
return c.json({ error: "Template not found" }, 404);
|
|
17224
|
+
}
|
|
17225
|
+
const operation = template.operations[input.operationName];
|
|
17226
|
+
if (!operation) {
|
|
17227
|
+
return c.json({ error: "Template operation not found" }, 404);
|
|
17228
|
+
}
|
|
17229
|
+
let body;
|
|
17230
|
+
let payload;
|
|
17231
|
+
try {
|
|
17232
|
+
body = primitiveEnvelopeSchema.parse(await c.req.json());
|
|
17233
|
+
payload = operation.inputSchema.parse(body.payload);
|
|
17234
|
+
}
|
|
17235
|
+
catch (error) {
|
|
17236
|
+
if (error instanceof z.ZodError) {
|
|
17237
|
+
return c.json({
|
|
17238
|
+
error: "Invalid template request.",
|
|
17239
|
+
issues: error.issues
|
|
17240
|
+
}, 400);
|
|
17241
|
+
}
|
|
17242
|
+
if (isJsonBodyParseError(error)) {
|
|
17243
|
+
return c.json({
|
|
17244
|
+
error: "Invalid template request.",
|
|
17245
|
+
detail: "Request body must be valid JSON with top-level tracer and payload fields."
|
|
17246
|
+
}, 400);
|
|
17247
|
+
}
|
|
17248
|
+
throw error;
|
|
17249
|
+
}
|
|
17250
|
+
const providerPreflight = await preflightAiProviderKeys({
|
|
17251
|
+
customerId: customer.id,
|
|
17252
|
+
templateId: template.id,
|
|
17253
|
+
operationName: input.operationName,
|
|
17254
|
+
operationHint: operation.providerHint,
|
|
17255
|
+
payload
|
|
17256
|
+
});
|
|
17257
|
+
if (providerPreflight) {
|
|
17258
|
+
return c.json(providerPreflight, 412);
|
|
17259
|
+
}
|
|
17260
|
+
let job;
|
|
17261
|
+
try {
|
|
17262
|
+
await assertWalletCanQueueJobs(customer.id);
|
|
17263
|
+
job = await jobs.createRootJob({
|
|
17264
|
+
templateId: template.id,
|
|
17265
|
+
operationName: input.operationName,
|
|
17266
|
+
workflowName: operation.workflow,
|
|
17267
|
+
tracer: body.tracer,
|
|
17268
|
+
payload,
|
|
17269
|
+
webhookUrl: body.webhook_url,
|
|
17270
|
+
customer,
|
|
17271
|
+
providerHint: await deriveProviderHint({
|
|
17272
|
+
customerId: customer.id,
|
|
17273
|
+
templateId: template.id,
|
|
17274
|
+
operationName: input.operationName,
|
|
17275
|
+
operationHint: operation.providerHint,
|
|
17276
|
+
payload
|
|
17277
|
+
})
|
|
17278
|
+
});
|
|
17279
|
+
}
|
|
17280
|
+
catch (error) {
|
|
17281
|
+
if (error instanceof InsufficientWalletFundsError) {
|
|
17282
|
+
return insufficientFundsResponse(c, error);
|
|
17283
|
+
}
|
|
17284
|
+
if (error instanceof ActiveJobLimitExceededError) {
|
|
17285
|
+
return activeJobLimitExceededResponse(c, error);
|
|
17286
|
+
}
|
|
17287
|
+
throw error;
|
|
17288
|
+
}
|
|
17289
|
+
if (!config.VIDFARM_JOB_STATE_MACHINE_ARN) {
|
|
17290
|
+
void runTemplateJobInProcess(job.id).catch((error) => {
|
|
17291
|
+
console.error("local template job failed", job.id, error instanceof Error ? error.message : error);
|
|
17292
|
+
});
|
|
17293
|
+
}
|
|
17294
|
+
return c.json({
|
|
17295
|
+
job_id: job.id,
|
|
17296
|
+
tracer: job.tracer,
|
|
17297
|
+
status: job.status,
|
|
17298
|
+
template_id: template.id,
|
|
17299
|
+
template_type: "template",
|
|
17300
|
+
operation_name: input.operationName
|
|
17301
|
+
}, 202);
|
|
17302
|
+
}
|
|
17148
17303
|
function resolvePrimitiveRouteTarget(primitiveParam) {
|
|
17149
17304
|
const normalized = primitiveParam.trim();
|
|
17150
17305
|
if (!normalized) {
|
|
@@ -17185,6 +17340,12 @@ app.post(`${PRIMITIVES_PREFIX}/:primitiveKind/operations/:operationName`, async
|
|
|
17185
17340
|
operationName: c.req.param("operationName")
|
|
17186
17341
|
});
|
|
17187
17342
|
});
|
|
17343
|
+
app.post(`${TEMPLATES_PREFIX}/:templateId/operations/:operationName`, async (c) => {
|
|
17344
|
+
return createTemplateJob(c, {
|
|
17345
|
+
templateId: c.req.param("templateId"),
|
|
17346
|
+
operationName: c.req.param("operationName")
|
|
17347
|
+
});
|
|
17348
|
+
});
|
|
17188
17349
|
app.get(`${PRIMITIVES_PREFIX}/jobs`, async (c) => {
|
|
17189
17350
|
const customer = requireCustomer(c);
|
|
17190
17351
|
const query = listJobsQuerySchema.parse({
|
|
@@ -17195,8 +17356,9 @@ app.get(`${PRIMITIVES_PREFIX}/jobs`, async (c) => {
|
|
|
17195
17356
|
limit: c.req.query("limit")
|
|
17196
17357
|
});
|
|
17197
17358
|
const limit = clampPageLimit(query.limit, 100);
|
|
17198
|
-
const listedJobs = await
|
|
17359
|
+
const listedJobs = await listJobsForCustomerByTemplateId({
|
|
17199
17360
|
customerId: customer.id,
|
|
17361
|
+
templateIdPrefix: "primitive:",
|
|
17200
17362
|
tracer: query.tracer,
|
|
17201
17363
|
startTime: query.start_time,
|
|
17202
17364
|
endTime: query.end_time,
|
|
@@ -17206,9 +17368,40 @@ app.get(`${PRIMITIVES_PREFIX}/jobs`, async (c) => {
|
|
|
17206
17368
|
const page = paginateDescendingByCreatedAt(listedJobs, limit);
|
|
17207
17369
|
return c.json({ primitive_jobs: await Promise.all(page.items.map(serializePrimitiveJob)), next_cursor: page.nextCursor });
|
|
17208
17370
|
});
|
|
17371
|
+
app.get(`${TEMPLATES_PREFIX}/:templateId/jobs`, async (c) => {
|
|
17372
|
+
const customer = requireCustomer(c);
|
|
17373
|
+
const template = await templateRegistry.getExecutable(c.req.param("templateId"));
|
|
17374
|
+
if (!template) {
|
|
17375
|
+
return c.json({ error: "Template not found" }, 404);
|
|
17376
|
+
}
|
|
17377
|
+
const query = listJobsQuerySchema.parse({
|
|
17378
|
+
tracer: c.req.query("tracer"),
|
|
17379
|
+
start_time: c.req.query("start_time"),
|
|
17380
|
+
end_time: c.req.query("end_time"),
|
|
17381
|
+
cursor: c.req.query("cursor"),
|
|
17382
|
+
limit: c.req.query("limit")
|
|
17383
|
+
});
|
|
17384
|
+
const limit = clampPageLimit(query.limit, 100);
|
|
17385
|
+
const listedJobs = await listJobsForCustomerByTemplateId({
|
|
17386
|
+
customerId: customer.id,
|
|
17387
|
+
templateId: template.id,
|
|
17388
|
+
tracer: query.tracer,
|
|
17389
|
+
startTime: query.start_time,
|
|
17390
|
+
endTime: query.end_time,
|
|
17391
|
+
limit,
|
|
17392
|
+
cursor: parseCreatedAtIdCursor(query.cursor)
|
|
17393
|
+
});
|
|
17394
|
+
const page = paginateDescendingByCreatedAt(listedJobs, limit);
|
|
17395
|
+
return c.json({
|
|
17396
|
+
template_id: template.id,
|
|
17397
|
+
template_type: "template",
|
|
17398
|
+
jobs: await Promise.all(page.items.map(serializeJob)),
|
|
17399
|
+
next_cursor: page.nextCursor
|
|
17400
|
+
});
|
|
17401
|
+
});
|
|
17209
17402
|
app.get(`${PRIMITIVES_PREFIX}/jobs/:jobId`, async (c) => {
|
|
17210
17403
|
const customer = requireCustomer(c);
|
|
17211
|
-
const job = await
|
|
17404
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17212
17405
|
jobId: c.req.param("jobId"),
|
|
17213
17406
|
customerId: customer.id
|
|
17214
17407
|
});
|
|
@@ -17217,9 +17410,25 @@ app.get(`${PRIMITIVES_PREFIX}/jobs/:jobId`, async (c) => {
|
|
|
17217
17410
|
}
|
|
17218
17411
|
return c.json(await serializePrimitiveJob(job));
|
|
17219
17412
|
});
|
|
17413
|
+
app.get(`${TEMPLATES_PREFIX}/:templateId/jobs/:jobId`, async (c) => {
|
|
17414
|
+
const customer = requireCustomer(c);
|
|
17415
|
+
const template = await templateRegistry.getExecutable(c.req.param("templateId"));
|
|
17416
|
+
if (!template) {
|
|
17417
|
+
return c.json({ error: "Template not found" }, 404);
|
|
17418
|
+
}
|
|
17419
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17420
|
+
jobId: c.req.param("jobId"),
|
|
17421
|
+
customerId: customer.id,
|
|
17422
|
+
templateId: template.id
|
|
17423
|
+
});
|
|
17424
|
+
if (!job) {
|
|
17425
|
+
return c.json({ error: "Template job not found" }, 404);
|
|
17426
|
+
}
|
|
17427
|
+
return c.json(await serializeJob(job));
|
|
17428
|
+
});
|
|
17220
17429
|
app.get(`${PRIMITIVES_PREFIX}/jobs/:jobId/artifacts`, async (c) => {
|
|
17221
17430
|
const customer = requireCustomer(c);
|
|
17222
|
-
const job = await
|
|
17431
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17223
17432
|
jobId: c.req.param("jobId"),
|
|
17224
17433
|
customerId: customer.id
|
|
17225
17434
|
});
|
|
@@ -17242,9 +17451,40 @@ app.get(`${PRIMITIVES_PREFIX}/jobs/:jobId/artifacts`, async (c) => {
|
|
|
17242
17451
|
next_cursor: page.nextCursor
|
|
17243
17452
|
});
|
|
17244
17453
|
});
|
|
17454
|
+
app.get(`${TEMPLATES_PREFIX}/:templateId/jobs/:jobId/artifacts`, async (c) => {
|
|
17455
|
+
const customer = requireCustomer(c);
|
|
17456
|
+
const template = await templateRegistry.getExecutable(c.req.param("templateId"));
|
|
17457
|
+
if (!template) {
|
|
17458
|
+
return c.json({ error: "Template not found" }, 404);
|
|
17459
|
+
}
|
|
17460
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17461
|
+
jobId: c.req.param("jobId"),
|
|
17462
|
+
customerId: customer.id,
|
|
17463
|
+
templateId: template.id
|
|
17464
|
+
});
|
|
17465
|
+
if (!job) {
|
|
17466
|
+
return c.json({ error: "Template job not found" }, 404);
|
|
17467
|
+
}
|
|
17468
|
+
const limit = clampPageLimit(Number(c.req.query("limit") || "100"), 100);
|
|
17469
|
+
const page = await listArtifactsForJobPage({
|
|
17470
|
+
jobId: job.id,
|
|
17471
|
+
customerId: customer.id,
|
|
17472
|
+
templateId: job.templateId,
|
|
17473
|
+
limit,
|
|
17474
|
+
cursor: parseCreatedAtIdCursor(c.req.query("cursor"))
|
|
17475
|
+
});
|
|
17476
|
+
return c.json({
|
|
17477
|
+
job_id: job.id,
|
|
17478
|
+
tracer: job.tracer,
|
|
17479
|
+
template_id: job.templateId,
|
|
17480
|
+
template_type: "template",
|
|
17481
|
+
artifacts: page.items.map(serializeArtifact),
|
|
17482
|
+
next_cursor: page.nextCursor
|
|
17483
|
+
});
|
|
17484
|
+
});
|
|
17245
17485
|
app.get(`${PRIMITIVES_PREFIX}/jobs/:jobId/logs`, async (c) => {
|
|
17246
17486
|
const customer = requireCustomer(c);
|
|
17247
|
-
const job = await
|
|
17487
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17248
17488
|
jobId: c.req.param("jobId"),
|
|
17249
17489
|
customerId: customer.id
|
|
17250
17490
|
});
|
|
@@ -17268,9 +17508,40 @@ app.get(`${PRIMITIVES_PREFIX}/jobs/:jobId/logs`, async (c) => {
|
|
|
17268
17508
|
const page = paginateDescendingByCreatedAt(logs, limit);
|
|
17269
17509
|
return c.json({ job_id: job.id, tracer: job.tracer, logs: page.items, next_cursor: page.nextCursor });
|
|
17270
17510
|
});
|
|
17511
|
+
app.get(`${TEMPLATES_PREFIX}/:templateId/jobs/:jobId/logs`, async (c) => {
|
|
17512
|
+
const customer = requireCustomer(c);
|
|
17513
|
+
const template = await templateRegistry.getExecutable(c.req.param("templateId"));
|
|
17514
|
+
if (!template) {
|
|
17515
|
+
return c.json({ error: "Template not found" }, 404);
|
|
17516
|
+
}
|
|
17517
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17518
|
+
jobId: c.req.param("jobId"),
|
|
17519
|
+
customerId: customer.id,
|
|
17520
|
+
templateId: template.id
|
|
17521
|
+
});
|
|
17522
|
+
if (!job) {
|
|
17523
|
+
return c.json({ error: "Template job not found" }, 404);
|
|
17524
|
+
}
|
|
17525
|
+
const query = listJobsQuerySchema.parse({
|
|
17526
|
+
start_time: c.req.query("start_time"),
|
|
17527
|
+
end_time: c.req.query("end_time"),
|
|
17528
|
+
cursor: c.req.query("cursor"),
|
|
17529
|
+
limit: c.req.query("limit")
|
|
17530
|
+
});
|
|
17531
|
+
const limit = clampPageLimit(query.limit, 100);
|
|
17532
|
+
const logs = await jobs.listLogs({
|
|
17533
|
+
jobId: job.id,
|
|
17534
|
+
startTime: query.start_time,
|
|
17535
|
+
endTime: query.end_time,
|
|
17536
|
+
limit: limit + 1,
|
|
17537
|
+
cursor: parseCreatedAtIdCursor(query.cursor)
|
|
17538
|
+
});
|
|
17539
|
+
const page = paginateDescendingByCreatedAt(logs, limit);
|
|
17540
|
+
return c.json({ job_id: job.id, tracer: job.tracer, logs: page.items, next_cursor: page.nextCursor });
|
|
17541
|
+
});
|
|
17271
17542
|
app.post(`${PRIMITIVES_PREFIX}/jobs/:jobId/cancel`, async (c) => {
|
|
17272
17543
|
const customer = requireCustomer(c);
|
|
17273
|
-
const job = await
|
|
17544
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17274
17545
|
jobId: c.req.param("jobId"),
|
|
17275
17546
|
customerId: customer.id
|
|
17276
17547
|
});
|
|
@@ -17280,6 +17551,23 @@ app.post(`${PRIMITIVES_PREFIX}/jobs/:jobId/cancel`, async (c) => {
|
|
|
17280
17551
|
await jobs.cancelJobAsync(job.id);
|
|
17281
17552
|
return c.json({ ok: true, job_id: job.id, status: "cancelled" });
|
|
17282
17553
|
});
|
|
17554
|
+
app.post(`${TEMPLATES_PREFIX}/:templateId/jobs/:jobId/cancel`, async (c) => {
|
|
17555
|
+
const customer = requireCustomer(c);
|
|
17556
|
+
const template = await templateRegistry.getExecutable(c.req.param("templateId"));
|
|
17557
|
+
if (!template) {
|
|
17558
|
+
return c.json({ error: "Template not found" }, 404);
|
|
17559
|
+
}
|
|
17560
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17561
|
+
jobId: c.req.param("jobId"),
|
|
17562
|
+
customerId: customer.id,
|
|
17563
|
+
templateId: template.id
|
|
17564
|
+
});
|
|
17565
|
+
if (!job) {
|
|
17566
|
+
return c.json({ error: "Template job not found" }, 404);
|
|
17567
|
+
}
|
|
17568
|
+
await jobs.cancelJobAsync(job.id);
|
|
17569
|
+
return c.json({ ok: true, job_id: job.id, status: "cancelled" });
|
|
17570
|
+
});
|
|
17283
17571
|
app.get(`${PRIMITIVES_PREFIX}/:primitiveKind/jobs`, async (c) => {
|
|
17284
17572
|
const customer = requireCustomer(c);
|
|
17285
17573
|
const primitive = resolvePrimitiveRouteTarget(c.req.param("primitiveKind"));
|
|
@@ -17294,9 +17582,9 @@ app.get(`${PRIMITIVES_PREFIX}/:primitiveKind/jobs`, async (c) => {
|
|
|
17294
17582
|
limit: c.req.query("limit")
|
|
17295
17583
|
});
|
|
17296
17584
|
const limit = clampPageLimit(query.limit, 100);
|
|
17297
|
-
const listedJobs = await
|
|
17585
|
+
const listedJobs = await listJobsForCustomerByTemplateId({
|
|
17298
17586
|
customerId: customer.id,
|
|
17299
|
-
|
|
17587
|
+
templateId: primitive.id,
|
|
17300
17588
|
tracer: query.tracer,
|
|
17301
17589
|
startTime: query.start_time,
|
|
17302
17590
|
endTime: query.end_time,
|
|
@@ -17317,10 +17605,10 @@ app.get(`${PRIMITIVES_PREFIX}/:primitiveKind/jobs/:jobId`, async (c) => {
|
|
|
17317
17605
|
if (!primitive) {
|
|
17318
17606
|
return c.json({ error: "Primitive not found" }, 404);
|
|
17319
17607
|
}
|
|
17320
|
-
const job = await
|
|
17608
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17321
17609
|
jobId: c.req.param("jobId"),
|
|
17322
17610
|
customerId: customer.id,
|
|
17323
|
-
|
|
17611
|
+
templateId: primitive.id
|
|
17324
17612
|
});
|
|
17325
17613
|
if (!job) {
|
|
17326
17614
|
return c.json({ error: "Primitive job not found" }, 404);
|
|
@@ -17333,10 +17621,10 @@ app.get(`${PRIMITIVES_PREFIX}/:primitiveKind/jobs/:jobId/artifacts`, async (c) =
|
|
|
17333
17621
|
if (!primitive) {
|
|
17334
17622
|
return c.json({ error: "Primitive not found" }, 404);
|
|
17335
17623
|
}
|
|
17336
|
-
const job = await
|
|
17624
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17337
17625
|
jobId: c.req.param("jobId"),
|
|
17338
17626
|
customerId: customer.id,
|
|
17339
|
-
|
|
17627
|
+
templateId: primitive.id
|
|
17340
17628
|
});
|
|
17341
17629
|
if (!job) {
|
|
17342
17630
|
return c.json({ error: "Primitive job not found" }, 404);
|
|
@@ -17364,10 +17652,10 @@ app.get(`${PRIMITIVES_PREFIX}/:primitiveKind/jobs/:jobId/logs`, async (c) => {
|
|
|
17364
17652
|
if (!primitive) {
|
|
17365
17653
|
return c.json({ error: "Primitive not found" }, 404);
|
|
17366
17654
|
}
|
|
17367
|
-
const job = await
|
|
17655
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17368
17656
|
jobId: c.req.param("jobId"),
|
|
17369
17657
|
customerId: customer.id,
|
|
17370
|
-
|
|
17658
|
+
templateId: primitive.id
|
|
17371
17659
|
});
|
|
17372
17660
|
if (!job) {
|
|
17373
17661
|
return c.json({ error: "Primitive job not found" }, 404);
|
|
@@ -17402,10 +17690,10 @@ app.post(`${PRIMITIVES_PREFIX}/:primitiveKind/jobs/:jobId/cancel`, async (c) =>
|
|
|
17402
17690
|
if (!primitive) {
|
|
17403
17691
|
return c.json({ error: "Primitive not found" }, 404);
|
|
17404
17692
|
}
|
|
17405
|
-
const job = await
|
|
17693
|
+
const job = await getJobForCustomerByTemplateId({
|
|
17406
17694
|
jobId: c.req.param("jobId"),
|
|
17407
17695
|
customerId: customer.id,
|
|
17408
|
-
|
|
17696
|
+
templateId: primitive.id
|
|
17409
17697
|
});
|
|
17410
17698
|
if (!job) {
|
|
17411
17699
|
return c.json({ error: "Primitive job not found" }, 404);
|