@botpress/runtime 1.13.8 → 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 (40) 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 +406 -378
  4. package/dist/definition.js.map +4 -4
  5. package/dist/internal.js +500 -472
  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 +433 -372
  10. package/dist/library.js.map +4 -4
  11. package/dist/primitives/conversation-instance.d.ts +0 -8
  12. package/dist/primitives/conversation-instance.d.ts.map +1 -1
  13. package/dist/primitives/conversation.d.ts +24 -13
  14. package/dist/primitives/conversation.d.ts.map +1 -1
  15. package/dist/primitives/data-sources/source-base.d.ts +1 -1
  16. package/dist/primitives/data-sources/source-base.d.ts.map +1 -1
  17. package/dist/primitives/index.d.ts +1 -1
  18. package/dist/primitives/workflow-instance.d.ts +45 -1
  19. package/dist/primitives/workflow-instance.d.ts.map +1 -1
  20. package/dist/primitives/workflow.d.ts +3 -2
  21. package/dist/primitives/workflow.d.ts.map +1 -1
  22. package/dist/runtime/autonomous.d.ts +1 -0
  23. package/dist/runtime/autonomous.d.ts.map +1 -1
  24. package/dist/runtime/context/context.d.ts +3 -0
  25. package/dist/runtime/context/context.d.ts.map +1 -1
  26. package/dist/runtime/context/handlers.d.ts.map +1 -1
  27. package/dist/runtime/handlers/event.d.ts.map +1 -1
  28. package/dist/runtime/handlers/workflow.d.ts.map +1 -1
  29. package/dist/runtime/tracked-tags.d.ts.map +1 -1
  30. package/dist/runtime.d.ts +0 -1
  31. package/dist/runtime.d.ts.map +1 -1
  32. package/dist/runtime.js +457 -394
  33. package/dist/runtime.js.map +4 -4
  34. package/dist/utilities/events.d.ts +28 -0
  35. package/dist/utilities/events.d.ts.map +1 -1
  36. package/dist/utilities/validate-event-name.d.ts +20 -0
  37. package/dist/utilities/validate-event-name.d.ts.map +1 -0
  38. package/package.json +2 -2
  39. package/dist/utilities/trigger-tags.d.ts +0 -31
  40. package/dist/utilities/trigger-tags.d.ts.map +0 -1
package/dist/runtime.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.8", adk: "1.13.8", 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
 
@@ -25805,7 +25805,7 @@ var require_form_data = __commonJS({
25805
25805
  var parseUrl = __require("url").parse;
25806
25806
  var fs3 = __require("fs");
25807
25807
  var Stream2 = __require("stream").Stream;
25808
- var crypto3 = __require("crypto");
25808
+ var crypto2 = __require("crypto");
25809
25809
  var mime = require_mime_types();
25810
25810
  var asynckit = require_asynckit();
25811
25811
  var setToStringTag = require_es_set_tostringtag();
@@ -26011,7 +26011,7 @@ var require_form_data = __commonJS({
26011
26011
  return Buffer.concat([dataBuffer, Buffer.from(this._lastBoundary())]);
26012
26012
  };
26013
26013
  FormData3.prototype._generateBoundary = function() {
26014
- this._boundary = "--------------------------" + crypto3.randomBytes(12).toString("hex");
26014
+ this._boundary = "--------------------------" + crypto2.randomBytes(12).toString("hex");
26015
26015
  };
26016
26016
  FormData3.prototype.getLengthSync = function() {
26017
26017
  var knownLength = this._overheadLength + this._valueLength;
@@ -27286,41 +27286,41 @@ var require_ms = __commonJS({
27286
27286
  return void 0;
27287
27287
  }
27288
27288
  }
27289
- function fmtShort(ms3) {
27290
- var msAbs = Math.abs(ms3);
27289
+ function fmtShort(ms4) {
27290
+ var msAbs = Math.abs(ms4);
27291
27291
  if (msAbs >= d) {
27292
- return Math.round(ms3 / d) + "d";
27292
+ return Math.round(ms4 / d) + "d";
27293
27293
  }
27294
27294
  if (msAbs >= h) {
27295
- return Math.round(ms3 / h) + "h";
27295
+ return Math.round(ms4 / h) + "h";
27296
27296
  }
27297
27297
  if (msAbs >= m) {
27298
- return Math.round(ms3 / m) + "m";
27298
+ return Math.round(ms4 / m) + "m";
27299
27299
  }
27300
27300
  if (msAbs >= s) {
27301
- return Math.round(ms3 / s) + "s";
27301
+ return Math.round(ms4 / s) + "s";
27302
27302
  }
27303
- return ms3 + "ms";
27303
+ return ms4 + "ms";
27304
27304
  }
27305
- function fmtLong(ms3) {
27306
- var msAbs = Math.abs(ms3);
27305
+ function fmtLong(ms4) {
27306
+ var msAbs = Math.abs(ms4);
27307
27307
  if (msAbs >= d) {
27308
- return plural(ms3, msAbs, d, "day");
27308
+ return plural(ms4, msAbs, d, "day");
27309
27309
  }
27310
27310
  if (msAbs >= h) {
27311
- return plural(ms3, msAbs, h, "hour");
27311
+ return plural(ms4, msAbs, h, "hour");
27312
27312
  }
27313
27313
  if (msAbs >= m) {
27314
- return plural(ms3, msAbs, m, "minute");
27314
+ return plural(ms4, msAbs, m, "minute");
27315
27315
  }
27316
27316
  if (msAbs >= s) {
27317
- return plural(ms3, msAbs, s, "second");
27317
+ return plural(ms4, msAbs, s, "second");
27318
27318
  }
27319
- return ms3 + " ms";
27319
+ return ms4 + " ms";
27320
27320
  }
27321
- function plural(ms3, msAbs, n, name) {
27321
+ function plural(ms4, msAbs, n, name) {
27322
27322
  var isPlural = msAbs >= n * 1.5;
27323
- return Math.round(ms3 / n) + " " + name + (isPlural ? "s" : "");
27323
+ return Math.round(ms4 / n) + " " + name + (isPlural ? "s" : "");
27324
27324
  }
27325
27325
  }
27326
27326
  });
@@ -27365,8 +27365,8 @@ var require_common = __commonJS({
27365
27365
  }
27366
27366
  const self2 = debug;
27367
27367
  const curr = Number(/* @__PURE__ */ new Date());
27368
- const ms3 = curr - (prevTime || curr);
27369
- self2.diff = ms3;
27368
+ const ms4 = curr - (prevTime || curr);
27369
+ self2.diff = ms4;
27370
27370
  self2.prev = prevTime;
27371
27371
  self2.curr = curr;
27372
27372
  prevTime = curr;
@@ -33594,47 +33594,6 @@ var init_asset = __esm({
33594
33594
  }
33595
33595
  });
33596
33596
 
33597
- // src/utilities/trigger-tags.ts
33598
- var trigger_tags_exports = {};
33599
- __export(trigger_tags_exports, {
33600
- getTriggerSubscriptionTags: () => getTriggerSubscriptionTags,
33601
- getTriggerTagName: () => getTriggerTagName,
33602
- getTriggerTagValue: () => getTriggerTagValue,
33603
- isConversationSubscribedToTrigger: () => isConversationSubscribedToTrigger
33604
- });
33605
- import crypto2 from "crypto";
33606
- var hashString, getTriggerTagName, getTriggerTagValue, getTriggerSubscriptionTags, isConversationSubscribedToTrigger;
33607
- var init_trigger_tags = __esm({
33608
- "src/utilities/trigger-tags.ts"() {
33609
- "use strict";
33610
- init_define_BUILD();
33611
- init_define_PACKAGE_VERSIONS();
33612
- hashString = (str) => {
33613
- return crypto2.createHash("md5").update(str).digest("hex").substring(0, 5).toUpperCase();
33614
- };
33615
- getTriggerTagName = (triggerName) => {
33616
- return `trigger${hashString(triggerName)}`;
33617
- };
33618
- getTriggerTagValue = (key) => {
33619
- return key ?? "*";
33620
- };
33621
- getTriggerSubscriptionTags = (triggerName, key) => {
33622
- return {
33623
- name: getTriggerTagName(triggerName),
33624
- value: getTriggerTagValue(key)
33625
- };
33626
- };
33627
- isConversationSubscribedToTrigger = (conversationTags, triggerName, triggerKey) => {
33628
- const tagName = getTriggerTagName(triggerName);
33629
- const tagValue = conversationTags[tagName];
33630
- if (!tagValue) {
33631
- return false;
33632
- }
33633
- return tagValue === "*" || tagValue === triggerKey;
33634
- };
33635
- }
33636
- });
33637
-
33638
33597
  // src/primitives/conversation-instance.ts
33639
33598
  var BaseConversationInstance;
33640
33599
  var init_conversation_instance = __esm({
@@ -33749,38 +33708,6 @@ var init_conversation_instance = __esm({
33749
33708
  });
33750
33709
  }
33751
33710
  }
33752
- /**
33753
- * Subscribe to a trigger
33754
- */
33755
- async subscribeToTrigger(triggerName, key) {
33756
- const { getTriggerSubscriptionTags: getTriggerSubscriptionTags2, isConversationSubscribedToTrigger: isConversationSubscribedToTrigger2 } = await Promise.resolve().then(() => (init_trigger_tags(), trigger_tags_exports));
33757
- if (isConversationSubscribedToTrigger2(this.tags, triggerName, key)) {
33758
- return;
33759
- }
33760
- const { name, value } = getTriggerSubscriptionTags2(triggerName, key);
33761
- await this.client.updateConversation({
33762
- id: this.id,
33763
- tags: {
33764
- [name]: value
33765
- }
33766
- });
33767
- }
33768
- /**
33769
- * Unsubscribe from a trigger
33770
- */
33771
- async unsubscribeFromTrigger(triggerName, key) {
33772
- const { getTriggerSubscriptionTags: getTriggerSubscriptionTags2, isConversationSubscribedToTrigger: isConversationSubscribedToTrigger2 } = await Promise.resolve().then(() => (init_trigger_tags(), trigger_tags_exports));
33773
- if (!isConversationSubscribedToTrigger2(this.tags, triggerName, key)) {
33774
- return;
33775
- }
33776
- const { name } = getTriggerSubscriptionTags2(triggerName, key);
33777
- await this.client.updateConversation({
33778
- id: this.id,
33779
- tags: {
33780
- [name]: ""
33781
- }
33782
- });
33783
- }
33784
33711
  };
33785
33712
  }
33786
33713
  });
@@ -34346,6 +34273,9 @@ Always prefer information from the knowledge bases over general knowledge when a
34346
34273
  ...props.hooks?.onBeforeTool && {
34347
34274
  onBeforeTool: asyncResource.bind(props.hooks.onBeforeTool)
34348
34275
  },
34276
+ ...props.hooks?.onIterationStart && {
34277
+ onIterationStart: asyncResource.bind(props.hooks.onIterationStart)
34278
+ },
34349
34279
  ...props.hooks?.onAfterTool && {
34350
34280
  onAfterTool: asyncResource.bind(props.hooks.onAfterTool)
34351
34281
  },
@@ -36801,7 +36731,7 @@ var init_source_website = __esm({
36801
36731
  type: "website",
36802
36732
  state: State,
36803
36733
  async handler({ input, step: step2, state, client: client2 }) {
36804
- const crypto3 = await import("crypto");
36734
+ const crypto2 = await import("crypto");
36805
36735
  console.log(
36806
36736
  `Starting sync for WebsiteSource [${this.id}] in mode [${this.mode}, maxPages=${this.maxPages}, maxDepth=${this.maxDepth}, baseUrl=${this.baseUrl}, sitemapUrl=${this.sitemapUrl}]`
36807
36737
  );
@@ -36883,7 +36813,7 @@ var init_source_website = __esm({
36883
36813
  content,
36884
36814
  metadata: fetchMetadata
36885
36815
  } = await this.fetchUrl(sitemapUrl.loc);
36886
- const hash = crypto3.createHash("sha256").update(content).digest("hex");
36816
+ const hash = crypto2.createHash("sha256").update(content).digest("hex");
36887
36817
  let contentType = fetchedContentType;
36888
36818
  if (!contentType) {
36889
36819
  contentType = content.includes("<html") ? "text/html" : "text/markdown";
@@ -43880,7 +43810,7 @@ var init_source_directory = __esm({
43880
43810
  const glob2 = await Promise.resolve().then(() => (init_esm9(), esm_exports3));
43881
43811
  const path4 = await import("path");
43882
43812
  const fs3 = await import("fs/promises");
43883
- const crypto3 = await import("crypto");
43813
+ const crypto2 = await import("crypto");
43884
43814
  const directory = path4.resolve(adk.environment.agent.directory, this.directoryPath);
43885
43815
  const tags = {
43886
43816
  [WellKnownTags.knowledge.KNOWLEDGE]: "knowledge-base",
@@ -43942,7 +43872,7 @@ var init_source_directory = __esm({
43942
43872
  const upsertFile = async (local) => {
43943
43873
  const key = `data_source://${this.type}/${this.id}/${local.rel}`;
43944
43874
  const content = await fs3.readFile(local.abs);
43945
- const hash = crypto3.createHash("sha256").update(content).digest("hex");
43875
+ const hash = crypto2.createHash("sha256").update(content).digest("hex");
43946
43876
  const { file } = await client2.getFile({ id: key }).catch(() => ({ file: null }));
43947
43877
  if (!input.force && file?.metadata?.hash === hash) {
43948
43878
  console.log(`Skipping unchanged file: ${local.rel}`);
@@ -44082,19 +44012,11 @@ var init_conversation = __esm({
44082
44012
  /** @internal */
44083
44013
  schema;
44084
44014
  #handler;
44085
- #startFromTrigger;
44086
44015
  constructor(props) {
44087
44016
  this.channel = props.channel;
44088
44017
  this.events = props.events ?? [];
44089
44018
  this.schema = props.state ?? z10.object({}).passthrough();
44090
44019
  this.#handler = props.handler;
44091
- if (props.startFromTrigger) {
44092
- this.#startFromTrigger = props.startFromTrigger;
44093
- }
44094
- }
44095
- /** @internal */
44096
- get startFromTrigger() {
44097
- return this.#startFromTrigger;
44098
44020
  }
44099
44021
  /** @internal */
44100
44022
  getDefinition() {
@@ -45204,15 +45126,51 @@ var init_validate_tag_name = __esm({
45204
45126
  }
45205
45127
  });
45206
45128
 
45129
+ // src/utilities/validate-event-name.ts
45130
+ function validateEventName(name) {
45131
+ if (!name || typeof name !== "string") {
45132
+ return { valid: false, error: "Event name must be a non-empty string" };
45133
+ }
45134
+ if (name.length > 100) {
45135
+ return { valid: false, error: `Event name "${name}" must be less than 100 characters` };
45136
+ }
45137
+ if (!/^[a-zA-Z]/.test(name)) {
45138
+ return { valid: false, error: `Event name "${name}" must start with a letter` };
45139
+ }
45140
+ if (!/^[a-zA-Z0-9_]+$/.test(name)) {
45141
+ return {
45142
+ valid: false,
45143
+ error: `Event name "${name}" can only contain letters (A-Z, a-z), numbers (0-9), and underscores (_)`
45144
+ };
45145
+ }
45146
+ return { valid: true };
45147
+ }
45148
+ function validateEventDefinitions(events, context3) {
45149
+ for (const eventName of Object.keys(events)) {
45150
+ const validation = validateEventName(eventName);
45151
+ if (!validation.valid) {
45152
+ throw new Error(`Invalid event name in ${context3}: ${validation.error}`);
45153
+ }
45154
+ }
45155
+ }
45156
+ var init_validate_event_name = __esm({
45157
+ "src/utilities/validate-event-name.ts"() {
45158
+ "use strict";
45159
+ init_define_BUILD();
45160
+ init_define_PACKAGE_VERSIONS();
45161
+ }
45162
+ });
45163
+
45207
45164
  // src/define-config.ts
45208
45165
  import { z as z17 } from "@botpress/sdk";
45209
- var zuiSchema, modelSchema, tagDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, defineConfig;
45166
+ var zuiSchema, modelSchema, tagDefinitionSchema, eventDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, defineConfig;
45210
45167
  var init_define_config = __esm({
45211
45168
  "src/define-config.ts"() {
45212
45169
  "use strict";
45213
45170
  init_define_BUILD();
45214
45171
  init_define_PACKAGE_VERSIONS();
45215
45172
  init_validate_tag_name();
45173
+ init_validate_event_name();
45216
45174
  zuiSchema = z17.custom(
45217
45175
  (val) => {
45218
45176
  if (typeof val === "object" && val !== null && "parse" in val) {
@@ -45237,6 +45195,13 @@ var init_define_config = __esm({
45237
45195
  description: z17.string().optional()
45238
45196
  })
45239
45197
  );
45198
+ eventDefinitionSchema = z17.record(
45199
+ z17.string(),
45200
+ z17.object({
45201
+ schema: zuiSchema.optional(),
45202
+ description: z17.string().optional()
45203
+ })
45204
+ );
45240
45205
  configSchema = z17.object({
45241
45206
  name: z17.string().optional(),
45242
45207
  description: z17.string().optional(),
@@ -45277,7 +45242,8 @@ var init_define_config = __esm({
45277
45242
  zai: val?.zai ?? "openai:gpt-4.1-2025-04-14",
45278
45243
  autonomous: val?.autonomous ?? "openai:gpt-4.1-mini-2025-04-14"
45279
45244
  })),
45280
- dependencies: z17.custom()
45245
+ dependencies: z17.custom(),
45246
+ events: eventDefinitionSchema.optional()
45281
45247
  });
45282
45248
  AGENT_CONFIG_BRAND = Symbol.for("@botpress/runtime/AgentConfig");
45283
45249
  defineConfig = (config) => {
@@ -45297,6 +45263,9 @@ var init_define_config = __esm({
45297
45263
  if (parsed.workflow?.tags) {
45298
45264
  validateTagDefinitions(parsed.workflow.tags, "workflow.tags");
45299
45265
  }
45266
+ if (parsed.events) {
45267
+ validateEventDefinitions(parsed.events, "events");
45268
+ }
45300
45269
  return {
45301
45270
  ...parsed,
45302
45271
  __brand: "AgentConfig",
@@ -45554,12 +45523,12 @@ var init_workflow_step = __esm({
45554
45523
  workflowControlContext.abort();
45555
45524
  throw createStepSignal();
45556
45525
  };
45557
- step.sleep = async (name, ms3) => {
45526
+ step.sleep = async (name, ms4) => {
45558
45527
  await _step(
45559
45528
  name,
45560
45529
  async () => {
45561
45530
  const remainingTime = context2.get("runtime").getRemainingExecutionTimeInMs();
45562
- if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms3 || ms3 >= 1e4) {
45531
+ if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms4 || ms4 >= 1e4) {
45563
45532
  const client2 = context2.get("client");
45564
45533
  const workflowControlContext = context2.get("workflowControlContext");
45565
45534
  await client2.createEvent({
@@ -45567,7 +45536,7 @@ var init_workflow_step = __esm({
45567
45536
  payload: {},
45568
45537
  workflowId: workflowControlContext.workflow.id,
45569
45538
  schedule: {
45570
- delay: ms3
45539
+ delay: ms4
45571
45540
  }
45572
45541
  });
45573
45542
  await updateWorkflow({
@@ -45576,7 +45545,7 @@ var init_workflow_step = __esm({
45576
45545
  });
45577
45546
  workflowControlContext.abort();
45578
45547
  } else {
45579
- await new Promise((resolve) => void setTimeout(resolve, ms3));
45548
+ await new Promise((resolve) => void setTimeout(resolve, ms4));
45580
45549
  context2.get("workflowControlContext").signal.throwIfAborted();
45581
45550
  }
45582
45551
  },
@@ -45587,8 +45556,8 @@ var init_workflow_step = __esm({
45587
45556
  );
45588
45557
  };
45589
45558
  step.sleepUntil = async (name, date) => {
45590
- const ms3 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
45591
- await step.sleep(name, ms3);
45559
+ const ms4 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
45560
+ await step.sleep(name, ms4);
45592
45561
  };
45593
45562
  step.waitForWorkflow = async (name, workflowId) => {
45594
45563
  const workflowControlContext = context2.get("workflowControlContext");
@@ -45807,12 +45776,13 @@ function createWorkflowExecutionState(client2, workflowId) {
45807
45776
  name: BUILT_IN_STATES.workflowSteps
45808
45777
  });
45809
45778
  }
45810
- var workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
45779
+ var import_ms2, workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
45811
45780
  var init_workflow_instance = __esm({
45812
45781
  "src/primitives/workflow-instance.ts"() {
45813
45782
  "use strict";
45814
45783
  init_define_BUILD();
45815
45784
  init_define_PACKAGE_VERSIONS();
45785
+ import_ms2 = __toESM(require_ms(), 1);
45816
45786
  init_errors();
45817
45787
  init_library();
45818
45788
  init_autonomous();
@@ -45939,6 +45909,81 @@ var init_workflow_instance = __esm({
45939
45909
  });
45940
45910
  Object.assign(this.workflow, workflow);
45941
45911
  }
45912
+ /**
45913
+ * Extend the workflow timeout by setting a new timeout.
45914
+ * This is useful for long-running workflows that need more time to complete.
45915
+ *
45916
+ * @param options - Either `{ in: string }` for relative duration or `{ at: string }` for absolute ISO timestamp
45917
+ * @returns A promise that resolves when the timeout is updated (can be awaited or not)
45918
+ * @example
45919
+ * // Relative timeout (duration from now):
45920
+ * workflow.setTimeout({ in: '30m' }) // Timeout in 30 minutes
45921
+ * workflow.setTimeout({ in: '6 hours' }) // Timeout in 6 hours
45922
+ *
45923
+ * // Absolute timeout (ISO timestamp):
45924
+ * workflow.setTimeout({ at: '2024-12-25T00:00:00Z' })
45925
+ *
45926
+ * // Optionally await if you need to ensure the update completes:
45927
+ * await workflow.setTimeout({ in: '1h' })
45928
+ */
45929
+ setTimeout(options) {
45930
+ let newTimeoutAt;
45931
+ if ("in" in options) {
45932
+ const durationMs = (0, import_ms2.default)(options.in);
45933
+ if (!durationMs) {
45934
+ throw new Error(`Invalid duration format: "${options.in}". Use formats like "30m", "1h", "6 hours".`);
45935
+ }
45936
+ newTimeoutAt = new Date(Date.now() + durationMs).toISOString();
45937
+ } else {
45938
+ const date = new Date(options.at);
45939
+ if (isNaN(date.getTime())) {
45940
+ throw new Error(`Invalid ISO date format: "${options.at}".`);
45941
+ }
45942
+ newTimeoutAt = date.toISOString();
45943
+ }
45944
+ return updateWorkflow({
45945
+ id: this.id,
45946
+ timeoutAt: newTimeoutAt
45947
+ }).then(({ workflow }) => {
45948
+ Object.assign(this.workflow, workflow);
45949
+ });
45950
+ }
45951
+ /**
45952
+ * Fail the workflow with an error reason.
45953
+ * This immediately interrupts the workflow handler and marks the workflow as failed.
45954
+ * Can only be called from within a workflow handler.
45955
+ *
45956
+ * @param reason - The error reason for the failure
45957
+ * @throws Never returns - always throws to interrupt the handler
45958
+ * @example
45959
+ * workflow.fail('Invalid input data')
45960
+ */
45961
+ fail(reason) {
45962
+ const controlContext = context2.get("workflowControlContext", { optional: true });
45963
+ if (!controlContext || controlContext.workflow.id !== this.id) {
45964
+ throw new Error("workflow.fail() can only be called from within the workflow handler");
45965
+ }
45966
+ controlContext.fail(reason);
45967
+ throw createStepSignal();
45968
+ }
45969
+ /**
45970
+ * Complete the workflow early with the given output.
45971
+ * This immediately interrupts the workflow handler and marks the workflow as completed.
45972
+ * Can only be called from within a workflow handler.
45973
+ *
45974
+ * @param output - The workflow output (typed according to workflow definition)
45975
+ * @throws Never returns - always throws to interrupt the handler
45976
+ * @example
45977
+ * workflow.complete({ result: 'success', data: processedData })
45978
+ */
45979
+ complete(output2) {
45980
+ const controlContext = context2.get("workflowControlContext", { optional: true });
45981
+ if (!controlContext || controlContext.workflow.id !== this.id) {
45982
+ throw new Error("workflow.complete() can only be called from within the workflow handler");
45983
+ }
45984
+ controlContext.complete(output2);
45985
+ throw createStepSignal();
45986
+ }
45942
45987
  /**
45943
45988
  * Provide data in response to a workflow data request (instance method).
45944
45989
  * Call this method from a conversation handler when you receive a WorkflowDataRequestEvent.
@@ -45989,6 +46034,7 @@ var init_workflow_instance = __esm({
45989
46034
  workflow: this.workflow,
45990
46035
  aborted: false,
45991
46036
  failed: false,
46037
+ completed: false,
45992
46038
  acked: false,
45993
46039
  restarted: false,
45994
46040
  signal: abortSignal,
@@ -46003,6 +46049,10 @@ var init_workflow_instance = __esm({
46003
46049
  workflowControlContext.failed = true;
46004
46050
  workflowControlContext.failedReason = reason;
46005
46051
  },
46052
+ complete: (result) => {
46053
+ workflowControlContext.completed = true;
46054
+ workflowControlContext.completedResult = result;
46055
+ },
46006
46056
  ack: async () => {
46007
46057
  if (workflowControlContext.acked) {
46008
46058
  return;
@@ -46056,7 +46106,8 @@ var init_workflow_instance = __esm({
46056
46106
  step,
46057
46107
  client: this.client,
46058
46108
  execute: this.execute.bind(this),
46059
- signal: abortSignal
46109
+ signal: abortSignal,
46110
+ workflow: this
46060
46111
  });
46061
46112
  return {
46062
46113
  status: "done",
@@ -46067,6 +46118,12 @@ var init_workflow_instance = __esm({
46067
46118
  }
46068
46119
  } catch (err) {
46069
46120
  if (isStepSignal(err)) {
46121
+ if (workflowControlContext.completed) {
46122
+ return {
46123
+ status: "done",
46124
+ result: workflowControlContext.completedResult
46125
+ };
46126
+ }
46070
46127
  if (workflowControlContext.failed) {
46071
46128
  return {
46072
46129
  status: "error",
@@ -46682,6 +46739,259 @@ var init_tracked_state = __esm({
46682
46739
  }
46683
46740
  });
46684
46741
 
46742
+ // src/runtime/tracked-tags.ts
46743
+ var TrackedTags;
46744
+ var init_tracked_tags = __esm({
46745
+ "src/runtime/tracked-tags.ts"() {
46746
+ "use strict";
46747
+ init_define_BUILD();
46748
+ init_define_PACKAGE_VERSIONS();
46749
+ init_context3();
46750
+ init_tracing();
46751
+ TrackedTags = class _TrackedTags {
46752
+ type;
46753
+ id;
46754
+ client;
46755
+ _tags = {};
46756
+ _initialTags = {};
46757
+ _loaded = false;
46758
+ _saving = false;
46759
+ _saveAgain = false;
46760
+ _saveAgainCount = 0;
46761
+ static _savingAll = false;
46762
+ static _saveAllAgain = false;
46763
+ static _saveAllCount = 0;
46764
+ constructor(props) {
46765
+ this.type = props.type;
46766
+ this.id = props.id;
46767
+ this.client = props.client;
46768
+ }
46769
+ static create(props) {
46770
+ const tags = context2.get("tags", { optional: true });
46771
+ const executionFinished = context2.get("executionFinished", { optional: true });
46772
+ if (executionFinished) {
46773
+ throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
46774
+ }
46775
+ const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
46776
+ if (match2) {
46777
+ return match2;
46778
+ }
46779
+ const instance = new _TrackedTags(props);
46780
+ if (props.initialTags) {
46781
+ instance._tags = { ...props.initialTags };
46782
+ instance._initialTags = { ...props.initialTags };
46783
+ instance._loaded = true;
46784
+ }
46785
+ tags?.push(instance);
46786
+ return instance;
46787
+ }
46788
+ static async saveAllDirty() {
46789
+ if (this._savingAll) {
46790
+ this._saveAllAgain = true;
46791
+ return;
46792
+ }
46793
+ try {
46794
+ this._savingAll = true;
46795
+ const tags = context2.get("tags", { optional: true });
46796
+ const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
46797
+ if (!dirtyTags.length) {
46798
+ return;
46799
+ }
46800
+ await span(
46801
+ "tags.saveAllDirty",
46802
+ {
46803
+ tags_count: tags?.length || 0,
46804
+ tags: tags.map((t) => `${t.type}/${t.id}`)
46805
+ },
46806
+ () => Promise.allSettled(dirtyTags.map((t) => t.save()))
46807
+ );
46808
+ } finally {
46809
+ this._savingAll = false;
46810
+ if (this._saveAllAgain && this._saveAllCount++ <= 5) {
46811
+ this._saveAllAgain = false;
46812
+ await this.saveAllDirty();
46813
+ } else {
46814
+ this._saveAllCount = 0;
46815
+ }
46816
+ }
46817
+ }
46818
+ static async loadAll() {
46819
+ await span("tags.loadAll", {}, async () => {
46820
+ const client2 = context2.get("client")._inner;
46821
+ const bot2 = context2.get("bot", { optional: true });
46822
+ const user2 = context2.get("user", { optional: true });
46823
+ const conversation = context2.get("conversation", { optional: true });
46824
+ const workflow = context2.get("workflow", { optional: true });
46825
+ if (bot2) {
46826
+ const botTags = bot2.tags;
46827
+ _TrackedTags.create({
46828
+ client: client2,
46829
+ type: "bot",
46830
+ id: bot2.id,
46831
+ ...botTags && { initialTags: botTags }
46832
+ });
46833
+ }
46834
+ if (user2) {
46835
+ const userTags = user2.tags;
46836
+ _TrackedTags.create({
46837
+ client: client2,
46838
+ type: "user",
46839
+ id: user2.id,
46840
+ ...userTags && { initialTags: userTags }
46841
+ });
46842
+ }
46843
+ if (conversation) {
46844
+ const conversationTags = conversation.tags;
46845
+ _TrackedTags.create({
46846
+ client: client2,
46847
+ type: "conversation",
46848
+ id: conversation.id,
46849
+ ...conversationTags && { initialTags: conversationTags }
46850
+ });
46851
+ }
46852
+ if (workflow) {
46853
+ const workflowTags = workflow.tags;
46854
+ _TrackedTags.create({
46855
+ client: client2,
46856
+ type: "workflow",
46857
+ id: workflow.id,
46858
+ ...workflowTags && { initialTags: workflowTags }
46859
+ });
46860
+ }
46861
+ const tags = context2.get("tags", { optional: true });
46862
+ const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
46863
+ if (unloadedTags.length > 0) {
46864
+ await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
46865
+ }
46866
+ });
46867
+ }
46868
+ static unloadAll() {
46869
+ context2.get("tags", { optional: true })?.splice(0);
46870
+ }
46871
+ async load(force = false) {
46872
+ if (this._loaded && !force) {
46873
+ return;
46874
+ }
46875
+ await span(
46876
+ "tags.load",
46877
+ {
46878
+ type: this.type,
46879
+ id: this.id
46880
+ },
46881
+ async () => {
46882
+ const tags = await this.fetchTags();
46883
+ this._tags = { ...tags };
46884
+ this._initialTags = { ...tags };
46885
+ this._loaded = true;
46886
+ }
46887
+ );
46888
+ }
46889
+ async save() {
46890
+ if (this._saving) {
46891
+ this._saveAgain = true;
46892
+ return;
46893
+ }
46894
+ const executionFinished = context2.get("executionFinished", { optional: true });
46895
+ if (executionFinished) {
46896
+ throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
46897
+ }
46898
+ try {
46899
+ this._saving = true;
46900
+ await span(
46901
+ "tags.save",
46902
+ {
46903
+ type: this.type,
46904
+ id: this.id
46905
+ },
46906
+ async () => {
46907
+ await this.persistTags(this._tags);
46908
+ this._initialTags = { ...this._tags };
46909
+ }
46910
+ );
46911
+ } finally {
46912
+ this._saving = false;
46913
+ if (this._saveAgain && this._saveAgainCount++ <= 5) {
46914
+ this._saveAgain = false;
46915
+ await this.save();
46916
+ } else {
46917
+ this._saveAgainCount = 0;
46918
+ }
46919
+ }
46920
+ }
46921
+ isDirty() {
46922
+ const currentKeys = Object.keys(this._tags).filter((k) => !k.includes(":")).sort();
46923
+ const initialKeys = Object.keys(this._initialTags).filter((k) => !k.includes(":")).sort();
46924
+ if (currentKeys.length !== initialKeys.length) {
46925
+ return true;
46926
+ }
46927
+ for (const key of currentKeys) {
46928
+ if (this._tags[key] !== this._initialTags[key]) {
46929
+ return true;
46930
+ }
46931
+ }
46932
+ return false;
46933
+ }
46934
+ get tags() {
46935
+ return new Proxy(this._tags, {
46936
+ set: (target, prop, value) => {
46937
+ target[prop] = value;
46938
+ return true;
46939
+ },
46940
+ deleteProperty: (target, prop) => {
46941
+ target[prop] = void 0;
46942
+ return true;
46943
+ }
46944
+ });
46945
+ }
46946
+ set tags(value) {
46947
+ this._tags = { ...value };
46948
+ }
46949
+ async fetchTags() {
46950
+ try {
46951
+ if (this.type === "bot") {
46952
+ const { bot: bot2 } = await this.client.getBot({ id: this.id });
46953
+ return bot2.tags || {};
46954
+ } else if (this.type === "user") {
46955
+ const { user: user2 } = await this.client.getUser({ id: this.id });
46956
+ return user2.tags || {};
46957
+ } else if (this.type === "conversation") {
46958
+ const { conversation } = await this.client.getConversation({ id: this.id });
46959
+ return conversation.tags || {};
46960
+ } else if (this.type === "workflow") {
46961
+ const { workflow } = await this.client.getWorkflow({ id: this.id });
46962
+ return workflow.tags || {};
46963
+ }
46964
+ } catch (err) {
46965
+ console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
46966
+ }
46967
+ return {};
46968
+ }
46969
+ async persistTags(tags) {
46970
+ const tagsForApi = {};
46971
+ for (const [key, value] of Object.entries(tags)) {
46972
+ if (value !== void 0 && !key.includes(":")) {
46973
+ tagsForApi[key] = value;
46974
+ }
46975
+ }
46976
+ try {
46977
+ if (this.type === "bot") {
46978
+ await this.client.updateBot({ id: this.id, tags: tagsForApi });
46979
+ } else if (this.type === "user") {
46980
+ await this.client.updateUser({ id: this.id, tags: tagsForApi });
46981
+ } else if (this.type === "conversation") {
46982
+ await this.client.updateConversation({ id: this.id, tags: tagsForApi });
46983
+ } else if (this.type === "workflow") {
46984
+ await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
46985
+ }
46986
+ } catch (err) {
46987
+ console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
46988
+ throw err;
46989
+ }
46990
+ }
46991
+ };
46992
+ }
46993
+ });
46994
+
46685
46995
  // src/runtime/context/inspector-handler.ts
46686
46996
  async function handleInspectorDisable() {
46687
46997
  const inspector = await import("inspector");
@@ -46824,6 +47134,7 @@ var init_handlers = __esm({
46824
47134
  init_http();
46825
47135
  init_agent_registry();
46826
47136
  init_tracked_state();
47137
+ init_tracked_tags();
46827
47138
  init_tracing();
46828
47139
  init_heavy_imports();
46829
47140
  init_environment();
@@ -46951,12 +47262,13 @@ var init_handlers = __esm({
46951
47262
  reject(error);
46952
47263
  } finally {
46953
47264
  clearTimeout(timeout);
46954
- await TrackedState2.saveAllDirty();
47265
+ await Promise.all([TrackedState2.saveAllDirty(), TrackedTags.saveAllDirty()]);
46955
47266
  }
46956
47267
  });
46957
47268
  } finally {
46958
- await TrackedState2.saveAllDirty();
47269
+ await Promise.all([TrackedState2.saveAllDirty(), TrackedTags.saveAllDirty()]);
46959
47270
  TrackedState2.unloadAll();
47271
+ TrackedTags.unloadAll();
46960
47272
  context2.set("executionFinished", true);
46961
47273
  await shutdownPromiseTracker();
46962
47274
  }
@@ -48470,7 +48782,7 @@ var workflow_exports = {};
48470
48782
  __export(workflow_exports, {
48471
48783
  setup: () => setup3
48472
48784
  });
48473
- var import_ms2, setup3;
48785
+ var import_ms3, setup3;
48474
48786
  var init_workflow2 = __esm({
48475
48787
  "src/runtime/handlers/workflow.ts"() {
48476
48788
  "use strict";
@@ -48483,7 +48795,7 @@ var init_workflow2 = __esm({
48483
48795
  init_esm();
48484
48796
  init_adk();
48485
48797
  init_workflow_utils();
48486
- import_ms2 = __toESM(require_ms(), 1);
48798
+ import_ms3 = __toESM(require_ms(), 1);
48487
48799
  setup3 = (bot2) => {
48488
48800
  const handler = async function({ workflow, event, client: client2, ctx, conversation }) {
48489
48801
  await span(
@@ -48511,7 +48823,7 @@ var init_workflow2 = __esm({
48511
48823
  });
48512
48824
  return;
48513
48825
  }
48514
- const DEFAULT_TIMEOUT_MS = (0, import_ms2.default)("5m");
48826
+ const DEFAULT_TIMEOUT_MS = (0, import_ms3.default)("5m");
48515
48827
  const configuredTimeout = workflowDefinition.timeout;
48516
48828
  if (workflow.timeoutAt && configuredTimeout !== DEFAULT_TIMEOUT_MS) {
48517
48829
  const workflowStartedAt = new Date(workflow.createdAt).getTime();
@@ -48529,10 +48841,13 @@ var init_workflow2 = __esm({
48529
48841
  s.setAttribute("workflow.timeout.to", configuredTimeout);
48530
48842
  }
48531
48843
  }
48532
- const instance = await BaseWorkflowInstance.load({
48533
- id: workflow.id,
48534
- workflow
48535
- });
48844
+ const [instance] = await Promise.all([
48845
+ BaseWorkflowInstance.load({
48846
+ id: workflow.id,
48847
+ workflow
48848
+ }),
48849
+ TrackedState2.loadAll()
48850
+ ]);
48536
48851
  void workflow.acknowledgeStartOfProcessing();
48537
48852
  try {
48538
48853
  const interval = setInterval(async () => {
@@ -48687,15 +49002,18 @@ var init_event = __esm({
48687
49002
  logger.warn(`Skipping ${WorkflowCallbackEvent.name} event, conversation not found in context`);
48688
49003
  return;
48689
49004
  }
48690
- let alias = conversation.integration;
48691
- const colonIndex = event.type.indexOf(":");
48692
- if (colonIndex > 0) {
48693
- alias = event.type.substring(0, colonIndex);
48694
- }
48695
- const handlerName = alias + "." + conversation.channel;
48696
- const handler = findMatchingHandler(adk.project.conversations, handlerName);
49005
+ const handlerName = conversation.integration + "." + conversation.channel;
49006
+ const isBuiltInEvent = event.type === WorkflowCallbackEvent.name || event.type === WorkflowDataRequestEvent2.name;
49007
+ const matchingHandlers = adk.project.conversations.filter(
49008
+ (h) => matchesChannel(h.channel, handlerName) && (isBuiltInEvent || h.events.includes(event.type))
49009
+ );
49010
+ const handler = matchingHandlers.sort((a, b) => {
49011
+ const aScore = a.channel === "*" ? 0 : Array.isArray(a.channel) ? 1 : 2;
49012
+ const bScore = b.channel === "*" ? 0 : Array.isArray(b.channel) ? 1 : 2;
49013
+ return bScore - aScore;
49014
+ })[0];
48697
49015
  if (!handler) {
48698
- logger.debug(`Skipping message, no ADK Conversation defined for "${handlerName}"`);
49016
+ logger.debug(`Skipping event "${event.type}", no ADK Conversation listening to this event for channel "${handlerName}"`);
48699
49017
  return;
48700
49018
  }
48701
49019
  await span(
@@ -48713,15 +49031,18 @@ var init_event = __esm({
48713
49031
  async () => {
48714
49032
  const chat = new BotpressChat(context2.getAll());
48715
49033
  context2.set("chat", chat);
48716
- const transcript = await chat.fetchTranscript();
49034
+ const [transcript, _statesLoaded, _tagsLoaded] = await Promise.all([
49035
+ chat.fetchTranscript(),
49036
+ TrackedState2.loadAll(),
49037
+ TrackedTags.loadAll()
49038
+ ]);
48717
49039
  if (transcript.find((x) => x.id === event.id)) {
48718
49040
  logger.debug(`Message ${event.id} already processed`);
48719
49041
  return;
48720
49042
  }
48721
49043
  await chat.addEvent(event);
48722
- await TrackedState2.loadAll();
48723
49044
  await handler[ConversationHandler]();
48724
- await TrackedState2.saveAllDirty();
49045
+ await Promise.all([TrackedState2.saveAllDirty(), TrackedTags.saveAllDirty()]);
48725
49046
  await chat.saveTranscript();
48726
49047
  }
48727
49048
  );
@@ -48814,259 +49135,6 @@ var init_handlers2 = __esm({
48814
49135
  }
48815
49136
  });
48816
49137
 
48817
- // src/runtime/tracked-tags.ts
48818
- var TrackedTags;
48819
- var init_tracked_tags = __esm({
48820
- "src/runtime/tracked-tags.ts"() {
48821
- "use strict";
48822
- init_define_BUILD();
48823
- init_define_PACKAGE_VERSIONS();
48824
- init_context3();
48825
- init_tracing();
48826
- TrackedTags = class _TrackedTags {
48827
- type;
48828
- id;
48829
- client;
48830
- _tags = {};
48831
- _initialTags = {};
48832
- _loaded = false;
48833
- _saving = false;
48834
- _saveAgain = false;
48835
- _saveAgainCount = 0;
48836
- static _savingAll = false;
48837
- static _saveAllAgain = false;
48838
- static _saveAllCount = 0;
48839
- constructor(props) {
48840
- this.type = props.type;
48841
- this.id = props.id;
48842
- this.client = props.client;
48843
- }
48844
- static create(props) {
48845
- const tags = context2.get("tags", { optional: true });
48846
- const executionFinished = context2.get("executionFinished", { optional: true });
48847
- if (executionFinished) {
48848
- throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
48849
- }
48850
- const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
48851
- if (match2) {
48852
- return match2;
48853
- }
48854
- const instance = new _TrackedTags(props);
48855
- if (props.initialTags) {
48856
- instance._tags = { ...props.initialTags };
48857
- instance._initialTags = { ...props.initialTags };
48858
- instance._loaded = true;
48859
- }
48860
- tags?.push(instance);
48861
- return instance;
48862
- }
48863
- static async saveAllDirty() {
48864
- if (this._savingAll) {
48865
- this._saveAllAgain = true;
48866
- return;
48867
- }
48868
- try {
48869
- this._savingAll = true;
48870
- const tags = context2.get("tags", { optional: true });
48871
- const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
48872
- if (!dirtyTags.length) {
48873
- return;
48874
- }
48875
- await span(
48876
- "tags.saveAllDirty",
48877
- {
48878
- tags_count: tags?.length || 0,
48879
- tags: tags.map((t) => `${t.type}/${t.id}`)
48880
- },
48881
- () => Promise.allSettled(dirtyTags.map((t) => t.save()))
48882
- );
48883
- } finally {
48884
- this._savingAll = false;
48885
- if (this._saveAllAgain && this._saveAllCount++ <= 5) {
48886
- this._saveAllAgain = false;
48887
- await this.saveAllDirty();
48888
- } else {
48889
- this._saveAllCount = 0;
48890
- }
48891
- }
48892
- }
48893
- static async loadAll() {
48894
- await span("tags.loadAll", {}, async () => {
48895
- const client2 = context2.get("client")._inner;
48896
- const bot2 = context2.get("bot", { optional: true });
48897
- const user2 = context2.get("user", { optional: true });
48898
- const conversation = context2.get("conversation", { optional: true });
48899
- const workflow = context2.get("workflow", { optional: true });
48900
- if (bot2) {
48901
- const botTags = bot2.tags;
48902
- _TrackedTags.create({
48903
- client: client2,
48904
- type: "bot",
48905
- id: bot2.id,
48906
- ...botTags && { initialTags: botTags }
48907
- });
48908
- }
48909
- if (user2) {
48910
- const userTags = user2.tags;
48911
- _TrackedTags.create({
48912
- client: client2,
48913
- type: "user",
48914
- id: user2.id,
48915
- ...userTags && { initialTags: userTags }
48916
- });
48917
- }
48918
- if (conversation) {
48919
- const conversationTags = conversation.tags;
48920
- _TrackedTags.create({
48921
- client: client2,
48922
- type: "conversation",
48923
- id: conversation.id,
48924
- ...conversationTags && { initialTags: conversationTags }
48925
- });
48926
- }
48927
- if (workflow) {
48928
- const workflowTags = workflow.tags;
48929
- _TrackedTags.create({
48930
- client: client2,
48931
- type: "workflow",
48932
- id: workflow.id,
48933
- ...workflowTags && { initialTags: workflowTags }
48934
- });
48935
- }
48936
- const tags = context2.get("tags", { optional: true });
48937
- const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
48938
- if (unloadedTags.length > 0) {
48939
- await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
48940
- }
48941
- });
48942
- }
48943
- static unloadAll() {
48944
- context2.get("tags", { optional: true })?.splice(0);
48945
- }
48946
- async load(force = false) {
48947
- if (this._loaded && !force) {
48948
- return;
48949
- }
48950
- await span(
48951
- "tags.load",
48952
- {
48953
- type: this.type,
48954
- id: this.id
48955
- },
48956
- async () => {
48957
- const tags = await this.fetchTags();
48958
- this._tags = { ...tags };
48959
- this._initialTags = { ...tags };
48960
- this._loaded = true;
48961
- }
48962
- );
48963
- }
48964
- async save() {
48965
- if (this._saving) {
48966
- this._saveAgain = true;
48967
- return;
48968
- }
48969
- const executionFinished = context2.get("executionFinished", { optional: true });
48970
- if (executionFinished) {
48971
- throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
48972
- }
48973
- try {
48974
- this._saving = true;
48975
- await span(
48976
- "tags.save",
48977
- {
48978
- type: this.type,
48979
- id: this.id
48980
- },
48981
- async () => {
48982
- await this.persistTags(this._tags);
48983
- this._initialTags = { ...this._tags };
48984
- }
48985
- );
48986
- } finally {
48987
- this._saving = false;
48988
- if (this._saveAgain && this._saveAgainCount++ <= 5) {
48989
- this._saveAgain = false;
48990
- await this.save();
48991
- } else {
48992
- this._saveAgainCount = 0;
48993
- }
48994
- }
48995
- }
48996
- isDirty() {
48997
- const currentKeys = Object.keys(this._tags).sort();
48998
- const initialKeys = Object.keys(this._initialTags).sort();
48999
- if (currentKeys.length !== initialKeys.length) {
49000
- return true;
49001
- }
49002
- for (const key of currentKeys) {
49003
- if (this._tags[key] !== this._initialTags[key]) {
49004
- return true;
49005
- }
49006
- }
49007
- return false;
49008
- }
49009
- get tags() {
49010
- return new Proxy(this._tags, {
49011
- set: (target, prop, value) => {
49012
- target[prop] = value;
49013
- return true;
49014
- },
49015
- deleteProperty: (target, prop) => {
49016
- target[prop] = void 0;
49017
- return true;
49018
- }
49019
- });
49020
- }
49021
- set tags(value) {
49022
- this._tags = { ...value };
49023
- }
49024
- async fetchTags() {
49025
- try {
49026
- if (this.type === "bot") {
49027
- const { bot: bot2 } = await this.client.getBot({ id: this.id });
49028
- return bot2.tags || {};
49029
- } else if (this.type === "user") {
49030
- const { user: user2 } = await this.client.getUser({ id: this.id });
49031
- return user2.tags || {};
49032
- } else if (this.type === "conversation") {
49033
- const { conversation } = await this.client.getConversation({ id: this.id });
49034
- return conversation.tags || {};
49035
- } else if (this.type === "workflow") {
49036
- const { workflow } = await this.client.getWorkflow({ id: this.id });
49037
- return workflow.tags || {};
49038
- }
49039
- } catch (err) {
49040
- console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
49041
- }
49042
- return {};
49043
- }
49044
- async persistTags(tags) {
49045
- const tagsForApi = {};
49046
- for (const [key, value] of Object.entries(tags)) {
49047
- if (value !== void 0) {
49048
- tagsForApi[key] = value;
49049
- }
49050
- }
49051
- try {
49052
- if (this.type === "bot") {
49053
- await this.client.updateBot({ id: this.id, tags: tagsForApi });
49054
- } else if (this.type === "user") {
49055
- await this.client.updateUser({ id: this.id, tags: tagsForApi });
49056
- } else if (this.type === "conversation") {
49057
- await this.client.updateConversation({ id: this.id, tags: tagsForApi });
49058
- } else if (this.type === "workflow") {
49059
- await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
49060
- }
49061
- } catch (err) {
49062
- console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
49063
- throw err;
49064
- }
49065
- }
49066
- };
49067
- }
49068
- });
49069
-
49070
49138
  // src/runtime/index.ts
49071
49139
  var init_runtime = __esm({
49072
49140
  "src/runtime/index.ts"() {
@@ -50083,7 +50151,6 @@ var init_runtime2 = __esm({
50083
50151
  init_structured_logging();
50084
50152
  init_environment();
50085
50153
  init_runtime();
50086
- init_trigger_tags();
50087
50154
  init_types2();
50088
50155
  init_errors();
50089
50156
  init_state();
@@ -50122,14 +50189,10 @@ export {
50122
50189
  defineConfig,
50123
50190
  expandCitationsInObject,
50124
50191
  getAssetsMetadata,
50125
- getTriggerSubscriptionTags,
50126
- getTriggerTagName,
50127
- getTriggerTagValue,
50128
50192
  handlers,
50129
50193
  initAssets,
50130
50194
  initialize,
50131
50195
  interfaceMappings,
50132
- isConversationSubscribedToTrigger,
50133
50196
  joinMarkdownChildren,
50134
50197
  patchHandlers,
50135
50198
  register,