@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
@@ -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
 
@@ -12138,41 +12138,41 @@ var require_ms = __commonJS({
12138
12138
  return void 0;
12139
12139
  }
12140
12140
  }
12141
- function fmtShort(ms3) {
12142
- var msAbs = Math.abs(ms3);
12141
+ function fmtShort(ms4) {
12142
+ var msAbs = Math.abs(ms4);
12143
12143
  if (msAbs >= d) {
12144
- return Math.round(ms3 / d) + "d";
12144
+ return Math.round(ms4 / d) + "d";
12145
12145
  }
12146
12146
  if (msAbs >= h) {
12147
- return Math.round(ms3 / h) + "h";
12147
+ return Math.round(ms4 / h) + "h";
12148
12148
  }
12149
12149
  if (msAbs >= m) {
12150
- return Math.round(ms3 / m) + "m";
12150
+ return Math.round(ms4 / m) + "m";
12151
12151
  }
12152
12152
  if (msAbs >= s) {
12153
- return Math.round(ms3 / s) + "s";
12153
+ return Math.round(ms4 / s) + "s";
12154
12154
  }
12155
- return ms3 + "ms";
12155
+ return ms4 + "ms";
12156
12156
  }
12157
- function fmtLong(ms3) {
12158
- var msAbs = Math.abs(ms3);
12157
+ function fmtLong(ms4) {
12158
+ var msAbs = Math.abs(ms4);
12159
12159
  if (msAbs >= d) {
12160
- return plural(ms3, msAbs, d, "day");
12160
+ return plural(ms4, msAbs, d, "day");
12161
12161
  }
12162
12162
  if (msAbs >= h) {
12163
- return plural(ms3, msAbs, h, "hour");
12163
+ return plural(ms4, msAbs, h, "hour");
12164
12164
  }
12165
12165
  if (msAbs >= m) {
12166
- return plural(ms3, msAbs, m, "minute");
12166
+ return plural(ms4, msAbs, m, "minute");
12167
12167
  }
12168
12168
  if (msAbs >= s) {
12169
- return plural(ms3, msAbs, s, "second");
12169
+ return plural(ms4, msAbs, s, "second");
12170
12170
  }
12171
- return ms3 + " ms";
12171
+ return ms4 + " ms";
12172
12172
  }
12173
- function plural(ms3, msAbs, n, name) {
12173
+ function plural(ms4, msAbs, n, name) {
12174
12174
  var isPlural = msAbs >= n * 1.5;
12175
- return Math.round(ms3 / n) + " " + name + (isPlural ? "s" : "");
12175
+ return Math.round(ms4 / n) + " " + name + (isPlural ? "s" : "");
12176
12176
  }
12177
12177
  }
12178
12178
  });
@@ -12217,8 +12217,8 @@ var require_common = __commonJS({
12217
12217
  }
12218
12218
  const self2 = debug;
12219
12219
  const curr = Number(/* @__PURE__ */ new Date());
12220
- const ms3 = curr - (prevTime || curr);
12221
- self2.diff = ms3;
12220
+ const ms4 = curr - (prevTime || curr);
12221
+ self2.diff = ms4;
12222
12222
  self2.prev = prevTime;
12223
12223
  self2.curr = curr;
12224
12224
  prevTime = curr;
@@ -32780,7 +32780,7 @@ var init_assets = __esm({
32780
32780
 
32781
32781
  // src/runtime/context/context.ts
32782
32782
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
32783
- var storage, context2;
32783
+ var storage, defaultContext, context2;
32784
32784
  var init_context3 = __esm({
32785
32785
  "src/runtime/context/context.ts"() {
32786
32786
  "use strict";
@@ -32788,6 +32788,7 @@ var init_context3 = __esm({
32788
32788
  init_define_PACKAGE_VERSIONS();
32789
32789
  init_singletons();
32790
32790
  storage = getSingleton("__ADK_GLOBAL_CTX_STORAGE", () => new AsyncLocalStorage2());
32791
+ defaultContext = getSingleton("__ADK_GLOBAL_DEFAULT_CTX", () => ({ value: null }));
32791
32792
  context2 = {
32792
32793
  enterWith: (data) => {
32793
32794
  storage.enterWith(data);
@@ -32806,7 +32807,10 @@ var init_context3 = __esm({
32806
32807
  return store;
32807
32808
  },
32808
32809
  get: (key, opts) => {
32809
- const store = storage.getStore();
32810
+ let store = storage.getStore();
32811
+ if (!store && defaultContext.value) {
32812
+ store = defaultContext.value;
32813
+ }
32810
32814
  if (store) {
32811
32815
  store.states ??= [];
32812
32816
  store.tags ??= [];
@@ -32822,6 +32826,28 @@ var init_context3 = __esm({
32822
32826
  const store = storage.getStore();
32823
32827
  if (!store) throw new Error("Cannot set context outside of `run`");
32824
32828
  store[key] = value;
32829
+ },
32830
+ /**
32831
+ * Set a default context that will be used as a fallback when no AsyncLocalStorage context is active.
32832
+ * This is useful for testing and script execution where code runs outside of request handlers.
32833
+ *
32834
+ * @example
32835
+ * ```typescript
32836
+ * context.setDefaultContext({
32837
+ * botId: 'my-bot',
32838
+ * integrations: agentRegistry.integrations,
32839
+ * interfaces: agentRegistry.interfaces,
32840
+ * })
32841
+ * ```
32842
+ */
32843
+ setDefaultContext: (data) => {
32844
+ defaultContext.value = data;
32845
+ },
32846
+ /**
32847
+ * Clear the default context.
32848
+ */
32849
+ clearDefaultContext: () => {
32850
+ defaultContext.value = null;
32825
32851
  }
32826
32852
  };
32827
32853
  }
@@ -32944,6 +32970,268 @@ var init_agent_registry = __esm({
32944
32970
  }
32945
32971
  });
32946
32972
 
32973
+ // src/runtime/tracked-tags.ts
32974
+ function isSystemTag(key) {
32975
+ return key.includes(":");
32976
+ }
32977
+ var TrackedTags;
32978
+ var init_tracked_tags = __esm({
32979
+ "src/runtime/tracked-tags.ts"() {
32980
+ "use strict";
32981
+ init_define_BUILD();
32982
+ init_define_PACKAGE_VERSIONS();
32983
+ init_context3();
32984
+ init_tracing();
32985
+ TrackedTags = class _TrackedTags {
32986
+ type;
32987
+ id;
32988
+ client;
32989
+ _tags = {};
32990
+ _initialTags = {};
32991
+ _loaded = false;
32992
+ _saving = false;
32993
+ _saveAgain = false;
32994
+ _saveAgainCount = 0;
32995
+ static _savingAll = false;
32996
+ static _saveAllAgain = false;
32997
+ static _saveAllCount = 0;
32998
+ constructor(props) {
32999
+ this.type = props.type;
33000
+ this.id = props.id;
33001
+ this.client = props.client;
33002
+ }
33003
+ static create(props) {
33004
+ const tags = context2.get("tags", { optional: true });
33005
+ const executionFinished = context2.get("executionFinished", { optional: true });
33006
+ if (executionFinished) {
33007
+ throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
33008
+ }
33009
+ const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
33010
+ if (match2) {
33011
+ return match2;
33012
+ }
33013
+ const instance = new _TrackedTags(props);
33014
+ if (props.initialTags) {
33015
+ instance._tags = { ...props.initialTags };
33016
+ instance._initialTags = { ...props.initialTags };
33017
+ instance._loaded = true;
33018
+ }
33019
+ tags?.push(instance);
33020
+ return instance;
33021
+ }
33022
+ static async saveAllDirty() {
33023
+ if (this._savingAll) {
33024
+ this._saveAllAgain = true;
33025
+ return;
33026
+ }
33027
+ try {
33028
+ this._savingAll = true;
33029
+ const tags = context2.get("tags", { optional: true });
33030
+ const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
33031
+ if (!dirtyTags.length) {
33032
+ return;
33033
+ }
33034
+ await span(
33035
+ "tags.saveAllDirty",
33036
+ {
33037
+ tags_count: tags?.length || 0,
33038
+ tags: tags.map((t) => `${t.type}/${t.id}`)
33039
+ },
33040
+ () => Promise.allSettled(dirtyTags.map((t) => t.save()))
33041
+ );
33042
+ } finally {
33043
+ this._savingAll = false;
33044
+ if (this._saveAllAgain && this._saveAllCount++ <= 5) {
33045
+ this._saveAllAgain = false;
33046
+ await this.saveAllDirty();
33047
+ } else {
33048
+ this._saveAllCount = 0;
33049
+ }
33050
+ }
33051
+ }
33052
+ static async loadAll() {
33053
+ await span("tags.loadAll", {}, async () => {
33054
+ const client2 = context2.get("client")._inner;
33055
+ const bot2 = context2.get("bot", { optional: true });
33056
+ const user2 = context2.get("user", { optional: true });
33057
+ const conversation = context2.get("conversation", { optional: true });
33058
+ const workflow = context2.get("workflow", { optional: true });
33059
+ if (bot2) {
33060
+ const botTags = bot2.tags;
33061
+ _TrackedTags.create({
33062
+ client: client2,
33063
+ type: "bot",
33064
+ id: bot2.id,
33065
+ ...botTags && { initialTags: botTags }
33066
+ });
33067
+ }
33068
+ if (user2) {
33069
+ const userTags = user2.tags;
33070
+ _TrackedTags.create({
33071
+ client: client2,
33072
+ type: "user",
33073
+ id: user2.id,
33074
+ ...userTags && { initialTags: userTags }
33075
+ });
33076
+ }
33077
+ if (conversation) {
33078
+ const conversationTags = conversation.tags;
33079
+ _TrackedTags.create({
33080
+ client: client2,
33081
+ type: "conversation",
33082
+ id: conversation.id,
33083
+ ...conversationTags && { initialTags: conversationTags }
33084
+ });
33085
+ }
33086
+ if (workflow) {
33087
+ const workflowTags = workflow.tags;
33088
+ _TrackedTags.create({
33089
+ client: client2,
33090
+ type: "workflow",
33091
+ id: workflow.id,
33092
+ ...workflowTags && { initialTags: workflowTags }
33093
+ });
33094
+ }
33095
+ const tags = context2.get("tags", { optional: true });
33096
+ const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
33097
+ if (unloadedTags.length > 0) {
33098
+ await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
33099
+ }
33100
+ });
33101
+ }
33102
+ static unloadAll() {
33103
+ context2.get("tags", { optional: true })?.splice(0);
33104
+ }
33105
+ async load(force = false) {
33106
+ if (this._loaded && !force) {
33107
+ return;
33108
+ }
33109
+ await span(
33110
+ "tags.load",
33111
+ {
33112
+ type: this.type,
33113
+ id: this.id
33114
+ },
33115
+ async () => {
33116
+ const tags = await this.fetchTags();
33117
+ this._tags = { ...tags };
33118
+ this._initialTags = { ...tags };
33119
+ this._loaded = true;
33120
+ }
33121
+ );
33122
+ }
33123
+ async save() {
33124
+ if (this._saving) {
33125
+ this._saveAgain = true;
33126
+ return;
33127
+ }
33128
+ const executionFinished = context2.get("executionFinished", { optional: true });
33129
+ if (executionFinished) {
33130
+ throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
33131
+ }
33132
+ try {
33133
+ this._saving = true;
33134
+ await span(
33135
+ "tags.save",
33136
+ {
33137
+ type: this.type,
33138
+ id: this.id
33139
+ },
33140
+ async () => {
33141
+ await this.persistTags(this._tags);
33142
+ this._initialTags = { ...this._tags };
33143
+ }
33144
+ );
33145
+ } finally {
33146
+ this._saving = false;
33147
+ if (this._saveAgain && this._saveAgainCount++ <= 5) {
33148
+ this._saveAgain = false;
33149
+ await this.save();
33150
+ } else {
33151
+ this._saveAgainCount = 0;
33152
+ }
33153
+ }
33154
+ }
33155
+ isDirty() {
33156
+ const currentKeys = Object.keys(this._tags).filter((k) => !isSystemTag(k)).sort();
33157
+ const initialKeys = Object.keys(this._initialTags).filter((k) => !isSystemTag(k)).sort();
33158
+ if (currentKeys.length !== initialKeys.length) {
33159
+ return true;
33160
+ }
33161
+ for (const key of currentKeys) {
33162
+ if (this._tags[key] !== this._initialTags[key]) {
33163
+ return true;
33164
+ }
33165
+ }
33166
+ return false;
33167
+ }
33168
+ get tags() {
33169
+ return new Proxy(this._tags, {
33170
+ set: (target, prop, value) => {
33171
+ if (isSystemTag(prop)) {
33172
+ return true;
33173
+ }
33174
+ target[prop] = value;
33175
+ return true;
33176
+ },
33177
+ deleteProperty: (target, prop) => {
33178
+ if (isSystemTag(prop)) {
33179
+ return true;
33180
+ }
33181
+ target[prop] = void 0;
33182
+ return true;
33183
+ }
33184
+ });
33185
+ }
33186
+ set tags(value) {
33187
+ this._tags = { ...value };
33188
+ }
33189
+ async fetchTags() {
33190
+ try {
33191
+ if (this.type === "bot") {
33192
+ const { bot: bot2 } = await this.client.getBot({ id: this.id });
33193
+ return bot2.tags || {};
33194
+ } else if (this.type === "user") {
33195
+ const { user: user2 } = await this.client.getUser({ id: this.id });
33196
+ return user2.tags || {};
33197
+ } else if (this.type === "conversation") {
33198
+ const { conversation } = await this.client.getConversation({ id: this.id });
33199
+ return conversation.tags || {};
33200
+ } else if (this.type === "workflow") {
33201
+ const { workflow } = await this.client.getWorkflow({ id: this.id });
33202
+ return workflow.tags || {};
33203
+ }
33204
+ } catch (err) {
33205
+ console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
33206
+ }
33207
+ return {};
33208
+ }
33209
+ async persistTags(tags) {
33210
+ const tagsForApi = {};
33211
+ for (const [key, value] of Object.entries(tags)) {
33212
+ if (value !== void 0 && !isSystemTag(key)) {
33213
+ tagsForApi[key] = value;
33214
+ }
33215
+ }
33216
+ try {
33217
+ if (this.type === "bot") {
33218
+ await this.client.updateBot({ id: this.id, tags: tagsForApi });
33219
+ } else if (this.type === "user") {
33220
+ await this.client.updateUser({ id: this.id, tags: tagsForApi });
33221
+ } else if (this.type === "conversation") {
33222
+ await this.client.updateConversation({ id: this.id, tags: tagsForApi });
33223
+ } else if (this.type === "workflow") {
33224
+ await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
33225
+ }
33226
+ } catch (err) {
33227
+ console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
33228
+ throw err;
33229
+ }
33230
+ }
33231
+ };
33232
+ }
33233
+ });
33234
+
32947
33235
  // src/runtime/heavy-imports.ts
32948
33236
  var HEAVY_IMPORTS, clearScheduledHeavyImports, importScheduledHeavyImports;
32949
33237
  var init_heavy_imports = __esm({
@@ -33058,6 +33346,7 @@ var init_handlers = __esm({
33058
33346
  init_http2();
33059
33347
  init_agent_registry();
33060
33348
  init_tracked_state();
33349
+ init_tracked_tags();
33061
33350
  init_tracing();
33062
33351
  init_heavy_imports();
33063
33352
  init_environment();
@@ -33854,6 +34143,9 @@ Always prefer information from the knowledge bases over general knowledge when a
33854
34143
  ...props.hooks?.onBeforeTool && {
33855
34144
  onBeforeTool: asyncResource.bind(props.hooks.onBeforeTool)
33856
34145
  },
34146
+ ...props.hooks?.onIterationStart && {
34147
+ onIterationStart: asyncResource.bind(props.hooks.onIterationStart)
34148
+ },
33857
34149
  ...props.hooks?.onAfterTool && {
33858
34150
  onAfterTool: asyncResource.bind(props.hooks.onAfterTool)
33859
34151
  },
@@ -33983,7 +34275,7 @@ var init_actions = __esm({
33983
34275
  }
33984
34276
  integrations ??= context2.get("integrations", { optional: true });
33985
34277
  client2 ??= context2.get("client", { optional: true });
33986
- const integration = integrations.find((i) => i.alias === integrationName);
34278
+ const integration = integrations?.find((i) => i.alias === integrationName);
33987
34279
  const actionDef = integration?.definition.actions?.[actionName];
33988
34280
  const handler = async (params) => {
33989
34281
  integrations ??= context2.get("integrations", { optional: true });
@@ -44353,15 +44645,25 @@ var init_validate_tag_name = __esm({
44353
44645
  }
44354
44646
  });
44355
44647
 
44648
+ // src/utilities/validate-event-name.ts
44649
+ var init_validate_event_name = __esm({
44650
+ "src/utilities/validate-event-name.ts"() {
44651
+ "use strict";
44652
+ init_define_BUILD();
44653
+ init_define_PACKAGE_VERSIONS();
44654
+ }
44655
+ });
44656
+
44356
44657
  // src/define-config.ts
44357
44658
  import { z as z14 } from "@botpress/sdk";
44358
- var zuiSchema, modelSchema, tagDefinitionSchema, configSchema, AGENT_CONFIG_BRAND;
44659
+ var zuiSchema, modelSchema, tagDefinitionSchema, eventDefinitionSchema, configSchema, AGENT_CONFIG_BRAND;
44359
44660
  var init_define_config = __esm({
44360
44661
  "src/define-config.ts"() {
44361
44662
  "use strict";
44362
44663
  init_define_BUILD();
44363
44664
  init_define_PACKAGE_VERSIONS();
44364
44665
  init_validate_tag_name();
44666
+ init_validate_event_name();
44365
44667
  zuiSchema = z14.custom(
44366
44668
  (val) => {
44367
44669
  if (typeof val === "object" && val !== null && "parse" in val) {
@@ -44386,6 +44688,13 @@ var init_define_config = __esm({
44386
44688
  description: z14.string().optional()
44387
44689
  })
44388
44690
  );
44691
+ eventDefinitionSchema = z14.record(
44692
+ z14.string(),
44693
+ z14.object({
44694
+ schema: zuiSchema.optional(),
44695
+ description: z14.string().optional()
44696
+ })
44697
+ );
44389
44698
  configSchema = z14.object({
44390
44699
  name: z14.string().optional(),
44391
44700
  description: z14.string().optional(),
@@ -44426,7 +44735,8 @@ var init_define_config = __esm({
44426
44735
  zai: val?.zai ?? "openai:gpt-4.1-2025-04-14",
44427
44736
  autonomous: val?.autonomous ?? "openai:gpt-4.1-mini-2025-04-14"
44428
44737
  })),
44429
- dependencies: z14.custom()
44738
+ dependencies: z14.custom(),
44739
+ events: eventDefinitionSchema.optional()
44430
44740
  });
44431
44741
  AGENT_CONFIG_BRAND = Symbol.for("@botpress/runtime/AgentConfig");
44432
44742
  }
@@ -44917,12 +45227,12 @@ var init_workflow_step = __esm({
44917
45227
  workflowControlContext.abort();
44918
45228
  throw createStepSignal();
44919
45229
  };
44920
- step.sleep = async (name, ms3) => {
45230
+ step.sleep = async (name, ms4) => {
44921
45231
  await _step(
44922
45232
  name,
44923
45233
  async () => {
44924
45234
  const remainingTime = context2.get("runtime").getRemainingExecutionTimeInMs();
44925
- if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms3 || ms3 >= 1e4) {
45235
+ if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms4 || ms4 >= 1e4) {
44926
45236
  const client2 = context2.get("client");
44927
45237
  const workflowControlContext = context2.get("workflowControlContext");
44928
45238
  await client2.createEvent({
@@ -44930,7 +45240,7 @@ var init_workflow_step = __esm({
44930
45240
  payload: {},
44931
45241
  workflowId: workflowControlContext.workflow.id,
44932
45242
  schedule: {
44933
- delay: ms3
45243
+ delay: ms4
44934
45244
  }
44935
45245
  });
44936
45246
  await updateWorkflow({
@@ -44939,7 +45249,7 @@ var init_workflow_step = __esm({
44939
45249
  });
44940
45250
  workflowControlContext.abort();
44941
45251
  } else {
44942
- await new Promise((resolve) => void setTimeout(resolve, ms3));
45252
+ await new Promise((resolve) => void setTimeout(resolve, ms4));
44943
45253
  context2.get("workflowControlContext").signal.throwIfAborted();
44944
45254
  }
44945
45255
  },
@@ -44950,8 +45260,8 @@ var init_workflow_step = __esm({
44950
45260
  );
44951
45261
  };
44952
45262
  step.sleepUntil = async (name, date) => {
44953
- const ms3 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
44954
- await step.sleep(name, ms3);
45263
+ const ms4 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
45264
+ await step.sleep(name, ms4);
44955
45265
  };
44956
45266
  step.waitForWorkflow = async (name, workflowId) => {
44957
45267
  const workflowControlContext = context2.get("workflowControlContext");
@@ -45170,12 +45480,13 @@ function createWorkflowExecutionState(client2, workflowId) {
45170
45480
  name: BUILT_IN_STATES.workflowSteps
45171
45481
  });
45172
45482
  }
45173
- var workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
45483
+ var import_ms, workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
45174
45484
  var init_workflow_instance = __esm({
45175
45485
  "src/primitives/workflow-instance.ts"() {
45176
45486
  "use strict";
45177
45487
  init_define_BUILD();
45178
45488
  init_define_PACKAGE_VERSIONS();
45489
+ import_ms = __toESM(require_ms(), 1);
45179
45490
  init_errors();
45180
45491
  init_library();
45181
45492
  init_autonomous();
@@ -45302,6 +45613,81 @@ var init_workflow_instance = __esm({
45302
45613
  });
45303
45614
  Object.assign(this.workflow, workflow);
45304
45615
  }
45616
+ /**
45617
+ * Extend the workflow timeout by setting a new timeout.
45618
+ * This is useful for long-running workflows that need more time to complete.
45619
+ *
45620
+ * @param options - Either `{ in: string }` for relative duration or `{ at: string }` for absolute ISO timestamp
45621
+ * @returns A promise that resolves when the timeout is updated (can be awaited or not)
45622
+ * @example
45623
+ * // Relative timeout (duration from now):
45624
+ * workflow.setTimeout({ in: '30m' }) // Timeout in 30 minutes
45625
+ * workflow.setTimeout({ in: '6 hours' }) // Timeout in 6 hours
45626
+ *
45627
+ * // Absolute timeout (ISO timestamp):
45628
+ * workflow.setTimeout({ at: '2024-12-25T00:00:00Z' })
45629
+ *
45630
+ * // Optionally await if you need to ensure the update completes:
45631
+ * await workflow.setTimeout({ in: '1h' })
45632
+ */
45633
+ setTimeout(options) {
45634
+ let newTimeoutAt;
45635
+ if ("in" in options) {
45636
+ const durationMs = (0, import_ms.default)(options.in);
45637
+ if (!durationMs) {
45638
+ throw new Error(`Invalid duration format: "${options.in}". Use formats like "30m", "1h", "6 hours".`);
45639
+ }
45640
+ newTimeoutAt = new Date(Date.now() + durationMs).toISOString();
45641
+ } else {
45642
+ const date = new Date(options.at);
45643
+ if (isNaN(date.getTime())) {
45644
+ throw new Error(`Invalid ISO date format: "${options.at}".`);
45645
+ }
45646
+ newTimeoutAt = date.toISOString();
45647
+ }
45648
+ return updateWorkflow({
45649
+ id: this.id,
45650
+ timeoutAt: newTimeoutAt
45651
+ }).then(({ workflow }) => {
45652
+ Object.assign(this.workflow, workflow);
45653
+ });
45654
+ }
45655
+ /**
45656
+ * Fail the workflow with an error reason.
45657
+ * This immediately interrupts the workflow handler and marks the workflow as failed.
45658
+ * Can only be called from within a workflow handler.
45659
+ *
45660
+ * @param reason - The error reason for the failure
45661
+ * @throws Never returns - always throws to interrupt the handler
45662
+ * @example
45663
+ * workflow.fail('Invalid input data')
45664
+ */
45665
+ fail(reason) {
45666
+ const controlContext = context2.get("workflowControlContext", { optional: true });
45667
+ if (!controlContext || controlContext.workflow.id !== this.id) {
45668
+ throw new Error("workflow.fail() can only be called from within the workflow handler");
45669
+ }
45670
+ controlContext.fail(reason);
45671
+ throw createStepSignal();
45672
+ }
45673
+ /**
45674
+ * Complete the workflow early with the given output.
45675
+ * This immediately interrupts the workflow handler and marks the workflow as completed.
45676
+ * Can only be called from within a workflow handler.
45677
+ *
45678
+ * @param output - The workflow output (typed according to workflow definition)
45679
+ * @throws Never returns - always throws to interrupt the handler
45680
+ * @example
45681
+ * workflow.complete({ result: 'success', data: processedData })
45682
+ */
45683
+ complete(output2) {
45684
+ const controlContext = context2.get("workflowControlContext", { optional: true });
45685
+ if (!controlContext || controlContext.workflow.id !== this.id) {
45686
+ throw new Error("workflow.complete() can only be called from within the workflow handler");
45687
+ }
45688
+ controlContext.complete(output2);
45689
+ throw createStepSignal();
45690
+ }
45305
45691
  /**
45306
45692
  * Provide data in response to a workflow data request (instance method).
45307
45693
  * Call this method from a conversation handler when you receive a WorkflowDataRequestEvent.
@@ -45352,6 +45738,7 @@ var init_workflow_instance = __esm({
45352
45738
  workflow: this.workflow,
45353
45739
  aborted: false,
45354
45740
  failed: false,
45741
+ completed: false,
45355
45742
  acked: false,
45356
45743
  restarted: false,
45357
45744
  signal: abortSignal,
@@ -45366,6 +45753,10 @@ var init_workflow_instance = __esm({
45366
45753
  workflowControlContext.failed = true;
45367
45754
  workflowControlContext.failedReason = reason;
45368
45755
  },
45756
+ complete: (result) => {
45757
+ workflowControlContext.completed = true;
45758
+ workflowControlContext.completedResult = result;
45759
+ },
45369
45760
  ack: async () => {
45370
45761
  if (workflowControlContext.acked) {
45371
45762
  return;
@@ -45419,7 +45810,8 @@ var init_workflow_instance = __esm({
45419
45810
  step,
45420
45811
  client: this.client,
45421
45812
  execute: this.execute.bind(this),
45422
- signal: abortSignal
45813
+ signal: abortSignal,
45814
+ workflow: this
45423
45815
  });
45424
45816
  return {
45425
45817
  status: "done",
@@ -45430,6 +45822,12 @@ var init_workflow_instance = __esm({
45430
45822
  }
45431
45823
  } catch (err) {
45432
45824
  if (isStepSignal(err)) {
45825
+ if (workflowControlContext.completed) {
45826
+ return {
45827
+ status: "done",
45828
+ result: workflowControlContext.completedResult
45829
+ };
45830
+ }
45433
45831
  if (workflowControlContext.failed) {
45434
45832
  return {
45435
45833
  status: "error",
@@ -45484,7 +45882,7 @@ var init_workflow_instance = __esm({
45484
45882
 
45485
45883
  // src/primitives/workflow.ts
45486
45884
  import { z as z23 } from "@botpress/sdk";
45487
- var import_ms, WorkflowHandler, Typings7, BaseWorkflow;
45885
+ var import_ms2, WorkflowHandler, Typings7, BaseWorkflow;
45488
45886
  var init_workflow = __esm({
45489
45887
  "src/primitives/workflow.ts"() {
45490
45888
  "use strict";
@@ -45492,7 +45890,7 @@ var init_workflow = __esm({
45492
45890
  init_define_PACKAGE_VERSIONS();
45493
45891
  init_workflow_instance();
45494
45892
  init_context3();
45495
- import_ms = __toESM(require_ms(), 1);
45893
+ import_ms2 = __toESM(require_ms(), 1);
45496
45894
  init_autonomous();
45497
45895
  init_runtime();
45498
45896
  WorkflowHandler = Symbol.for("workflow.handler");
@@ -45514,7 +45912,7 @@ var init_workflow = __esm({
45514
45912
  _handler;
45515
45913
  /** @internal */
45516
45914
  schedule;
45517
- timeout = (0, import_ms.default)("5m");
45915
+ timeout = (0, import_ms2.default)("5m");
45518
45916
  constructor(props) {
45519
45917
  this.name = props.name;
45520
45918
  if (props.description !== void 0) {
@@ -45527,7 +45925,7 @@ var init_workflow = __esm({
45527
45925
  this._handler = props.handler;
45528
45926
  this.schedule = props.schedule;
45529
45927
  if (props.timeout) {
45530
- this.timeout = (0, import_ms.default)(props.timeout);
45928
+ this.timeout = (0, import_ms2.default)(props.timeout);
45531
45929
  }
45532
45930
  }
45533
45931
  // @internal
@@ -45583,7 +45981,7 @@ var init_workflow = __esm({
45583
45981
  tags,
45584
45982
  conversationId: context2.get("conversation", { optional: true })?.id,
45585
45983
  parentWorkflowId: context2.get("workflow", { optional: true })?.id,
45586
- timeoutAt: new Date(Date.now() + (this.timeout ?? (0, import_ms.default)("5m"))).toISOString(),
45984
+ timeoutAt: new Date(Date.now() + (this.timeout ?? (0, import_ms2.default)("5m"))).toISOString(),
45587
45985
  ...discriminator && { discriminateBy: { tags: discriminator } }
45588
45986
  };
45589
45987
  let { workflow } = await client2._inner.getOrCreateWorkflow(createArgs);
@@ -45646,7 +46044,7 @@ var init_workflow = __esm({
45646
46044
  input: validatedInput,
45647
46045
  parentWorkflowId: workflow?.id,
45648
46046
  conversationId: context2.get("conversation", { optional: true })?.id,
45649
- timeoutAt: new Date(Date.now() + (this.timeout ?? (0, import_ms.default)("5m"))).toISOString()
46047
+ timeoutAt: new Date(Date.now() + (this.timeout ?? (0, import_ms2.default)("5m"))).toISOString()
45650
46048
  });
45651
46049
  return await BaseWorkflowInstance.load({
45652
46050
  id: res.workflow.id,
@@ -46461,7 +46859,7 @@ var init_trigger2 = __esm({
46461
46859
  });
46462
46860
 
46463
46861
  // src/runtime/handlers/workflow.ts
46464
- var import_ms2;
46862
+ var import_ms3;
46465
46863
  var init_workflow2 = __esm({
46466
46864
  "src/runtime/handlers/workflow.ts"() {
46467
46865
  "use strict";
@@ -46473,7 +46871,7 @@ var init_workflow2 = __esm({
46473
46871
  init_tracing();
46474
46872
  init_adk();
46475
46873
  init_workflow_utils();
46476
- import_ms2 = __toESM(require_ms(), 1);
46874
+ import_ms3 = __toESM(require_ms(), 1);
46477
46875
  }
46478
46876
  });
46479
46877
 
@@ -46517,259 +46915,6 @@ var init_handlers2 = __esm({
46517
46915
  }
46518
46916
  });
46519
46917
 
46520
- // src/runtime/tracked-tags.ts
46521
- var TrackedTags;
46522
- var init_tracked_tags = __esm({
46523
- "src/runtime/tracked-tags.ts"() {
46524
- "use strict";
46525
- init_define_BUILD();
46526
- init_define_PACKAGE_VERSIONS();
46527
- init_context3();
46528
- init_tracing();
46529
- TrackedTags = class _TrackedTags {
46530
- type;
46531
- id;
46532
- client;
46533
- _tags = {};
46534
- _initialTags = {};
46535
- _loaded = false;
46536
- _saving = false;
46537
- _saveAgain = false;
46538
- _saveAgainCount = 0;
46539
- static _savingAll = false;
46540
- static _saveAllAgain = false;
46541
- static _saveAllCount = 0;
46542
- constructor(props) {
46543
- this.type = props.type;
46544
- this.id = props.id;
46545
- this.client = props.client;
46546
- }
46547
- static create(props) {
46548
- const tags = context2.get("tags", { optional: true });
46549
- const executionFinished = context2.get("executionFinished", { optional: true });
46550
- if (executionFinished) {
46551
- throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
46552
- }
46553
- const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
46554
- if (match2) {
46555
- return match2;
46556
- }
46557
- const instance = new _TrackedTags(props);
46558
- if (props.initialTags) {
46559
- instance._tags = { ...props.initialTags };
46560
- instance._initialTags = { ...props.initialTags };
46561
- instance._loaded = true;
46562
- }
46563
- tags?.push(instance);
46564
- return instance;
46565
- }
46566
- static async saveAllDirty() {
46567
- if (this._savingAll) {
46568
- this._saveAllAgain = true;
46569
- return;
46570
- }
46571
- try {
46572
- this._savingAll = true;
46573
- const tags = context2.get("tags", { optional: true });
46574
- const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
46575
- if (!dirtyTags.length) {
46576
- return;
46577
- }
46578
- await span(
46579
- "tags.saveAllDirty",
46580
- {
46581
- tags_count: tags?.length || 0,
46582
- tags: tags.map((t) => `${t.type}/${t.id}`)
46583
- },
46584
- () => Promise.allSettled(dirtyTags.map((t) => t.save()))
46585
- );
46586
- } finally {
46587
- this._savingAll = false;
46588
- if (this._saveAllAgain && this._saveAllCount++ <= 5) {
46589
- this._saveAllAgain = false;
46590
- await this.saveAllDirty();
46591
- } else {
46592
- this._saveAllCount = 0;
46593
- }
46594
- }
46595
- }
46596
- static async loadAll() {
46597
- await span("tags.loadAll", {}, async () => {
46598
- const client2 = context2.get("client")._inner;
46599
- const bot2 = context2.get("bot", { optional: true });
46600
- const user2 = context2.get("user", { optional: true });
46601
- const conversation = context2.get("conversation", { optional: true });
46602
- const workflow = context2.get("workflow", { optional: true });
46603
- if (bot2) {
46604
- const botTags = bot2.tags;
46605
- _TrackedTags.create({
46606
- client: client2,
46607
- type: "bot",
46608
- id: bot2.id,
46609
- ...botTags && { initialTags: botTags }
46610
- });
46611
- }
46612
- if (user2) {
46613
- const userTags = user2.tags;
46614
- _TrackedTags.create({
46615
- client: client2,
46616
- type: "user",
46617
- id: user2.id,
46618
- ...userTags && { initialTags: userTags }
46619
- });
46620
- }
46621
- if (conversation) {
46622
- const conversationTags = conversation.tags;
46623
- _TrackedTags.create({
46624
- client: client2,
46625
- type: "conversation",
46626
- id: conversation.id,
46627
- ...conversationTags && { initialTags: conversationTags }
46628
- });
46629
- }
46630
- if (workflow) {
46631
- const workflowTags = workflow.tags;
46632
- _TrackedTags.create({
46633
- client: client2,
46634
- type: "workflow",
46635
- id: workflow.id,
46636
- ...workflowTags && { initialTags: workflowTags }
46637
- });
46638
- }
46639
- const tags = context2.get("tags", { optional: true });
46640
- const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
46641
- if (unloadedTags.length > 0) {
46642
- await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
46643
- }
46644
- });
46645
- }
46646
- static unloadAll() {
46647
- context2.get("tags", { optional: true })?.splice(0);
46648
- }
46649
- async load(force = false) {
46650
- if (this._loaded && !force) {
46651
- return;
46652
- }
46653
- await span(
46654
- "tags.load",
46655
- {
46656
- type: this.type,
46657
- id: this.id
46658
- },
46659
- async () => {
46660
- const tags = await this.fetchTags();
46661
- this._tags = { ...tags };
46662
- this._initialTags = { ...tags };
46663
- this._loaded = true;
46664
- }
46665
- );
46666
- }
46667
- async save() {
46668
- if (this._saving) {
46669
- this._saveAgain = true;
46670
- return;
46671
- }
46672
- const executionFinished = context2.get("executionFinished", { optional: true });
46673
- if (executionFinished) {
46674
- throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
46675
- }
46676
- try {
46677
- this._saving = true;
46678
- await span(
46679
- "tags.save",
46680
- {
46681
- type: this.type,
46682
- id: this.id
46683
- },
46684
- async () => {
46685
- await this.persistTags(this._tags);
46686
- this._initialTags = { ...this._tags };
46687
- }
46688
- );
46689
- } finally {
46690
- this._saving = false;
46691
- if (this._saveAgain && this._saveAgainCount++ <= 5) {
46692
- this._saveAgain = false;
46693
- await this.save();
46694
- } else {
46695
- this._saveAgainCount = 0;
46696
- }
46697
- }
46698
- }
46699
- isDirty() {
46700
- const currentKeys = Object.keys(this._tags).sort();
46701
- const initialKeys = Object.keys(this._initialTags).sort();
46702
- if (currentKeys.length !== initialKeys.length) {
46703
- return true;
46704
- }
46705
- for (const key of currentKeys) {
46706
- if (this._tags[key] !== this._initialTags[key]) {
46707
- return true;
46708
- }
46709
- }
46710
- return false;
46711
- }
46712
- get tags() {
46713
- return new Proxy(this._tags, {
46714
- set: (target, prop, value) => {
46715
- target[prop] = value;
46716
- return true;
46717
- },
46718
- deleteProperty: (target, prop) => {
46719
- target[prop] = void 0;
46720
- return true;
46721
- }
46722
- });
46723
- }
46724
- set tags(value) {
46725
- this._tags = { ...value };
46726
- }
46727
- async fetchTags() {
46728
- try {
46729
- if (this.type === "bot") {
46730
- const { bot: bot2 } = await this.client.getBot({ id: this.id });
46731
- return bot2.tags || {};
46732
- } else if (this.type === "user") {
46733
- const { user: user2 } = await this.client.getUser({ id: this.id });
46734
- return user2.tags || {};
46735
- } else if (this.type === "conversation") {
46736
- const { conversation } = await this.client.getConversation({ id: this.id });
46737
- return conversation.tags || {};
46738
- } else if (this.type === "workflow") {
46739
- const { workflow } = await this.client.getWorkflow({ id: this.id });
46740
- return workflow.tags || {};
46741
- }
46742
- } catch (err) {
46743
- console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
46744
- }
46745
- return {};
46746
- }
46747
- async persistTags(tags) {
46748
- const tagsForApi = {};
46749
- for (const [key, value] of Object.entries(tags)) {
46750
- if (value !== void 0) {
46751
- tagsForApi[key] = value;
46752
- }
46753
- }
46754
- try {
46755
- if (this.type === "bot") {
46756
- await this.client.updateBot({ id: this.id, tags: tagsForApi });
46757
- } else if (this.type === "user") {
46758
- await this.client.updateUser({ id: this.id, tags: tagsForApi });
46759
- } else if (this.type === "conversation") {
46760
- await this.client.updateConversation({ id: this.id, tags: tagsForApi });
46761
- } else if (this.type === "workflow") {
46762
- await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
46763
- }
46764
- } catch (err) {
46765
- console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
46766
- throw err;
46767
- }
46768
- }
46769
- };
46770
- }
46771
- });
46772
-
46773
46918
  // src/runtime/index.ts
46774
46919
  var init_runtime2 = __esm({
46775
46920
  "src/runtime/index.ts"() {