veryfront 0.1.75 → 0.1.76

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.
Files changed (63) hide show
  1. package/README.md +2 -0
  2. package/esm/cli/commands/files/command.d.ts +3 -3
  3. package/esm/deno.d.ts +5 -0
  4. package/esm/deno.js +11 -6
  5. package/esm/src/data/server-data-fetcher.d.ts.map +1 -1
  6. package/esm/src/data/server-data-fetcher.js +17 -1
  7. package/esm/src/jobs/index.d.ts +34 -0
  8. package/esm/src/jobs/index.d.ts.map +1 -0
  9. package/esm/src/jobs/index.js +33 -0
  10. package/esm/src/jobs/jobs-client.d.ts +134 -0
  11. package/esm/src/jobs/jobs-client.d.ts.map +1 -0
  12. package/esm/src/jobs/jobs-client.js +218 -0
  13. package/esm/src/jobs/schemas.d.ts +1304 -0
  14. package/esm/src/jobs/schemas.d.ts.map +1 -0
  15. package/esm/src/jobs/schemas.js +159 -0
  16. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts +4 -0
  17. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts.map +1 -1
  18. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.js +12 -6
  19. package/esm/src/proxy/handler.d.ts.map +1 -1
  20. package/esm/src/proxy/handler.js +21 -21
  21. package/esm/src/routing/api/route-executor.d.ts.map +1 -1
  22. package/esm/src/routing/api/route-executor.js +30 -3
  23. package/esm/src/security/deno-permissions.d.ts +1 -1
  24. package/esm/src/security/deno-permissions.d.ts.map +1 -1
  25. package/esm/src/security/deno-permissions.js +2 -1
  26. package/esm/src/security/sandbox/project-worker.d.ts.map +1 -1
  27. package/esm/src/security/sandbox/project-worker.js +2 -2
  28. package/esm/src/security/sandbox/worker-permissions.d.ts.map +1 -1
  29. package/esm/src/security/sandbox/worker-permissions.js +23 -20
  30. package/esm/src/security/sandbox/worker-pool.d.ts.map +1 -1
  31. package/esm/src/security/sandbox/worker-pool.js +17 -14
  32. package/esm/src/security/sandbox/worker-types.d.ts +2 -0
  33. package/esm/src/security/sandbox/worker-types.d.ts.map +1 -1
  34. package/esm/src/security/sandbox/worker-types.js +2 -0
  35. package/esm/src/server/handlers/request/internal-tasks-list.handler.d.ts +11 -0
  36. package/esm/src/server/handlers/request/internal-tasks-list.handler.d.ts.map +1 -0
  37. package/esm/src/server/handlers/request/internal-tasks-list.handler.js +72 -0
  38. package/esm/src/server/runtime-handler/index.d.ts +1 -1
  39. package/esm/src/server/runtime-handler/index.d.ts.map +1 -1
  40. package/esm/src/server/runtime-handler/index.js +3 -0
  41. package/esm/src/task/control-plane.d.ts +105 -0
  42. package/esm/src/task/control-plane.d.ts.map +1 -0
  43. package/esm/src/task/control-plane.js +52 -0
  44. package/esm/src/task/types.d.ts +6 -0
  45. package/esm/src/task/types.d.ts.map +1 -1
  46. package/package.json +5 -1
  47. package/src/deno.js +11 -6
  48. package/src/src/data/server-data-fetcher.ts +30 -2
  49. package/src/src/jobs/index.ts +85 -0
  50. package/src/src/jobs/jobs-client.ts +503 -0
  51. package/src/src/jobs/schemas.ts +202 -0
  52. package/src/src/platform/adapters/veryfront-api-client/retry-handler.ts +15 -6
  53. package/src/src/proxy/handler.ts +27 -19
  54. package/src/src/routing/api/route-executor.ts +43 -7
  55. package/src/src/security/deno-permissions.ts +2 -1
  56. package/src/src/security/sandbox/project-worker.ts +2 -2
  57. package/src/src/security/sandbox/worker-permissions.ts +22 -19
  58. package/src/src/security/sandbox/worker-pool.ts +21 -13
  59. package/src/src/security/sandbox/worker-types.ts +3 -0
  60. package/src/src/server/handlers/request/internal-tasks-list.handler.ts +103 -0
  61. package/src/src/server/runtime-handler/index.ts +3 -0
  62. package/src/src/task/control-plane.ts +76 -0
  63. package/src/src/task/types.ts +6 -0
@@ -0,0 +1,503 @@
1
+ /**
2
+ * Jobs client SDK for project-scoped background execution.
3
+ *
4
+ * Provides a stable public client for one-off jobs, cron jobs, job batches,
5
+ * and job target discovery on the Veryfront Jobs API.
6
+ */
7
+
8
+ import { getVeryfrontCloudBootstrap } from "../platform/cloud/resolver.js";
9
+ import {
10
+ requestWithRetry,
11
+ type RetryConfig,
12
+ } from "../platform/adapters/veryfront-api-client/retry-handler.js";
13
+ import { API_CLIENT_ERROR } from "../platform/adapters/veryfront-api-client/types.js";
14
+ import { z } from "zod";
15
+ import {
16
+ type CronJob,
17
+ CronJobSchema,
18
+ type CronJobStatus,
19
+ type Job,
20
+ type JobBatch,
21
+ JobBatchSchema,
22
+ type JobEventsResponse,
23
+ JobEventsResponseSchema,
24
+ type JobLogsResponse,
25
+ JobLogsResponseSchema,
26
+ JobSchema,
27
+ type JobStatus,
28
+ type JobTargetDefinition,
29
+ JobTargetDefinitionSchema,
30
+ type JobTargetDefinitionsResponse,
31
+ JobTargetDefinitionsResponseSchema,
32
+ type PaginatedCronJobsResponse,
33
+ PaginatedCronJobsResponseSchema,
34
+ type PaginatedJobsResponse,
35
+ PaginatedJobsResponseSchema,
36
+ } from "./schemas.js";
37
+
38
+ const DEFAULT_MAX_RETRIES = 3;
39
+ const DEFAULT_INITIAL_RETRY_DELAY_MS = 1_000;
40
+ const DEFAULT_MAX_RETRY_DELAY_MS = 10_000;
41
+
42
+ export interface VeryfrontJobsClientConfig {
43
+ apiUrl?: string;
44
+ authToken?: string;
45
+ projectReference?: string;
46
+ retry?: Partial<RetryConfig>;
47
+ }
48
+
49
+ export interface ProjectScopedOptions {
50
+ projectReference?: string;
51
+ }
52
+
53
+ export interface ListJobsOptions extends ProjectScopedOptions {
54
+ cursor?: string;
55
+ limit?: number;
56
+ status?: JobStatus;
57
+ cronJobId?: string;
58
+ environmentId?: string;
59
+ batchId?: string;
60
+ }
61
+
62
+ export interface ListJobEventsOptions extends ProjectScopedOptions {
63
+ cursor?: string;
64
+ limit?: number;
65
+ direction?: "forward" | "backward";
66
+ }
67
+
68
+ export interface CreateJobInput extends ProjectScopedOptions {
69
+ name: string;
70
+ target: string;
71
+ environmentId?: string;
72
+ batchId?: string;
73
+ config?: Record<string, unknown>;
74
+ timeoutSeconds?: number;
75
+ backoffLimit?: number;
76
+ }
77
+
78
+ export interface ListBatchJobsOptions extends ProjectScopedOptions {
79
+ cursor?: string;
80
+ limit?: number;
81
+ status?: JobStatus;
82
+ }
83
+
84
+ export interface CreateCronJobInput extends ProjectScopedOptions {
85
+ name: string;
86
+ target: string;
87
+ environmentId?: string;
88
+ schedule: string;
89
+ timezone?: string;
90
+ config?: Record<string, unknown>;
91
+ timeoutSeconds?: number;
92
+ backoffLimit?: number;
93
+ concurrencyPolicy?: "Allow" | "Forbid" | "Replace";
94
+ }
95
+
96
+ export interface ListCronJobsOptions extends ProjectScopedOptions {
97
+ cursor?: string;
98
+ limit?: number;
99
+ status?: CronJobStatus;
100
+ environmentId?: string;
101
+ }
102
+
103
+ export interface UpdateCronJobInput extends ProjectScopedOptions {
104
+ name?: string;
105
+ schedule?: string;
106
+ timezone?: string;
107
+ config?: Record<string, unknown>;
108
+ timeoutSeconds?: number;
109
+ backoffLimit?: number;
110
+ concurrencyPolicy?: "Allow" | "Forbid" | "Replace";
111
+ status?: "active" | "paused";
112
+ }
113
+
114
+ type NamespaceMethod<TArgs extends unknown[], TResult> = (...args: TArgs) => Promise<TResult>;
115
+
116
+ function toQueryParams(
117
+ values: Record<string, string | number | undefined>,
118
+ ): URLSearchParams {
119
+ const params = new URLSearchParams();
120
+
121
+ for (const [key, value] of Object.entries(values)) {
122
+ if (value == null) {
123
+ continue;
124
+ }
125
+ params.set(key, String(value));
126
+ }
127
+
128
+ return params;
129
+ }
130
+
131
+ function withQuery(path: string, params: URLSearchParams): string {
132
+ const query = params.toString();
133
+ return query.length > 0 ? `${path}?${query}` : path;
134
+ }
135
+
136
+ export class VeryfrontJobsClient {
137
+ private readonly retryConfig: RetryConfig;
138
+ private requestToken?: string;
139
+ private requestProjectReference?: string;
140
+
141
+ readonly cron: {
142
+ create: NamespaceMethod<[CreateCronJobInput], CronJob>;
143
+ list: NamespaceMethod<[ListCronJobsOptions?], PaginatedCronJobsResponse>;
144
+ get: NamespaceMethod<[cronJobId: string, options?: ProjectScopedOptions], CronJob>;
145
+ update: NamespaceMethod<[cronJobId: string, input: UpdateCronJobInput], CronJob>;
146
+ delete: NamespaceMethod<[cronJobId: string, options?: ProjectScopedOptions], CronJob>;
147
+ trigger: NamespaceMethod<[cronJobId: string, options?: ProjectScopedOptions], Job>;
148
+ };
149
+
150
+ readonly batches: {
151
+ get: NamespaceMethod<[batchId: string, options?: ProjectScopedOptions], JobBatch>;
152
+ listJobs: NamespaceMethod<
153
+ [batchId: string, options?: ListBatchJobsOptions],
154
+ PaginatedJobsResponse
155
+ >;
156
+ };
157
+
158
+ readonly targets: {
159
+ list: NamespaceMethod<[options?: ProjectScopedOptions], JobTargetDefinitionsResponse>;
160
+ get: NamespaceMethod<[target: string, options?: ProjectScopedOptions], JobTargetDefinition>;
161
+ };
162
+
163
+ constructor(private readonly config: VeryfrontJobsClientConfig = {}) {
164
+ this.retryConfig = {
165
+ maxRetries: config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES,
166
+ initialDelay: config.retry?.initialDelay ?? DEFAULT_INITIAL_RETRY_DELAY_MS,
167
+ maxDelay: config.retry?.maxDelay ?? DEFAULT_MAX_RETRY_DELAY_MS,
168
+ };
169
+
170
+ this.cron = {
171
+ create: (input) => this.createCronJob(input),
172
+ list: (options) => this.listCronJobs(options),
173
+ get: (cronJobId, options) => this.getCronJob(cronJobId, options),
174
+ update: (cronJobId, input) => this.updateCronJob(cronJobId, input),
175
+ delete: (cronJobId, options) => this.deleteCronJob(cronJobId, options),
176
+ trigger: (cronJobId, options) => this.triggerCronJob(cronJobId, options),
177
+ };
178
+
179
+ this.batches = {
180
+ get: (batchId, options) => this.getBatch(batchId, options),
181
+ listJobs: (batchId, options) => this.listBatchJobs(batchId, options),
182
+ };
183
+
184
+ this.targets = {
185
+ list: (options) => this.listTargets(options),
186
+ get: (target, options) => this.getTarget(target, options),
187
+ };
188
+ }
189
+
190
+ setRequestToken(token: string): void {
191
+ this.requestToken = token;
192
+ }
193
+
194
+ clearRequestToken(): void {
195
+ this.requestToken = undefined;
196
+ }
197
+
198
+ setProjectReference(projectReference: string): void {
199
+ this.requestProjectReference = projectReference;
200
+ }
201
+
202
+ getProjectReference(): string | undefined {
203
+ return this.requestProjectReference ?? this.config.projectReference;
204
+ }
205
+
206
+ clearProjectReference(): void {
207
+ this.requestProjectReference = undefined;
208
+ }
209
+
210
+ create(input: CreateJobInput): Promise<Job> {
211
+ const { projectReference, environmentId, batchId, timeoutSeconds, backoffLimit, ...rest } =
212
+ input;
213
+
214
+ return this.requestProjectJson(
215
+ projectReference,
216
+ "/jobs",
217
+ JobSchema,
218
+ {
219
+ method: "POST",
220
+ body: {
221
+ ...rest,
222
+ environment_id: environmentId,
223
+ batch_id: batchId,
224
+ timeout_seconds: timeoutSeconds,
225
+ backoff_limit: backoffLimit,
226
+ },
227
+ },
228
+ );
229
+ }
230
+
231
+ list(options: ListJobsOptions = {}): Promise<PaginatedJobsResponse> {
232
+ const { projectReference, cursor, limit, status, cronJobId, environmentId, batchId } = options;
233
+
234
+ return this.requestProjectJson(
235
+ projectReference,
236
+ withQuery(
237
+ "/jobs",
238
+ toQueryParams({
239
+ cursor,
240
+ limit,
241
+ status,
242
+ cron_job_id: cronJobId,
243
+ environment_id: environmentId,
244
+ batch_id: batchId,
245
+ }),
246
+ ),
247
+ PaginatedJobsResponseSchema,
248
+ );
249
+ }
250
+
251
+ get(jobId: string, options: ProjectScopedOptions = {}): Promise<Job> {
252
+ return this.requestProjectJson(
253
+ options.projectReference,
254
+ `/jobs/${encodeURIComponent(jobId)}`,
255
+ JobSchema,
256
+ );
257
+ }
258
+
259
+ /**
260
+ * Canonical user-visible operational output for a job.
261
+ * Prefer this over raw logs for status, progress, and per-file activity.
262
+ */
263
+ events(jobId: string, options: ListJobEventsOptions = {}): Promise<JobEventsResponse> {
264
+ const { projectReference, cursor, limit, direction } = options;
265
+
266
+ return this.requestProjectJson(
267
+ projectReference,
268
+ withQuery(
269
+ `/jobs/${encodeURIComponent(jobId)}/events`,
270
+ toQueryParams({ cursor, limit, direction }),
271
+ ),
272
+ JobEventsResponseSchema,
273
+ );
274
+ }
275
+
276
+ /**
277
+ * Raw debugging output for a job.
278
+ * This is secondary to `events()` for operational UX.
279
+ */
280
+ logs(jobId: string, options: ProjectScopedOptions = {}): Promise<JobLogsResponse> {
281
+ return this.requestProjectJson(
282
+ options.projectReference,
283
+ `/jobs/${encodeURIComponent(jobId)}/logs`,
284
+ JobLogsResponseSchema,
285
+ );
286
+ }
287
+
288
+ cancel(jobId: string, options: ProjectScopedOptions = {}): Promise<Job> {
289
+ return this.requestProjectJson(
290
+ options.projectReference,
291
+ `/jobs/${encodeURIComponent(jobId)}/cancel`,
292
+ JobSchema,
293
+ { method: "POST" },
294
+ );
295
+ }
296
+
297
+ private createCronJob(input: CreateCronJobInput): Promise<CronJob> {
298
+ const {
299
+ projectReference,
300
+ environmentId,
301
+ timeoutSeconds,
302
+ backoffLimit,
303
+ concurrencyPolicy,
304
+ ...rest
305
+ } = input;
306
+
307
+ return this.requestProjectJson(
308
+ projectReference,
309
+ "/cron-jobs",
310
+ CronJobSchema,
311
+ {
312
+ method: "POST",
313
+ body: {
314
+ ...rest,
315
+ environment_id: environmentId,
316
+ timeout_seconds: timeoutSeconds,
317
+ backoff_limit: backoffLimit,
318
+ concurrency_policy: concurrencyPolicy,
319
+ },
320
+ },
321
+ );
322
+ }
323
+
324
+ private listCronJobs(options: ListCronJobsOptions = {}): Promise<PaginatedCronJobsResponse> {
325
+ const { projectReference, cursor, limit, status, environmentId } = options;
326
+
327
+ return this.requestProjectJson(
328
+ projectReference,
329
+ withQuery(
330
+ "/cron-jobs",
331
+ toQueryParams({
332
+ cursor,
333
+ limit,
334
+ status,
335
+ environment_id: environmentId,
336
+ }),
337
+ ),
338
+ PaginatedCronJobsResponseSchema,
339
+ );
340
+ }
341
+
342
+ private getCronJob(cronJobId: string, options: ProjectScopedOptions = {}): Promise<CronJob> {
343
+ return this.requestProjectJson(
344
+ options.projectReference,
345
+ `/cron-jobs/${encodeURIComponent(cronJobId)}`,
346
+ CronJobSchema,
347
+ );
348
+ }
349
+
350
+ private updateCronJob(cronJobId: string, input: UpdateCronJobInput): Promise<CronJob> {
351
+ const {
352
+ projectReference,
353
+ timeoutSeconds,
354
+ backoffLimit,
355
+ concurrencyPolicy,
356
+ ...rest
357
+ } = input;
358
+
359
+ return this.requestProjectJson(
360
+ projectReference,
361
+ `/cron-jobs/${encodeURIComponent(cronJobId)}`,
362
+ CronJobSchema,
363
+ {
364
+ method: "PATCH",
365
+ body: {
366
+ ...rest,
367
+ timeout_seconds: timeoutSeconds,
368
+ backoff_limit: backoffLimit,
369
+ concurrency_policy: concurrencyPolicy,
370
+ },
371
+ },
372
+ );
373
+ }
374
+
375
+ private deleteCronJob(cronJobId: string, options: ProjectScopedOptions = {}): Promise<CronJob> {
376
+ return this.requestProjectJson(
377
+ options.projectReference,
378
+ `/cron-jobs/${encodeURIComponent(cronJobId)}`,
379
+ CronJobSchema,
380
+ { method: "DELETE" },
381
+ );
382
+ }
383
+
384
+ private triggerCronJob(cronJobId: string, options: ProjectScopedOptions = {}): Promise<Job> {
385
+ return this.requestProjectJson(
386
+ options.projectReference,
387
+ `/cron-jobs/${encodeURIComponent(cronJobId)}/trigger`,
388
+ JobSchema,
389
+ { method: "POST" },
390
+ );
391
+ }
392
+
393
+ private getBatch(batchId: string, options: ProjectScopedOptions = {}): Promise<JobBatch> {
394
+ return this.requestProjectJson(
395
+ options.projectReference,
396
+ `/job-batches/${encodeURIComponent(batchId)}`,
397
+ JobBatchSchema,
398
+ );
399
+ }
400
+
401
+ private listBatchJobs(
402
+ batchId: string,
403
+ options: ListBatchJobsOptions = {},
404
+ ): Promise<PaginatedJobsResponse> {
405
+ const { projectReference, cursor, limit, status } = options;
406
+
407
+ return this.requestProjectJson(
408
+ projectReference,
409
+ withQuery(
410
+ `/job-batches/${encodeURIComponent(batchId)}/jobs`,
411
+ toQueryParams({
412
+ cursor,
413
+ limit,
414
+ status,
415
+ }),
416
+ ),
417
+ PaginatedJobsResponseSchema,
418
+ );
419
+ }
420
+
421
+ private listTargets(
422
+ options: ProjectScopedOptions = {},
423
+ ): Promise<JobTargetDefinitionsResponse> {
424
+ return this.requestProjectJson(
425
+ options.projectReference,
426
+ "/job-targets",
427
+ JobTargetDefinitionsResponseSchema,
428
+ );
429
+ }
430
+
431
+ private getTarget(
432
+ target: string,
433
+ options: ProjectScopedOptions = {},
434
+ ): Promise<JobTargetDefinition> {
435
+ return this.requestProjectJson(
436
+ options.projectReference,
437
+ `/job-targets/${encodeURIComponent(target)}`,
438
+ JobTargetDefinitionSchema,
439
+ );
440
+ }
441
+
442
+ private resolveApiUrl(): string {
443
+ return this.config.apiUrl ?? getVeryfrontCloudBootstrap().apiBaseUrl;
444
+ }
445
+
446
+ private resolveAuthToken(): string {
447
+ const token = this.requestToken ?? this.config.authToken ??
448
+ getVeryfrontCloudBootstrap().apiToken;
449
+ if (token) {
450
+ return token;
451
+ }
452
+
453
+ throw API_CLIENT_ERROR.create({
454
+ detail:
455
+ "Jobs auth not configured. Set VERYFRONT_API_TOKEN, provide request-scoped Veryfront credentials, or pass authToken explicitly.",
456
+ status: 401,
457
+ });
458
+ }
459
+
460
+ private resolveProjectReference(projectReference?: string): string {
461
+ const resolved = projectReference ??
462
+ this.requestProjectReference ??
463
+ this.config.projectReference ??
464
+ getVeryfrontCloudBootstrap().projectSlug;
465
+
466
+ if (resolved) {
467
+ return resolved;
468
+ }
469
+
470
+ throw API_CLIENT_ERROR.create({
471
+ detail:
472
+ "Jobs project reference not configured. Pass projectReference explicitly, set VERYFRONT_PROJECT_SLUG, or provide request-scoped Veryfront project context.",
473
+ status: 400,
474
+ });
475
+ }
476
+
477
+ private async requestProjectJson<TSchema extends z.ZodTypeAny>(
478
+ projectReference: string | undefined,
479
+ path: string,
480
+ schema: TSchema,
481
+ options: {
482
+ method?: "GET" | "POST" | "PATCH" | "DELETE";
483
+ body?: Record<string, unknown>;
484
+ } = {},
485
+ ): Promise<z.infer<TSchema>> {
486
+ const resolvedProjectReference = this.resolveProjectReference(projectReference);
487
+ const raw = await requestWithRetry(
488
+ `${this.resolveApiUrl()}/projects/${encodeURIComponent(resolvedProjectReference)}${path}`,
489
+ this.resolveAuthToken(),
490
+ this.retryConfig,
491
+ {
492
+ method: options.method,
493
+ body: options.body == null ? undefined : JSON.stringify(options.body),
494
+ },
495
+ );
496
+
497
+ return schema.parse(raw);
498
+ }
499
+ }
500
+
501
+ export function createJobsClient(config?: VeryfrontJobsClientConfig): VeryfrontJobsClient {
502
+ return new VeryfrontJobsClient(config);
503
+ }
@@ -0,0 +1,202 @@
1
+ import { z } from "zod";
2
+
3
+ export const JobStatusSchema = z.enum([
4
+ "submitted",
5
+ "working",
6
+ "completed",
7
+ "failed",
8
+ "canceled",
9
+ ]);
10
+
11
+ export const CronJobStatusSchema = z.enum(["active", "paused", "deleting"]);
12
+
13
+ export const ReservedJobTargetFamilySchema = z.enum(["task:*", "workflow:*", "deploy:*"]);
14
+
15
+ export const PageInfoSchema = z.object({
16
+ self: z.string().nullable(),
17
+ first: z.literal(null),
18
+ next: z.string().nullable(),
19
+ prev: z.string().nullable(),
20
+ });
21
+
22
+ const JsonObjectSchema = z.record(z.unknown());
23
+
24
+ export const KnowledgeIngestFileResultSchema = z.object({
25
+ source: z.string(),
26
+ localSourcePath: z.string(),
27
+ outputPath: z.string(),
28
+ remotePath: z.string(),
29
+ slug: z.string(),
30
+ sourceType: z.string(),
31
+ summary: z.string(),
32
+ stats: JsonObjectSchema,
33
+ warnings: z.array(z.string()),
34
+ });
35
+
36
+ export const JobResultSchema = z
37
+ .discriminatedUnion("kind", [
38
+ z.object({
39
+ kind: z.literal("knowledge_ingest"),
40
+ files: z.array(KnowledgeIngestFileResultSchema),
41
+ }),
42
+ z.object({
43
+ kind: z.literal("artifacts"),
44
+ artifacts: z.array(z.unknown()),
45
+ }),
46
+ ])
47
+ .nullable();
48
+
49
+ export const JobSchema = z.object({
50
+ id: z.string().uuid(),
51
+ project_id: z.string().uuid(),
52
+ environment_id: z.string().uuid().nullable(),
53
+ cron_job_id: z.string().uuid().nullable(),
54
+ batch_id: z.string().uuid().nullable(),
55
+ name: z.string(),
56
+ status: JobStatusSchema,
57
+ target: z.string(),
58
+ config: JsonObjectSchema,
59
+ context_id: z.string().uuid().nullable(),
60
+ timeout_seconds: z.number(),
61
+ backoff_limit: z.number(),
62
+ exit_code: z.number().nullable(),
63
+ failed_reason: z.string().nullable(),
64
+ failure_detail: z.string().nullable(),
65
+ result: JobResultSchema,
66
+ started_at: z.string().nullable(),
67
+ completed_at: z.string().nullable(),
68
+ created_by: z.string().uuid().nullable(),
69
+ created_at: z.string(),
70
+ updated_at: z.string(),
71
+ });
72
+
73
+ export const PaginatedJobsResponseSchema = z.object({
74
+ data: z.array(JobSchema),
75
+ page_info: PageInfoSchema,
76
+ });
77
+
78
+ export const JobEventSchema = z.object({
79
+ timestamp: z.string(),
80
+ level: z.string(),
81
+ message: z.string(),
82
+ service: z.string(),
83
+ trace_id: z.string().optional(),
84
+ request_id: z.string().optional(),
85
+ metadata: z.record(z.string()).optional(),
86
+ });
87
+
88
+ export const JobEventsResponseSchema = z.object({
89
+ entries: z.array(JobEventSchema),
90
+ next_cursor: z.string().nullable(),
91
+ stats: z.object({
92
+ bytes_processed: z.number(),
93
+ lines_processed: z.number(),
94
+ query_time_ms: z.number(),
95
+ }),
96
+ });
97
+
98
+ export const JobLogsResponseSchema = z.object({
99
+ logs: z.string().nullable(),
100
+ });
101
+
102
+ export const KnowledgeIngestBatchSourceSchema = z.object({
103
+ label: z.string(),
104
+ path: z.string().nullable(),
105
+ upload_id: z.string().uuid().nullable(),
106
+ remote_path: z.string().nullable(),
107
+ warning_count: z.number().int().nonnegative(),
108
+ });
109
+
110
+ export const JobBatchStatusCountsSchema = z.object({
111
+ submitted: z.number().int().nonnegative(),
112
+ working: z.number().int().nonnegative(),
113
+ completed: z.number().int().nonnegative(),
114
+ failed: z.number().int().nonnegative(),
115
+ canceled: z.number().int().nonnegative(),
116
+ });
117
+
118
+ export const JobBatchResultSchema = z
119
+ .discriminatedUnion("kind", [
120
+ z.object({
121
+ kind: z.literal("knowledge_ingest"),
122
+ total_count: z.number().int().nonnegative(),
123
+ completed_count: z.number().int().nonnegative(),
124
+ processing: z.array(KnowledgeIngestBatchSourceSchema),
125
+ completed: z.array(KnowledgeIngestBatchSourceSchema),
126
+ remaining: z.array(KnowledgeIngestBatchSourceSchema),
127
+ remaining_label: z.enum(["Remaining Files", "Not Ingested Files"]),
128
+ }),
129
+ ])
130
+ .nullable();
131
+
132
+ export const JobBatchSchema = z.object({
133
+ id: z.string().uuid(),
134
+ project_id: z.string().uuid(),
135
+ target: z.string().nullable(),
136
+ job_count: z.number().int().nonnegative(),
137
+ status_counts: JobBatchStatusCountsSchema,
138
+ created_at: z.string(),
139
+ updated_at: z.string(),
140
+ result: JobBatchResultSchema,
141
+ });
142
+
143
+ export const JobTargetDefinitionSchema = z.object({
144
+ target: z.string(),
145
+ family: z.string(),
146
+ description: z.string(),
147
+ input_schema: JsonObjectSchema,
148
+ output_schema: JsonObjectSchema.nullable(),
149
+ });
150
+
151
+ export const JobTargetDefinitionsResponseSchema = z.object({
152
+ reserved_families: z.array(ReservedJobTargetFamilySchema),
153
+ data: z.array(JobTargetDefinitionSchema),
154
+ });
155
+
156
+ export const CronJobSchema = z.object({
157
+ id: z.string().uuid(),
158
+ project_id: z.string().uuid(),
159
+ environment_id: z.string().uuid().nullable(),
160
+ name: z.string(),
161
+ status: CronJobStatusSchema,
162
+ target: z.string(),
163
+ schedule: z.string(),
164
+ timezone: z.string(),
165
+ config: JsonObjectSchema,
166
+ timeout_seconds: z.number(),
167
+ backoff_limit: z.number(),
168
+ concurrency_policy: z.string(),
169
+ last_scheduled_at: z.string().nullable(),
170
+ last_successful_at: z.string().nullable(),
171
+ created_by: z.string().uuid().nullable(),
172
+ created_at: z.string(),
173
+ updated_at: z.string(),
174
+ });
175
+
176
+ export const PaginatedCronJobsResponseSchema = z.object({
177
+ data: z.array(CronJobSchema),
178
+ page_info: PageInfoSchema,
179
+ });
180
+
181
+ export type JobStatus = z.infer<typeof JobStatusSchema>;
182
+ export type CronJobStatus = z.infer<typeof CronJobStatusSchema>;
183
+ export type ReservedJobTargetFamily = z.infer<typeof ReservedJobTargetFamilySchema>;
184
+
185
+ export type KnowledgeIngestFileResult = z.infer<typeof KnowledgeIngestFileResultSchema>;
186
+ export type JobResult = z.infer<typeof JobResultSchema>;
187
+ export type Job = z.infer<typeof JobSchema>;
188
+ export type PaginatedJobsResponse = z.infer<typeof PaginatedJobsResponseSchema>;
189
+ export type JobEvent = z.infer<typeof JobEventSchema>;
190
+ export type JobEventsResponse = z.infer<typeof JobEventsResponseSchema>;
191
+ export type JobLogsResponse = z.infer<typeof JobLogsResponseSchema>;
192
+
193
+ export type KnowledgeIngestBatchSource = z.infer<typeof KnowledgeIngestBatchSourceSchema>;
194
+ export type JobBatchStatusCounts = z.infer<typeof JobBatchStatusCountsSchema>;
195
+ export type JobBatchResult = z.infer<typeof JobBatchResultSchema>;
196
+ export type JobBatch = z.infer<typeof JobBatchSchema>;
197
+
198
+ export type JobTargetDefinition = z.infer<typeof JobTargetDefinitionSchema>;
199
+ export type JobTargetDefinitionsResponse = z.infer<typeof JobTargetDefinitionsResponseSchema>;
200
+
201
+ export type CronJob = z.infer<typeof CronJobSchema>;
202
+ export type PaginatedCronJobsResponse = z.infer<typeof PaginatedCronJobsResponseSchema>;