@oxygen-agent/cli 1.377.3 → 1.575.19
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/README.md +1 -1
- package/dist/column-run-notices.d.ts +11 -0
- package/dist/column-run-notices.js +37 -0
- package/dist/command-manifest.js +13 -8
- package/dist/help.js +78 -16
- package/dist/index.js +3450 -447
- package/dist/skills.js +106 -1
- package/node_modules/@oxygen/formula/dist/coerce.d.ts +8 -0
- package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
- package/node_modules/@oxygen/formula/dist/evaluate.d.ts +31 -0
- package/node_modules/@oxygen/formula/dist/evaluate.js +248 -0
- package/node_modules/@oxygen/formula/dist/expression.d.ts +64 -0
- package/node_modules/@oxygen/formula/dist/expression.js +428 -0
- package/node_modules/@oxygen/formula/dist/formula-functions.d.ts +71 -0
- package/node_modules/@oxygen/formula/dist/formula-functions.js +1100 -0
- package/node_modules/@oxygen/formula/dist/index.d.ts +17 -0
- package/node_modules/@oxygen/formula/dist/index.js +17 -0
- package/node_modules/@oxygen/formula/dist/value-normalizers.d.ts +30 -0
- package/node_modules/@oxygen/formula/dist/value-normalizers.js +80 -0
- package/node_modules/@oxygen/formula/package.json +26 -0
- package/node_modules/@oxygen/recipe-sdk/dist/index.d.ts +30 -0
- package/node_modules/@oxygen/recipe-sdk/dist/index.js +2 -2
- package/node_modules/@oxygen/shared/dist/billing-anchors.d.ts +60 -0
- package/node_modules/@oxygen/shared/dist/billing-anchors.js +135 -0
- package/node_modules/@oxygen/shared/dist/billing.d.ts +99 -5
- package/node_modules/@oxygen/shared/dist/billing.js +185 -8
- package/node_modules/@oxygen/shared/dist/call-outcomes.d.ts +59 -0
- package/node_modules/@oxygen/shared/dist/call-outcomes.js +73 -0
- package/node_modules/@oxygen/shared/dist/cli-result.js +1 -0
- package/node_modules/@oxygen/shared/dist/credit-guidance.js +3 -1
- package/node_modules/@oxygen/shared/dist/crm-reply-events.d.ts +35 -0
- package/node_modules/@oxygen/shared/dist/crm-reply-events.js +31 -0
- package/node_modules/@oxygen/shared/dist/dial-guardrail-overrides.d.ts +50 -0
- package/node_modules/@oxygen/shared/dist/dial-guardrail-overrides.js +65 -0
- package/node_modules/@oxygen/shared/dist/directory.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/directory.js +1 -0
- package/node_modules/@oxygen/shared/dist/hosted-ai.d.ts +15 -0
- package/node_modules/@oxygen/shared/dist/hosted-ai.js +19 -0
- package/node_modules/@oxygen/shared/dist/index.d.ts +9 -0
- package/node_modules/@oxygen/shared/dist/index.js +9 -0
- package/node_modules/@oxygen/shared/dist/linkedin-quota-denial.d.ts +31 -0
- package/node_modules/@oxygen/shared/dist/linkedin-quota-denial.js +56 -0
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +5 -4
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +5 -4
- package/node_modules/@oxygen/shared/dist/linkedin-url.d.ts +22 -0
- package/node_modules/@oxygen/shared/dist/linkedin-url.js +7 -4
- package/node_modules/@oxygen/shared/dist/log.js +41 -2
- package/node_modules/@oxygen/shared/dist/microsoft-consent-url.d.ts +7 -0
- package/node_modules/@oxygen/shared/dist/microsoft-consent-url.js +29 -0
- package/node_modules/@oxygen/shared/dist/object-storage.d.ts +31 -0
- package/node_modules/@oxygen/shared/dist/object-storage.js +61 -0
- package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +636 -0
- package/node_modules/@oxygen/shared/dist/plan-limits.js +199 -0
- package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +89 -23
- package/node_modules/@oxygen/shared/dist/pricing-sheet.js +88 -24
- package/node_modules/@oxygen/shared/dist/sequence-crm-events.d.ts +291 -0
- package/node_modules/@oxygen/shared/dist/sequence-crm-events.js +224 -0
- package/node_modules/@oxygen/shared/dist/sequence-template.d.ts +42 -1
- package/node_modules/@oxygen/shared/dist/sequence-template.js +0 -0
- package/node_modules/@oxygen/shared/dist/sequences.d.ts +287 -24
- package/node_modules/@oxygen/shared/dist/sequences.js +940 -60
- package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +70 -0
- package/node_modules/@oxygen/shared/dist/spend-safety.js +106 -0
- package/node_modules/@oxygen/shared/dist/tags.d.ts +90 -1
- package/node_modules/@oxygen/shared/dist/tags.js +122 -6
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.js +4 -0
- package/node_modules/@oxygen/shared/package.json +95 -0
- package/node_modules/@oxygen/workflows/dist/event-dispatch.d.ts +126 -0
- package/node_modules/@oxygen/workflows/dist/event-dispatch.js +173 -0
- package/node_modules/@oxygen/workflows/dist/graph/expression.d.ts +78 -0
- package/node_modules/@oxygen/workflows/dist/graph/expression.js +700 -0
- package/node_modules/@oxygen/workflows/dist/graph/index.d.ts +20 -0
- package/node_modules/@oxygen/workflows/dist/graph/index.js +20 -0
- package/node_modules/@oxygen/workflows/dist/graph/lint.d.ts +4 -0
- package/node_modules/@oxygen/workflows/dist/graph/lint.js +812 -0
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +501 -0
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.js +200 -0
- package/node_modules/@oxygen/workflows/dist/graph/params.d.ts +86 -0
- package/node_modules/@oxygen/workflows/dist/graph/params.js +173 -0
- package/node_modules/@oxygen/workflows/dist/graph/remap.d.ts +48 -0
- package/node_modules/@oxygen/workflows/dist/graph/remap.js +213 -0
- package/node_modules/@oxygen/workflows/dist/graph/topology.d.ts +46 -0
- package/node_modules/@oxygen/workflows/dist/graph/topology.js +280 -0
- package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +270 -0
- package/node_modules/@oxygen/workflows/dist/graph/types.js +93 -0
- package/node_modules/@oxygen/workflows/dist/index.d.ts +113 -1
- package/node_modules/@oxygen/workflows/dist/index.js +179 -13
- package/node_modules/@oxygen/workflows/dist/tool-effects.d.ts +1 -0
- package/node_modules/@oxygen/workflows/dist/tool-effects.js +19 -0
- package/node_modules/@oxygen/workflows/dist/usage-estimate.js +135 -4
- package/node_modules/@oxygen/workflows/package.json +4 -0
- package/package.json +7 -5
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type { JsonSchema, WorkflowMode, WorkflowStatus, WorkflowStepEffect, WorkflowTriggerManifest } from "../index.js";
|
|
2
|
+
export declare const WORKFLOW_GRAPH_MANIFEST_VERSION = 2;
|
|
3
|
+
export declare const WORKFLOW_GRAPH_COMPILER_VERSION = "oxygen-workflows-v2";
|
|
4
|
+
export declare const RESERVED_NODE_IDS: ReadonlySet<string>;
|
|
5
|
+
export declare const LOOP_BODY_HANDLE = "loop_body";
|
|
6
|
+
export declare const LOOP_DONE_HANDLE = "loop_done";
|
|
7
|
+
export declare const ERROR_HANDLE = "error";
|
|
8
|
+
export declare const RESERVED_EDGE_HANDLES: ReadonlySet<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Hard ceiling on the iterations a single `loop` node may run, independent of the
|
|
11
|
+
* node's declared `max_iterations`.
|
|
12
|
+
*
|
|
13
|
+
* ONE constant, shared by three consumers that must agree or the billing gates
|
|
14
|
+
* lie: the linter (an authored `max_iterations` above this is refused, so nobody
|
|
15
|
+
* authors a bound the runtime will silently ignore), the usage estimator (the
|
|
16
|
+
* per-run action floor multiplies by the declared cap, which therefore must be a
|
|
17
|
+
* cap the runtime honours), and the worker interpreter (which clamps every loop
|
|
18
|
+
* to this regardless of what the manifest says, so one run cannot monopolise a
|
|
19
|
+
* tenant tick).
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_WORKFLOW_LOOP_ITERATIONS = 1000;
|
|
22
|
+
/**
|
|
23
|
+
* Node kinds a v2 run bills an automation action for.
|
|
24
|
+
*
|
|
25
|
+
* The rest of the graph — trigger, filter, switch, loop, merge, set, wait, code —
|
|
26
|
+
* is in-process control flow that crosses no boundary and draws nothing. This set
|
|
27
|
+
* is the SINGLE definition of that contract: the worker interpreter records an
|
|
28
|
+
* automation action exactly for these kinds, the usage estimator prices exactly
|
|
29
|
+
* these kinds, and the run-allowance preflight subtracts settled rows of exactly
|
|
30
|
+
* these kinds. When the three disagree, the pre-write allowance gate reserves
|
|
31
|
+
* less than the run draws and a capped workspace strands partial writes — which
|
|
32
|
+
* is precisely what having one exported set prevents.
|
|
33
|
+
*
|
|
34
|
+
* `code` is deliberately free even though its v1 cousin (a `transform` step)
|
|
35
|
+
* bills: a v2 graph decomposes what was one v1 step into several nodes, and
|
|
36
|
+
* billing each of them would make the same motion cost several times more on the
|
|
37
|
+
* visual builder than in the CLI.
|
|
38
|
+
*/
|
|
39
|
+
export declare const BILLABLE_WORKFLOW_GRAPH_NODE_KINDS: ReadonlySet<string>;
|
|
40
|
+
/** Whether a v2 node of this kind draws an automation action when it executes. */
|
|
41
|
+
export declare function workflowGraphNodeKindBills(kind: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* How a node input is bound to a value at run time. A deliberate sibling of
|
|
44
|
+
* tenant-db's ColumnValueRef so Tables and Workflows share one binding
|
|
45
|
+
* vocabulary — a user who learned column bindings already knows node bindings.
|
|
46
|
+
*/
|
|
47
|
+
export type WorkflowValueRef =
|
|
48
|
+
/** Use `value` verbatim. */
|
|
49
|
+
{
|
|
50
|
+
type: "literal";
|
|
51
|
+
value: unknown;
|
|
52
|
+
}
|
|
53
|
+
/** Interpolated string, e.g. "Hi {{ nodes.find_person.output.first_name }}". */
|
|
54
|
+
| {
|
|
55
|
+
type: "template";
|
|
56
|
+
value: string;
|
|
57
|
+
}
|
|
58
|
+
/** A single scope path: "trigger.input.x" | "steps.<id>.output.y" | "loop.<id>.item.z". */
|
|
59
|
+
| {
|
|
60
|
+
type: "ref";
|
|
61
|
+
path: string;
|
|
62
|
+
}
|
|
63
|
+
/** An OXYGEN formula-language expression (packages/formula). */
|
|
64
|
+
| {
|
|
65
|
+
type: "formula";
|
|
66
|
+
expression: string;
|
|
67
|
+
}
|
|
68
|
+
/** Knowledge-layer company profile, optionally a path inside it. */
|
|
69
|
+
| {
|
|
70
|
+
type: "context_profile";
|
|
71
|
+
path?: string;
|
|
72
|
+
}
|
|
73
|
+
/** A specific Knowledge-layer asset, optionally a path inside it. */
|
|
74
|
+
| {
|
|
75
|
+
type: "context_asset";
|
|
76
|
+
assetId: string;
|
|
77
|
+
path?: string;
|
|
78
|
+
};
|
|
79
|
+
export type WorkflowValueRefType = WorkflowValueRef["type"];
|
|
80
|
+
export type WorkflowCompareOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "contains" | "not_contains" | "starts_with" | "ends_with" | "is_empty" | "is_not_empty" | "in" | "not_in" | "matches";
|
|
81
|
+
/**
|
|
82
|
+
* A structured (never source-code) predicate, so the editor can render it and the
|
|
83
|
+
* runtime can evaluate it without a sandbox.
|
|
84
|
+
*
|
|
85
|
+
* `right` is omitted for the unary operators (`is_empty` / `is_not_empty`).
|
|
86
|
+
*/
|
|
87
|
+
export type WorkflowCondition = {
|
|
88
|
+
type: "group";
|
|
89
|
+
op: "all" | "any";
|
|
90
|
+
not?: boolean;
|
|
91
|
+
children: WorkflowCondition[];
|
|
92
|
+
} | {
|
|
93
|
+
type: "compare";
|
|
94
|
+
left: WorkflowValueRef;
|
|
95
|
+
op: WorkflowCompareOp;
|
|
96
|
+
right?: WorkflowValueRef;
|
|
97
|
+
};
|
|
98
|
+
type WorkflowGraphNodeBase = {
|
|
99
|
+
id: string;
|
|
100
|
+
name: string;
|
|
101
|
+
description?: string;
|
|
102
|
+
/** Canvas position. Presentation only — it never affects execution order. */
|
|
103
|
+
ui: {
|
|
104
|
+
x: number;
|
|
105
|
+
y: number;
|
|
106
|
+
};
|
|
107
|
+
/** Kept in the graph but skipped at run time. */
|
|
108
|
+
disabled?: boolean;
|
|
109
|
+
/** Route failures to the "error" handle instead of failing the run. */
|
|
110
|
+
continue_on_error?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Per-node retry, for a provider that fails transiently — a rate limit, a flaky
|
|
113
|
+
* upstream. n8n, Make and Zapier all expose this per step; without it "retry
|
|
114
|
+
* this enrichment twice with a pause" has to be hand-built from wait + switch.
|
|
115
|
+
*
|
|
116
|
+
* It can only ever NARROW. The worker consults it AFTER
|
|
117
|
+
* isRetryableWorkflowStepError has already permitted a retry, so it bounds
|
|
118
|
+
* attempts and sets the pause but can never authorize one the safety rules
|
|
119
|
+
* refuse. A live `external_write` is still never auto-retried whatever this
|
|
120
|
+
* says: an ambiguous network error may have LANDED, and no replay cache makes a
|
|
121
|
+
* second call a no-op.
|
|
122
|
+
*/
|
|
123
|
+
retry?: {
|
|
124
|
+
/** Attempts for THIS node, counting the first. */
|
|
125
|
+
max_attempts: number;
|
|
126
|
+
/** Fixed pause between attempts. Omitted means the run's usual backoff. */
|
|
127
|
+
wait_seconds?: number;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
/** Bounds on a node's own retry budget. */
|
|
131
|
+
export declare const MAX_WORKFLOW_NODE_RETRY_ATTEMPTS = 5;
|
|
132
|
+
export declare const MAX_WORKFLOW_NODE_RETRY_WAIT_SECONDS = 3600;
|
|
133
|
+
export type WorkflowGraphNode =
|
|
134
|
+
/** The run's entry point. Its output is the trigger payload. */
|
|
135
|
+
(WorkflowGraphNodeBase & {
|
|
136
|
+
kind: "trigger";
|
|
137
|
+
}) | (WorkflowGraphNodeBase & {
|
|
138
|
+
kind: "tool";
|
|
139
|
+
tool: string;
|
|
140
|
+
effect: WorkflowStepEffect;
|
|
141
|
+
mode?: WorkflowMode;
|
|
142
|
+
/** Per-node managed-credit ceiling, same semantics as v1 tool steps. */
|
|
143
|
+
max_credits?: number;
|
|
144
|
+
params: Record<string, WorkflowValueRef>;
|
|
145
|
+
})
|
|
146
|
+
/** Passes execution on only when `when` holds. */
|
|
147
|
+
| (WorkflowGraphNodeBase & {
|
|
148
|
+
kind: "filter";
|
|
149
|
+
when: WorkflowCondition;
|
|
150
|
+
})
|
|
151
|
+
/**
|
|
152
|
+
* Multi-way branch. Each case owns an outgoing handle named by its `id`;
|
|
153
|
+
* `fallthrough` allows every matching case to fire instead of only the first.
|
|
154
|
+
*/
|
|
155
|
+
| (WorkflowGraphNodeBase & {
|
|
156
|
+
kind: "switch";
|
|
157
|
+
cases: Array<{
|
|
158
|
+
id: string;
|
|
159
|
+
label: string;
|
|
160
|
+
when: WorkflowCondition;
|
|
161
|
+
}>;
|
|
162
|
+
fallthrough?: boolean;
|
|
163
|
+
})
|
|
164
|
+
/**
|
|
165
|
+
* Iterates `over`. The "loop_body" handle enters the body; the body's last node
|
|
166
|
+
* edges back to this node (the one legal back-edge); "loop_done" continues after.
|
|
167
|
+
*/
|
|
168
|
+
| (WorkflowGraphNodeBase & {
|
|
169
|
+
kind: "loop";
|
|
170
|
+
over: WorkflowValueRef;
|
|
171
|
+
item_name?: string;
|
|
172
|
+
max_iterations?: number;
|
|
173
|
+
concurrency?: number;
|
|
174
|
+
})
|
|
175
|
+
/** Joins several inbound edges back into one. */
|
|
176
|
+
| (WorkflowGraphNodeBase & {
|
|
177
|
+
kind: "merge";
|
|
178
|
+
strategy: "append" | "first" | "wait_all";
|
|
179
|
+
})
|
|
180
|
+
/** Builds a plain object output from bound fields. */
|
|
181
|
+
| (WorkflowGraphNodeBase & {
|
|
182
|
+
kind: "set";
|
|
183
|
+
fields: Array<{
|
|
184
|
+
key: string;
|
|
185
|
+
value: WorkflowValueRef;
|
|
186
|
+
}>;
|
|
187
|
+
keep_input?: boolean;
|
|
188
|
+
})
|
|
189
|
+
/** Delays for a fixed duration, or until `until` evaluates truthy. */
|
|
190
|
+
| (WorkflowGraphNodeBase & {
|
|
191
|
+
kind: "wait";
|
|
192
|
+
duration_seconds?: number;
|
|
193
|
+
until?: WorkflowValueRef;
|
|
194
|
+
})
|
|
195
|
+
/**
|
|
196
|
+
* Blocks the run until a human approves. The one node kind whose output is a
|
|
197
|
+
* decision rather than data: on approval execution continues out the default
|
|
198
|
+
* handle; on rejection the run ends terminally, because "proceed anyway" is
|
|
199
|
+
* exactly what an approval gate exists to prevent (the primitive's
|
|
200
|
+
* "approvals block, never advise" invariant).
|
|
201
|
+
*
|
|
202
|
+
* `reason` and `request` are for the person deciding — they are resolved and
|
|
203
|
+
* stored on the approval row, so the approver sees why they were asked and
|
|
204
|
+
* what is about to happen instead of only a node id. Non-live modes pass
|
|
205
|
+
* through without asking: a dry run has no side effect to authorize, and
|
|
206
|
+
* blocking a preview on a human would make previews unusable.
|
|
207
|
+
*/
|
|
208
|
+
| (WorkflowGraphNodeBase & {
|
|
209
|
+
kind: "approval";
|
|
210
|
+
reason?: WorkflowValueRef;
|
|
211
|
+
request?: Record<string, WorkflowValueRef>;
|
|
212
|
+
})
|
|
213
|
+
/** Sandboxed transform source, the v2 spelling of a v1 transform step. */
|
|
214
|
+
| (WorkflowGraphNodeBase & {
|
|
215
|
+
kind: "code";
|
|
216
|
+
run_source: string;
|
|
217
|
+
})
|
|
218
|
+
/** Calls another workflow as a child run. */
|
|
219
|
+
| (WorkflowGraphNodeBase & {
|
|
220
|
+
kind: "workflow";
|
|
221
|
+
workflow_id: string;
|
|
222
|
+
input: Record<string, WorkflowValueRef>;
|
|
223
|
+
});
|
|
224
|
+
export type WorkflowGraphNodeKind = WorkflowGraphNode["kind"];
|
|
225
|
+
/** Narrow a node union member by its `kind` discriminant. */
|
|
226
|
+
export type WorkflowGraphNodeOfKind<K extends WorkflowGraphNodeKind> = Extract<WorkflowGraphNode, {
|
|
227
|
+
kind: K;
|
|
228
|
+
}>;
|
|
229
|
+
/**
|
|
230
|
+
* A directed execution edge.
|
|
231
|
+
*
|
|
232
|
+
* `source_handle` names which output of the source node this edge leaves from:
|
|
233
|
+
* a `switch` case id, "loop_body", "loop_done", "error", or undefined for the
|
|
234
|
+
* node's default output.
|
|
235
|
+
*/
|
|
236
|
+
export type WorkflowGraphEdge = {
|
|
237
|
+
id: string;
|
|
238
|
+
source: string;
|
|
239
|
+
source_handle?: string;
|
|
240
|
+
target: string;
|
|
241
|
+
};
|
|
242
|
+
export type WorkflowGraphManifest = {
|
|
243
|
+
manifest_version: typeof WORKFLOW_GRAPH_MANIFEST_VERSION;
|
|
244
|
+
workflow: {
|
|
245
|
+
id: string;
|
|
246
|
+
name: string;
|
|
247
|
+
status?: WorkflowStatus;
|
|
248
|
+
};
|
|
249
|
+
specification?: string;
|
|
250
|
+
trigger?: WorkflowTriggerManifest;
|
|
251
|
+
input_schema?: JsonSchema;
|
|
252
|
+
nodes: WorkflowGraphNode[];
|
|
253
|
+
edges: WorkflowGraphEdge[];
|
|
254
|
+
/** Per-RUN managed-credit ceiling, same semantics as WorkflowManifest.max_credits. */
|
|
255
|
+
max_credits?: number;
|
|
256
|
+
source_hash: string;
|
|
257
|
+
compiler_version: typeof WORKFLOW_GRAPH_COMPILER_VERSION;
|
|
258
|
+
created_at: string;
|
|
259
|
+
};
|
|
260
|
+
/**
|
|
261
|
+
* Shape gate only — enough to route a manifest to the v2 code path. Full
|
|
262
|
+
* structural validation is the linter's job, not this guard's.
|
|
263
|
+
*/
|
|
264
|
+
export declare function isWorkflowGraphManifest(value: unknown): value is WorkflowGraphManifest;
|
|
265
|
+
export declare function isTriggerNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"trigger">;
|
|
266
|
+
export declare function isToolNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"tool">;
|
|
267
|
+
export declare function isSwitchNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"switch">;
|
|
268
|
+
export declare function isLoopNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"loop">;
|
|
269
|
+
export declare function isWorkflowSubgraphNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"workflow">;
|
|
270
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export const WORKFLOW_GRAPH_MANIFEST_VERSION = 2;
|
|
2
|
+
export const WORKFLOW_GRAPH_COMPILER_VERSION = "oxygen-workflows-v2";
|
|
3
|
+
// Node ids become keys on the runtime scope object (`steps.<id>.output`), exactly
|
|
4
|
+
// as v1 step ids become keys on ctx.steps. The same JavaScript-internals collision
|
|
5
|
+
// applies: a node named `__proto__` would silently lose its output.
|
|
6
|
+
export const RESERVED_NODE_IDS = new Set([
|
|
7
|
+
"__proto__",
|
|
8
|
+
"constructor",
|
|
9
|
+
"prototype",
|
|
10
|
+
]);
|
|
11
|
+
// Reserved edge source handles. Anything else in `source_handle` must name a
|
|
12
|
+
// case id on a `switch` node.
|
|
13
|
+
export const LOOP_BODY_HANDLE = "loop_body";
|
|
14
|
+
export const LOOP_DONE_HANDLE = "loop_done";
|
|
15
|
+
export const ERROR_HANDLE = "error";
|
|
16
|
+
export const RESERVED_EDGE_HANDLES = new Set([
|
|
17
|
+
LOOP_BODY_HANDLE,
|
|
18
|
+
LOOP_DONE_HANDLE,
|
|
19
|
+
ERROR_HANDLE,
|
|
20
|
+
]);
|
|
21
|
+
/**
|
|
22
|
+
* Hard ceiling on the iterations a single `loop` node may run, independent of the
|
|
23
|
+
* node's declared `max_iterations`.
|
|
24
|
+
*
|
|
25
|
+
* ONE constant, shared by three consumers that must agree or the billing gates
|
|
26
|
+
* lie: the linter (an authored `max_iterations` above this is refused, so nobody
|
|
27
|
+
* authors a bound the runtime will silently ignore), the usage estimator (the
|
|
28
|
+
* per-run action floor multiplies by the declared cap, which therefore must be a
|
|
29
|
+
* cap the runtime honours), and the worker interpreter (which clamps every loop
|
|
30
|
+
* to this regardless of what the manifest says, so one run cannot monopolise a
|
|
31
|
+
* tenant tick).
|
|
32
|
+
*/
|
|
33
|
+
export const MAX_WORKFLOW_LOOP_ITERATIONS = 1_000;
|
|
34
|
+
/**
|
|
35
|
+
* Node kinds a v2 run bills an automation action for.
|
|
36
|
+
*
|
|
37
|
+
* The rest of the graph — trigger, filter, switch, loop, merge, set, wait, code —
|
|
38
|
+
* is in-process control flow that crosses no boundary and draws nothing. This set
|
|
39
|
+
* is the SINGLE definition of that contract: the worker interpreter records an
|
|
40
|
+
* automation action exactly for these kinds, the usage estimator prices exactly
|
|
41
|
+
* these kinds, and the run-allowance preflight subtracts settled rows of exactly
|
|
42
|
+
* these kinds. When the three disagree, the pre-write allowance gate reserves
|
|
43
|
+
* less than the run draws and a capped workspace strands partial writes — which
|
|
44
|
+
* is precisely what having one exported set prevents.
|
|
45
|
+
*
|
|
46
|
+
* `code` is deliberately free even though its v1 cousin (a `transform` step)
|
|
47
|
+
* bills: a v2 graph decomposes what was one v1 step into several nodes, and
|
|
48
|
+
* billing each of them would make the same motion cost several times more on the
|
|
49
|
+
* visual builder than in the CLI.
|
|
50
|
+
*/
|
|
51
|
+
export const BILLABLE_WORKFLOW_GRAPH_NODE_KINDS = new Set([
|
|
52
|
+
"tool",
|
|
53
|
+
"workflow",
|
|
54
|
+
]);
|
|
55
|
+
/** Whether a v2 node of this kind draws an automation action when it executes. */
|
|
56
|
+
export function workflowGraphNodeKindBills(kind) {
|
|
57
|
+
return BILLABLE_WORKFLOW_GRAPH_NODE_KINDS.has(kind);
|
|
58
|
+
}
|
|
59
|
+
/** Bounds on a node's own retry budget. */
|
|
60
|
+
export const MAX_WORKFLOW_NODE_RETRY_ATTEMPTS = 5;
|
|
61
|
+
export const MAX_WORKFLOW_NODE_RETRY_WAIT_SECONDS = 3_600;
|
|
62
|
+
function isRecord(value) {
|
|
63
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Shape gate only — enough to route a manifest to the v2 code path. Full
|
|
67
|
+
* structural validation is the linter's job, not this guard's.
|
|
68
|
+
*/
|
|
69
|
+
export function isWorkflowGraphManifest(value) {
|
|
70
|
+
return isRecord(value)
|
|
71
|
+
&& value.manifest_version === WORKFLOW_GRAPH_MANIFEST_VERSION
|
|
72
|
+
&& value.compiler_version === WORKFLOW_GRAPH_COMPILER_VERSION
|
|
73
|
+
&& Array.isArray(value.nodes)
|
|
74
|
+
&& Array.isArray(value.edges);
|
|
75
|
+
}
|
|
76
|
+
function isNodeOfKind(node, kind) {
|
|
77
|
+
return node.kind === kind;
|
|
78
|
+
}
|
|
79
|
+
export function isTriggerNode(node) {
|
|
80
|
+
return isNodeOfKind(node, "trigger");
|
|
81
|
+
}
|
|
82
|
+
export function isToolNode(node) {
|
|
83
|
+
return isNodeOfKind(node, "tool");
|
|
84
|
+
}
|
|
85
|
+
export function isSwitchNode(node) {
|
|
86
|
+
return isNodeOfKind(node, "switch");
|
|
87
|
+
}
|
|
88
|
+
export function isLoopNode(node) {
|
|
89
|
+
return isNodeOfKind(node, "loop");
|
|
90
|
+
}
|
|
91
|
+
export function isWorkflowSubgraphNode(node) {
|
|
92
|
+
return isNodeOfKind(node, "workflow");
|
|
93
|
+
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import { type WorkflowGraphManifest } from "./graph/types.js";
|
|
2
|
+
import type { ToolParamFields, ToolParamSpec } from "./graph/params.js";
|
|
1
3
|
export * from "./usage-estimate.js";
|
|
4
|
+
export * from "./event-dispatch.js";
|
|
5
|
+
export type { CanonicalWorkflowToolEffect } from "./tool-effects.js";
|
|
6
|
+
export * from "./graph/index.js";
|
|
7
|
+
export * from "./graph/lint.js";
|
|
2
8
|
export declare const WORKFLOW_MANIFEST_VERSION = 1;
|
|
3
9
|
export declare const WORKFLOW_COMPILER_VERSION = "oxygen-workflows-v1";
|
|
4
10
|
export declare const DURABLE_RECIPE_COMPILER_VERSION = "oxygen-recipes-v2";
|
|
@@ -148,7 +154,7 @@ export type RecipeManifest = {
|
|
|
148
154
|
compiler_version: typeof DURABLE_RECIPE_COMPILER_VERSION;
|
|
149
155
|
created_at: string;
|
|
150
156
|
};
|
|
151
|
-
export type AnyWorkflowManifest = WorkflowManifest | RecipeManifest;
|
|
157
|
+
export type AnyWorkflowManifest = WorkflowManifest | RecipeManifest | WorkflowGraphManifest;
|
|
152
158
|
export type BlueprintColumnInput = {
|
|
153
159
|
key?: string;
|
|
154
160
|
label: string;
|
|
@@ -269,6 +275,23 @@ export type WorkflowLintResult = {
|
|
|
269
275
|
export type JsonSchemaValidationIssue = WorkflowLintIssue;
|
|
270
276
|
export type WorkflowManifestValidationOptions = {
|
|
271
277
|
isToolAllowed?: (toolId: string) => boolean;
|
|
278
|
+
/**
|
|
279
|
+
* A tool's input fields, so lint can tell whether a node is actually filled in.
|
|
280
|
+
*
|
|
281
|
+
* Injected exactly like resolveToolEffect and for the same reason: the field
|
|
282
|
+
* list lives in @oxygen/tools / @oxygen/mcp-server, which the CLI and the
|
|
283
|
+
* browser bundle cannot carry. Omitting it SKIPS the check rather than
|
|
284
|
+
* refusing — but every SERVER lint path must inject it, because without it the
|
|
285
|
+
* editor blocks a node that `apply` then accepts, which is precisely the
|
|
286
|
+
* GUI-only guarantee this option exists to end.
|
|
287
|
+
*/
|
|
288
|
+
/**
|
|
289
|
+
* Accepts a bare field list or a `{ fields, closed }` pair. The union is
|
|
290
|
+
* deliberate: it widens the contract for callers that can report whether the
|
|
291
|
+
* schema is closed without touching the ones that cannot.
|
|
292
|
+
*/
|
|
293
|
+
resolveToolParamFields?: (toolId: string) => readonly ToolParamSpec[] | ToolParamFields | null;
|
|
294
|
+
resolveToolEffect?: (toolId: string) => WorkflowStepEffect | null;
|
|
272
295
|
};
|
|
273
296
|
export declare function defineWorkflow(input: {
|
|
274
297
|
id: string;
|
|
@@ -345,6 +368,13 @@ export declare function branchStep(input: {
|
|
|
345
368
|
export declare function isWorkflowDefinition(value: unknown): value is WorkflowDefinition;
|
|
346
369
|
export declare function isWorkflowManifest(value: unknown): value is WorkflowManifest;
|
|
347
370
|
export declare function isRecipeManifest(value: unknown): value is RecipeManifest;
|
|
371
|
+
/**
|
|
372
|
+
* Every manifest shape the platform can store and run: v1 hosted steps, durable
|
|
373
|
+
* recipes, and oxygen-workflows-v2 graphs. This is the gate `workflows apply`
|
|
374
|
+
* and the CLI loader route through, so a shape listed here must already have a
|
|
375
|
+
* linter and a worker execution path — accepting a manifest we cannot run would
|
|
376
|
+
* cut a revision that fails at run time instead of at authoring time.
|
|
377
|
+
*/
|
|
348
378
|
export declare function isAnyWorkflowManifest(value: unknown): value is AnyWorkflowManifest;
|
|
349
379
|
export declare function compileWorkflowDefinition(// skipcq: JS-R1005 -- compiler validates workflow metadata, trigger, steps, branch targets, and defaults together.
|
|
350
380
|
definition: WorkflowDefinition, options?: {
|
|
@@ -365,6 +395,7 @@ export declare function buildRecipeManifest(input: {
|
|
|
365
395
|
sourceHash?: string;
|
|
366
396
|
createdAt?: Date;
|
|
367
397
|
}): RecipeManifest;
|
|
398
|
+
export declare function validateOptionalMaxCredits(value: unknown, path: string, add: (path: string, code: string, message: string) => void): void;
|
|
368
399
|
export declare function lintWorkflowManifest(// skipcq: JS-R1005
|
|
369
400
|
value: unknown, options?: WorkflowManifestValidationOptions): WorkflowLintResult;
|
|
370
401
|
export declare function lintRecipeManifest(// skipcq: JS-R1005
|
|
@@ -411,6 +442,15 @@ export declare const workflowApplySchema: {
|
|
|
411
442
|
readonly manifest: {
|
|
412
443
|
readonly $ref: "#/$defs/manifest";
|
|
413
444
|
};
|
|
445
|
+
readonly approved: {
|
|
446
|
+
readonly type: "boolean";
|
|
447
|
+
readonly description: "Standing tool authorization for this exact autonomous revision.";
|
|
448
|
+
};
|
|
449
|
+
readonly max_credits: {
|
|
450
|
+
readonly type: "number";
|
|
451
|
+
readonly exclusiveMinimum: 0;
|
|
452
|
+
readonly description: "Hard credit ceiling for each autonomous delivery.";
|
|
453
|
+
};
|
|
414
454
|
};
|
|
415
455
|
readonly required: readonly ["manifest"];
|
|
416
456
|
readonly $defs: {
|
|
@@ -553,6 +593,15 @@ export declare function getWorkflowSchema(subject?: "apply" | "call" | "event" |
|
|
|
553
593
|
readonly manifest: {
|
|
554
594
|
readonly $ref: "#/$defs/manifest";
|
|
555
595
|
};
|
|
596
|
+
readonly approved: {
|
|
597
|
+
readonly type: "boolean";
|
|
598
|
+
readonly description: "Standing tool authorization for this exact autonomous revision.";
|
|
599
|
+
};
|
|
600
|
+
readonly max_credits: {
|
|
601
|
+
readonly type: "number";
|
|
602
|
+
readonly exclusiveMinimum: 0;
|
|
603
|
+
readonly description: "Hard credit ceiling for each autonomous delivery.";
|
|
604
|
+
};
|
|
556
605
|
};
|
|
557
606
|
readonly required: readonly ["manifest"];
|
|
558
607
|
readonly $defs: {
|
|
@@ -692,6 +741,15 @@ export declare function getWorkflowSchema(subject?: "apply" | "call" | "event" |
|
|
|
692
741
|
readonly manifest: {
|
|
693
742
|
readonly $ref: "#/$defs/manifest";
|
|
694
743
|
};
|
|
744
|
+
readonly approved: {
|
|
745
|
+
readonly type: "boolean";
|
|
746
|
+
readonly description: "Standing tool authorization for this exact autonomous revision.";
|
|
747
|
+
};
|
|
748
|
+
readonly max_credits: {
|
|
749
|
+
readonly type: "number";
|
|
750
|
+
readonly exclusiveMinimum: 0;
|
|
751
|
+
readonly description: "Hard credit ceiling for each autonomous delivery.";
|
|
752
|
+
};
|
|
695
753
|
};
|
|
696
754
|
readonly required: readonly ["manifest"];
|
|
697
755
|
readonly $defs: {
|
|
@@ -827,9 +885,63 @@ export declare function getWorkflowSchema(subject?: "apply" | "call" | "event" |
|
|
|
827
885
|
};
|
|
828
886
|
};
|
|
829
887
|
};
|
|
888
|
+
export declare function validateTrigger(// skipcq: JS-R1005
|
|
889
|
+
value: unknown, path: string, add: (path: string, code: string, message: string) => void): void;
|
|
890
|
+
export declare function validatePureFunctionSource(source: string, path: string, add: (path: string, code: string, message: string) => void): void;
|
|
891
|
+
export declare function isWorkflowToolRejected(toolId: string): boolean;
|
|
830
892
|
export declare function computeWorkflowPlanHash(input: Record<string, unknown>): string;
|
|
831
893
|
export declare const WORKFLOW_MAX_CREDITS_EXCEEDED_ERROR_CODE = "max_credits_exceeded";
|
|
832
894
|
export declare function readWorkflowRunMaxCredits(metadata: Record<string, unknown> | null | undefined): number | null;
|
|
895
|
+
export declare const WORKFLOW_STANDING_AUTHORIZATION_METADATA_KEY = "standing_authorization";
|
|
896
|
+
export declare const WORKFLOW_STANDING_AUTHORIZATION_POLICY_METADATA_KEY = "standing_authorization_policy";
|
|
897
|
+
export declare const WORKFLOW_STANDING_AUTHORIZATION_POLICY_REVISION_BOUND_V1 = "revision_bound_v1";
|
|
898
|
+
export declare const WORKFLOW_STANDING_AUTHORIZATION_REQUIRED_ERROR_CODE = "workflow_standing_authorization_required";
|
|
899
|
+
export declare const WORKFLOW_STANDING_AUTHORIZATION_REQUIRED_MESSAGE = "This autonomous workflow can call tools and needs standing authorization for its current revision. Re-enable it with approved=true; pass a positive max_credits per delivery or omit it to use the plan default.";
|
|
900
|
+
type WorkflowStandingAuthorizationBase = {
|
|
901
|
+
approved: true;
|
|
902
|
+
revisionId: string;
|
|
903
|
+
authorizedByActorId: string;
|
|
904
|
+
authorizedAt: string;
|
|
905
|
+
};
|
|
906
|
+
export type WorkflowStandingAuthorization = WorkflowStandingAuthorizationBase & ({
|
|
907
|
+
capPolicy: "explicit";
|
|
908
|
+
maxCredits: number;
|
|
909
|
+
} | {
|
|
910
|
+
capPolicy: "plan_default";
|
|
911
|
+
maxCredits: null;
|
|
912
|
+
});
|
|
913
|
+
export declare function isAutonomousWorkflowTriggerType(value: unknown): value is "cron" | "webhook" | "event";
|
|
914
|
+
/**
|
|
915
|
+
* Whether this manifest can cross into a tool at runtime. Hosted workflows are
|
|
916
|
+
* explicit in `steps`; oxygen-workflows-v2 graphs are explicit in `nodes`;
|
|
917
|
+
* durable recipes declare the complete allowlist in `tools_used`. Keeping this
|
|
918
|
+
* predicate structural means legacy revisions can be checked before execution
|
|
919
|
+
* without trusting trigger metadata.
|
|
920
|
+
*
|
|
921
|
+
* The v2 branch is load-bearing, not cosmetic: this predicate is the ONLY input
|
|
922
|
+
* to workflowRequiresStandingAuthorization, so a graph it does not recognise arms
|
|
923
|
+
* a cron / webhook / event trigger with no standing authorization and therefore
|
|
924
|
+
* no per-delivery credit ceiling. A `workflow` (sub-graph) node counts as well —
|
|
925
|
+
* a child run can invoke tools of its own, and the gate must fail closed.
|
|
926
|
+
*/
|
|
927
|
+
export declare function workflowManifestCanInvokeTool(manifest: unknown): boolean;
|
|
928
|
+
/** The single apply/enable/runtime gate for standing autonomous authority. */
|
|
929
|
+
export declare function workflowRequiresStandingAuthorization(manifest: unknown, triggerType?: unknown): boolean;
|
|
930
|
+
/**
|
|
931
|
+
* Runtime enforcement marker for triggers created or explicitly re-armed after
|
|
932
|
+
* revision-bound standing authority shipped. Legacy active triggers have no
|
|
933
|
+
* marker and stay runnable during the default-ceiling compatibility rollout;
|
|
934
|
+
* every new/re-armed tool trigger carries this marker and fails closed if its
|
|
935
|
+
* matching authorization is missing or stale.
|
|
936
|
+
*/
|
|
937
|
+
export declare function workflowStandingAuthorizationPolicyIsEnforced(metadata: Record<string, unknown> | null | undefined, triggerDefaultCapsMode?: unknown): boolean;
|
|
938
|
+
/**
|
|
939
|
+
* Read the standing authority for one autonomous trigger revision. A null
|
|
940
|
+
* result is fail-closed for policy-marked triggers. Legacy active rows
|
|
941
|
+
* are distinguished by the separate policy marker so they can continue under
|
|
942
|
+
* the fire-time default-ceiling compatibility rollout.
|
|
943
|
+
*/
|
|
944
|
+
export declare function readWorkflowStandingAuthorization(metadata: Record<string, unknown> | null | undefined, revisionId: string): WorkflowStandingAuthorization | null;
|
|
833
945
|
export declare function readWorkflowRunPreApprovedLabels(metadata: Record<string, unknown> | null | undefined): string[];
|
|
834
946
|
export declare function readManagedToolRunCredits(output: unknown): number;
|
|
835
947
|
export type WorkflowSpendCapDecision = {
|