@lunnoa/client 2.2.0 → 2.3.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. 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. See Lunnoa Docs under `guides/develop/client/define`, `runs`, and `cli-deploy`.
268
268
 
269
269
  ### CLI discovery
270
270
 
@@ -284,7 +284,7 @@ npx @lunnoa/client entity-types list --json
284
284
  npx @lunnoa/client features --json
285
285
  ```
286
286
 
287
- `tools list` is compact (`appId`, `actionId`, name, flags). `tools get` prints `inputConfig` and a `defineAction({ id, appId, input })` sketch. `ai-connections list --json` prints the model ids each AI connection accepts; use `models[].id` as `defineAgent({ model })`. Auth flags and `LUNNOA_URL` / `LUNNOA_API_KEY` / `lunnoa.config` work the same as deploy. The CLI also reads `./.env` (real environment variables win).
287
+ `tools list` is compact (`appId`, `actionId`, name, flags). `tools get` prints `inputConfig` and a `defineAction({ id, appId, input })` sketch. `apps get --json` includes each trigger and a `defineTrigger` sketch. Use `triggers[].triggerId`. Do not invent trigger ids. `ai-connections list --json` prints the model ids each AI connection accepts; use `models[].id` as `defineAgent({ model })`. Auth flags and `LUNNOA_URL` / `LUNNOA_API_KEY` / `lunnoa.config` work the same as deploy. The CLI also reads `./.env` (real environment variables win).
288
288
 
289
289
  ## Regenerating the API types
290
290
 
package/dist/cli.js CHANGED
@@ -541,6 +541,7 @@ var DEFINE_KINDS = {
541
541
  connection: "connection",
542
542
  aiConnection: "aiConnection",
543
543
  action: "action",
544
+ trigger: "trigger",
544
545
  workflow: "workflow",
545
546
  agent: "agent",
546
547
  entityType: "entityType"
@@ -563,6 +564,40 @@ function resolveActionAppId(action) {
563
564
  `Cannot infer appId for action "${id}". Pass appId explicitly.`
564
565
  );
565
566
  }
567
+ function resolveTriggerAppId(trigger) {
568
+ if (trigger.appId?.trim()) {
569
+ return trigger.appId.trim();
570
+ }
571
+ const id = trigger.id.trim();
572
+ const marker = "_trigger_";
573
+ const markerIndex = id.indexOf(marker);
574
+ if (markerIndex > 0) {
575
+ return id.slice(0, markerIndex);
576
+ }
577
+ const dot = id.indexOf(".");
578
+ if (dot > 0) {
579
+ return id.slice(0, dot);
580
+ }
581
+ throw new Error(
582
+ `Cannot infer appId for trigger "${id}". Pass appId explicitly.`
583
+ );
584
+ }
585
+ function resolveTriggerId(trigger) {
586
+ const id = trigger.id.trim();
587
+ const appId = trigger.appId?.trim();
588
+ if (appId && id.startsWith(`${appId}.`)) {
589
+ return id.slice(appId.length + 1);
590
+ }
591
+ const marker = "_trigger_";
592
+ if (id.includes(marker)) {
593
+ return id;
594
+ }
595
+ const dot = id.indexOf(".");
596
+ if (dot > 0) {
597
+ return id.slice(dot + 1);
598
+ }
599
+ return id;
600
+ }
566
601
  function resolveActionId(action) {
567
602
  const id = action.id.trim();
568
603
  const appId = action.appId?.trim();
@@ -1977,6 +2012,17 @@ var WorkflowAppsResource = class {
1977
2012
  };
1978
2013
 
1979
2014
  // src/resources/workflows.ts
2015
+ function triggerToUpsertInput(trigger) {
2016
+ return {
2017
+ triggerId: resolveTriggerId(trigger),
2018
+ appId: resolveTriggerAppId(trigger),
2019
+ ...trigger.connection?.id ? { connectionId: trigger.connection.id } : {},
2020
+ ...trigger.input ? { input: trigger.input } : {},
2021
+ ...trigger.inputs?.length ? { inputs: trigger.inputs } : {},
2022
+ ...trigger.name ? { name: trigger.name } : {},
2023
+ ...trigger.description ? { description: trigger.description } : {}
2024
+ };
2025
+ }
1980
2026
  function stepToUpsertInput(step) {
1981
2027
  const use = step.use;
1982
2028
  return {
@@ -1997,6 +2043,7 @@ function workflowDefinitionToUpsert(def) {
1997
2043
  name: def.name,
1998
2044
  description: def.description,
1999
2045
  isActive: def.isActive,
2046
+ ...def.trigger ? { trigger: triggerToUpsertInput(def.trigger) } : {},
2000
2047
  managedByCode: true,
2001
2048
  steps: def.steps.map(stepToUpsertInput)
2002
2049
  };
@@ -2264,7 +2311,8 @@ ai-connections list prints the model ids each AI connection accepts. Use
2264
2311
  models[].id as defineAgent({ model }). connections list is app connections
2265
2312
  (Gmail, HTTP), not model providers.
2266
2313
  tools get prints inputConfig and a defineAction() sketch. tools list is compact;
2267
- run tools get for the schema. An entity-type slug is unique on the deployment
2314
+ run tools get for the schema. apps get --json includes triggers and a
2315
+ defineTrigger() sketch. Do not invent trigger ids. An entity-type slug is unique on the deployment
2268
2316
  and grants the API key's workspace when the slug is new.
2269
2317
  A slug already granted to other workspaces is not rewritten. Unknown instance attributes are rejected unless
2270
2318
  allowUnknownAttributes is true; use extensions.
@@ -2277,6 +2325,32 @@ function asRecord(value) {
2277
2325
  }
2278
2326
  return void 0;
2279
2327
  }
2328
+ function flattenTriggers(apps) {
2329
+ const out = [];
2330
+ for (const app of apps) {
2331
+ const appId = typeof app.id === "string" ? app.id : "";
2332
+ if (!appId) {
2333
+ continue;
2334
+ }
2335
+ const triggers = Array.isArray(app.triggers) ? app.triggers : [];
2336
+ for (const raw of triggers) {
2337
+ const trigger = asRecord(raw);
2338
+ if (!trigger || typeof trigger.id !== "string" || !trigger.id) {
2339
+ continue;
2340
+ }
2341
+ out.push({
2342
+ appId,
2343
+ appName: typeof app.name === "string" ? app.name : appId,
2344
+ triggerId: trigger.id,
2345
+ name: typeof trigger.name === "string" ? trigger.name : trigger.id,
2346
+ description: typeof trigger.description === "string" ? trigger.description : "",
2347
+ needsConnection: typeof trigger.needsConnection === "boolean" ? trigger.needsConnection : Boolean(app.needsConnection),
2348
+ inputConfig: trigger.inputConfig
2349
+ });
2350
+ }
2351
+ }
2352
+ return out;
2353
+ }
2280
2354
  function flattenActions(apps) {
2281
2355
  const out = [];
2282
2356
  for (const app of apps) {
@@ -2438,6 +2512,49 @@ function formatDefineActionSnippet(action) {
2438
2512
  "})"
2439
2513
  ].join("\n");
2440
2514
  }
2515
+ function formatDefineTriggerSnippet(trigger) {
2516
+ if (trigger.triggerId === "flow-control_trigger_manual") {
2517
+ return [
2518
+ "defineTrigger({",
2519
+ ` id: '${trigger.triggerId}',`,
2520
+ " // inputs become the Manually Run form (customInputConfig)",
2521
+ " inputs: [",
2522
+ " // { id, label, inputType, required }",
2523
+ " ],",
2524
+ "})"
2525
+ ].join("\n");
2526
+ }
2527
+ const fields = extractInputFields(trigger.inputConfig);
2528
+ const inputBlock = fields.length === 0 ? " // no inputConfig fields advertised" : fields.map((field) => {
2529
+ const notes = [
2530
+ field.label && field.label !== field.id ? field.label : void 0,
2531
+ field.type,
2532
+ field.required ? "required" : void 0
2533
+ ].filter(Boolean).join(", ");
2534
+ return notes ? ` // ${field.id} \u2014 ${notes}` : ` // ${field.id}`;
2535
+ }).join("\n");
2536
+ return [
2537
+ "defineTrigger({",
2538
+ ` id: '${trigger.triggerId}',`,
2539
+ ` appId: '${trigger.appId}',`,
2540
+ " input: {",
2541
+ inputBlock,
2542
+ " },",
2543
+ "})"
2544
+ ].join("\n");
2545
+ }
2546
+ function triggerDetail(trigger) {
2547
+ return {
2548
+ appId: trigger.appId,
2549
+ triggerId: trigger.triggerId,
2550
+ name: trigger.name,
2551
+ description: trigger.description,
2552
+ needsConnection: trigger.needsConnection,
2553
+ inputFields: extractInputFields(trigger.inputConfig),
2554
+ inputConfig: trigger.inputConfig ?? null,
2555
+ defineTrigger: formatDefineTriggerSnippet(trigger)
2556
+ };
2557
+ }
2441
2558
  function actionDetail(action) {
2442
2559
  return {
2443
2560
  ...summarizeAction(action),
@@ -2597,6 +2714,7 @@ async function runAppsGet(client, args) {
2597
2714
  throw new Error(`Unknown app "${appId}". Try: apps list`);
2598
2715
  }
2599
2716
  const actions = flattenActions([app]).map(summarizeAction);
2717
+ const triggers = flattenTriggers([app]).map(triggerDetail);
2600
2718
  const payload = {
2601
2719
  id: app.id,
2602
2720
  name: app.name,
@@ -2605,6 +2723,7 @@ async function runAppsGet(client, args) {
2605
2723
  needsConnection: Boolean(app.needsConnection),
2606
2724
  isPublished: Boolean(app.isPublished),
2607
2725
  actions,
2726
+ triggers,
2608
2727
  connectionTypes: Array.isArray(app.connections) ? app.connections : []
2609
2728
  };
2610
2729
  if (args.json) {
@@ -2625,6 +2744,22 @@ async function runAppsGet(client, args) {
2625
2744
  { key: "availableForAgent", header: "FOR_AGENT" },
2626
2745
  { key: "needsConnection", header: "NEEDS_CONN" }
2627
2746
  ]);
2747
+ if (triggers.length) {
2748
+ console.log("");
2749
+ console.log("triggers:");
2750
+ printTable(
2751
+ triggers.map((trigger) => ({
2752
+ triggerId: trigger.triggerId,
2753
+ name: trigger.name,
2754
+ needsConnection: trigger.needsConnection
2755
+ })),
2756
+ [
2757
+ { key: "triggerId", header: "TRIGGER" },
2758
+ { key: "name", header: "NAME" },
2759
+ { key: "needsConnection", header: "NEEDS_CONN" }
2760
+ ]
2761
+ );
2762
+ }
2628
2763
  }
2629
2764
  async function runAiConnectionsList(client, args) {
2630
2765
  const connections = await client.aiConnections.list();
package/dist/index.cjs CHANGED
@@ -537,6 +537,7 @@ var DEFINE_KINDS = {
537
537
  connection: "connection",
538
538
  aiConnection: "aiConnection",
539
539
  action: "action",
540
+ trigger: "trigger",
540
541
  workflow: "workflow",
541
542
  agent: "agent",
542
543
  entityType: "entityType"
@@ -553,6 +554,25 @@ function defineAction(config) {
553
554
  }
554
555
  return { kind: DEFINE_KINDS.action, ...config };
555
556
  }
557
+ function assertTriggerConfig(config) {
558
+ if (!config.id?.trim()) {
559
+ throw new Error("defineTrigger requires id (catalogue trigger id)");
560
+ }
561
+ for (const field of config.inputs ?? []) {
562
+ if (!field?.id?.trim()) {
563
+ throw new Error("defineTrigger inputs require id");
564
+ }
565
+ }
566
+ if (config.inputs?.length && config.id.trim() !== "flow-control_trigger_manual") {
567
+ throw new Error(
568
+ "defineTrigger inputs are only valid on flow-control_trigger_manual"
569
+ );
570
+ }
571
+ }
572
+ function defineTrigger(config) {
573
+ assertTriggerConfig(config);
574
+ return { kind: DEFINE_KINDS.trigger, ...config };
575
+ }
556
576
  function defineWorkflow(config) {
557
577
  if (!config.slug?.trim()) {
558
578
  throw new Error("defineWorkflow requires slug");
@@ -560,6 +580,9 @@ function defineWorkflow(config) {
560
580
  if (!config.steps?.length) {
561
581
  throw new Error("defineWorkflow requires at least one step");
562
582
  }
583
+ if (config.trigger) {
584
+ assertTriggerConfig(config.trigger);
585
+ }
563
586
  return { kind: DEFINE_KINDS.workflow, ...config };
564
587
  }
565
588
  function defineAgent(config) {
@@ -605,6 +628,40 @@ function resolveActionAppId(action) {
605
628
  `Cannot infer appId for action "${id}". Pass appId explicitly.`
606
629
  );
607
630
  }
631
+ function resolveTriggerAppId(trigger) {
632
+ if (trigger.appId?.trim()) {
633
+ return trigger.appId.trim();
634
+ }
635
+ const id = trigger.id.trim();
636
+ const marker = "_trigger_";
637
+ const markerIndex = id.indexOf(marker);
638
+ if (markerIndex > 0) {
639
+ return id.slice(0, markerIndex);
640
+ }
641
+ const dot = id.indexOf(".");
642
+ if (dot > 0) {
643
+ return id.slice(0, dot);
644
+ }
645
+ throw new Error(
646
+ `Cannot infer appId for trigger "${id}". Pass appId explicitly.`
647
+ );
648
+ }
649
+ function resolveTriggerId(trigger) {
650
+ const id = trigger.id.trim();
651
+ const appId = trigger.appId?.trim();
652
+ if (appId && id.startsWith(`${appId}.`)) {
653
+ return id.slice(appId.length + 1);
654
+ }
655
+ const marker = "_trigger_";
656
+ if (id.includes(marker)) {
657
+ return id;
658
+ }
659
+ const dot = id.indexOf(".");
660
+ if (dot > 0) {
661
+ return id.slice(dot + 1);
662
+ }
663
+ return id;
664
+ }
608
665
  function resolveActionId(action) {
609
666
  const id = action.id.trim();
610
667
  const appId = action.appId?.trim();
@@ -2019,6 +2076,17 @@ var WorkflowAppsResource = class {
2019
2076
  };
2020
2077
 
2021
2078
  // src/resources/workflows.ts
2079
+ function triggerToUpsertInput(trigger) {
2080
+ return {
2081
+ triggerId: resolveTriggerId(trigger),
2082
+ appId: resolveTriggerAppId(trigger),
2083
+ ...trigger.connection?.id ? { connectionId: trigger.connection.id } : {},
2084
+ ...trigger.input ? { input: trigger.input } : {},
2085
+ ...trigger.inputs?.length ? { inputs: trigger.inputs } : {},
2086
+ ...trigger.name ? { name: trigger.name } : {},
2087
+ ...trigger.description ? { description: trigger.description } : {}
2088
+ };
2089
+ }
2022
2090
  function stepToUpsertInput(step) {
2023
2091
  const use = step.use;
2024
2092
  return {
@@ -2039,6 +2107,7 @@ function workflowDefinitionToUpsert(def) {
2039
2107
  name: def.name,
2040
2108
  description: def.description,
2041
2109
  isActive: def.isActive,
2110
+ ...def.trigger ? { trigger: triggerToUpsertInput(def.trigger) } : {},
2042
2111
  managedByCode: true,
2043
2112
  steps: def.steps.map(stepToUpsertInput)
2044
2113
  };
@@ -2277,6 +2346,7 @@ exports.defineAgent = defineAgent;
2277
2346
  exports.defineAiConnection = defineAiConnection;
2278
2347
  exports.defineConnection = defineConnection;
2279
2348
  exports.defineEntityType = defineEntityType;
2349
+ exports.defineTrigger = defineTrigger;
2280
2350
  exports.defineWorkflow = defineWorkflow;
2281
2351
  exports.entityTypeDefinitionToUpsert = entityTypeDefinitionToUpsert;
2282
2352
  exports.isBrowserEnvironment = isBrowserEnvironment;
@@ -2287,5 +2357,7 @@ exports.parseSseEvents = parseSseEvents;
2287
2357
  exports.parseSseStream = parseSseStream;
2288
2358
  exports.resolveActionAppId = resolveActionAppId;
2289
2359
  exports.resolveActionId = resolveActionId;
2360
+ exports.resolveTriggerAppId = resolveTriggerAppId;
2361
+ exports.resolveTriggerId = resolveTriggerId;
2290
2362
  //# sourceMappingURL=index.cjs.map
2291
2363
  //# sourceMappingURL=index.cjs.map