@lunnoa/client 2.3.0 → 2.4.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/README.md CHANGED
@@ -264,7 +264,7 @@ npx @lunnoa/client agents deploy ./agents/triage.ts \
264
264
  --url https://lunnoa.example --api-key lna_...
265
265
  ```
266
266
 
267
- `defineAction` binds catalogue actions only; toolkit `createAction` is for in-platform apps. `defineWorkflow` takes an optional `defineTrigger`. Omit it for Manually Run with no input fields. `runs.start` ignores the trigger and runs the steps only. See Lunnoa Docs under `guides/develop/client/define`, `runs`, and `cli-deploy`.
267
+ `defineAction` binds catalogue actions only; toolkit `createAction` is for in-platform apps. `defineWorkflow` takes an optional `defineTrigger`. Omit it for Manually Run with no input fields. `runs.start` ignores the trigger and runs the steps only. Pass data into step settings with `ref.trigger('caseId')` or `ref.step('load', 'rows', 0)` (give the source step a `key`); the server resolves them on deploy and the builder shows them as mapped fields. See Lunnoa Docs under `guides/develop/client/define`, `runs`, and `cli-deploy`.
268
268
 
269
269
  ### CLI discovery
270
270
 
package/dist/cli.js CHANGED
@@ -1810,7 +1810,9 @@ function stepFromDefinition(step) {
1810
1810
  ...use.input ?? {},
1811
1811
  ...step.input ?? {}
1812
1812
  };
1813
+ const key = step.key;
1813
1814
  return {
1815
+ ...key ? { key } : {},
1814
1816
  appId: resolveActionAppId(use),
1815
1817
  actionId: resolveActionId(use),
1816
1818
  ...use.connection?.id ? { connectionId: use.connection.id } : {},
@@ -2026,6 +2028,7 @@ function triggerToUpsertInput(trigger) {
2026
2028
  function stepToUpsertInput(step) {
2027
2029
  const use = step.use;
2028
2030
  return {
2031
+ ...step.key ? { key: step.key } : {},
2029
2032
  appId: resolveActionAppId(use),
2030
2033
  actionId: resolveActionId(use),
2031
2034
  connectionId: use.connection?.id,
package/dist/index.cjs CHANGED
@@ -563,7 +563,7 @@ function assertTriggerConfig(config) {
563
563
  throw new Error("defineTrigger inputs require id");
564
564
  }
565
565
  }
566
- if (config.inputs?.length && config.id.trim() !== "flow-control_trigger_manual") {
566
+ if (config.inputs?.length && config.id.trim() !== MANUAL_TRIGGER_ID) {
567
567
  throw new Error(
568
568
  "defineTrigger inputs are only valid on flow-control_trigger_manual"
569
569
  );
@@ -573,6 +573,73 @@ function defineTrigger(config) {
573
573
  assertTriggerConfig(config);
574
574
  return { kind: DEFINE_KINDS.trigger, ...config };
575
575
  }
576
+ var MANUAL_TRIGGER_ID = "flow-control_trigger_manual";
577
+ var TRIGGER_KEY = "trigger";
578
+ var STEP_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;
579
+ var STEP_REF_PATTERN = /={{step:([^}]*)}}/g;
580
+ function refString(key, path) {
581
+ const parts = [key, ...path.map(String)];
582
+ for (const part of parts) {
583
+ if (!part || /[,{}]/.test(part)) {
584
+ throw new Error(`ref path parts must be non-empty and contain no , { or }: "${part}"`);
585
+ }
586
+ }
587
+ return `={{step:${parts.join(",")}}}`;
588
+ }
589
+ var ref = {
590
+ /** A trigger output field, e.g. a Manually Run input id. */
591
+ trigger: (field, ...path) => refString(TRIGGER_KEY, [field, ...path]),
592
+ /** An earlier step's output, by its `key`. Array indexes are numbers. */
593
+ step: (key, ...path) => refString(key, path)
594
+ };
595
+ function collectRefs(value, out) {
596
+ if (typeof value === "string") {
597
+ for (const match of value.matchAll(STEP_REF_PATTERN)) {
598
+ out.push(match[1].split(",").map((part) => part.trim()));
599
+ }
600
+ } else if (Array.isArray(value)) {
601
+ value.forEach((item) => collectRefs(item, out));
602
+ } else if (value && typeof value === "object") {
603
+ Object.values(value).forEach((item) => collectRefs(item, out));
604
+ }
605
+ }
606
+ function assertStepRefs(config) {
607
+ const triggerId = config.trigger?.id.trim() ?? MANUAL_TRIGGER_ID;
608
+ const triggerFields = triggerId === MANUAL_TRIGGER_ID ? new Set((config.trigger?.inputs ?? []).map((f) => f.id.trim())) : void 0;
609
+ const allKeys = /* @__PURE__ */ new Set();
610
+ for (const step of config.steps) {
611
+ if (step.key === void 0) continue;
612
+ if (!STEP_KEY_PATTERN.test(step.key) || step.key === TRIGGER_KEY) {
613
+ throw new Error(
614
+ `Step key "${step.key}" must start with a letter, use letters, digits, - or _, and not be "${TRIGGER_KEY}".`
615
+ );
616
+ }
617
+ if (allKeys.has(step.key)) {
618
+ throw new Error(`Step key "${step.key}" is used twice.`);
619
+ }
620
+ allKeys.add(step.key);
621
+ }
622
+ const earlier = /* @__PURE__ */ new Set([TRIGGER_KEY]);
623
+ config.steps.forEach((step, index) => {
624
+ const refs = [];
625
+ collectRefs([step.use?.input, step.input], refs);
626
+ const where = `Step "${step.key ?? step.name ?? index + 1}"`;
627
+ for (const [key = "", ...path] of refs) {
628
+ const shown = `={{step:${[key, ...path].join(",")}}}`;
629
+ if (!earlier.has(key)) {
630
+ throw new Error(
631
+ allKeys.has(key) ? `${where}: ${shown} refers to itself or a later step. Use the trigger or an earlier step.` : `${where}: ${shown} names unknown key "${key}". Use "trigger" or an earlier step's key.`
632
+ );
633
+ }
634
+ if (key === TRIGGER_KEY && triggerFields && !triggerFields.has(path[0] ?? "")) {
635
+ throw new Error(
636
+ `${where}: ${shown} uses trigger field "${path[0] ?? ""}", which is not declared in trigger inputs.`
637
+ );
638
+ }
639
+ }
640
+ if (step.key) earlier.add(step.key);
641
+ });
642
+ }
576
643
  function defineWorkflow(config) {
577
644
  if (!config.slug?.trim()) {
578
645
  throw new Error("defineWorkflow requires slug");
@@ -583,6 +650,7 @@ function defineWorkflow(config) {
583
650
  if (config.trigger) {
584
651
  assertTriggerConfig(config.trigger);
585
652
  }
653
+ assertStepRefs(config);
586
654
  return { kind: DEFINE_KINDS.workflow, ...config };
587
655
  }
588
656
  function defineAgent(config) {
@@ -1874,7 +1942,9 @@ function stepFromDefinition(step) {
1874
1942
  ...use.input ?? {},
1875
1943
  ...step.input ?? {}
1876
1944
  };
1945
+ const key = step.key;
1877
1946
  return {
1947
+ ...key ? { key } : {},
1878
1948
  appId: resolveActionAppId(use),
1879
1949
  actionId: resolveActionId(use),
1880
1950
  ...use.connection?.id ? { connectionId: use.connection.id } : {},
@@ -2090,6 +2160,7 @@ function triggerToUpsertInput(trigger) {
2090
2160
  function stepToUpsertInput(step) {
2091
2161
  const use = step.use;
2092
2162
  return {
2163
+ ...step.key ? { key: step.key } : {},
2093
2164
  appId: resolveActionAppId(use),
2094
2165
  actionId: resolveActionId(use),
2095
2166
  connectionId: use.connection?.id,
@@ -2355,6 +2426,7 @@ exports.iterateOffset = iterateOffset;
2355
2426
  exports.iteratePages = iteratePages;
2356
2427
  exports.parseSseEvents = parseSseEvents;
2357
2428
  exports.parseSseStream = parseSseStream;
2429
+ exports.ref = ref;
2358
2430
  exports.resolveActionAppId = resolveActionAppId;
2359
2431
  exports.resolveActionId = resolveActionId;
2360
2432
  exports.resolveTriggerAppId = resolveTriggerAppId;