@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/library.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
 
@@ -8433,6 +8433,7 @@ var init_context_manager = __esm({
8433
8433
  import { randomBytes } from "node:crypto";
8434
8434
  import http from "node:http";
8435
8435
  import https from "node:https";
8436
+ import { gunzipSync, inflateSync, brotliDecompressSync } from "node:zlib";
8436
8437
  import { Dispatcher, getGlobalDispatcher, setGlobalDispatcher } from "undici";
8437
8438
  function isBotpressUrl(fullUrl) {
8438
8439
  try {
@@ -8464,6 +8465,31 @@ function extractIds(fullUrl, body) {
8464
8465
  }
8465
8466
  return ids;
8466
8467
  }
8468
+ function decompressBody(buffer, contentEncoding) {
8469
+ if (!contentEncoding) {
8470
+ return buffer.toString("utf-8");
8471
+ }
8472
+ const encoding = contentEncoding.toLowerCase().trim();
8473
+ try {
8474
+ switch (encoding) {
8475
+ case "gzip":
8476
+ case "x-gzip":
8477
+ return gunzipSync(buffer).toString("utf-8");
8478
+ case "deflate":
8479
+ return inflateSync(buffer).toString("utf-8");
8480
+ case "br":
8481
+ return brotliDecompressSync(buffer).toString("utf-8");
8482
+ case "identity":
8483
+ case "":
8484
+ return buffer.toString("utf-8");
8485
+ default:
8486
+ return buffer.toString("utf-8");
8487
+ }
8488
+ } catch (error) {
8489
+ console.warn(`Failed to decompress response with encoding "${encoding}":`, error);
8490
+ return buffer.toString("utf-8");
8491
+ }
8492
+ }
8467
8493
  function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8468
8494
  const restores = [];
8469
8495
  const genId = (n) => randomBytes(n).toString("hex");
@@ -8498,6 +8524,9 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8498
8524
  if (options.headers[INSTRUMENTED_HEADER]) {
8499
8525
  return requestFn.apply(this, args);
8500
8526
  }
8527
+ if (isSilentTracing()) {
8528
+ return requestFn.apply(this, args);
8529
+ }
8501
8530
  options.headers[INSTRUMENTED_HEADER] = "true";
8502
8531
  const method = (options.method || "GET").toUpperCase();
8503
8532
  const isBotpress = isBotpressUrl(urlString);
@@ -8513,12 +8542,14 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8513
8542
  if (method === "POST" && urlString.includes("/v1/chat/actions") && bodyData?.type) {
8514
8543
  actionName = bodyData.type;
8515
8544
  }
8545
+ const isWorkflowStatusCheck = method === "GET" && /\/workflows\/[^/?]+$/.test(urlString);
8516
8546
  const spanName = isBotpress ? "botpress.client" : "http.client";
8517
8547
  const spanAttributes = isBotpress ? {
8518
8548
  "botpress.method": method,
8519
8549
  "botpress.url": urlString,
8520
8550
  "botpress.via": "http",
8521
- importance: "medium",
8551
+ importance: isWorkflowStatusCheck ? "low" : "medium",
8552
+ ...isWorkflowStatusCheck && { "debug.type": "workflow-status-check" },
8522
8553
  ...ids,
8523
8554
  ...actionName && { "action.name": actionName }
8524
8555
  } : {
@@ -8563,12 +8594,14 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8563
8594
  req.on("response", (res) => {
8564
8595
  span2.setAttribute(isBotpress ? "botpress.status_code" : "http.status_code", res.statusCode || 0);
8565
8596
  const responseBodyChunks = [];
8597
+ const contentEncoding = res.headers["content-encoding"];
8566
8598
  res.on("data", (chunk) => {
8567
8599
  responseBodyChunks.push(chunk);
8568
8600
  });
8569
8601
  res.on("end", () => {
8570
8602
  if (responseBodyChunks.length > 0) {
8571
- const bodyString = Buffer.concat(responseBodyChunks).toString("utf-8");
8603
+ const bodyBuffer = Buffer.concat(responseBodyChunks);
8604
+ const bodyString = decompressBody(bodyBuffer, contentEncoding);
8572
8605
  span2.setAttribute(isBotpress ? "botpress.response.body" : "http.response.body", bodyString);
8573
8606
  }
8574
8607
  if ((res.statusCode || 0) >= 400) {
@@ -8641,6 +8674,9 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8641
8674
  }
8642
8675
  }
8643
8676
  }
8677
+ if (isSilentTracing()) {
8678
+ return this.d.dispatch(opts, handler);
8679
+ }
8644
8680
  const method = (opts.method || "GET").toUpperCase();
8645
8681
  const origin2 = String(opts.origin ?? "");
8646
8682
  const path4 = String(opts.path ?? "");
@@ -8659,12 +8695,14 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8659
8695
  if (method === "POST" && path4 === "/v1/chat/actions" && bodyData?.type) {
8660
8696
  actionName = bodyData.type;
8661
8697
  }
8698
+ const isWorkflowStatusCheck = method === "GET" && /\/workflows\/[^/?]+$/.test(fullUrl);
8662
8699
  const spanName = isBotpress ? "botpress.client" : "http.client";
8663
8700
  const spanAttributes = isBotpress ? {
8664
8701
  "botpress.method": method,
8665
8702
  "botpress.url": path4,
8666
8703
  "botpress.via": "undici",
8667
- importance: "medium",
8704
+ importance: isWorkflowStatusCheck ? "low" : "medium",
8705
+ ...isWorkflowStatusCheck && { "debug.type": "workflow-status-check" },
8668
8706
  ...ids,
8669
8707
  ...actionName && { "action.name": actionName }
8670
8708
  } : {
@@ -8715,11 +8753,18 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8715
8753
  }
8716
8754
  const nextOpts = { ...opts, headers };
8717
8755
  const responseBodyChunks = [];
8756
+ let contentEncoding;
8718
8757
  const wrap = {
8719
8758
  onConnect: handler.onConnect?.bind(handler),
8720
8759
  onUpgrade: handler.onUpgrade?.bind(handler),
8721
8760
  onHeaders: (statusCode, rawHeaders, resume) => {
8722
8761
  span2.setAttribute(isBotpress ? "botpress.status_code" : "http.status_code", statusCode);
8762
+ for (let i = 0; i < rawHeaders.length; i += 2) {
8763
+ if (String(rawHeaders[i]).toLowerCase() === "content-encoding") {
8764
+ contentEncoding = String(rawHeaders[i + 1]);
8765
+ break;
8766
+ }
8767
+ }
8723
8768
  if (statusCode >= 500) {
8724
8769
  span2.setStatus({
8725
8770
  code: SpanStatusCode.ERROR,
@@ -8750,7 +8795,8 @@ function installHttpClientInstrumentation({ injectTraceHeader = true } = {}) {
8750
8795
  },
8751
8796
  onComplete: (trailers) => {
8752
8797
  if (responseBodyChunks.length > 0) {
8753
- const bodyString = Buffer.concat(responseBodyChunks).toString("utf-8");
8798
+ const bodyBuffer = Buffer.concat(responseBodyChunks);
8799
+ const bodyString = decompressBody(bodyBuffer, contentEncoding);
8754
8800
  span2.setAttribute(isBotpress ? "botpress.response.body" : "http.response.body", bodyString);
8755
8801
  }
8756
8802
  span2.end();
@@ -13144,7 +13190,7 @@ var require_lodash = __commonJS({
13144
13190
  return value === true || value === false || isObjectLike2(value) && baseGetTag(value) == boolTag;
13145
13191
  }
13146
13192
  var isBuffer2 = nativeIsBuffer || stubFalse;
13147
- var isDate2 = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
13193
+ var isDate3 = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
13148
13194
  function isElement(value) {
13149
13195
  return isObjectLike2(value) && value.nodeType === 1 && !isPlainObject2(value);
13150
13196
  }
@@ -14279,7 +14325,7 @@ var require_lodash = __commonJS({
14279
14325
  lodash.isArrayLikeObject = isArrayLikeObject;
14280
14326
  lodash.isBoolean = isBoolean2;
14281
14327
  lodash.isBuffer = isBuffer2;
14282
- lodash.isDate = isDate2;
14328
+ lodash.isDate = isDate3;
14283
14329
  lodash.isElement = isElement;
14284
14330
  lodash.isEmpty = isEmpty;
14285
14331
  lodash.isEqual = isEqual;
@@ -15142,7 +15188,11 @@ var init_spans = __esm({
15142
15188
  "workflow.step.attempt": { type: "number", required: true },
15143
15189
  "workflow.step.output": { type: "json" },
15144
15190
  "workflow.step.max_attempts": { type: "number" },
15145
- "workflow.step.error": { type: "string" }
15191
+ "workflow.step.error": { type: "string" },
15192
+ // Map-specific attributes
15193
+ "workflow.map.total": { type: "number", description: "Total number of items to process in map" },
15194
+ "workflow.map.concurrency": { type: "number", description: "Concurrency level for map operation" },
15195
+ "workflow.map.item_index": { type: "number", description: "Index of item in map operation" }
15146
15196
  }
15147
15197
  };
15148
15198
  ActionHandlerSpan = {
@@ -15604,7 +15654,14 @@ var init_span_helpers = __esm({
15604
15654
  });
15605
15655
 
15606
15656
  // src/telemetry/tracing.ts
15607
- var import_sdk_trace_base, import_sdk_trace_node, import_resources, import_core2, spanProcessors, environmentInfo, resource, provider, contextManager, tracer;
15657
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
15658
+ function withSilentTracing(fn) {
15659
+ return silentTracingFlag.run(true, fn);
15660
+ }
15661
+ function isSilentTracing() {
15662
+ return silentTracingFlag.getStore() === true;
15663
+ }
15664
+ var import_sdk_trace_base, import_sdk_trace_node, import_resources, import_core2, spanProcessors, environmentInfo, resource, provider, contextManager, tracer, silentTracingFlag;
15608
15665
  var init_tracing = __esm({
15609
15666
  "src/telemetry/tracing.ts"() {
15610
15667
  "use strict";
@@ -15652,6 +15709,7 @@ var init_tracing = __esm({
15652
15709
  });
15653
15710
  }
15654
15711
  tracer = trace.getTracer("adk", "1.0.0");
15712
+ silentTracingFlag = getSingleton("__ADK_GLOBAL_SILENT_TRACING", () => new AsyncLocalStorage3());
15655
15713
  for (const sig of ["SIGINT", "SIGTERM"]) {
15656
15714
  process.on(sig, async () => {
15657
15715
  await provider.forceFlush();
@@ -36050,14 +36108,70 @@ var init_workflow_utils = __esm({
36050
36108
  }
36051
36109
  });
36052
36110
 
36111
+ // src/primitives/date-serialization.ts
36112
+ function isDateMarker(value) {
36113
+ return typeof value === "object" && value !== null && DATE_MARKER in value && typeof value[DATE_MARKER] === "string";
36114
+ }
36115
+ function isDate2(value) {
36116
+ return value instanceof Date;
36117
+ }
36118
+ function serializeDates(data) {
36119
+ if (data === null || data === void 0) {
36120
+ return data;
36121
+ }
36122
+ if (isDate2(data)) {
36123
+ return { [DATE_MARKER]: data.toISOString() };
36124
+ }
36125
+ if (Array.isArray(data)) {
36126
+ return data.map((item) => serializeDates(item));
36127
+ }
36128
+ if (typeof data === "object" && data.constructor === Object) {
36129
+ const result = {};
36130
+ for (const [key, value] of Object.entries(data)) {
36131
+ result[key] = serializeDates(value);
36132
+ }
36133
+ return result;
36134
+ }
36135
+ return data;
36136
+ }
36137
+ function deserializeDates(data) {
36138
+ if (data === null || data === void 0) {
36139
+ return data;
36140
+ }
36141
+ if (isDateMarker(data)) {
36142
+ return new Date(data[DATE_MARKER]);
36143
+ }
36144
+ if (Array.isArray(data)) {
36145
+ return data.map((item) => deserializeDates(item));
36146
+ }
36147
+ if (typeof data === "object" && data.constructor === Object) {
36148
+ const result = {};
36149
+ for (const [key, value] of Object.entries(data)) {
36150
+ result[key] = deserializeDates(value);
36151
+ }
36152
+ return result;
36153
+ }
36154
+ return data;
36155
+ }
36156
+ var DATE_MARKER;
36157
+ var init_date_serialization = __esm({
36158
+ "src/primitives/date-serialization.ts"() {
36159
+ "use strict";
36160
+ init_define_BUILD();
36161
+ init_define_PACKAGE_VERSIONS();
36162
+ DATE_MARKER = "__date__";
36163
+ }
36164
+ });
36165
+
36053
36166
  // src/primitives/workflow-step.ts
36054
36167
  import { ulid } from "ulid";
36055
36168
  import assert from "assert";
36056
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
36169
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
36057
36170
  import { transforms as transforms2 } from "@botpress/sdk";
36058
36171
  async function _step(name, run, { maxAttempts = DEFAULT_MAX_ATTEMPTS } = {}, {
36059
36172
  spanFunc,
36060
- stepType
36173
+ stepType,
36174
+ stepMeta
36061
36175
  } = {}) {
36062
36176
  const workflowControlContext = context.get("workflowControlContext");
36063
36177
  workflowControlContext.signal.throwIfAborted();
@@ -36081,14 +36195,19 @@ async function _step(name, run, { maxAttempts = DEFAULT_MAX_ATTEMPTS } = {}, {
36081
36195
  const steps = stepContext?.steps ?? state.value.steps;
36082
36196
  steps[name] ??= {
36083
36197
  attempts: 0,
36198
+ maxAttempts,
36084
36199
  steps: {},
36085
36200
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
36086
36201
  };
36202
+ if (stepMeta) {
36203
+ Object.assign(steps[name], stepMeta);
36204
+ console.log(`[_step] Applied stepMeta to "${name}":`, JSON.stringify(stepMeta), "\u2192 keys now:", Object.keys(steps[name]));
36205
+ }
36087
36206
  if (steps[name].finishedAt) {
36088
36207
  if (steps[name].error) {
36089
36208
  throw new Error(steps[name].error.message);
36090
36209
  }
36091
- return steps[name].output;
36210
+ return deserializeDates(steps[name].output);
36092
36211
  }
36093
36212
  while (true) {
36094
36213
  let shouldRetry = false;
@@ -36170,7 +36289,7 @@ async function _step(name, run, { maxAttempts = DEFAULT_MAX_ATTEMPTS } = {}, {
36170
36289
  throw createStepSignal();
36171
36290
  }
36172
36291
  steps[name].finishedAt = (/* @__PURE__ */ new Date()).toISOString();
36173
- steps[name].output = result;
36292
+ steps[name].output = serializeDates(result);
36174
36293
  steps[name].steps = {};
36175
36294
  state.value.revision++;
36176
36295
  await workflowControlContext.ack();
@@ -36218,9 +36337,10 @@ var init_workflow_step = __esm({
36218
36337
  init_adk();
36219
36338
  init_singletons();
36220
36339
  init_workflow_utils();
36340
+ init_date_serialization();
36221
36341
  DEFAULT_MAX_ATTEMPTS = 5;
36222
36342
  MIN_STEP_REMAINING_TIME_MS = 1e4;
36223
- storage2 = getSingleton("__ADK_GLOBAL_CTX_WORKFLOW_STEP", () => new AsyncLocalStorage3());
36343
+ storage2 = getSingleton("__ADK_GLOBAL_CTX_WORKFLOW_STEP", () => new AsyncLocalStorage4());
36224
36344
  step = (async (name, run, options = {}) => {
36225
36345
  return _step(name, run, options);
36226
36346
  });
@@ -36359,6 +36479,8 @@ var init_workflow_step = __esm({
36359
36479
  {}
36360
36480
  );
36361
36481
  step.map = async (name, items, run, opts = {}) => {
36482
+ const concurrency = opts.concurrency ?? 1;
36483
+ const maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
36362
36484
  return _step(
36363
36485
  name,
36364
36486
  async () => {
@@ -36370,15 +36492,28 @@ var init_workflow_step = __esm({
36370
36492
  async () => {
36371
36493
  return await run(item, { i });
36372
36494
  },
36373
- opts
36495
+ opts,
36496
+ {
36497
+ stepType: "map-item",
36498
+ spanFunc: (span2) => {
36499
+ span2.setAttribute("workflow.map.item_index", i);
36500
+ span2.setAttribute("workflow.map.total", items.length);
36501
+ }
36502
+ }
36374
36503
  );
36375
36504
  },
36376
- opts.concurrency ?? 1
36505
+ concurrency
36377
36506
  );
36378
36507
  },
36379
36508
  opts,
36380
36509
  {
36381
- stepType: "map"
36510
+ stepType: "map",
36511
+ stepMeta: { mapTotal: items.length, mapConcurrency: concurrency },
36512
+ spanFunc: (span2) => {
36513
+ span2.setAttribute("workflow.map.total", items.length);
36514
+ span2.setAttribute("workflow.map.concurrency", concurrency);
36515
+ span2.setAttribute("workflow.step.max_attempts", maxAttempts);
36516
+ }
36382
36517
  }
36383
36518
  );
36384
36519
  };
@@ -36473,7 +36608,7 @@ function startWorkflowCancellationMonitor(props) {
36473
36608
  return;
36474
36609
  }
36475
36610
  try {
36476
- const { workflow } = await client2.getWorkflow({ id: workflowId });
36611
+ const { workflow } = await withSilentTracing(() => client2.getWorkflow({ id: workflowId }));
36477
36612
  const isTerminated = workflow.status === "cancelled" || workflow.status === "failed" || workflow.status === "timedout";
36478
36613
  if (isTerminated) {
36479
36614
  workflowControlContext.aborted = true;
@@ -36496,6 +36631,7 @@ var init_workflow_cancellation_monitor = __esm({
36496
36631
  "use strict";
36497
36632
  init_define_BUILD();
36498
36633
  init_define_PACKAGE_VERSIONS();
36634
+ init_tracing();
36499
36635
  }
36500
36636
  });
36501
36637
 
@@ -36548,7 +36684,9 @@ var init_workflow_instance = __esm({
36548
36684
  i: z12.number().optional(),
36549
36685
  startedAt: z12.string(),
36550
36686
  finishedAt: z12.string().optional(),
36687
+ maxAttempts: z12.number().optional(),
36551
36688
  steps: z12.record(z12.string(), workflowStepContextSchema).optional(),
36689
+ mapTotal: z12.number().optional(),
36552
36690
  error: z12.object({
36553
36691
  message: z12.string(),
36554
36692
  failedAt: z12.string(),