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/index.js
CHANGED
|
@@ -164,12 +164,12 @@ function validateUrlValue(value, widget) {
|
|
|
164
164
|
}
|
|
165
165
|
return null;
|
|
166
166
|
}
|
|
167
|
-
function validateContextPublicUrls(
|
|
168
|
-
if (!
|
|
167
|
+
function validateContextPublicUrls(context2) {
|
|
168
|
+
if (!context2?.data) {
|
|
169
169
|
return null;
|
|
170
170
|
}
|
|
171
|
-
for (const [field, value] of Object.entries(
|
|
172
|
-
const widget = widgetType(
|
|
171
|
+
for (const [field, value] of Object.entries(context2.data)) {
|
|
172
|
+
const widget = widgetType(context2.ui, field);
|
|
173
173
|
if (!widget) {
|
|
174
174
|
continue;
|
|
175
175
|
}
|
|
@@ -224,7 +224,8 @@ var contextDataSchema = z.object({
|
|
|
224
224
|
data: z.record(z.string(), z.unknown()),
|
|
225
225
|
ui: contextUiSchema
|
|
226
226
|
}).optional();
|
|
227
|
-
var
|
|
227
|
+
var TASK_CONTEXT_FORMAT_VERSION = 2;
|
|
228
|
+
var taskContextObjectBaseSchema = z.object({
|
|
228
229
|
/** Source application id; omitted tasks are grouped in the default inbox. */
|
|
229
230
|
app: z.string().min(1).optional(),
|
|
230
231
|
type: z.string().min(1),
|
|
@@ -232,9 +233,22 @@ var taskContextObjectSchema = z.object({
|
|
|
232
233
|
description: z.string().optional(),
|
|
233
234
|
validUntil: z.string().optional(),
|
|
234
235
|
context: contextDataSchema,
|
|
236
|
+
/** Task context wire format version. @default 2 */
|
|
237
|
+
contextVersion: z.literal(2).optional(),
|
|
238
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
235
239
|
version: z.literal(2).optional(),
|
|
236
240
|
actions: z.array(taskActionSchema).min(1, "At least one action is required")
|
|
237
241
|
});
|
|
242
|
+
function normalizeTaskContextVersion(data) {
|
|
243
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
244
|
+
return {
|
|
245
|
+
...rest,
|
|
246
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
var taskContextObjectSchema = taskContextObjectBaseSchema.transform(
|
|
250
|
+
normalizeTaskContextVersion
|
|
251
|
+
);
|
|
238
252
|
function refineContextPublicUrls(data, ctx) {
|
|
239
253
|
const error = validateContextPublicUrls(data.context);
|
|
240
254
|
if (error) {
|
|
@@ -278,61 +292,11 @@ var threadUpdateInputSchema = z.object({
|
|
|
278
292
|
});
|
|
279
293
|
var taskPriorities = ["low", "normal", "high", "urgent"];
|
|
280
294
|
var taskPrioritySchema = z.enum(taskPriorities);
|
|
281
|
-
var nonNegativeInt = z.number().int().nonnegative();
|
|
282
|
-
var agentCostTokensSchema = z.object({
|
|
283
|
-
input: nonNegativeInt.optional(),
|
|
284
|
-
output: nonNegativeInt.optional(),
|
|
285
|
-
total: nonNegativeInt.optional()
|
|
286
|
-
});
|
|
287
|
-
var agentCostSchema = z.object({
|
|
288
|
-
tokens: agentCostTokensSchema.optional(),
|
|
289
|
-
eur: z.number().nonnegative().optional(),
|
|
290
|
-
usd: z.number().nonnegative().optional()
|
|
291
|
-
});
|
|
292
|
-
var AGENT_INFO_MAX_KEYS = 32;
|
|
293
|
-
var AGENT_TOOL_CALLS_MAX_KEYS = 64;
|
|
294
|
-
var AGENT_OTEL_SPANS_MAX = 32;
|
|
295
|
-
var agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
|
|
296
|
-
var agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
|
|
297
|
-
var agentOtelSpanSummarySchema = z.object({
|
|
298
|
-
name: z.string().min(1),
|
|
299
|
-
durationMs: z.number().nonnegative(),
|
|
300
|
-
status: agentOtelSpanStatusSchema
|
|
301
|
-
});
|
|
302
|
-
var agentOtelSchema = z.object({
|
|
303
|
-
traceId: z.string().min(1),
|
|
304
|
-
spanId: z.string().min(1).optional(),
|
|
305
|
-
rootDurationMs: z.number().nonnegative().optional(),
|
|
306
|
-
spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
|
|
307
|
-
});
|
|
308
295
|
var agentTelemetrySchema = z.object({
|
|
309
296
|
/** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
|
|
310
|
-
version: z.string().min(1)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
/** Per-tool invocation counts keyed by tool name. */
|
|
314
|
-
toolCalls: agentToolCallsSchema.optional(),
|
|
315
|
-
cost: agentCostSchema.optional(),
|
|
316
|
-
/** Free-form metadata for experiments (model, prompt variant, etc.). */
|
|
317
|
-
info: z.record(z.string(), z.unknown()).optional(),
|
|
318
|
-
/** Structured OpenTelemetry span snapshot for feedback analysis. */
|
|
319
|
-
otel: agentOtelSchema.optional()
|
|
320
|
-
}).refine(
|
|
321
|
-
(data) => {
|
|
322
|
-
const keys = data.info ? Object.keys(data.info) : [];
|
|
323
|
-
return keys.length <= AGENT_INFO_MAX_KEYS;
|
|
324
|
-
},
|
|
325
|
-
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS} keys` }
|
|
326
|
-
).refine(
|
|
327
|
-
(data) => {
|
|
328
|
-
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
329
|
-
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS;
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS} tool names`
|
|
333
|
-
}
|
|
334
|
-
);
|
|
335
|
-
var createTaskBodySchema = taskContextObjectSchema.extend({
|
|
297
|
+
version: z.string().min(1)
|
|
298
|
+
});
|
|
299
|
+
var createTaskBodySchema = taskContextObjectBaseSchema.extend({
|
|
336
300
|
assignTo: assignToSchema.optional(),
|
|
337
301
|
/**
|
|
338
302
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -349,9 +313,9 @@ var createTaskBodySchema = taskContextObjectSchema.extend({
|
|
|
349
313
|
* the inbox status bar and the thread update log.
|
|
350
314
|
*/
|
|
351
315
|
update: threadUpdateInputSchema.optional(),
|
|
352
|
-
/** Agent
|
|
316
|
+
/** Agent release version — not shown in inbox UI. */
|
|
353
317
|
agent: agentTelemetrySchema.optional()
|
|
354
|
-
}).superRefine(refineContextPublicUrls);
|
|
318
|
+
}).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
|
|
355
319
|
|
|
356
320
|
// src/schemas/index.ts
|
|
357
321
|
var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
|
|
@@ -395,16 +359,29 @@ var contextDataSchema2 = z2.object({
|
|
|
395
359
|
data: z2.record(z2.string(), z2.unknown()),
|
|
396
360
|
ui: contextUiSchema2
|
|
397
361
|
}).optional();
|
|
398
|
-
var
|
|
362
|
+
var TASK_CONTEXT_FORMAT_VERSION2 = 2;
|
|
363
|
+
var taskContextObjectBaseSchema2 = z2.object({
|
|
399
364
|
app: z2.string().min(1).optional(),
|
|
400
365
|
type: z2.string().min(1),
|
|
401
366
|
name: z2.string().min(1),
|
|
402
367
|
description: z2.string().optional(),
|
|
403
368
|
validUntil: z2.string().optional(),
|
|
404
369
|
context: contextDataSchema2,
|
|
370
|
+
contextVersion: z2.literal(2).optional(),
|
|
371
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
405
372
|
version: z2.literal(2).optional(),
|
|
406
373
|
actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
|
|
407
374
|
});
|
|
375
|
+
function normalizeTaskContextVersion2(data) {
|
|
376
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
377
|
+
return {
|
|
378
|
+
...rest,
|
|
379
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION2
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
var taskContextObjectSchema2 = taskContextObjectBaseSchema2.transform(
|
|
383
|
+
normalizeTaskContextVersion2
|
|
384
|
+
);
|
|
408
385
|
function refineContextPublicUrls2(data, ctx) {
|
|
409
386
|
const error = validateContextPublicUrls(data.context);
|
|
410
387
|
if (error) {
|
|
@@ -457,56 +434,10 @@ var TASK_PRIORITY_RANK = {
|
|
|
457
434
|
high: 3,
|
|
458
435
|
urgent: 4
|
|
459
436
|
};
|
|
460
|
-
var nonNegativeInt2 = z2.number().int().nonnegative();
|
|
461
|
-
var agentCostTokensSchema2 = z2.object({
|
|
462
|
-
input: nonNegativeInt2.optional(),
|
|
463
|
-
output: nonNegativeInt2.optional(),
|
|
464
|
-
total: nonNegativeInt2.optional()
|
|
465
|
-
});
|
|
466
|
-
var agentCostSchema2 = z2.object({
|
|
467
|
-
tokens: agentCostTokensSchema2.optional(),
|
|
468
|
-
eur: z2.number().nonnegative().optional(),
|
|
469
|
-
usd: z2.number().nonnegative().optional()
|
|
470
|
-
});
|
|
471
|
-
var AGENT_INFO_MAX_KEYS2 = 32;
|
|
472
|
-
var AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
|
|
473
|
-
var AGENT_OTEL_SPANS_MAX2 = 32;
|
|
474
|
-
var agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
|
|
475
|
-
var agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
|
|
476
|
-
var agentOtelSpanSummarySchema2 = z2.object({
|
|
477
|
-
name: z2.string().min(1),
|
|
478
|
-
durationMs: z2.number().nonnegative(),
|
|
479
|
-
status: agentOtelSpanStatusSchema2
|
|
480
|
-
});
|
|
481
|
-
var agentOtelSchema2 = z2.object({
|
|
482
|
-
traceId: z2.string().min(1),
|
|
483
|
-
spanId: z2.string().min(1).optional(),
|
|
484
|
-
rootDurationMs: z2.number().nonnegative().optional(),
|
|
485
|
-
spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
|
|
486
|
-
});
|
|
487
437
|
var agentTelemetrySchema2 = z2.object({
|
|
488
|
-
version: z2.string().min(1)
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
cost: agentCostSchema2.optional(),
|
|
492
|
-
info: z2.record(z2.string(), z2.unknown()).optional(),
|
|
493
|
-
otel: agentOtelSchema2.optional()
|
|
494
|
-
}).refine(
|
|
495
|
-
(data) => {
|
|
496
|
-
const keys = data.info ? Object.keys(data.info) : [];
|
|
497
|
-
return keys.length <= AGENT_INFO_MAX_KEYS2;
|
|
498
|
-
},
|
|
499
|
-
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS2} keys` }
|
|
500
|
-
).refine(
|
|
501
|
-
(data) => {
|
|
502
|
-
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
503
|
-
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS2;
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS2} tool names`
|
|
507
|
-
}
|
|
508
|
-
);
|
|
509
|
-
var createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
438
|
+
version: z2.string().min(1)
|
|
439
|
+
});
|
|
440
|
+
var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
|
|
510
441
|
assignTo: assignToSchema2.optional(),
|
|
511
442
|
/**
|
|
512
443
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -524,7 +455,7 @@ var createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
|
524
455
|
*/
|
|
525
456
|
update: threadUpdateInputSchema2.optional(),
|
|
526
457
|
agent: agentTelemetrySchema2.optional()
|
|
527
|
-
}).superRefine(refineContextPublicUrls2);
|
|
458
|
+
}).transform(normalizeTaskContextVersion2).superRefine(refineContextPublicUrls2);
|
|
528
459
|
var threadUpdateBodySchema = threadUpdateInputSchema2;
|
|
529
460
|
|
|
530
461
|
// src/approval-result.ts
|
|
@@ -560,6 +491,10 @@ var DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
|
560
491
|
function sleep(ms) {
|
|
561
492
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
562
493
|
}
|
|
494
|
+
function resolveAgentVersionFromEnv() {
|
|
495
|
+
const fromEnv = process.env.AGENT_VERSION?.trim() || process.env.ROBOTROCK_AGENT_VERSION?.trim();
|
|
496
|
+
return fromEnv || void 0;
|
|
497
|
+
}
|
|
563
498
|
function parseValidUntilMs(value) {
|
|
564
499
|
if (value === void 0) {
|
|
565
500
|
return void 0;
|
|
@@ -599,7 +534,8 @@ var RobotRock = class {
|
|
|
599
534
|
apiKey;
|
|
600
535
|
baseUrl;
|
|
601
536
|
app;
|
|
602
|
-
|
|
537
|
+
agentVersion;
|
|
538
|
+
contextVersion;
|
|
603
539
|
webhook;
|
|
604
540
|
polling;
|
|
605
541
|
constructor(config) {
|
|
@@ -618,7 +554,8 @@ var RobotRock = class {
|
|
|
618
554
|
const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
|
|
619
555
|
this.baseUrl = rawBase.replace(/\/+$/, "");
|
|
620
556
|
this.app = config.app;
|
|
621
|
-
this.
|
|
557
|
+
this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
|
|
558
|
+
this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
|
|
622
559
|
this.webhook = config.webhook;
|
|
623
560
|
this.polling = config.polling ?? {};
|
|
624
561
|
}
|
|
@@ -629,15 +566,17 @@ var RobotRock = class {
|
|
|
629
566
|
const normalizedTask = normalizeSendToHumanInput(task, {
|
|
630
567
|
webhook: this.webhook,
|
|
631
568
|
app: this.app,
|
|
632
|
-
|
|
569
|
+
contextVersion: this.contextVersion,
|
|
570
|
+
agentVersion: this.agentVersion
|
|
633
571
|
});
|
|
572
|
+
const agentVersion = task.version ?? this.agentVersion;
|
|
634
573
|
const bodyPayload = {
|
|
635
574
|
...normalizedTask,
|
|
636
575
|
...task.assignTo !== void 0 ? { assignTo: task.assignTo } : {},
|
|
637
576
|
...task.threadId !== void 0 ? { threadId: task.threadId } : {},
|
|
638
577
|
...task.priority !== void 0 ? { priority: task.priority } : {},
|
|
639
578
|
...task.update !== void 0 ? { update: task.update } : {},
|
|
640
|
-
...
|
|
579
|
+
...agentVersion !== void 0 ? { agent: { version: agentVersion } } : {}
|
|
641
580
|
};
|
|
642
581
|
const validation = createTaskBodySchema2.safeParse(bodyPayload);
|
|
643
582
|
if (!validation.success) {
|
|
@@ -673,7 +612,8 @@ var RobotRock = class {
|
|
|
673
612
|
const normalizedTask = normalizeSendToHumanInput(task, {
|
|
674
613
|
webhook: this.webhook,
|
|
675
614
|
app: this.app,
|
|
676
|
-
|
|
615
|
+
contextVersion: this.contextVersion,
|
|
616
|
+
agentVersion: this.agentVersion
|
|
677
617
|
});
|
|
678
618
|
const createdTaskTask = await this.createTask(task);
|
|
679
619
|
const hasHandlers = normalizedTask.actions.some(
|
|
@@ -817,6 +757,7 @@ function normalizeSendToHumanInput(task, clientDefaults) {
|
|
|
817
757
|
threadId: _threadId,
|
|
818
758
|
priority: _priority,
|
|
819
759
|
update: _update,
|
|
760
|
+
version: _version,
|
|
820
761
|
validUntil,
|
|
821
762
|
app: taskApp,
|
|
822
763
|
...rest
|
|
@@ -826,7 +767,7 @@ function normalizeSendToHumanInput(task, clientDefaults) {
|
|
|
826
767
|
const app = taskApp ?? clientDefaults.app;
|
|
827
768
|
return {
|
|
828
769
|
...rest,
|
|
829
|
-
|
|
770
|
+
contextVersion: clientDefaults.contextVersion,
|
|
830
771
|
...app ? { app } : {},
|
|
831
772
|
...validUntil !== void 0 ? { validUntil: serializeValidUntil(validUntil) } : {},
|
|
832
773
|
actions: normalizedActions
|
|
@@ -885,6 +826,97 @@ function resolveRobotRockClient(client, configOverrides) {
|
|
|
885
826
|
return createClient(resolveRobotRockConfig(configOverrides));
|
|
886
827
|
}
|
|
887
828
|
|
|
829
|
+
// src/platform-actions.ts
|
|
830
|
+
var PLATFORM_MARK_DONE_ACTION_ID = "robotrock:mark-done";
|
|
831
|
+
var PLATFORM_REJECT_REQUEST_ACTION_ID = "robotrock:reject-request";
|
|
832
|
+
var PLATFORM_MARK_DONE_ACTION_TITLE = "Mark as done";
|
|
833
|
+
var PLATFORM_REJECT_REQUEST_ACTION_TITLE = "Reject request";
|
|
834
|
+
var PLATFORM_TERMINAL_ACTION_IDS = [
|
|
835
|
+
PLATFORM_MARK_DONE_ACTION_ID,
|
|
836
|
+
PLATFORM_REJECT_REQUEST_ACTION_ID
|
|
837
|
+
];
|
|
838
|
+
var PlatformRejectRequestError = class extends Error {
|
|
839
|
+
actionId = PLATFORM_REJECT_REQUEST_ACTION_ID;
|
|
840
|
+
feedback;
|
|
841
|
+
constructor(feedback, message) {
|
|
842
|
+
super(message ?? `Human rejected the request: ${feedback}`);
|
|
843
|
+
this.name = "PlatformRejectRequestError";
|
|
844
|
+
this.feedback = feedback;
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
function isPlatformMarkDoneAction(actionId) {
|
|
848
|
+
return actionId === PLATFORM_MARK_DONE_ACTION_ID;
|
|
849
|
+
}
|
|
850
|
+
function isPlatformRejectRequestAction(actionId) {
|
|
851
|
+
return actionId === PLATFORM_REJECT_REQUEST_ACTION_ID;
|
|
852
|
+
}
|
|
853
|
+
function isPlatformTerminalAction(actionId) {
|
|
854
|
+
return isPlatformMarkDoneAction(actionId) || isPlatformRejectRequestAction(actionId);
|
|
855
|
+
}
|
|
856
|
+
function parsePlatformRejectRequestData(data) {
|
|
857
|
+
if (data == null || typeof data !== "object") {
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
const feedback = data.feedback;
|
|
861
|
+
if (typeof feedback !== "string") {
|
|
862
|
+
return null;
|
|
863
|
+
}
|
|
864
|
+
const trimmed = feedback.trim();
|
|
865
|
+
if (!trimmed) {
|
|
866
|
+
return null;
|
|
867
|
+
}
|
|
868
|
+
return { feedback: trimmed };
|
|
869
|
+
}
|
|
870
|
+
function toHandledAt(value) {
|
|
871
|
+
if (value === void 0) {
|
|
872
|
+
return void 0;
|
|
873
|
+
}
|
|
874
|
+
return value instanceof Date ? value : new Date(value);
|
|
875
|
+
}
|
|
876
|
+
function parseHandledOutcome(input) {
|
|
877
|
+
const handledAt = toHandledAt(input.handledAt);
|
|
878
|
+
const handledBy = input.handledBy;
|
|
879
|
+
if (isPlatformMarkDoneAction(input.actionId)) {
|
|
880
|
+
return {
|
|
881
|
+
source: "platform",
|
|
882
|
+
kind: "mark-done",
|
|
883
|
+
actionId: PLATFORM_MARK_DONE_ACTION_ID,
|
|
884
|
+
data: {},
|
|
885
|
+
handledBy,
|
|
886
|
+
handledAt
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
if (isPlatformRejectRequestAction(input.actionId)) {
|
|
890
|
+
return {
|
|
891
|
+
source: "platform",
|
|
892
|
+
kind: "reject-request",
|
|
893
|
+
actionId: PLATFORM_REJECT_REQUEST_ACTION_ID,
|
|
894
|
+
data: parsePlatformRejectRequestData(input.data) ?? { feedback: "" },
|
|
895
|
+
handledBy,
|
|
896
|
+
handledAt
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
return {
|
|
900
|
+
source: "task",
|
|
901
|
+
actionId: input.actionId,
|
|
902
|
+
data: input.data ?? {},
|
|
903
|
+
handledBy,
|
|
904
|
+
handledAt
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
function assertNotPlatformRejectRequest(actionId, data) {
|
|
908
|
+
if (!isPlatformRejectRequestAction(actionId)) {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
const parsed = parsePlatformRejectRequestData(data);
|
|
912
|
+
throw new PlatformRejectRequestError(
|
|
913
|
+
parsed?.feedback ?? "No feedback provided"
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
function shouldStopAgentForHandledAction(actionId) {
|
|
917
|
+
return isPlatformTerminalAction(actionId);
|
|
918
|
+
}
|
|
919
|
+
|
|
888
920
|
// src/webhook.ts
|
|
889
921
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
890
922
|
import { z as z3 } from "zod";
|
|
@@ -900,9 +932,6 @@ var robotRockWebhookPayloadBodySchema = z3.object({
|
|
|
900
932
|
handledAt: z3.string().min(1),
|
|
901
933
|
handlerType: z3.string().min(1)
|
|
902
934
|
});
|
|
903
|
-
var robotRockWebhookPayloadSchema = robotRockWebhookPayloadBodySchema.extend({
|
|
904
|
-
headers: z3.record(z3.string(), z3.string())
|
|
905
|
-
});
|
|
906
935
|
var RobotRockWebhookError = class extends Error {
|
|
907
936
|
constructor(message, code, details) {
|
|
908
937
|
super(message);
|
|
@@ -991,14 +1020,18 @@ function normalizeHeaders(headers) {
|
|
|
991
1020
|
return result;
|
|
992
1021
|
}
|
|
993
1022
|
|
|
994
|
-
// src/
|
|
995
|
-
import {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
}
|
|
1023
|
+
// src/record-handled-to-otel.ts
|
|
1024
|
+
import {
|
|
1025
|
+
context,
|
|
1026
|
+
trace,
|
|
1027
|
+
SpanStatusCode
|
|
1028
|
+
} from "@opentelemetry/api";
|
|
1029
|
+
var TRACER_NAME = "robotrock";
|
|
1030
|
+
var WAIT_SPAN_NAME = "robotrock.wait_for_human";
|
|
1031
|
+
var HANDLED_EVENT_NAME = "robotrock.task_handled";
|
|
1032
|
+
var INVALID_TRACE_ID = "00000000000000000000000000000000";
|
|
1000
1033
|
function isValidTraceId(traceId) {
|
|
1001
|
-
return typeof traceId === "string" && traceId.length > 0 && traceId !==
|
|
1034
|
+
return typeof traceId === "string" && traceId.length > 0 && traceId !== INVALID_TRACE_ID;
|
|
1002
1035
|
}
|
|
1003
1036
|
function resolveSpanContext(span) {
|
|
1004
1037
|
const active = span ?? trace.getActiveSpan();
|
|
@@ -1008,121 +1041,217 @@ function resolveSpanContext(span) {
|
|
|
1008
1041
|
}
|
|
1009
1042
|
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
|
1010
1043
|
}
|
|
1011
|
-
function
|
|
1012
|
-
if (
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
const info = { ...options.extraInfo };
|
|
1017
|
-
if (spanCtx) {
|
|
1018
|
-
info.traceId = spanCtx.traceId;
|
|
1019
|
-
info.spanId = spanCtx.spanId;
|
|
1020
|
-
}
|
|
1021
|
-
if (options.runStartedAt != null) {
|
|
1022
|
-
const durationMs = Date.now() - options.runStartedAt;
|
|
1023
|
-
if (durationMs >= 0) {
|
|
1024
|
-
info.durationMs = durationMs;
|
|
1044
|
+
function parseTaskCreatedAt(submittedAt) {
|
|
1045
|
+
if (submittedAt) {
|
|
1046
|
+
const parsed = Date.parse(submittedAt);
|
|
1047
|
+
if (!Number.isNaN(parsed)) {
|
|
1048
|
+
return parsed;
|
|
1025
1049
|
}
|
|
1026
1050
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1051
|
+
return Date.now();
|
|
1052
|
+
}
|
|
1053
|
+
function parseHandledAtMs(handledAt) {
|
|
1054
|
+
if (handledAt instanceof Date) {
|
|
1055
|
+
return handledAt.getTime();
|
|
1030
1056
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
return void 0;
|
|
1057
|
+
if (typeof handledAt === "number") {
|
|
1058
|
+
return handledAt;
|
|
1034
1059
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
return
|
|
1060
|
+
const parsed = Date.parse(handledAt);
|
|
1061
|
+
return Number.isNaN(parsed) ? Date.now() : parsed;
|
|
1062
|
+
}
|
|
1063
|
+
function toRobotRockHandledOtelInput(handled) {
|
|
1064
|
+
if ("actionId" in handled) {
|
|
1065
|
+
return {
|
|
1066
|
+
taskId: handled.taskId,
|
|
1067
|
+
action: {
|
|
1068
|
+
id: handled.actionId,
|
|
1069
|
+
data: handled.data
|
|
1070
|
+
},
|
|
1071
|
+
handledBy: handled.handledBy,
|
|
1072
|
+
handledAt: handled.handledAt
|
|
1073
|
+
};
|
|
1041
1074
|
}
|
|
1042
|
-
return
|
|
1075
|
+
return {
|
|
1076
|
+
taskId: handled.taskId,
|
|
1077
|
+
action: {
|
|
1078
|
+
id: handled.action.id,
|
|
1079
|
+
title: handled.action.title,
|
|
1080
|
+
data: handled.action.data
|
|
1081
|
+
},
|
|
1082
|
+
handledBy: handled.handledBy,
|
|
1083
|
+
handledAt: handled.handledAt
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
function captureRobotRockOtelHandle(task, options) {
|
|
1087
|
+
const spanCtx = resolveSpanContext(options?.span);
|
|
1088
|
+
return {
|
|
1089
|
+
traceId: spanCtx?.traceId ?? "",
|
|
1090
|
+
spanId: spanCtx?.spanId ?? "",
|
|
1091
|
+
taskId: task.taskId,
|
|
1092
|
+
threadId: task.threadId,
|
|
1093
|
+
taskCreatedAt: parseTaskCreatedAt(task.submittedAt)
|
|
1094
|
+
};
|
|
1043
1095
|
}
|
|
1044
|
-
function
|
|
1045
|
-
const
|
|
1046
|
-
if (!
|
|
1096
|
+
function startRobotRockHumanWaitSpan(handle, options) {
|
|
1097
|
+
const parent = options?.span ?? trace.getActiveSpan();
|
|
1098
|
+
if (!parent) {
|
|
1047
1099
|
return void 0;
|
|
1048
1100
|
}
|
|
1049
|
-
const
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1101
|
+
const tracer = trace.getTracer(options?.tracerName ?? TRACER_NAME);
|
|
1102
|
+
const span = tracer.startSpan(
|
|
1103
|
+
WAIT_SPAN_NAME,
|
|
1104
|
+
{},
|
|
1105
|
+
trace.setSpan(context.active(), parent)
|
|
1106
|
+
);
|
|
1107
|
+
span.setAttribute("robotrock.task_id", handle.taskId);
|
|
1108
|
+
if (handle.threadId) {
|
|
1109
|
+
span.setAttribute("robotrock.thread_id", handle.threadId);
|
|
1110
|
+
}
|
|
1111
|
+
return span;
|
|
1112
|
+
}
|
|
1113
|
+
function recordRobotRockHandledToOtel(handled, options = {}) {
|
|
1114
|
+
const span = options.span ?? trace.getActiveSpan();
|
|
1115
|
+
if (!span) {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
const input = toRobotRockHandledOtelInput(handled);
|
|
1119
|
+
const handledAtMs = parseHandledAtMs(input.handledAt);
|
|
1120
|
+
const handle = options.handle;
|
|
1121
|
+
const humanWaitMs = handle != null ? Math.max(0, handledAtMs - handle.taskCreatedAt) : void 0;
|
|
1122
|
+
span.setAttribute("robotrock.task_id", input.taskId);
|
|
1123
|
+
span.setAttribute("robotrock.action.id", input.action.id);
|
|
1124
|
+
if (input.action.title) {
|
|
1125
|
+
span.setAttribute("robotrock.action.title", input.action.title);
|
|
1126
|
+
}
|
|
1127
|
+
if (input.handledBy) {
|
|
1128
|
+
span.setAttribute("robotrock.handled_by", input.handledBy);
|
|
1129
|
+
}
|
|
1130
|
+
span.setAttribute("robotrock.handled_at", new Date(handledAtMs).toISOString());
|
|
1131
|
+
if (humanWaitMs != null) {
|
|
1132
|
+
span.setAttribute("robotrock.human_wait_ms", humanWaitMs);
|
|
1133
|
+
}
|
|
1134
|
+
if (input.threadId) {
|
|
1135
|
+
span.setAttribute("robotrock.thread_id", input.threadId);
|
|
1136
|
+
}
|
|
1137
|
+
const eventAttributes = {
|
|
1138
|
+
"robotrock.task_id": input.taskId,
|
|
1139
|
+
"robotrock.action.id": input.action.id
|
|
1140
|
+
};
|
|
1141
|
+
if (input.handledBy) {
|
|
1142
|
+
eventAttributes["robotrock.handled_by"] = input.handledBy;
|
|
1055
1143
|
}
|
|
1056
|
-
if (
|
|
1057
|
-
|
|
1144
|
+
if (humanWaitMs != null) {
|
|
1145
|
+
eventAttributes["robotrock.human_wait_ms"] = humanWaitMs;
|
|
1058
1146
|
}
|
|
1059
|
-
if (
|
|
1060
|
-
|
|
1147
|
+
if (options.includeActionData && input.action.data != null) {
|
|
1148
|
+
const serialized = JSON.stringify(input.action.data);
|
|
1149
|
+
const truncated = serialized.length > 512 ? `${serialized.slice(0, 512)}\u2026` : serialized;
|
|
1150
|
+
span.setAttribute("robotrock.action.data", truncated);
|
|
1151
|
+
eventAttributes["robotrock.action.data"] = truncated;
|
|
1061
1152
|
}
|
|
1062
|
-
|
|
1153
|
+
span.addEvent(HANDLED_EVENT_NAME, eventAttributes);
|
|
1063
1154
|
}
|
|
1064
|
-
function
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
telemetry.cost = options.cost;
|
|
1155
|
+
function endRobotRockHumanWaitSpan(span, handled, options = {}) {
|
|
1156
|
+
if (!span) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
const outcome = options.outcome ?? (handled ? "handled" : "timeout");
|
|
1160
|
+
if (handled && outcome === "handled") {
|
|
1161
|
+
recordRobotRockHandledToOtel(handled, {
|
|
1162
|
+
span,
|
|
1163
|
+
handle: options.handle,
|
|
1164
|
+
includeActionData: options.includeActionData
|
|
1165
|
+
});
|
|
1166
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1167
|
+
} else {
|
|
1168
|
+
span.setAttribute("robotrock.outcome", outcome);
|
|
1169
|
+
span.setStatus({
|
|
1170
|
+
code: SpanStatusCode.ERROR,
|
|
1171
|
+
message: outcome === "timeout" ? "Human response timed out before validUntil" : "Human wait failed"
|
|
1172
|
+
});
|
|
1083
1173
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1174
|
+
span.end();
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
// src/otel-platform.ts
|
|
1178
|
+
function shouldRecordRobotRockOtel(recordOtel) {
|
|
1179
|
+
if (recordOtel === true) {
|
|
1180
|
+
return true;
|
|
1087
1181
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
telemetry.otel = otel;
|
|
1182
|
+
if (recordOtel === false) {
|
|
1183
|
+
return false;
|
|
1091
1184
|
}
|
|
1092
|
-
|
|
1185
|
+
const env = process.env.ROBOTROCK_OTEL_RECORD_HANDLED;
|
|
1186
|
+
return env === "true" || env === "1";
|
|
1093
1187
|
}
|
|
1094
|
-
function
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1097
|
-
|
|
1188
|
+
function stripPlatformOtelFields(payload) {
|
|
1189
|
+
const { recordOtel: _recordOtel, otelIncludeActionData: _otelIncludeActionData, ...rest } = payload;
|
|
1190
|
+
return rest;
|
|
1191
|
+
}
|
|
1192
|
+
function beginRobotRockHumanWaitOtel(task, options = {}) {
|
|
1193
|
+
const recordOtel = shouldRecordRobotRockOtel(options.recordOtel);
|
|
1194
|
+
if (!recordOtel) {
|
|
1195
|
+
return { recordOtel: false };
|
|
1098
1196
|
}
|
|
1099
|
-
|
|
1197
|
+
const handle = captureRobotRockOtelHandle(task);
|
|
1198
|
+
const waitSpan = startRobotRockHumanWaitSpan(handle);
|
|
1199
|
+
return {
|
|
1200
|
+
recordOtel: true,
|
|
1201
|
+
handle,
|
|
1202
|
+
waitSpan,
|
|
1203
|
+
includeActionData: options.otelIncludeActionData
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
function finishRobotRockHumanWaitOtel(session, handled, outcome) {
|
|
1207
|
+
if (!session.recordOtel) {
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
endRobotRockHumanWaitSpan(session.waitSpan, handled, {
|
|
1211
|
+
handle: session.handle,
|
|
1212
|
+
outcome,
|
|
1213
|
+
includeActionData: session.includeActionData
|
|
1214
|
+
});
|
|
1100
1215
|
}
|
|
1101
1216
|
export {
|
|
1102
|
-
AGENT_OTEL_SPANS_MAX2 as AGENT_OTEL_SPANS_MAX,
|
|
1103
1217
|
DEFAULT_TASK_PRIORITY,
|
|
1104
1218
|
DEFAULT_THREAD_UPDATE_STATUS,
|
|
1105
1219
|
LOWEST_TASK_PRIORITY,
|
|
1220
|
+
PLATFORM_MARK_DONE_ACTION_ID,
|
|
1221
|
+
PLATFORM_MARK_DONE_ACTION_TITLE,
|
|
1222
|
+
PLATFORM_REJECT_REQUEST_ACTION_ID,
|
|
1223
|
+
PLATFORM_REJECT_REQUEST_ACTION_TITLE,
|
|
1224
|
+
PLATFORM_TERMINAL_ACTION_IDS,
|
|
1225
|
+
PlatformRejectRequestError,
|
|
1106
1226
|
RobotRock,
|
|
1107
1227
|
RobotRockError,
|
|
1108
1228
|
RobotRockWebhookError,
|
|
1229
|
+
TASK_CONTEXT_FORMAT_VERSION2 as TASK_CONTEXT_FORMAT_VERSION,
|
|
1109
1230
|
TASK_PRIORITY_RANK,
|
|
1110
1231
|
TaskExpiredError,
|
|
1111
1232
|
TaskTimeoutError,
|
|
1112
|
-
agentCostSchema2 as agentCostSchema,
|
|
1113
|
-
agentCostTokensSchema2 as agentCostTokensSchema,
|
|
1114
|
-
agentOtelSchema2 as agentOtelSchema,
|
|
1115
|
-
agentOtelSpanStatusSchema2 as agentOtelSpanStatusSchema,
|
|
1116
|
-
agentOtelSpanSummarySchema2 as agentOtelSpanSummarySchema,
|
|
1117
|
-
agentTelemetryFromOtel,
|
|
1118
1233
|
agentTelemetrySchema2 as agentTelemetrySchema,
|
|
1119
|
-
|
|
1234
|
+
assertNotPlatformRejectRequest,
|
|
1120
1235
|
assignToSchema2 as assignToSchema,
|
|
1121
1236
|
attachWebhookToActions,
|
|
1237
|
+
beginRobotRockHumanWaitOtel,
|
|
1238
|
+
captureRobotRockOtelHandle,
|
|
1122
1239
|
createClient,
|
|
1123
1240
|
createTaskBodySchema2 as createTaskBodySchema,
|
|
1241
|
+
endRobotRockHumanWaitSpan,
|
|
1242
|
+
finishRobotRockHumanWaitOtel,
|
|
1243
|
+
isPlatformMarkDoneAction,
|
|
1244
|
+
isPlatformRejectRequestAction,
|
|
1245
|
+
isPlatformTerminalAction,
|
|
1246
|
+
parseHandledOutcome,
|
|
1247
|
+
parsePlatformRejectRequestData,
|
|
1248
|
+
recordRobotRockHandledToOtel,
|
|
1124
1249
|
resolveRobotRockClient,
|
|
1125
1250
|
resolveRobotRockConfig,
|
|
1251
|
+
shouldRecordRobotRockOtel,
|
|
1252
|
+
shouldStopAgentForHandledAction,
|
|
1253
|
+
startRobotRockHumanWaitSpan,
|
|
1254
|
+
stripPlatformOtelFields,
|
|
1126
1255
|
taskContextSchema2 as taskContextSchema,
|
|
1127
1256
|
taskPriorities2 as taskPriorities,
|
|
1128
1257
|
taskPrioritySchema2 as taskPrioritySchema,
|
|
@@ -1131,7 +1260,7 @@ export {
|
|
|
1131
1260
|
threadUpdateStatusSchema2 as threadUpdateStatusSchema,
|
|
1132
1261
|
threadUpdateStatuses2 as threadUpdateStatuses,
|
|
1133
1262
|
toDiscriminatedApprovalResult,
|
|
1134
|
-
|
|
1263
|
+
toRobotRockHandledOtelInput,
|
|
1135
1264
|
verifyRobotRockWebhook
|
|
1136
1265
|
};
|
|
1137
1266
|
//# sourceMappingURL=index.js.map
|