@botpress/runtime 1.2.3 → 1.2.5

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 (48) hide show
  1. package/dist/_types/channels.d.ts +18 -0
  2. package/dist/_types/channels.d.ts.map +1 -0
  3. package/dist/_types/conversations.d.ts +9 -0
  4. package/dist/_types/conversations.d.ts.map +1 -0
  5. package/dist/_types/integrations.d.ts +13 -0
  6. package/dist/_types/integrations.d.ts.map +1 -0
  7. package/dist/consts.d.ts +1 -0
  8. package/dist/consts.d.ts.map +1 -1
  9. package/dist/definition.d.ts +1 -0
  10. package/dist/definition.d.ts.map +1 -1
  11. package/dist/definition.js +45914 -9
  12. package/dist/definition.js.map +4 -4
  13. package/dist/internal.d.ts +2 -0
  14. package/dist/internal.d.ts.map +1 -1
  15. package/dist/internal.js +313 -202
  16. package/dist/internal.js.map +4 -4
  17. package/dist/library.d.ts +5 -1
  18. package/dist/library.d.ts.map +1 -1
  19. package/dist/library.js +290 -162
  20. package/dist/library.js.map +4 -4
  21. package/dist/primitives/conversation-instance.d.ts +42 -0
  22. package/dist/primitives/conversation-instance.d.ts.map +1 -0
  23. package/dist/primitives/conversation.d.ts +30 -64
  24. package/dist/primitives/conversation.d.ts.map +1 -1
  25. package/dist/primitives/definition.d.ts +1 -1
  26. package/dist/primitives/definition.d.ts.map +1 -1
  27. package/dist/primitives/index.d.ts +3 -0
  28. package/dist/primitives/index.d.ts.map +1 -1
  29. package/dist/primitives/knowledge.d.ts.map +1 -1
  30. package/dist/primitives/workflow-instance.d.ts +0 -2
  31. package/dist/primitives/workflow-instance.d.ts.map +1 -1
  32. package/dist/primitives/workflow.d.ts +1 -2
  33. package/dist/primitives/workflow.d.ts.map +1 -1
  34. package/dist/runtime/adk.d.ts +1 -1
  35. package/dist/runtime/adk.d.ts.map +1 -1
  36. package/dist/runtime/autonomous.d.ts.map +1 -1
  37. package/dist/runtime/handlers/conversation-matching.d.ts +17 -0
  38. package/dist/runtime/handlers/conversation-matching.d.ts.map +1 -0
  39. package/dist/runtime/handlers/conversation.d.ts.map +1 -1
  40. package/dist/runtime/handlers/event.d.ts.map +1 -1
  41. package/dist/runtime/tracked-state.d.ts +16 -5
  42. package/dist/runtime/tracked-state.d.ts.map +1 -1
  43. package/dist/runtime.js +325 -205
  44. package/dist/runtime.js.map +4 -4
  45. package/dist/telemetry/structured-logging.d.ts.map +1 -1
  46. package/dist/workers/dev_worker.d.ts.map +1 -1
  47. package/dist/workers/worker_pool.d.ts.map +1 -1
  48. package/package.json +1 -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.2.3", adk: "not-installed", sdk: "4.16.0", llmz: "0.0.26", zai: "2.1.16", cognitive: "0.1.47" };
51
+ define_PACKAGE_VERSIONS_default = { runtime: "1.2.5", adk: "not-installed", sdk: "4.16.0", llmz: "0.0.26", zai: "2.1.16", cognitive: "0.1.47" };
52
52
  }
53
53
  });
54
54
 
@@ -27463,6 +27463,47 @@ var require_indexv2 = __commonJS({
27463
27463
  }
27464
27464
  });
27465
27465
 
27466
+ // src/utilities/trigger-tags.ts
27467
+ var trigger_tags_exports = {};
27468
+ __export(trigger_tags_exports, {
27469
+ getTriggerSubscriptionTags: () => getTriggerSubscriptionTags,
27470
+ getTriggerTagName: () => getTriggerTagName,
27471
+ getTriggerTagValue: () => getTriggerTagValue,
27472
+ isConversationSubscribedToTrigger: () => isConversationSubscribedToTrigger
27473
+ });
27474
+ import crypto2 from "crypto";
27475
+ var hashString, getTriggerTagName, getTriggerTagValue, getTriggerSubscriptionTags, isConversationSubscribedToTrigger;
27476
+ var init_trigger_tags = __esm({
27477
+ "src/utilities/trigger-tags.ts"() {
27478
+ "use strict";
27479
+ init_define_BUILD();
27480
+ init_define_PACKAGE_VERSIONS();
27481
+ hashString = (str) => {
27482
+ return crypto2.createHash("md5").update(str).digest("hex").substring(0, 5).toUpperCase();
27483
+ };
27484
+ getTriggerTagName = (triggerName) => {
27485
+ return `trigger${hashString(triggerName)}`;
27486
+ };
27487
+ getTriggerTagValue = (key) => {
27488
+ return key ?? "*";
27489
+ };
27490
+ getTriggerSubscriptionTags = (triggerName, key) => {
27491
+ return {
27492
+ name: getTriggerTagName(triggerName),
27493
+ value: getTriggerTagValue(key)
27494
+ };
27495
+ };
27496
+ isConversationSubscribedToTrigger = (conversationTags, triggerName, triggerKey) => {
27497
+ const tagName = getTriggerTagName(triggerName);
27498
+ const tagValue = conversationTags[tagName];
27499
+ if (!tagValue) {
27500
+ return false;
27501
+ }
27502
+ return tagValue === "*" || tagValue === triggerKey;
27503
+ };
27504
+ }
27505
+ });
27506
+
27466
27507
  // ../../node_modules/.bun/@isaacs+balanced-match@4.0.1/node_modules/@isaacs/balanced-match/dist/esm/index.js
27467
27508
  var balanced, maybeMatch, range;
27468
27509
  var init_esm3 = __esm({
@@ -35610,6 +35651,7 @@ var CONFIGURATION_TYPE_HEADER = "x-bp-configuration-type";
35610
35651
  var CONFIGURATION_PAYLOAD_HEADER = "x-bp-configuration";
35611
35652
  var OPERATION_TYPE_HEADER = "x-bp-operation";
35612
35653
  var OPERATION_SUBTYPE_HEADER = "x-bp-type";
35654
+ var LOG_DELIMITER = "<|MESSAGE_END|>\n";
35613
35655
 
35614
35656
  // src/runtime/context/http.ts
35615
35657
  var decodeBase64Obj = (str) => {
@@ -39715,6 +39757,8 @@ If the question is not related to the knowledge bases, do NOT use this tool.`.tr
39715
39757
  const { passages } = await client.searchFiles({
39716
39758
  query,
39717
39759
  withContext: true,
39760
+ includeBreadcrumb: true,
39761
+ contextDepth: 4,
39718
39762
  tags: {
39719
39763
  [WellKnownTags.knowledge.KNOWLEDGE]: "true",
39720
39764
  [WellKnownTags.knowledge.KNOWLEDGE_BASE_NAME]: kbNames
@@ -39758,8 +39802,9 @@ If the question is not related to the knowledge bases, do NOT use this tool.`.tr
39758
39802
  citationMetadata.sourceId = tags[WellKnownTags.knowledge.KNOWLEDGE_SOURCE_ID];
39759
39803
  }
39760
39804
  const { tag } = citations.registerSource(citationMetadata);
39761
- message.push(`<${tag} file="${p.file.key}">`);
39762
- message.push(`**${citationMetadata.title || p.file.key}**`);
39805
+ message.push(
39806
+ `<${tag} file="${p.file.key}" title="${citationMetadata.title || p.file.key}">`
39807
+ );
39763
39808
  message.push(p.content);
39764
39809
  message.push(`</${tag}>`);
39765
39810
  }
@@ -39885,6 +39930,7 @@ Always prefer information from the knowledge bases over general knowledge when a
39885
39930
  message: "ThinkSignal"
39886
39931
  });
39887
39932
  err[HandledErrorProp] = true;
39933
+ throw err;
39888
39934
  } else {
39889
39935
  s.setAttributes({
39890
39936
  "autonomous.tool.status": "error",
@@ -40357,6 +40403,129 @@ init_define_PACKAGE_VERSIONS();
40357
40403
  init_define_BUILD();
40358
40404
  init_define_PACKAGE_VERSIONS();
40359
40405
 
40406
+ // src/primitives/conversation-instance.ts
40407
+ init_define_BUILD();
40408
+ init_define_PACKAGE_VERSIONS();
40409
+ var BaseConversationInstance = class {
40410
+ id;
40411
+ channel;
40412
+ integration;
40413
+ tags;
40414
+ conversation;
40415
+ // @internal
40416
+ client;
40417
+ // @internal
40418
+ TrackedState;
40419
+ constructor(conversation, client) {
40420
+ this.id = conversation.id;
40421
+ this.channel = conversation.channel;
40422
+ this.integration = conversation.integration;
40423
+ this.tags = conversation.tags;
40424
+ this.conversation = conversation;
40425
+ this.client = client;
40426
+ const states = context2.get("states", { optional: true });
40427
+ const existingState = states?.find(
40428
+ (s) => s.type === "conversation" && s.id === conversation.id && s.name === BUILT_IN_STATES.conversation
40429
+ );
40430
+ if (!existingState) {
40431
+ throw new Error(
40432
+ `Conversation state not found for conversation ${conversation.id}. Make sure TrackedState.loadAll() is called before creating conversation instances.`
40433
+ );
40434
+ }
40435
+ this.TrackedState = existingState;
40436
+ }
40437
+ /**
40438
+ * Send a message to this conversation
40439
+ */
40440
+ async send(message) {
40441
+ try {
40442
+ const chat = context2.get("chat");
40443
+ await trackPromise(
40444
+ chat.sendMessage({
40445
+ type: message.type,
40446
+ payload: message.payload
40447
+ })
40448
+ );
40449
+ } catch (err) {
40450
+ console.error("Error sending message in conversation:", err);
40451
+ }
40452
+ }
40453
+ /**
40454
+ * Start typing indicator
40455
+ */
40456
+ async startTyping() {
40457
+ const mapping = InterfaceMappings.getIntegrationAction(
40458
+ "typingIndicator",
40459
+ "startTypingIndicator",
40460
+ this.integration
40461
+ );
40462
+ if (mapping) {
40463
+ const message = context2.get("message", { optional: true });
40464
+ await this.client.callAction({
40465
+ type: mapping,
40466
+ input: {
40467
+ conversationId: this.id,
40468
+ messageId: message?.id
40469
+ }
40470
+ }).catch(() => {
40471
+ });
40472
+ }
40473
+ }
40474
+ /**
40475
+ * Stop typing indicator
40476
+ */
40477
+ async stopTyping() {
40478
+ const mapping = InterfaceMappings.getIntegrationAction(
40479
+ "typingIndicator",
40480
+ "stopTypingIndicator",
40481
+ this.integration
40482
+ );
40483
+ if (mapping) {
40484
+ const message = context2.get("message", { optional: true });
40485
+ await this.client.callAction({
40486
+ type: mapping,
40487
+ input: {
40488
+ conversationId: this.id,
40489
+ messageId: message?.id
40490
+ }
40491
+ }).catch(() => {
40492
+ });
40493
+ }
40494
+ }
40495
+ /**
40496
+ * Subscribe to a trigger
40497
+ */
40498
+ async subscribeToTrigger(triggerName, key) {
40499
+ const { getTriggerSubscriptionTags: getTriggerSubscriptionTags2, isConversationSubscribedToTrigger: isConversationSubscribedToTrigger2 } = await Promise.resolve().then(() => (init_trigger_tags(), trigger_tags_exports));
40500
+ if (isConversationSubscribedToTrigger2(this.tags, triggerName, key)) {
40501
+ return;
40502
+ }
40503
+ const { name, value } = getTriggerSubscriptionTags2(triggerName, key);
40504
+ await this.client.updateConversation({
40505
+ id: this.id,
40506
+ tags: {
40507
+ [name]: value
40508
+ }
40509
+ });
40510
+ }
40511
+ /**
40512
+ * Unsubscribe from a trigger
40513
+ */
40514
+ async unsubscribeFromTrigger(triggerName, key) {
40515
+ const { getTriggerSubscriptionTags: getTriggerSubscriptionTags2, isConversationSubscribedToTrigger: isConversationSubscribedToTrigger2 } = await Promise.resolve().then(() => (init_trigger_tags(), trigger_tags_exports));
40516
+ if (!isConversationSubscribedToTrigger2(this.tags, triggerName, key)) {
40517
+ return;
40518
+ }
40519
+ const { name } = getTriggerSubscriptionTags2(triggerName, key);
40520
+ await this.client.updateConversation({
40521
+ id: this.id,
40522
+ tags: {
40523
+ [name]: ""
40524
+ }
40525
+ });
40526
+ }
40527
+ };
40528
+
40360
40529
  // src/primitives/definition.ts
40361
40530
  init_define_BUILD();
40362
40531
  init_define_PACKAGE_VERSIONS();
@@ -40365,7 +40534,12 @@ var Definitions;
40365
40534
  ((Definitions2) => {
40366
40535
  const conversationDefinitionSchema = z3.object({
40367
40536
  type: z3.literal("conversation"),
40368
- channel: z3.string().min(1, "Channel must be a non-empty string").max(255, "Channel must be less than 255 characters").regex(/^[a-zA-Z0-9._-]+$/, "Channel must be a valid identifier")
40537
+ channel: z3.union([
40538
+ z3.string().min(1, "Channel must be a non-empty string").max(255, "Channel must be less than 255 characters").regex(/^(\*|[a-zA-Z0-9._-]+)$/, "Channel must be a valid identifier or glob '*'"),
40539
+ z3.array(
40540
+ z3.string().min(1, "Channel must be a non-empty string").max(255, "Channel must be less than 255 characters").regex(/^[a-zA-Z0-9._-]+$/, "Channel must be a valid identifier")
40541
+ )
40542
+ ])
40369
40543
  });
40370
40544
  const workflowDefinitionSchema = z3.object({
40371
40545
  type: z3.literal("workflow"),
@@ -42662,34 +42836,6 @@ init_define_PACKAGE_VERSIONS();
42662
42836
  import { z as z8 } from "@botpress/sdk";
42663
42837
  import { setTimeout as setTimeout2 } from "node:timers/promises";
42664
42838
 
42665
- // src/utilities/trigger-tags.ts
42666
- init_define_BUILD();
42667
- init_define_PACKAGE_VERSIONS();
42668
- import crypto2 from "crypto";
42669
- var hashString = (str) => {
42670
- return crypto2.createHash("md5").update(str).digest("hex").substring(0, 5).toUpperCase();
42671
- };
42672
- var getTriggerTagName = (triggerName) => {
42673
- return `trigger${hashString(triggerName)}`;
42674
- };
42675
- var getTriggerTagValue = (key) => {
42676
- return key ?? "*";
42677
- };
42678
- var getTriggerSubscriptionTags = (triggerName, key) => {
42679
- return {
42680
- name: getTriggerTagName(triggerName),
42681
- value: getTriggerTagValue(key)
42682
- };
42683
- };
42684
- var isConversationSubscribedToTrigger = (conversationTags, triggerName, triggerKey) => {
42685
- const tagName = getTriggerTagName(triggerName);
42686
- const tagValue = conversationTags[tagName];
42687
- if (!tagValue) {
42688
- return false;
42689
- }
42690
- return tagValue === "*" || tagValue === triggerKey;
42691
- };
42692
-
42693
42839
  // src/utilities/events.ts
42694
42840
  init_define_BUILD();
42695
42841
  init_define_PACKAGE_VERSIONS();
@@ -42714,18 +42860,14 @@ var Typings2;
42714
42860
  Typings8.Primitive = "conversation";
42715
42861
  })(Typings2 || (Typings2 = {}));
42716
42862
  var BaseConversation = class {
42717
- integration;
42718
42863
  channel;
42719
42864
  /** @internal */
42720
42865
  schema;
42721
42866
  #handler;
42722
- #state;
42723
42867
  #startFromTrigger;
42724
- #interruptionSignal;
42725
42868
  constructor(props) {
42726
42869
  this.channel = props.channel;
42727
42870
  this.schema = props.state ?? z8.object({}).passthrough();
42728
- this.integration = props.channel.split(".")[0];
42729
42871
  this.#handler = props.handler;
42730
42872
  if (props.startFromTrigger) {
42731
42873
  this.#startFromTrigger = props.startFromTrigger;
@@ -42737,31 +42879,34 @@ var BaseConversation = class {
42737
42879
  }
42738
42880
  /** @internal */
42739
42881
  getDefinition() {
42740
- return {
42741
- type: "conversation",
42742
- channel: this.channel
42743
- };
42744
- }
42745
- set state(state) {
42746
- this.#state = state;
42747
- }
42748
- get state() {
42749
- return this.#state;
42750
- }
42751
- get id() {
42752
- return context2.get("conversation").id;
42753
- }
42754
- get tags() {
42755
- return context2.get("conversation").tags;
42882
+ if (this.channel === "*") {
42883
+ return {
42884
+ type: "conversation",
42885
+ channel: "*"
42886
+ };
42887
+ } else if (Array.isArray(this.channel)) {
42888
+ return {
42889
+ type: "conversation",
42890
+ channel: this.channel
42891
+ };
42892
+ } else {
42893
+ return {
42894
+ type: "conversation",
42895
+ channel: this.channel
42896
+ };
42897
+ }
42756
42898
  }
42757
- // TODO: separate the handler from the conversation definition
42758
- // TODO: each execution should have its own instance to avoid state conflicts etc
42899
+ /** @internal */
42759
42900
  async [ConversationHandler]() {
42760
42901
  const message = context2.get("message", { optional: true });
42761
42902
  const event = context2.get("event", { optional: true });
42762
42903
  const chat = context2.get("chat");
42763
42904
  const client = context2.get("client");
42764
- const conversationId = this.id;
42905
+ const botpressConversation = context2.get("conversation");
42906
+ const conversationInstance = new BaseConversationInstance(
42907
+ botpressConversation,
42908
+ client
42909
+ );
42765
42910
  let type;
42766
42911
  let requestObject = void 0;
42767
42912
  if (message) {
@@ -42786,11 +42931,10 @@ var BaseConversation = class {
42786
42931
  type = "event";
42787
42932
  }
42788
42933
  const controller = new AbortController();
42789
- this.#interruptionSignal = controller.signal;
42790
42934
  void span(
42791
42935
  "interruption.check",
42792
42936
  {
42793
- conversationId
42937
+ conversationId: conversationInstance.id
42794
42938
  },
42795
42939
  async (s) => {
42796
42940
  async function checkNewUserMessage() {
@@ -42798,7 +42942,7 @@ var BaseConversation = class {
42798
42942
  return;
42799
42943
  }
42800
42944
  const { events } = await client.listEvents({
42801
- conversationId,
42945
+ conversationId: conversationInstance.id,
42802
42946
  status: "pending"
42803
42947
  });
42804
42948
  const newEvents = events.filter(
@@ -42854,98 +42998,30 @@ var BaseConversation = class {
42854
42998
  const execute = Autonomous.createExecute({
42855
42999
  mode: "chat",
42856
43000
  defaultModel: adk.project.config.defaultModels.autonomous,
42857
- ...this.#interruptionSignal && {
42858
- interruption: this.#interruptionSignal
43001
+ interruption: controller.signal
43002
+ });
43003
+ if (!conversationInstance.TrackedState.value) {
43004
+ conversationInstance.TrackedState.value = {};
43005
+ }
43006
+ const stateProxy = new Proxy(conversationInstance.TrackedState.value, {
43007
+ set(target, prop, value) {
43008
+ const result = Reflect.set(target, prop, value);
43009
+ conversationInstance.TrackedState.markDirty();
43010
+ return result;
42859
43011
  }
42860
43012
  });
42861
- await this.#handler.call(this, {
43013
+ await this.#handler({
42862
43014
  type,
42863
43015
  message,
42864
43016
  event,
42865
43017
  request: requestObject,
43018
+ conversation: conversationInstance,
43019
+ state: stateProxy,
43020
+ client,
42866
43021
  execute
42867
43022
  });
42868
43023
  controller.abort();
42869
43024
  }
42870
- async subscribeToTrigger(triggerName, key) {
42871
- if (isConversationSubscribedToTrigger(this.tags, triggerName, key)) {
42872
- return;
42873
- }
42874
- const conversation = context2.get("conversation");
42875
- const client = context2.get("client");
42876
- const { name, value } = getTriggerSubscriptionTags(triggerName, key);
42877
- await client.updateConversation({
42878
- id: conversation.id,
42879
- tags: {
42880
- [name]: value
42881
- }
42882
- });
42883
- }
42884
- async unsubscribeFromTrigger(triggerName, key) {
42885
- if (!isConversationSubscribedToTrigger(this.tags, triggerName, key)) {
42886
- return;
42887
- }
42888
- const conversation = context2.get("conversation");
42889
- const client = context2.get("client");
42890
- const { name } = getTriggerSubscriptionTags(triggerName, key);
42891
- await client.updateConversation({
42892
- id: conversation.id,
42893
- tags: {
42894
- [name]: ""
42895
- }
42896
- });
42897
- }
42898
- async startTyping() {
42899
- const conversation = context2.get("conversation", { optional: true });
42900
- const message = context2.get("message", { optional: true });
42901
- const mapping = InterfaceMappings.getIntegrationAction(
42902
- "typingIndicator",
42903
- "startTypingIndicator",
42904
- conversation?.integration
42905
- );
42906
- if (conversation && mapping) {
42907
- await context2.get("client").callAction({
42908
- type: mapping,
42909
- input: {
42910
- conversationId: conversation.id,
42911
- messageId: message?.id
42912
- }
42913
- }).catch(() => {
42914
- });
42915
- }
42916
- }
42917
- async stopTyping() {
42918
- const conversation = context2.get("conversation", { optional: true });
42919
- const message = context2.get("message", { optional: true });
42920
- const mapping = InterfaceMappings.getIntegrationAction(
42921
- "typingIndicator",
42922
- "stopTypingIndicator",
42923
- conversation?.integration
42924
- );
42925
- if (conversation && mapping) {
42926
- await context2.get("client").callAction({
42927
- type: mapping,
42928
- input: {
42929
- conversationId: conversation.id,
42930
- messageId: message?.id
42931
- }
42932
- }).catch(() => {
42933
- });
42934
- }
42935
- }
42936
- async send(message) {
42937
- try {
42938
- const chat = context2.get("chat");
42939
- await trackPromise(
42940
- chat.sendMessage({
42941
- type: message.type,
42942
- payload: message.payload
42943
- })
42944
- );
42945
- } catch (err) {
42946
- console.error("Error getting context in conversation.send:", err);
42947
- }
42948
- }
42949
43025
  };
42950
43026
 
42951
43027
  // src/primitives/knowledge.ts
@@ -42962,6 +43038,7 @@ var BaseKnowledge = class {
42962
43038
  constructor(props) {
42963
43039
  this.name = props.name;
42964
43040
  this.sources = props.sources;
43041
+ this.description = props.description;
42965
43042
  }
42966
43043
  /** @internal */
42967
43044
  getDefinition() {
@@ -43335,6 +43412,7 @@ var Primitives;
43335
43412
  ((Primitives2) => {
43336
43413
  Primitives2.Definitions = Definitions;
43337
43414
  Primitives2.BaseConversation = BaseConversation;
43415
+ Primitives2.BaseConversationInstance = BaseConversationInstance;
43338
43416
  Primitives2.Conversation = Typings2;
43339
43417
  Primitives2.BaseKnowledge = BaseKnowledge;
43340
43418
  Primitives2.Knowledge = Typings3;
@@ -43944,22 +44022,16 @@ var BaseWorkflowInstance = class _BaseWorkflowInstance {
43944
44022
  workflow;
43945
44023
  // @internal
43946
44024
  TrackedState;
43947
- set state(state) {
43948
- this.TrackedState.value = state;
43949
- }
43950
- get state() {
43951
- return this.TrackedState.value;
43952
- }
43953
44025
  constructor(workflow, client) {
43954
44026
  const definition = adk.project.workflows.find(
43955
44027
  (w) => w.name === workflow.name
43956
44028
  );
43957
- this.TrackedState = TrackedState.create({
44029
+ this.TrackedState = TrackedState2.create({
43958
44030
  type: "workflow",
43959
44031
  client: client._inner,
43960
44032
  id: workflow.id,
43961
44033
  schema: definition?.stateSchema,
43962
- name: "workflowState"
44034
+ name: BUILT_IN_STATES.workflowState
43963
44035
  });
43964
44036
  this.id = workflow.id;
43965
44037
  this.name = workflow.name;
@@ -44043,7 +44115,7 @@ var BaseWorkflowInstance = class _BaseWorkflowInstance {
44043
44115
  `No ADK Workflow handler found for "${this.name}"`
44044
44116
  );
44045
44117
  }
44046
- await TrackedState.loadAll();
44118
+ await TrackedState2.loadAll();
44047
44119
  const workflowControlContext = {
44048
44120
  workflow: this.workflow,
44049
44121
  aborted: false,
@@ -44090,14 +44162,25 @@ var BaseWorkflowInstance = class _BaseWorkflowInstance {
44090
44162
  "Workflow execution state is not loaded"
44091
44163
  );
44092
44164
  workflowExecutionState.value.executionCount++;
44165
+ if (!this.TrackedState.value) {
44166
+ this.TrackedState.value = {};
44167
+ }
44168
+ const trackedState = this.TrackedState;
44169
+ const stateProxy = new Proxy(this.TrackedState.value, {
44170
+ set(target, prop, value) {
44171
+ const result2 = Reflect.set(target, prop, value);
44172
+ trackedState.markDirty();
44173
+ return result2;
44174
+ }
44175
+ });
44093
44176
  const result = await context2.run(
44094
44177
  {
44095
44178
  ...ctx,
44096
44179
  workflowControlContext
44097
44180
  },
44098
- async () => handler.call(this, {
44181
+ async () => handler({
44099
44182
  input: this.input,
44100
- state: this.state,
44183
+ state: stateProxy,
44101
44184
  step,
44102
44185
  client: this.client,
44103
44186
  execute: this.execute.bind(this)
@@ -44126,7 +44209,7 @@ var BaseWorkflowInstance = class _BaseWorkflowInstance {
44126
44209
  };
44127
44210
  }
44128
44211
  } finally {
44129
- await TrackedState.saveAllDirty();
44212
+ await TrackedState2.saveAllDirty();
44130
44213
  }
44131
44214
  }
44132
44215
  /**
@@ -44158,12 +44241,12 @@ var BaseWorkflowInstance = class _BaseWorkflowInstance {
44158
44241
  }
44159
44242
  };
44160
44243
  function createWorkflowExecutionState(client, workflowId) {
44161
- return TrackedState.create({
44244
+ return TrackedState2.create({
44162
44245
  type: "workflow",
44163
44246
  client,
44164
44247
  id: workflowId,
44165
44248
  schema: workflowExecutionContextSchema,
44166
- name: "workflowExecutionContext"
44249
+ name: BUILT_IN_STATES.workflowSteps
44167
44250
  });
44168
44251
  }
44169
44252
 
@@ -44190,8 +44273,6 @@ var BaseWorkflow = class {
44190
44273
  /** @internal */
44191
44274
  schedule;
44192
44275
  timeout = (0, import_ms.default)("5m");
44193
- // Runtime state
44194
- state;
44195
44276
  constructor(props) {
44196
44277
  this.name = props.name;
44197
44278
  if (props.description !== void 0) {
@@ -44559,13 +44640,18 @@ var EMPTY_STATE = {
44559
44640
  };
44560
44641
  var MAX_SWAP_FILE_SIZE = import_bytes2.default.parse("100MB");
44561
44642
  var BUILT_IN_STATES = {
44562
- user: "userState",
44643
+ /** Generic conversation-specific state (user-defined per conversation) */
44563
44644
  conversation: "state",
44645
+ /** User-specific state (persists across conversations per user) */
44646
+ user: "userState",
44647
+ /** Bot-wide global state (persists across all conversations) */
44564
44648
  bot: "botState",
44649
+ /** Workflow-specific state (persists across workflow executions) */
44565
44650
  workflowState: "workflowState",
44651
+ /** Workflow cached steps executions */
44566
44652
  workflowSteps: "workflowSteps"
44567
44653
  };
44568
- var TrackedState = class _TrackedState {
44654
+ var TrackedState2 = class _TrackedState {
44569
44655
  type;
44570
44656
  id;
44571
44657
  name;
@@ -44635,6 +44721,7 @@ var TrackedState = class _TrackedState {
44635
44721
  const client = context2.get("client")._inner;
44636
44722
  const botId = context2.get("botId", { optional: true });
44637
44723
  const user2 = context2.get("user", { optional: true });
44724
+ const conversation = context2.get("conversation", { optional: true });
44638
44725
  if (botId) {
44639
44726
  _TrackedState.create({
44640
44727
  client,
@@ -44653,6 +44740,23 @@ var TrackedState = class _TrackedState {
44653
44740
  schema: adk.project.config.user?.state || z20.object({})
44654
44741
  });
44655
44742
  }
44743
+ if (conversation) {
44744
+ const definition = adk.project.conversations.find((c) => {
44745
+ const def = c.getDefinition();
44746
+ if (typeof def.channel === "string") {
44747
+ return def.channel === conversation.channel || def.channel === "*";
44748
+ } else {
44749
+ return def.channel.includes(conversation.channel);
44750
+ }
44751
+ });
44752
+ _TrackedState.create({
44753
+ client,
44754
+ name: BUILT_IN_STATES.conversation,
44755
+ type: "conversation",
44756
+ id: conversation.id,
44757
+ schema: definition?.schema || z20.object({})
44758
+ });
44759
+ }
44656
44760
  const states = context2.get("states", { optional: true });
44657
44761
  const promises = Promise.allSettled(
44658
44762
  states?.map((state) => state.load()) ?? []
@@ -44699,16 +44803,23 @@ var TrackedState = class _TrackedState {
44699
44803
  } else {
44700
44804
  this.value = value;
44701
44805
  }
44702
- if ((this.value == null || this.value === void 0) && this.state && "parse" in this.state) {
44703
- try {
44704
- this.value = this.state.parse({});
44705
- this._isDirty = true;
44706
- } catch (error) {
44806
+ if (this.value == null || this.value === void 0) {
44807
+ if (this.state && "parse" in this.state) {
44707
44808
  try {
44708
- this.value = this.state.parse(void 0);
44809
+ this.value = this.state.parse({});
44709
44810
  this._isDirty = true;
44710
- } catch {
44811
+ } catch (error) {
44812
+ try {
44813
+ this.value = this.state.parse(void 0);
44814
+ this._isDirty = true;
44815
+ } catch {
44816
+ this.value = {};
44817
+ this._isDirty = true;
44818
+ }
44711
44819
  }
44820
+ } else {
44821
+ this.value = {};
44822
+ this._isDirty = true;
44712
44823
  }
44713
44824
  }
44714
44825
  try {
@@ -45110,12 +45221,12 @@ var patchHandlers = (bot2) => {
45110
45221
  reject(error);
45111
45222
  } finally {
45112
45223
  clearTimeout(timeout);
45113
- await TrackedState.saveAllDirty();
45224
+ await TrackedState2.saveAllDirty();
45114
45225
  }
45115
45226
  });
45116
45227
  } finally {
45117
- await TrackedState.saveAllDirty();
45118
- TrackedState.unloadAll();
45228
+ await TrackedState2.saveAllDirty();
45229
+ TrackedState2.unloadAll();
45119
45230
  await shutdownPromiseTracker();
45120
45231
  }
45121
45232
  }
@@ -46058,6 +46169,31 @@ __export(conversation_exports, {
46058
46169
  });
46059
46170
  init_define_BUILD();
46060
46171
  init_define_PACKAGE_VERSIONS();
46172
+
46173
+ // src/runtime/handlers/conversation-matching.ts
46174
+ init_define_BUILD();
46175
+ init_define_PACKAGE_VERSIONS();
46176
+ function matchesChannel(handlerChannel, incomingChannel) {
46177
+ if (handlerChannel === "*") {
46178
+ return true;
46179
+ } else if (Array.isArray(handlerChannel)) {
46180
+ return handlerChannel.includes(incomingChannel);
46181
+ } else {
46182
+ return handlerChannel === incomingChannel;
46183
+ }
46184
+ }
46185
+ function findMatchingHandler(handlers2, incomingChannel) {
46186
+ const matchingHandlers = handlers2.filter(
46187
+ (h) => matchesChannel(h.channel, incomingChannel)
46188
+ );
46189
+ return matchingHandlers.sort((a, b) => {
46190
+ const aScore = a.channel === "*" ? 0 : Array.isArray(a.channel) ? 1 : 2;
46191
+ const bScore = b.channel === "*" ? 0 : Array.isArray(b.channel) ? 1 : 2;
46192
+ return bScore - aScore;
46193
+ })[0];
46194
+ }
46195
+
46196
+ // src/runtime/handlers/conversation.ts
46061
46197
  var setup = (bot2) => {
46062
46198
  bot2.on.message(
46063
46199
  "*",
@@ -46079,38 +46215,25 @@ var setup = (bot2) => {
46079
46215
  },
46080
46216
  async () => {
46081
46217
  const handlerName = conversation.integration + "." + conversation.channel;
46082
- const handler = adk.project.conversations.find(
46083
- (x) => x.channel === handlerName
46084
- );
46218
+ const handler = findMatchingHandler(adk.project.conversations, handlerName);
46085
46219
  if (!handler) {
46086
46220
  logger.debug(
46087
46221
  `Skipping message, no ADK Conversation defined for "${handlerName}"`
46088
46222
  );
46089
46223
  return;
46090
46224
  }
46091
- const startTyping = trackPromise(handler.startTyping());
46092
46225
  const chat = new BotpressChat(context2.getAll());
46093
46226
  context2.set("chat", chat);
46094
- const state = TrackedState.create({
46095
- type: "conversation",
46096
- client: client._inner,
46097
- id: conversation.id,
46098
- schema: handler.state,
46099
- name: "state"
46100
- });
46101
46227
  const [transcript, _statesLoaded] = await Promise.all([
46102
46228
  chat.fetchTranscript(),
46103
- TrackedState.loadAll()
46229
+ TrackedState2.loadAll()
46104
46230
  ]);
46105
46231
  if (transcript.find((x) => x.id === message.id)) {
46106
46232
  return;
46107
46233
  }
46108
46234
  await chat.addMessage(message);
46109
- handler.state = state.value;
46110
46235
  await handler[ConversationHandler]();
46111
- state.value = handler.state;
46112
- trackPromise(TrackedState.saveAllDirty());
46113
- trackPromise(startTyping.then(() => handler.stopTyping()));
46236
+ await TrackedState2.saveAllDirty();
46114
46237
  await chat.saveTranscript();
46115
46238
  }
46116
46239
  );
@@ -46229,7 +46352,7 @@ var setup3 = (bot2) => {
46229
46352
  });
46230
46353
  try {
46231
46354
  const interval = setInterval(async () => {
46232
- await TrackedState.saveAllDirty();
46355
+ await TrackedState2.saveAllDirty();
46233
46356
  }, 2e4);
46234
46357
  const result = await new Promise((resolve, reject) => {
46235
46358
  const remainingTime = context2.get("runtime").getRemainingExecutionTimeInMs();
@@ -46252,7 +46375,7 @@ var setup3 = (bot2) => {
46252
46375
  });
46253
46376
  if (result.status === "continue") {
46254
46377
  s.setAttribute("workflow.status.final", "continue");
46255
- await TrackedState.saveAllDirty();
46378
+ await TrackedState2.saveAllDirty();
46256
46379
  } else if (result.status === "done") {
46257
46380
  s.setAttribute("workflow.status.final", "completed");
46258
46381
  await updateWorkflow({
@@ -46366,9 +46489,7 @@ var setup4 = (bot2) => {
46366
46489
  return;
46367
46490
  }
46368
46491
  const handlerName = conversation.integration + "." + conversation.channel;
46369
- const handler = adk.project.conversations.find(
46370
- (c) => c.channel === handlerName
46371
- );
46492
+ const handler = findMatchingHandler(adk.project.conversations, handlerName);
46372
46493
  if (!handler) {
46373
46494
  logger.debug(
46374
46495
  `Skipping message, no ADK Conversation defined for "${handlerName}"`
@@ -46388,28 +46509,17 @@ var setup4 = (bot2) => {
46388
46509
  workflowId: payload.workflowId
46389
46510
  },
46390
46511
  async () => {
46391
- const startTyping = trackPromise(handler.startTyping());
46392
46512
  const chat = new BotpressChat(context2.getAll());
46393
46513
  context2.set("chat", chat);
46394
- const state = TrackedState.create({
46395
- type: "conversation",
46396
- client: client._inner,
46397
- id: conversation.id,
46398
- schema: handler.state,
46399
- name: "state"
46400
- });
46401
46514
  const transcript = await chat.fetchTranscript();
46402
46515
  if (transcript.find((x) => x.id === event.id)) {
46403
46516
  logger.debug(`Message ${event.id} already processed`);
46404
46517
  return;
46405
46518
  }
46406
46519
  await chat.addEvent(event);
46407
- await TrackedState.loadAll();
46408
- handler.state = state.value;
46520
+ await TrackedState2.loadAll();
46409
46521
  await handler[ConversationHandler]();
46410
- state.value = handler.state;
46411
- trackPromise(TrackedState.saveAllDirty());
46412
- trackPromise(startTyping.then(() => handler.stopTyping()));
46522
+ await TrackedState2.saveAllDirty();
46413
46523
  await chat.saveTranscript();
46414
46524
  }
46415
46525
  );
@@ -47404,7 +47514,17 @@ function serializeArgs(...args) {
47404
47514
  });
47405
47515
  }
47406
47516
  function writeStructuredLog(type, ...args) {
47517
+ const output2 = process.stdout;
47407
47518
  const { spanId, traceId } = getTraceContext();
47519
+ let maybeArgObj = null;
47520
+ try {
47521
+ maybeArgObj = typeof args[0] === "string" ? JSON.parse(args[0]) : args[0];
47522
+ } catch {
47523
+ }
47524
+ if (maybeArgObj && typeof maybeArgObj === "object" && maybeArgObj.type === "worker_stats") {
47525
+ output2.write((0, import_fast_safe_stringify3.default)(maybeArgObj) + LOG_DELIMITER);
47526
+ return;
47527
+ }
47408
47528
  const logEntry = {
47409
47529
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
47410
47530
  type,
@@ -47416,8 +47536,7 @@ function writeStructuredLog(type, ...args) {
47416
47536
  if (traceId) {
47417
47537
  logEntry.traceId = traceId;
47418
47538
  }
47419
- const output2 = process.stdout;
47420
- output2.write(JSON.stringify(logEntry) + "\n");
47539
+ output2.write((0, import_fast_safe_stringify3.default)(logEntry) + LOG_DELIMITER);
47421
47540
  }
47422
47541
  function installStructuredLogging() {
47423
47542
  console.log = (...args) => {
@@ -47438,6 +47557,7 @@ function installStructuredLogging() {
47438
47557
  }
47439
47558
 
47440
47559
  // src/runtime.ts
47560
+ init_trigger_tags();
47441
47561
  import { z as z24 } from "@botpress/sdk";
47442
47562
  if (Environment.isDevelopment() || Environment.isProduction()) {
47443
47563
  installStructuredLogging();
@@ -47450,7 +47570,7 @@ export {
47450
47570
  Message,
47451
47571
  PromiseTracker,
47452
47572
  SubworkflowFinished,
47453
- TrackedState,
47573
+ TrackedState2 as TrackedState,
47454
47574
  TrackedStateSchema,
47455
47575
  TranscriptSchema,
47456
47576
  WorkflowCallbackEvent,