@frontera-sdk/workflow 1.50.62-next.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.
- package/LICENSE +202 -0
- package/README.md +150 -0
- package/package.json +48 -0
- package/src/definition.ts +297 -0
- package/src/types.ts +483 -0
- package/src/workflow-client.ts +355 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import type { InputsSchema } from '@frontera-sdk/functions'
|
|
2
|
+
|
|
3
|
+
export type WorkflowRunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'canceled'
|
|
4
|
+
export type WorkflowNodeStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'canceled'
|
|
5
|
+
|
|
6
|
+
export const TERMINAL_RUN_STATUSES: ReadonlySet<WorkflowRunStatus> = new Set<WorkflowRunStatus>([
|
|
7
|
+
'succeeded',
|
|
8
|
+
'failed',
|
|
9
|
+
'canceled',
|
|
10
|
+
])
|
|
11
|
+
|
|
12
|
+
export function isTerminalRunStatus(status: string): boolean {
|
|
13
|
+
return TERMINAL_RUN_STATUSES.has(status as WorkflowRunStatus)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** A row of `GET /v1/workflows`. */
|
|
17
|
+
export interface WorkflowSummary {
|
|
18
|
+
id: string
|
|
19
|
+
slug: string
|
|
20
|
+
enabled: boolean
|
|
21
|
+
description: string | null
|
|
22
|
+
liveVersion: number | null
|
|
23
|
+
latestDraftNumber: number | null
|
|
24
|
+
versionCount: number
|
|
25
|
+
runCount: number
|
|
26
|
+
lastRunAt: string | null
|
|
27
|
+
lastRunStatus: WorkflowRunStatus | null
|
|
28
|
+
triggerKinds: string[]
|
|
29
|
+
cron: string | null
|
|
30
|
+
subjectApiName: string | null
|
|
31
|
+
subjectLabel: string | null
|
|
32
|
+
/** One per webhook trigger. Absent from a service that predates webhooks. */
|
|
33
|
+
webhooks?: WorkflowWebhook[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface WorkflowWebhook {
|
|
37
|
+
methods: string[]
|
|
38
|
+
path: string
|
|
39
|
+
auth: string
|
|
40
|
+
respond: string
|
|
41
|
+
url: string
|
|
42
|
+
testUrl: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The whole workflow row, which the two create routes answer with. */
|
|
46
|
+
export interface Workflow {
|
|
47
|
+
id: string
|
|
48
|
+
orgId: string
|
|
49
|
+
workspaceId: string
|
|
50
|
+
slug: string
|
|
51
|
+
displayName: string | null
|
|
52
|
+
subjectObjectTypeId: string | null
|
|
53
|
+
enabled: boolean
|
|
54
|
+
liveVersionId: string | null
|
|
55
|
+
testHookVersionId: string | null
|
|
56
|
+
testHookUntil: string | null
|
|
57
|
+
createdBy: string
|
|
58
|
+
createdAt: string
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface CreateWorkflowInput {
|
|
62
|
+
/** Lowercase, digits and hyphens; unique in the workspace. */
|
|
63
|
+
slug: string
|
|
64
|
+
/** A Blueprint object type id. Every run is then about one of its objects. */
|
|
65
|
+
subjectObjectTypeId?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** `createDraft`: the workflow and the empty draft made with it, in one write. */
|
|
69
|
+
export interface WorkflowDraft {
|
|
70
|
+
workflow: Workflow
|
|
71
|
+
version: { id: string; number: number; status: WorkflowVersionStatus }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** What `rename` answers with. The slug does not move with the name. */
|
|
75
|
+
export interface RenameResult {
|
|
76
|
+
id: string
|
|
77
|
+
slug: string
|
|
78
|
+
displayName: string
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface EnabledResult {
|
|
82
|
+
id: string
|
|
83
|
+
enabled: boolean
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface WorkflowDeleteResult {
|
|
87
|
+
deleted: boolean
|
|
88
|
+
runsDeleted: number
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Answered by the two routes that remove a version or a binding. */
|
|
92
|
+
export interface DeletedResult {
|
|
93
|
+
deleted: boolean
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** draft | live | draining | retired */
|
|
97
|
+
export type WorkflowVersionStatus = 'draft' | 'live' | 'draining' | 'retired'
|
|
98
|
+
|
|
99
|
+
/** A row of `GET /v1/workflows/:slug/versions`, narrowed to what a listing shows. */
|
|
100
|
+
export interface VersionSummary {
|
|
101
|
+
id: string
|
|
102
|
+
number: number
|
|
103
|
+
status: WorkflowVersionStatus
|
|
104
|
+
createdAt: string
|
|
105
|
+
createdVia: string | null
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The whole row `GET /v1/workflows/:slug/versions/:n` answers with. */
|
|
109
|
+
export interface WorkflowVersion {
|
|
110
|
+
id: string
|
|
111
|
+
workflowId: string
|
|
112
|
+
number: number
|
|
113
|
+
status: WorkflowVersionStatus
|
|
114
|
+
definition: Record<string, unknown>
|
|
115
|
+
grants: string[]
|
|
116
|
+
lineage: LineageEdge[]
|
|
117
|
+
inputSchema: InputsSchema | null
|
|
118
|
+
/** Presentation only; null means none saved. */
|
|
119
|
+
layout?: WorkflowLayout | null
|
|
120
|
+
createdVia: string | null
|
|
121
|
+
createdBy: string
|
|
122
|
+
createdAt: string
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Canvas card positions keyed by node id. Never read by the engine. */
|
|
126
|
+
export type WorkflowLayout = Record<string, { x: number; y: number }>
|
|
127
|
+
|
|
128
|
+
/** What `saveLayout` answers with. */
|
|
129
|
+
export interface LayoutResult {
|
|
130
|
+
versionId: string
|
|
131
|
+
number: number
|
|
132
|
+
layout: WorkflowLayout | null
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* One step run on its own against the draft's newest test data.
|
|
137
|
+
*
|
|
138
|
+
* `ok: false` is the step failing, not the request failing — a 200 carries it.
|
|
139
|
+
* `preview` marks a kind that only reports what it would do, so its output is
|
|
140
|
+
* never what a real run would put in `$steps`.
|
|
141
|
+
*/
|
|
142
|
+
export type NodeTestResult =
|
|
143
|
+
| { ok: true; nodeId: string; kind: string; mocked: boolean; preview?: boolean; input: unknown; output: unknown }
|
|
144
|
+
| {
|
|
145
|
+
ok: false
|
|
146
|
+
nodeId: string
|
|
147
|
+
kind: string
|
|
148
|
+
mocked: boolean
|
|
149
|
+
preview?: boolean
|
|
150
|
+
input: unknown
|
|
151
|
+
error: Record<string, unknown>
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** One step's newest stored step test, as `stepTests` lists them. */
|
|
155
|
+
export interface StepTest {
|
|
156
|
+
nodeId: string
|
|
157
|
+
kind: string
|
|
158
|
+
status: 'succeeded' | 'failed'
|
|
159
|
+
mocked: boolean
|
|
160
|
+
preview: boolean
|
|
161
|
+
input: unknown
|
|
162
|
+
output: unknown
|
|
163
|
+
error: Record<string, unknown> | null
|
|
164
|
+
testedAt: string
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** How long the draft's test webhook URL stays armed, ISO. */
|
|
168
|
+
export interface WebhookTestWindow {
|
|
169
|
+
until: string
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* What a push answers with.
|
|
174
|
+
*
|
|
175
|
+
* `ok: false` is a result, not a transport failure, and only on a dry run. A
|
|
176
|
+
* real push that fails validation comes back as a 400 whose
|
|
177
|
+
* `FronteraError.details.errors` lists the reasons.
|
|
178
|
+
*/
|
|
179
|
+
export interface PushResult {
|
|
180
|
+
ok: boolean
|
|
181
|
+
errors?: string[]
|
|
182
|
+
workflowId?: string
|
|
183
|
+
version?: { id: string; number: number; status: WorkflowVersionStatus }
|
|
184
|
+
grants?: string[]
|
|
185
|
+
lineage?: LineageEdge[]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface PromoteResult {
|
|
189
|
+
workflowId: string
|
|
190
|
+
versionId: string
|
|
191
|
+
/** True when the version was already live and nothing changed. */
|
|
192
|
+
alreadyLive: boolean
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface LineageEdge {
|
|
196
|
+
kind: string
|
|
197
|
+
resourceKind: string
|
|
198
|
+
resourceId: string
|
|
199
|
+
label?: string | null
|
|
200
|
+
property?: string | null
|
|
201
|
+
nodeId?: string | null
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface VersionLineage {
|
|
205
|
+
version: number
|
|
206
|
+
status: WorkflowVersionStatus
|
|
207
|
+
grants: string[]
|
|
208
|
+
lineage: LineageEdge[]
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface RunRequest {
|
|
212
|
+
/**
|
|
213
|
+
* A `File` value here is sent as its own multipart part, named after the
|
|
214
|
+
* `file` input it fills; everything else travels as JSON.
|
|
215
|
+
*/
|
|
216
|
+
input?: Record<string, unknown>
|
|
217
|
+
subject?: { pk: string }
|
|
218
|
+
/** A version number; without it the live version runs. */
|
|
219
|
+
version?: number
|
|
220
|
+
/** `test` is allowed only against a draft. */
|
|
221
|
+
source?: 'manual' | 'test'
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export interface RunResult {
|
|
225
|
+
runId: string
|
|
226
|
+
versionNumber: number
|
|
227
|
+
/** True when an idempotency key matched a run that already existed. */
|
|
228
|
+
reused?: boolean
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** A row of `GET /v1/workflows/:slug/runs`. */
|
|
232
|
+
export interface RunSummary {
|
|
233
|
+
id: string
|
|
234
|
+
orgId: string
|
|
235
|
+
workflowId: string
|
|
236
|
+
versionId: string
|
|
237
|
+
status: WorkflowRunStatus
|
|
238
|
+
triggerSource: string
|
|
239
|
+
triggerIndex: number | null
|
|
240
|
+
triggeredBy: string | null
|
|
241
|
+
subjectObjectTypeId: string | null
|
|
242
|
+
subjectPk: string | null
|
|
243
|
+
rootRunId: string | null
|
|
244
|
+
parentRunId: string | null
|
|
245
|
+
depth: number
|
|
246
|
+
input: Record<string, unknown>
|
|
247
|
+
output: unknown
|
|
248
|
+
error: Record<string, unknown> | null
|
|
249
|
+
nodeCalls: number
|
|
250
|
+
conversationId: string | null
|
|
251
|
+
idempotencyKey: string | null
|
|
252
|
+
invocationDepth: number
|
|
253
|
+
iteration: { nodePath: string; nodeId: string; index: number; item: unknown; outerSteps: Record<string, unknown> } | null
|
|
254
|
+
startedAt: string
|
|
255
|
+
endedAt: string | null
|
|
256
|
+
versionNumber: number
|
|
257
|
+
workflowSlug: string
|
|
258
|
+
workflowDisplayName: string | null
|
|
259
|
+
triggeredByName: string | null
|
|
260
|
+
triggeredByEmail: string | null
|
|
261
|
+
subjectLabel: string | null
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export type RunListFilters = {
|
|
265
|
+
/** `live` hides test runs; `test` shows only them. */
|
|
266
|
+
source?: 'live' | 'test'
|
|
267
|
+
status?: WorkflowRunStatus
|
|
268
|
+
/** Default 50, maximum 200. */
|
|
269
|
+
limit?: number
|
|
270
|
+
/** Keyset cursor `<startedAt ISO>|<run id>`; see `runCursor`. */
|
|
271
|
+
before?: string
|
|
272
|
+
from?: string
|
|
273
|
+
to?: string
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* `workspaceRuns` filters: the per-workflow set plus the slug that narrows to
|
|
278
|
+
* one workflow. A `type`, not an `interface`, because it is passed as a query
|
|
279
|
+
* bag and only a type alias carries an implicit index signature.
|
|
280
|
+
*/
|
|
281
|
+
export type WorkspaceRunListFilters = RunListFilters & {
|
|
282
|
+
/** A workflow slug. Without it, every workflow in the workspace is included. */
|
|
283
|
+
workflow?: string
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export type RunMetricsPeriod = '24h' | '7d' | '30d' | '90d'
|
|
287
|
+
|
|
288
|
+
export type RunMetricsQuery = {
|
|
289
|
+
/** Default `7d`. */
|
|
290
|
+
period?: RunMetricsPeriod
|
|
291
|
+
/** A workflow slug; without it the whole workspace is counted. */
|
|
292
|
+
workflow?: string
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Run counts over one window. Test runs and forEach children are excluded. */
|
|
296
|
+
export interface RunMetricsTotals {
|
|
297
|
+
runs: number
|
|
298
|
+
succeeded: number
|
|
299
|
+
failed: number
|
|
300
|
+
canceled: number
|
|
301
|
+
running: number
|
|
302
|
+
/** Succeeded over finished. Null when nothing finished in the window. */
|
|
303
|
+
successRate: number | null
|
|
304
|
+
p50DurationMs: number | null
|
|
305
|
+
p95DurationMs: number | null
|
|
306
|
+
nodeCalls: number
|
|
307
|
+
lastRunAt: string | null
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface RunMetricsByWorkflow extends RunMetricsTotals {
|
|
311
|
+
workflowId: string
|
|
312
|
+
workflowSlug: string
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export interface RunVolumeBucket {
|
|
316
|
+
/** Bucket start, ISO. */
|
|
317
|
+
at: string
|
|
318
|
+
succeeded: number
|
|
319
|
+
failed: number
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export interface RunMetrics {
|
|
323
|
+
period: RunMetricsPeriod
|
|
324
|
+
/** The current window, ISO; `to` is exclusive. `previous` is the span before it. */
|
|
325
|
+
range: { from: string; to: string }
|
|
326
|
+
granularity: 'hour' | 'day' | 'week' | 'month'
|
|
327
|
+
current: RunMetricsTotals
|
|
328
|
+
previous: RunMetricsTotals
|
|
329
|
+
buckets: RunVolumeBucket[]
|
|
330
|
+
byWorkflow: RunMetricsByWorkflow[]
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** A step output stored by reference, read back whole. */
|
|
334
|
+
export interface NodeOutput {
|
|
335
|
+
id: string
|
|
336
|
+
runId: string
|
|
337
|
+
nodeId: string
|
|
338
|
+
output: unknown
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** `run` implies `read`; `read` grants the observation tools and no run tool. */
|
|
342
|
+
export type BindingAccess = 'read' | 'run'
|
|
343
|
+
|
|
344
|
+
/** One agent's standing permission on one workflow, from the workflow's side. */
|
|
345
|
+
export interface WorkflowBinding {
|
|
346
|
+
agentId: string
|
|
347
|
+
agentSlug: string
|
|
348
|
+
agentName: string
|
|
349
|
+
enabled: boolean
|
|
350
|
+
access: BindingAccess
|
|
351
|
+
requiresApproval: boolean
|
|
352
|
+
waitSeconds: number
|
|
353
|
+
createdBy: string
|
|
354
|
+
createdAt: string
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* The same permission from the agent's side, plus whether it currently grants
|
|
359
|
+
* anything: a row can exist while nothing is promoted, or while the live
|
|
360
|
+
* version declares a redacted input an agent may not supply.
|
|
361
|
+
*/
|
|
362
|
+
export interface AgentBinding {
|
|
363
|
+
workflowId: string
|
|
364
|
+
workflowSlug: string
|
|
365
|
+
enabled: boolean
|
|
366
|
+
access: BindingAccess
|
|
367
|
+
requiresApproval: boolean
|
|
368
|
+
waitSeconds: number
|
|
369
|
+
runnable: boolean
|
|
370
|
+
/** Why not, when `runnable` is false. */
|
|
371
|
+
inertReason: 'no_live_version' | 'input_redacted' | 'disabled' | 'read_only' | null
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** Every field is optional: an omitted one keeps what the row already holds. */
|
|
375
|
+
export interface BindAgentInput {
|
|
376
|
+
enabled?: boolean
|
|
377
|
+
/** Defaults to `run` on a binding that does not exist yet. */
|
|
378
|
+
access?: BindingAccess
|
|
379
|
+
requiresApproval?: boolean
|
|
380
|
+
/** 5 to 300; defaults to 90. */
|
|
381
|
+
waitSeconds?: number
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** The `before` cursor for the page after `run`, the last row of the current page. */
|
|
385
|
+
export function runCursor(run: Pick<RunSummary, 'startedAt' | 'id'>): string {
|
|
386
|
+
return `${run.startedAt}|${run.id}`
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export interface RunTreeNode {
|
|
390
|
+
id: string
|
|
391
|
+
nodePath: string
|
|
392
|
+
nodeId: string
|
|
393
|
+
kind: string
|
|
394
|
+
status: WorkflowNodeStatus
|
|
395
|
+
attempt: number
|
|
396
|
+
input: unknown
|
|
397
|
+
output: unknown
|
|
398
|
+
error: unknown
|
|
399
|
+
startedAt: string
|
|
400
|
+
endedAt: string | null
|
|
401
|
+
functionRunId: string | null
|
|
402
|
+
actionRequestId: string | null
|
|
403
|
+
conversationId: string | null
|
|
404
|
+
childRunId: string | null
|
|
405
|
+
/** Present with `depth: 'all'`. */
|
|
406
|
+
functionRun?: {
|
|
407
|
+
id: string
|
|
408
|
+
slug: string | null
|
|
409
|
+
status: string
|
|
410
|
+
startedAt: string
|
|
411
|
+
endedAt: string | null
|
|
412
|
+
result: unknown
|
|
413
|
+
errorMessage: string | null
|
|
414
|
+
steps: Array<{
|
|
415
|
+
id: string
|
|
416
|
+
seq: number
|
|
417
|
+
kind: string
|
|
418
|
+
label: string
|
|
419
|
+
status: string
|
|
420
|
+
durationMs: number | null
|
|
421
|
+
stepName: string | null
|
|
422
|
+
}>
|
|
423
|
+
} | null
|
|
424
|
+
/** Present with `depth: 'all'`. */
|
|
425
|
+
actionRequest?: {
|
|
426
|
+
id: string
|
|
427
|
+
lifecycle: string
|
|
428
|
+
createdAt: string
|
|
429
|
+
attempts: Array<{ id: string; createdAt: string }>
|
|
430
|
+
approvals: Array<{ id: string; decision: string; createdAt: string }>
|
|
431
|
+
outcomes: Array<{ id: string; certainty: string; businessOutcomeCode: string | null; createdAt: string }>
|
|
432
|
+
} | null
|
|
433
|
+
/** Present with `depth: 'all'`. */
|
|
434
|
+
conversation?: {
|
|
435
|
+
id: string
|
|
436
|
+
status: string | null
|
|
437
|
+
createdAt: string | null
|
|
438
|
+
messages: Array<{ id: string; role: string; createdAt: string | null }>
|
|
439
|
+
} | null
|
|
440
|
+
/** Present with `depth: 'all'`. */
|
|
441
|
+
childRun?: RunTree | null
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export interface RunTree {
|
|
445
|
+
id: string
|
|
446
|
+
workflowId: string
|
|
447
|
+
slug: string
|
|
448
|
+
versionId: string
|
|
449
|
+
versionNumber: number | null
|
|
450
|
+
status: WorkflowRunStatus
|
|
451
|
+
triggerSource: string
|
|
452
|
+
triggeredBy: string | null
|
|
453
|
+
triggeredByName: string | null
|
|
454
|
+
subject: { objectTypeId: string; pk: string; apiName: string | null; label: string | null } | null
|
|
455
|
+
rootRunId: string | null
|
|
456
|
+
parentRunId: string | null
|
|
457
|
+
depth: number
|
|
458
|
+
input: Record<string, unknown>
|
|
459
|
+
output: unknown
|
|
460
|
+
error: unknown
|
|
461
|
+
nodeCalls: number
|
|
462
|
+
startedAt: string
|
|
463
|
+
endedAt: string | null
|
|
464
|
+
nodes: RunTreeNode[]
|
|
465
|
+
/** Only on the root of the tree, and only for a webhook delivery. */
|
|
466
|
+
triggerCapture?: unknown
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export interface CancelResult {
|
|
470
|
+
runId: string
|
|
471
|
+
status: WorkflowRunStatus
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export interface WaitForRunOptions {
|
|
475
|
+
/** Default 1500. */
|
|
476
|
+
intervalMs?: number
|
|
477
|
+
/** Default 10 minutes. The run is left running on timeout. */
|
|
478
|
+
timeoutMs?: number
|
|
479
|
+
signal?: AbortSignal
|
|
480
|
+
/** Default `'run'`. */
|
|
481
|
+
depth?: 'run' | 'all'
|
|
482
|
+
onPoll?: (run: RunTree) => void
|
|
483
|
+
}
|