@ancplua/qyl-api-schema 4.0.0 → 5.0.0

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.
@@ -0,0 +1,537 @@
1
+ import "../common/types.tsp";
2
+
3
+ using Qyl.Api.Contracts.Common;
4
+
5
+ namespace Qyl.Api.Contracts.Workflow;
6
+
7
+ @doc("Stable identifier of one observed Codex workflow run.")
8
+ @minLength(1)
9
+ @maxLength(128)
10
+ scalar WorkflowRunId extends string;
11
+
12
+ @doc("Stable identifier of one workflow attempt.")
13
+ @minLength(1)
14
+ @maxLength(128)
15
+ scalar WorkflowAttemptId extends string;
16
+
17
+ @doc("Stable identifier of one agent within a workflow run.")
18
+ @minLength(1)
19
+ @maxLength(128)
20
+ scalar WorkflowAgentId extends string;
21
+
22
+ @doc("Stable identifier of one tool call within a workflow run.")
23
+ @minLength(1)
24
+ @maxLength(128)
25
+ scalar WorkflowToolCallId extends string;
26
+
27
+ @doc("Stable identifier of one immutable journal event.")
28
+ @minLength(1)
29
+ @maxLength(160)
30
+ scalar WorkflowEventId extends string;
31
+
32
+ @doc("Stable identifier of one run-level control command.")
33
+ @minLength(1)
34
+ @maxLength(128)
35
+ scalar WorkflowCommandId extends string;
36
+
37
+ @doc("Stable identifier of one graph node.")
38
+ @minLength(1)
39
+ @maxLength(192)
40
+ scalar WorkflowNodeId extends string;
41
+
42
+ @doc("Content-addressed reference to a captured workflow payload.")
43
+ @pattern("^sha256:[a-f0-9]{64}$")
44
+ @minLength(71)
45
+ @maxLength(71)
46
+ scalar WorkflowContentRef extends string;
47
+
48
+ @doc("Unsigned source or collector journal sequence encoded without JavaScript precision loss.")
49
+ @minValue(0)
50
+ @encode(string)
51
+ scalar WorkflowSequence extends uint64;
52
+
53
+ @doc("Current lifecycle of a workflow run.")
54
+ enum WorkflowRunStatus {
55
+ active: "active",
56
+ completed: "completed",
57
+ failed: "failed",
58
+ interrupted: "interrupted",
59
+ }
60
+
61
+ @doc("Current lifecycle of one workflow attempt.")
62
+ enum WorkflowAttemptStatus {
63
+ pending: "pending",
64
+ running: "running",
65
+ succeeded: "succeeded",
66
+ failed: "failed",
67
+ interrupted: "interrupted",
68
+ }
69
+
70
+ @doc("Current lifecycle of an observed workflow agent.")
71
+ enum WorkflowAgentStatus {
72
+ pending: "pending",
73
+ running: "running",
74
+ waiting: "waiting",
75
+ succeeded: "succeeded",
76
+ failed: "failed",
77
+ interrupted: "interrupted",
78
+ }
79
+
80
+ @doc("Current lifecycle of an observed tool call.")
81
+ enum WorkflowToolCallStatus {
82
+ requested: "requested",
83
+ running: "running",
84
+ succeeded: "succeeded",
85
+ failed: "failed",
86
+ rejected: "rejected",
87
+ }
88
+
89
+ @doc("Kinds of execution node in the deterministic workflow graph.")
90
+ enum WorkflowNodeKind {
91
+ run: "run",
92
+ attempt: "attempt",
93
+ turn: "turn",
94
+ agent: "agent",
95
+ toolCall: "tool_call",
96
+ message: "message",
97
+ wait: "wait",
98
+ gate: "gate",
99
+ resource: "resource",
100
+ }
101
+
102
+ @doc("Semantic relationship represented by a workflow graph edge.")
103
+ enum WorkflowEdgeKind {
104
+ data: "data",
105
+ control: "control",
106
+ conflict: "conflict",
107
+ resource: "resource",
108
+ gate: "gate",
109
+ temporal: "temporal",
110
+ }
111
+
112
+ @doc("Immutable journal event kinds accepted from a Codex observer.")
113
+ enum WorkflowJournalEventKind {
114
+ runCreated: "run_created",
115
+ runCompleted: "run_completed",
116
+ threadStarted: "thread_started",
117
+ threadResumed: "thread_resumed",
118
+ turnStarted: "turn_started",
119
+ turnCompleted: "turn_completed",
120
+ turnInterrupted: "turn_interrupted",
121
+ attemptStarted: "attempt_started",
122
+ attemptCompleted: "attempt_completed",
123
+ agentSpawned: "agent_spawned",
124
+ agentStarted: "agent_started",
125
+ agentCompleted: "agent_completed",
126
+ messageSent: "message_sent",
127
+ messageReceived: "message_received",
128
+ waitStarted: "wait_started",
129
+ waitCompleted: "wait_completed",
130
+ joined: "joined",
131
+ itemStarted: "item_started",
132
+ itemCompleted: "item_completed",
133
+ toolStarted: "tool_started",
134
+ toolCompleted: "tool_completed",
135
+ approvalRequested: "approval_requested",
136
+ approvalResolved: "approval_resolved",
137
+ contentCaptured: "content_captured",
138
+ fileWritten: "file_written",
139
+ controlRequested: "control_requested",
140
+ controlAccepted: "control_accepted",
141
+ controlApplied: "control_applied",
142
+ controlRejected: "control_rejected",
143
+ controlFailed: "control_failed",
144
+ }
145
+
146
+ @doc("Control operation supported by the Codex app-server boundary.")
147
+ enum WorkflowControlAction {
148
+ steer: "steer",
149
+ interrupt: "interrupt",
150
+ resume: "resume",
151
+ }
152
+
153
+ @doc("Durable lifecycle of a workflow control command.")
154
+ enum WorkflowControlStatus {
155
+ requested: "requested",
156
+ accepted: "accepted",
157
+ applied: "applied",
158
+ rejected: "rejected",
159
+ failed: "failed",
160
+ }
161
+
162
+ @doc("Encoding used when lazily returning captured workflow content.")
163
+ enum WorkflowContentEncoding {
164
+ utf8: "utf8",
165
+ base64: "base64",
166
+ }
167
+
168
+ @doc("One immutable workflow run.")
169
+ model WorkflowRun {
170
+ @encodedName("application/json", "run_id")
171
+ runId: WorkflowRunId;
172
+
173
+ @encodedName("application/json", "thread_id")
174
+ threadId?: string;
175
+
176
+ title?: string;
177
+ status: WorkflowRunStatus;
178
+
179
+ @encodedName("application/json", "started_at")
180
+ startedAt: utcDateTime;
181
+
182
+ @encodedName("application/json", "ended_at")
183
+ endedAt?: utcDateTime;
184
+
185
+ @encodedName("application/json", "latest_journal_sequence")
186
+ latestJournalSequence: WorkflowSequence;
187
+
188
+ @encodedName("application/json", "active_attempt_id")
189
+ activeAttemptId?: WorkflowAttemptId;
190
+
191
+ metadata?: Record<unknown>;
192
+ }
193
+
194
+ @doc("Request to create an observed workflow run before appending journal events.")
195
+ model WorkflowRunCreateRequest {
196
+ @encodedName("application/json", "run_id")
197
+ runId: WorkflowRunId;
198
+
199
+ @encodedName("application/json", "thread_id")
200
+ threadId?: string;
201
+
202
+ title?: string;
203
+
204
+ @encodedName("application/json", "started_at")
205
+ startedAt: utcDateTime;
206
+
207
+ metadata?: Record<unknown>;
208
+ }
209
+
210
+ @doc("Cursor page of workflow runs.")
211
+ model WorkflowRunPage {
212
+ items: WorkflowRun[];
213
+
214
+ @encodedName("application/json", "next_cursor")
215
+ nextCursor?: string;
216
+
217
+ @encodedName("application/json", "has_more")
218
+ hasMore: boolean;
219
+ }
220
+
221
+ @doc("One captured payload supplied with an append batch.")
222
+ model WorkflowContentChunk {
223
+ @encodedName("application/json", "content_ref")
224
+ contentRef: WorkflowContentRef;
225
+
226
+ @encodedName("application/json", "content_type")
227
+ contentType: ContentType;
228
+
229
+ encoding: WorkflowContentEncoding;
230
+
231
+ @doc("UTF-8 text or base64 bytes, according to encoding.")
232
+ @maxLength(1398104)
233
+ content: string;
234
+ }
235
+
236
+ @doc("One source-ordered immutable journal event awaiting collector sequence assignment.")
237
+ model WorkflowEventAppend {
238
+ @encodedName("application/json", "event_id")
239
+ eventId: WorkflowEventId;
240
+
241
+ @encodedName("application/json", "source_sequence")
242
+ sourceSequence: WorkflowSequence;
243
+
244
+ timestamp: utcDateTime;
245
+ kind: WorkflowJournalEventKind;
246
+
247
+ @encodedName("application/json", "thread_id")
248
+ threadId?: string;
249
+
250
+ @encodedName("application/json", "turn_id")
251
+ turnId?: string;
252
+
253
+ @encodedName("application/json", "attempt_id")
254
+ attemptId?: WorkflowAttemptId;
255
+
256
+ @encodedName("application/json", "agent_id")
257
+ agentId?: WorkflowAgentId;
258
+
259
+ @encodedName("application/json", "parent_agent_id")
260
+ parentAgentId?: WorkflowAgentId;
261
+
262
+ @encodedName("application/json", "receiver_agent_id")
263
+ receiverAgentId?: WorkflowAgentId;
264
+
265
+ @encodedName("application/json", "tool_call_id")
266
+ toolCallId?: WorkflowToolCallId;
267
+
268
+ @encodedName("application/json", "content_refs")
269
+ @maxItems(64)
270
+ contentRefs?: WorkflowContentRef[];
271
+
272
+ data?: Record<unknown>;
273
+ }
274
+
275
+ @doc("Idempotent append batch from one observer client.")
276
+ model WorkflowEventBatchAppendRequest {
277
+ @encodedName("application/json", "client_id")
278
+ @minLength(1)
279
+ @maxLength(128)
280
+ clientId: string;
281
+
282
+ @minItems(1)
283
+ @maxItems(500)
284
+ events: WorkflowEventAppend[];
285
+
286
+ @maxItems(500)
287
+ content?: WorkflowContentChunk[];
288
+ }
289
+
290
+ @doc("Collector acknowledgement for an idempotent workflow-event append.")
291
+ model WorkflowEventBatchAppendResponse {
292
+ @encodedName("application/json", "accepted_count")
293
+ @minValue(0)
294
+ acceptedCount: int32;
295
+
296
+ @encodedName("application/json", "duplicate_count")
297
+ @minValue(0)
298
+ duplicateCount: int32;
299
+
300
+ @encodedName("application/json", "acknowledged_source_sequence")
301
+ acknowledgedSourceSequence: WorkflowSequence;
302
+
303
+ @encodedName("application/json", "first_journal_sequence")
304
+ firstJournalSequence?: WorkflowSequence;
305
+
306
+ @encodedName("application/json", "last_journal_sequence")
307
+ lastJournalSequence?: WorkflowSequence;
308
+ }
309
+
310
+ @doc("One immutable event after collector journal sequence assignment.")
311
+ model WorkflowJournalEvent extends WorkflowEventAppend {
312
+ @encodedName("application/json", "run_id")
313
+ runId: WorkflowRunId;
314
+
315
+ @encodedName("application/json", "client_id")
316
+ clientId: string;
317
+
318
+ @encodedName("application/json", "journal_sequence")
319
+ journalSequence: WorkflowSequence;
320
+ }
321
+
322
+ @doc("A bounded page of workflow journal events.")
323
+ model WorkflowEventPage {
324
+ events: WorkflowJournalEvent[];
325
+
326
+ @encodedName("application/json", "next_sequence")
327
+ nextSequence: WorkflowSequence;
328
+
329
+ @encodedName("application/json", "high_water_mark")
330
+ highWaterMark: WorkflowSequence;
331
+
332
+ @encodedName("application/json", "cursor_gap")
333
+ cursorGap: boolean;
334
+ }
335
+
336
+ @doc("Recorded edge provenance directly observed from Codex.")
337
+ model RecordedWorkflowEdgeProvenance {
338
+ type: "recorded";
339
+
340
+ @encodedName("application/json", "event_ids")
341
+ @minItems(1)
342
+ eventIds: WorkflowEventId[];
343
+ }
344
+
345
+ @doc("Derived edge provenance with explicit evidence and confidence.")
346
+ model DerivedWorkflowEdgeProvenance {
347
+ type: "derived";
348
+
349
+ @encodedName("application/json", "event_ids")
350
+ @minItems(1)
351
+ eventIds: WorkflowEventId[];
352
+
353
+ evidence: string;
354
+ confidence: Ratio;
355
+ }
356
+
357
+ @doc("Provenance for one workflow graph edge.")
358
+ union WorkflowEdgeProvenance {
359
+ recorded: RecordedWorkflowEdgeProvenance,
360
+ derived: DerivedWorkflowEdgeProvenance,
361
+ }
362
+
363
+ @doc("One node in the deterministic workflow graph projection.")
364
+ model WorkflowGraphNode {
365
+ @encodedName("application/json", "node_id")
366
+ nodeId: WorkflowNodeId;
367
+
368
+ kind: WorkflowNodeKind;
369
+ label: string;
370
+ status: string;
371
+
372
+ @encodedName("application/json", "attempt_id")
373
+ attemptId?: WorkflowAttemptId;
374
+
375
+ @encodedName("application/json", "agent_id")
376
+ agentId?: WorkflowAgentId;
377
+
378
+ @encodedName("application/json", "parent_node_id")
379
+ parentNodeId?: WorkflowNodeId;
380
+
381
+ @encodedName("application/json", "started_at")
382
+ startedAt?: utcDateTime;
383
+
384
+ @encodedName("application/json", "ended_at")
385
+ endedAt?: utcDateTime;
386
+
387
+ @encodedName("application/json", "duration_ms")
388
+ durationMs?: DurationMs;
389
+
390
+ @encodedName("application/json", "content_refs")
391
+ contentRefs?: WorkflowContentRef[];
392
+
393
+ attributes?: Record<unknown>;
394
+ }
395
+
396
+ @doc("One typed edge in the deterministic workflow graph projection.")
397
+ model WorkflowGraphEdge {
398
+ @encodedName("application/json", "edge_id")
399
+ edgeId: string;
400
+
401
+ @encodedName("application/json", "source_node_id")
402
+ sourceNodeId: WorkflowNodeId;
403
+
404
+ @encodedName("application/json", "target_node_id")
405
+ targetNodeId: WorkflowNodeId;
406
+
407
+ kind: WorkflowEdgeKind;
408
+ provenance: WorkflowEdgeProvenance;
409
+ }
410
+
411
+ @doc("Work and critical-path statistics for a workflow graph.")
412
+ model WorkflowGraphStatistics {
413
+ @encodedName("application/json", "t1_ms")
414
+ t1Ms: DurationMs;
415
+
416
+ @encodedName("application/json", "t_infinity_ms")
417
+ tInfinityMs: DurationMs;
418
+
419
+ @encodedName("application/json", "wall_time_ms")
420
+ wallTimeMs: DurationMs;
421
+
422
+ @encodedName("application/json", "peak_concurrency")
423
+ @minValue(0)
424
+ peakConcurrency: int32;
425
+
426
+ @encodedName("application/json", "worker_count")
427
+ @minValue(1)
428
+ workerCount: int32;
429
+
430
+ @encodedName("application/json", "parallel_lower_bound_ms")
431
+ parallelLowerBoundMs: DurationMs;
432
+
433
+ @encodedName("application/json", "critical_path_node_ids")
434
+ criticalPathNodeIds: WorkflowNodeId[];
435
+ }
436
+
437
+ @doc("Deterministic graph projection at one journal cursor.")
438
+ model WorkflowGraphSnapshot {
439
+ run: WorkflowRun;
440
+ nodes: WorkflowGraphNode[];
441
+ edges: WorkflowGraphEdge[];
442
+ statistics: WorkflowGraphStatistics;
443
+
444
+ @encodedName("application/json", "journal_sequence")
445
+ journalSequence: WorkflowSequence;
446
+
447
+ @encodedName("application/json", "next_node_cursor")
448
+ nextNodeCursor?: string;
449
+
450
+ @encodedName("application/json", "next_edge_cursor")
451
+ nextEdgeCursor?: string;
452
+
453
+ @encodedName("application/json", "has_more_nodes")
454
+ hasMoreNodes: boolean;
455
+
456
+ @encodedName("application/json", "has_more_edges")
457
+ hasMoreEdges: boolean;
458
+
459
+ @encodedName("application/json", "total_node_count")
460
+ @minValue(0)
461
+ totalNodeCount: int32;
462
+
463
+ @encodedName("application/json", "total_edge_count")
464
+ @minValue(0)
465
+ totalEdgeCount: int32;
466
+ }
467
+
468
+ @doc("Lazily retrieved captured workflow content.")
469
+ model WorkflowContent {
470
+ @encodedName("application/json", "content_ref")
471
+ contentRef: WorkflowContentRef;
472
+
473
+ @encodedName("application/json", "content_type")
474
+ contentType: ContentType;
475
+
476
+ encoding: WorkflowContentEncoding;
477
+ content: string;
478
+
479
+ @encodedName("application/json", "size_bytes")
480
+ sizeBytes: ByteSize;
481
+ }
482
+
483
+ @doc("Request to enqueue one idempotent run-level control command.")
484
+ model WorkflowControlRequest {
485
+ action: WorkflowControlAction;
486
+
487
+ @encodedName("application/json", "idempotency_key")
488
+ @minLength(1)
489
+ @maxLength(160)
490
+ idempotencyKey: string;
491
+
492
+ @doc("Text appended by steer or resume. Omit for interrupt.")
493
+ @maxLength(32768)
494
+ input?: string;
495
+ }
496
+
497
+ @doc("Durable run-level control command.")
498
+ model WorkflowControlCommand {
499
+ @encodedName("application/json", "command_id")
500
+ commandId: WorkflowCommandId;
501
+
502
+ @encodedName("application/json", "run_id")
503
+ runId: WorkflowRunId;
504
+
505
+ action: WorkflowControlAction;
506
+ status: WorkflowControlStatus;
507
+
508
+ @encodedName("application/json", "idempotency_key")
509
+ idempotencyKey: string;
510
+
511
+ input?: string;
512
+
513
+ @encodedName("application/json", "requested_at")
514
+ requestedAt: utcDateTime;
515
+
516
+ @encodedName("application/json", "updated_at")
517
+ updatedAt: utcDateTime;
518
+
519
+ @encodedName("application/json", "command_sequence")
520
+ commandSequence: WorkflowSequence;
521
+
522
+ error?: string;
523
+ }
524
+
525
+ @doc("Page of control commands polled by the launcher-owned outbound adapter.")
526
+ model WorkflowControlCommandPage {
527
+ commands: WorkflowControlCommand[];
528
+
529
+ @encodedName("application/json", "next_sequence")
530
+ nextSequence: WorkflowSequence;
531
+ }
532
+
533
+ @doc("Adapter acknowledgement or terminal result for one control command.")
534
+ model WorkflowControlStatusUpdateRequest {
535
+ status: WorkflowControlStatus;
536
+ error?: string;
537
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ancplua/qyl-api-schema",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "TypeSpec source of truth for qyl API contracts. Emits OpenAPI, JSON Schema, Qyl.Api.Contracts DTOs, and TypeScript contract types; not an OpenTelemetry package, storage schema, or server implementation.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -53,6 +53,7 @@
53
53
  "api/routes.tsp",
54
54
  "api/runner.tsp",
55
55
  "api/streaming.tsp",
56
+ "api/workflow.tsp",
56
57
  "api/workbench.tsp",
57
58
  "common/errors.tsp",
58
59
  "common/pagination.tsp",
@@ -60,6 +61,7 @@
60
61
  "models/health.tsp",
61
62
  "models/runner.tsp",
62
63
  "models/workbench.tsp",
64
+ "models/workflow.tsp",
63
65
  "models/mcp-tools.tsp",
64
66
  "models/session.tsp",
65
67
  "otel/enums.tsp",
@@ -89,7 +91,6 @@
89
91
  "prepare": "npm run build:emitters",
90
92
  "prepack": "npm run compile",
91
93
  "compile": "npm run clean:generated && npm run build:emitters && tsp compile main.tsp && npm run emit:contract-revision && npm run build:json-schema && npm run build:ts-runtime",
92
- "watch": "tsp compile main.tsp --watch",
93
94
  "format": "tsp format **/*.tsp",
94
95
  "lint": "npm run build:emitters && tsp compile main.tsp --no-emit --warn-as-error",
95
96
  "lint:public": "npm run build:emitters && tsp compile index.tsp --no-emit --warn-as-error",