@botpress/runtime 1.13.9 → 1.13.11

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 (36) 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 +438 -293
  4. package/dist/definition.js.map +4 -4
  5. package/dist/internal.js +532 -387
  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 +465 -287
  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 +21 -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/trigger.d.ts.map +1 -1
  27. package/dist/runtime/handlers/workflow.d.ts.map +1 -1
  28. package/dist/runtime/tracked-tags.d.ts +2 -0
  29. package/dist/runtime/tracked-tags.d.ts.map +1 -1
  30. package/dist/runtime.js +503 -317
  31. package/dist/runtime.js.map +4 -4
  32. package/dist/utilities/events.d.ts +28 -0
  33. package/dist/utilities/events.d.ts.map +1 -1
  34. package/dist/utilities/validate-event-name.d.ts +20 -0
  35. package/dist/utilities/validate-event-name.d.ts.map +1 -0
  36. 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.11", adk: "1.13.11", sdk: "5.0.2", llmz: "0.0.37", zai: "2.5.6", cognitive: "0.3.3" };
52
52
  }
53
53
  });
54
54
 
@@ -79,7 +79,7 @@ var init_singletons = __esm({
79
79
 
80
80
  // src/runtime/context/context.ts
81
81
  import { AsyncLocalStorage } from "async_hooks";
82
- var storage, context;
82
+ var storage, defaultContext, context;
83
83
  var init_context = __esm({
84
84
  "src/runtime/context/context.ts"() {
85
85
  "use strict";
@@ -87,6 +87,7 @@ var init_context = __esm({
87
87
  init_define_PACKAGE_VERSIONS();
88
88
  init_singletons();
89
89
  storage = getSingleton("__ADK_GLOBAL_CTX_STORAGE", () => new AsyncLocalStorage());
90
+ defaultContext = getSingleton("__ADK_GLOBAL_DEFAULT_CTX", () => ({ value: null }));
90
91
  context = {
91
92
  enterWith: (data) => {
92
93
  storage.enterWith(data);
@@ -105,7 +106,10 @@ var init_context = __esm({
105
106
  return store;
106
107
  },
107
108
  get: (key, opts) => {
108
- const store = storage.getStore();
109
+ let store = storage.getStore();
110
+ if (!store && defaultContext.value) {
111
+ store = defaultContext.value;
112
+ }
109
113
  if (store) {
110
114
  store.states ??= [];
111
115
  store.tags ??= [];
@@ -121,6 +125,28 @@ var init_context = __esm({
121
125
  const store = storage.getStore();
122
126
  if (!store) throw new Error("Cannot set context outside of `run`");
123
127
  store[key] = value;
128
+ },
129
+ /**
130
+ * Set a default context that will be used as a fallback when no AsyncLocalStorage context is active.
131
+ * This is useful for testing and script execution where code runs outside of request handlers.
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * context.setDefaultContext({
136
+ * botId: 'my-bot',
137
+ * integrations: agentRegistry.integrations,
138
+ * interfaces: agentRegistry.interfaces,
139
+ * })
140
+ * ```
141
+ */
142
+ setDefaultContext: (data) => {
143
+ defaultContext.value = data;
144
+ },
145
+ /**
146
+ * Clear the default context.
147
+ */
148
+ clearDefaultContext: () => {
149
+ defaultContext.value = null;
124
150
  }
125
151
  };
126
152
  }
@@ -27795,41 +27821,41 @@ var require_ms = __commonJS({
27795
27821
  return void 0;
27796
27822
  }
27797
27823
  }
27798
- function fmtShort(ms3) {
27799
- var msAbs = Math.abs(ms3);
27824
+ function fmtShort(ms4) {
27825
+ var msAbs = Math.abs(ms4);
27800
27826
  if (msAbs >= d) {
27801
- return Math.round(ms3 / d) + "d";
27827
+ return Math.round(ms4 / d) + "d";
27802
27828
  }
27803
27829
  if (msAbs >= h) {
27804
- return Math.round(ms3 / h) + "h";
27830
+ return Math.round(ms4 / h) + "h";
27805
27831
  }
27806
27832
  if (msAbs >= m) {
27807
- return Math.round(ms3 / m) + "m";
27833
+ return Math.round(ms4 / m) + "m";
27808
27834
  }
27809
27835
  if (msAbs >= s) {
27810
- return Math.round(ms3 / s) + "s";
27836
+ return Math.round(ms4 / s) + "s";
27811
27837
  }
27812
- return ms3 + "ms";
27838
+ return ms4 + "ms";
27813
27839
  }
27814
- function fmtLong(ms3) {
27815
- var msAbs = Math.abs(ms3);
27840
+ function fmtLong(ms4) {
27841
+ var msAbs = Math.abs(ms4);
27816
27842
  if (msAbs >= d) {
27817
- return plural(ms3, msAbs, d, "day");
27843
+ return plural(ms4, msAbs, d, "day");
27818
27844
  }
27819
27845
  if (msAbs >= h) {
27820
- return plural(ms3, msAbs, h, "hour");
27846
+ return plural(ms4, msAbs, h, "hour");
27821
27847
  }
27822
27848
  if (msAbs >= m) {
27823
- return plural(ms3, msAbs, m, "minute");
27849
+ return plural(ms4, msAbs, m, "minute");
27824
27850
  }
27825
27851
  if (msAbs >= s) {
27826
- return plural(ms3, msAbs, s, "second");
27852
+ return plural(ms4, msAbs, s, "second");
27827
27853
  }
27828
- return ms3 + " ms";
27854
+ return ms4 + " ms";
27829
27855
  }
27830
- function plural(ms3, msAbs, n, name) {
27856
+ function plural(ms4, msAbs, n, name) {
27831
27857
  var isPlural = msAbs >= n * 1.5;
27832
- return Math.round(ms3 / n) + " " + name + (isPlural ? "s" : "");
27858
+ return Math.round(ms4 / n) + " " + name + (isPlural ? "s" : "");
27833
27859
  }
27834
27860
  }
27835
27861
  });
@@ -27874,8 +27900,8 @@ var require_common = __commonJS({
27874
27900
  }
27875
27901
  const self2 = debug;
27876
27902
  const curr = Number(/* @__PURE__ */ new Date());
27877
- const ms3 = curr - (prevTime || curr);
27878
- self2.diff = ms3;
27903
+ const ms4 = curr - (prevTime || curr);
27904
+ self2.diff = ms4;
27879
27905
  self2.prev = prevTime;
27880
27906
  self2.curr = curr;
27881
27907
  prevTime = curr;
@@ -34476,6 +34502,9 @@ Always prefer information from the knowledge bases over general knowledge when a
34476
34502
  ...props.hooks?.onBeforeTool && {
34477
34503
  onBeforeTool: asyncResource.bind(props.hooks.onBeforeTool)
34478
34504
  },
34505
+ ...props.hooks?.onIterationStart && {
34506
+ onIterationStart: asyncResource.bind(props.hooks.onIterationStart)
34507
+ },
34479
34508
  ...props.hooks?.onAfterTool && {
34480
34509
  onAfterTool: asyncResource.bind(props.hooks.onAfterTool)
34481
34510
  },
@@ -34605,7 +34634,7 @@ var init_actions = __esm({
34605
34634
  }
34606
34635
  integrations ??= context.get("integrations", { optional: true });
34607
34636
  client2 ??= context.get("client", { optional: true });
34608
- const integration = integrations.find((i) => i.alias === integrationName);
34637
+ const integration = integrations?.find((i) => i.alias === integrationName);
34609
34638
  const actionDef = integration?.definition.actions?.[actionName];
34610
34639
  const handler = async (params) => {
34611
34640
  integrations ??= context.get("integrations", { optional: true });
@@ -35045,15 +35074,51 @@ var init_validate_tag_name = __esm({
35045
35074
  }
35046
35075
  });
35047
35076
 
35077
+ // src/utilities/validate-event-name.ts
35078
+ function validateEventName(name) {
35079
+ if (!name || typeof name !== "string") {
35080
+ return { valid: false, error: "Event name must be a non-empty string" };
35081
+ }
35082
+ if (name.length > 100) {
35083
+ return { valid: false, error: `Event name "${name}" must be less than 100 characters` };
35084
+ }
35085
+ if (!/^[a-zA-Z]/.test(name)) {
35086
+ return { valid: false, error: `Event name "${name}" must start with a letter` };
35087
+ }
35088
+ if (!/^[a-zA-Z0-9_]+$/.test(name)) {
35089
+ return {
35090
+ valid: false,
35091
+ error: `Event name "${name}" can only contain letters (A-Z, a-z), numbers (0-9), and underscores (_)`
35092
+ };
35093
+ }
35094
+ return { valid: true };
35095
+ }
35096
+ function validateEventDefinitions(events, context3) {
35097
+ for (const eventName of Object.keys(events)) {
35098
+ const validation = validateEventName(eventName);
35099
+ if (!validation.valid) {
35100
+ throw new Error(`Invalid event name in ${context3}: ${validation.error}`);
35101
+ }
35102
+ }
35103
+ }
35104
+ var init_validate_event_name = __esm({
35105
+ "src/utilities/validate-event-name.ts"() {
35106
+ "use strict";
35107
+ init_define_BUILD();
35108
+ init_define_PACKAGE_VERSIONS();
35109
+ }
35110
+ });
35111
+
35048
35112
  // src/define-config.ts
35049
35113
  import { z as z3 } from "@botpress/sdk";
35050
- var zuiSchema, modelSchema, tagDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, defineConfig;
35114
+ var zuiSchema, modelSchema, tagDefinitionSchema, eventDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, defineConfig;
35051
35115
  var init_define_config = __esm({
35052
35116
  "src/define-config.ts"() {
35053
35117
  "use strict";
35054
35118
  init_define_BUILD();
35055
35119
  init_define_PACKAGE_VERSIONS();
35056
35120
  init_validate_tag_name();
35121
+ init_validate_event_name();
35057
35122
  zuiSchema = z3.custom(
35058
35123
  (val) => {
35059
35124
  if (typeof val === "object" && val !== null && "parse" in val) {
@@ -35078,6 +35143,13 @@ var init_define_config = __esm({
35078
35143
  description: z3.string().optional()
35079
35144
  })
35080
35145
  );
35146
+ eventDefinitionSchema = z3.record(
35147
+ z3.string(),
35148
+ z3.object({
35149
+ schema: zuiSchema.optional(),
35150
+ description: z3.string().optional()
35151
+ })
35152
+ );
35081
35153
  configSchema = z3.object({
35082
35154
  name: z3.string().optional(),
35083
35155
  description: z3.string().optional(),
@@ -35118,7 +35190,8 @@ var init_define_config = __esm({
35118
35190
  zai: val?.zai ?? "openai:gpt-4.1-2025-04-14",
35119
35191
  autonomous: val?.autonomous ?? "openai:gpt-4.1-mini-2025-04-14"
35120
35192
  })),
35121
- dependencies: z3.custom()
35193
+ dependencies: z3.custom(),
35194
+ events: eventDefinitionSchema.optional()
35122
35195
  });
35123
35196
  AGENT_CONFIG_BRAND = Symbol.for("@botpress/runtime/AgentConfig");
35124
35197
  defineConfig = (config) => {
@@ -35138,6 +35211,9 @@ var init_define_config = __esm({
35138
35211
  if (parsed.workflow?.tags) {
35139
35212
  validateTagDefinitions(parsed.workflow.tags, "workflow.tags");
35140
35213
  }
35214
+ if (parsed.events) {
35215
+ validateEventDefinitions(parsed.events, "events");
35216
+ }
35141
35217
  return {
35142
35218
  ...parsed,
35143
35219
  __brand: "AgentConfig",
@@ -35912,6 +35988,9 @@ function isEventMessage(event) {
35912
35988
  function isWorkflowCallback(event) {
35913
35989
  return event !== null && typeof event === "object" && "type" in event && event.type === "workflowCallback" && "payload" in event && event.payload !== null && typeof event.payload === "object";
35914
35990
  }
35991
+ function isEventOfType(event, eventName) {
35992
+ return isEvent(event) && event.type === eventName;
35993
+ }
35915
35994
  var init_events = __esm({
35916
35995
  "src/utilities/events.ts"() {
35917
35996
  "use strict";
@@ -36185,12 +36264,12 @@ var init_workflow_step = __esm({
36185
36264
  workflowControlContext.abort();
36186
36265
  throw createStepSignal();
36187
36266
  };
36188
- step.sleep = async (name, ms3) => {
36267
+ step.sleep = async (name, ms4) => {
36189
36268
  await _step(
36190
36269
  name,
36191
36270
  async () => {
36192
36271
  const remainingTime = context.get("runtime").getRemainingExecutionTimeInMs();
36193
- if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms3 || ms3 >= 1e4) {
36272
+ if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms4 || ms4 >= 1e4) {
36194
36273
  const client2 = context.get("client");
36195
36274
  const workflowControlContext = context.get("workflowControlContext");
36196
36275
  await client2.createEvent({
@@ -36198,7 +36277,7 @@ var init_workflow_step = __esm({
36198
36277
  payload: {},
36199
36278
  workflowId: workflowControlContext.workflow.id,
36200
36279
  schedule: {
36201
- delay: ms3
36280
+ delay: ms4
36202
36281
  }
36203
36282
  });
36204
36283
  await updateWorkflow({
@@ -36207,7 +36286,7 @@ var init_workflow_step = __esm({
36207
36286
  });
36208
36287
  workflowControlContext.abort();
36209
36288
  } else {
36210
- await new Promise((resolve) => void setTimeout(resolve, ms3));
36289
+ await new Promise((resolve) => void setTimeout(resolve, ms4));
36211
36290
  context.get("workflowControlContext").signal.throwIfAborted();
36212
36291
  }
36213
36292
  },
@@ -36218,8 +36297,8 @@ var init_workflow_step = __esm({
36218
36297
  );
36219
36298
  };
36220
36299
  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);
36300
+ const ms4 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
36301
+ await step.sleep(name, ms4);
36223
36302
  };
36224
36303
  step.waitForWorkflow = async (name, workflowId) => {
36225
36304
  const workflowControlContext = context.get("workflowControlContext");
@@ -36438,12 +36517,13 @@ function createWorkflowExecutionState(client2, workflowId) {
36438
36517
  name: BUILT_IN_STATES.workflowSteps
36439
36518
  });
36440
36519
  }
36441
- var workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
36520
+ var import_ms2, workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
36442
36521
  var init_workflow_instance = __esm({
36443
36522
  "src/primitives/workflow-instance.ts"() {
36444
36523
  "use strict";
36445
36524
  init_define_BUILD();
36446
36525
  init_define_PACKAGE_VERSIONS();
36526
+ import_ms2 = __toESM(require_ms(), 1);
36447
36527
  init_errors();
36448
36528
  init_library();
36449
36529
  init_autonomous();
@@ -36570,6 +36650,81 @@ var init_workflow_instance = __esm({
36570
36650
  });
36571
36651
  Object.assign(this.workflow, workflow);
36572
36652
  }
36653
+ /**
36654
+ * Extend the workflow timeout by setting a new timeout.
36655
+ * This is useful for long-running workflows that need more time to complete.
36656
+ *
36657
+ * @param options - Either `{ in: string }` for relative duration or `{ at: string }` for absolute ISO timestamp
36658
+ * @returns A promise that resolves when the timeout is updated (can be awaited or not)
36659
+ * @example
36660
+ * // Relative timeout (duration from now):
36661
+ * workflow.setTimeout({ in: '30m' }) // Timeout in 30 minutes
36662
+ * workflow.setTimeout({ in: '6 hours' }) // Timeout in 6 hours
36663
+ *
36664
+ * // Absolute timeout (ISO timestamp):
36665
+ * workflow.setTimeout({ at: '2024-12-25T00:00:00Z' })
36666
+ *
36667
+ * // Optionally await if you need to ensure the update completes:
36668
+ * await workflow.setTimeout({ in: '1h' })
36669
+ */
36670
+ setTimeout(options) {
36671
+ let newTimeoutAt;
36672
+ if ("in" in options) {
36673
+ const durationMs = (0, import_ms2.default)(options.in);
36674
+ if (!durationMs) {
36675
+ throw new Error(`Invalid duration format: "${options.in}". Use formats like "30m", "1h", "6 hours".`);
36676
+ }
36677
+ newTimeoutAt = new Date(Date.now() + durationMs).toISOString();
36678
+ } else {
36679
+ const date = new Date(options.at);
36680
+ if (isNaN(date.getTime())) {
36681
+ throw new Error(`Invalid ISO date format: "${options.at}".`);
36682
+ }
36683
+ newTimeoutAt = date.toISOString();
36684
+ }
36685
+ return updateWorkflow({
36686
+ id: this.id,
36687
+ timeoutAt: newTimeoutAt
36688
+ }).then(({ workflow }) => {
36689
+ Object.assign(this.workflow, workflow);
36690
+ });
36691
+ }
36692
+ /**
36693
+ * Fail the workflow with an error reason.
36694
+ * This immediately interrupts the workflow handler and marks the workflow as failed.
36695
+ * Can only be called from within a workflow handler.
36696
+ *
36697
+ * @param reason - The error reason for the failure
36698
+ * @throws Never returns - always throws to interrupt the handler
36699
+ * @example
36700
+ * workflow.fail('Invalid input data')
36701
+ */
36702
+ fail(reason) {
36703
+ const controlContext = context.get("workflowControlContext", { optional: true });
36704
+ if (!controlContext || controlContext.workflow.id !== this.id) {
36705
+ throw new Error("workflow.fail() can only be called from within the workflow handler");
36706
+ }
36707
+ controlContext.fail(reason);
36708
+ throw createStepSignal();
36709
+ }
36710
+ /**
36711
+ * Complete the workflow early with the given output.
36712
+ * This immediately interrupts the workflow handler and marks the workflow as completed.
36713
+ * Can only be called from within a workflow handler.
36714
+ *
36715
+ * @param output - The workflow output (typed according to workflow definition)
36716
+ * @throws Never returns - always throws to interrupt the handler
36717
+ * @example
36718
+ * workflow.complete({ result: 'success', data: processedData })
36719
+ */
36720
+ complete(output2) {
36721
+ const controlContext = context.get("workflowControlContext", { optional: true });
36722
+ if (!controlContext || controlContext.workflow.id !== this.id) {
36723
+ throw new Error("workflow.complete() can only be called from within the workflow handler");
36724
+ }
36725
+ controlContext.complete(output2);
36726
+ throw createStepSignal();
36727
+ }
36573
36728
  /**
36574
36729
  * Provide data in response to a workflow data request (instance method).
36575
36730
  * Call this method from a conversation handler when you receive a WorkflowDataRequestEvent.
@@ -36620,6 +36775,7 @@ var init_workflow_instance = __esm({
36620
36775
  workflow: this.workflow,
36621
36776
  aborted: false,
36622
36777
  failed: false,
36778
+ completed: false,
36623
36779
  acked: false,
36624
36780
  restarted: false,
36625
36781
  signal: abortSignal,
@@ -36634,6 +36790,10 @@ var init_workflow_instance = __esm({
36634
36790
  workflowControlContext.failed = true;
36635
36791
  workflowControlContext.failedReason = reason;
36636
36792
  },
36793
+ complete: (result) => {
36794
+ workflowControlContext.completed = true;
36795
+ workflowControlContext.completedResult = result;
36796
+ },
36637
36797
  ack: async () => {
36638
36798
  if (workflowControlContext.acked) {
36639
36799
  return;
@@ -36687,7 +36847,8 @@ var init_workflow_instance = __esm({
36687
36847
  step,
36688
36848
  client: this.client,
36689
36849
  execute: this.execute.bind(this),
36690
- signal: abortSignal
36850
+ signal: abortSignal,
36851
+ workflow: this
36691
36852
  });
36692
36853
  return {
36693
36854
  status: "done",
@@ -36698,6 +36859,12 @@ var init_workflow_instance = __esm({
36698
36859
  }
36699
36860
  } catch (err) {
36700
36861
  if (isStepSignal(err)) {
36862
+ if (workflowControlContext.completed) {
36863
+ return {
36864
+ status: "done",
36865
+ result: workflowControlContext.completedResult
36866
+ };
36867
+ }
36701
36868
  if (workflowControlContext.failed) {
36702
36869
  return {
36703
36870
  status: "error",
@@ -37313,6 +37480,268 @@ var init_tracked_state = __esm({
37313
37480
  }
37314
37481
  });
37315
37482
 
37483
+ // src/runtime/tracked-tags.ts
37484
+ function isSystemTag(key) {
37485
+ return key.includes(":");
37486
+ }
37487
+ var TrackedTags;
37488
+ var init_tracked_tags = __esm({
37489
+ "src/runtime/tracked-tags.ts"() {
37490
+ "use strict";
37491
+ init_define_BUILD();
37492
+ init_define_PACKAGE_VERSIONS();
37493
+ init_context();
37494
+ init_tracing();
37495
+ TrackedTags = class _TrackedTags {
37496
+ type;
37497
+ id;
37498
+ client;
37499
+ _tags = {};
37500
+ _initialTags = {};
37501
+ _loaded = false;
37502
+ _saving = false;
37503
+ _saveAgain = false;
37504
+ _saveAgainCount = 0;
37505
+ static _savingAll = false;
37506
+ static _saveAllAgain = false;
37507
+ static _saveAllCount = 0;
37508
+ constructor(props) {
37509
+ this.type = props.type;
37510
+ this.id = props.id;
37511
+ this.client = props.client;
37512
+ }
37513
+ static create(props) {
37514
+ const tags = context.get("tags", { optional: true });
37515
+ const executionFinished = context.get("executionFinished", { optional: true });
37516
+ if (executionFinished) {
37517
+ throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
37518
+ }
37519
+ const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
37520
+ if (match2) {
37521
+ return match2;
37522
+ }
37523
+ const instance = new _TrackedTags(props);
37524
+ if (props.initialTags) {
37525
+ instance._tags = { ...props.initialTags };
37526
+ instance._initialTags = { ...props.initialTags };
37527
+ instance._loaded = true;
37528
+ }
37529
+ tags?.push(instance);
37530
+ return instance;
37531
+ }
37532
+ static async saveAllDirty() {
37533
+ if (this._savingAll) {
37534
+ this._saveAllAgain = true;
37535
+ return;
37536
+ }
37537
+ try {
37538
+ this._savingAll = true;
37539
+ const tags = context.get("tags", { optional: true });
37540
+ const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
37541
+ if (!dirtyTags.length) {
37542
+ return;
37543
+ }
37544
+ await span(
37545
+ "tags.saveAllDirty",
37546
+ {
37547
+ tags_count: tags?.length || 0,
37548
+ tags: tags.map((t) => `${t.type}/${t.id}`)
37549
+ },
37550
+ () => Promise.allSettled(dirtyTags.map((t) => t.save()))
37551
+ );
37552
+ } finally {
37553
+ this._savingAll = false;
37554
+ if (this._saveAllAgain && this._saveAllCount++ <= 5) {
37555
+ this._saveAllAgain = false;
37556
+ await this.saveAllDirty();
37557
+ } else {
37558
+ this._saveAllCount = 0;
37559
+ }
37560
+ }
37561
+ }
37562
+ static async loadAll() {
37563
+ await span("tags.loadAll", {}, async () => {
37564
+ const client2 = context.get("client")._inner;
37565
+ const bot2 = context.get("bot", { optional: true });
37566
+ const user2 = context.get("user", { optional: true });
37567
+ const conversation = context.get("conversation", { optional: true });
37568
+ const workflow = context.get("workflow", { optional: true });
37569
+ if (bot2) {
37570
+ const botTags = bot2.tags;
37571
+ _TrackedTags.create({
37572
+ client: client2,
37573
+ type: "bot",
37574
+ id: bot2.id,
37575
+ ...botTags && { initialTags: botTags }
37576
+ });
37577
+ }
37578
+ if (user2) {
37579
+ const userTags = user2.tags;
37580
+ _TrackedTags.create({
37581
+ client: client2,
37582
+ type: "user",
37583
+ id: user2.id,
37584
+ ...userTags && { initialTags: userTags }
37585
+ });
37586
+ }
37587
+ if (conversation) {
37588
+ const conversationTags = conversation.tags;
37589
+ _TrackedTags.create({
37590
+ client: client2,
37591
+ type: "conversation",
37592
+ id: conversation.id,
37593
+ ...conversationTags && { initialTags: conversationTags }
37594
+ });
37595
+ }
37596
+ if (workflow) {
37597
+ const workflowTags = workflow.tags;
37598
+ _TrackedTags.create({
37599
+ client: client2,
37600
+ type: "workflow",
37601
+ id: workflow.id,
37602
+ ...workflowTags && { initialTags: workflowTags }
37603
+ });
37604
+ }
37605
+ const tags = context.get("tags", { optional: true });
37606
+ const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
37607
+ if (unloadedTags.length > 0) {
37608
+ await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
37609
+ }
37610
+ });
37611
+ }
37612
+ static unloadAll() {
37613
+ context.get("tags", { optional: true })?.splice(0);
37614
+ }
37615
+ async load(force = false) {
37616
+ if (this._loaded && !force) {
37617
+ return;
37618
+ }
37619
+ await span(
37620
+ "tags.load",
37621
+ {
37622
+ type: this.type,
37623
+ id: this.id
37624
+ },
37625
+ async () => {
37626
+ const tags = await this.fetchTags();
37627
+ this._tags = { ...tags };
37628
+ this._initialTags = { ...tags };
37629
+ this._loaded = true;
37630
+ }
37631
+ );
37632
+ }
37633
+ async save() {
37634
+ if (this._saving) {
37635
+ this._saveAgain = true;
37636
+ return;
37637
+ }
37638
+ const executionFinished = context.get("executionFinished", { optional: true });
37639
+ if (executionFinished) {
37640
+ throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
37641
+ }
37642
+ try {
37643
+ this._saving = true;
37644
+ await span(
37645
+ "tags.save",
37646
+ {
37647
+ type: this.type,
37648
+ id: this.id
37649
+ },
37650
+ async () => {
37651
+ await this.persistTags(this._tags);
37652
+ this._initialTags = { ...this._tags };
37653
+ }
37654
+ );
37655
+ } finally {
37656
+ this._saving = false;
37657
+ if (this._saveAgain && this._saveAgainCount++ <= 5) {
37658
+ this._saveAgain = false;
37659
+ await this.save();
37660
+ } else {
37661
+ this._saveAgainCount = 0;
37662
+ }
37663
+ }
37664
+ }
37665
+ isDirty() {
37666
+ const currentKeys = Object.keys(this._tags).filter((k) => !isSystemTag(k)).sort();
37667
+ const initialKeys = Object.keys(this._initialTags).filter((k) => !isSystemTag(k)).sort();
37668
+ if (currentKeys.length !== initialKeys.length) {
37669
+ return true;
37670
+ }
37671
+ for (const key of currentKeys) {
37672
+ if (this._tags[key] !== this._initialTags[key]) {
37673
+ return true;
37674
+ }
37675
+ }
37676
+ return false;
37677
+ }
37678
+ get tags() {
37679
+ return new Proxy(this._tags, {
37680
+ set: (target, prop, value) => {
37681
+ if (isSystemTag(prop)) {
37682
+ return true;
37683
+ }
37684
+ target[prop] = value;
37685
+ return true;
37686
+ },
37687
+ deleteProperty: (target, prop) => {
37688
+ if (isSystemTag(prop)) {
37689
+ return true;
37690
+ }
37691
+ target[prop] = void 0;
37692
+ return true;
37693
+ }
37694
+ });
37695
+ }
37696
+ set tags(value) {
37697
+ this._tags = { ...value };
37698
+ }
37699
+ async fetchTags() {
37700
+ try {
37701
+ if (this.type === "bot") {
37702
+ const { bot: bot2 } = await this.client.getBot({ id: this.id });
37703
+ return bot2.tags || {};
37704
+ } else if (this.type === "user") {
37705
+ const { user: user2 } = await this.client.getUser({ id: this.id });
37706
+ return user2.tags || {};
37707
+ } else if (this.type === "conversation") {
37708
+ const { conversation } = await this.client.getConversation({ id: this.id });
37709
+ return conversation.tags || {};
37710
+ } else if (this.type === "workflow") {
37711
+ const { workflow } = await this.client.getWorkflow({ id: this.id });
37712
+ return workflow.tags || {};
37713
+ }
37714
+ } catch (err) {
37715
+ console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
37716
+ }
37717
+ return {};
37718
+ }
37719
+ async persistTags(tags) {
37720
+ const tagsForApi = {};
37721
+ for (const [key, value] of Object.entries(tags)) {
37722
+ if (value !== void 0 && !isSystemTag(key)) {
37723
+ tagsForApi[key] = value;
37724
+ }
37725
+ }
37726
+ try {
37727
+ if (this.type === "bot") {
37728
+ await this.client.updateBot({ id: this.id, tags: tagsForApi });
37729
+ } else if (this.type === "user") {
37730
+ await this.client.updateUser({ id: this.id, tags: tagsForApi });
37731
+ } else if (this.type === "conversation") {
37732
+ await this.client.updateConversation({ id: this.id, tags: tagsForApi });
37733
+ } else if (this.type === "workflow") {
37734
+ await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
37735
+ }
37736
+ } catch (err) {
37737
+ console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
37738
+ throw err;
37739
+ }
37740
+ }
37741
+ };
37742
+ }
37743
+ });
37744
+
37316
37745
  // src/runtime/context/inspector-handler.ts
37317
37746
  var init_inspector_handler = __esm({
37318
37747
  "src/runtime/context/inspector-handler.ts"() {
@@ -37394,6 +37823,7 @@ var init_handlers = __esm({
37394
37823
  init_http();
37395
37824
  init_agent_registry();
37396
37825
  init_tracked_state();
37826
+ init_tracked_tags();
37397
37827
  init_tracing();
37398
37828
  init_heavy_imports();
37399
37829
  init_environment();
@@ -48339,7 +48769,7 @@ var init_primitives = __esm({
48339
48769
  });
48340
48770
 
48341
48771
  // src/runtime/handlers/workflow.ts
48342
- var import_ms2;
48772
+ var import_ms3;
48343
48773
  var init_workflow2 = __esm({
48344
48774
  "src/runtime/handlers/workflow.ts"() {
48345
48775
  "use strict";
@@ -48351,7 +48781,7 @@ var init_workflow2 = __esm({
48351
48781
  init_tracing();
48352
48782
  init_adk();
48353
48783
  init_workflow_utils();
48354
- import_ms2 = __toESM(require_ms(), 1);
48784
+ import_ms3 = __toESM(require_ms(), 1);
48355
48785
  }
48356
48786
  });
48357
48787
 
@@ -48395,259 +48825,6 @@ var init_handlers2 = __esm({
48395
48825
  }
48396
48826
  });
48397
48827
 
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
48828
  // src/runtime/client.ts
48652
48829
  import { Client as Client3 } from "@botpress/client";
48653
48830
  function getStandaloneClient() {
@@ -48762,6 +48939,7 @@ export {
48762
48939
  configuration,
48763
48940
  context,
48764
48941
  defineConfig,
48942
+ isEventOfType,
48765
48943
  isWorkflowCallback,
48766
48944
  isWorkflowDataRequest,
48767
48945
  user,