callman-core 1.31.0 → 1.32.0

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 (78) hide show
  1. package/ai-packs/db-queries.md +1 -1
  2. package/ai-packs/scenario-nodes.md +33 -14
  3. package/dist/ai/prompts/scenario.d.ts.map +1 -1
  4. package/dist/ai/prompts/scenario.js +3 -2
  5. package/dist/ai/prompts/scenario.js.map +1 -1
  6. package/dist/ai/prompts/scenarioNodeReference.d.ts.map +1 -1
  7. package/dist/ai/prompts/scenarioNodeReference.js +56 -15
  8. package/dist/ai/prompts/scenarioNodeReference.js.map +1 -1
  9. package/dist/host/db/db-query-reference.js +1 -1
  10. package/dist/host/db/db-query-reference.js.map +1 -1
  11. package/dist/host/db/mongoAdapter.d.ts +1 -0
  12. package/dist/host/db/mongoAdapter.d.ts.map +1 -1
  13. package/dist/host/db/mongoAdapter.js +21 -0
  14. package/dist/host/db/mongoAdapter.js.map +1 -1
  15. package/dist/host/db/queryExecutor.js +2 -2
  16. package/dist/host/db/queryExecutor.js.map +1 -1
  17. package/dist/host/index.d.ts +1 -1
  18. package/dist/host/index.d.ts.map +1 -1
  19. package/dist/host/index.js +1 -1
  20. package/dist/host/index.js.map +1 -1
  21. package/dist/scenario-runner/adapters/index.d.ts +1 -0
  22. package/dist/scenario-runner/adapters/index.d.ts.map +1 -1
  23. package/dist/scenario-runner/adapters/index.js +1 -0
  24. package/dist/scenario-runner/adapters/index.js.map +1 -1
  25. package/dist/scenario-runner/adapters/kafka-executor.d.ts +5 -0
  26. package/dist/scenario-runner/adapters/kafka-executor.d.ts.map +1 -1
  27. package/dist/scenario-runner/adapters/kafka-executor.js +12 -3
  28. package/dist/scenario-runner/adapters/kafka-executor.js.map +1 -1
  29. package/dist/scenario-runner/adapters/types.d.ts +1 -0
  30. package/dist/scenario-runner/adapters/types.d.ts.map +1 -1
  31. package/dist/scenario-runner/index.d.ts +3 -0
  32. package/dist/scenario-runner/index.d.ts.map +1 -1
  33. package/dist/scenario-runner/index.js +5 -0
  34. package/dist/scenario-runner/index.js.map +1 -1
  35. package/dist/scenario-runner/kafkaEvent.d.ts +3 -0
  36. package/dist/scenario-runner/kafkaEvent.d.ts.map +1 -0
  37. package/dist/scenario-runner/kafkaEvent.js +18 -0
  38. package/dist/scenario-runner/kafkaEvent.js.map +1 -0
  39. package/dist/scenario-runner/nodePolicy.d.ts +8 -1
  40. package/dist/scenario-runner/nodePolicy.d.ts.map +1 -1
  41. package/dist/scenario-runner/nodePolicy.js +50 -0
  42. package/dist/scenario-runner/nodePolicy.js.map +1 -1
  43. package/dist/scenario-runner/runScenario.d.ts.map +1 -1
  44. package/dist/scenario-runner/runScenario.js +39 -22
  45. package/dist/scenario-runner/runScenario.js.map +1 -1
  46. package/dist/scenario-runner/scenarioReference.d.ts +45 -0
  47. package/dist/scenario-runner/scenarioReference.d.ts.map +1 -0
  48. package/dist/scenario-runner/scenarioReference.js +151 -0
  49. package/dist/scenario-runner/scenarioReference.js.map +1 -0
  50. package/dist/scenario-runner/types.d.ts +5 -0
  51. package/dist/scenario-runner/types.d.ts.map +1 -1
  52. package/dist-cjs/ai/prompts/scenario.js +3 -2
  53. package/dist-cjs/ai/prompts/scenario.js.map +1 -1
  54. package/dist-cjs/ai/prompts/scenarioNodeReference.js +56 -15
  55. package/dist-cjs/ai/prompts/scenarioNodeReference.js.map +1 -1
  56. package/dist-cjs/host/db/db-query-reference.js +1 -1
  57. package/dist-cjs/host/db/db-query-reference.js.map +1 -1
  58. package/dist-cjs/host/db/mongoAdapter.js +23 -1
  59. package/dist-cjs/host/db/mongoAdapter.js.map +1 -1
  60. package/dist-cjs/host/db/queryExecutor.js +1 -1
  61. package/dist-cjs/host/db/queryExecutor.js.map +1 -1
  62. package/dist-cjs/host/index.js +3 -2
  63. package/dist-cjs/host/index.js.map +1 -1
  64. package/dist-cjs/scenario-runner/adapters/index.js +9 -3
  65. package/dist-cjs/scenario-runner/adapters/index.js.map +1 -1
  66. package/dist-cjs/scenario-runner/adapters/kafka-executor.js +15 -4
  67. package/dist-cjs/scenario-runner/adapters/kafka-executor.js.map +1 -1
  68. package/dist-cjs/scenario-runner/index.js +21 -1
  69. package/dist-cjs/scenario-runner/index.js.map +1 -1
  70. package/dist-cjs/scenario-runner/kafkaEvent.js +22 -0
  71. package/dist-cjs/scenario-runner/kafkaEvent.js.map +1 -0
  72. package/dist-cjs/scenario-runner/nodePolicy.js +53 -1
  73. package/dist-cjs/scenario-runner/nodePolicy.js.map +1 -1
  74. package/dist-cjs/scenario-runner/runScenario.js +38 -21
  75. package/dist-cjs/scenario-runner/runScenario.js.map +1 -1
  76. package/dist-cjs/scenario-runner/scenarioReference.js +159 -0
  77. package/dist-cjs/scenario-runner/scenarioReference.js.map +1 -0
  78. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.patchScenarioNodeExecutionPolicy = exports.getScenarioNodePolicyBadges = exports.getScenarioNodeMaxAttempts = exports.getScenarioNodeExecutionPolicy = exports.getNewScenarioNodeExecutionPolicyPreset = exports.getLegacyScenarioNodeExecutionPolicy = exports.normalizeScenarioNodeExecutionPolicy = exports.supportsScenarioNodeExecutionPolicy = exports.STRICT_SCENARIO_NODE_EXECUTION_POLICY = void 0;
3
+ exports.patchScenarioNodeExecutionPolicy = exports.getScenarioNodePolicyBadges = exports.getScenarioNodeMaxAttempts = exports.getScenarioNodeExecutionPolicy = exports.getNewScenarioNodeExecutionPolicyPreset = exports.getLegacyScenarioNodeExecutionPolicy = exports.normalizeScenarioNodeExecutionPolicy = exports.supportsScenarioNodeExecutionPolicy = exports.matchScenarioExpectedFailure = exports.supportsScenarioNodeExpectedFailure = exports.SCENARIO_EXPECT_FAILURE_NODE_TYPES = exports.EXPECT_FAILURE_PATTERN_MAX_LENGTH = exports.STRICT_SCENARIO_NODE_EXECUTION_POLICY = void 0;
4
4
  exports.STRICT_SCENARIO_NODE_EXECUTION_POLICY = {
5
5
  onFailure: "stop",
6
6
  retry: {
@@ -64,6 +64,51 @@ const clonePolicy = (policy) => ({
64
64
  delayMs: policy.retry.delayMs,
65
65
  },
66
66
  });
67
+ exports.EXPECT_FAILURE_PATTERN_MAX_LENGTH = 500;
68
+ // Leaf nodes whose own work can fail. Containers (foreach, subscenario,
69
+ // scenario-ref), routing (condition, end), pure data nodes (set-vars,
70
+ // aggregator) and wait have no failure of their own to expect.
71
+ exports.SCENARIO_EXPECT_FAILURE_NODE_TYPES = [
72
+ "request",
73
+ "db",
74
+ "redis",
75
+ "kafka",
76
+ "websocket",
77
+ "script",
78
+ "assertion",
79
+ "poll",
80
+ "ai",
81
+ "notification",
82
+ ];
83
+ const supportsScenarioNodeExpectedFailure = (type) => exports.SCENARIO_EXPECT_FAILURE_NODE_TYPES.includes(type);
84
+ exports.supportsScenarioNodeExpectedFailure = supportsScenarioNodeExpectedFailure;
85
+ const normalizeExpectedFailure = (value) => {
86
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
87
+ return undefined;
88
+ }
89
+ const raw = value.messagePattern;
90
+ const pattern = typeof raw === "string" ? raw.trim().slice(0, exports.EXPECT_FAILURE_PATTERN_MAX_LENGTH) : "";
91
+ return pattern ? { messagePattern: pattern } : {};
92
+ };
93
+ // Whether a failure message satisfies the expectation. An empty expectation
94
+ // accepts any failure; an invalid regex never matches (and says so).
95
+ const matchScenarioExpectedFailure = (expectation, message) => {
96
+ const pattern = expectation.messagePattern?.trim();
97
+ if (!pattern) {
98
+ return { matched: true, mismatchReason: null };
99
+ }
100
+ let re;
101
+ try {
102
+ re = new RegExp(pattern);
103
+ }
104
+ catch {
105
+ return { matched: false, mismatchReason: `invalid expectFailure.messagePattern regex: ${pattern}` };
106
+ }
107
+ return re.test(message)
108
+ ? { matched: true, mismatchReason: null }
109
+ : { matched: false, mismatchReason: `the error did not match /${pattern}/` };
110
+ };
111
+ exports.matchScenarioExpectedFailure = matchScenarioExpectedFailure;
67
112
  const supportsScenarioNodeExecutionPolicy = (nodeOrType) => {
68
113
  const type = typeof nodeOrType === "string" ? nodeOrType : nodeOrType.type;
69
114
  return type !== "condition";
@@ -108,6 +153,9 @@ const normalizeScenarioNodeExecutionPolicy = (value, fallback = exports.STRICT_S
108
153
  const maxDelayMs = retryEnabled && backoffMultiplier && typeof retryMaxDelayRaw === "number" && retryMaxDelayRaw > 0
109
154
  ? Math.max(delayMs, Math.round(retryMaxDelayRaw))
110
155
  : undefined;
156
+ const expectFailure = typeof value === "object" && value !== null && "expectFailure" in value
157
+ ? normalizeExpectedFailure(value.expectFailure)
158
+ : undefined;
111
159
  return {
112
160
  onFailure: normalizedOnFailure,
113
161
  retry: {
@@ -117,6 +165,7 @@ const normalizeScenarioNodeExecutionPolicy = (value, fallback = exports.STRICT_S
117
165
  ...(backoffMultiplier ? { backoffMultiplier } : {}),
118
166
  ...(maxDelayMs ? { maxDelayMs } : {}),
119
167
  },
168
+ ...(expectFailure ? { expectFailure } : {}),
120
169
  };
121
170
  };
122
171
  exports.normalizeScenarioNodeExecutionPolicy = normalizeScenarioNodeExecutionPolicy;
@@ -140,6 +189,9 @@ const getScenarioNodePolicyBadges = (node) => {
140
189
  if (policy.retry.enabled) {
141
190
  badges.push(`Retry ×${(0, exports.getScenarioNodeMaxAttempts)(policy)}`);
142
191
  }
192
+ if (policy.expectFailure && (0, exports.supportsScenarioNodeExpectedFailure)(node.type)) {
193
+ badges.push("Expects failure");
194
+ }
143
195
  return badges;
144
196
  };
145
197
  exports.getScenarioNodePolicyBadges = getScenarioNodePolicyBadges;
@@ -1 +1 @@
1
- {"version":3,"file":"nodePolicy.js","sourceRoot":"","sources":["../../src/scenario-runner/nodePolicy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nodePolicy.js","sourceRoot":"","sources":["../../src/scenario-runner/nodePolicy.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ const graphTraversal_js_1 = require("./graphTraversal.js");
9
9
  const websocket_js_1 = require("./websocket.js");
10
10
  const executionPolicyRunner_js_1 = require("./executionPolicyRunner.js");
11
11
  const boundSnapshot_js_1 = require("./boundSnapshot.js");
12
+ const kafkaEvent_js_1 = require("./kafkaEvent.js");
12
13
  const nodePolicy_js_1 = require("./nodePolicy.js");
13
14
  const templateResolver_js_1 = require("./templateResolver.js");
14
15
  const waitNodeExecutor_js_1 = require("./waitNodeExecutor.js");
@@ -25,6 +26,11 @@ class ScenarioNodeFailureError extends Error {
25
26
  this.name = "ScenarioNodeFailureError";
26
27
  }
27
28
  }
29
+ // An attempt that succeeded although the node's policy expects a failure.
30
+ // Kept apart from ordinary failures so it is never mistaken for the
31
+ // expected one.
32
+ class ScenarioExpectedFailureNotMetError extends ScenarioNodeFailureError {
33
+ }
28
34
  const DEFAULT_MIN_NODE_VISUAL_STATE_MS = 180;
29
35
  const createId = (prefix) => {
30
36
  const randomUuid = globalThis.crypto?.randomUUID?.();
@@ -125,24 +131,6 @@ const createContextSnapshot = (context, mode = "full") => {
125
131
  redisResult: bound(context.redisResult),
126
132
  };
127
133
  };
128
- const buildKafkaEventValue = (message) => {
129
- const fallbackValue = {
130
- value: message.valueJson ?? message.valueText,
131
- text: message.valueText,
132
- key: message.key,
133
- partition: message.partition,
134
- offset: message.offset,
135
- timestamp: message.timestamp,
136
- headers: Object.fromEntries(message.headers.map((header) => [header.key, header.value])),
137
- };
138
- if (isRecord(message.valueJson)) {
139
- return {
140
- ...message.valueJson,
141
- meta: fallbackValue,
142
- };
143
- }
144
- return fallbackValue;
145
- };
146
134
  const buildKafkaFailureMessage = (result, usedMatch) => {
147
135
  if (result.errorMessage?.trim()) {
148
136
  return result.errorMessage;
@@ -867,6 +855,16 @@ const runScenario = async ({ scenario, environment = {}, globals = {}, runtimeAd
867
855
  retry: { enabled: false, maxAttempts: 0, delayMs: 0 },
868
856
  };
869
857
  }
858
+ // Negative test: this node must fail. On a db node a non-empty
859
+ // expectError is the more precise expectation and wins.
860
+ const dbExpectsError = node.type === "db" &&
861
+ Boolean(node.data.config.expectError?.sqlState?.trim() ||
862
+ node.data.config.expectError?.messagePattern?.trim());
863
+ const expectedFailure = executionPolicy.expectFailure &&
864
+ (0, nodePolicy_js_1.supportsScenarioNodeExpectedFailure)(node.type) &&
865
+ !dbExpectsError
866
+ ? executionPolicy.expectFailure
867
+ : undefined;
870
868
  const executionStartedAtMs = Date.now();
871
869
  let inputData = createInputSnapshot(runtimeContext);
872
870
  // The node's OWN resolved input (query + params, topic + payload, the
@@ -1515,7 +1513,7 @@ const runScenario = async ({ scenario, environment = {}, globals = {}, runtimeAd
1515
1513
  if (resolvedMatchMode === "rules" && rules.length > 0) {
1516
1514
  matchedMessage =
1517
1515
  captureResult.messages.find((message) => {
1518
- const kafkaEventValue = buildKafkaEventValue(message);
1516
+ const kafkaEventValue = (0, kafkaEvent_js_1.buildScenarioKafkaEventValue)(message, captureResult.topic);
1519
1517
  const scopedValues = (0, templateResolver_js_1.buildScenarioTemplateValues)({
1520
1518
  environment: runtimeContext.environment,
1521
1519
  globals: runtimeContext.globals,
@@ -1534,7 +1532,7 @@ const runScenario = async ({ scenario, environment = {}, globals = {}, runtimeAd
1534
1532
  throw new ScenarioNodeFailureError(buildKafkaFailureMessage(captureResult, Boolean(rules.length)));
1535
1533
  }
1536
1534
  runtimeContext.kafkaCapture = captureResult;
1537
- runtimeContext.kafkaEvent = buildKafkaEventValue(matchedMessage);
1535
+ runtimeContext.kafkaEvent = (0, kafkaEvent_js_1.buildScenarioKafkaEventValue)(matchedMessage, captureResult.topic);
1538
1536
  outputData = runtimeContext.kafkaEvent;
1539
1537
  }
1540
1538
  }
@@ -2228,15 +2226,34 @@ const runScenario = async ({ scenario, environment = {}, globals = {}, runtimeAd
2228
2226
  runtimeContext.workflowContext[nodeLabel] = workflowOutput;
2229
2227
  }
2230
2228
  await ensureMinimumVisualDuration(attemptStartedAtMs);
2229
+ if (expectedFailure) {
2230
+ throw new ScenarioExpectedFailureNotMetError(`Expected this node to fail${expectedFailure.messagePattern
2231
+ ? ` with an error matching /${expectedFailure.messagePattern}/`
2232
+ : ""}, but it succeeded.`);
2233
+ }
2231
2234
  }
2232
2235
  catch (error) {
2233
2236
  if (error instanceof ScenarioStopError) {
2234
2237
  throw error;
2235
2238
  }
2236
2239
  await ensureMinimumVisualDuration(attemptStartedAtMs);
2237
- throw error instanceof ScenarioNodeFailureError
2240
+ const failure = error instanceof ScenarioNodeFailureError
2238
2241
  ? error
2239
2242
  : new ScenarioNodeFailureError(error instanceof Error ? error.message : "Scenario node failed");
2243
+ if (expectedFailure && !(failure instanceof ScenarioExpectedFailureNotMetError)) {
2244
+ const match = (0, nodePolicy_js_1.matchScenarioExpectedFailure)(expectedFailure, failure.message);
2245
+ if (!match.matched) {
2246
+ throw new ScenarioNodeFailureError(`The node failed, but not as expected (${match.mismatchReason}): ${failure.message}`);
2247
+ }
2248
+ // The failure IS the result: the node succeeds and exposes it.
2249
+ outputData = { expectedFailure: { message: failure.message } };
2250
+ workflowOutput = outputData;
2251
+ if (nodeLabel && !RESERVED_WORKFLOW_ROOT_LABELS.has(nodeLabel)) {
2252
+ runtimeContext.workflowContext[nodeLabel] = workflowOutput;
2253
+ }
2254
+ return;
2255
+ }
2256
+ throw failure;
2240
2257
  }
2241
2258
  };
2242
2259
  try {