robotrock 0.8.4 → 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.
- package/README.md +56 -0
- package/dist/ai/index.d.ts +4 -4
- package/dist/ai/index.js +398 -202
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/trigger.d.ts +3 -3
- package/dist/ai/trigger.js +398 -202
- package/dist/ai/trigger.js.map +1 -1
- package/dist/ai/workflow.d.ts +3 -3
- package/dist/ai/workflow.js +399 -203
- package/dist/ai/workflow.js.map +1 -1
- package/dist/{client-D-XEBOWd.d.ts → client-Cy7YLxms.d.ts} +17 -9
- package/dist/index.d.ts +76 -9
- package/dist/index.js +337 -208
- package/dist/index.js.map +1 -1
- package/dist/otel-platform-DzHyHkGk.d.ts +108 -0
- package/dist/schemas/index.d.ts +162 -104
- package/dist/schemas/index.js +39 -114
- package/dist/schemas/index.js.map +1 -1
- package/dist/{tool-approval-bridge-BKDY5NAY.d.ts → tool-approval-bridge-G765kMJR.d.ts} +1 -1
- package/dist/trigger/index.d.ts +6 -4
- package/dist/trigger/index.js +308 -145
- package/dist/trigger/index.js.map +1 -1
- package/dist/{trigger-CsOLTjsH.d.ts → trigger-D0shjqk0.d.ts} +2 -2
- package/dist/workflow/index.d.ts +6 -4
- package/dist/workflow/index.js +302 -142
- package/dist/workflow/index.js.map +1 -1
- package/package.json +1 -5
- package/dist/handler-webhook-BqEi6Bk-.d.ts +0 -16
- package/dist/otel/index.d.ts +0 -49
- package/dist/otel/index.js +0 -633
- package/dist/otel/index.js.map +0 -1
package/dist/trigger/index.js
CHANGED
|
@@ -1,6 +1,200 @@
|
|
|
1
1
|
// src/trigger/index.ts
|
|
2
2
|
import { task, wait } from "@trigger.dev/sdk";
|
|
3
3
|
|
|
4
|
+
// src/record-handled-to-otel.ts
|
|
5
|
+
import {
|
|
6
|
+
context,
|
|
7
|
+
trace,
|
|
8
|
+
SpanStatusCode
|
|
9
|
+
} from "@opentelemetry/api";
|
|
10
|
+
var TRACER_NAME = "robotrock";
|
|
11
|
+
var WAIT_SPAN_NAME = "robotrock.wait_for_human";
|
|
12
|
+
var HANDLED_EVENT_NAME = "robotrock.task_handled";
|
|
13
|
+
var INVALID_TRACE_ID = "00000000000000000000000000000000";
|
|
14
|
+
function isValidTraceId(traceId) {
|
|
15
|
+
return typeof traceId === "string" && traceId.length > 0 && traceId !== INVALID_TRACE_ID;
|
|
16
|
+
}
|
|
17
|
+
function resolveSpanContext(span) {
|
|
18
|
+
const active = span ?? trace.getActiveSpan();
|
|
19
|
+
const ctx = active?.spanContext();
|
|
20
|
+
if (!ctx || !isValidTraceId(ctx.traceId)) {
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
|
24
|
+
}
|
|
25
|
+
function parseTaskCreatedAt(submittedAt) {
|
|
26
|
+
if (submittedAt) {
|
|
27
|
+
const parsed = Date.parse(submittedAt);
|
|
28
|
+
if (!Number.isNaN(parsed)) {
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return Date.now();
|
|
33
|
+
}
|
|
34
|
+
function parseHandledAtMs(handledAt) {
|
|
35
|
+
if (handledAt instanceof Date) {
|
|
36
|
+
return handledAt.getTime();
|
|
37
|
+
}
|
|
38
|
+
if (typeof handledAt === "number") {
|
|
39
|
+
return handledAt;
|
|
40
|
+
}
|
|
41
|
+
const parsed = Date.parse(handledAt);
|
|
42
|
+
return Number.isNaN(parsed) ? Date.now() : parsed;
|
|
43
|
+
}
|
|
44
|
+
function toRobotRockHandledOtelInput(handled) {
|
|
45
|
+
if ("actionId" in handled) {
|
|
46
|
+
return {
|
|
47
|
+
taskId: handled.taskId,
|
|
48
|
+
action: {
|
|
49
|
+
id: handled.actionId,
|
|
50
|
+
data: handled.data
|
|
51
|
+
},
|
|
52
|
+
handledBy: handled.handledBy,
|
|
53
|
+
handledAt: handled.handledAt
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
taskId: handled.taskId,
|
|
58
|
+
action: {
|
|
59
|
+
id: handled.action.id,
|
|
60
|
+
title: handled.action.title,
|
|
61
|
+
data: handled.action.data
|
|
62
|
+
},
|
|
63
|
+
handledBy: handled.handledBy,
|
|
64
|
+
handledAt: handled.handledAt
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function captureRobotRockOtelHandle(task2, options) {
|
|
68
|
+
const spanCtx = resolveSpanContext(options?.span);
|
|
69
|
+
return {
|
|
70
|
+
traceId: spanCtx?.traceId ?? "",
|
|
71
|
+
spanId: spanCtx?.spanId ?? "",
|
|
72
|
+
taskId: task2.taskId,
|
|
73
|
+
threadId: task2.threadId,
|
|
74
|
+
taskCreatedAt: parseTaskCreatedAt(task2.submittedAt)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function startRobotRockHumanWaitSpan(handle, options) {
|
|
78
|
+
const parent = options?.span ?? trace.getActiveSpan();
|
|
79
|
+
if (!parent) {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
const tracer = trace.getTracer(options?.tracerName ?? TRACER_NAME);
|
|
83
|
+
const span = tracer.startSpan(
|
|
84
|
+
WAIT_SPAN_NAME,
|
|
85
|
+
{},
|
|
86
|
+
trace.setSpan(context.active(), parent)
|
|
87
|
+
);
|
|
88
|
+
span.setAttribute("robotrock.task_id", handle.taskId);
|
|
89
|
+
if (handle.threadId) {
|
|
90
|
+
span.setAttribute("robotrock.thread_id", handle.threadId);
|
|
91
|
+
}
|
|
92
|
+
return span;
|
|
93
|
+
}
|
|
94
|
+
function recordRobotRockHandledToOtel(handled, options = {}) {
|
|
95
|
+
const span = options.span ?? trace.getActiveSpan();
|
|
96
|
+
if (!span) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const input = toRobotRockHandledOtelInput(handled);
|
|
100
|
+
const handledAtMs = parseHandledAtMs(input.handledAt);
|
|
101
|
+
const handle = options.handle;
|
|
102
|
+
const humanWaitMs = handle != null ? Math.max(0, handledAtMs - handle.taskCreatedAt) : void 0;
|
|
103
|
+
span.setAttribute("robotrock.task_id", input.taskId);
|
|
104
|
+
span.setAttribute("robotrock.action.id", input.action.id);
|
|
105
|
+
if (input.action.title) {
|
|
106
|
+
span.setAttribute("robotrock.action.title", input.action.title);
|
|
107
|
+
}
|
|
108
|
+
if (input.handledBy) {
|
|
109
|
+
span.setAttribute("robotrock.handled_by", input.handledBy);
|
|
110
|
+
}
|
|
111
|
+
span.setAttribute("robotrock.handled_at", new Date(handledAtMs).toISOString());
|
|
112
|
+
if (humanWaitMs != null) {
|
|
113
|
+
span.setAttribute("robotrock.human_wait_ms", humanWaitMs);
|
|
114
|
+
}
|
|
115
|
+
if (input.threadId) {
|
|
116
|
+
span.setAttribute("robotrock.thread_id", input.threadId);
|
|
117
|
+
}
|
|
118
|
+
const eventAttributes = {
|
|
119
|
+
"robotrock.task_id": input.taskId,
|
|
120
|
+
"robotrock.action.id": input.action.id
|
|
121
|
+
};
|
|
122
|
+
if (input.handledBy) {
|
|
123
|
+
eventAttributes["robotrock.handled_by"] = input.handledBy;
|
|
124
|
+
}
|
|
125
|
+
if (humanWaitMs != null) {
|
|
126
|
+
eventAttributes["robotrock.human_wait_ms"] = humanWaitMs;
|
|
127
|
+
}
|
|
128
|
+
if (options.includeActionData && input.action.data != null) {
|
|
129
|
+
const serialized = JSON.stringify(input.action.data);
|
|
130
|
+
const truncated = serialized.length > 512 ? `${serialized.slice(0, 512)}\u2026` : serialized;
|
|
131
|
+
span.setAttribute("robotrock.action.data", truncated);
|
|
132
|
+
eventAttributes["robotrock.action.data"] = truncated;
|
|
133
|
+
}
|
|
134
|
+
span.addEvent(HANDLED_EVENT_NAME, eventAttributes);
|
|
135
|
+
}
|
|
136
|
+
function endRobotRockHumanWaitSpan(span, handled, options = {}) {
|
|
137
|
+
if (!span) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const outcome = options.outcome ?? (handled ? "handled" : "timeout");
|
|
141
|
+
if (handled && outcome === "handled") {
|
|
142
|
+
recordRobotRockHandledToOtel(handled, {
|
|
143
|
+
span,
|
|
144
|
+
handle: options.handle,
|
|
145
|
+
includeActionData: options.includeActionData
|
|
146
|
+
});
|
|
147
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
148
|
+
} else {
|
|
149
|
+
span.setAttribute("robotrock.outcome", outcome);
|
|
150
|
+
span.setStatus({
|
|
151
|
+
code: SpanStatusCode.ERROR,
|
|
152
|
+
message: outcome === "timeout" ? "Human response timed out before validUntil" : "Human wait failed"
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
span.end();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/otel-platform.ts
|
|
159
|
+
function shouldRecordRobotRockOtel(recordOtel) {
|
|
160
|
+
if (recordOtel === true) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
if (recordOtel === false) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
const env = process.env.ROBOTROCK_OTEL_RECORD_HANDLED;
|
|
167
|
+
return env === "true" || env === "1";
|
|
168
|
+
}
|
|
169
|
+
function stripPlatformOtelFields(payload) {
|
|
170
|
+
const { recordOtel: _recordOtel, otelIncludeActionData: _otelIncludeActionData, ...rest } = payload;
|
|
171
|
+
return rest;
|
|
172
|
+
}
|
|
173
|
+
function beginRobotRockHumanWaitOtel(task2, options = {}) {
|
|
174
|
+
const recordOtel = shouldRecordRobotRockOtel(options.recordOtel);
|
|
175
|
+
if (!recordOtel) {
|
|
176
|
+
return { recordOtel: false };
|
|
177
|
+
}
|
|
178
|
+
const handle = captureRobotRockOtelHandle(task2);
|
|
179
|
+
const waitSpan = startRobotRockHumanWaitSpan(handle);
|
|
180
|
+
return {
|
|
181
|
+
recordOtel: true,
|
|
182
|
+
handle,
|
|
183
|
+
waitSpan,
|
|
184
|
+
includeActionData: options.otelIncludeActionData
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function finishRobotRockHumanWaitOtel(session, handled, outcome) {
|
|
188
|
+
if (!session.recordOtel) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
endRobotRockHumanWaitSpan(session.waitSpan, handled, {
|
|
192
|
+
handle: session.handle,
|
|
193
|
+
outcome,
|
|
194
|
+
includeActionData: session.includeActionData
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
4
198
|
// src/schemas/index.ts
|
|
5
199
|
import { z as z2 } from "zod";
|
|
6
200
|
|
|
@@ -167,12 +361,12 @@ function validateUrlValue(value, widget) {
|
|
|
167
361
|
}
|
|
168
362
|
return null;
|
|
169
363
|
}
|
|
170
|
-
function validateContextPublicUrls(
|
|
171
|
-
if (!
|
|
364
|
+
function validateContextPublicUrls(context2) {
|
|
365
|
+
if (!context2?.data) {
|
|
172
366
|
return null;
|
|
173
367
|
}
|
|
174
|
-
for (const [field, value] of Object.entries(
|
|
175
|
-
const widget = widgetType(
|
|
368
|
+
for (const [field, value] of Object.entries(context2.data)) {
|
|
369
|
+
const widget = widgetType(context2.ui, field);
|
|
176
370
|
if (!widget) {
|
|
177
371
|
continue;
|
|
178
372
|
}
|
|
@@ -227,7 +421,8 @@ var contextDataSchema = z.object({
|
|
|
227
421
|
data: z.record(z.string(), z.unknown()),
|
|
228
422
|
ui: contextUiSchema
|
|
229
423
|
}).optional();
|
|
230
|
-
var
|
|
424
|
+
var TASK_CONTEXT_FORMAT_VERSION = 2;
|
|
425
|
+
var taskContextObjectBaseSchema = z.object({
|
|
231
426
|
/** Source application id; omitted tasks are grouped in the default inbox. */
|
|
232
427
|
app: z.string().min(1).optional(),
|
|
233
428
|
type: z.string().min(1),
|
|
@@ -235,9 +430,22 @@ var taskContextObjectSchema = z.object({
|
|
|
235
430
|
description: z.string().optional(),
|
|
236
431
|
validUntil: z.string().optional(),
|
|
237
432
|
context: contextDataSchema,
|
|
433
|
+
/** Task context wire format version. @default 2 */
|
|
434
|
+
contextVersion: z.literal(2).optional(),
|
|
435
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
238
436
|
version: z.literal(2).optional(),
|
|
239
437
|
actions: z.array(taskActionSchema).min(1, "At least one action is required")
|
|
240
438
|
});
|
|
439
|
+
function normalizeTaskContextVersion(data) {
|
|
440
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
441
|
+
return {
|
|
442
|
+
...rest,
|
|
443
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
var taskContextObjectSchema = taskContextObjectBaseSchema.transform(
|
|
447
|
+
normalizeTaskContextVersion
|
|
448
|
+
);
|
|
241
449
|
function refineContextPublicUrls(data, ctx) {
|
|
242
450
|
const error = validateContextPublicUrls(data.context);
|
|
243
451
|
if (error) {
|
|
@@ -281,61 +489,11 @@ var threadUpdateInputSchema = z.object({
|
|
|
281
489
|
});
|
|
282
490
|
var taskPriorities = ["low", "normal", "high", "urgent"];
|
|
283
491
|
var taskPrioritySchema = z.enum(taskPriorities);
|
|
284
|
-
var nonNegativeInt = z.number().int().nonnegative();
|
|
285
|
-
var agentCostTokensSchema = z.object({
|
|
286
|
-
input: nonNegativeInt.optional(),
|
|
287
|
-
output: nonNegativeInt.optional(),
|
|
288
|
-
total: nonNegativeInt.optional()
|
|
289
|
-
});
|
|
290
|
-
var agentCostSchema = z.object({
|
|
291
|
-
tokens: agentCostTokensSchema.optional(),
|
|
292
|
-
eur: z.number().nonnegative().optional(),
|
|
293
|
-
usd: z.number().nonnegative().optional()
|
|
294
|
-
});
|
|
295
|
-
var AGENT_INFO_MAX_KEYS = 32;
|
|
296
|
-
var AGENT_TOOL_CALLS_MAX_KEYS = 64;
|
|
297
|
-
var AGENT_OTEL_SPANS_MAX = 32;
|
|
298
|
-
var agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
|
|
299
|
-
var agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
|
|
300
|
-
var agentOtelSpanSummarySchema = z.object({
|
|
301
|
-
name: z.string().min(1),
|
|
302
|
-
durationMs: z.number().nonnegative(),
|
|
303
|
-
status: agentOtelSpanStatusSchema
|
|
304
|
-
});
|
|
305
|
-
var agentOtelSchema = z.object({
|
|
306
|
-
traceId: z.string().min(1),
|
|
307
|
-
spanId: z.string().min(1).optional(),
|
|
308
|
-
rootDurationMs: z.number().nonnegative().optional(),
|
|
309
|
-
spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
|
|
310
|
-
});
|
|
311
492
|
var agentTelemetrySchema = z.object({
|
|
312
493
|
/** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
|
|
313
|
-
version: z.string().min(1)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
/** Per-tool invocation counts keyed by tool name. */
|
|
317
|
-
toolCalls: agentToolCallsSchema.optional(),
|
|
318
|
-
cost: agentCostSchema.optional(),
|
|
319
|
-
/** Free-form metadata for experiments (model, prompt variant, etc.). */
|
|
320
|
-
info: z.record(z.string(), z.unknown()).optional(),
|
|
321
|
-
/** Structured OpenTelemetry span snapshot for feedback analysis. */
|
|
322
|
-
otel: agentOtelSchema.optional()
|
|
323
|
-
}).refine(
|
|
324
|
-
(data) => {
|
|
325
|
-
const keys = data.info ? Object.keys(data.info) : [];
|
|
326
|
-
return keys.length <= AGENT_INFO_MAX_KEYS;
|
|
327
|
-
},
|
|
328
|
-
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS} keys` }
|
|
329
|
-
).refine(
|
|
330
|
-
(data) => {
|
|
331
|
-
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
332
|
-
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS;
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS} tool names`
|
|
336
|
-
}
|
|
337
|
-
);
|
|
338
|
-
var createTaskBodySchema = taskContextObjectSchema.extend({
|
|
494
|
+
version: z.string().min(1)
|
|
495
|
+
});
|
|
496
|
+
var createTaskBodySchema = taskContextObjectBaseSchema.extend({
|
|
339
497
|
assignTo: assignToSchema.optional(),
|
|
340
498
|
/**
|
|
341
499
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -352,9 +510,9 @@ var createTaskBodySchema = taskContextObjectSchema.extend({
|
|
|
352
510
|
* the inbox status bar and the thread update log.
|
|
353
511
|
*/
|
|
354
512
|
update: threadUpdateInputSchema.optional(),
|
|
355
|
-
/** Agent
|
|
513
|
+
/** Agent release version — not shown in inbox UI. */
|
|
356
514
|
agent: agentTelemetrySchema.optional()
|
|
357
|
-
}).superRefine(refineContextPublicUrls);
|
|
515
|
+
}).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
|
|
358
516
|
|
|
359
517
|
// src/schemas/index.ts
|
|
360
518
|
var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
|
|
@@ -398,16 +556,29 @@ var contextDataSchema2 = z2.object({
|
|
|
398
556
|
data: z2.record(z2.string(), z2.unknown()),
|
|
399
557
|
ui: contextUiSchema2
|
|
400
558
|
}).optional();
|
|
401
|
-
var
|
|
559
|
+
var TASK_CONTEXT_FORMAT_VERSION2 = 2;
|
|
560
|
+
var taskContextObjectBaseSchema2 = z2.object({
|
|
402
561
|
app: z2.string().min(1).optional(),
|
|
403
562
|
type: z2.string().min(1),
|
|
404
563
|
name: z2.string().min(1),
|
|
405
564
|
description: z2.string().optional(),
|
|
406
565
|
validUntil: z2.string().optional(),
|
|
407
566
|
context: contextDataSchema2,
|
|
567
|
+
contextVersion: z2.literal(2).optional(),
|
|
568
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
408
569
|
version: z2.literal(2).optional(),
|
|
409
570
|
actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
|
|
410
571
|
});
|
|
572
|
+
function normalizeTaskContextVersion2(data) {
|
|
573
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
574
|
+
return {
|
|
575
|
+
...rest,
|
|
576
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION2
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
var taskContextObjectSchema2 = taskContextObjectBaseSchema2.transform(
|
|
580
|
+
normalizeTaskContextVersion2
|
|
581
|
+
);
|
|
411
582
|
function refineContextPublicUrls2(data, ctx) {
|
|
412
583
|
const error = validateContextPublicUrls(data.context);
|
|
413
584
|
if (error) {
|
|
@@ -451,56 +622,10 @@ var threadUpdateInputSchema2 = z2.object({
|
|
|
451
622
|
});
|
|
452
623
|
var taskPriorities2 = ["low", "normal", "high", "urgent"];
|
|
453
624
|
var taskPrioritySchema2 = z2.enum(taskPriorities2);
|
|
454
|
-
var nonNegativeInt2 = z2.number().int().nonnegative();
|
|
455
|
-
var agentCostTokensSchema2 = z2.object({
|
|
456
|
-
input: nonNegativeInt2.optional(),
|
|
457
|
-
output: nonNegativeInt2.optional(),
|
|
458
|
-
total: nonNegativeInt2.optional()
|
|
459
|
-
});
|
|
460
|
-
var agentCostSchema2 = z2.object({
|
|
461
|
-
tokens: agentCostTokensSchema2.optional(),
|
|
462
|
-
eur: z2.number().nonnegative().optional(),
|
|
463
|
-
usd: z2.number().nonnegative().optional()
|
|
464
|
-
});
|
|
465
|
-
var AGENT_INFO_MAX_KEYS2 = 32;
|
|
466
|
-
var AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
|
|
467
|
-
var AGENT_OTEL_SPANS_MAX2 = 32;
|
|
468
|
-
var agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
|
|
469
|
-
var agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
|
|
470
|
-
var agentOtelSpanSummarySchema2 = z2.object({
|
|
471
|
-
name: z2.string().min(1),
|
|
472
|
-
durationMs: z2.number().nonnegative(),
|
|
473
|
-
status: agentOtelSpanStatusSchema2
|
|
474
|
-
});
|
|
475
|
-
var agentOtelSchema2 = z2.object({
|
|
476
|
-
traceId: z2.string().min(1),
|
|
477
|
-
spanId: z2.string().min(1).optional(),
|
|
478
|
-
rootDurationMs: z2.number().nonnegative().optional(),
|
|
479
|
-
spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
|
|
480
|
-
});
|
|
481
625
|
var agentTelemetrySchema2 = z2.object({
|
|
482
|
-
version: z2.string().min(1)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
cost: agentCostSchema2.optional(),
|
|
486
|
-
info: z2.record(z2.string(), z2.unknown()).optional(),
|
|
487
|
-
otel: agentOtelSchema2.optional()
|
|
488
|
-
}).refine(
|
|
489
|
-
(data) => {
|
|
490
|
-
const keys = data.info ? Object.keys(data.info) : [];
|
|
491
|
-
return keys.length <= AGENT_INFO_MAX_KEYS2;
|
|
492
|
-
},
|
|
493
|
-
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS2} keys` }
|
|
494
|
-
).refine(
|
|
495
|
-
(data) => {
|
|
496
|
-
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
497
|
-
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS2;
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS2} tool names`
|
|
501
|
-
}
|
|
502
|
-
);
|
|
503
|
-
var createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
626
|
+
version: z2.string().min(1)
|
|
627
|
+
});
|
|
628
|
+
var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
|
|
504
629
|
assignTo: assignToSchema2.optional(),
|
|
505
630
|
/**
|
|
506
631
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -518,7 +643,7 @@ var createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
|
518
643
|
*/
|
|
519
644
|
update: threadUpdateInputSchema2.optional(),
|
|
520
645
|
agent: agentTelemetrySchema2.optional()
|
|
521
|
-
}).superRefine(refineContextPublicUrls2);
|
|
646
|
+
}).transform(normalizeTaskContextVersion2).superRefine(refineContextPublicUrls2);
|
|
522
647
|
var threadUpdateBodySchema = threadUpdateInputSchema2;
|
|
523
648
|
|
|
524
649
|
// src/approval-result.ts
|
|
@@ -554,6 +679,10 @@ var DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
|
554
679
|
function sleep(ms) {
|
|
555
680
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
556
681
|
}
|
|
682
|
+
function resolveAgentVersionFromEnv() {
|
|
683
|
+
const fromEnv = process.env.AGENT_VERSION?.trim() || process.env.ROBOTROCK_AGENT_VERSION?.trim();
|
|
684
|
+
return fromEnv || void 0;
|
|
685
|
+
}
|
|
557
686
|
function parseValidUntilMs(value) {
|
|
558
687
|
if (value === void 0) {
|
|
559
688
|
return void 0;
|
|
@@ -593,7 +722,8 @@ var RobotRock = class {
|
|
|
593
722
|
apiKey;
|
|
594
723
|
baseUrl;
|
|
595
724
|
app;
|
|
596
|
-
|
|
725
|
+
agentVersion;
|
|
726
|
+
contextVersion;
|
|
597
727
|
webhook;
|
|
598
728
|
polling;
|
|
599
729
|
constructor(config) {
|
|
@@ -612,7 +742,8 @@ var RobotRock = class {
|
|
|
612
742
|
const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
|
|
613
743
|
this.baseUrl = rawBase.replace(/\/+$/, "");
|
|
614
744
|
this.app = config.app;
|
|
615
|
-
this.
|
|
745
|
+
this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
|
|
746
|
+
this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
|
|
616
747
|
this.webhook = config.webhook;
|
|
617
748
|
this.polling = config.polling ?? {};
|
|
618
749
|
}
|
|
@@ -623,15 +754,17 @@ var RobotRock = class {
|
|
|
623
754
|
const normalizedTask = normalizeSendToHumanInput(task2, {
|
|
624
755
|
webhook: this.webhook,
|
|
625
756
|
app: this.app,
|
|
626
|
-
|
|
757
|
+
contextVersion: this.contextVersion,
|
|
758
|
+
agentVersion: this.agentVersion
|
|
627
759
|
});
|
|
760
|
+
const agentVersion = task2.version ?? this.agentVersion;
|
|
628
761
|
const bodyPayload = {
|
|
629
762
|
...normalizedTask,
|
|
630
763
|
...task2.assignTo !== void 0 ? { assignTo: task2.assignTo } : {},
|
|
631
764
|
...task2.threadId !== void 0 ? { threadId: task2.threadId } : {},
|
|
632
765
|
...task2.priority !== void 0 ? { priority: task2.priority } : {},
|
|
633
766
|
...task2.update !== void 0 ? { update: task2.update } : {},
|
|
634
|
-
...
|
|
767
|
+
...agentVersion !== void 0 ? { agent: { version: agentVersion } } : {}
|
|
635
768
|
};
|
|
636
769
|
const validation = createTaskBodySchema2.safeParse(bodyPayload);
|
|
637
770
|
if (!validation.success) {
|
|
@@ -667,7 +800,8 @@ var RobotRock = class {
|
|
|
667
800
|
const normalizedTask = normalizeSendToHumanInput(task2, {
|
|
668
801
|
webhook: this.webhook,
|
|
669
802
|
app: this.app,
|
|
670
|
-
|
|
803
|
+
contextVersion: this.contextVersion,
|
|
804
|
+
agentVersion: this.agentVersion
|
|
671
805
|
});
|
|
672
806
|
const createdTaskTask = await this.createTask(task2);
|
|
673
807
|
const hasHandlers = normalizedTask.actions.some(
|
|
@@ -811,6 +945,7 @@ function normalizeSendToHumanInput(task2, clientDefaults) {
|
|
|
811
945
|
threadId: _threadId,
|
|
812
946
|
priority: _priority,
|
|
813
947
|
update: _update,
|
|
948
|
+
version: _version,
|
|
814
949
|
validUntil,
|
|
815
950
|
app: taskApp,
|
|
816
951
|
...rest
|
|
@@ -820,7 +955,7 @@ function normalizeSendToHumanInput(task2, clientDefaults) {
|
|
|
820
955
|
const app = taskApp ?? clientDefaults.app;
|
|
821
956
|
return {
|
|
822
957
|
...rest,
|
|
823
|
-
|
|
958
|
+
contextVersion: clientDefaults.contextVersion,
|
|
824
959
|
...app ? { app } : {},
|
|
825
960
|
...validUntil !== void 0 ? { validUntil: serializeValidUntil(validUntil) } : {},
|
|
826
961
|
actions: normalizedActions
|
|
@@ -940,7 +1075,7 @@ var APPROVE_BY_HUMAN_ACTIONS = [
|
|
|
940
1075
|
{ id: "decline", title: "Decline" }
|
|
941
1076
|
];
|
|
942
1077
|
async function runSendToHuman(payload) {
|
|
943
|
-
const { validUntil: validUntilInput, ...
|
|
1078
|
+
const { validUntil: validUntilInput, app, recordOtel, otelIncludeActionData, ...taskFields } = payload;
|
|
944
1079
|
const { validUntil, timeout } = resolveWaitTiming(validUntilInput);
|
|
945
1080
|
const token = await wait.createToken({ timeout });
|
|
946
1081
|
const baseConfig = resolveRobotRockConfig();
|
|
@@ -949,40 +1084,68 @@ async function runSendToHuman(payload) {
|
|
|
949
1084
|
baseUrl: baseConfig.baseUrl,
|
|
950
1085
|
...baseConfig.app ? { app: baseConfig.app } : {},
|
|
951
1086
|
...baseConfig.version ? { version: baseConfig.version } : {},
|
|
1087
|
+
...baseConfig.advanced ? { advanced: baseConfig.advanced } : {},
|
|
952
1088
|
webhook: { url: token.url }
|
|
953
1089
|
});
|
|
1090
|
+
const taskInput = stripPlatformOtelFields(taskFields);
|
|
954
1091
|
const sendResult = await client.sendToHuman({
|
|
955
1092
|
...taskInput,
|
|
956
|
-
validUntil
|
|
1093
|
+
validUntil,
|
|
1094
|
+
...app !== void 0 ? { app } : {}
|
|
957
1095
|
});
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
)
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1096
|
+
const otelSession = beginRobotRockHumanWaitOtel(sendResult.task, {
|
|
1097
|
+
recordOtel,
|
|
1098
|
+
otelIncludeActionData
|
|
1099
|
+
});
|
|
1100
|
+
let handledPayload = null;
|
|
1101
|
+
let waitOutcome = "pending";
|
|
1102
|
+
try {
|
|
1103
|
+
const outcome = await wait.forToken(token.id);
|
|
1104
|
+
if (!outcome.ok) {
|
|
1105
|
+
waitOutcome = "timeout";
|
|
1106
|
+
throw new Error(`Human response timed out before validUntil (${timeout})`);
|
|
1107
|
+
}
|
|
1108
|
+
const output = outcome.output;
|
|
1109
|
+
if (!isRobotRockHandlerWebhookPayload(output)) {
|
|
1110
|
+
waitOutcome = "error";
|
|
1111
|
+
throw new Error(
|
|
1112
|
+
"Wait token completed with unexpected payload; expected RobotRock handler body (taskId, action.id, action.data)."
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
handledPayload = output;
|
|
1116
|
+
waitOutcome = "handled";
|
|
1117
|
+
return toDiscriminatedApprovalResult(
|
|
1118
|
+
payload.actions,
|
|
1119
|
+
{
|
|
1120
|
+
id: output.taskId,
|
|
1121
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1122
|
+
status: "handled",
|
|
1123
|
+
context: sendResult.task.context,
|
|
1124
|
+
validUntil: Date.now(),
|
|
1125
|
+
handledAt: new Date(output.handledAt).getTime(),
|
|
1126
|
+
handled: {
|
|
1127
|
+
action: {
|
|
1128
|
+
id: output.action.id,
|
|
1129
|
+
data: output.action.data
|
|
1130
|
+
},
|
|
1131
|
+
handledBy: output.handledBy
|
|
1132
|
+
}
|
|
983
1133
|
}
|
|
1134
|
+
);
|
|
1135
|
+
} catch (error) {
|
|
1136
|
+
if (waitOutcome === "pending") {
|
|
1137
|
+
waitOutcome = "error";
|
|
984
1138
|
}
|
|
985
|
-
|
|
1139
|
+
throw error;
|
|
1140
|
+
} finally {
|
|
1141
|
+
if (waitOutcome !== "pending") {
|
|
1142
|
+
finishRobotRockHumanWaitOtel(
|
|
1143
|
+
otelSession,
|
|
1144
|
+
handledPayload,
|
|
1145
|
+
waitOutcome === "handled" ? "handled" : waitOutcome
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
986
1149
|
}
|
|
987
1150
|
var sendToHumanTask = task({
|
|
988
1151
|
id: "robotrock/send-to-human",
|