robotrock 0.8.5 → 0.9.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.
@@ -213,12 +213,12 @@ function validateUrlValue(value, widget) {
213
213
  }
214
214
  return null;
215
215
  }
216
- function validateContextPublicUrls(context) {
217
- if (!context?.data) {
216
+ function validateContextPublicUrls(context2) {
217
+ if (!context2?.data) {
218
218
  return null;
219
219
  }
220
- for (const [field, value] of Object.entries(context.data)) {
221
- const widget = widgetType(context.ui, field);
220
+ for (const [field, value] of Object.entries(context2.data)) {
221
+ const widget = widgetType(context2.ui, field);
222
222
  if (!widget) {
223
223
  continue;
224
224
  }
@@ -273,7 +273,8 @@ var contextDataSchema = z.object({
273
273
  data: z.record(z.string(), z.unknown()),
274
274
  ui: contextUiSchema
275
275
  }).optional();
276
- var taskContextObjectSchema = z.object({
276
+ var TASK_CONTEXT_FORMAT_VERSION = 2;
277
+ var taskContextObjectBaseSchema = z.object({
277
278
  /** Source application id; omitted tasks are grouped in the default inbox. */
278
279
  app: z.string().min(1).optional(),
279
280
  type: z.string().min(1),
@@ -281,9 +282,22 @@ var taskContextObjectSchema = z.object({
281
282
  description: z.string().optional(),
282
283
  validUntil: z.string().optional(),
283
284
  context: contextDataSchema,
285
+ /** Task context wire format version. @default 2 */
286
+ contextVersion: z.literal(2).optional(),
287
+ /** @deprecated Use `contextVersion`. Accepted on ingest only. */
284
288
  version: z.literal(2).optional(),
285
289
  actions: z.array(taskActionSchema).min(1, "At least one action is required")
286
290
  });
291
+ function normalizeTaskContextVersion(data) {
292
+ const { version: legacyVersion, contextVersion, ...rest } = data;
293
+ return {
294
+ ...rest,
295
+ contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION
296
+ };
297
+ }
298
+ var taskContextObjectSchema = taskContextObjectBaseSchema.transform(
299
+ normalizeTaskContextVersion
300
+ );
287
301
  function refineContextPublicUrls(data, ctx) {
288
302
  const error = validateContextPublicUrls(data.context);
289
303
  if (error) {
@@ -327,61 +341,11 @@ var threadUpdateInputSchema = z.object({
327
341
  });
328
342
  var taskPriorities = ["low", "normal", "high", "urgent"];
329
343
  var taskPrioritySchema = z.enum(taskPriorities);
330
- var nonNegativeInt = z.number().int().nonnegative();
331
- var agentCostTokensSchema = z.object({
332
- input: nonNegativeInt.optional(),
333
- output: nonNegativeInt.optional(),
334
- total: nonNegativeInt.optional()
335
- });
336
- var agentCostSchema = z.object({
337
- tokens: agentCostTokensSchema.optional(),
338
- eur: z.number().nonnegative().optional(),
339
- usd: z.number().nonnegative().optional()
340
- });
341
- var AGENT_INFO_MAX_KEYS = 32;
342
- var AGENT_TOOL_CALLS_MAX_KEYS = 64;
343
- var AGENT_OTEL_SPANS_MAX = 32;
344
- var agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
345
- var agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
346
- var agentOtelSpanSummarySchema = z.object({
347
- name: z.string().min(1),
348
- durationMs: z.number().nonnegative(),
349
- status: agentOtelSpanStatusSchema
350
- });
351
- var agentOtelSchema = z.object({
352
- traceId: z.string().min(1),
353
- spanId: z.string().min(1).optional(),
354
- rootDurationMs: z.number().nonnegative().optional(),
355
- spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
356
- });
357
344
  var agentTelemetrySchema = z.object({
358
345
  /** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
359
- version: z.string().min(1).optional(),
360
- /** Total tool invocations. When omitted but `toolCalls` is set, the sum of counts is used. */
361
- toolCallCount: nonNegativeInt.optional(),
362
- /** Per-tool invocation counts keyed by tool name. */
363
- toolCalls: agentToolCallsSchema.optional(),
364
- cost: agentCostSchema.optional(),
365
- /** Free-form metadata for experiments (model, prompt variant, etc.). */
366
- info: z.record(z.string(), z.unknown()).optional(),
367
- /** Structured OpenTelemetry span snapshot for feedback analysis. */
368
- otel: agentOtelSchema.optional()
369
- }).refine(
370
- (data) => {
371
- const keys = data.info ? Object.keys(data.info) : [];
372
- return keys.length <= AGENT_INFO_MAX_KEYS;
373
- },
374
- { message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS} keys` }
375
- ).refine(
376
- (data) => {
377
- const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
378
- return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS;
379
- },
380
- {
381
- message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS} tool names`
382
- }
383
- );
384
- var createTaskBodySchema = taskContextObjectSchema.extend({
346
+ version: z.string().min(1)
347
+ });
348
+ var createTaskBodySchema = taskContextObjectBaseSchema.extend({
385
349
  assignTo: assignToSchema.optional(),
386
350
  /**
387
351
  * Groups related tasks together. When omitted, the server generates one and
@@ -398,9 +362,9 @@ var createTaskBodySchema = taskContextObjectSchema.extend({
398
362
  * the inbox status bar and the thread update log.
399
363
  */
400
364
  update: threadUpdateInputSchema.optional(),
401
- /** Agent telemetry (version, cost, tool calls) — not shown in inbox UI. */
365
+ /** Agent release version — not shown in inbox UI. */
402
366
  agent: agentTelemetrySchema.optional()
403
- }).superRefine(refineContextPublicUrls);
367
+ }).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
404
368
 
405
369
  // src/schemas/index.ts
406
370
  var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
@@ -444,16 +408,29 @@ var contextDataSchema2 = z2.object({
444
408
  data: z2.record(z2.string(), z2.unknown()),
445
409
  ui: contextUiSchema2
446
410
  }).optional();
447
- var taskContextObjectSchema2 = z2.object({
411
+ var TASK_CONTEXT_FORMAT_VERSION2 = 2;
412
+ var taskContextObjectBaseSchema2 = z2.object({
448
413
  app: z2.string().min(1).optional(),
449
414
  type: z2.string().min(1),
450
415
  name: z2.string().min(1),
451
416
  description: z2.string().optional(),
452
417
  validUntil: z2.string().optional(),
453
418
  context: contextDataSchema2,
419
+ contextVersion: z2.literal(2).optional(),
420
+ /** @deprecated Use `contextVersion`. Accepted on ingest only. */
454
421
  version: z2.literal(2).optional(),
455
422
  actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
456
423
  });
424
+ function normalizeTaskContextVersion2(data) {
425
+ const { version: legacyVersion, contextVersion, ...rest } = data;
426
+ return {
427
+ ...rest,
428
+ contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION2
429
+ };
430
+ }
431
+ var taskContextObjectSchema2 = taskContextObjectBaseSchema2.transform(
432
+ normalizeTaskContextVersion2
433
+ );
457
434
  function refineContextPublicUrls2(data, ctx) {
458
435
  const error = validateContextPublicUrls(data.context);
459
436
  if (error) {
@@ -497,56 +474,10 @@ var threadUpdateInputSchema2 = z2.object({
497
474
  });
498
475
  var taskPriorities2 = ["low", "normal", "high", "urgent"];
499
476
  var taskPrioritySchema2 = z2.enum(taskPriorities2);
500
- var nonNegativeInt2 = z2.number().int().nonnegative();
501
- var agentCostTokensSchema2 = z2.object({
502
- input: nonNegativeInt2.optional(),
503
- output: nonNegativeInt2.optional(),
504
- total: nonNegativeInt2.optional()
505
- });
506
- var agentCostSchema2 = z2.object({
507
- tokens: agentCostTokensSchema2.optional(),
508
- eur: z2.number().nonnegative().optional(),
509
- usd: z2.number().nonnegative().optional()
510
- });
511
- var AGENT_INFO_MAX_KEYS2 = 32;
512
- var AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
513
- var AGENT_OTEL_SPANS_MAX2 = 32;
514
- var agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
515
- var agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
516
- var agentOtelSpanSummarySchema2 = z2.object({
517
- name: z2.string().min(1),
518
- durationMs: z2.number().nonnegative(),
519
- status: agentOtelSpanStatusSchema2
520
- });
521
- var agentOtelSchema2 = z2.object({
522
- traceId: z2.string().min(1),
523
- spanId: z2.string().min(1).optional(),
524
- rootDurationMs: z2.number().nonnegative().optional(),
525
- spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
526
- });
527
477
  var agentTelemetrySchema2 = z2.object({
528
- version: z2.string().min(1).optional(),
529
- toolCallCount: nonNegativeInt2.optional(),
530
- toolCalls: agentToolCallsSchema2.optional(),
531
- cost: agentCostSchema2.optional(),
532
- info: z2.record(z2.string(), z2.unknown()).optional(),
533
- otel: agentOtelSchema2.optional()
534
- }).refine(
535
- (data) => {
536
- const keys = data.info ? Object.keys(data.info) : [];
537
- return keys.length <= AGENT_INFO_MAX_KEYS2;
538
- },
539
- { message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS2} keys` }
540
- ).refine(
541
- (data) => {
542
- const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
543
- return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS2;
544
- },
545
- {
546
- message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS2} tool names`
547
- }
548
- );
549
- var createTaskBodySchema2 = taskContextObjectSchema2.extend({
478
+ version: z2.string().min(1)
479
+ });
480
+ var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
550
481
  assignTo: assignToSchema2.optional(),
551
482
  /**
552
483
  * Groups related tasks together. When omitted, the server generates one and
@@ -564,7 +495,7 @@ var createTaskBodySchema2 = taskContextObjectSchema2.extend({
564
495
  */
565
496
  update: threadUpdateInputSchema2.optional(),
566
497
  agent: agentTelemetrySchema2.optional()
567
- }).superRefine(refineContextPublicUrls2);
498
+ }).transform(normalizeTaskContextVersion2).superRefine(refineContextPublicUrls2);
568
499
  var threadUpdateBodySchema = threadUpdateInputSchema2;
569
500
 
570
501
  // src/approval-result.ts
@@ -600,6 +531,10 @@ var DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
600
531
  function sleep(ms) {
601
532
  return new Promise((resolve) => setTimeout(resolve, ms));
602
533
  }
534
+ function resolveAgentVersionFromEnv() {
535
+ const fromEnv = process.env.AGENT_VERSION?.trim() || process.env.ROBOTROCK_AGENT_VERSION?.trim();
536
+ return fromEnv || void 0;
537
+ }
603
538
  function parseValidUntilMs(value) {
604
539
  if (value === void 0) {
605
540
  return void 0;
@@ -639,7 +574,8 @@ var RobotRock = class {
639
574
  apiKey;
640
575
  baseUrl;
641
576
  app;
642
- version;
577
+ agentVersion;
578
+ contextVersion;
643
579
  webhook;
644
580
  polling;
645
581
  constructor(config) {
@@ -658,7 +594,8 @@ var RobotRock = class {
658
594
  const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
659
595
  this.baseUrl = rawBase.replace(/\/+$/, "");
660
596
  this.app = config.app;
661
- this.version = config.version ?? 2;
597
+ this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
598
+ this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
662
599
  this.webhook = config.webhook;
663
600
  this.polling = config.polling ?? {};
664
601
  }
@@ -669,15 +606,17 @@ var RobotRock = class {
669
606
  const normalizedTask = normalizeSendToHumanInput(task, {
670
607
  webhook: this.webhook,
671
608
  app: this.app,
672
- version: this.version
609
+ contextVersion: this.contextVersion,
610
+ agentVersion: this.agentVersion
673
611
  });
612
+ const agentVersion = task.version ?? this.agentVersion;
674
613
  const bodyPayload = {
675
614
  ...normalizedTask,
676
615
  ...task.assignTo !== void 0 ? { assignTo: task.assignTo } : {},
677
616
  ...task.threadId !== void 0 ? { threadId: task.threadId } : {},
678
617
  ...task.priority !== void 0 ? { priority: task.priority } : {},
679
618
  ...task.update !== void 0 ? { update: task.update } : {},
680
- ...task.agent !== void 0 ? { agent: task.agent } : {}
619
+ ...agentVersion !== void 0 ? { agent: { version: agentVersion } } : {}
681
620
  };
682
621
  const validation = createTaskBodySchema2.safeParse(bodyPayload);
683
622
  if (!validation.success) {
@@ -713,7 +652,8 @@ var RobotRock = class {
713
652
  const normalizedTask = normalizeSendToHumanInput(task, {
714
653
  webhook: this.webhook,
715
654
  app: this.app,
716
- version: this.version
655
+ contextVersion: this.contextVersion,
656
+ agentVersion: this.agentVersion
717
657
  });
718
658
  const createdTaskTask = await this.createTask(task);
719
659
  const hasHandlers = normalizedTask.actions.some(
@@ -857,6 +797,7 @@ function normalizeSendToHumanInput(task, clientDefaults) {
857
797
  threadId: _threadId,
858
798
  priority: _priority,
859
799
  update: _update,
800
+ version: _version,
860
801
  validUntil,
861
802
  app: taskApp,
862
803
  ...rest
@@ -866,7 +807,7 @@ function normalizeSendToHumanInput(task, clientDefaults) {
866
807
  const app = taskApp ?? clientDefaults.app;
867
808
  return {
868
809
  ...rest,
869
- version: clientDefaults.version,
810
+ contextVersion: clientDefaults.contextVersion,
870
811
  ...app ? { app } : {},
871
812
  ...validUntil !== void 0 ? { validUntil: serializeValidUntil(validUntil) } : {},
872
813
  actions: normalizedActions
@@ -980,6 +921,200 @@ function durationMsToTimeout(durationMs) {
980
921
  return `${seconds}s`;
981
922
  }
982
923
 
924
+ // src/record-handled-to-otel.ts
925
+ import {
926
+ context,
927
+ trace,
928
+ SpanStatusCode
929
+ } from "@opentelemetry/api";
930
+ var TRACER_NAME = "robotrock";
931
+ var WAIT_SPAN_NAME = "robotrock.wait_for_human";
932
+ var HANDLED_EVENT_NAME = "robotrock.task_handled";
933
+ var INVALID_TRACE_ID = "00000000000000000000000000000000";
934
+ function isValidTraceId(traceId) {
935
+ return typeof traceId === "string" && traceId.length > 0 && traceId !== INVALID_TRACE_ID;
936
+ }
937
+ function resolveSpanContext(span) {
938
+ const active = span ?? trace.getActiveSpan();
939
+ const ctx = active?.spanContext();
940
+ if (!ctx || !isValidTraceId(ctx.traceId)) {
941
+ return void 0;
942
+ }
943
+ return { traceId: ctx.traceId, spanId: ctx.spanId };
944
+ }
945
+ function parseTaskCreatedAt(submittedAt) {
946
+ if (submittedAt) {
947
+ const parsed = Date.parse(submittedAt);
948
+ if (!Number.isNaN(parsed)) {
949
+ return parsed;
950
+ }
951
+ }
952
+ return Date.now();
953
+ }
954
+ function parseHandledAtMs(handledAt) {
955
+ if (handledAt instanceof Date) {
956
+ return handledAt.getTime();
957
+ }
958
+ if (typeof handledAt === "number") {
959
+ return handledAt;
960
+ }
961
+ const parsed = Date.parse(handledAt);
962
+ return Number.isNaN(parsed) ? Date.now() : parsed;
963
+ }
964
+ function toRobotRockHandledOtelInput(handled) {
965
+ if ("actionId" in handled) {
966
+ return {
967
+ taskId: handled.taskId,
968
+ action: {
969
+ id: handled.actionId,
970
+ data: handled.data
971
+ },
972
+ handledBy: handled.handledBy,
973
+ handledAt: handled.handledAt
974
+ };
975
+ }
976
+ return {
977
+ taskId: handled.taskId,
978
+ action: {
979
+ id: handled.action.id,
980
+ title: handled.action.title,
981
+ data: handled.action.data
982
+ },
983
+ handledBy: handled.handledBy,
984
+ handledAt: handled.handledAt
985
+ };
986
+ }
987
+ function captureRobotRockOtelHandle(task, options) {
988
+ const spanCtx = resolveSpanContext(options?.span);
989
+ return {
990
+ traceId: spanCtx?.traceId ?? "",
991
+ spanId: spanCtx?.spanId ?? "",
992
+ taskId: task.taskId,
993
+ threadId: task.threadId,
994
+ taskCreatedAt: parseTaskCreatedAt(task.submittedAt)
995
+ };
996
+ }
997
+ function startRobotRockHumanWaitSpan(handle, options) {
998
+ const parent = options?.span ?? trace.getActiveSpan();
999
+ if (!parent) {
1000
+ return void 0;
1001
+ }
1002
+ const tracer = trace.getTracer(options?.tracerName ?? TRACER_NAME);
1003
+ const span = tracer.startSpan(
1004
+ WAIT_SPAN_NAME,
1005
+ {},
1006
+ trace.setSpan(context.active(), parent)
1007
+ );
1008
+ span.setAttribute("robotrock.task_id", handle.taskId);
1009
+ if (handle.threadId) {
1010
+ span.setAttribute("robotrock.thread_id", handle.threadId);
1011
+ }
1012
+ return span;
1013
+ }
1014
+ function recordRobotRockHandledToOtel(handled, options = {}) {
1015
+ const span = options.span ?? trace.getActiveSpan();
1016
+ if (!span) {
1017
+ return;
1018
+ }
1019
+ const input = toRobotRockHandledOtelInput(handled);
1020
+ const handledAtMs = parseHandledAtMs(input.handledAt);
1021
+ const handle = options.handle;
1022
+ const humanWaitMs = handle != null ? Math.max(0, handledAtMs - handle.taskCreatedAt) : void 0;
1023
+ span.setAttribute("robotrock.task_id", input.taskId);
1024
+ span.setAttribute("robotrock.action.id", input.action.id);
1025
+ if (input.action.title) {
1026
+ span.setAttribute("robotrock.action.title", input.action.title);
1027
+ }
1028
+ if (input.handledBy) {
1029
+ span.setAttribute("robotrock.handled_by", input.handledBy);
1030
+ }
1031
+ span.setAttribute("robotrock.handled_at", new Date(handledAtMs).toISOString());
1032
+ if (humanWaitMs != null) {
1033
+ span.setAttribute("robotrock.human_wait_ms", humanWaitMs);
1034
+ }
1035
+ if (input.threadId) {
1036
+ span.setAttribute("robotrock.thread_id", input.threadId);
1037
+ }
1038
+ const eventAttributes = {
1039
+ "robotrock.task_id": input.taskId,
1040
+ "robotrock.action.id": input.action.id
1041
+ };
1042
+ if (input.handledBy) {
1043
+ eventAttributes["robotrock.handled_by"] = input.handledBy;
1044
+ }
1045
+ if (humanWaitMs != null) {
1046
+ eventAttributes["robotrock.human_wait_ms"] = humanWaitMs;
1047
+ }
1048
+ if (options.includeActionData && input.action.data != null) {
1049
+ const serialized = JSON.stringify(input.action.data);
1050
+ const truncated = serialized.length > 512 ? `${serialized.slice(0, 512)}\u2026` : serialized;
1051
+ span.setAttribute("robotrock.action.data", truncated);
1052
+ eventAttributes["robotrock.action.data"] = truncated;
1053
+ }
1054
+ span.addEvent(HANDLED_EVENT_NAME, eventAttributes);
1055
+ }
1056
+ function endRobotRockHumanWaitSpan(span, handled, options = {}) {
1057
+ if (!span) {
1058
+ return;
1059
+ }
1060
+ const outcome = options.outcome ?? (handled ? "handled" : "timeout");
1061
+ if (handled && outcome === "handled") {
1062
+ recordRobotRockHandledToOtel(handled, {
1063
+ span,
1064
+ handle: options.handle,
1065
+ includeActionData: options.includeActionData
1066
+ });
1067
+ span.setStatus({ code: SpanStatusCode.OK });
1068
+ } else {
1069
+ span.setAttribute("robotrock.outcome", outcome);
1070
+ span.setStatus({
1071
+ code: SpanStatusCode.ERROR,
1072
+ message: outcome === "timeout" ? "Human response timed out before validUntil" : "Human wait failed"
1073
+ });
1074
+ }
1075
+ span.end();
1076
+ }
1077
+
1078
+ // src/otel-platform.ts
1079
+ function shouldRecordRobotRockOtel(recordOtel) {
1080
+ if (recordOtel === true) {
1081
+ return true;
1082
+ }
1083
+ if (recordOtel === false) {
1084
+ return false;
1085
+ }
1086
+ const env = process.env.ROBOTROCK_OTEL_RECORD_HANDLED;
1087
+ return env === "true" || env === "1";
1088
+ }
1089
+ function stripPlatformOtelFields(payload) {
1090
+ const { recordOtel: _recordOtel, otelIncludeActionData: _otelIncludeActionData, ...rest } = payload;
1091
+ return rest;
1092
+ }
1093
+ function beginRobotRockHumanWaitOtel(task, options = {}) {
1094
+ const recordOtel = shouldRecordRobotRockOtel(options.recordOtel);
1095
+ if (!recordOtel) {
1096
+ return { recordOtel: false };
1097
+ }
1098
+ const handle = captureRobotRockOtelHandle(task);
1099
+ const waitSpan = startRobotRockHumanWaitSpan(handle);
1100
+ return {
1101
+ recordOtel: true,
1102
+ handle,
1103
+ waitSpan,
1104
+ includeActionData: options.otelIncludeActionData
1105
+ };
1106
+ }
1107
+ function finishRobotRockHumanWaitOtel(session, handled, outcome) {
1108
+ if (!session.recordOtel) {
1109
+ return;
1110
+ }
1111
+ endRobotRockHumanWaitSpan(session.waitSpan, handled, {
1112
+ handle: session.handle,
1113
+ outcome,
1114
+ includeActionData: session.includeActionData
1115
+ });
1116
+ }
1117
+
983
1118
  // src/workflow/index.ts
984
1119
  var APPROVE_BY_HUMAN_ACTIONS = [
985
1120
  { id: "approve", title: "Approve" },
@@ -993,6 +1128,7 @@ async function createRobotRockTaskForWebhook(input) {
993
1128
  baseUrl: baseConfig.baseUrl,
994
1129
  ...input.app ?? baseConfig.app ? { app: input.app ?? baseConfig.app } : {},
995
1130
  ...baseConfig.version ? { version: baseConfig.version } : {},
1131
+ ...baseConfig.advanced ? { advanced: baseConfig.advanced } : {},
996
1132
  webhook: { url: input.webhookUrl }
997
1133
  });
998
1134
  return client.sendToHuman({
@@ -1013,7 +1149,7 @@ async function parseRobotRockWebhookRequest(request) {
1013
1149
  async function sendToHumanInWorkflow(payload) {
1014
1150
  var _stack = [];
1015
1151
  try {
1016
- const { validUntil: validUntilInput, app, ...taskInput } = payload;
1152
+ const { validUntil: validUntilInput, app, recordOtel, otelIncludeActionData, ...taskFields } = payload;
1017
1153
  const { validUntil, timeout } = resolveWaitTiming(validUntilInput);
1018
1154
  const timeoutMs = parseValidUntilMs2(validUntil) - Date.now();
1019
1155
  const webhook = __using(_stack, createWebhook());
@@ -1021,31 +1157,54 @@ async function sendToHumanInWorkflow(payload) {
1021
1157
  webhookUrl: webhook.url,
1022
1158
  app,
1023
1159
  validUntil,
1024
- taskInput
1160
+ taskInput: stripPlatformOtelFields(taskFields)
1025
1161
  });
1026
- const outcome = await Promise.race([
1027
- webhook.then((request) => parseRobotRockWebhookRequest(request)),
1028
- sleep2(timeoutMs).then(() => ({ timedOut: true }))
1029
- ]);
1030
- if ("timedOut" in outcome) {
1031
- throw new Error(`Human response timed out before validUntil (${timeout})`);
1032
- }
1033
- const output = outcome;
1034
- return toDiscriminatedApprovalResult(payload.actions, {
1035
- id: output.taskId,
1036
- createdAt: /* @__PURE__ */ new Date(),
1037
- status: "handled",
1038
- context: sendResult.task.context,
1039
- validUntil: Date.now(),
1040
- handledAt: new Date(output.handledAt).getTime(),
1041
- handled: {
1042
- action: {
1043
- id: output.action.id,
1044
- data: output.action.data
1045
- },
1046
- handledBy: output.handledBy
1047
- }
1162
+ const otelSession = beginRobotRockHumanWaitOtel(sendResult.task, {
1163
+ recordOtel,
1164
+ otelIncludeActionData
1048
1165
  });
1166
+ let handledPayload = null;
1167
+ let waitOutcome = "pending";
1168
+ try {
1169
+ const outcome = await Promise.race([
1170
+ webhook.then((request) => parseRobotRockWebhookRequest(request)),
1171
+ sleep2(timeoutMs).then(() => ({ timedOut: true }))
1172
+ ]);
1173
+ if ("timedOut" in outcome) {
1174
+ waitOutcome = "timeout";
1175
+ throw new Error(`Human response timed out before validUntil (${timeout})`);
1176
+ }
1177
+ handledPayload = outcome;
1178
+ waitOutcome = "handled";
1179
+ return toDiscriminatedApprovalResult(payload.actions, {
1180
+ id: outcome.taskId,
1181
+ createdAt: /* @__PURE__ */ new Date(),
1182
+ status: "handled",
1183
+ context: sendResult.task.context,
1184
+ validUntil: Date.now(),
1185
+ handledAt: new Date(outcome.handledAt).getTime(),
1186
+ handled: {
1187
+ action: {
1188
+ id: outcome.action.id,
1189
+ data: outcome.action.data
1190
+ },
1191
+ handledBy: outcome.handledBy
1192
+ }
1193
+ });
1194
+ } catch (error) {
1195
+ if (waitOutcome === "pending") {
1196
+ waitOutcome = "error";
1197
+ }
1198
+ throw error;
1199
+ } finally {
1200
+ if (waitOutcome !== "pending") {
1201
+ finishRobotRockHumanWaitOtel(
1202
+ otelSession,
1203
+ handledPayload,
1204
+ waitOutcome === "handled" ? "handled" : waitOutcome
1205
+ );
1206
+ }
1207
+ }
1049
1208
  } catch (_) {
1050
1209
  var _error = _, _hasError = true;
1051
1210
  } finally {
@@ -1066,7 +1225,8 @@ async function sendRobotRockUpdate(payload) {
1066
1225
  apiKey: baseConfig.apiKey,
1067
1226
  baseUrl: baseConfig.baseUrl,
1068
1227
  ...app ?? baseConfig.app ? { app: app ?? baseConfig.app } : {},
1069
- ...baseConfig.version ? { version: baseConfig.version } : {}
1228
+ ...baseConfig.version ? { version: baseConfig.version } : {},
1229
+ ...baseConfig.advanced ? { advanced: baseConfig.advanced } : {}
1070
1230
  });
1071
1231
  return client.sendUpdate(update);
1072
1232
  }