@botpress/runtime 1.13.9 → 1.13.10

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 (34) hide show
  1. package/dist/define-config.d.ts +23 -1
  2. package/dist/define-config.d.ts.map +1 -1
  3. package/dist/definition.js +400 -290
  4. package/dist/definition.js.map +4 -4
  5. package/dist/internal.js +494 -384
  6. package/dist/internal.js.map +4 -4
  7. package/dist/library.d.ts +4 -2
  8. package/dist/library.d.ts.map +1 -1
  9. package/dist/library.js +427 -284
  10. package/dist/library.js.map +4 -4
  11. package/dist/primitives/conversation.d.ts +24 -11
  12. package/dist/primitives/conversation.d.ts.map +1 -1
  13. package/dist/primitives/data-sources/source-base.d.ts +1 -1
  14. package/dist/primitives/data-sources/source-base.d.ts.map +1 -1
  15. package/dist/primitives/index.d.ts +1 -1
  16. package/dist/primitives/workflow-instance.d.ts +45 -1
  17. package/dist/primitives/workflow-instance.d.ts.map +1 -1
  18. package/dist/primitives/workflow.d.ts +3 -2
  19. package/dist/primitives/workflow.d.ts.map +1 -1
  20. package/dist/runtime/autonomous.d.ts +1 -0
  21. package/dist/runtime/autonomous.d.ts.map +1 -1
  22. package/dist/runtime/context/context.d.ts +3 -0
  23. package/dist/runtime/context/context.d.ts.map +1 -1
  24. package/dist/runtime/context/handlers.d.ts.map +1 -1
  25. package/dist/runtime/handlers/event.d.ts.map +1 -1
  26. package/dist/runtime/handlers/workflow.d.ts.map +1 -1
  27. package/dist/runtime/tracked-tags.d.ts.map +1 -1
  28. package/dist/runtime.js +451 -302
  29. package/dist/runtime.js.map +4 -4
  30. package/dist/utilities/events.d.ts +28 -0
  31. package/dist/utilities/events.d.ts.map +1 -1
  32. package/dist/utilities/validate-event-name.d.ts +20 -0
  33. package/dist/utilities/validate-event-name.d.ts.map +1 -0
  34. package/package.json +1 -1
package/dist/library.js CHANGED
@@ -48,7 +48,7 @@ var init_define_BUILD = __esm({
48
48
  var define_PACKAGE_VERSIONS_default;
49
49
  var init_define_PACKAGE_VERSIONS = __esm({
50
50
  "<define:__PACKAGE_VERSIONS__>"() {
51
- define_PACKAGE_VERSIONS_default = { runtime: "1.13.9", adk: "1.13.9", sdk: "5.0.2", llmz: "0.0.35", zai: "2.5.6", cognitive: "0.3.3" };
51
+ define_PACKAGE_VERSIONS_default = { runtime: "1.13.10", adk: "1.13.10", sdk: "5.0.2", llmz: "0.0.35", zai: "2.5.6", cognitive: "0.3.3" };
52
52
  }
53
53
  });
54
54
 
@@ -27795,41 +27795,41 @@ var require_ms = __commonJS({
27795
27795
  return void 0;
27796
27796
  }
27797
27797
  }
27798
- function fmtShort(ms3) {
27799
- var msAbs = Math.abs(ms3);
27798
+ function fmtShort(ms4) {
27799
+ var msAbs = Math.abs(ms4);
27800
27800
  if (msAbs >= d) {
27801
- return Math.round(ms3 / d) + "d";
27801
+ return Math.round(ms4 / d) + "d";
27802
27802
  }
27803
27803
  if (msAbs >= h) {
27804
- return Math.round(ms3 / h) + "h";
27804
+ return Math.round(ms4 / h) + "h";
27805
27805
  }
27806
27806
  if (msAbs >= m) {
27807
- return Math.round(ms3 / m) + "m";
27807
+ return Math.round(ms4 / m) + "m";
27808
27808
  }
27809
27809
  if (msAbs >= s) {
27810
- return Math.round(ms3 / s) + "s";
27810
+ return Math.round(ms4 / s) + "s";
27811
27811
  }
27812
- return ms3 + "ms";
27812
+ return ms4 + "ms";
27813
27813
  }
27814
- function fmtLong(ms3) {
27815
- var msAbs = Math.abs(ms3);
27814
+ function fmtLong(ms4) {
27815
+ var msAbs = Math.abs(ms4);
27816
27816
  if (msAbs >= d) {
27817
- return plural(ms3, msAbs, d, "day");
27817
+ return plural(ms4, msAbs, d, "day");
27818
27818
  }
27819
27819
  if (msAbs >= h) {
27820
- return plural(ms3, msAbs, h, "hour");
27820
+ return plural(ms4, msAbs, h, "hour");
27821
27821
  }
27822
27822
  if (msAbs >= m) {
27823
- return plural(ms3, msAbs, m, "minute");
27823
+ return plural(ms4, msAbs, m, "minute");
27824
27824
  }
27825
27825
  if (msAbs >= s) {
27826
- return plural(ms3, msAbs, s, "second");
27826
+ return plural(ms4, msAbs, s, "second");
27827
27827
  }
27828
- return ms3 + " ms";
27828
+ return ms4 + " ms";
27829
27829
  }
27830
- function plural(ms3, msAbs, n, name) {
27830
+ function plural(ms4, msAbs, n, name) {
27831
27831
  var isPlural = msAbs >= n * 1.5;
27832
- return Math.round(ms3 / n) + " " + name + (isPlural ? "s" : "");
27832
+ return Math.round(ms4 / n) + " " + name + (isPlural ? "s" : "");
27833
27833
  }
27834
27834
  }
27835
27835
  });
@@ -27874,8 +27874,8 @@ var require_common = __commonJS({
27874
27874
  }
27875
27875
  const self2 = debug;
27876
27876
  const curr = Number(/* @__PURE__ */ new Date());
27877
- const ms3 = curr - (prevTime || curr);
27878
- self2.diff = ms3;
27877
+ const ms4 = curr - (prevTime || curr);
27878
+ self2.diff = ms4;
27879
27879
  self2.prev = prevTime;
27880
27880
  self2.curr = curr;
27881
27881
  prevTime = curr;
@@ -34476,6 +34476,9 @@ Always prefer information from the knowledge bases over general knowledge when a
34476
34476
  ...props.hooks?.onBeforeTool && {
34477
34477
  onBeforeTool: asyncResource.bind(props.hooks.onBeforeTool)
34478
34478
  },
34479
+ ...props.hooks?.onIterationStart && {
34480
+ onIterationStart: asyncResource.bind(props.hooks.onIterationStart)
34481
+ },
34479
34482
  ...props.hooks?.onAfterTool && {
34480
34483
  onAfterTool: asyncResource.bind(props.hooks.onAfterTool)
34481
34484
  },
@@ -35045,15 +35048,51 @@ var init_validate_tag_name = __esm({
35045
35048
  }
35046
35049
  });
35047
35050
 
35051
+ // src/utilities/validate-event-name.ts
35052
+ function validateEventName(name) {
35053
+ if (!name || typeof name !== "string") {
35054
+ return { valid: false, error: "Event name must be a non-empty string" };
35055
+ }
35056
+ if (name.length > 100) {
35057
+ return { valid: false, error: `Event name "${name}" must be less than 100 characters` };
35058
+ }
35059
+ if (!/^[a-zA-Z]/.test(name)) {
35060
+ return { valid: false, error: `Event name "${name}" must start with a letter` };
35061
+ }
35062
+ if (!/^[a-zA-Z0-9_]+$/.test(name)) {
35063
+ return {
35064
+ valid: false,
35065
+ error: `Event name "${name}" can only contain letters (A-Z, a-z), numbers (0-9), and underscores (_)`
35066
+ };
35067
+ }
35068
+ return { valid: true };
35069
+ }
35070
+ function validateEventDefinitions(events, context3) {
35071
+ for (const eventName of Object.keys(events)) {
35072
+ const validation = validateEventName(eventName);
35073
+ if (!validation.valid) {
35074
+ throw new Error(`Invalid event name in ${context3}: ${validation.error}`);
35075
+ }
35076
+ }
35077
+ }
35078
+ var init_validate_event_name = __esm({
35079
+ "src/utilities/validate-event-name.ts"() {
35080
+ "use strict";
35081
+ init_define_BUILD();
35082
+ init_define_PACKAGE_VERSIONS();
35083
+ }
35084
+ });
35085
+
35048
35086
  // src/define-config.ts
35049
35087
  import { z as z3 } from "@botpress/sdk";
35050
- var zuiSchema, modelSchema, tagDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, defineConfig;
35088
+ var zuiSchema, modelSchema, tagDefinitionSchema, eventDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, defineConfig;
35051
35089
  var init_define_config = __esm({
35052
35090
  "src/define-config.ts"() {
35053
35091
  "use strict";
35054
35092
  init_define_BUILD();
35055
35093
  init_define_PACKAGE_VERSIONS();
35056
35094
  init_validate_tag_name();
35095
+ init_validate_event_name();
35057
35096
  zuiSchema = z3.custom(
35058
35097
  (val) => {
35059
35098
  if (typeof val === "object" && val !== null && "parse" in val) {
@@ -35078,6 +35117,13 @@ var init_define_config = __esm({
35078
35117
  description: z3.string().optional()
35079
35118
  })
35080
35119
  );
35120
+ eventDefinitionSchema = z3.record(
35121
+ z3.string(),
35122
+ z3.object({
35123
+ schema: zuiSchema.optional(),
35124
+ description: z3.string().optional()
35125
+ })
35126
+ );
35081
35127
  configSchema = z3.object({
35082
35128
  name: z3.string().optional(),
35083
35129
  description: z3.string().optional(),
@@ -35118,7 +35164,8 @@ var init_define_config = __esm({
35118
35164
  zai: val?.zai ?? "openai:gpt-4.1-2025-04-14",
35119
35165
  autonomous: val?.autonomous ?? "openai:gpt-4.1-mini-2025-04-14"
35120
35166
  })),
35121
- dependencies: z3.custom()
35167
+ dependencies: z3.custom(),
35168
+ events: eventDefinitionSchema.optional()
35122
35169
  });
35123
35170
  AGENT_CONFIG_BRAND = Symbol.for("@botpress/runtime/AgentConfig");
35124
35171
  defineConfig = (config) => {
@@ -35138,6 +35185,9 @@ var init_define_config = __esm({
35138
35185
  if (parsed.workflow?.tags) {
35139
35186
  validateTagDefinitions(parsed.workflow.tags, "workflow.tags");
35140
35187
  }
35188
+ if (parsed.events) {
35189
+ validateEventDefinitions(parsed.events, "events");
35190
+ }
35141
35191
  return {
35142
35192
  ...parsed,
35143
35193
  __brand: "AgentConfig",
@@ -35912,6 +35962,9 @@ function isEventMessage(event) {
35912
35962
  function isWorkflowCallback(event) {
35913
35963
  return event !== null && typeof event === "object" && "type" in event && event.type === "workflowCallback" && "payload" in event && event.payload !== null && typeof event.payload === "object";
35914
35964
  }
35965
+ function isEventOfType(event, eventName) {
35966
+ return isEvent(event) && event.type === eventName;
35967
+ }
35915
35968
  var init_events = __esm({
35916
35969
  "src/utilities/events.ts"() {
35917
35970
  "use strict";
@@ -36185,12 +36238,12 @@ var init_workflow_step = __esm({
36185
36238
  workflowControlContext.abort();
36186
36239
  throw createStepSignal();
36187
36240
  };
36188
- step.sleep = async (name, ms3) => {
36241
+ step.sleep = async (name, ms4) => {
36189
36242
  await _step(
36190
36243
  name,
36191
36244
  async () => {
36192
36245
  const remainingTime = context.get("runtime").getRemainingExecutionTimeInMs();
36193
- if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms3 || ms3 >= 1e4) {
36246
+ if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms4 || ms4 >= 1e4) {
36194
36247
  const client2 = context.get("client");
36195
36248
  const workflowControlContext = context.get("workflowControlContext");
36196
36249
  await client2.createEvent({
@@ -36198,7 +36251,7 @@ var init_workflow_step = __esm({
36198
36251
  payload: {},
36199
36252
  workflowId: workflowControlContext.workflow.id,
36200
36253
  schedule: {
36201
- delay: ms3
36254
+ delay: ms4
36202
36255
  }
36203
36256
  });
36204
36257
  await updateWorkflow({
@@ -36207,7 +36260,7 @@ var init_workflow_step = __esm({
36207
36260
  });
36208
36261
  workflowControlContext.abort();
36209
36262
  } else {
36210
- await new Promise((resolve) => void setTimeout(resolve, ms3));
36263
+ await new Promise((resolve) => void setTimeout(resolve, ms4));
36211
36264
  context.get("workflowControlContext").signal.throwIfAborted();
36212
36265
  }
36213
36266
  },
@@ -36218,8 +36271,8 @@ var init_workflow_step = __esm({
36218
36271
  );
36219
36272
  };
36220
36273
  step.sleepUntil = async (name, date) => {
36221
- const ms3 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
36222
- await step.sleep(name, ms3);
36274
+ const ms4 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
36275
+ await step.sleep(name, ms4);
36223
36276
  };
36224
36277
  step.waitForWorkflow = async (name, workflowId) => {
36225
36278
  const workflowControlContext = context.get("workflowControlContext");
@@ -36438,12 +36491,13 @@ function createWorkflowExecutionState(client2, workflowId) {
36438
36491
  name: BUILT_IN_STATES.workflowSteps
36439
36492
  });
36440
36493
  }
36441
- var workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
36494
+ var import_ms2, workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
36442
36495
  var init_workflow_instance = __esm({
36443
36496
  "src/primitives/workflow-instance.ts"() {
36444
36497
  "use strict";
36445
36498
  init_define_BUILD();
36446
36499
  init_define_PACKAGE_VERSIONS();
36500
+ import_ms2 = __toESM(require_ms(), 1);
36447
36501
  init_errors();
36448
36502
  init_library();
36449
36503
  init_autonomous();
@@ -36570,6 +36624,81 @@ var init_workflow_instance = __esm({
36570
36624
  });
36571
36625
  Object.assign(this.workflow, workflow);
36572
36626
  }
36627
+ /**
36628
+ * Extend the workflow timeout by setting a new timeout.
36629
+ * This is useful for long-running workflows that need more time to complete.
36630
+ *
36631
+ * @param options - Either `{ in: string }` for relative duration or `{ at: string }` for absolute ISO timestamp
36632
+ * @returns A promise that resolves when the timeout is updated (can be awaited or not)
36633
+ * @example
36634
+ * // Relative timeout (duration from now):
36635
+ * workflow.setTimeout({ in: '30m' }) // Timeout in 30 minutes
36636
+ * workflow.setTimeout({ in: '6 hours' }) // Timeout in 6 hours
36637
+ *
36638
+ * // Absolute timeout (ISO timestamp):
36639
+ * workflow.setTimeout({ at: '2024-12-25T00:00:00Z' })
36640
+ *
36641
+ * // Optionally await if you need to ensure the update completes:
36642
+ * await workflow.setTimeout({ in: '1h' })
36643
+ */
36644
+ setTimeout(options) {
36645
+ let newTimeoutAt;
36646
+ if ("in" in options) {
36647
+ const durationMs = (0, import_ms2.default)(options.in);
36648
+ if (!durationMs) {
36649
+ throw new Error(`Invalid duration format: "${options.in}". Use formats like "30m", "1h", "6 hours".`);
36650
+ }
36651
+ newTimeoutAt = new Date(Date.now() + durationMs).toISOString();
36652
+ } else {
36653
+ const date = new Date(options.at);
36654
+ if (isNaN(date.getTime())) {
36655
+ throw new Error(`Invalid ISO date format: "${options.at}".`);
36656
+ }
36657
+ newTimeoutAt = date.toISOString();
36658
+ }
36659
+ return updateWorkflow({
36660
+ id: this.id,
36661
+ timeoutAt: newTimeoutAt
36662
+ }).then(({ workflow }) => {
36663
+ Object.assign(this.workflow, workflow);
36664
+ });
36665
+ }
36666
+ /**
36667
+ * Fail the workflow with an error reason.
36668
+ * This immediately interrupts the workflow handler and marks the workflow as failed.
36669
+ * Can only be called from within a workflow handler.
36670
+ *
36671
+ * @param reason - The error reason for the failure
36672
+ * @throws Never returns - always throws to interrupt the handler
36673
+ * @example
36674
+ * workflow.fail('Invalid input data')
36675
+ */
36676
+ fail(reason) {
36677
+ const controlContext = context.get("workflowControlContext", { optional: true });
36678
+ if (!controlContext || controlContext.workflow.id !== this.id) {
36679
+ throw new Error("workflow.fail() can only be called from within the workflow handler");
36680
+ }
36681
+ controlContext.fail(reason);
36682
+ throw createStepSignal();
36683
+ }
36684
+ /**
36685
+ * Complete the workflow early with the given output.
36686
+ * This immediately interrupts the workflow handler and marks the workflow as completed.
36687
+ * Can only be called from within a workflow handler.
36688
+ *
36689
+ * @param output - The workflow output (typed according to workflow definition)
36690
+ * @throws Never returns - always throws to interrupt the handler
36691
+ * @example
36692
+ * workflow.complete({ result: 'success', data: processedData })
36693
+ */
36694
+ complete(output2) {
36695
+ const controlContext = context.get("workflowControlContext", { optional: true });
36696
+ if (!controlContext || controlContext.workflow.id !== this.id) {
36697
+ throw new Error("workflow.complete() can only be called from within the workflow handler");
36698
+ }
36699
+ controlContext.complete(output2);
36700
+ throw createStepSignal();
36701
+ }
36573
36702
  /**
36574
36703
  * Provide data in response to a workflow data request (instance method).
36575
36704
  * Call this method from a conversation handler when you receive a WorkflowDataRequestEvent.
@@ -36620,6 +36749,7 @@ var init_workflow_instance = __esm({
36620
36749
  workflow: this.workflow,
36621
36750
  aborted: false,
36622
36751
  failed: false,
36752
+ completed: false,
36623
36753
  acked: false,
36624
36754
  restarted: false,
36625
36755
  signal: abortSignal,
@@ -36634,6 +36764,10 @@ var init_workflow_instance = __esm({
36634
36764
  workflowControlContext.failed = true;
36635
36765
  workflowControlContext.failedReason = reason;
36636
36766
  },
36767
+ complete: (result) => {
36768
+ workflowControlContext.completed = true;
36769
+ workflowControlContext.completedResult = result;
36770
+ },
36637
36771
  ack: async () => {
36638
36772
  if (workflowControlContext.acked) {
36639
36773
  return;
@@ -36687,7 +36821,8 @@ var init_workflow_instance = __esm({
36687
36821
  step,
36688
36822
  client: this.client,
36689
36823
  execute: this.execute.bind(this),
36690
- signal: abortSignal
36824
+ signal: abortSignal,
36825
+ workflow: this
36691
36826
  });
36692
36827
  return {
36693
36828
  status: "done",
@@ -36698,6 +36833,12 @@ var init_workflow_instance = __esm({
36698
36833
  }
36699
36834
  } catch (err) {
36700
36835
  if (isStepSignal(err)) {
36836
+ if (workflowControlContext.completed) {
36837
+ return {
36838
+ status: "done",
36839
+ result: workflowControlContext.completedResult
36840
+ };
36841
+ }
36701
36842
  if (workflowControlContext.failed) {
36702
36843
  return {
36703
36844
  status: "error",
@@ -37313,6 +37454,259 @@ var init_tracked_state = __esm({
37313
37454
  }
37314
37455
  });
37315
37456
 
37457
+ // src/runtime/tracked-tags.ts
37458
+ var TrackedTags;
37459
+ var init_tracked_tags = __esm({
37460
+ "src/runtime/tracked-tags.ts"() {
37461
+ "use strict";
37462
+ init_define_BUILD();
37463
+ init_define_PACKAGE_VERSIONS();
37464
+ init_context();
37465
+ init_tracing();
37466
+ TrackedTags = class _TrackedTags {
37467
+ type;
37468
+ id;
37469
+ client;
37470
+ _tags = {};
37471
+ _initialTags = {};
37472
+ _loaded = false;
37473
+ _saving = false;
37474
+ _saveAgain = false;
37475
+ _saveAgainCount = 0;
37476
+ static _savingAll = false;
37477
+ static _saveAllAgain = false;
37478
+ static _saveAllCount = 0;
37479
+ constructor(props) {
37480
+ this.type = props.type;
37481
+ this.id = props.id;
37482
+ this.client = props.client;
37483
+ }
37484
+ static create(props) {
37485
+ const tags = context.get("tags", { optional: true });
37486
+ const executionFinished = context.get("executionFinished", { optional: true });
37487
+ if (executionFinished) {
37488
+ throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
37489
+ }
37490
+ const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
37491
+ if (match2) {
37492
+ return match2;
37493
+ }
37494
+ const instance = new _TrackedTags(props);
37495
+ if (props.initialTags) {
37496
+ instance._tags = { ...props.initialTags };
37497
+ instance._initialTags = { ...props.initialTags };
37498
+ instance._loaded = true;
37499
+ }
37500
+ tags?.push(instance);
37501
+ return instance;
37502
+ }
37503
+ static async saveAllDirty() {
37504
+ if (this._savingAll) {
37505
+ this._saveAllAgain = true;
37506
+ return;
37507
+ }
37508
+ try {
37509
+ this._savingAll = true;
37510
+ const tags = context.get("tags", { optional: true });
37511
+ const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
37512
+ if (!dirtyTags.length) {
37513
+ return;
37514
+ }
37515
+ await span(
37516
+ "tags.saveAllDirty",
37517
+ {
37518
+ tags_count: tags?.length || 0,
37519
+ tags: tags.map((t) => `${t.type}/${t.id}`)
37520
+ },
37521
+ () => Promise.allSettled(dirtyTags.map((t) => t.save()))
37522
+ );
37523
+ } finally {
37524
+ this._savingAll = false;
37525
+ if (this._saveAllAgain && this._saveAllCount++ <= 5) {
37526
+ this._saveAllAgain = false;
37527
+ await this.saveAllDirty();
37528
+ } else {
37529
+ this._saveAllCount = 0;
37530
+ }
37531
+ }
37532
+ }
37533
+ static async loadAll() {
37534
+ await span("tags.loadAll", {}, async () => {
37535
+ const client2 = context.get("client")._inner;
37536
+ const bot2 = context.get("bot", { optional: true });
37537
+ const user2 = context.get("user", { optional: true });
37538
+ const conversation = context.get("conversation", { optional: true });
37539
+ const workflow = context.get("workflow", { optional: true });
37540
+ if (bot2) {
37541
+ const botTags = bot2.tags;
37542
+ _TrackedTags.create({
37543
+ client: client2,
37544
+ type: "bot",
37545
+ id: bot2.id,
37546
+ ...botTags && { initialTags: botTags }
37547
+ });
37548
+ }
37549
+ if (user2) {
37550
+ const userTags = user2.tags;
37551
+ _TrackedTags.create({
37552
+ client: client2,
37553
+ type: "user",
37554
+ id: user2.id,
37555
+ ...userTags && { initialTags: userTags }
37556
+ });
37557
+ }
37558
+ if (conversation) {
37559
+ const conversationTags = conversation.tags;
37560
+ _TrackedTags.create({
37561
+ client: client2,
37562
+ type: "conversation",
37563
+ id: conversation.id,
37564
+ ...conversationTags && { initialTags: conversationTags }
37565
+ });
37566
+ }
37567
+ if (workflow) {
37568
+ const workflowTags = workflow.tags;
37569
+ _TrackedTags.create({
37570
+ client: client2,
37571
+ type: "workflow",
37572
+ id: workflow.id,
37573
+ ...workflowTags && { initialTags: workflowTags }
37574
+ });
37575
+ }
37576
+ const tags = context.get("tags", { optional: true });
37577
+ const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
37578
+ if (unloadedTags.length > 0) {
37579
+ await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
37580
+ }
37581
+ });
37582
+ }
37583
+ static unloadAll() {
37584
+ context.get("tags", { optional: true })?.splice(0);
37585
+ }
37586
+ async load(force = false) {
37587
+ if (this._loaded && !force) {
37588
+ return;
37589
+ }
37590
+ await span(
37591
+ "tags.load",
37592
+ {
37593
+ type: this.type,
37594
+ id: this.id
37595
+ },
37596
+ async () => {
37597
+ const tags = await this.fetchTags();
37598
+ this._tags = { ...tags };
37599
+ this._initialTags = { ...tags };
37600
+ this._loaded = true;
37601
+ }
37602
+ );
37603
+ }
37604
+ async save() {
37605
+ if (this._saving) {
37606
+ this._saveAgain = true;
37607
+ return;
37608
+ }
37609
+ const executionFinished = context.get("executionFinished", { optional: true });
37610
+ if (executionFinished) {
37611
+ throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
37612
+ }
37613
+ try {
37614
+ this._saving = true;
37615
+ await span(
37616
+ "tags.save",
37617
+ {
37618
+ type: this.type,
37619
+ id: this.id
37620
+ },
37621
+ async () => {
37622
+ await this.persistTags(this._tags);
37623
+ this._initialTags = { ...this._tags };
37624
+ }
37625
+ );
37626
+ } finally {
37627
+ this._saving = false;
37628
+ if (this._saveAgain && this._saveAgainCount++ <= 5) {
37629
+ this._saveAgain = false;
37630
+ await this.save();
37631
+ } else {
37632
+ this._saveAgainCount = 0;
37633
+ }
37634
+ }
37635
+ }
37636
+ isDirty() {
37637
+ const currentKeys = Object.keys(this._tags).filter((k) => !k.includes(":")).sort();
37638
+ const initialKeys = Object.keys(this._initialTags).filter((k) => !k.includes(":")).sort();
37639
+ if (currentKeys.length !== initialKeys.length) {
37640
+ return true;
37641
+ }
37642
+ for (const key of currentKeys) {
37643
+ if (this._tags[key] !== this._initialTags[key]) {
37644
+ return true;
37645
+ }
37646
+ }
37647
+ return false;
37648
+ }
37649
+ get tags() {
37650
+ return new Proxy(this._tags, {
37651
+ set: (target, prop, value) => {
37652
+ target[prop] = value;
37653
+ return true;
37654
+ },
37655
+ deleteProperty: (target, prop) => {
37656
+ target[prop] = void 0;
37657
+ return true;
37658
+ }
37659
+ });
37660
+ }
37661
+ set tags(value) {
37662
+ this._tags = { ...value };
37663
+ }
37664
+ async fetchTags() {
37665
+ try {
37666
+ if (this.type === "bot") {
37667
+ const { bot: bot2 } = await this.client.getBot({ id: this.id });
37668
+ return bot2.tags || {};
37669
+ } else if (this.type === "user") {
37670
+ const { user: user2 } = await this.client.getUser({ id: this.id });
37671
+ return user2.tags || {};
37672
+ } else if (this.type === "conversation") {
37673
+ const { conversation } = await this.client.getConversation({ id: this.id });
37674
+ return conversation.tags || {};
37675
+ } else if (this.type === "workflow") {
37676
+ const { workflow } = await this.client.getWorkflow({ id: this.id });
37677
+ return workflow.tags || {};
37678
+ }
37679
+ } catch (err) {
37680
+ console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
37681
+ }
37682
+ return {};
37683
+ }
37684
+ async persistTags(tags) {
37685
+ const tagsForApi = {};
37686
+ for (const [key, value] of Object.entries(tags)) {
37687
+ if (value !== void 0 && !key.includes(":")) {
37688
+ tagsForApi[key] = value;
37689
+ }
37690
+ }
37691
+ try {
37692
+ if (this.type === "bot") {
37693
+ await this.client.updateBot({ id: this.id, tags: tagsForApi });
37694
+ } else if (this.type === "user") {
37695
+ await this.client.updateUser({ id: this.id, tags: tagsForApi });
37696
+ } else if (this.type === "conversation") {
37697
+ await this.client.updateConversation({ id: this.id, tags: tagsForApi });
37698
+ } else if (this.type === "workflow") {
37699
+ await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
37700
+ }
37701
+ } catch (err) {
37702
+ console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
37703
+ throw err;
37704
+ }
37705
+ }
37706
+ };
37707
+ }
37708
+ });
37709
+
37316
37710
  // src/runtime/context/inspector-handler.ts
37317
37711
  var init_inspector_handler = __esm({
37318
37712
  "src/runtime/context/inspector-handler.ts"() {
@@ -37394,6 +37788,7 @@ var init_handlers = __esm({
37394
37788
  init_http();
37395
37789
  init_agent_registry();
37396
37790
  init_tracked_state();
37791
+ init_tracked_tags();
37397
37792
  init_tracing();
37398
37793
  init_heavy_imports();
37399
37794
  init_environment();
@@ -48339,7 +48734,7 @@ var init_primitives = __esm({
48339
48734
  });
48340
48735
 
48341
48736
  // src/runtime/handlers/workflow.ts
48342
- var import_ms2;
48737
+ var import_ms3;
48343
48738
  var init_workflow2 = __esm({
48344
48739
  "src/runtime/handlers/workflow.ts"() {
48345
48740
  "use strict";
@@ -48351,7 +48746,7 @@ var init_workflow2 = __esm({
48351
48746
  init_tracing();
48352
48747
  init_adk();
48353
48748
  init_workflow_utils();
48354
- import_ms2 = __toESM(require_ms(), 1);
48749
+ import_ms3 = __toESM(require_ms(), 1);
48355
48750
  }
48356
48751
  });
48357
48752
 
@@ -48395,259 +48790,6 @@ var init_handlers2 = __esm({
48395
48790
  }
48396
48791
  });
48397
48792
 
48398
- // src/runtime/tracked-tags.ts
48399
- var TrackedTags;
48400
- var init_tracked_tags = __esm({
48401
- "src/runtime/tracked-tags.ts"() {
48402
- "use strict";
48403
- init_define_BUILD();
48404
- init_define_PACKAGE_VERSIONS();
48405
- init_context();
48406
- init_tracing();
48407
- TrackedTags = class _TrackedTags {
48408
- type;
48409
- id;
48410
- client;
48411
- _tags = {};
48412
- _initialTags = {};
48413
- _loaded = false;
48414
- _saving = false;
48415
- _saveAgain = false;
48416
- _saveAgainCount = 0;
48417
- static _savingAll = false;
48418
- static _saveAllAgain = false;
48419
- static _saveAllCount = 0;
48420
- constructor(props) {
48421
- this.type = props.type;
48422
- this.id = props.id;
48423
- this.client = props.client;
48424
- }
48425
- static create(props) {
48426
- const tags = context.get("tags", { optional: true });
48427
- const executionFinished = context.get("executionFinished", { optional: true });
48428
- if (executionFinished) {
48429
- throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
48430
- }
48431
- const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
48432
- if (match2) {
48433
- return match2;
48434
- }
48435
- const instance = new _TrackedTags(props);
48436
- if (props.initialTags) {
48437
- instance._tags = { ...props.initialTags };
48438
- instance._initialTags = { ...props.initialTags };
48439
- instance._loaded = true;
48440
- }
48441
- tags?.push(instance);
48442
- return instance;
48443
- }
48444
- static async saveAllDirty() {
48445
- if (this._savingAll) {
48446
- this._saveAllAgain = true;
48447
- return;
48448
- }
48449
- try {
48450
- this._savingAll = true;
48451
- const tags = context.get("tags", { optional: true });
48452
- const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
48453
- if (!dirtyTags.length) {
48454
- return;
48455
- }
48456
- await span(
48457
- "tags.saveAllDirty",
48458
- {
48459
- tags_count: tags?.length || 0,
48460
- tags: tags.map((t) => `${t.type}/${t.id}`)
48461
- },
48462
- () => Promise.allSettled(dirtyTags.map((t) => t.save()))
48463
- );
48464
- } finally {
48465
- this._savingAll = false;
48466
- if (this._saveAllAgain && this._saveAllCount++ <= 5) {
48467
- this._saveAllAgain = false;
48468
- await this.saveAllDirty();
48469
- } else {
48470
- this._saveAllCount = 0;
48471
- }
48472
- }
48473
- }
48474
- static async loadAll() {
48475
- await span("tags.loadAll", {}, async () => {
48476
- const client2 = context.get("client")._inner;
48477
- const bot2 = context.get("bot", { optional: true });
48478
- const user2 = context.get("user", { optional: true });
48479
- const conversation = context.get("conversation", { optional: true });
48480
- const workflow = context.get("workflow", { optional: true });
48481
- if (bot2) {
48482
- const botTags = bot2.tags;
48483
- _TrackedTags.create({
48484
- client: client2,
48485
- type: "bot",
48486
- id: bot2.id,
48487
- ...botTags && { initialTags: botTags }
48488
- });
48489
- }
48490
- if (user2) {
48491
- const userTags = user2.tags;
48492
- _TrackedTags.create({
48493
- client: client2,
48494
- type: "user",
48495
- id: user2.id,
48496
- ...userTags && { initialTags: userTags }
48497
- });
48498
- }
48499
- if (conversation) {
48500
- const conversationTags = conversation.tags;
48501
- _TrackedTags.create({
48502
- client: client2,
48503
- type: "conversation",
48504
- id: conversation.id,
48505
- ...conversationTags && { initialTags: conversationTags }
48506
- });
48507
- }
48508
- if (workflow) {
48509
- const workflowTags = workflow.tags;
48510
- _TrackedTags.create({
48511
- client: client2,
48512
- type: "workflow",
48513
- id: workflow.id,
48514
- ...workflowTags && { initialTags: workflowTags }
48515
- });
48516
- }
48517
- const tags = context.get("tags", { optional: true });
48518
- const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
48519
- if (unloadedTags.length > 0) {
48520
- await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
48521
- }
48522
- });
48523
- }
48524
- static unloadAll() {
48525
- context.get("tags", { optional: true })?.splice(0);
48526
- }
48527
- async load(force = false) {
48528
- if (this._loaded && !force) {
48529
- return;
48530
- }
48531
- await span(
48532
- "tags.load",
48533
- {
48534
- type: this.type,
48535
- id: this.id
48536
- },
48537
- async () => {
48538
- const tags = await this.fetchTags();
48539
- this._tags = { ...tags };
48540
- this._initialTags = { ...tags };
48541
- this._loaded = true;
48542
- }
48543
- );
48544
- }
48545
- async save() {
48546
- if (this._saving) {
48547
- this._saveAgain = true;
48548
- return;
48549
- }
48550
- const executionFinished = context.get("executionFinished", { optional: true });
48551
- if (executionFinished) {
48552
- throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
48553
- }
48554
- try {
48555
- this._saving = true;
48556
- await span(
48557
- "tags.save",
48558
- {
48559
- type: this.type,
48560
- id: this.id
48561
- },
48562
- async () => {
48563
- await this.persistTags(this._tags);
48564
- this._initialTags = { ...this._tags };
48565
- }
48566
- );
48567
- } finally {
48568
- this._saving = false;
48569
- if (this._saveAgain && this._saveAgainCount++ <= 5) {
48570
- this._saveAgain = false;
48571
- await this.save();
48572
- } else {
48573
- this._saveAgainCount = 0;
48574
- }
48575
- }
48576
- }
48577
- isDirty() {
48578
- const currentKeys = Object.keys(this._tags).sort();
48579
- const initialKeys = Object.keys(this._initialTags).sort();
48580
- if (currentKeys.length !== initialKeys.length) {
48581
- return true;
48582
- }
48583
- for (const key of currentKeys) {
48584
- if (this._tags[key] !== this._initialTags[key]) {
48585
- return true;
48586
- }
48587
- }
48588
- return false;
48589
- }
48590
- get tags() {
48591
- return new Proxy(this._tags, {
48592
- set: (target, prop, value) => {
48593
- target[prop] = value;
48594
- return true;
48595
- },
48596
- deleteProperty: (target, prop) => {
48597
- target[prop] = void 0;
48598
- return true;
48599
- }
48600
- });
48601
- }
48602
- set tags(value) {
48603
- this._tags = { ...value };
48604
- }
48605
- async fetchTags() {
48606
- try {
48607
- if (this.type === "bot") {
48608
- const { bot: bot2 } = await this.client.getBot({ id: this.id });
48609
- return bot2.tags || {};
48610
- } else if (this.type === "user") {
48611
- const { user: user2 } = await this.client.getUser({ id: this.id });
48612
- return user2.tags || {};
48613
- } else if (this.type === "conversation") {
48614
- const { conversation } = await this.client.getConversation({ id: this.id });
48615
- return conversation.tags || {};
48616
- } else if (this.type === "workflow") {
48617
- const { workflow } = await this.client.getWorkflow({ id: this.id });
48618
- return workflow.tags || {};
48619
- }
48620
- } catch (err) {
48621
- console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
48622
- }
48623
- return {};
48624
- }
48625
- async persistTags(tags) {
48626
- const tagsForApi = {};
48627
- for (const [key, value] of Object.entries(tags)) {
48628
- if (value !== void 0) {
48629
- tagsForApi[key] = value;
48630
- }
48631
- }
48632
- try {
48633
- if (this.type === "bot") {
48634
- await this.client.updateBot({ id: this.id, tags: tagsForApi });
48635
- } else if (this.type === "user") {
48636
- await this.client.updateUser({ id: this.id, tags: tagsForApi });
48637
- } else if (this.type === "conversation") {
48638
- await this.client.updateConversation({ id: this.id, tags: tagsForApi });
48639
- } else if (this.type === "workflow") {
48640
- await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
48641
- }
48642
- } catch (err) {
48643
- console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
48644
- throw err;
48645
- }
48646
- }
48647
- };
48648
- }
48649
- });
48650
-
48651
48793
  // src/runtime/client.ts
48652
48794
  import { Client as Client3 } from "@botpress/client";
48653
48795
  function getStandaloneClient() {
@@ -48762,6 +48904,7 @@ export {
48762
48904
  configuration,
48763
48905
  context,
48764
48906
  defineConfig,
48907
+ isEventOfType,
48765
48908
  isWorkflowCallback,
48766
48909
  isWorkflowDataRequest,
48767
48910
  user,