@oxygen-agent/cli 1.365.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.
Files changed (99) hide show
  1. package/README.md +1 -1
  2. package/dist/column-run-notices.d.ts +11 -0
  3. package/dist/column-run-notices.js +37 -0
  4. package/dist/command-manifest.js +13 -8
  5. package/dist/help.js +78 -16
  6. package/dist/index.js +3873 -514
  7. package/dist/skills.js +106 -1
  8. package/node_modules/@oxygen/formula/dist/coerce.d.ts +8 -0
  9. package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
  10. package/node_modules/@oxygen/formula/dist/evaluate.d.ts +31 -0
  11. package/node_modules/@oxygen/formula/dist/evaluate.js +248 -0
  12. package/node_modules/@oxygen/formula/dist/expression.d.ts +64 -0
  13. package/node_modules/@oxygen/formula/dist/expression.js +428 -0
  14. package/node_modules/@oxygen/formula/dist/formula-functions.d.ts +71 -0
  15. package/node_modules/@oxygen/formula/dist/formula-functions.js +1100 -0
  16. package/node_modules/@oxygen/formula/dist/index.d.ts +17 -0
  17. package/node_modules/@oxygen/formula/dist/index.js +17 -0
  18. package/node_modules/@oxygen/formula/dist/value-normalizers.d.ts +30 -0
  19. package/node_modules/@oxygen/formula/dist/value-normalizers.js +80 -0
  20. package/node_modules/@oxygen/formula/package.json +26 -0
  21. package/node_modules/@oxygen/recipe-sdk/dist/index.d.ts +30 -0
  22. package/node_modules/@oxygen/recipe-sdk/dist/index.js +2 -2
  23. package/node_modules/@oxygen/shared/dist/billing-anchors.d.ts +60 -0
  24. package/node_modules/@oxygen/shared/dist/billing-anchors.js +135 -0
  25. package/node_modules/@oxygen/shared/dist/billing.d.ts +101 -5
  26. package/node_modules/@oxygen/shared/dist/billing.js +192 -8
  27. package/node_modules/@oxygen/shared/dist/call-outcomes.d.ts +59 -0
  28. package/node_modules/@oxygen/shared/dist/call-outcomes.js +73 -0
  29. package/node_modules/@oxygen/shared/dist/cli-result.js +1 -0
  30. package/node_modules/@oxygen/shared/dist/credit-guidance.js +3 -1
  31. package/node_modules/@oxygen/shared/dist/crm-reply-events.d.ts +35 -0
  32. package/node_modules/@oxygen/shared/dist/crm-reply-events.js +31 -0
  33. package/node_modules/@oxygen/shared/dist/dial-guardrail-overrides.d.ts +50 -0
  34. package/node_modules/@oxygen/shared/dist/dial-guardrail-overrides.js +65 -0
  35. package/node_modules/@oxygen/shared/dist/directory.d.ts +1 -1
  36. package/node_modules/@oxygen/shared/dist/directory.js +1 -0
  37. package/node_modules/@oxygen/shared/dist/hosted-ai.d.ts +17 -1
  38. package/node_modules/@oxygen/shared/dist/hosted-ai.js +52 -3
  39. package/node_modules/@oxygen/shared/dist/index.d.ts +11 -0
  40. package/node_modules/@oxygen/shared/dist/index.js +15 -0
  41. package/node_modules/@oxygen/shared/dist/langfuse.d.ts +77 -0
  42. package/node_modules/@oxygen/shared/dist/langfuse.js +231 -0
  43. package/node_modules/@oxygen/shared/dist/linkedin-quota-denial.d.ts +31 -0
  44. package/node_modules/@oxygen/shared/dist/linkedin-quota-denial.js +56 -0
  45. package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +5 -4
  46. package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +5 -4
  47. package/node_modules/@oxygen/shared/dist/linkedin-url.d.ts +22 -0
  48. package/node_modules/@oxygen/shared/dist/linkedin-url.js +7 -4
  49. package/node_modules/@oxygen/shared/dist/log.js +56 -4
  50. package/node_modules/@oxygen/shared/dist/microsoft-consent-url.d.ts +7 -0
  51. package/node_modules/@oxygen/shared/dist/microsoft-consent-url.js +29 -0
  52. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +31 -0
  53. package/node_modules/@oxygen/shared/dist/object-storage.js +61 -0
  54. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +636 -0
  55. package/node_modules/@oxygen/shared/dist/plan-limits.js +199 -0
  56. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +89 -23
  57. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +88 -24
  58. package/node_modules/@oxygen/shared/dist/sequence-crm-events.d.ts +291 -0
  59. package/node_modules/@oxygen/shared/dist/sequence-crm-events.js +224 -0
  60. package/node_modules/@oxygen/shared/dist/sequence-template.d.ts +42 -1
  61. package/node_modules/@oxygen/shared/dist/sequence-template.js +0 -0
  62. package/node_modules/@oxygen/shared/dist/sequences.d.ts +287 -24
  63. package/node_modules/@oxygen/shared/dist/sequences.js +940 -60
  64. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +70 -0
  65. package/node_modules/@oxygen/shared/dist/spend-safety.js +106 -0
  66. package/node_modules/@oxygen/shared/dist/tags.d.ts +90 -1
  67. package/node_modules/@oxygen/shared/dist/tags.js +126 -6
  68. package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
  69. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  70. package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.d.ts +1 -1
  71. package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.js +4 -0
  72. package/node_modules/@oxygen/shared/dist/workspace-agents.d.ts +8 -7
  73. package/node_modules/@oxygen/shared/dist/workspace-agents.js +34 -7
  74. package/node_modules/@oxygen/shared/package.json +95 -0
  75. package/node_modules/@oxygen/workflows/dist/event-dispatch.d.ts +126 -0
  76. package/node_modules/@oxygen/workflows/dist/event-dispatch.js +173 -0
  77. package/node_modules/@oxygen/workflows/dist/graph/expression.d.ts +78 -0
  78. package/node_modules/@oxygen/workflows/dist/graph/expression.js +700 -0
  79. package/node_modules/@oxygen/workflows/dist/graph/index.d.ts +20 -0
  80. package/node_modules/@oxygen/workflows/dist/graph/index.js +20 -0
  81. package/node_modules/@oxygen/workflows/dist/graph/lint.d.ts +4 -0
  82. package/node_modules/@oxygen/workflows/dist/graph/lint.js +812 -0
  83. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +501 -0
  84. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.js +200 -0
  85. package/node_modules/@oxygen/workflows/dist/graph/params.d.ts +86 -0
  86. package/node_modules/@oxygen/workflows/dist/graph/params.js +173 -0
  87. package/node_modules/@oxygen/workflows/dist/graph/remap.d.ts +48 -0
  88. package/node_modules/@oxygen/workflows/dist/graph/remap.js +213 -0
  89. package/node_modules/@oxygen/workflows/dist/graph/topology.d.ts +46 -0
  90. package/node_modules/@oxygen/workflows/dist/graph/topology.js +280 -0
  91. package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +270 -0
  92. package/node_modules/@oxygen/workflows/dist/graph/types.js +93 -0
  93. package/node_modules/@oxygen/workflows/dist/index.d.ts +113 -1
  94. package/node_modules/@oxygen/workflows/dist/index.js +179 -13
  95. package/node_modules/@oxygen/workflows/dist/tool-effects.d.ts +1 -0
  96. package/node_modules/@oxygen/workflows/dist/tool-effects.js +19 -0
  97. package/node_modules/@oxygen/workflows/dist/usage-estimate.js +135 -4
  98. package/node_modules/@oxygen/workflows/package.json +4 -0
  99. package/package.json +10 -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 = {