@botpress/runtime 1.13.9 → 1.13.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/define-config.d.ts +23 -1
  2. package/dist/define-config.d.ts.map +1 -1
  3. package/dist/definition.js +400 -290
  4. package/dist/definition.js.map +4 -4
  5. package/dist/internal.js +494 -384
  6. package/dist/internal.js.map +4 -4
  7. package/dist/library.d.ts +4 -2
  8. package/dist/library.d.ts.map +1 -1
  9. package/dist/library.js +427 -284
  10. package/dist/library.js.map +4 -4
  11. package/dist/primitives/conversation.d.ts +24 -11
  12. package/dist/primitives/conversation.d.ts.map +1 -1
  13. package/dist/primitives/data-sources/source-base.d.ts +1 -1
  14. package/dist/primitives/data-sources/source-base.d.ts.map +1 -1
  15. package/dist/primitives/index.d.ts +1 -1
  16. package/dist/primitives/workflow-instance.d.ts +45 -1
  17. package/dist/primitives/workflow-instance.d.ts.map +1 -1
  18. package/dist/primitives/workflow.d.ts +3 -2
  19. package/dist/primitives/workflow.d.ts.map +1 -1
  20. package/dist/runtime/autonomous.d.ts +1 -0
  21. package/dist/runtime/autonomous.d.ts.map +1 -1
  22. package/dist/runtime/context/context.d.ts +3 -0
  23. package/dist/runtime/context/context.d.ts.map +1 -1
  24. package/dist/runtime/context/handlers.d.ts.map +1 -1
  25. package/dist/runtime/handlers/event.d.ts.map +1 -1
  26. package/dist/runtime/handlers/workflow.d.ts.map +1 -1
  27. package/dist/runtime/tracked-tags.d.ts.map +1 -1
  28. package/dist/runtime.js +451 -302
  29. package/dist/runtime.js.map +4 -4
  30. package/dist/utilities/events.d.ts +28 -0
  31. package/dist/utilities/events.d.ts.map +1 -1
  32. package/dist/utilities/validate-event-name.d.ts +20 -0
  33. package/dist/utilities/validate-event-name.d.ts.map +1 -0
  34. package/package.json +1 -1
package/dist/internal.js CHANGED
@@ -48,7 +48,7 @@ var init_define_BUILD = __esm({
48
48
  var define_PACKAGE_VERSIONS_default;
49
49
  var init_define_PACKAGE_VERSIONS = __esm({
50
50
  "<define:__PACKAGE_VERSIONS__>"() {
51
- define_PACKAGE_VERSIONS_default = { runtime: "1.13.9", adk: "1.13.9", sdk: "5.0.2", llmz: "0.0.35", zai: "2.5.6", cognitive: "0.3.3" };
51
+ define_PACKAGE_VERSIONS_default = { runtime: "1.13.10", adk: "1.13.10", sdk: "5.0.2", llmz: "0.0.35", zai: "2.5.6", cognitive: "0.3.3" };
52
52
  }
53
53
  });
54
54
 
@@ -61,6 +61,124 @@ var init_asset = __esm({
61
61
  }
62
62
  });
63
63
 
64
+ // ../../node_modules/ms/index.js
65
+ var require_ms = __commonJS({
66
+ "../../node_modules/ms/index.js"(exports2, module) {
67
+ init_define_BUILD();
68
+ init_define_PACKAGE_VERSIONS();
69
+ var s = 1e3;
70
+ var m = s * 60;
71
+ var h = m * 60;
72
+ var d = h * 24;
73
+ var w = d * 7;
74
+ var y = d * 365.25;
75
+ module.exports = function(val, options) {
76
+ options = options || {};
77
+ var type = typeof val;
78
+ if (type === "string" && val.length > 0) {
79
+ return parse(val);
80
+ } else if (type === "number" && isFinite(val)) {
81
+ return options.long ? fmtLong(val) : fmtShort(val);
82
+ }
83
+ throw new Error(
84
+ "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
85
+ );
86
+ };
87
+ function parse(str) {
88
+ str = String(str);
89
+ if (str.length > 100) {
90
+ return;
91
+ }
92
+ var match2 = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
93
+ str
94
+ );
95
+ if (!match2) {
96
+ return;
97
+ }
98
+ var n = parseFloat(match2[1]);
99
+ var type = (match2[2] || "ms").toLowerCase();
100
+ switch (type) {
101
+ case "years":
102
+ case "year":
103
+ case "yrs":
104
+ case "yr":
105
+ case "y":
106
+ return n * y;
107
+ case "weeks":
108
+ case "week":
109
+ case "w":
110
+ return n * w;
111
+ case "days":
112
+ case "day":
113
+ case "d":
114
+ return n * d;
115
+ case "hours":
116
+ case "hour":
117
+ case "hrs":
118
+ case "hr":
119
+ case "h":
120
+ return n * h;
121
+ case "minutes":
122
+ case "minute":
123
+ case "mins":
124
+ case "min":
125
+ case "m":
126
+ return n * m;
127
+ case "seconds":
128
+ case "second":
129
+ case "secs":
130
+ case "sec":
131
+ case "s":
132
+ return n * s;
133
+ case "milliseconds":
134
+ case "millisecond":
135
+ case "msecs":
136
+ case "msec":
137
+ case "ms":
138
+ return n;
139
+ default:
140
+ return void 0;
141
+ }
142
+ }
143
+ function fmtShort(ms4) {
144
+ var msAbs = Math.abs(ms4);
145
+ if (msAbs >= d) {
146
+ return Math.round(ms4 / d) + "d";
147
+ }
148
+ if (msAbs >= h) {
149
+ return Math.round(ms4 / h) + "h";
150
+ }
151
+ if (msAbs >= m) {
152
+ return Math.round(ms4 / m) + "m";
153
+ }
154
+ if (msAbs >= s) {
155
+ return Math.round(ms4 / s) + "s";
156
+ }
157
+ return ms4 + "ms";
158
+ }
159
+ function fmtLong(ms4) {
160
+ var msAbs = Math.abs(ms4);
161
+ if (msAbs >= d) {
162
+ return plural(ms4, msAbs, d, "day");
163
+ }
164
+ if (msAbs >= h) {
165
+ return plural(ms4, msAbs, h, "hour");
166
+ }
167
+ if (msAbs >= m) {
168
+ return plural(ms4, msAbs, m, "minute");
169
+ }
170
+ if (msAbs >= s) {
171
+ return plural(ms4, msAbs, s, "second");
172
+ }
173
+ return ms4 + " ms";
174
+ }
175
+ function plural(ms4, msAbs, n, name) {
176
+ var isPlural = msAbs >= n * 1.5;
177
+ return Math.round(ms4 / n) + " " + name + (isPlural ? "s" : "");
178
+ }
179
+ }
180
+ });
181
+
64
182
  // src/errors.ts
65
183
  import { z } from "@botpress/sdk";
66
184
  var Errors;
@@ -27909,124 +28027,6 @@ var require_proxy_from_env = __commonJS({
27909
28027
  }
27910
28028
  });
27911
28029
 
27912
- // ../../node_modules/ms/index.js
27913
- var require_ms = __commonJS({
27914
- "../../node_modules/ms/index.js"(exports2, module) {
27915
- init_define_BUILD();
27916
- init_define_PACKAGE_VERSIONS();
27917
- var s = 1e3;
27918
- var m = s * 60;
27919
- var h = m * 60;
27920
- var d = h * 24;
27921
- var w = d * 7;
27922
- var y = d * 365.25;
27923
- module.exports = function(val, options) {
27924
- options = options || {};
27925
- var type = typeof val;
27926
- if (type === "string" && val.length > 0) {
27927
- return parse(val);
27928
- } else if (type === "number" && isFinite(val)) {
27929
- return options.long ? fmtLong(val) : fmtShort(val);
27930
- }
27931
- throw new Error(
27932
- "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
27933
- );
27934
- };
27935
- function parse(str) {
27936
- str = String(str);
27937
- if (str.length > 100) {
27938
- return;
27939
- }
27940
- var match2 = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
27941
- str
27942
- );
27943
- if (!match2) {
27944
- return;
27945
- }
27946
- var n = parseFloat(match2[1]);
27947
- var type = (match2[2] || "ms").toLowerCase();
27948
- switch (type) {
27949
- case "years":
27950
- case "year":
27951
- case "yrs":
27952
- case "yr":
27953
- case "y":
27954
- return n * y;
27955
- case "weeks":
27956
- case "week":
27957
- case "w":
27958
- return n * w;
27959
- case "days":
27960
- case "day":
27961
- case "d":
27962
- return n * d;
27963
- case "hours":
27964
- case "hour":
27965
- case "hrs":
27966
- case "hr":
27967
- case "h":
27968
- return n * h;
27969
- case "minutes":
27970
- case "minute":
27971
- case "mins":
27972
- case "min":
27973
- case "m":
27974
- return n * m;
27975
- case "seconds":
27976
- case "second":
27977
- case "secs":
27978
- case "sec":
27979
- case "s":
27980
- return n * s;
27981
- case "milliseconds":
27982
- case "millisecond":
27983
- case "msecs":
27984
- case "msec":
27985
- case "ms":
27986
- return n;
27987
- default:
27988
- return void 0;
27989
- }
27990
- }
27991
- function fmtShort(ms3) {
27992
- var msAbs = Math.abs(ms3);
27993
- if (msAbs >= d) {
27994
- return Math.round(ms3 / d) + "d";
27995
- }
27996
- if (msAbs >= h) {
27997
- return Math.round(ms3 / h) + "h";
27998
- }
27999
- if (msAbs >= m) {
28000
- return Math.round(ms3 / m) + "m";
28001
- }
28002
- if (msAbs >= s) {
28003
- return Math.round(ms3 / s) + "s";
28004
- }
28005
- return ms3 + "ms";
28006
- }
28007
- function fmtLong(ms3) {
28008
- var msAbs = Math.abs(ms3);
28009
- if (msAbs >= d) {
28010
- return plural(ms3, msAbs, d, "day");
28011
- }
28012
- if (msAbs >= h) {
28013
- return plural(ms3, msAbs, h, "hour");
28014
- }
28015
- if (msAbs >= m) {
28016
- return plural(ms3, msAbs, m, "minute");
28017
- }
28018
- if (msAbs >= s) {
28019
- return plural(ms3, msAbs, s, "second");
28020
- }
28021
- return ms3 + " ms";
28022
- }
28023
- function plural(ms3, msAbs, n, name) {
28024
- var isPlural = msAbs >= n * 1.5;
28025
- return Math.round(ms3 / n) + " " + name + (isPlural ? "s" : "");
28026
- }
28027
- }
28028
- });
28029
-
28030
28030
  // ../../node_modules/debug/src/common.js
28031
28031
  var require_common = __commonJS({
28032
28032
  "../../node_modules/debug/src/common.js"(exports2, module) {
@@ -28067,8 +28067,8 @@ var require_common = __commonJS({
28067
28067
  }
28068
28068
  const self2 = debug;
28069
28069
  const curr = Number(/* @__PURE__ */ new Date());
28070
- const ms3 = curr - (prevTime || curr);
28071
- self2.diff = ms3;
28070
+ const ms4 = curr - (prevTime || curr);
28071
+ self2.diff = ms4;
28072
28072
  self2.prev = prevTime;
28073
28073
  self2.curr = curr;
28074
28074
  prevTime = curr;
@@ -34676,6 +34676,9 @@ Always prefer information from the knowledge bases over general knowledge when a
34676
34676
  ...props.hooks?.onBeforeTool && {
34677
34677
  onBeforeTool: asyncResource.bind(props.hooks.onBeforeTool)
34678
34678
  },
34679
+ ...props.hooks?.onIterationStart && {
34680
+ onIterationStart: asyncResource.bind(props.hooks.onIterationStart)
34681
+ },
34679
34682
  ...props.hooks?.onAfterTool && {
34680
34683
  onAfterTool: asyncResource.bind(props.hooks.onAfterTool)
34681
34684
  },
@@ -35120,15 +35123,25 @@ var init_validate_tag_name = __esm({
35120
35123
  }
35121
35124
  });
35122
35125
 
35126
+ // src/utilities/validate-event-name.ts
35127
+ var init_validate_event_name = __esm({
35128
+ "src/utilities/validate-event-name.ts"() {
35129
+ "use strict";
35130
+ init_define_BUILD();
35131
+ init_define_PACKAGE_VERSIONS();
35132
+ }
35133
+ });
35134
+
35123
35135
  // src/define-config.ts
35124
35136
  import { z as z4 } from "@botpress/sdk";
35125
- var zuiSchema, modelSchema, tagDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, isAgentConfig;
35137
+ var zuiSchema, modelSchema, tagDefinitionSchema, eventDefinitionSchema, configSchema, AGENT_CONFIG_BRAND, isAgentConfig;
35126
35138
  var init_define_config = __esm({
35127
35139
  "src/define-config.ts"() {
35128
35140
  "use strict";
35129
35141
  init_define_BUILD();
35130
35142
  init_define_PACKAGE_VERSIONS();
35131
35143
  init_validate_tag_name();
35144
+ init_validate_event_name();
35132
35145
  zuiSchema = z4.custom(
35133
35146
  (val) => {
35134
35147
  if (typeof val === "object" && val !== null && "parse" in val) {
@@ -35153,6 +35166,13 @@ var init_define_config = __esm({
35153
35166
  description: z4.string().optional()
35154
35167
  })
35155
35168
  );
35169
+ eventDefinitionSchema = z4.record(
35170
+ z4.string(),
35171
+ z4.object({
35172
+ schema: zuiSchema.optional(),
35173
+ description: z4.string().optional()
35174
+ })
35175
+ );
35156
35176
  configSchema = z4.object({
35157
35177
  name: z4.string().optional(),
35158
35178
  description: z4.string().optional(),
@@ -35193,7 +35213,8 @@ var init_define_config = __esm({
35193
35213
  zai: val?.zai ?? "openai:gpt-4.1-2025-04-14",
35194
35214
  autonomous: val?.autonomous ?? "openai:gpt-4.1-mini-2025-04-14"
35195
35215
  })),
35196
- dependencies: z4.custom()
35216
+ dependencies: z4.custom(),
35217
+ events: eventDefinitionSchema.optional()
35197
35218
  });
35198
35219
  AGENT_CONFIG_BRAND = Symbol.for("@botpress/runtime/AgentConfig");
35199
35220
  isAgentConfig = (value) => {
@@ -36335,6 +36356,259 @@ var init_tracked_state = __esm({
36335
36356
  }
36336
36357
  });
36337
36358
 
36359
+ // src/runtime/tracked-tags.ts
36360
+ var TrackedTags;
36361
+ var init_tracked_tags = __esm({
36362
+ "src/runtime/tracked-tags.ts"() {
36363
+ "use strict";
36364
+ init_define_BUILD();
36365
+ init_define_PACKAGE_VERSIONS();
36366
+ init_context();
36367
+ init_tracing();
36368
+ TrackedTags = class _TrackedTags {
36369
+ type;
36370
+ id;
36371
+ client;
36372
+ _tags = {};
36373
+ _initialTags = {};
36374
+ _loaded = false;
36375
+ _saving = false;
36376
+ _saveAgain = false;
36377
+ _saveAgainCount = 0;
36378
+ static _savingAll = false;
36379
+ static _saveAllAgain = false;
36380
+ static _saveAllCount = 0;
36381
+ constructor(props) {
36382
+ this.type = props.type;
36383
+ this.id = props.id;
36384
+ this.client = props.client;
36385
+ }
36386
+ static create(props) {
36387
+ const tags = context.get("tags", { optional: true });
36388
+ const executionFinished = context.get("executionFinished", { optional: true });
36389
+ if (executionFinished) {
36390
+ throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
36391
+ }
36392
+ const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
36393
+ if (match2) {
36394
+ return match2;
36395
+ }
36396
+ const instance = new _TrackedTags(props);
36397
+ if (props.initialTags) {
36398
+ instance._tags = { ...props.initialTags };
36399
+ instance._initialTags = { ...props.initialTags };
36400
+ instance._loaded = true;
36401
+ }
36402
+ tags?.push(instance);
36403
+ return instance;
36404
+ }
36405
+ static async saveAllDirty() {
36406
+ if (this._savingAll) {
36407
+ this._saveAllAgain = true;
36408
+ return;
36409
+ }
36410
+ try {
36411
+ this._savingAll = true;
36412
+ const tags = context.get("tags", { optional: true });
36413
+ const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
36414
+ if (!dirtyTags.length) {
36415
+ return;
36416
+ }
36417
+ await span(
36418
+ "tags.saveAllDirty",
36419
+ {
36420
+ tags_count: tags?.length || 0,
36421
+ tags: tags.map((t) => `${t.type}/${t.id}`)
36422
+ },
36423
+ () => Promise.allSettled(dirtyTags.map((t) => t.save()))
36424
+ );
36425
+ } finally {
36426
+ this._savingAll = false;
36427
+ if (this._saveAllAgain && this._saveAllCount++ <= 5) {
36428
+ this._saveAllAgain = false;
36429
+ await this.saveAllDirty();
36430
+ } else {
36431
+ this._saveAllCount = 0;
36432
+ }
36433
+ }
36434
+ }
36435
+ static async loadAll() {
36436
+ await span("tags.loadAll", {}, async () => {
36437
+ const client2 = context.get("client")._inner;
36438
+ const bot2 = context.get("bot", { optional: true });
36439
+ const user2 = context.get("user", { optional: true });
36440
+ const conversation = context.get("conversation", { optional: true });
36441
+ const workflow = context.get("workflow", { optional: true });
36442
+ if (bot2) {
36443
+ const botTags = bot2.tags;
36444
+ _TrackedTags.create({
36445
+ client: client2,
36446
+ type: "bot",
36447
+ id: bot2.id,
36448
+ ...botTags && { initialTags: botTags }
36449
+ });
36450
+ }
36451
+ if (user2) {
36452
+ const userTags = user2.tags;
36453
+ _TrackedTags.create({
36454
+ client: client2,
36455
+ type: "user",
36456
+ id: user2.id,
36457
+ ...userTags && { initialTags: userTags }
36458
+ });
36459
+ }
36460
+ if (conversation) {
36461
+ const conversationTags = conversation.tags;
36462
+ _TrackedTags.create({
36463
+ client: client2,
36464
+ type: "conversation",
36465
+ id: conversation.id,
36466
+ ...conversationTags && { initialTags: conversationTags }
36467
+ });
36468
+ }
36469
+ if (workflow) {
36470
+ const workflowTags = workflow.tags;
36471
+ _TrackedTags.create({
36472
+ client: client2,
36473
+ type: "workflow",
36474
+ id: workflow.id,
36475
+ ...workflowTags && { initialTags: workflowTags }
36476
+ });
36477
+ }
36478
+ const tags = context.get("tags", { optional: true });
36479
+ const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
36480
+ if (unloadedTags.length > 0) {
36481
+ await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
36482
+ }
36483
+ });
36484
+ }
36485
+ static unloadAll() {
36486
+ context.get("tags", { optional: true })?.splice(0);
36487
+ }
36488
+ async load(force = false) {
36489
+ if (this._loaded && !force) {
36490
+ return;
36491
+ }
36492
+ await span(
36493
+ "tags.load",
36494
+ {
36495
+ type: this.type,
36496
+ id: this.id
36497
+ },
36498
+ async () => {
36499
+ const tags = await this.fetchTags();
36500
+ this._tags = { ...tags };
36501
+ this._initialTags = { ...tags };
36502
+ this._loaded = true;
36503
+ }
36504
+ );
36505
+ }
36506
+ async save() {
36507
+ if (this._saving) {
36508
+ this._saveAgain = true;
36509
+ return;
36510
+ }
36511
+ const executionFinished = context.get("executionFinished", { optional: true });
36512
+ if (executionFinished) {
36513
+ throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
36514
+ }
36515
+ try {
36516
+ this._saving = true;
36517
+ await span(
36518
+ "tags.save",
36519
+ {
36520
+ type: this.type,
36521
+ id: this.id
36522
+ },
36523
+ async () => {
36524
+ await this.persistTags(this._tags);
36525
+ this._initialTags = { ...this._tags };
36526
+ }
36527
+ );
36528
+ } finally {
36529
+ this._saving = false;
36530
+ if (this._saveAgain && this._saveAgainCount++ <= 5) {
36531
+ this._saveAgain = false;
36532
+ await this.save();
36533
+ } else {
36534
+ this._saveAgainCount = 0;
36535
+ }
36536
+ }
36537
+ }
36538
+ isDirty() {
36539
+ const currentKeys = Object.keys(this._tags).filter((k) => !k.includes(":")).sort();
36540
+ const initialKeys = Object.keys(this._initialTags).filter((k) => !k.includes(":")).sort();
36541
+ if (currentKeys.length !== initialKeys.length) {
36542
+ return true;
36543
+ }
36544
+ for (const key of currentKeys) {
36545
+ if (this._tags[key] !== this._initialTags[key]) {
36546
+ return true;
36547
+ }
36548
+ }
36549
+ return false;
36550
+ }
36551
+ get tags() {
36552
+ return new Proxy(this._tags, {
36553
+ set: (target, prop, value) => {
36554
+ target[prop] = value;
36555
+ return true;
36556
+ },
36557
+ deleteProperty: (target, prop) => {
36558
+ target[prop] = void 0;
36559
+ return true;
36560
+ }
36561
+ });
36562
+ }
36563
+ set tags(value) {
36564
+ this._tags = { ...value };
36565
+ }
36566
+ async fetchTags() {
36567
+ try {
36568
+ if (this.type === "bot") {
36569
+ const { bot: bot2 } = await this.client.getBot({ id: this.id });
36570
+ return bot2.tags || {};
36571
+ } else if (this.type === "user") {
36572
+ const { user: user2 } = await this.client.getUser({ id: this.id });
36573
+ return user2.tags || {};
36574
+ } else if (this.type === "conversation") {
36575
+ const { conversation } = await this.client.getConversation({ id: this.id });
36576
+ return conversation.tags || {};
36577
+ } else if (this.type === "workflow") {
36578
+ const { workflow } = await this.client.getWorkflow({ id: this.id });
36579
+ return workflow.tags || {};
36580
+ }
36581
+ } catch (err) {
36582
+ console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
36583
+ }
36584
+ return {};
36585
+ }
36586
+ async persistTags(tags) {
36587
+ const tagsForApi = {};
36588
+ for (const [key, value] of Object.entries(tags)) {
36589
+ if (value !== void 0 && !key.includes(":")) {
36590
+ tagsForApi[key] = value;
36591
+ }
36592
+ }
36593
+ try {
36594
+ if (this.type === "bot") {
36595
+ await this.client.updateBot({ id: this.id, tags: tagsForApi });
36596
+ } else if (this.type === "user") {
36597
+ await this.client.updateUser({ id: this.id, tags: tagsForApi });
36598
+ } else if (this.type === "conversation") {
36599
+ await this.client.updateConversation({ id: this.id, tags: tagsForApi });
36600
+ } else if (this.type === "workflow") {
36601
+ await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
36602
+ }
36603
+ } catch (err) {
36604
+ console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
36605
+ throw err;
36606
+ }
36607
+ }
36608
+ };
36609
+ }
36610
+ });
36611
+
36338
36612
  // src/runtime/context/inspector-handler.ts
36339
36613
  var init_inspector_handler = __esm({
36340
36614
  "src/runtime/context/inspector-handler.ts"() {
@@ -36416,6 +36690,7 @@ var init_handlers = __esm({
36416
36690
  init_http();
36417
36691
  init_agent_registry();
36418
36692
  init_tracked_state();
36693
+ init_tracked_tags();
36419
36694
  init_tracing();
36420
36695
  init_heavy_imports();
36421
36696
  init_environment();
@@ -37588,259 +37863,6 @@ var init_handlers2 = __esm({
37588
37863
  }
37589
37864
  });
37590
37865
 
37591
- // src/runtime/tracked-tags.ts
37592
- var TrackedTags;
37593
- var init_tracked_tags = __esm({
37594
- "src/runtime/tracked-tags.ts"() {
37595
- "use strict";
37596
- init_define_BUILD();
37597
- init_define_PACKAGE_VERSIONS();
37598
- init_context();
37599
- init_tracing();
37600
- TrackedTags = class _TrackedTags {
37601
- type;
37602
- id;
37603
- client;
37604
- _tags = {};
37605
- _initialTags = {};
37606
- _loaded = false;
37607
- _saving = false;
37608
- _saveAgain = false;
37609
- _saveAgainCount = 0;
37610
- static _savingAll = false;
37611
- static _saveAllAgain = false;
37612
- static _saveAllCount = 0;
37613
- constructor(props) {
37614
- this.type = props.type;
37615
- this.id = props.id;
37616
- this.client = props.client;
37617
- }
37618
- static create(props) {
37619
- const tags = context.get("tags", { optional: true });
37620
- const executionFinished = context.get("executionFinished", { optional: true });
37621
- if (executionFinished) {
37622
- throw new Error(`Cannot create new TrackedTags "${props.type}/${props.id}" after execution has finished.`);
37623
- }
37624
- const match2 = tags?.find((x) => x.id === props.id && x.type === props.type);
37625
- if (match2) {
37626
- return match2;
37627
- }
37628
- const instance = new _TrackedTags(props);
37629
- if (props.initialTags) {
37630
- instance._tags = { ...props.initialTags };
37631
- instance._initialTags = { ...props.initialTags };
37632
- instance._loaded = true;
37633
- }
37634
- tags?.push(instance);
37635
- return instance;
37636
- }
37637
- static async saveAllDirty() {
37638
- if (this._savingAll) {
37639
- this._saveAllAgain = true;
37640
- return;
37641
- }
37642
- try {
37643
- this._savingAll = true;
37644
- const tags = context.get("tags", { optional: true });
37645
- const dirtyTags = tags?.filter((t) => t.isDirty()) || [];
37646
- if (!dirtyTags.length) {
37647
- return;
37648
- }
37649
- await span(
37650
- "tags.saveAllDirty",
37651
- {
37652
- tags_count: tags?.length || 0,
37653
- tags: tags.map((t) => `${t.type}/${t.id}`)
37654
- },
37655
- () => Promise.allSettled(dirtyTags.map((t) => t.save()))
37656
- );
37657
- } finally {
37658
- this._savingAll = false;
37659
- if (this._saveAllAgain && this._saveAllCount++ <= 5) {
37660
- this._saveAllAgain = false;
37661
- await this.saveAllDirty();
37662
- } else {
37663
- this._saveAllCount = 0;
37664
- }
37665
- }
37666
- }
37667
- static async loadAll() {
37668
- await span("tags.loadAll", {}, async () => {
37669
- const client2 = context.get("client")._inner;
37670
- const bot2 = context.get("bot", { optional: true });
37671
- const user2 = context.get("user", { optional: true });
37672
- const conversation = context.get("conversation", { optional: true });
37673
- const workflow = context.get("workflow", { optional: true });
37674
- if (bot2) {
37675
- const botTags = bot2.tags;
37676
- _TrackedTags.create({
37677
- client: client2,
37678
- type: "bot",
37679
- id: bot2.id,
37680
- ...botTags && { initialTags: botTags }
37681
- });
37682
- }
37683
- if (user2) {
37684
- const userTags = user2.tags;
37685
- _TrackedTags.create({
37686
- client: client2,
37687
- type: "user",
37688
- id: user2.id,
37689
- ...userTags && { initialTags: userTags }
37690
- });
37691
- }
37692
- if (conversation) {
37693
- const conversationTags = conversation.tags;
37694
- _TrackedTags.create({
37695
- client: client2,
37696
- type: "conversation",
37697
- id: conversation.id,
37698
- ...conversationTags && { initialTags: conversationTags }
37699
- });
37700
- }
37701
- if (workflow) {
37702
- const workflowTags = workflow.tags;
37703
- _TrackedTags.create({
37704
- client: client2,
37705
- type: "workflow",
37706
- id: workflow.id,
37707
- ...workflowTags && { initialTags: workflowTags }
37708
- });
37709
- }
37710
- const tags = context.get("tags", { optional: true });
37711
- const unloadedTags = tags?.filter((tag) => !tag._loaded) ?? [];
37712
- if (unloadedTags.length > 0) {
37713
- await Promise.allSettled(unloadedTags.map((tag) => tag.load()));
37714
- }
37715
- });
37716
- }
37717
- static unloadAll() {
37718
- context.get("tags", { optional: true })?.splice(0);
37719
- }
37720
- async load(force = false) {
37721
- if (this._loaded && !force) {
37722
- return;
37723
- }
37724
- await span(
37725
- "tags.load",
37726
- {
37727
- type: this.type,
37728
- id: this.id
37729
- },
37730
- async () => {
37731
- const tags = await this.fetchTags();
37732
- this._tags = { ...tags };
37733
- this._initialTags = { ...tags };
37734
- this._loaded = true;
37735
- }
37736
- );
37737
- }
37738
- async save() {
37739
- if (this._saving) {
37740
- this._saveAgain = true;
37741
- return;
37742
- }
37743
- const executionFinished = context.get("executionFinished", { optional: true });
37744
- if (executionFinished) {
37745
- throw new Error(`Cannot save TrackedTags "${this.type}/${this.id}" after execution has finished.`);
37746
- }
37747
- try {
37748
- this._saving = true;
37749
- await span(
37750
- "tags.save",
37751
- {
37752
- type: this.type,
37753
- id: this.id
37754
- },
37755
- async () => {
37756
- await this.persistTags(this._tags);
37757
- this._initialTags = { ...this._tags };
37758
- }
37759
- );
37760
- } finally {
37761
- this._saving = false;
37762
- if (this._saveAgain && this._saveAgainCount++ <= 5) {
37763
- this._saveAgain = false;
37764
- await this.save();
37765
- } else {
37766
- this._saveAgainCount = 0;
37767
- }
37768
- }
37769
- }
37770
- isDirty() {
37771
- const currentKeys = Object.keys(this._tags).sort();
37772
- const initialKeys = Object.keys(this._initialTags).sort();
37773
- if (currentKeys.length !== initialKeys.length) {
37774
- return true;
37775
- }
37776
- for (const key of currentKeys) {
37777
- if (this._tags[key] !== this._initialTags[key]) {
37778
- return true;
37779
- }
37780
- }
37781
- return false;
37782
- }
37783
- get tags() {
37784
- return new Proxy(this._tags, {
37785
- set: (target, prop, value) => {
37786
- target[prop] = value;
37787
- return true;
37788
- },
37789
- deleteProperty: (target, prop) => {
37790
- target[prop] = void 0;
37791
- return true;
37792
- }
37793
- });
37794
- }
37795
- set tags(value) {
37796
- this._tags = { ...value };
37797
- }
37798
- async fetchTags() {
37799
- try {
37800
- if (this.type === "bot") {
37801
- const { bot: bot2 } = await this.client.getBot({ id: this.id });
37802
- return bot2.tags || {};
37803
- } else if (this.type === "user") {
37804
- const { user: user2 } = await this.client.getUser({ id: this.id });
37805
- return user2.tags || {};
37806
- } else if (this.type === "conversation") {
37807
- const { conversation } = await this.client.getConversation({ id: this.id });
37808
- return conversation.tags || {};
37809
- } else if (this.type === "workflow") {
37810
- const { workflow } = await this.client.getWorkflow({ id: this.id });
37811
- return workflow.tags || {};
37812
- }
37813
- } catch (err) {
37814
- console.error(`Failed to fetch tags for ${this.type}/${this.id}:`, err);
37815
- }
37816
- return {};
37817
- }
37818
- async persistTags(tags) {
37819
- const tagsForApi = {};
37820
- for (const [key, value] of Object.entries(tags)) {
37821
- if (value !== void 0) {
37822
- tagsForApi[key] = value;
37823
- }
37824
- }
37825
- try {
37826
- if (this.type === "bot") {
37827
- await this.client.updateBot({ id: this.id, tags: tagsForApi });
37828
- } else if (this.type === "user") {
37829
- await this.client.updateUser({ id: this.id, tags: tagsForApi });
37830
- } else if (this.type === "conversation") {
37831
- await this.client.updateConversation({ id: this.id, tags: tagsForApi });
37832
- } else if (this.type === "workflow") {
37833
- await this.client.updateWorkflow({ id: this.id, tags: tagsForApi });
37834
- }
37835
- } catch (err) {
37836
- console.error(`Failed to persist tags for ${this.type}/${this.id}:`, err);
37837
- throw err;
37838
- }
37839
- }
37840
- };
37841
- }
37842
- });
37843
-
37844
37866
  // src/runtime/client.ts
37845
37867
  import { Client as Client3 } from "@botpress/client";
37846
37868
  function getStandaloneClient() {
@@ -38157,12 +38179,12 @@ var init_workflow_step = __esm({
38157
38179
  workflowControlContext.abort();
38158
38180
  throw createStepSignal();
38159
38181
  };
38160
- step.sleep = async (name, ms3) => {
38182
+ step.sleep = async (name, ms4) => {
38161
38183
  await _step(
38162
38184
  name,
38163
38185
  async () => {
38164
38186
  const remainingTime = context.get("runtime").getRemainingExecutionTimeInMs();
38165
- if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms3 || ms3 >= 1e4) {
38187
+ if (remainingTime - MIN_STEP_REMAINING_TIME_MS <= ms4 || ms4 >= 1e4) {
38166
38188
  const client2 = context.get("client");
38167
38189
  const workflowControlContext = context.get("workflowControlContext");
38168
38190
  await client2.createEvent({
@@ -38170,7 +38192,7 @@ var init_workflow_step = __esm({
38170
38192
  payload: {},
38171
38193
  workflowId: workflowControlContext.workflow.id,
38172
38194
  schedule: {
38173
- delay: ms3
38195
+ delay: ms4
38174
38196
  }
38175
38197
  });
38176
38198
  await updateWorkflow({
@@ -38179,7 +38201,7 @@ var init_workflow_step = __esm({
38179
38201
  });
38180
38202
  workflowControlContext.abort();
38181
38203
  } else {
38182
- await new Promise((resolve) => void setTimeout(resolve, ms3));
38204
+ await new Promise((resolve) => void setTimeout(resolve, ms4));
38183
38205
  context.get("workflowControlContext").signal.throwIfAborted();
38184
38206
  }
38185
38207
  },
@@ -38190,8 +38212,8 @@ var init_workflow_step = __esm({
38190
38212
  );
38191
38213
  };
38192
38214
  step.sleepUntil = async (name, date) => {
38193
- const ms3 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
38194
- await step.sleep(name, ms3);
38215
+ const ms4 = Math.max(0, new Date(date).getTime() - Date.now() - MIN_STEP_REMAINING_TIME_MS);
38216
+ await step.sleep(name, ms4);
38195
38217
  };
38196
38218
  step.waitForWorkflow = async (name, workflowId) => {
38197
38219
  const workflowControlContext = context.get("workflowControlContext");
@@ -38410,12 +38432,13 @@ function createWorkflowExecutionState(client2, workflowId) {
38410
38432
  name: BUILT_IN_STATES.workflowSteps
38411
38433
  });
38412
38434
  }
38413
- var workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
38435
+ var import_ms3, workflowStepContextSchema, workflowExecutionContextSchema, StepSymbol, BaseWorkflowInstance;
38414
38436
  var init_workflow_instance = __esm({
38415
38437
  "src/primitives/workflow-instance.ts"() {
38416
38438
  "use strict";
38417
38439
  init_define_BUILD();
38418
38440
  init_define_PACKAGE_VERSIONS();
38441
+ import_ms3 = __toESM(require_ms(), 1);
38419
38442
  init_errors();
38420
38443
  init_library();
38421
38444
  init_autonomous();
@@ -38542,6 +38565,81 @@ var init_workflow_instance = __esm({
38542
38565
  });
38543
38566
  Object.assign(this.workflow, workflow);
38544
38567
  }
38568
+ /**
38569
+ * Extend the workflow timeout by setting a new timeout.
38570
+ * This is useful for long-running workflows that need more time to complete.
38571
+ *
38572
+ * @param options - Either `{ in: string }` for relative duration or `{ at: string }` for absolute ISO timestamp
38573
+ * @returns A promise that resolves when the timeout is updated (can be awaited or not)
38574
+ * @example
38575
+ * // Relative timeout (duration from now):
38576
+ * workflow.setTimeout({ in: '30m' }) // Timeout in 30 minutes
38577
+ * workflow.setTimeout({ in: '6 hours' }) // Timeout in 6 hours
38578
+ *
38579
+ * // Absolute timeout (ISO timestamp):
38580
+ * workflow.setTimeout({ at: '2024-12-25T00:00:00Z' })
38581
+ *
38582
+ * // Optionally await if you need to ensure the update completes:
38583
+ * await workflow.setTimeout({ in: '1h' })
38584
+ */
38585
+ setTimeout(options) {
38586
+ let newTimeoutAt;
38587
+ if ("in" in options) {
38588
+ const durationMs = (0, import_ms3.default)(options.in);
38589
+ if (!durationMs) {
38590
+ throw new Error(`Invalid duration format: "${options.in}". Use formats like "30m", "1h", "6 hours".`);
38591
+ }
38592
+ newTimeoutAt = new Date(Date.now() + durationMs).toISOString();
38593
+ } else {
38594
+ const date = new Date(options.at);
38595
+ if (isNaN(date.getTime())) {
38596
+ throw new Error(`Invalid ISO date format: "${options.at}".`);
38597
+ }
38598
+ newTimeoutAt = date.toISOString();
38599
+ }
38600
+ return updateWorkflow({
38601
+ id: this.id,
38602
+ timeoutAt: newTimeoutAt
38603
+ }).then(({ workflow }) => {
38604
+ Object.assign(this.workflow, workflow);
38605
+ });
38606
+ }
38607
+ /**
38608
+ * Fail the workflow with an error reason.
38609
+ * This immediately interrupts the workflow handler and marks the workflow as failed.
38610
+ * Can only be called from within a workflow handler.
38611
+ *
38612
+ * @param reason - The error reason for the failure
38613
+ * @throws Never returns - always throws to interrupt the handler
38614
+ * @example
38615
+ * workflow.fail('Invalid input data')
38616
+ */
38617
+ fail(reason) {
38618
+ const controlContext = context.get("workflowControlContext", { optional: true });
38619
+ if (!controlContext || controlContext.workflow.id !== this.id) {
38620
+ throw new Error("workflow.fail() can only be called from within the workflow handler");
38621
+ }
38622
+ controlContext.fail(reason);
38623
+ throw createStepSignal();
38624
+ }
38625
+ /**
38626
+ * Complete the workflow early with the given output.
38627
+ * This immediately interrupts the workflow handler and marks the workflow as completed.
38628
+ * Can only be called from within a workflow handler.
38629
+ *
38630
+ * @param output - The workflow output (typed according to workflow definition)
38631
+ * @throws Never returns - always throws to interrupt the handler
38632
+ * @example
38633
+ * workflow.complete({ result: 'success', data: processedData })
38634
+ */
38635
+ complete(output2) {
38636
+ const controlContext = context.get("workflowControlContext", { optional: true });
38637
+ if (!controlContext || controlContext.workflow.id !== this.id) {
38638
+ throw new Error("workflow.complete() can only be called from within the workflow handler");
38639
+ }
38640
+ controlContext.complete(output2);
38641
+ throw createStepSignal();
38642
+ }
38545
38643
  /**
38546
38644
  * Provide data in response to a workflow data request (instance method).
38547
38645
  * Call this method from a conversation handler when you receive a WorkflowDataRequestEvent.
@@ -38592,6 +38690,7 @@ var init_workflow_instance = __esm({
38592
38690
  workflow: this.workflow,
38593
38691
  aborted: false,
38594
38692
  failed: false,
38693
+ completed: false,
38595
38694
  acked: false,
38596
38695
  restarted: false,
38597
38696
  signal: abortSignal,
@@ -38606,6 +38705,10 @@ var init_workflow_instance = __esm({
38606
38705
  workflowControlContext.failed = true;
38607
38706
  workflowControlContext.failedReason = reason;
38608
38707
  },
38708
+ complete: (result) => {
38709
+ workflowControlContext.completed = true;
38710
+ workflowControlContext.completedResult = result;
38711
+ },
38609
38712
  ack: async () => {
38610
38713
  if (workflowControlContext.acked) {
38611
38714
  return;
@@ -38659,7 +38762,8 @@ var init_workflow_instance = __esm({
38659
38762
  step,
38660
38763
  client: this.client,
38661
38764
  execute: this.execute.bind(this),
38662
- signal: abortSignal
38765
+ signal: abortSignal,
38766
+ workflow: this
38663
38767
  });
38664
38768
  return {
38665
38769
  status: "done",
@@ -38670,6 +38774,12 @@ var init_workflow_instance = __esm({
38670
38774
  }
38671
38775
  } catch (err) {
38672
38776
  if (isStepSignal(err)) {
38777
+ if (workflowControlContext.completed) {
38778
+ return {
38779
+ status: "done",
38780
+ result: workflowControlContext.completedResult
38781
+ };
38782
+ }
38673
38783
  if (workflowControlContext.failed) {
38674
38784
  return {
38675
38785
  status: "error",