@botpress/runtime 1.14.0 → 1.14.1

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.
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.14.0", adk: "1.14.0", sdk: "5.0.2", llmz: "0.0.37", zai: "2.5.6", cognitive: "0.3.3" };
51
+ define_PACKAGE_VERSIONS_default = { runtime: "1.14.1", adk: "1.14.1", sdk: "5.0.2", llmz: "0.0.37", zai: "2.5.6", cognitive: "0.3.3" };
52
52
  }
53
53
  });
54
54
 
@@ -8734,6 +8734,7 @@ var init_context_manager = __esm({
8734
8734
  import { randomBytes } from "node:crypto";
8735
8735
  import http from "node:http";
8736
8736
  import https from "node:https";
8737
+ import { gunzipSync, inflateSync, brotliDecompressSync } from "node:zlib";
8737
8738
  import { Dispatcher, getGlobalDispatcher, setGlobalDispatcher } from "undici";
8738
8739
  function isBotpressUrl(fullUrl) {
8739
8740
  try {
@@ -8765,6 +8766,31 @@ function extractIds(fullUrl, body) {
8765
8766
  }
8766
8767
  return ids;
8767
8768
  }
8769
+ function decompressBody(buffer, contentEncoding) {
8770
+ if (!contentEncoding) {
8771
+ return buffer.toString("utf-8");
8772
+ }
8773
+ const encoding = contentEncoding.toLowerCase().trim();
8774
+ try {
8775
+ switch (encoding) {
8776
+ case "gzip":
8777
+ case "x-gzip":
8778
+ return gunzipSync(buffer).toString("utf-8");
8779
+ case "deflate":
8780
+ return inflateSync(buffer).toString("utf-8");
8781
+ case "br":
8782
+ return brotliDecompressSync(buffer).toString("utf-8");
8783
+ case "identity":
8784
+ case "":
8785
+ return buffer.toString("utf-8");
8786
+ default:
8787
+ return buffer.toString("utf-8");
8788
+ }
8789
+ } catch (error) {
8790
+ console.warn(`Failed to decompress response with encoding "${encoding}":`, error);
8791
+ return buffer.toString("utf-8");
8792
+ }
8793
+ }
8768
8794
  function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8769
8795
  const restores = [];
8770
8796
  const genId = (n) => randomBytes(n).toString("hex");
@@ -8799,6 +8825,9 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8799
8825
  if (options.headers[INSTRUMENTED_HEADER]) {
8800
8826
  return requestFn.apply(this, args);
8801
8827
  }
8828
+ if (isSilentTracing()) {
8829
+ return requestFn.apply(this, args);
8830
+ }
8802
8831
  options.headers[INSTRUMENTED_HEADER] = "true";
8803
8832
  const method = (options.method || "GET").toUpperCase();
8804
8833
  const isBotpress = isBotpressUrl(urlString);
@@ -8814,12 +8843,14 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8814
8843
  if (method === "POST" && urlString.includes("/v1/chat/actions") && bodyData?.type) {
8815
8844
  actionName = bodyData.type;
8816
8845
  }
8846
+ const isWorkflowStatusCheck = method === "GET" && /\/workflows\/[^/?]+$/.test(urlString);
8817
8847
  const spanName = isBotpress ? "botpress.client" : "http.client";
8818
8848
  const spanAttributes = isBotpress ? {
8819
8849
  "botpress.method": method,
8820
8850
  "botpress.url": urlString,
8821
8851
  "botpress.via": "http",
8822
- importance: "medium",
8852
+ importance: isWorkflowStatusCheck ? "low" : "medium",
8853
+ ...isWorkflowStatusCheck && { "debug.type": "workflow-status-check" },
8823
8854
  ...ids,
8824
8855
  ...actionName && { "action.name": actionName }
8825
8856
  } : {
@@ -8864,12 +8895,14 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8864
8895
  req.on("response", (res) => {
8865
8896
  span2.setAttribute(isBotpress ? "botpress.status_code" : "http.status_code", res.statusCode || 0);
8866
8897
  const responseBodyChunks = [];
8898
+ const contentEncoding = res.headers["content-encoding"];
8867
8899
  res.on("data", (chunk) => {
8868
8900
  responseBodyChunks.push(chunk);
8869
8901
  });
8870
8902
  res.on("end", () => {
8871
8903
  if (responseBodyChunks.length > 0) {
8872
- const bodyString = Buffer.concat(responseBodyChunks).toString("utf-8");
8904
+ const bodyBuffer = Buffer.concat(responseBodyChunks);
8905
+ const bodyString = decompressBody(bodyBuffer, contentEncoding);
8873
8906
  span2.setAttribute(isBotpress ? "botpress.response.body" : "http.response.body", bodyString);
8874
8907
  }
8875
8908
  if ((res.statusCode || 0) >= 400) {
@@ -8942,6 +8975,9 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8942
8975
  }
8943
8976
  }
8944
8977
  }
8978
+ if (isSilentTracing()) {
8979
+ return this.d.dispatch(opts, handler);
8980
+ }
8945
8981
  const method = (opts.method || "GET").toUpperCase();
8946
8982
  const origin2 = String(opts.origin ?? "");
8947
8983
  const path5 = String(opts.path ?? "");
@@ -8960,12 +8996,14 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8960
8996
  if (method === "POST" && path5 === "/v1/chat/actions" && bodyData?.type) {
8961
8997
  actionName = bodyData.type;
8962
8998
  }
8999
+ const isWorkflowStatusCheck = method === "GET" && /\/workflows\/[^/?]+$/.test(fullUrl);
8963
9000
  const spanName = isBotpress ? "botpress.client" : "http.client";
8964
9001
  const spanAttributes = isBotpress ? {
8965
9002
  "botpress.method": method,
8966
9003
  "botpress.url": path5,
8967
9004
  "botpress.via": "undici",
8968
- importance: "medium",
9005
+ importance: isWorkflowStatusCheck ? "low" : "medium",
9006
+ ...isWorkflowStatusCheck && { "debug.type": "workflow-status-check" },
8969
9007
  ...ids,
8970
9008
  ...actionName && { "action.name": actionName }
8971
9009
  } : {
@@ -9016,11 +9054,18 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
9016
9054
  }
9017
9055
  const nextOpts = { ...opts, headers };
9018
9056
  const responseBodyChunks = [];
9057
+ let contentEncoding;
9019
9058
  const wrap = {
9020
9059
  onConnect: handler.onConnect?.bind(handler),
9021
9060
  onUpgrade: handler.onUpgrade?.bind(handler),
9022
9061
  onHeaders: (statusCode, rawHeaders, resume) => {
9023
9062
  span2.setAttribute(isBotpress ? "botpress.status_code" : "http.status_code", statusCode);
9063
+ for (let i = 0; i < rawHeaders.length; i += 2) {
9064
+ if (String(rawHeaders[i]).toLowerCase() === "content-encoding") {
9065
+ contentEncoding = String(rawHeaders[i + 1]);
9066
+ break;
9067
+ }
9068
+ }
9024
9069
  if (statusCode >= 500) {
9025
9070
  span2.setStatus({
9026
9071
  code: SpanStatusCode.ERROR,
@@ -9051,7 +9096,8 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
9051
9096
  },
9052
9097
  onComplete: (trailers) => {
9053
9098
  if (responseBodyChunks.length > 0) {
9054
- const bodyString = Buffer.concat(responseBodyChunks).toString("utf-8");
9099
+ const bodyBuffer = Buffer.concat(responseBodyChunks);
9100
+ const bodyString = decompressBody(bodyBuffer, contentEncoding);
9055
9101
  span2.setAttribute(isBotpress ? "botpress.response.body" : "http.response.body", bodyString);
9056
9102
  }
9057
9103
  span2.end();
@@ -13448,7 +13494,7 @@ var require_lodash = __commonJS({
13448
13494
  return value === true || value === false || isObjectLike2(value) && baseGetTag(value) == boolTag;
13449
13495
  }
13450
13496
  var isBuffer2 = nativeIsBuffer || stubFalse;
13451
- var isDate2 = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
13497
+ var isDate3 = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
13452
13498
  function isElement(value) {
13453
13499
  return isObjectLike2(value) && value.nodeType === 1 && !isPlainObject2(value);
13454
13500
  }
@@ -14583,7 +14629,7 @@ var require_lodash = __commonJS({
14583
14629
  lodash.isArrayLikeObject = isArrayLikeObject;
14584
14630
  lodash.isBoolean = isBoolean2;
14585
14631
  lodash.isBuffer = isBuffer2;
14586
- lodash.isDate = isDate2;
14632
+ lodash.isDate = isDate3;
14587
14633
  lodash.isElement = isElement;
14588
14634
  lodash.isEmpty = isEmpty;
14589
14635
  lodash.isEqual = isEqual;
@@ -15446,7 +15492,11 @@ var init_spans = __esm({
15446
15492
  "workflow.step.attempt": { type: "number", required: true },
15447
15493
  "workflow.step.output": { type: "json" },
15448
15494
  "workflow.step.max_attempts": { type: "number" },
15449
- "workflow.step.error": { type: "string" }
15495
+ "workflow.step.error": { type: "string" },
15496
+ // Map-specific attributes
15497
+ "workflow.map.total": { type: "number", description: "Total number of items to process in map" },
15498
+ "workflow.map.concurrency": { type: "number", description: "Concurrency level for map operation" },
15499
+ "workflow.map.item_index": { type: "number", description: "Index of item in map operation" }
15450
15500
  }
15451
15501
  };
15452
15502
  ActionHandlerSpan = {
@@ -15908,7 +15958,14 @@ var init_span_helpers = __esm({
15908
15958
  });
15909
15959
 
15910
15960
  // src/telemetry/tracing.ts
15911
- var import_sdk_trace_base, import_sdk_trace_node, import_resources, import_core2, spanProcessors, environmentInfo, resource, provider, contextManager, tracer;
15961
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
15962
+ function withSilentTracing(fn) {
15963
+ return silentTracingFlag.run(true, fn);
15964
+ }
15965
+ function isSilentTracing() {
15966
+ return silentTracingFlag.getStore() === true;
15967
+ }
15968
+ var import_sdk_trace_base, import_sdk_trace_node, import_resources, import_core2, spanProcessors, environmentInfo, resource, provider, contextManager, tracer, silentTracingFlag;
15912
15969
  var init_tracing = __esm({
15913
15970
  "src/telemetry/tracing.ts"() {
15914
15971
  "use strict";
@@ -15956,6 +16013,7 @@ var init_tracing = __esm({
15956
16013
  });
15957
16014
  }
15958
16015
  tracer = trace.getTracer("adk", "1.0.0");
16016
+ silentTracingFlag = getSingleton("__ADK_GLOBAL_SILENT_TRACING", () => new AsyncLocalStorage3());
15959
16017
  for (const sig of ["SIGINT", "SIGTERM"]) {
15960
16018
  process.on(sig, async () => {
15961
16019
  await provider.forceFlush();
@@ -38651,14 +38709,70 @@ var init_library = __esm({
38651
38709
  }
38652
38710
  });
38653
38711
 
38712
+ // src/primitives/date-serialization.ts
38713
+ function isDateMarker(value) {
38714
+ return typeof value === "object" && value !== null && DATE_MARKER in value && typeof value[DATE_MARKER] === "string";
38715
+ }
38716
+ function isDate2(value) {
38717
+ return value instanceof Date;
38718
+ }
38719
+ function serializeDates(data) {
38720
+ if (data === null || data === void 0) {
38721
+ return data;
38722
+ }
38723
+ if (isDate2(data)) {
38724
+ return { [DATE_MARKER]: data.toISOString() };
38725
+ }
38726
+ if (Array.isArray(data)) {
38727
+ return data.map((item) => serializeDates(item));
38728
+ }
38729
+ if (typeof data === "object" && data.constructor === Object) {
38730
+ const result = {};
38731
+ for (const [key, value] of Object.entries(data)) {
38732
+ result[key] = serializeDates(value);
38733
+ }
38734
+ return result;
38735
+ }
38736
+ return data;
38737
+ }
38738
+ function deserializeDates(data) {
38739
+ if (data === null || data === void 0) {
38740
+ return data;
38741
+ }
38742
+ if (isDateMarker(data)) {
38743
+ return new Date(data[DATE_MARKER]);
38744
+ }
38745
+ if (Array.isArray(data)) {
38746
+ return data.map((item) => deserializeDates(item));
38747
+ }
38748
+ if (typeof data === "object" && data.constructor === Object) {
38749
+ const result = {};
38750
+ for (const [key, value] of Object.entries(data)) {
38751
+ result[key] = deserializeDates(value);
38752
+ }
38753
+ return result;
38754
+ }
38755
+ return data;
38756
+ }
38757
+ var DATE_MARKER;
38758
+ var init_date_serialization = __esm({
38759
+ "src/primitives/date-serialization.ts"() {
38760
+ "use strict";
38761
+ init_define_BUILD();
38762
+ init_define_PACKAGE_VERSIONS();
38763
+ DATE_MARKER = "__date__";
38764
+ }
38765
+ });
38766
+
38654
38767
  // src/primitives/workflow-step.ts
38655
38768
  import { ulid as ulid2 } from "ulid";
38656
38769
  import assert from "assert";
38657
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
38770
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
38658
38771
  import { transforms as transforms2 } from "@botpress/sdk";
38659
38772
  async function _step(name, run, { maxAttempts = DEFAULT_MAX_ATTEMPTS } = {}, {
38660
38773
  spanFunc,
38661
- stepType
38774
+ stepType,
38775
+ stepMeta
38662
38776
  } = {}) {
38663
38777
  const workflowControlContext = context.get("workflowControlContext");
38664
38778
  workflowControlContext.signal.throwIfAborted();
@@ -38682,14 +38796,19 @@ async function _step(name, run, { maxAttempts = DEFAULT_MAX_ATTEMPTS } = {}, {
38682
38796
  const steps = stepContext?.steps ?? state.value.steps;
38683
38797
  steps[name] ??= {
38684
38798
  attempts: 0,
38799
+ maxAttempts,
38685
38800
  steps: {},
38686
38801
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
38687
38802
  };
38803
+ if (stepMeta) {
38804
+ Object.assign(steps[name], stepMeta);
38805
+ console.log(`[_step] Applied stepMeta to "${name}":`, JSON.stringify(stepMeta), "\u2192 keys now:", Object.keys(steps[name]));
38806
+ }
38688
38807
  if (steps[name].finishedAt) {
38689
38808
  if (steps[name].error) {
38690
38809
  throw new Error(steps[name].error.message);
38691
38810
  }
38692
- return steps[name].output;
38811
+ return deserializeDates(steps[name].output);
38693
38812
  }
38694
38813
  while (true) {
38695
38814
  let shouldRetry = false;
@@ -38771,7 +38890,7 @@ async function _step(name, run, { maxAttempts = DEFAULT_MAX_ATTEMPTS } = {}, {
38771
38890
  throw createStepSignal();
38772
38891
  }
38773
38892
  steps[name].finishedAt = (/* @__PURE__ */ new Date()).toISOString();
38774
- steps[name].output = result;
38893
+ steps[name].output = serializeDates(result);
38775
38894
  steps[name].steps = {};
38776
38895
  state.value.revision++;
38777
38896
  await workflowControlContext.ack();
@@ -38819,9 +38938,10 @@ var init_workflow_step = __esm({
38819
38938
  init_adk();
38820
38939
  init_singletons();
38821
38940
  init_workflow_utils();
38941
+ init_date_serialization();
38822
38942
  DEFAULT_MAX_ATTEMPTS = 5;
38823
38943
  MIN_STEP_REMAINING_TIME_MS = 1e4;
38824
- storage2 = getSingleton("__ADK_GLOBAL_CTX_WORKFLOW_STEP", () => new AsyncLocalStorage3());
38944
+ storage2 = getSingleton("__ADK_GLOBAL_CTX_WORKFLOW_STEP", () => new AsyncLocalStorage4());
38825
38945
  step = (async (name, run, options = {}) => {
38826
38946
  return _step(name, run, options);
38827
38947
  });
@@ -38960,6 +39080,8 @@ var init_workflow_step = __esm({
38960
39080
  {}
38961
39081
  );
38962
39082
  step.map = async (name, items, run, opts = {}) => {
39083
+ const concurrency = opts.concurrency ?? 1;
39084
+ const maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
38963
39085
  return _step(
38964
39086
  name,
38965
39087
  async () => {
@@ -38971,15 +39093,28 @@ var init_workflow_step = __esm({
38971
39093
  async () => {
38972
39094
  return await run(item, { i });
38973
39095
  },
38974
- opts
39096
+ opts,
39097
+ {
39098
+ stepType: "map-item",
39099
+ spanFunc: (span2) => {
39100
+ span2.setAttribute("workflow.map.item_index", i);
39101
+ span2.setAttribute("workflow.map.total", items.length);
39102
+ }
39103
+ }
38975
39104
  );
38976
39105
  },
38977
- opts.concurrency ?? 1
39106
+ concurrency
38978
39107
  );
38979
39108
  },
38980
39109
  opts,
38981
39110
  {
38982
- stepType: "map"
39111
+ stepType: "map",
39112
+ stepMeta: { mapTotal: items.length, mapConcurrency: concurrency },
39113
+ spanFunc: (span2) => {
39114
+ span2.setAttribute("workflow.map.total", items.length);
39115
+ span2.setAttribute("workflow.map.concurrency", concurrency);
39116
+ span2.setAttribute("workflow.step.max_attempts", maxAttempts);
39117
+ }
38983
39118
  }
38984
39119
  );
38985
39120
  };
@@ -39074,7 +39209,7 @@ function startWorkflowCancellationMonitor(props) {
39074
39209
  return;
39075
39210
  }
39076
39211
  try {
39077
- const { workflow } = await client2.getWorkflow({ id: workflowId });
39212
+ const { workflow } = await withSilentTracing(() => client2.getWorkflow({ id: workflowId }));
39078
39213
  const isTerminated = workflow.status === "cancelled" || workflow.status === "failed" || workflow.status === "timedout";
39079
39214
  if (isTerminated) {
39080
39215
  workflowControlContext.aborted = true;
@@ -39097,6 +39232,7 @@ var init_workflow_cancellation_monitor = __esm({
39097
39232
  "use strict";
39098
39233
  init_define_BUILD();
39099
39234
  init_define_PACKAGE_VERSIONS();
39235
+ init_tracing();
39100
39236
  }
39101
39237
  });
39102
39238
 
@@ -39149,7 +39285,9 @@ var init_workflow_instance = __esm({
39149
39285
  i: z20.number().optional(),
39150
39286
  startedAt: z20.string(),
39151
39287
  finishedAt: z20.string().optional(),
39288
+ maxAttempts: z20.number().optional(),
39152
39289
  steps: z20.record(z20.string(), workflowStepContextSchema).optional(),
39290
+ mapTotal: z20.number().optional(),
39153
39291
  error: z20.object({
39154
39292
  message: z20.string(),
39155
39293
  failedAt: z20.string(),
@@ -50132,12 +50270,14 @@ export {
50132
50270
  initializeParentWorker,
50133
50271
  isAgentConfig,
50134
50272
  isMainThread,
50273
+ isSilentTracing,
50135
50274
  isStepSignal,
50136
50275
  isWorkerMode,
50137
50276
  runWorker,
50138
50277
  setAdkCommand,
50139
50278
  span,
50140
- tracer
50279
+ tracer,
50280
+ withSilentTracing
50141
50281
  };
50142
50282
  /*! Bundled license information:
50143
50283