@teamkeel/functions-runtime 0.413.0-next.1 → 0.413.2-next.2

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/dist/index.cjs CHANGED
@@ -2333,6 +2333,7 @@ __name(tryExecuteFlow, "tryExecuteFlow");
2333
2333
  // src/flows/ui/elements/input/text.ts
2334
2334
  var textInput = /* @__PURE__ */ __name((name, options) => {
2335
2335
  return {
2336
+ __type: "input",
2336
2337
  uiConfig: {
2337
2338
  __type: "ui.input.text",
2338
2339
  name,
@@ -2352,6 +2353,7 @@ var textInput = /* @__PURE__ */ __name((name, options) => {
2352
2353
  // src/flows/ui/elements/input/number.ts
2353
2354
  var numberInput = /* @__PURE__ */ __name((name, options) => {
2354
2355
  return {
2356
+ __type: "input",
2355
2357
  uiConfig: {
2356
2358
  __type: "ui.input.number",
2357
2359
  name,
@@ -2379,6 +2381,7 @@ var divider = /* @__PURE__ */ __name((options) => {
2379
2381
  // src/flows/ui/elements/input/boolean.ts
2380
2382
  var booleanInput = /* @__PURE__ */ __name((name, options) => {
2381
2383
  return {
2384
+ __type: "input",
2382
2385
  uiConfig: {
2383
2386
  __type: "ui.input.boolean",
2384
2387
  name,
@@ -2420,11 +2423,12 @@ var table = /* @__PURE__ */ __name((options) => {
2420
2423
  };
2421
2424
  }, "table");
2422
2425
 
2423
- // src/flows/ui/elements/select/single.ts
2426
+ // src/flows/ui/elements/select/one.ts
2424
2427
  var selectOne = /* @__PURE__ */ __name((name, options) => {
2425
2428
  return {
2429
+ __type: "input",
2426
2430
  uiConfig: {
2427
- __type: "ui.select.single",
2431
+ __type: "ui.select.one",
2428
2432
  name,
2429
2433
  label: options?.label || name,
2430
2434
  defaultValue: options?.defaultValue,
@@ -2436,6 +2440,20 @@ var selectOne = /* @__PURE__ */ __name((name, options) => {
2436
2440
  };
2437
2441
  }, "selectOne");
2438
2442
 
2443
+ // src/flows/ui/page.ts
2444
+ var page = /* @__PURE__ */ __name((options) => {
2445
+ const content = options.content;
2446
+ const contentUiConfig = content.map((c) => c.uiConfig).filter(Boolean);
2447
+ return {
2448
+ __type: "ui.page",
2449
+ stage: options.stage,
2450
+ title: options.title,
2451
+ description: options.description,
2452
+ content: contentUiConfig,
2453
+ actions: options.actions
2454
+ };
2455
+ }, "page");
2456
+
2439
2457
  // src/flows/disrupts.ts
2440
2458
  var FlowDisrupt = class {
2441
2459
  static {
@@ -2454,18 +2472,17 @@ var UIRenderDisrupt = class extends FlowDisrupt {
2454
2472
  __name(this, "UIRenderDisrupt");
2455
2473
  }
2456
2474
  };
2457
- var StepErrorDisrupt = class extends FlowDisrupt {
2458
- constructor(message) {
2459
- super();
2460
- this.message = message;
2461
- }
2475
+ var StepCreatedDisrupt = class extends FlowDisrupt {
2462
2476
  static {
2463
- __name(this, "StepErrorDisrupt");
2477
+ __name(this, "StepCreatedDisrupt");
2478
+ }
2479
+ constructor() {
2480
+ super();
2464
2481
  }
2465
2482
  };
2466
- var StepCompletedDisrupt = class extends FlowDisrupt {
2483
+ var ExhuastedRetriesDisrupt = class extends FlowDisrupt {
2467
2484
  static {
2468
- __name(this, "StepCompletedDisrupt");
2485
+ __name(this, "ExhuastedRetriesDisrupt");
2469
2486
  }
2470
2487
  constructor() {
2471
2488
  super();
@@ -2513,7 +2530,14 @@ var grid = /* @__PURE__ */ __name((options) => {
2513
2530
  return {
2514
2531
  uiConfig: {
2515
2532
  __type: "ui.display.grid",
2516
- data: options.data.map(options.render)
2533
+ data: options.data.map((item) => {
2534
+ const rendered = options.render(item);
2535
+ return {
2536
+ title: rendered.title,
2537
+ description: rendered.description,
2538
+ image: rendered.image
2539
+ };
2540
+ })
2517
2541
  }
2518
2542
  };
2519
2543
  }, "grid");
@@ -2523,7 +2547,14 @@ var list = /* @__PURE__ */ __name((options) => {
2523
2547
  return {
2524
2548
  uiConfig: {
2525
2549
  __type: "ui.display.list",
2526
- data: options.data.map(options.render)
2550
+ data: options.data.map((item) => {
2551
+ const rendered = options.render(item);
2552
+ return {
2553
+ title: rendered.title,
2554
+ description: rendered.description,
2555
+ image: rendered.image
2556
+ };
2557
+ })
2527
2558
  }
2528
2559
  };
2529
2560
  }, "list");
@@ -2547,46 +2578,80 @@ var defaultOpts = {
2547
2578
  };
2548
2579
  function createFlowContext(runId, data, spanId) {
2549
2580
  return {
2550
- step: /* @__PURE__ */ __name(async (name, options, fn) => {
2581
+ step: /* @__PURE__ */ __name(async (name, optionsOrFn, fn) => {
2582
+ const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
2583
+ const actualFn = typeof optionsOrFn === "function" ? optionsOrFn : fn;
2551
2584
  const db = useDatabase();
2552
- const completed = await db.selectFrom("keel_flow_step").where("run_id", "=", runId).where("name", "=", name).where("status", "=", "COMPLETED" /* COMPLETED */).selectAll().executeTakeFirst();
2553
- if (completed) {
2554
- return completed.value;
2585
+ const past = await db.selectFrom("keel_flow_step").where("run_id", "=", runId).where("name", "=", name).selectAll().execute();
2586
+ const newSteps = past.filter((step) => step.status === "NEW" /* NEW */);
2587
+ const completedSteps = past.filter(
2588
+ (step) => step.status === "COMPLETED" /* COMPLETED */
2589
+ );
2590
+ const failedSteps = past.filter(
2591
+ (step) => step.status === "FAILED" /* FAILED */
2592
+ );
2593
+ if (newSteps.length > 1) {
2594
+ throw new Error("Multiple NEW steps found for the same step");
2595
+ }
2596
+ if (completedSteps.length > 1) {
2597
+ throw new Error("Multiple completed steps found for the same step");
2598
+ }
2599
+ if (completedSteps.length > 1 && newSteps.length > 1) {
2600
+ throw new Error(
2601
+ "Multiple completed and new steps found for the same step"
2602
+ );
2603
+ }
2604
+ if (completedSteps.length === 1) {
2605
+ return completedSteps[0].value;
2606
+ }
2607
+ if (newSteps.length === 1) {
2608
+ let result = null;
2609
+ await db.updateTable("keel_flow_step").set({
2610
+ startTime: /* @__PURE__ */ new Date()
2611
+ }).where("id", "=", newSteps[0].id).returningAll().executeTakeFirst();
2612
+ try {
2613
+ result = await withTimeout(
2614
+ actualFn(),
2615
+ options.timeoutInMs ?? defaultOpts.timeoutInMs
2616
+ );
2617
+ } catch (e) {
2618
+ await db.updateTable("keel_flow_step").set({
2619
+ status: "FAILED" /* FAILED */,
2620
+ spanId,
2621
+ endTime: /* @__PURE__ */ new Date(),
2622
+ error: e instanceof Error ? e.message : "An error occurred"
2623
+ }).where("id", "=", newSteps[0].id).returningAll().executeTakeFirst();
2624
+ if (failedSteps.length + 1 >= (options.maxRetries ?? defaultOpts.maxRetries)) {
2625
+ throw new ExhuastedRetriesDisrupt();
2626
+ }
2627
+ await db.insertInto("keel_flow_step").values({
2628
+ run_id: runId,
2629
+ name,
2630
+ stage: options.stage,
2631
+ status: "NEW" /* NEW */,
2632
+ type: "FUNCTION" /* FUNCTION */
2633
+ }).returningAll().executeTakeFirst();
2634
+ throw new StepCreatedDisrupt();
2635
+ }
2636
+ await db.updateTable("keel_flow_step").set({
2637
+ status: "COMPLETED" /* COMPLETED */,
2638
+ value: JSON.stringify(result),
2639
+ spanId,
2640
+ endTime: /* @__PURE__ */ new Date()
2641
+ }).where("id", "=", newSteps[0].id).returningAll().executeTakeFirst();
2642
+ return result;
2555
2643
  }
2556
- const step = await db.insertInto("keel_flow_step").values({
2644
+ await db.insertInto("keel_flow_step").values({
2557
2645
  run_id: runId,
2558
2646
  name,
2559
2647
  stage: options.stage,
2560
2648
  status: "NEW" /* NEW */,
2561
- type: "FUNCTION" /* FUNCTION */,
2562
- maxRetries: options?.maxRetries ?? defaultOpts.maxRetries,
2563
- timeoutInMs: options?.timeoutInMs ?? defaultOpts.timeoutInMs
2649
+ type: "FUNCTION" /* FUNCTION */
2564
2650
  }).returningAll().executeTakeFirst();
2565
- if (!step) {
2566
- throw new Error("Failed to create step");
2567
- }
2568
- let result = null;
2569
- try {
2570
- result = await withTimeout(fn(), step.timeoutInMs);
2571
- } catch (e) {
2572
- await db.updateTable("keel_flow_step").set({
2573
- status: "FAILED" /* FAILED */,
2574
- spanId
2575
- // TODO: store error message
2576
- }).where("id", "=", step.id).returningAll().executeTakeFirst();
2577
- throw new StepErrorDisrupt(
2578
- e instanceof Error ? e.message : "an error occurred"
2579
- );
2580
- }
2581
- await db.updateTable("keel_flow_step").set({
2582
- status: "COMPLETED" /* COMPLETED */,
2583
- value: JSON.stringify(result),
2584
- spanId
2585
- }).where("id", "=", step.id).returningAll().executeTakeFirst();
2586
- throw new StepCompletedDisrupt();
2651
+ throw new StepCreatedDisrupt();
2587
2652
  }, "step"),
2588
2653
  ui: {
2589
- page: /* @__PURE__ */ __name(async (name, page) => {
2654
+ page: /* @__PURE__ */ __name(async (name, options) => {
2590
2655
  const db = useDatabase();
2591
2656
  let step = await db.selectFrom("keel_flow_step").where("run_id", "=", runId).where("name", "=", name).selectAll().executeTakeFirst();
2592
2657
  if (step && step.status === "COMPLETED" /* COMPLETED */) {
@@ -2596,26 +2661,23 @@ function createFlowContext(runId, data, spanId) {
2596
2661
  step = await db.insertInto("keel_flow_step").values({
2597
2662
  run_id: runId,
2598
2663
  name,
2599
- stage: page.stage,
2664
+ stage: options.stage,
2600
2665
  status: "PENDING" /* PENDING */,
2601
2666
  type: "UI" /* UI */,
2602
- maxRetries: 3,
2603
- timeoutInMs: 1e3
2667
+ startTime: /* @__PURE__ */ new Date()
2604
2668
  }).returningAll().executeTakeFirst();
2669
+ throw new UIRenderDisrupt(step?.id, page(options));
2605
2670
  }
2606
- if (!step) {
2607
- throw new Error("Failed to create step");
2608
- }
2609
- if (data) {
2610
- await db.updateTable("keel_flow_step").set({
2611
- status: "COMPLETED" /* COMPLETED */,
2612
- value: JSON.stringify(data),
2613
- spanId
2614
- }).where("id", "=", step.id).returningAll().executeTakeFirst();
2615
- return data;
2616
- } else {
2617
- throw new UIRenderDisrupt(step.id, page);
2671
+ if (!data) {
2672
+ throw new UIRenderDisrupt(step?.id, page(options));
2618
2673
  }
2674
+ await db.updateTable("keel_flow_step").set({
2675
+ status: "COMPLETED" /* COMPLETED */,
2676
+ value: JSON.stringify(data),
2677
+ spanId,
2678
+ endTime: /* @__PURE__ */ new Date()
2679
+ }).where("id", "=", step.id).returningAll().executeTakeFirst();
2680
+ return data;
2619
2681
  }, "page"),
2620
2682
  inputs: {
2621
2683
  text: textInput,
@@ -2634,7 +2696,7 @@ function createFlowContext(runId, data, spanId) {
2634
2696
  list
2635
2697
  },
2636
2698
  select: {
2637
- single: selectOne
2699
+ one: selectOne
2638
2700
  }
2639
2701
  }
2640
2702
  };
@@ -2648,7 +2710,7 @@ function withTimeout(promiseFn, timeout) {
2648
2710
  return Promise.race([
2649
2711
  promiseFn,
2650
2712
  wait(timeout).then(() => {
2651
- throw new Error(`flow times out after ${timeout}ms`);
2713
+ throw new Error(`Step function timed out after ${timeout}ms`);
2652
2714
  })
2653
2715
  ]);
2654
2716
  }
@@ -2706,7 +2768,7 @@ async function handleFlow(request, config) {
2706
2768
  config: flowConfig
2707
2769
  });
2708
2770
  } catch (e) {
2709
- if (e instanceof StepCompletedDisrupt) {
2771
+ if (e instanceof StepCreatedDisrupt) {
2710
2772
  return (0, import_json_rpc_26.createJSONRPCSuccessResponse)(request.id, {
2711
2773
  runId,
2712
2774
  runCompleted: false,
@@ -2726,11 +2788,19 @@ async function handleFlow(request, config) {
2726
2788
  code: opentelemetry6.SpanStatusCode.ERROR,
2727
2789
  message: e.message
2728
2790
  });
2729
- return (0, import_json_rpc_26.createJSONRPCSuccessResponse)(request.id, {
2730
- runId,
2731
- runCompleted: false,
2732
- config: flowConfig
2733
- });
2791
+ if (e instanceof ExhuastedRetriesDisrupt) {
2792
+ return (0, import_json_rpc_26.createJSONRPCSuccessResponse)(request.id, {
2793
+ runId,
2794
+ runCompleted: true,
2795
+ error: "flow failed due to exhausted step retries",
2796
+ config: flowConfig
2797
+ });
2798
+ }
2799
+ return (0, import_json_rpc_26.createJSONRPCErrorResponse)(
2800
+ request.id,
2801
+ import_json_rpc_26.JSONRPCErrorCode.InternalError,
2802
+ e.message
2803
+ );
2734
2804
  } finally {
2735
2805
  if (db) {
2736
2806
  await db.destroy();