@oxygen-agent/cli 1.750.4 → 1.782.1

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 (55) hide show
  1. package/README.md +1 -1
  2. package/dist/command-manifest.js +11 -1
  3. package/dist/help.js +8 -0
  4. package/dist/index.js +492 -96
  5. package/node_modules/@oxygen/shared/dist/billing.d.ts +88 -46
  6. package/node_modules/@oxygen/shared/dist/billing.js +134 -74
  7. package/node_modules/@oxygen/shared/dist/capability-discovery.js +12 -4
  8. package/node_modules/@oxygen/shared/dist/cli-result.js +1 -0
  9. package/node_modules/@oxygen/shared/dist/copilot-journeys.d.ts +8 -0
  10. package/node_modules/@oxygen/shared/dist/copilot-journeys.js +23 -5
  11. package/node_modules/@oxygen/shared/dist/future-signup-events.d.ts +13 -2
  12. package/node_modules/@oxygen/shared/dist/future-signup-events.js +17 -2
  13. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.d.ts +106 -1
  14. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.js +156 -45
  15. package/node_modules/@oxygen/shared/dist/index.d.ts +5 -0
  16. package/node_modules/@oxygen/shared/dist/index.js +5 -0
  17. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +33 -0
  18. package/node_modules/@oxygen/shared/dist/object-storage.js +69 -4
  19. package/node_modules/@oxygen/shared/dist/person-name.d.ts +40 -0
  20. package/node_modules/@oxygen/shared/dist/person-name.js +23 -0
  21. package/node_modules/@oxygen/shared/dist/plan-capabilities.d.ts +82 -0
  22. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +130 -0
  23. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +2 -2
  24. package/node_modules/@oxygen/shared/dist/plan-limits.js +18 -2
  25. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +50 -56
  26. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +77 -90
  27. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +62 -0
  28. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +91 -0
  29. package/node_modules/@oxygen/shared/dist/provider-funding-errors.d.ts +44 -0
  30. package/node_modules/@oxygen/shared/dist/provider-funding-errors.js +81 -0
  31. package/node_modules/@oxygen/shared/dist/publishing-limits.d.ts +24 -0
  32. package/node_modules/@oxygen/shared/dist/publishing-limits.js +24 -0
  33. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +27 -6
  34. package/node_modules/@oxygen/shared/dist/spend-safety.js +34 -6
  35. package/node_modules/@oxygen/shared/dist/table-capacity.d.ts +13 -0
  36. package/node_modules/@oxygen/shared/dist/table-capacity.js +14 -0
  37. package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
  38. package/node_modules/@oxygen/shared/dist/version.js +6 -3
  39. package/node_modules/@oxygen/shared/package.json +10 -0
  40. package/node_modules/@oxygen/workflows/dist/graph/diff.d.ts +33 -0
  41. package/node_modules/@oxygen/workflows/dist/graph/diff.js +75 -0
  42. package/node_modules/@oxygen/workflows/dist/graph/expression.js +17 -1
  43. package/node_modules/@oxygen/workflows/dist/graph/index.d.ts +1 -0
  44. package/node_modules/@oxygen/workflows/dist/graph/index.js +1 -0
  45. package/node_modules/@oxygen/workflows/dist/graph/lint.js +30 -28
  46. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +2 -2
  47. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.js +1 -1
  48. package/node_modules/@oxygen/workflows/dist/graph/remap.js +0 -5
  49. package/node_modules/@oxygen/workflows/dist/graph/topology.d.ts +27 -0
  50. package/node_modules/@oxygen/workflows/dist/graph/topology.js +95 -0
  51. package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +27 -8
  52. package/node_modules/@oxygen/workflows/dist/graph/types.js +2 -4
  53. package/node_modules/@oxygen/workflows/dist/index.js +0 -1
  54. package/node_modules/@oxygen/workflows/dist/portable.js +0 -9
  55. package/package.json +1 -1
@@ -282,6 +282,101 @@ export function dominatingNodeIds(graph, targetNodeId) {
282
282
  }
283
283
  return dominators.get(targetNodeId) ?? new Set();
284
284
  }
285
+ /** Add every forward-graph predecessor of `startIds` to `selected`. */
286
+ function addForwardAncestors(startIds, incoming, selected) {
287
+ const queue = [...startIds];
288
+ let changed = false;
289
+ while (queue.length > 0) {
290
+ const current = queue.pop();
291
+ if (current === undefined || selected.has(current))
292
+ continue;
293
+ selected.add(current);
294
+ changed = true;
295
+ for (const predecessor of incoming.get(current) ?? [])
296
+ queue.push(predecessor);
297
+ }
298
+ return changed;
299
+ }
300
+ /**
301
+ * Plan a safe selected-node test over the canonical graph.
302
+ *
303
+ * The slice contains the target and every possible predecessor, not every node
304
+ * that happens to appear earlier in topological order. Legal loop back-edges are
305
+ * ignored while finding predecessors so selecting a node halfway through a loop
306
+ * does not accidentally pull later body nodes into the test. Conversely, when a
307
+ * completed loop is upstream of the target (or is itself the target), its whole
308
+ * body is required because the loop's output includes those executions.
309
+ */
310
+ export function planWorkflowGraphNodeTest(graph, targetNodeId) {
311
+ const nodes = nodeIndex(graph);
312
+ const target = nodes.get(targetNodeId);
313
+ if (!target) {
314
+ return {
315
+ ok: false,
316
+ code: "workflow_test_target_not_found",
317
+ message: `Workflow node '${targetNodeId}' does not exist in this revision.`,
318
+ };
319
+ }
320
+ if (isTriggerNode(target)) {
321
+ return {
322
+ ok: false,
323
+ code: "workflow_test_target_is_trigger",
324
+ message: "Choose an executable workflow step, not the trigger node.",
325
+ };
326
+ }
327
+ if (target.disabled === true) {
328
+ return {
329
+ ok: false,
330
+ code: "workflow_test_target_disabled",
331
+ message: `Workflow node '${targetNodeId}' is disabled and cannot be tested.`,
332
+ };
333
+ }
334
+ if (!reachableNodeIds(graph).has(targetNodeId)) {
335
+ return {
336
+ ok: false,
337
+ code: "workflow_test_target_unreachable",
338
+ message: `Workflow node '${targetNodeId}' is not reachable from the trigger.`,
339
+ };
340
+ }
341
+ const forward = forwardOutgoing(graph);
342
+ const incoming = new Map();
343
+ for (const id of nodes.keys())
344
+ incoming.set(id, []);
345
+ for (const [source, edges] of forward) {
346
+ for (const edge of edges)
347
+ incoming.get(edge.target)?.push(source);
348
+ }
349
+ const selected = new Set();
350
+ addForwardAncestors([targetNodeId], incoming, selected);
351
+ const loopBodies = graph.nodes
352
+ .filter(isLoopNode)
353
+ .map((loop) => ({ loop, body: loopBodyNodeIds(graph, loop.id) }));
354
+ let expanded = true;
355
+ while (expanded) {
356
+ expanded = false;
357
+ for (const { loop, body } of loopBodies) {
358
+ if (!selected.has(loop.id) || body.has(targetNodeId))
359
+ continue;
360
+ if (addForwardAncestors(body, incoming, selected))
361
+ expanded = true;
362
+ }
363
+ }
364
+ const nodeIds = graph.nodes
365
+ .map((node) => node.id)
366
+ .filter((id) => selected.has(id));
367
+ return {
368
+ ok: true,
369
+ plan: {
370
+ targetNodeId,
371
+ nodeIds,
372
+ manifest: {
373
+ ...graph,
374
+ nodes: graph.nodes.filter((node) => selected.has(node.id)),
375
+ edges: graph.edges.filter((edge) => selected.has(edge.source) && selected.has(edge.target)),
376
+ },
377
+ },
378
+ };
379
+ }
285
380
  /**
286
381
  * Illegal cycles: one entry per strongly connected component that still contains
287
382
  * a cycle once legal loop back-edges are removed.
@@ -3,6 +3,32 @@ export declare const WORKFLOW_GRAPH_MANIFEST_VERSION = 2;
3
3
  export declare const WORKFLOW_GRAPH_COMPILER_VERSION = "oxygen-workflows-v2";
4
4
  export declare const PORTABLE_WORKFLOW_DEFINITION_VERSION = 1;
5
5
  export declare const PORTABLE_WORKFLOW_DEFINITION_COMPILER_VERSION = "oxygen-workflow-definition-v1";
6
+ /** Source-run metadata key for the exact non-live graph scope a test executed. */
7
+ export declare const WORKFLOW_TEST_SCOPE_METADATA_KEY = "workflow_test_scope";
8
+ /**
9
+ * Optional execution scope for a non-live Workflow call.
10
+ *
11
+ * Omission keeps the historic whole-workflow behavior. A node scope is a
12
+ * server-planned backward slice of the same immutable graph revision; callers
13
+ * never submit a second graph or a list of nodes to trust.
14
+ */
15
+ export type WorkflowTestScope = {
16
+ type: "workflow";
17
+ } | {
18
+ type: "node";
19
+ node_id: string;
20
+ };
21
+ /** Durable evidence recorded on the source run after the server plans a test. */
22
+ export type WorkflowTestScopeReceipt = WorkflowTestScope & {
23
+ source_hash: string;
24
+ planned_node_ids: string[];
25
+ /**
26
+ * The nodes this scope deliberately excludes. Recorded so "the downstream step
27
+ * did not run" is something the product states, not something a reader infers
28
+ * from a missing row in the step list.
29
+ */
30
+ excluded_node_ids?: string[];
31
+ };
6
32
  export declare const RESERVED_NODE_IDS: ReadonlySet<string>;
7
33
  /**
8
34
  * Named Code inputs and declared output fields become dotted scope paths and
@@ -356,13 +382,7 @@ export type WorkflowGraphNode =
356
382
  request?: Record<string, WorkflowValueRef>;
357
383
  })
358
384
  /** Legacy source, imported durable recipe, or typed oxygen-js-v1 code. */
359
- | WorkflowGraphCodeNode
360
- /** Calls another workflow as a child run. */
361
- | (WorkflowGraphNodeBase & {
362
- kind: "workflow";
363
- workflow_id: string;
364
- input: Record<string, WorkflowValueRef>;
365
- });
385
+ | WorkflowGraphCodeNode;
366
386
  export type WorkflowGraphNodeKind = WorkflowGraphNode["kind"];
367
387
  /** Narrow a node union member by its `kind` discriminant. */
368
388
  export type WorkflowGraphNodeOfKind<K extends WorkflowGraphNodeKind> = Extract<WorkflowGraphNode, {
@@ -455,5 +475,4 @@ export declare function isTriggerNode(node: WorkflowGraphNode): node is Workflow
455
475
  export declare function isToolNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"tool">;
456
476
  export declare function isSwitchNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"switch">;
457
477
  export declare function isLoopNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"loop">;
458
- export declare function isWorkflowSubgraphNode(node: WorkflowGraphNode): node is WorkflowGraphNodeOfKind<"workflow">;
459
478
  export {};
@@ -2,6 +2,8 @@ export const WORKFLOW_GRAPH_MANIFEST_VERSION = 2;
2
2
  export const WORKFLOW_GRAPH_COMPILER_VERSION = "oxygen-workflows-v2";
3
3
  export const PORTABLE_WORKFLOW_DEFINITION_VERSION = 1;
4
4
  export const PORTABLE_WORKFLOW_DEFINITION_COMPILER_VERSION = "oxygen-workflow-definition-v1";
5
+ /** Source-run metadata key for the exact non-live graph scope a test executed. */
6
+ export const WORKFLOW_TEST_SCOPE_METADATA_KEY = "workflow_test_scope";
5
7
  // Node ids become keys on the runtime scope object (`steps.<id>.output`), exactly
6
8
  // as v1 step ids become keys on ctx.steps. The same JavaScript-internals collision
7
9
  // applies: a node named `__proto__` would silently lose its output.
@@ -63,7 +65,6 @@ export const MAX_WORKFLOW_LOOP_ITERATIONS = 1_000;
63
65
  */
64
66
  export const BILLABLE_WORKFLOW_GRAPH_NODE_KINDS = new Set([
65
67
  "tool",
66
- "workflow",
67
68
  ]);
68
69
  /** Whether a v2 node of this kind draws an automation action when it executes. */
69
70
  export function workflowGraphNodeKindBills(kind) {
@@ -159,6 +160,3 @@ export function isSwitchNode(node) {
159
160
  export function isLoopNode(node) {
160
161
  return isNodeOfKind(node, "loop");
161
162
  }
162
- export function isWorkflowSubgraphNode(node) {
163
- return isNodeOfKind(node, "workflow");
164
- }
@@ -1938,7 +1938,6 @@ export function workflowManifestCanInvokeTool(manifest) {
1938
1938
  && manifest.tools_used.some((toolId) => isNonEmptyString(toolId));
1939
1939
  const viaGraph = Array.isArray(manifest.nodes)
1940
1940
  && manifest.nodes.some((node) => isRecord(node) && (node.kind === "tool"
1941
- || node.kind === "workflow"
1942
1941
  || (isRecord(node.recipe)
1943
1942
  && Array.isArray(node.recipe.tools_used)
1944
1943
  && node.recipe.tools_used.some((toolId) => isNonEmptyString(toolId)))));
@@ -69,13 +69,6 @@ function portableNodeIssue(node, index) {
69
69
  message: "Legacy execution context cannot be represented as a portable editable graph.",
70
70
  };
71
71
  }
72
- if (node.kind === "workflow") {
73
- return {
74
- path: `$.graph.nodes.${index}`,
75
- code: "workflow_node_not_portable",
76
- message: "Child-workflow nodes are not executable yet and cannot be exported as a portable definition.",
77
- };
78
- }
79
72
  return null;
80
73
  }
81
74
  function valueRefUsesWorkspaceAsset(ref) {
@@ -114,8 +107,6 @@ function nodeUsesWorkspaceAsset(node) {
114
107
  return node.code !== undefined
115
108
  ? Object.values(node.code.inputs).some(valueRefUsesWorkspaceAsset)
116
109
  : Object.values(node.configuration ?? {}).some(valueRefUsesWorkspaceAsset);
117
- case "workflow":
118
- return Object.values(node.input).some(valueRefUsesWorkspaceAsset);
119
110
  case "trigger":
120
111
  case "merge":
121
112
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxygen-agent/cli",
3
- "version": "1.750.4",
3
+ "version": "1.782.1",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",