robotrock 0.8.5 → 1.0.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/dist/ai/index.d.ts +18 -7
- package/dist/ai/index.js +976 -281
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/trigger.d.ts +4 -3
- package/dist/ai/trigger.js +934 -281
- package/dist/ai/trigger.js.map +1 -1
- package/dist/ai/workflow.d.ts +15 -4
- package/dist/ai/workflow.js +854 -282
- package/dist/ai/workflow.js.map +1 -1
- package/dist/client-CzVmjXpz.d.ts +219 -0
- package/dist/index.d.ts +17 -9
- package/dist/index.js +495 -273
- package/dist/index.js.map +1 -1
- package/dist/otel-platform-DzHyHkGk.d.ts +108 -0
- package/dist/schemas/index.d.ts +172 -104
- package/dist/schemas/index.js +98 -118
- package/dist/schemas/index.js.map +1 -1
- package/dist/{tool-approval-bridge-BKDY5NAY.d.ts → tool-approval-bridge-DbwUEBHv.d.ts} +93 -2
- package/dist/trigger/index.d.ts +7 -4
- package/dist/trigger/index.js +558 -201
- package/dist/trigger/index.js.map +1 -1
- package/dist/{trigger-CsOLTjsH.d.ts → trigger-BCKBbAV7.d.ts} +64 -3
- package/dist/workflow/index.d.ts +7 -4
- package/dist/workflow/index.js +553 -199
- package/dist/workflow/index.js.map +1 -1
- package/package.json +1 -5
- package/dist/client-D-XEBOWd.d.ts +0 -137
- 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
|
}
|
|
@@ -202,13 +202,15 @@ var triggerHandlerSchema = webhookHandlerSchema.extend({
|
|
|
202
202
|
tokenId: z.string().min(1)
|
|
203
203
|
});
|
|
204
204
|
var handlerSchema = z.discriminatedUnion("type", [webhookHandlerSchema, triggerHandlerSchema]);
|
|
205
|
-
var
|
|
205
|
+
var taskActionInputSchema = z.object({
|
|
206
206
|
id: z.string().min(1),
|
|
207
207
|
title: z.string().min(1),
|
|
208
208
|
description: z.string().optional(),
|
|
209
209
|
schema: jsonSchema7Schema.optional(),
|
|
210
210
|
ui: uiSchemaSchema.optional(),
|
|
211
|
-
data: z.record(z.string(), z.unknown()).optional()
|
|
211
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
212
|
+
});
|
|
213
|
+
var taskActionSchema = taskActionInputSchema.extend({
|
|
212
214
|
// Optional handlers for this action - if present, must have at least 1
|
|
213
215
|
handlers: z.array(handlerSchema).min(1).optional()
|
|
214
216
|
});
|
|
@@ -224,7 +226,8 @@ var contextDataSchema = z.object({
|
|
|
224
226
|
data: z.record(z.string(), z.unknown()),
|
|
225
227
|
ui: contextUiSchema
|
|
226
228
|
}).optional();
|
|
227
|
-
var
|
|
229
|
+
var TASK_CONTEXT_FORMAT_VERSION = 2;
|
|
230
|
+
var taskContextObjectBaseSchema = z.object({
|
|
228
231
|
/** Source application id; omitted tasks are grouped in the default inbox. */
|
|
229
232
|
app: z.string().min(1).optional(),
|
|
230
233
|
type: z.string().min(1),
|
|
@@ -232,9 +235,22 @@ var taskContextObjectSchema = z.object({
|
|
|
232
235
|
description: z.string().optional(),
|
|
233
236
|
validUntil: z.string().optional(),
|
|
234
237
|
context: contextDataSchema,
|
|
238
|
+
/** Task context wire format version. @default 2 */
|
|
239
|
+
contextVersion: z.literal(2).optional(),
|
|
240
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
235
241
|
version: z.literal(2).optional(),
|
|
236
242
|
actions: z.array(taskActionSchema).min(1, "At least one action is required")
|
|
237
243
|
});
|
|
244
|
+
function normalizeTaskContextVersion(data) {
|
|
245
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
246
|
+
return {
|
|
247
|
+
...rest,
|
|
248
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
var taskContextObjectSchema = taskContextObjectBaseSchema.transform(
|
|
252
|
+
normalizeTaskContextVersion
|
|
253
|
+
);
|
|
238
254
|
function refineContextPublicUrls(data, ctx) {
|
|
239
255
|
const error = validateContextPublicUrls(data.context);
|
|
240
256
|
if (error) {
|
|
@@ -278,61 +294,11 @@ var threadUpdateInputSchema = z.object({
|
|
|
278
294
|
});
|
|
279
295
|
var taskPriorities = ["low", "normal", "high", "urgent"];
|
|
280
296
|
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
297
|
var agentTelemetrySchema = z.object({
|
|
309
298
|
/** 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({
|
|
299
|
+
version: z.string().min(1)
|
|
300
|
+
});
|
|
301
|
+
var createTaskBodySchema = taskContextObjectBaseSchema.extend({
|
|
336
302
|
assignTo: assignToSchema.optional(),
|
|
337
303
|
/**
|
|
338
304
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -349,9 +315,59 @@ var createTaskBodySchema = taskContextObjectSchema.extend({
|
|
|
349
315
|
* the inbox status bar and the thread update log.
|
|
350
316
|
*/
|
|
351
317
|
update: threadUpdateInputSchema.optional(),
|
|
352
|
-
/** Agent
|
|
318
|
+
/** Agent release version — not shown in inbox UI. */
|
|
353
319
|
agent: agentTelemetrySchema.optional()
|
|
354
|
-
}).superRefine(refineContextPublicUrls);
|
|
320
|
+
}).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
|
|
321
|
+
var agentChatSeedActionSchema = z.object({
|
|
322
|
+
/** Stable action id echoed back on submit; auto-derived from title when omitted. */
|
|
323
|
+
id: z.string().min(1).optional(),
|
|
324
|
+
title: z.string().min(1),
|
|
325
|
+
description: z.string().optional(),
|
|
326
|
+
/** JSON Schema object for the form fields. */
|
|
327
|
+
schema: z.record(z.string(), z.unknown()).optional(),
|
|
328
|
+
/** RJSF ui schema overrides (ui:widget, ui:enumNames, etc.). */
|
|
329
|
+
ui: z.record(z.string(), z.unknown()).optional(),
|
|
330
|
+
/** Optional default field values. */
|
|
331
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
332
|
+
});
|
|
333
|
+
var agentChatSeedMessageSchema = z.object({
|
|
334
|
+
role: z.enum(["user", "assistant"]),
|
|
335
|
+
text: z.string().min(1),
|
|
336
|
+
/** Optional display-name override for the message sender. */
|
|
337
|
+
senderName: z.string().min(1).optional(),
|
|
338
|
+
/**
|
|
339
|
+
* Optional structured input request rendered as a styled RobotRock action
|
|
340
|
+
* widget below the message text. Use this instead of asking the user to reply
|
|
341
|
+
* in plain text so the request is always a proper action form.
|
|
342
|
+
*/
|
|
343
|
+
requestActionInput: z.object({
|
|
344
|
+
prompt: z.string().optional(),
|
|
345
|
+
action: agentChatSeedActionSchema
|
|
346
|
+
}).optional()
|
|
347
|
+
});
|
|
348
|
+
var createAgentChatBodySchema = z.object({
|
|
349
|
+
/** Trigger chat agent id (task slug). Required unless `parentChatId` is set. */
|
|
350
|
+
agentIdentifier: z.string().min(1).optional(),
|
|
351
|
+
/** Inherit tenant/connection/agent from an existing chat (agent-spawned chats). */
|
|
352
|
+
parentChatId: z.string().min(1).optional(),
|
|
353
|
+
/** Convex tenantTriggerConnections id; resolved from the tenant when omitted. */
|
|
354
|
+
connectionId: z.string().min(1).optional(),
|
|
355
|
+
/** Source application id; groups the chat under an inbox section. */
|
|
356
|
+
app: z.string().min(1).optional(),
|
|
357
|
+
assignTo: assignToSchema.optional(),
|
|
358
|
+
title: z.string().min(1),
|
|
359
|
+
messages: z.array(agentChatSeedMessageSchema).default([]),
|
|
360
|
+
/** Provenance label stored on the session ("cron" | "agent" | ...). */
|
|
361
|
+
source: z.string().min(1).optional()
|
|
362
|
+
}).refine((data) => Boolean(data.agentIdentifier || data.parentChatId), {
|
|
363
|
+
message: "Provide either agentIdentifier or parentChatId"
|
|
364
|
+
});
|
|
365
|
+
var agentChatTransportBodySchema = z.object({
|
|
366
|
+
chatId: z.string().min(1),
|
|
367
|
+
publicAccessToken: z.string().min(1),
|
|
368
|
+
lastEventId: z.string().optional(),
|
|
369
|
+
isStreaming: z.boolean().optional()
|
|
370
|
+
});
|
|
355
371
|
|
|
356
372
|
// src/schemas/index.ts
|
|
357
373
|
var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
|
|
@@ -374,13 +390,15 @@ var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
|
|
|
374
390
|
tokenId: z2.string().min(1)
|
|
375
391
|
});
|
|
376
392
|
var handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
|
|
377
|
-
var
|
|
393
|
+
var taskActionInputSchema2 = z2.object({
|
|
378
394
|
id: z2.string().min(1),
|
|
379
395
|
title: z2.string().min(1),
|
|
380
396
|
description: z2.string().optional(),
|
|
381
397
|
schema: jsonSchema7Schema2.optional(),
|
|
382
398
|
ui: uiSchemaSchema2.optional(),
|
|
383
|
-
data: z2.record(z2.string(), z2.unknown()).optional()
|
|
399
|
+
data: z2.record(z2.string(), z2.unknown()).optional()
|
|
400
|
+
});
|
|
401
|
+
var taskActionSchema2 = taskActionInputSchema2.extend({
|
|
384
402
|
handlers: z2.array(handlerSchema2).min(1).optional()
|
|
385
403
|
});
|
|
386
404
|
var uiFieldSchemaSchema2 = z2.object({
|
|
@@ -395,16 +413,29 @@ var contextDataSchema2 = z2.object({
|
|
|
395
413
|
data: z2.record(z2.string(), z2.unknown()),
|
|
396
414
|
ui: contextUiSchema2
|
|
397
415
|
}).optional();
|
|
398
|
-
var
|
|
416
|
+
var TASK_CONTEXT_FORMAT_VERSION2 = 2;
|
|
417
|
+
var taskContextObjectBaseSchema2 = z2.object({
|
|
399
418
|
app: z2.string().min(1).optional(),
|
|
400
419
|
type: z2.string().min(1),
|
|
401
420
|
name: z2.string().min(1),
|
|
402
421
|
description: z2.string().optional(),
|
|
403
422
|
validUntil: z2.string().optional(),
|
|
404
423
|
context: contextDataSchema2,
|
|
424
|
+
contextVersion: z2.literal(2).optional(),
|
|
425
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
405
426
|
version: z2.literal(2).optional(),
|
|
406
427
|
actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
|
|
407
428
|
});
|
|
429
|
+
function normalizeTaskContextVersion2(data) {
|
|
430
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
431
|
+
return {
|
|
432
|
+
...rest,
|
|
433
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION2
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
var taskContextObjectSchema2 = taskContextObjectBaseSchema2.transform(
|
|
437
|
+
normalizeTaskContextVersion2
|
|
438
|
+
);
|
|
408
439
|
function refineContextPublicUrls2(data, ctx) {
|
|
409
440
|
const error = validateContextPublicUrls(data.context);
|
|
410
441
|
if (error) {
|
|
@@ -457,56 +488,10 @@ var TASK_PRIORITY_RANK = {
|
|
|
457
488
|
high: 3,
|
|
458
489
|
urgent: 4
|
|
459
490
|
};
|
|
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
491
|
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({
|
|
492
|
+
version: z2.string().min(1)
|
|
493
|
+
});
|
|
494
|
+
var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
|
|
510
495
|
assignTo: assignToSchema2.optional(),
|
|
511
496
|
/**
|
|
512
497
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -524,7 +509,7 @@ var createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
|
524
509
|
*/
|
|
525
510
|
update: threadUpdateInputSchema2.optional(),
|
|
526
511
|
agent: agentTelemetrySchema2.optional()
|
|
527
|
-
}).superRefine(refineContextPublicUrls2);
|
|
512
|
+
}).transform(normalizeTaskContextVersion2).superRefine(refineContextPublicUrls2);
|
|
528
513
|
var threadUpdateBodySchema = threadUpdateInputSchema2;
|
|
529
514
|
|
|
530
515
|
// src/approval-result.ts
|
|
@@ -554,12 +539,159 @@ function toDiscriminatedApprovalResult(actions, task) {
|
|
|
554
539
|
};
|
|
555
540
|
}
|
|
556
541
|
|
|
542
|
+
// src/http.ts
|
|
543
|
+
var RobotRockError = class extends Error {
|
|
544
|
+
constructor(message, statusCode, response) {
|
|
545
|
+
super(message);
|
|
546
|
+
this.statusCode = statusCode;
|
|
547
|
+
this.response = response;
|
|
548
|
+
this.name = "RobotRockError";
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
async function parseResponseBody(response) {
|
|
552
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
553
|
+
const bodyText = await response.text();
|
|
554
|
+
if (!bodyText) {
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
if (contentType.toLowerCase().includes("application/json")) {
|
|
558
|
+
try {
|
|
559
|
+
return JSON.parse(bodyText);
|
|
560
|
+
} catch {
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
try {
|
|
564
|
+
return JSON.parse(bodyText);
|
|
565
|
+
} catch {
|
|
566
|
+
return bodyText;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function getErrorMessage(data, fallback) {
|
|
570
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
571
|
+
const maybeMessage = data.message;
|
|
572
|
+
if (typeof maybeMessage === "string" && maybeMessage.trim()) {
|
|
573
|
+
return maybeMessage;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (typeof data === "string" && data.trim()) {
|
|
577
|
+
const compact = data.replace(/\s+/g, " ").trim();
|
|
578
|
+
const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
579
|
+
return `${fallback}. Server returned non-JSON response: ${snippet}`;
|
|
580
|
+
}
|
|
581
|
+
return fallback;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// ../core/src/handler-retry.ts
|
|
585
|
+
var HANDLER_RETRY_DELAYS_MS = [
|
|
586
|
+
6e4,
|
|
587
|
+
// 1m
|
|
588
|
+
3e5,
|
|
589
|
+
// 5m
|
|
590
|
+
18e5,
|
|
591
|
+
// 30m
|
|
592
|
+
36e5,
|
|
593
|
+
// 1h
|
|
594
|
+
216e5,
|
|
595
|
+
// 6h
|
|
596
|
+
864e5,
|
|
597
|
+
// 24h
|
|
598
|
+
1728e5
|
|
599
|
+
// 48h
|
|
600
|
+
];
|
|
601
|
+
var HANDLER_MAX_ATTEMPTS = HANDLER_RETRY_DELAYS_MS.length + 1;
|
|
602
|
+
|
|
603
|
+
// ../core/src/attribution/index.ts
|
|
604
|
+
import { z as z3 } from "zod";
|
|
605
|
+
|
|
606
|
+
// ../core/src/app-url.ts
|
|
607
|
+
var PRODUCTION_APP_URL = "https://app.robotrock.io";
|
|
608
|
+
var APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
|
|
609
|
+
|
|
610
|
+
// ../core/src/attribution/index.ts
|
|
611
|
+
var ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
|
|
612
|
+
var attributionSchema = z3.object({
|
|
613
|
+
utmSource: z3.string().optional(),
|
|
614
|
+
utmMedium: z3.string().optional(),
|
|
615
|
+
utmCampaign: z3.string().optional(),
|
|
616
|
+
utmContent: z3.string().optional(),
|
|
617
|
+
utmTerm: z3.string().optional(),
|
|
618
|
+
gclid: z3.string().optional(),
|
|
619
|
+
landingUrl: z3.string().optional(),
|
|
620
|
+
referrer: z3.string().optional(),
|
|
621
|
+
capturedAt: z3.number()
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
// src/chats.ts
|
|
625
|
+
function createChatsApi(config) {
|
|
626
|
+
const headers = () => ({
|
|
627
|
+
"Content-Type": "application/json",
|
|
628
|
+
"X-Api-Key": config.apiKey
|
|
629
|
+
});
|
|
630
|
+
return {
|
|
631
|
+
async create(input) {
|
|
632
|
+
const bodyPayload = {
|
|
633
|
+
...input,
|
|
634
|
+
app: input.app ?? config.app,
|
|
635
|
+
messages: input.messages ?? []
|
|
636
|
+
};
|
|
637
|
+
const validation = createAgentChatBodySchema.safeParse(bodyPayload);
|
|
638
|
+
if (!validation.success) {
|
|
639
|
+
throw new RobotRockError(
|
|
640
|
+
`Invalid chat: ${validation.error.issues[0]?.message}`,
|
|
641
|
+
400,
|
|
642
|
+
validation.error.issues
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
const response = await fetch(`${config.baseUrl}/agent-chats`, {
|
|
646
|
+
method: "POST",
|
|
647
|
+
headers: headers(),
|
|
648
|
+
body: JSON.stringify(validation.data)
|
|
649
|
+
});
|
|
650
|
+
const data = await parseResponseBody(response);
|
|
651
|
+
if (!response.ok) {
|
|
652
|
+
throw new RobotRockError(
|
|
653
|
+
getErrorMessage(data, "Failed to create chat"),
|
|
654
|
+
response.status,
|
|
655
|
+
data
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
const result = data;
|
|
659
|
+
return { tenantSlug: result.tenantSlug, chats: result.chats };
|
|
660
|
+
},
|
|
661
|
+
async close(chatId, options) {
|
|
662
|
+
if (!chatId) {
|
|
663
|
+
throw new RobotRockError("chatId is required to close a chat", 400);
|
|
664
|
+
}
|
|
665
|
+
const response = await fetch(
|
|
666
|
+
`${config.baseUrl}/agent-chats/${encodeURIComponent(chatId)}/close`,
|
|
667
|
+
{
|
|
668
|
+
method: "POST",
|
|
669
|
+
headers: headers(),
|
|
670
|
+
body: JSON.stringify({ reason: options?.reason })
|
|
671
|
+
}
|
|
672
|
+
);
|
|
673
|
+
if (!response.ok) {
|
|
674
|
+
const data = await parseResponseBody(response);
|
|
675
|
+
throw new RobotRockError(
|
|
676
|
+
getErrorMessage(data, "Failed to close chat"),
|
|
677
|
+
response.status,
|
|
678
|
+
data
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
|
|
557
685
|
// src/client.ts
|
|
558
686
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
559
687
|
var DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
560
688
|
function sleep(ms) {
|
|
561
689
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
562
690
|
}
|
|
691
|
+
function resolveAgentVersionFromEnv() {
|
|
692
|
+
const fromEnv = process.env.AGENT_VERSION?.trim() || process.env.ROBOTROCK_AGENT_VERSION?.trim();
|
|
693
|
+
return fromEnv || void 0;
|
|
694
|
+
}
|
|
563
695
|
function parseValidUntilMs(value) {
|
|
564
696
|
if (value === void 0) {
|
|
565
697
|
return void 0;
|
|
@@ -587,21 +719,18 @@ function serializeValidUntil(value) {
|
|
|
587
719
|
}
|
|
588
720
|
throw new RobotRockError("Invalid validUntil: expected a Date or parseable date string", 400);
|
|
589
721
|
}
|
|
590
|
-
var RobotRockError = class extends Error {
|
|
591
|
-
constructor(message, statusCode, response) {
|
|
592
|
-
super(message);
|
|
593
|
-
this.statusCode = statusCode;
|
|
594
|
-
this.response = response;
|
|
595
|
-
this.name = "RobotRockError";
|
|
596
|
-
}
|
|
597
|
-
};
|
|
598
722
|
var RobotRock = class {
|
|
599
723
|
apiKey;
|
|
600
724
|
baseUrl;
|
|
601
725
|
app;
|
|
602
|
-
|
|
726
|
+
agentVersion;
|
|
727
|
+
contextVersion;
|
|
603
728
|
webhook;
|
|
604
729
|
polling;
|
|
730
|
+
/** Task CRUD: `create`, `get`, `cancel`, `sendUpdate`. */
|
|
731
|
+
tasks;
|
|
732
|
+
/** Chat CRUD: `create`, `close`. */
|
|
733
|
+
chats;
|
|
605
734
|
constructor(config) {
|
|
606
735
|
if (config.webhook && config.polling) {
|
|
607
736
|
throw new Error(
|
|
@@ -618,26 +747,37 @@ var RobotRock = class {
|
|
|
618
747
|
const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
|
|
619
748
|
this.baseUrl = rawBase.replace(/\/+$/, "");
|
|
620
749
|
this.app = config.app;
|
|
621
|
-
this.
|
|
750
|
+
this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
|
|
751
|
+
this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
|
|
622
752
|
this.webhook = config.webhook;
|
|
623
753
|
this.polling = config.polling ?? {};
|
|
754
|
+
this.tasks = {
|
|
755
|
+
create: (task) => this.createTaskRequest(task),
|
|
756
|
+
get: (taskId) => this.getTaskById(taskId),
|
|
757
|
+
cancel: (taskId) => this.cancelTaskRequest(taskId),
|
|
758
|
+
sendUpdate: (input) => this.sendThreadUpdate(input)
|
|
759
|
+
};
|
|
760
|
+
this.chats = createChatsApi({
|
|
761
|
+
baseUrl: this.baseUrl,
|
|
762
|
+
apiKey: this.apiKey,
|
|
763
|
+
app: this.app
|
|
764
|
+
});
|
|
624
765
|
}
|
|
625
|
-
|
|
626
|
-
* Create a task via POST /v1 without waiting for a human response.
|
|
627
|
-
*/
|
|
628
|
-
async createTask(task) {
|
|
766
|
+
async createTaskRequest(task) {
|
|
629
767
|
const normalizedTask = normalizeSendToHumanInput(task, {
|
|
630
768
|
webhook: this.webhook,
|
|
631
769
|
app: this.app,
|
|
632
|
-
|
|
770
|
+
contextVersion: this.contextVersion,
|
|
771
|
+
agentVersion: this.agentVersion
|
|
633
772
|
});
|
|
773
|
+
const agentVersion = task.version ?? this.agentVersion;
|
|
634
774
|
const bodyPayload = {
|
|
635
775
|
...normalizedTask,
|
|
636
776
|
...task.assignTo !== void 0 ? { assignTo: task.assignTo } : {},
|
|
637
777
|
...task.threadId !== void 0 ? { threadId: task.threadId } : {},
|
|
638
778
|
...task.priority !== void 0 ? { priority: task.priority } : {},
|
|
639
779
|
...task.update !== void 0 ? { update: task.update } : {},
|
|
640
|
-
...
|
|
780
|
+
...agentVersion !== void 0 ? { agent: { version: agentVersion } } : {}
|
|
641
781
|
};
|
|
642
782
|
const validation = createTaskBodySchema2.safeParse(bodyPayload);
|
|
643
783
|
if (!validation.success) {
|
|
@@ -673,9 +813,10 @@ var RobotRock = class {
|
|
|
673
813
|
const normalizedTask = normalizeSendToHumanInput(task, {
|
|
674
814
|
webhook: this.webhook,
|
|
675
815
|
app: this.app,
|
|
676
|
-
|
|
816
|
+
contextVersion: this.contextVersion,
|
|
817
|
+
agentVersion: this.agentVersion
|
|
677
818
|
});
|
|
678
|
-
const createdTaskTask = await this.
|
|
819
|
+
const createdTaskTask = await this.createTaskRequest(task);
|
|
679
820
|
const hasHandlers = normalizedTask.actions.some(
|
|
680
821
|
(action) => Array.isArray(action.handlers) && action.handlers.length > 0
|
|
681
822
|
);
|
|
@@ -692,7 +833,7 @@ var RobotRock = class {
|
|
|
692
833
|
const deadline = validUntilMs !== void 0 ? Math.min(pollingDeadline, validUntilMs) : pollingDeadline;
|
|
693
834
|
const taskId = createdTaskTask.taskId;
|
|
694
835
|
while (Date.now() < deadline) {
|
|
695
|
-
const existing = await this.
|
|
836
|
+
const existing = await this.getTaskById(taskId);
|
|
696
837
|
if (existing?.status === "handled" && existing.handled) {
|
|
697
838
|
return {
|
|
698
839
|
mode: "handled",
|
|
@@ -714,10 +855,35 @@ var RobotRock = class {
|
|
|
714
855
|
}
|
|
715
856
|
throw new TaskTimeoutError(`No human response within ${timeoutMs}ms`);
|
|
716
857
|
}
|
|
858
|
+
/**
|
|
859
|
+
* Create a task via POST /v1 without waiting for a human response.
|
|
860
|
+
* @deprecated Use `client.tasks.create()` instead.
|
|
861
|
+
*/
|
|
862
|
+
async createTask(task) {
|
|
863
|
+
return this.tasks.create(task);
|
|
864
|
+
}
|
|
717
865
|
/**
|
|
718
866
|
* Get a task by public task id (returned as `task.taskId` from {@link sendToHuman}).
|
|
867
|
+
* @deprecated Use `client.tasks.get()` instead.
|
|
719
868
|
*/
|
|
720
869
|
async getTask(taskId) {
|
|
870
|
+
return this.tasks.get(taskId);
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Log a status update against a thread.
|
|
874
|
+
* @deprecated Use `client.tasks.sendUpdate()` instead.
|
|
875
|
+
*/
|
|
876
|
+
async sendUpdate(input) {
|
|
877
|
+
return this.tasks.sendUpdate(input);
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Cancel a task by public task id.
|
|
881
|
+
* @deprecated Use `client.tasks.cancel()` instead.
|
|
882
|
+
*/
|
|
883
|
+
async cancelTask(taskId) {
|
|
884
|
+
return this.tasks.cancel(taskId);
|
|
885
|
+
}
|
|
886
|
+
async getTaskById(taskId) {
|
|
721
887
|
const response = await fetch(`${this.baseUrl}/tasks/${taskId}`, {
|
|
722
888
|
method: "GET",
|
|
723
889
|
headers: {
|
|
@@ -737,11 +903,11 @@ var RobotRock = class {
|
|
|
737
903
|
}
|
|
738
904
|
return data;
|
|
739
905
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
906
|
+
async sendThreadUpdate({
|
|
907
|
+
threadId,
|
|
908
|
+
message,
|
|
909
|
+
status
|
|
910
|
+
}) {
|
|
745
911
|
if (!threadId) {
|
|
746
912
|
throw new RobotRockError("threadId is required to send an update", 400);
|
|
747
913
|
}
|
|
@@ -774,7 +940,7 @@ var RobotRock = class {
|
|
|
774
940
|
}
|
|
775
941
|
return data.update;
|
|
776
942
|
}
|
|
777
|
-
async
|
|
943
|
+
async cancelTaskRequest(taskId) {
|
|
778
944
|
const response = await fetch(`${this.baseUrl}/tasks/${taskId}/cancel`, {
|
|
779
945
|
method: "POST",
|
|
780
946
|
headers: {
|
|
@@ -817,6 +983,7 @@ function normalizeSendToHumanInput(task, clientDefaults) {
|
|
|
817
983
|
threadId: _threadId,
|
|
818
984
|
priority: _priority,
|
|
819
985
|
update: _update,
|
|
986
|
+
version: _version,
|
|
820
987
|
validUntil,
|
|
821
988
|
app: taskApp,
|
|
822
989
|
...rest
|
|
@@ -826,44 +993,12 @@ function normalizeSendToHumanInput(task, clientDefaults) {
|
|
|
826
993
|
const app = taskApp ?? clientDefaults.app;
|
|
827
994
|
return {
|
|
828
995
|
...rest,
|
|
829
|
-
|
|
996
|
+
contextVersion: clientDefaults.contextVersion,
|
|
830
997
|
...app ? { app } : {},
|
|
831
998
|
...validUntil !== void 0 ? { validUntil: serializeValidUntil(validUntil) } : {},
|
|
832
999
|
actions: normalizedActions
|
|
833
1000
|
};
|
|
834
1001
|
}
|
|
835
|
-
async function parseResponseBody(response) {
|
|
836
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
837
|
-
const bodyText = await response.text();
|
|
838
|
-
if (!bodyText) {
|
|
839
|
-
return null;
|
|
840
|
-
}
|
|
841
|
-
if (contentType.toLowerCase().includes("application/json")) {
|
|
842
|
-
try {
|
|
843
|
-
return JSON.parse(bodyText);
|
|
844
|
-
} catch {
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
try {
|
|
848
|
-
return JSON.parse(bodyText);
|
|
849
|
-
} catch {
|
|
850
|
-
return bodyText;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
function getErrorMessage(data, fallback) {
|
|
854
|
-
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
855
|
-
const maybeMessage = data.message;
|
|
856
|
-
if (typeof maybeMessage === "string" && maybeMessage.trim()) {
|
|
857
|
-
return maybeMessage;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
if (typeof data === "string" && data.trim()) {
|
|
861
|
-
const compact = data.replace(/\s+/g, " ").trim();
|
|
862
|
-
const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
863
|
-
return `${fallback}. Server returned non-JSON response: ${snippet}`;
|
|
864
|
-
}
|
|
865
|
-
return fallback;
|
|
866
|
-
}
|
|
867
1002
|
|
|
868
1003
|
// src/env.ts
|
|
869
1004
|
var DEFAULT_BASE_URL = "https://api.robotrock.io/v1";
|
|
@@ -978,21 +1113,18 @@ function shouldStopAgentForHandledAction(actionId) {
|
|
|
978
1113
|
|
|
979
1114
|
// src/webhook.ts
|
|
980
1115
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
981
|
-
import { z as
|
|
1116
|
+
import { z as z4 } from "zod";
|
|
982
1117
|
var ROBOTROCK_SIGNATURE_HEADER = "x-robotrock-signature";
|
|
983
|
-
var robotRockWebhookPayloadBodySchema =
|
|
984
|
-
taskId:
|
|
985
|
-
action:
|
|
986
|
-
id:
|
|
987
|
-
title:
|
|
988
|
-
data:
|
|
1118
|
+
var robotRockWebhookPayloadBodySchema = z4.object({
|
|
1119
|
+
taskId: z4.string().min(1),
|
|
1120
|
+
action: z4.object({
|
|
1121
|
+
id: z4.string().min(1),
|
|
1122
|
+
title: z4.string().min(1),
|
|
1123
|
+
data: z4.unknown()
|
|
989
1124
|
}),
|
|
990
|
-
handledBy:
|
|
991
|
-
handledAt:
|
|
992
|
-
handlerType:
|
|
993
|
-
});
|
|
994
|
-
var robotRockWebhookPayloadSchema = robotRockWebhookPayloadBodySchema.extend({
|
|
995
|
-
headers: z3.record(z3.string(), z3.string())
|
|
1125
|
+
handledBy: z4.string().min(1).optional(),
|
|
1126
|
+
handledAt: z4.string().min(1),
|
|
1127
|
+
handlerType: z4.string().min(1)
|
|
996
1128
|
});
|
|
997
1129
|
var RobotRockWebhookError = class extends Error {
|
|
998
1130
|
constructor(message, code, details) {
|
|
@@ -1082,14 +1214,18 @@ function normalizeHeaders(headers) {
|
|
|
1082
1214
|
return result;
|
|
1083
1215
|
}
|
|
1084
1216
|
|
|
1085
|
-
// src/
|
|
1086
|
-
import {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
}
|
|
1217
|
+
// src/record-handled-to-otel.ts
|
|
1218
|
+
import {
|
|
1219
|
+
context,
|
|
1220
|
+
trace,
|
|
1221
|
+
SpanStatusCode
|
|
1222
|
+
} from "@opentelemetry/api";
|
|
1223
|
+
var TRACER_NAME = "robotrock";
|
|
1224
|
+
var WAIT_SPAN_NAME = "robotrock.wait_for_human";
|
|
1225
|
+
var HANDLED_EVENT_NAME = "robotrock.task_handled";
|
|
1226
|
+
var INVALID_TRACE_ID = "00000000000000000000000000000000";
|
|
1091
1227
|
function isValidTraceId(traceId) {
|
|
1092
|
-
return typeof traceId === "string" && traceId.length > 0 && traceId !==
|
|
1228
|
+
return typeof traceId === "string" && traceId.length > 0 && traceId !== INVALID_TRACE_ID;
|
|
1093
1229
|
}
|
|
1094
1230
|
function resolveSpanContext(span) {
|
|
1095
1231
|
const active = span ?? trace.getActiveSpan();
|
|
@@ -1099,98 +1235,179 @@ function resolveSpanContext(span) {
|
|
|
1099
1235
|
}
|
|
1100
1236
|
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
|
1101
1237
|
}
|
|
1102
|
-
function
|
|
1103
|
-
if (
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
const info = { ...options.extraInfo };
|
|
1108
|
-
if (spanCtx) {
|
|
1109
|
-
info.traceId = spanCtx.traceId;
|
|
1110
|
-
info.spanId = spanCtx.spanId;
|
|
1111
|
-
}
|
|
1112
|
-
if (options.runStartedAt != null) {
|
|
1113
|
-
const durationMs = Date.now() - options.runStartedAt;
|
|
1114
|
-
if (durationMs >= 0) {
|
|
1115
|
-
info.durationMs = durationMs;
|
|
1238
|
+
function parseTaskCreatedAt(submittedAt) {
|
|
1239
|
+
if (submittedAt) {
|
|
1240
|
+
const parsed = Date.parse(submittedAt);
|
|
1241
|
+
if (!Number.isNaN(parsed)) {
|
|
1242
|
+
return parsed;
|
|
1116
1243
|
}
|
|
1117
1244
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1245
|
+
return Date.now();
|
|
1246
|
+
}
|
|
1247
|
+
function parseHandledAtMs(handledAt) {
|
|
1248
|
+
if (handledAt instanceof Date) {
|
|
1249
|
+
return handledAt.getTime();
|
|
1121
1250
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
return void 0;
|
|
1251
|
+
if (typeof handledAt === "number") {
|
|
1252
|
+
return handledAt;
|
|
1125
1253
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
return
|
|
1254
|
+
const parsed = Date.parse(handledAt);
|
|
1255
|
+
return Number.isNaN(parsed) ? Date.now() : parsed;
|
|
1256
|
+
}
|
|
1257
|
+
function toRobotRockHandledOtelInput(handled) {
|
|
1258
|
+
if ("actionId" in handled) {
|
|
1259
|
+
return {
|
|
1260
|
+
taskId: handled.taskId,
|
|
1261
|
+
action: {
|
|
1262
|
+
id: handled.actionId,
|
|
1263
|
+
data: handled.data
|
|
1264
|
+
},
|
|
1265
|
+
handledBy: handled.handledBy,
|
|
1266
|
+
handledAt: handled.handledAt
|
|
1267
|
+
};
|
|
1132
1268
|
}
|
|
1133
|
-
return
|
|
1269
|
+
return {
|
|
1270
|
+
taskId: handled.taskId,
|
|
1271
|
+
action: {
|
|
1272
|
+
id: handled.action.id,
|
|
1273
|
+
title: handled.action.title,
|
|
1274
|
+
data: handled.action.data
|
|
1275
|
+
},
|
|
1276
|
+
handledBy: handled.handledBy,
|
|
1277
|
+
handledAt: handled.handledAt
|
|
1278
|
+
};
|
|
1134
1279
|
}
|
|
1135
|
-
function
|
|
1136
|
-
const
|
|
1137
|
-
|
|
1280
|
+
function captureRobotRockOtelHandle(task, options) {
|
|
1281
|
+
const spanCtx = resolveSpanContext(options?.span);
|
|
1282
|
+
return {
|
|
1283
|
+
traceId: spanCtx?.traceId ?? "",
|
|
1284
|
+
spanId: spanCtx?.spanId ?? "",
|
|
1285
|
+
taskId: task.taskId,
|
|
1286
|
+
threadId: task.threadId,
|
|
1287
|
+
taskCreatedAt: parseTaskCreatedAt(task.submittedAt)
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
function startRobotRockHumanWaitSpan(handle, options) {
|
|
1291
|
+
const parent = options?.span ?? trace.getActiveSpan();
|
|
1292
|
+
if (!parent) {
|
|
1138
1293
|
return void 0;
|
|
1139
1294
|
}
|
|
1140
|
-
const
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1295
|
+
const tracer = trace.getTracer(options?.tracerName ?? TRACER_NAME);
|
|
1296
|
+
const span = tracer.startSpan(
|
|
1297
|
+
WAIT_SPAN_NAME,
|
|
1298
|
+
{},
|
|
1299
|
+
trace.setSpan(context.active(), parent)
|
|
1300
|
+
);
|
|
1301
|
+
span.setAttribute("robotrock.task_id", handle.taskId);
|
|
1302
|
+
if (handle.threadId) {
|
|
1303
|
+
span.setAttribute("robotrock.thread_id", handle.threadId);
|
|
1304
|
+
}
|
|
1305
|
+
return span;
|
|
1306
|
+
}
|
|
1307
|
+
function recordRobotRockHandledToOtel(handled, options = {}) {
|
|
1308
|
+
const span = options.span ?? trace.getActiveSpan();
|
|
1309
|
+
if (!span) {
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
const input = toRobotRockHandledOtelInput(handled);
|
|
1313
|
+
const handledAtMs = parseHandledAtMs(input.handledAt);
|
|
1314
|
+
const handle = options.handle;
|
|
1315
|
+
const humanWaitMs = handle != null ? Math.max(0, handledAtMs - handle.taskCreatedAt) : void 0;
|
|
1316
|
+
span.setAttribute("robotrock.task_id", input.taskId);
|
|
1317
|
+
span.setAttribute("robotrock.action.id", input.action.id);
|
|
1318
|
+
if (input.action.title) {
|
|
1319
|
+
span.setAttribute("robotrock.action.title", input.action.title);
|
|
1320
|
+
}
|
|
1321
|
+
if (input.handledBy) {
|
|
1322
|
+
span.setAttribute("robotrock.handled_by", input.handledBy);
|
|
1146
1323
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1324
|
+
span.setAttribute("robotrock.handled_at", new Date(handledAtMs).toISOString());
|
|
1325
|
+
if (humanWaitMs != null) {
|
|
1326
|
+
span.setAttribute("robotrock.human_wait_ms", humanWaitMs);
|
|
1149
1327
|
}
|
|
1150
|
-
if (
|
|
1151
|
-
|
|
1328
|
+
if (input.threadId) {
|
|
1329
|
+
span.setAttribute("robotrock.thread_id", input.threadId);
|
|
1152
1330
|
}
|
|
1153
|
-
|
|
1331
|
+
const eventAttributes = {
|
|
1332
|
+
"robotrock.task_id": input.taskId,
|
|
1333
|
+
"robotrock.action.id": input.action.id
|
|
1334
|
+
};
|
|
1335
|
+
if (input.handledBy) {
|
|
1336
|
+
eventAttributes["robotrock.handled_by"] = input.handledBy;
|
|
1337
|
+
}
|
|
1338
|
+
if (humanWaitMs != null) {
|
|
1339
|
+
eventAttributes["robotrock.human_wait_ms"] = humanWaitMs;
|
|
1340
|
+
}
|
|
1341
|
+
if (options.includeActionData && input.action.data != null) {
|
|
1342
|
+
const serialized = JSON.stringify(input.action.data);
|
|
1343
|
+
const truncated = serialized.length > 512 ? `${serialized.slice(0, 512)}\u2026` : serialized;
|
|
1344
|
+
span.setAttribute("robotrock.action.data", truncated);
|
|
1345
|
+
eventAttributes["robotrock.action.data"] = truncated;
|
|
1346
|
+
}
|
|
1347
|
+
span.addEvent(HANDLED_EVENT_NAME, eventAttributes);
|
|
1154
1348
|
}
|
|
1155
|
-
function
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
if (options.version) {
|
|
1159
|
-
telemetry.version = options.version;
|
|
1160
|
-
}
|
|
1161
|
-
if (options.toolCalls && Object.keys(options.toolCalls).length > 0) {
|
|
1162
|
-
telemetry.toolCalls = options.toolCalls;
|
|
1163
|
-
}
|
|
1164
|
-
if (options.toolCallCount !== void 0) {
|
|
1165
|
-
telemetry.toolCallCount = options.toolCallCount;
|
|
1166
|
-
} else if (telemetry.toolCalls) {
|
|
1167
|
-
const sum = sumToolCalls(telemetry.toolCalls);
|
|
1168
|
-
if (sum > 0) {
|
|
1169
|
-
telemetry.toolCallCount = sum;
|
|
1170
|
-
}
|
|
1349
|
+
function endRobotRockHumanWaitSpan(span, handled, options = {}) {
|
|
1350
|
+
if (!span) {
|
|
1351
|
+
return;
|
|
1171
1352
|
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1353
|
+
const outcome = options.outcome ?? (handled ? "handled" : "timeout");
|
|
1354
|
+
if (handled && outcome === "handled") {
|
|
1355
|
+
recordRobotRockHandledToOtel(handled, {
|
|
1356
|
+
span,
|
|
1357
|
+
handle: options.handle,
|
|
1358
|
+
includeActionData: options.includeActionData
|
|
1359
|
+
});
|
|
1360
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1361
|
+
} else {
|
|
1362
|
+
span.setAttribute("robotrock.outcome", outcome);
|
|
1363
|
+
span.setStatus({
|
|
1364
|
+
code: SpanStatusCode.ERROR,
|
|
1365
|
+
message: outcome === "timeout" ? "Human response timed out before validUntil" : "Human wait failed"
|
|
1366
|
+
});
|
|
1174
1367
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1368
|
+
span.end();
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
// src/otel-platform.ts
|
|
1372
|
+
function shouldRecordRobotRockOtel(recordOtel) {
|
|
1373
|
+
if (recordOtel === true) {
|
|
1374
|
+
return true;
|
|
1178
1375
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
telemetry.otel = otel;
|
|
1376
|
+
if (recordOtel === false) {
|
|
1377
|
+
return false;
|
|
1182
1378
|
}
|
|
1183
|
-
|
|
1379
|
+
const env = process.env.ROBOTROCK_OTEL_RECORD_HANDLED;
|
|
1380
|
+
return env === "true" || env === "1";
|
|
1381
|
+
}
|
|
1382
|
+
function stripPlatformOtelFields(payload) {
|
|
1383
|
+
const { recordOtel: _recordOtel, otelIncludeActionData: _otelIncludeActionData, ...rest } = payload;
|
|
1384
|
+
return rest;
|
|
1184
1385
|
}
|
|
1185
|
-
function
|
|
1186
|
-
const
|
|
1187
|
-
|
|
1188
|
-
|
|
1386
|
+
function beginRobotRockHumanWaitOtel(task, options = {}) {
|
|
1387
|
+
const recordOtel = shouldRecordRobotRockOtel(options.recordOtel);
|
|
1388
|
+
if (!recordOtel) {
|
|
1389
|
+
return { recordOtel: false };
|
|
1189
1390
|
}
|
|
1190
|
-
|
|
1391
|
+
const handle = captureRobotRockOtelHandle(task);
|
|
1392
|
+
const waitSpan = startRobotRockHumanWaitSpan(handle);
|
|
1393
|
+
return {
|
|
1394
|
+
recordOtel: true,
|
|
1395
|
+
handle,
|
|
1396
|
+
waitSpan,
|
|
1397
|
+
includeActionData: options.otelIncludeActionData
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
function finishRobotRockHumanWaitOtel(session, handled, outcome) {
|
|
1401
|
+
if (!session.recordOtel) {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
endRobotRockHumanWaitSpan(session.waitSpan, handled, {
|
|
1405
|
+
handle: session.handle,
|
|
1406
|
+
outcome,
|
|
1407
|
+
includeActionData: session.includeActionData
|
|
1408
|
+
});
|
|
1191
1409
|
}
|
|
1192
1410
|
export {
|
|
1193
|
-
AGENT_OTEL_SPANS_MAX2 as AGENT_OTEL_SPANS_MAX,
|
|
1194
1411
|
DEFAULT_TASK_PRIORITY,
|
|
1195
1412
|
DEFAULT_THREAD_UPDATE_STATUS,
|
|
1196
1413
|
LOWEST_TASK_PRIORITY,
|
|
@@ -1203,30 +1420,35 @@ export {
|
|
|
1203
1420
|
RobotRock,
|
|
1204
1421
|
RobotRockError,
|
|
1205
1422
|
RobotRockWebhookError,
|
|
1423
|
+
TASK_CONTEXT_FORMAT_VERSION2 as TASK_CONTEXT_FORMAT_VERSION,
|
|
1206
1424
|
TASK_PRIORITY_RANK,
|
|
1207
1425
|
TaskExpiredError,
|
|
1208
1426
|
TaskTimeoutError,
|
|
1209
|
-
|
|
1210
|
-
agentCostTokensSchema2 as agentCostTokensSchema,
|
|
1211
|
-
agentOtelSchema2 as agentOtelSchema,
|
|
1212
|
-
agentOtelSpanStatusSchema2 as agentOtelSpanStatusSchema,
|
|
1213
|
-
agentOtelSpanSummarySchema2 as agentOtelSpanSummarySchema,
|
|
1214
|
-
agentTelemetryFromOtel,
|
|
1427
|
+
agentChatSeedMessageSchema,
|
|
1215
1428
|
agentTelemetrySchema2 as agentTelemetrySchema,
|
|
1216
|
-
agentToolCallsSchema2 as agentToolCallsSchema,
|
|
1217
1429
|
assertNotPlatformRejectRequest,
|
|
1218
1430
|
assignToSchema2 as assignToSchema,
|
|
1219
1431
|
attachWebhookToActions,
|
|
1432
|
+
beginRobotRockHumanWaitOtel,
|
|
1433
|
+
captureRobotRockOtelHandle,
|
|
1434
|
+
createAgentChatBodySchema,
|
|
1435
|
+
createChatsApi,
|
|
1220
1436
|
createClient,
|
|
1221
1437
|
createTaskBodySchema2 as createTaskBodySchema,
|
|
1438
|
+
endRobotRockHumanWaitSpan,
|
|
1439
|
+
finishRobotRockHumanWaitOtel,
|
|
1222
1440
|
isPlatformMarkDoneAction,
|
|
1223
1441
|
isPlatformRejectRequestAction,
|
|
1224
1442
|
isPlatformTerminalAction,
|
|
1225
1443
|
parseHandledOutcome,
|
|
1226
1444
|
parsePlatformRejectRequestData,
|
|
1445
|
+
recordRobotRockHandledToOtel,
|
|
1227
1446
|
resolveRobotRockClient,
|
|
1228
1447
|
resolveRobotRockConfig,
|
|
1448
|
+
shouldRecordRobotRockOtel,
|
|
1229
1449
|
shouldStopAgentForHandledAction,
|
|
1450
|
+
startRobotRockHumanWaitSpan,
|
|
1451
|
+
stripPlatformOtelFields,
|
|
1230
1452
|
taskContextSchema2 as taskContextSchema,
|
|
1231
1453
|
taskPriorities2 as taskPriorities,
|
|
1232
1454
|
taskPrioritySchema2 as taskPrioritySchema,
|
|
@@ -1235,7 +1457,7 @@ export {
|
|
|
1235
1457
|
threadUpdateStatusSchema2 as threadUpdateStatusSchema,
|
|
1236
1458
|
threadUpdateStatuses2 as threadUpdateStatuses,
|
|
1237
1459
|
toDiscriminatedApprovalResult,
|
|
1238
|
-
|
|
1460
|
+
toRobotRockHandledOtelInput,
|
|
1239
1461
|
verifyRobotRockWebhook
|
|
1240
1462
|
};
|
|
1241
1463
|
//# sourceMappingURL=index.js.map
|