@openbox-ai/openbox-mastra-sdk 0.1.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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/dist/client/index.d.ts +4 -0
  4. package/dist/client/index.js +2 -0
  5. package/dist/client/index.js.map +1 -0
  6. package/dist/client/openbox-client.d.ts +42 -0
  7. package/dist/client/openbox-client.js +405 -0
  8. package/dist/client/openbox-client.js.map +1 -0
  9. package/dist/config/index.d.ts +5 -0
  10. package/dist/config/index.js +2 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/config/openbox-config.d.ts +54 -0
  13. package/dist/config/openbox-config.js +162 -0
  14. package/dist/config/openbox-config.js.map +1 -0
  15. package/dist/governance/activity-runtime.d.ts +42 -0
  16. package/dist/governance/activity-runtime.js +712 -0
  17. package/dist/governance/activity-runtime.js.map +1 -0
  18. package/dist/governance/approval-registry.d.ts +17 -0
  19. package/dist/governance/approval-registry.js +32 -0
  20. package/dist/governance/approval-registry.js.map +1 -0
  21. package/dist/governance/context.d.ts +16 -0
  22. package/dist/governance/context.js +13 -0
  23. package/dist/governance/context.js.map +1 -0
  24. package/dist/governance/index.d.ts +2 -0
  25. package/dist/governance/index.js +1 -0
  26. package/dist/governance/index.js.map +1 -0
  27. package/dist/index.d.ts +18 -0
  28. package/dist/index.js +8 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/mastra/index.d.ts +16 -0
  31. package/dist/mastra/index.js +5 -0
  32. package/dist/mastra/index.js.map +1 -0
  33. package/dist/mastra/with-openbox.d.ts +30 -0
  34. package/dist/mastra/with-openbox.js +243 -0
  35. package/dist/mastra/with-openbox.js.map +1 -0
  36. package/dist/mastra/wrap-agent.d.ts +14 -0
  37. package/dist/mastra/wrap-agent.js +1744 -0
  38. package/dist/mastra/wrap-agent.js.map +1 -0
  39. package/dist/mastra/wrap-tool.d.ts +18 -0
  40. package/dist/mastra/wrap-tool.js +49 -0
  41. package/dist/mastra/wrap-tool.js.map +1 -0
  42. package/dist/mastra/wrap-workflow.d.ts +14 -0
  43. package/dist/mastra/wrap-workflow.js +386 -0
  44. package/dist/mastra/wrap-workflow.js.map +1 -0
  45. package/dist/otel/index.d.ts +11 -0
  46. package/dist/otel/index.js +2 -0
  47. package/dist/otel/index.js.map +1 -0
  48. package/dist/otel/setup-openbox-opentelemetry.d.ts +38 -0
  49. package/dist/otel/setup-openbox-opentelemetry.js +2249 -0
  50. package/dist/otel/setup-openbox-opentelemetry.js.map +1 -0
  51. package/dist/span/index.d.ts +5 -0
  52. package/dist/span/index.js +2 -0
  53. package/dist/span/index.js.map +1 -0
  54. package/dist/span/openbox-span-processor.d.ts +90 -0
  55. package/dist/span/openbox-span-processor.js +580 -0
  56. package/dist/span/openbox-span-processor.js.map +1 -0
  57. package/dist/types/errors.d.ts +25 -0
  58. package/dist/types/errors.js +40 -0
  59. package/dist/types/errors.js.map +1 -0
  60. package/dist/types/governance-verdict-response.d.ts +57 -0
  61. package/dist/types/governance-verdict-response.js +84 -0
  62. package/dist/types/governance-verdict-response.js.map +1 -0
  63. package/dist/types/guardrails.d.ts +23 -0
  64. package/dist/types/guardrails.js +27 -0
  65. package/dist/types/guardrails.js.map +1 -0
  66. package/dist/types/index.d.ts +6 -0
  67. package/dist/types/index.js +7 -0
  68. package/dist/types/index.js.map +1 -0
  69. package/dist/types/verdict.d.ts +22 -0
  70. package/dist/types/verdict.js +55 -0
  71. package/dist/types/verdict.js.map +1 -0
  72. package/dist/types/workflow-event-type.d.ts +10 -0
  73. package/dist/types/workflow-event-type.js +13 -0
  74. package/dist/types/workflow-event-type.js.map +1 -0
  75. package/dist/types/workflow-span-buffer.d.ts +31 -0
  76. package/dist/types/workflow-span-buffer.js +42 -0
  77. package/dist/types/workflow-span-buffer.js.map +1 -0
  78. package/docs/README.md +66 -0
  79. package/docs/api-reference.md +348 -0
  80. package/docs/approvals-and-guardrails.md +163 -0
  81. package/docs/architecture.md +186 -0
  82. package/docs/configuration.md +214 -0
  83. package/docs/event-model.md +215 -0
  84. package/docs/installation.md +108 -0
  85. package/docs/integration-patterns.md +214 -0
  86. package/docs/security-and-privacy.md +174 -0
  87. package/docs/telemetry.md +196 -0
  88. package/docs/troubleshooting.md +210 -0
  89. package/package.json +136 -0
@@ -0,0 +1,712 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { trace } from "@opentelemetry/api";
3
+ import {
4
+ ApprovalExpiredError,
5
+ ApprovalPendingError,
6
+ ApprovalRejectedError,
7
+ GovernanceVerdictResponse,
8
+ GovernanceHaltError,
9
+ GuardrailsValidationError,
10
+ Verdict,
11
+ WorkflowEventType,
12
+ WorkflowSpanBuffer
13
+ } from "../types/index.js";
14
+ import {
15
+ getOpenBoxExecutionContext,
16
+ runWithOpenBoxExecutionContext
17
+ } from "./context.js";
18
+ import {
19
+ clearActivityApproval,
20
+ clearPendingApproval,
21
+ isActivityApproved,
22
+ markActivityApproved,
23
+ setPendingApproval
24
+ } from "./approval-registry.js";
25
+ async function executeGovernedActivity({
26
+ dependencies,
27
+ execute,
28
+ input,
29
+ runtimeContext,
30
+ type
31
+ }) {
32
+ const descriptor = resolveActivityDescriptor(type, runtimeContext);
33
+ const startedInputForEvent = appendGoalToActivityInput(
34
+ serializeActivityInputForStartEvent(input),
35
+ descriptor.goal
36
+ );
37
+ let inputForExecution = cloneValue(input);
38
+ ensureSpanBuffer(descriptor, dependencies.spanProcessor);
39
+ dependencies.spanProcessor.clearActivityAbort(
40
+ descriptor.workflowId,
41
+ descriptor.activityId
42
+ );
43
+ dependencies.spanProcessor.clearHaltRequested(
44
+ descriptor.workflowId,
45
+ descriptor.activityId
46
+ );
47
+ dependencies.spanProcessor.setActivityContext(
48
+ descriptor.workflowId,
49
+ descriptor.activityId,
50
+ {
51
+ activity_id: descriptor.activityId,
52
+ activity_input: startedInputForEvent,
53
+ activity_type: descriptor.activityType,
54
+ attempt: descriptor.attempt,
55
+ ...descriptor.goal ? { goal: descriptor.goal } : {},
56
+ run_id: descriptor.runId,
57
+ task_queue: descriptor.taskQueue,
58
+ workflow_id: descriptor.workflowId,
59
+ workflow_type: descriptor.workflowType
60
+ }
61
+ );
62
+ const startVerdict = dependencies.config.sendActivityStartEvent ? await evaluateActivityEvent(dependencies, {
63
+ activity_id: descriptor.activityId,
64
+ activity_input: startedInputForEvent,
65
+ activity_type: descriptor.activityType,
66
+ attempt: descriptor.attempt,
67
+ event_type: WorkflowEventType.ACTIVITY_STARTED,
68
+ ...descriptor.goal ? { goal: descriptor.goal } : {},
69
+ run_id: descriptor.runId,
70
+ task_queue: descriptor.taskQueue,
71
+ workflow_id: descriptor.workflowId,
72
+ workflow_type: descriptor.workflowType
73
+ }) : null;
74
+ applyStopVerdict(startVerdict);
75
+ assertGuardrailsValid(startVerdict, "Guardrails validation failed");
76
+ if (startVerdict?.guardrailsResult?.inputType === "activity_input" && startVerdict.guardrailsResult.redactedInput !== void 0) {
77
+ const normalizedRedactedInput = normalizeRedactedActivityInput(
78
+ inputForExecution,
79
+ startVerdict.guardrailsResult.redactedInput
80
+ );
81
+ inputForExecution = applyRedaction(
82
+ inputForExecution,
83
+ normalizedRedactedInput
84
+ );
85
+ }
86
+ if (dependencies.config.hitlEnabled && Verdict.requiresApproval(startVerdict?.verdict ?? Verdict.ALLOW)) {
87
+ const approvalPayload = {
88
+ openbox: {
89
+ activityId: descriptor.activityId,
90
+ activityType: descriptor.activityType,
91
+ approvalId: startVerdict?.approvalId,
92
+ reason: startVerdict?.reason,
93
+ requestedAt: rfc3339Now(),
94
+ runId: descriptor.runId,
95
+ workflowId: descriptor.workflowId,
96
+ workflowType: descriptor.workflowType
97
+ }
98
+ };
99
+ setPendingApproval({
100
+ activityId: descriptor.activityId,
101
+ activityType: descriptor.activityType,
102
+ approvalId: startVerdict?.approvalId,
103
+ requestedAt: approvalPayload.openbox.requestedAt,
104
+ runId: descriptor.runId,
105
+ workflowId: descriptor.workflowId,
106
+ workflowType: descriptor.workflowType
107
+ });
108
+ const workflowSuspend = runtimeContext.workflow?.suspend;
109
+ if (workflowSuspend) {
110
+ return await workflowSuspend(approvalPayload);
111
+ }
112
+ await waitForApprovalInline(dependencies.client, descriptor, startVerdict?.reason);
113
+ }
114
+ return runWithOpenBoxExecutionContext(
115
+ {
116
+ activityId: descriptor.activityId,
117
+ activityType: descriptor.activityType,
118
+ attempt: descriptor.attempt,
119
+ goal: descriptor.goal,
120
+ runId: descriptor.runId,
121
+ source: "tool",
122
+ taskQueue: descriptor.taskQueue,
123
+ workflowId: descriptor.workflowId,
124
+ workflowType: descriptor.workflowType
125
+ },
126
+ async () => {
127
+ let error;
128
+ let haltReason;
129
+ let output;
130
+ const activityStartMs = Date.now();
131
+ try {
132
+ output = await trace.getTracer("openbox.mastra").startActiveSpan(`activity.${descriptor.activityType}`, async (activeSpan) => {
133
+ activeSpan.setAttribute("openbox.workflow_id", descriptor.workflowId);
134
+ activeSpan.setAttribute("openbox.activity_id", descriptor.activityId);
135
+ activeSpan.setAttribute("openbox.run_id", descriptor.runId);
136
+ dependencies.spanProcessor.registerTrace(
137
+ activeSpan.spanContext().traceId,
138
+ descriptor.workflowId,
139
+ descriptor.activityId,
140
+ descriptor.runId
141
+ );
142
+ try {
143
+ return await execute(inputForExecution);
144
+ } finally {
145
+ activeSpan.end();
146
+ }
147
+ });
148
+ } catch (caughtError) {
149
+ if (caughtError instanceof ApprovalPendingError && dependencies.config.hitlEnabled) {
150
+ const approvalPayload = {
151
+ openbox: {
152
+ activityId: descriptor.activityId,
153
+ activityType: descriptor.activityType,
154
+ approvalId: void 0,
155
+ reason: caughtError.message,
156
+ requestedAt: rfc3339Now(),
157
+ runId: descriptor.runId,
158
+ workflowId: descriptor.workflowId,
159
+ workflowType: descriptor.workflowType
160
+ }
161
+ };
162
+ setPendingApproval({
163
+ activityId: descriptor.activityId,
164
+ activityType: descriptor.activityType,
165
+ approvalId: void 0,
166
+ requestedAt: approvalPayload.openbox.requestedAt,
167
+ runId: descriptor.runId,
168
+ workflowId: descriptor.workflowId,
169
+ workflowType: descriptor.workflowType
170
+ });
171
+ const workflowSuspend = runtimeContext.workflow?.suspend;
172
+ if (workflowSuspend) {
173
+ return await workflowSuspend(approvalPayload);
174
+ }
175
+ await waitForApprovalInline(
176
+ dependencies.client,
177
+ descriptor,
178
+ caughtError.message
179
+ );
180
+ }
181
+ error = serializeError(caughtError);
182
+ throw caughtError;
183
+ } finally {
184
+ try {
185
+ const wasAborted = dependencies.spanProcessor.getActivityAbort(
186
+ descriptor.workflowId,
187
+ descriptor.activityId
188
+ );
189
+ const activityEndMs = Date.now();
190
+ const durationMs = Math.max(0, activityEndMs - activityStartMs);
191
+ const alreadyApproved = isActivityApproved(
192
+ descriptor.runId,
193
+ descriptor.activityId
194
+ );
195
+ if (!wasAborted) {
196
+ const completedInputForEvent = appendGoalToActivityInput(
197
+ serializeActivityInputForCompletedEvent(inputForExecution),
198
+ descriptor.goal
199
+ );
200
+ const completedActivityTypePayload = dependencies.config.hitlEnabled ? {} : { activity_type: descriptor.activityType };
201
+ const completedVerdict = await evaluateActivityEvent(dependencies, {
202
+ activity_id: descriptor.activityId,
203
+ activity_input: completedInputForEvent,
204
+ activity_output: serializeValue(output),
205
+ ...completedActivityTypePayload,
206
+ attempt: descriptor.attempt,
207
+ duration_ms: durationMs,
208
+ end_time: activityEndMs,
209
+ error,
210
+ event_type: WorkflowEventType.ACTIVITY_COMPLETED,
211
+ ...descriptor.goal ? { goal: descriptor.goal } : {},
212
+ run_id: descriptor.runId,
213
+ span_count: 0,
214
+ start_time: activityStartMs,
215
+ status: error ? "failed" : "completed",
216
+ task_queue: descriptor.taskQueue,
217
+ workflow_id: descriptor.workflowId,
218
+ workflow_type: descriptor.workflowType
219
+ });
220
+ applyStopVerdict(completedVerdict);
221
+ assertGuardrailsValid(
222
+ completedVerdict,
223
+ "Guardrails output validation failed"
224
+ );
225
+ if (completedVerdict?.guardrailsResult?.inputType === "activity_output" && completedVerdict.guardrailsResult.redactedInput !== void 0) {
226
+ output = applyRedaction(
227
+ output,
228
+ completedVerdict.guardrailsResult.redactedInput
229
+ );
230
+ }
231
+ if (dependencies.config.hitlEnabled && Verdict.requiresApproval(completedVerdict?.verdict ?? Verdict.ALLOW) && !alreadyApproved && !isActivityApproved(descriptor.runId, descriptor.activityId)) {
232
+ const approvalPayload = {
233
+ openbox: {
234
+ activityId: descriptor.activityId,
235
+ activityType: descriptor.activityType,
236
+ approvalId: completedVerdict?.approvalId,
237
+ reason: completedVerdict?.reason,
238
+ requestedAt: rfc3339Now(),
239
+ runId: descriptor.runId,
240
+ workflowId: descriptor.workflowId,
241
+ workflowType: descriptor.workflowType
242
+ }
243
+ };
244
+ setPendingApproval({
245
+ activityId: descriptor.activityId,
246
+ activityType: descriptor.activityType,
247
+ approvalId: completedVerdict?.approvalId,
248
+ requestedAt: approvalPayload.openbox.requestedAt,
249
+ runId: descriptor.runId,
250
+ workflowId: descriptor.workflowId,
251
+ workflowType: descriptor.workflowType
252
+ });
253
+ const workflowSuspend = runtimeContext.workflow?.suspend;
254
+ if (workflowSuspend) {
255
+ output = await workflowSuspend(approvalPayload);
256
+ } else {
257
+ await waitForApprovalInline(
258
+ dependencies.client,
259
+ descriptor,
260
+ completedVerdict?.reason ?? "Activity output requires human approval"
261
+ );
262
+ }
263
+ }
264
+ }
265
+ haltReason = dependencies.spanProcessor.getHaltRequested(
266
+ descriptor.workflowId,
267
+ descriptor.activityId
268
+ );
269
+ } finally {
270
+ dependencies.spanProcessor.clearActivityAbort(
271
+ descriptor.workflowId,
272
+ descriptor.activityId
273
+ );
274
+ dependencies.spanProcessor.clearHaltRequested(
275
+ descriptor.workflowId,
276
+ descriptor.activityId
277
+ );
278
+ dependencies.spanProcessor.clearActivityContext(
279
+ descriptor.workflowId,
280
+ descriptor.activityId
281
+ );
282
+ clearActivityApproval(descriptor.runId, descriptor.activityId);
283
+ }
284
+ }
285
+ if (haltReason) {
286
+ throw new GovernanceHaltError(`Governance blocked: ${haltReason}`);
287
+ }
288
+ return output;
289
+ }
290
+ );
291
+ }
292
+ const INLINE_APPROVAL_TIMEOUT_MS = 3e5;
293
+ const INLINE_APPROVAL_INITIAL_POLL_INTERVAL_MS = 2500;
294
+ const INLINE_APPROVAL_MAX_POLL_INTERVAL_MS = 15e3;
295
+ const INLINE_APPROVAL_BACKOFF_MULTIPLIER = 2;
296
+ const inflightInlineApprovalWaits = /* @__PURE__ */ new Map();
297
+ async function waitForApprovalInline(client, descriptor, reason) {
298
+ const inflightKey = `${descriptor.runId}::${descriptor.activityId}`;
299
+ const existingWait = inflightInlineApprovalWaits.get(inflightKey);
300
+ if (existingWait) {
301
+ await existingWait;
302
+ return;
303
+ }
304
+ const waitPromise = (async () => {
305
+ const timeoutAt = Date.now() + INLINE_APPROVAL_TIMEOUT_MS;
306
+ let pollIntervalMs = INLINE_APPROVAL_INITIAL_POLL_INTERVAL_MS;
307
+ while (Date.now() < timeoutAt) {
308
+ await delay(pollIntervalMs);
309
+ if (Date.now() >= timeoutAt) {
310
+ break;
311
+ }
312
+ const approval = await client.pollApproval({
313
+ activityId: descriptor.activityId,
314
+ runId: descriptor.runId,
315
+ workflowId: descriptor.workflowId
316
+ });
317
+ if (!approval) {
318
+ pollIntervalMs = Math.min(
319
+ INLINE_APPROVAL_MAX_POLL_INTERVAL_MS,
320
+ Math.ceil(pollIntervalMs * INLINE_APPROVAL_BACKOFF_MULTIPLIER)
321
+ );
322
+ continue;
323
+ }
324
+ if (approval.expired) {
325
+ clearPendingApproval(descriptor.runId);
326
+ throw new ApprovalExpiredError(
327
+ `Approval expired for activity ${descriptor.activityType}`
328
+ );
329
+ }
330
+ const verdict = Verdict.fromString(
331
+ approval.verdict ?? approval.action
332
+ );
333
+ if (verdict === Verdict.ALLOW) {
334
+ markActivityApproved(descriptor.runId, descriptor.activityId);
335
+ clearPendingApproval(descriptor.runId);
336
+ return;
337
+ }
338
+ if (Verdict.shouldStop(verdict)) {
339
+ clearPendingApproval(descriptor.runId);
340
+ throw new ApprovalRejectedError(
341
+ `Activity rejected: ${String(approval.reason ?? "Activity rejected")}`
342
+ );
343
+ }
344
+ pollIntervalMs = Math.min(
345
+ INLINE_APPROVAL_MAX_POLL_INTERVAL_MS,
346
+ Math.ceil(pollIntervalMs * INLINE_APPROVAL_BACKOFF_MULTIPLIER)
347
+ );
348
+ }
349
+ throw new ApprovalPendingError(
350
+ reason ?? `Awaiting approval for activity ${descriptor.activityType}`
351
+ );
352
+ })();
353
+ inflightInlineApprovalWaits.set(inflightKey, waitPromise);
354
+ try {
355
+ await waitPromise;
356
+ } finally {
357
+ inflightInlineApprovalWaits.delete(inflightKey);
358
+ }
359
+ }
360
+ async function delay(ms) {
361
+ if (ms <= 0) {
362
+ return;
363
+ }
364
+ await new Promise((resolve) => {
365
+ setTimeout(resolve, ms);
366
+ });
367
+ }
368
+ function serializeValue(value) {
369
+ if (value == null) {
370
+ return value;
371
+ }
372
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
373
+ return value;
374
+ }
375
+ if (value instanceof Uint8Array) {
376
+ return Buffer.from(value).toString("utf8");
377
+ }
378
+ if (Array.isArray(value)) {
379
+ return value.map((item) => serializeValue(item));
380
+ }
381
+ if (value instanceof Date) {
382
+ return value.toISOString();
383
+ }
384
+ if (typeof value === "object") {
385
+ return Object.fromEntries(
386
+ Object.entries(value).map(([key, entry]) => [
387
+ key,
388
+ serializeValue(entry)
389
+ ])
390
+ );
391
+ }
392
+ return String(value);
393
+ }
394
+ function normalizeSpansForGovernance(spans) {
395
+ return spans.map((span) => normalizeSpanForGovernance(span));
396
+ }
397
+ function serializeActivityInputForStartEvent(value) {
398
+ const serialized = serializeValue(value);
399
+ if (serialized == null) {
400
+ return [];
401
+ }
402
+ return serialized;
403
+ }
404
+ function serializeActivityInputForCompletedEvent(value) {
405
+ const serialized = serializeValue(value);
406
+ if (serialized == null) {
407
+ return [];
408
+ }
409
+ return Array.isArray(serialized) ? serialized : [serialized];
410
+ }
411
+ function appendGoalToActivityInput(activityInput, goal) {
412
+ if (!goal || goal.trim().length === 0) {
413
+ return activityInput;
414
+ }
415
+ const trimmedGoal = goal.trim();
416
+ if (trimmedGoal.length === 0) {
417
+ return activityInput;
418
+ }
419
+ if (Array.isArray(activityInput)) {
420
+ const inputItems = activityInput;
421
+ if (inputItems.length === 0) {
422
+ return [{ goal: trimmedGoal }];
423
+ }
424
+ const [first, ...rest] = inputItems;
425
+ if (first && typeof first === "object" && !Array.isArray(first)) {
426
+ const firstRecord = first;
427
+ const existingGoal = firstRecord.goal;
428
+ if (typeof existingGoal === "string" && existingGoal.trim().length > 0) {
429
+ return inputItems;
430
+ }
431
+ return [{ ...firstRecord, goal: trimmedGoal }, ...rest];
432
+ }
433
+ return [...inputItems, { goal: trimmedGoal }];
434
+ }
435
+ if (activityInput === void 0 || activityInput === null) {
436
+ return [{ goal: trimmedGoal }];
437
+ }
438
+ if (activityInput && typeof activityInput === "object") {
439
+ const activityRecord = activityInput;
440
+ const existingGoal = activityRecord.goal;
441
+ if (typeof existingGoal === "string" && existingGoal.trim().length > 0) {
442
+ return activityInput;
443
+ }
444
+ return {
445
+ ...activityRecord,
446
+ goal: trimmedGoal
447
+ };
448
+ }
449
+ return [activityInput, { goal: trimmedGoal }];
450
+ }
451
+ function normalizeRedactedActivityInput(originalInput, redactedInput) {
452
+ if (!Array.isArray(originalInput) && Array.isArray(redactedInput)) {
453
+ if (redactedInput.length === 0) {
454
+ return redactedInput;
455
+ }
456
+ if (redactedInput.length === 1) {
457
+ return redactedInput[0];
458
+ }
459
+ }
460
+ return redactedInput;
461
+ }
462
+ function applyRedaction(original, redacted) {
463
+ if (original && redacted && typeof original === "object" && typeof redacted === "object" && !Array.isArray(original) && !Array.isArray(redacted)) {
464
+ const updated = {
465
+ ...original
466
+ };
467
+ for (const [key, value] of Object.entries(redacted)) {
468
+ updated[key] = applyRedaction(
469
+ original[key],
470
+ value
471
+ );
472
+ }
473
+ return updated;
474
+ }
475
+ if (Array.isArray(redacted)) {
476
+ return redacted.map(
477
+ (value, index) => applyRedaction(Array.isArray(original) ? original[index] : void 0, value)
478
+ );
479
+ }
480
+ return cloneValue(redacted);
481
+ }
482
+ function cloneValue(value) {
483
+ if (value === void 0) {
484
+ return value;
485
+ }
486
+ return structuredClone(value);
487
+ }
488
+ function rfc3339Now() {
489
+ return (/* @__PURE__ */ new Date()).toISOString();
490
+ }
491
+ function resolveActivityDescriptor(type, runtimeContext) {
492
+ const normalizedType = normalizeActivityType(type);
493
+ const activeContext = getOpenBoxExecutionContext();
494
+ const runId = runtimeContext.workflow?.runId ?? activeContext?.runId ?? runtimeContext.agent?.toolCallId ?? randomUUID();
495
+ const workflowId = runtimeContext.workflow?.workflowId ?? activeContext?.workflowId ?? `tool:${type}`;
496
+ const workflowType = activeContext?.workflowType ?? workflowId;
497
+ const activityId = runtimeContext.agent?.toolCallId ?? activeContext?.activityId ?? `${workflowId}:${type}`;
498
+ return {
499
+ activityId,
500
+ activityType: normalizedType,
501
+ attempt: activeContext?.attempt ?? 1,
502
+ ...activeContext?.goal ? { goal: activeContext.goal } : {},
503
+ runId,
504
+ taskQueue: activeContext?.taskQueue ?? "mastra",
505
+ workflowId,
506
+ workflowType
507
+ };
508
+ }
509
+ function normalizeActivityType(value) {
510
+ const trimmed = value.trim();
511
+ if (!trimmed) {
512
+ return "activity";
513
+ }
514
+ if (/^[a-z][A-Za-z0-9]*$/.test(trimmed)) {
515
+ return trimmed;
516
+ }
517
+ const tokens = trimmed.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^A-Za-z0-9]+/).filter(Boolean).map((token) => token.toLowerCase());
518
+ if (tokens.length === 0) {
519
+ return "activity";
520
+ }
521
+ const [first, ...rest] = tokens;
522
+ return `${first}${rest.map((token) => token.charAt(0).toUpperCase() + token.slice(1)).join("")}`;
523
+ }
524
+ async function evaluateActivityEvent(dependencies, payload) {
525
+ const body = {
526
+ source: "workflow-telemetry",
527
+ timestamp: rfc3339Now(),
528
+ ...payload
529
+ };
530
+ try {
531
+ return await dependencies.client.evaluate(body);
532
+ } catch (error) {
533
+ if (dependencies.config.onApiError === "fail_closed") {
534
+ return new GovernanceVerdictResponse({
535
+ reason: `Governance API error: ${error instanceof Error ? error.message : String(error)}`,
536
+ verdict: Verdict.HALT
537
+ });
538
+ }
539
+ return null;
540
+ }
541
+ }
542
+ function applyStopVerdict(verdict) {
543
+ if (verdict && Verdict.shouldStop(verdict.verdict)) {
544
+ throw new GovernanceHaltError(
545
+ `Governance blocked: ${verdict.reason ?? "No reason provided"}`
546
+ );
547
+ }
548
+ }
549
+ function assertGuardrailsValid(verdict, fallbackMessage) {
550
+ if (!verdict?.guardrailsResult || verdict.guardrailsResult.validationPassed) {
551
+ return;
552
+ }
553
+ const reasons = verdict.guardrailsResult.getReasonStrings();
554
+ const reason = reasons.length > 0 ? reasons.join("; ") : fallbackMessage;
555
+ throw new GuardrailsValidationError(reason);
556
+ }
557
+ function serializeError(error) {
558
+ if (error instanceof Error) {
559
+ return {
560
+ message: error.message,
561
+ type: error.name
562
+ };
563
+ }
564
+ return {
565
+ message: String(error),
566
+ type: typeof error
567
+ };
568
+ }
569
+ function ensureSpanBuffer(descriptor, spanProcessor) {
570
+ const existing = spanProcessor.getBuffer(
571
+ descriptor.workflowId,
572
+ descriptor.runId
573
+ );
574
+ if (!existing || existing.runId !== descriptor.runId) {
575
+ spanProcessor.registerWorkflow(
576
+ descriptor.workflowId,
577
+ new WorkflowSpanBuffer({
578
+ runId: descriptor.runId,
579
+ taskQueue: descriptor.taskQueue,
580
+ workflowId: descriptor.workflowId,
581
+ workflowType: descriptor.workflowType
582
+ })
583
+ );
584
+ }
585
+ }
586
+ function normalizeSpanForGovernance(span) {
587
+ const attributes = asRecord(span.attributes);
588
+ const normalizedAttributes = {
589
+ ...attributes
590
+ };
591
+ const urlFull = toStringOrUndefined(normalizedAttributes["url.full"]);
592
+ if (!toStringOrUndefined(normalizedAttributes["http.url"]) && urlFull) {
593
+ normalizedAttributes["http.url"] = urlFull;
594
+ }
595
+ const normalized = {
596
+ attributes: normalizedAttributes,
597
+ end_time: toFiniteNumber(span.end_time ?? span.endTime),
598
+ events: normalizeSpanEvents(span.events),
599
+ name: toStringOrUndefined(span.name),
600
+ span_id: toStringOrUndefined(span.span_id ?? span.spanId),
601
+ start_time: toFiniteNumber(span.start_time ?? span.startTime),
602
+ trace_id: toStringOrUndefined(span.trace_id ?? span.traceId)
603
+ };
604
+ const parentSpanId = toStringOrUndefined(
605
+ span.parent_span_id ?? span.parentSpanId
606
+ );
607
+ const kind = toStringOrUndefined(span.kind);
608
+ const durationNs = toFiniteNumber(span.duration_ns ?? span.durationNs) ?? calculateDurationNs(normalized.start_time, normalized.end_time);
609
+ const status = normalizeSpanStatus(span.status);
610
+ const requestHeaders = toStringRecord(
611
+ span.request_headers ?? span.requestHeaders
612
+ );
613
+ const responseHeaders = toStringRecord(
614
+ span.response_headers ?? span.responseHeaders
615
+ );
616
+ const requestBody = toStringOrUndefined(span.request_body ?? span.requestBody);
617
+ const responseBody = toStringOrUndefined(span.response_body ?? span.responseBody);
618
+ const semanticType = toStringOrUndefined(
619
+ span.semantic_type ?? span.semanticType
620
+ );
621
+ if (parentSpanId) {
622
+ normalized.parent_span_id = parentSpanId;
623
+ }
624
+ if (kind) {
625
+ normalized.kind = kind;
626
+ }
627
+ if (durationNs !== void 0) {
628
+ normalized.duration_ns = durationNs;
629
+ }
630
+ if (status) {
631
+ normalized.status = status;
632
+ }
633
+ if (requestHeaders) {
634
+ normalized.request_headers = requestHeaders;
635
+ }
636
+ if (responseHeaders) {
637
+ normalized.response_headers = responseHeaders;
638
+ }
639
+ if (requestBody !== void 0) {
640
+ normalized.request_body = requestBody;
641
+ }
642
+ if (responseBody !== void 0) {
643
+ normalized.response_body = responseBody;
644
+ }
645
+ if (semanticType) {
646
+ normalized.semantic_type = semanticType;
647
+ }
648
+ return normalized;
649
+ }
650
+ function calculateDurationNs(startTime, endTime) {
651
+ if (typeof startTime !== "number" || typeof endTime !== "number") {
652
+ return void 0;
653
+ }
654
+ return Math.max(0, endTime - startTime);
655
+ }
656
+ function normalizeSpanEvents(events) {
657
+ if (!Array.isArray(events)) {
658
+ return [];
659
+ }
660
+ return events.map((event) => {
661
+ const eventRecord = asRecord(event);
662
+ return {
663
+ attributes: asRecord(eventRecord.attributes),
664
+ name: toStringOrUndefined(eventRecord.name) ?? "",
665
+ timestamp: toFiniteNumber(eventRecord.timestamp) ?? 0
666
+ };
667
+ });
668
+ }
669
+ function normalizeSpanStatus(status) {
670
+ const statusRecord = asRecord(status);
671
+ const code = toStringOrUndefined(statusRecord.code);
672
+ const description = toStringOrUndefined(statusRecord.description);
673
+ if (!code && !description) {
674
+ return void 0;
675
+ }
676
+ return {
677
+ ...code ? { code } : {},
678
+ ...description ? { description } : {}
679
+ };
680
+ }
681
+ function toFiniteNumber(value) {
682
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
683
+ }
684
+ function toStringOrUndefined(value) {
685
+ return typeof value === "string" ? value : void 0;
686
+ }
687
+ function asRecord(value) {
688
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
689
+ return {};
690
+ }
691
+ return value;
692
+ }
693
+ function toStringRecord(value) {
694
+ const record = asRecord(value);
695
+ if (Object.keys(record).length === 0) {
696
+ return void 0;
697
+ }
698
+ const serialized = Object.fromEntries(
699
+ Object.entries(record).flatMap(
700
+ ([key, entry]) => typeof entry === "string" ? [[key, entry]] : []
701
+ )
702
+ );
703
+ return Object.keys(serialized).length > 0 ? serialized : void 0;
704
+ }
705
+ export {
706
+ appendGoalToActivityInput,
707
+ applyRedaction,
708
+ executeGovernedActivity,
709
+ normalizeSpansForGovernance,
710
+ serializeValue
711
+ };
712
+ //# sourceMappingURL=activity-runtime.js.map