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/ai/workflow.js
CHANGED
|
@@ -259,12 +259,12 @@ function validateUrlValue(value, widget) {
|
|
|
259
259
|
}
|
|
260
260
|
return null;
|
|
261
261
|
}
|
|
262
|
-
function validateContextPublicUrls(
|
|
263
|
-
if (!
|
|
262
|
+
function validateContextPublicUrls(context2) {
|
|
263
|
+
if (!context2?.data) {
|
|
264
264
|
return null;
|
|
265
265
|
}
|
|
266
|
-
for (const [field, value] of Object.entries(
|
|
267
|
-
const widget = widgetType(
|
|
266
|
+
for (const [field, value] of Object.entries(context2.data)) {
|
|
267
|
+
const widget = widgetType(context2.ui, field);
|
|
268
268
|
if (!widget) {
|
|
269
269
|
continue;
|
|
270
270
|
}
|
|
@@ -284,6 +284,13 @@ var init_context_urls = __esm({
|
|
|
284
284
|
|
|
285
285
|
// ../core/src/schemas/task.ts
|
|
286
286
|
import { z } from "zod";
|
|
287
|
+
function normalizeTaskContextVersion(data) {
|
|
288
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
289
|
+
return {
|
|
290
|
+
...rest,
|
|
291
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION
|
|
292
|
+
};
|
|
293
|
+
}
|
|
287
294
|
function refineContextPublicUrls(data, ctx) {
|
|
288
295
|
const error = validateContextPublicUrls(data.context);
|
|
289
296
|
if (error) {
|
|
@@ -294,7 +301,7 @@ function refineContextPublicUrls(data, ctx) {
|
|
|
294
301
|
});
|
|
295
302
|
}
|
|
296
303
|
}
|
|
297
|
-
var safeUrlSchema, jsonSchema7Schema, uiSchemaSchema, webhookHandlerSchema, triggerHandlerSchema, handlerSchema, taskActionSchema, uiFieldSchemaSchema, contextUiSchema, contextDataSchema, taskContextObjectSchema, taskContextSchema, assignToSchema, threadUpdateMessageSchema, threadUpdateStatuses, threadUpdateStatusSchema, threadUpdateInputSchema, taskPriorities, taskPrioritySchema,
|
|
304
|
+
var safeUrlSchema, jsonSchema7Schema, uiSchemaSchema, webhookHandlerSchema, triggerHandlerSchema, handlerSchema, taskActionInputSchema, taskActionSchema, uiFieldSchemaSchema, contextUiSchema, contextDataSchema, TASK_CONTEXT_FORMAT_VERSION, taskContextObjectBaseSchema, taskContextObjectSchema, taskContextSchema, assignToSchema, threadUpdateMessageSchema, threadUpdateStatuses, threadUpdateStatusSchema, threadUpdateInputSchema, taskPriorities, taskPrioritySchema, agentTelemetrySchema, createTaskBodySchema, agentChatSeedActionSchema, agentChatSeedMessageSchema, createAgentChatBodySchema, agentChatTransportBodySchema;
|
|
298
305
|
var init_task = __esm({
|
|
299
306
|
"../core/src/schemas/task.ts"() {
|
|
300
307
|
"use strict";
|
|
@@ -320,13 +327,15 @@ var init_task = __esm({
|
|
|
320
327
|
tokenId: z.string().min(1)
|
|
321
328
|
});
|
|
322
329
|
handlerSchema = z.discriminatedUnion("type", [webhookHandlerSchema, triggerHandlerSchema]);
|
|
323
|
-
|
|
330
|
+
taskActionInputSchema = z.object({
|
|
324
331
|
id: z.string().min(1),
|
|
325
332
|
title: z.string().min(1),
|
|
326
333
|
description: z.string().optional(),
|
|
327
334
|
schema: jsonSchema7Schema.optional(),
|
|
328
335
|
ui: uiSchemaSchema.optional(),
|
|
329
|
-
data: z.record(z.string(), z.unknown()).optional()
|
|
336
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
337
|
+
});
|
|
338
|
+
taskActionSchema = taskActionInputSchema.extend({
|
|
330
339
|
// Optional handlers for this action - if present, must have at least 1
|
|
331
340
|
handlers: z.array(handlerSchema).min(1).optional()
|
|
332
341
|
});
|
|
@@ -342,7 +351,8 @@ var init_task = __esm({
|
|
|
342
351
|
data: z.record(z.string(), z.unknown()),
|
|
343
352
|
ui: contextUiSchema
|
|
344
353
|
}).optional();
|
|
345
|
-
|
|
354
|
+
TASK_CONTEXT_FORMAT_VERSION = 2;
|
|
355
|
+
taskContextObjectBaseSchema = z.object({
|
|
346
356
|
/** Source application id; omitted tasks are grouped in the default inbox. */
|
|
347
357
|
app: z.string().min(1).optional(),
|
|
348
358
|
type: z.string().min(1),
|
|
@@ -350,9 +360,15 @@ var init_task = __esm({
|
|
|
350
360
|
description: z.string().optional(),
|
|
351
361
|
validUntil: z.string().optional(),
|
|
352
362
|
context: contextDataSchema,
|
|
363
|
+
/** Task context wire format version. @default 2 */
|
|
364
|
+
contextVersion: z.literal(2).optional(),
|
|
365
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
353
366
|
version: z.literal(2).optional(),
|
|
354
367
|
actions: z.array(taskActionSchema).min(1, "At least one action is required")
|
|
355
368
|
});
|
|
369
|
+
taskContextObjectSchema = taskContextObjectBaseSchema.transform(
|
|
370
|
+
normalizeTaskContextVersion
|
|
371
|
+
);
|
|
356
372
|
taskContextSchema = taskContextObjectSchema.superRefine(
|
|
357
373
|
refineContextPublicUrls
|
|
358
374
|
);
|
|
@@ -386,61 +402,11 @@ var init_task = __esm({
|
|
|
386
402
|
});
|
|
387
403
|
taskPriorities = ["low", "normal", "high", "urgent"];
|
|
388
404
|
taskPrioritySchema = z.enum(taskPriorities);
|
|
389
|
-
nonNegativeInt = z.number().int().nonnegative();
|
|
390
|
-
agentCostTokensSchema = z.object({
|
|
391
|
-
input: nonNegativeInt.optional(),
|
|
392
|
-
output: nonNegativeInt.optional(),
|
|
393
|
-
total: nonNegativeInt.optional()
|
|
394
|
-
});
|
|
395
|
-
agentCostSchema = z.object({
|
|
396
|
-
tokens: agentCostTokensSchema.optional(),
|
|
397
|
-
eur: z.number().nonnegative().optional(),
|
|
398
|
-
usd: z.number().nonnegative().optional()
|
|
399
|
-
});
|
|
400
|
-
AGENT_INFO_MAX_KEYS = 32;
|
|
401
|
-
AGENT_TOOL_CALLS_MAX_KEYS = 64;
|
|
402
|
-
AGENT_OTEL_SPANS_MAX = 32;
|
|
403
|
-
agentToolCallsSchema = z.record(z.string().min(1), nonNegativeInt);
|
|
404
|
-
agentOtelSpanStatusSchema = z.enum(["ok", "error"]);
|
|
405
|
-
agentOtelSpanSummarySchema = z.object({
|
|
406
|
-
name: z.string().min(1),
|
|
407
|
-
durationMs: z.number().nonnegative(),
|
|
408
|
-
status: agentOtelSpanStatusSchema
|
|
409
|
-
});
|
|
410
|
-
agentOtelSchema = z.object({
|
|
411
|
-
traceId: z.string().min(1),
|
|
412
|
-
spanId: z.string().min(1).optional(),
|
|
413
|
-
rootDurationMs: z.number().nonnegative().optional(),
|
|
414
|
-
spans: z.array(agentOtelSpanSummarySchema).max(AGENT_OTEL_SPANS_MAX).optional()
|
|
415
|
-
});
|
|
416
405
|
agentTelemetrySchema = z.object({
|
|
417
406
|
/** Agent or app version (semver, git SHA, deploy tag — caller-defined). */
|
|
418
|
-
version: z.string().min(1)
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
/** Per-tool invocation counts keyed by tool name. */
|
|
422
|
-
toolCalls: agentToolCallsSchema.optional(),
|
|
423
|
-
cost: agentCostSchema.optional(),
|
|
424
|
-
/** Free-form metadata for experiments (model, prompt variant, etc.). */
|
|
425
|
-
info: z.record(z.string(), z.unknown()).optional(),
|
|
426
|
-
/** Structured OpenTelemetry span snapshot for feedback analysis. */
|
|
427
|
-
otel: agentOtelSchema.optional()
|
|
428
|
-
}).refine(
|
|
429
|
-
(data) => {
|
|
430
|
-
const keys = data.info ? Object.keys(data.info) : [];
|
|
431
|
-
return keys.length <= AGENT_INFO_MAX_KEYS;
|
|
432
|
-
},
|
|
433
|
-
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS} keys` }
|
|
434
|
-
).refine(
|
|
435
|
-
(data) => {
|
|
436
|
-
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
437
|
-
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS;
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS} tool names`
|
|
441
|
-
}
|
|
442
|
-
);
|
|
443
|
-
createTaskBodySchema = taskContextObjectSchema.extend({
|
|
407
|
+
version: z.string().min(1)
|
|
408
|
+
});
|
|
409
|
+
createTaskBodySchema = taskContextObjectBaseSchema.extend({
|
|
444
410
|
assignTo: assignToSchema.optional(),
|
|
445
411
|
/**
|
|
446
412
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -457,9 +423,59 @@ var init_task = __esm({
|
|
|
457
423
|
* the inbox status bar and the thread update log.
|
|
458
424
|
*/
|
|
459
425
|
update: threadUpdateInputSchema.optional(),
|
|
460
|
-
/** Agent
|
|
426
|
+
/** Agent release version — not shown in inbox UI. */
|
|
461
427
|
agent: agentTelemetrySchema.optional()
|
|
462
|
-
}).superRefine(refineContextPublicUrls);
|
|
428
|
+
}).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
|
|
429
|
+
agentChatSeedActionSchema = z.object({
|
|
430
|
+
/** Stable action id echoed back on submit; auto-derived from title when omitted. */
|
|
431
|
+
id: z.string().min(1).optional(),
|
|
432
|
+
title: z.string().min(1),
|
|
433
|
+
description: z.string().optional(),
|
|
434
|
+
/** JSON Schema object for the form fields. */
|
|
435
|
+
schema: z.record(z.string(), z.unknown()).optional(),
|
|
436
|
+
/** RJSF ui schema overrides (ui:widget, ui:enumNames, etc.). */
|
|
437
|
+
ui: z.record(z.string(), z.unknown()).optional(),
|
|
438
|
+
/** Optional default field values. */
|
|
439
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
440
|
+
});
|
|
441
|
+
agentChatSeedMessageSchema = z.object({
|
|
442
|
+
role: z.enum(["user", "assistant"]),
|
|
443
|
+
text: z.string().min(1),
|
|
444
|
+
/** Optional display-name override for the message sender. */
|
|
445
|
+
senderName: z.string().min(1).optional(),
|
|
446
|
+
/**
|
|
447
|
+
* Optional structured input request rendered as a styled RobotRock action
|
|
448
|
+
* widget below the message text. Use this instead of asking the user to reply
|
|
449
|
+
* in plain text so the request is always a proper action form.
|
|
450
|
+
*/
|
|
451
|
+
requestActionInput: z.object({
|
|
452
|
+
prompt: z.string().optional(),
|
|
453
|
+
action: agentChatSeedActionSchema
|
|
454
|
+
}).optional()
|
|
455
|
+
});
|
|
456
|
+
createAgentChatBodySchema = z.object({
|
|
457
|
+
/** Trigger chat agent id (task slug). Required unless `parentChatId` is set. */
|
|
458
|
+
agentIdentifier: z.string().min(1).optional(),
|
|
459
|
+
/** Inherit tenant/connection/agent from an existing chat (agent-spawned chats). */
|
|
460
|
+
parentChatId: z.string().min(1).optional(),
|
|
461
|
+
/** Convex tenantTriggerConnections id; resolved from the tenant when omitted. */
|
|
462
|
+
connectionId: z.string().min(1).optional(),
|
|
463
|
+
/** Source application id; groups the chat under an inbox section. */
|
|
464
|
+
app: z.string().min(1).optional(),
|
|
465
|
+
assignTo: assignToSchema.optional(),
|
|
466
|
+
title: z.string().min(1),
|
|
467
|
+
messages: z.array(agentChatSeedMessageSchema).default([]),
|
|
468
|
+
/** Provenance label stored on the session ("cron" | "agent" | ...). */
|
|
469
|
+
source: z.string().min(1).optional()
|
|
470
|
+
}).refine((data) => Boolean(data.agentIdentifier || data.parentChatId), {
|
|
471
|
+
message: "Provide either agentIdentifier or parentChatId"
|
|
472
|
+
});
|
|
473
|
+
agentChatTransportBodySchema = z.object({
|
|
474
|
+
chatId: z.string().min(1),
|
|
475
|
+
publicAccessToken: z.string().min(1),
|
|
476
|
+
lastEventId: z.string().optional(),
|
|
477
|
+
isStreaming: z.boolean().optional()
|
|
478
|
+
});
|
|
463
479
|
}
|
|
464
480
|
});
|
|
465
481
|
|
|
@@ -482,6 +498,13 @@ var init_schemas = __esm({
|
|
|
482
498
|
|
|
483
499
|
// src/schemas/index.ts
|
|
484
500
|
import { z as z2 } from "zod";
|
|
501
|
+
function normalizeTaskContextVersion2(data) {
|
|
502
|
+
const { version: legacyVersion, contextVersion, ...rest } = data;
|
|
503
|
+
return {
|
|
504
|
+
...rest,
|
|
505
|
+
contextVersion: contextVersion ?? legacyVersion ?? TASK_CONTEXT_FORMAT_VERSION2
|
|
506
|
+
};
|
|
507
|
+
}
|
|
485
508
|
function refineContextPublicUrls2(data, ctx) {
|
|
486
509
|
const error = validateContextPublicUrls(data.context);
|
|
487
510
|
if (error) {
|
|
@@ -492,7 +515,7 @@ function refineContextPublicUrls2(data, ctx) {
|
|
|
492
515
|
});
|
|
493
516
|
}
|
|
494
517
|
}
|
|
495
|
-
var safeUrlSchema2, jsonSchema7Schema2, uiSchemaSchema2, webhookHandlerSchema2, triggerHandlerSchema2, handlerSchema2, taskActionSchema2, uiFieldSchemaSchema2, contextUiSchema2, contextDataSchema2, taskContextObjectSchema2, taskContextSchema2, assignToSchema2, threadUpdateMessageSchema2, threadUpdateStatuses2, threadUpdateStatusSchema2, threadUpdateInputSchema2, taskPriorities2, taskPrioritySchema2,
|
|
518
|
+
var safeUrlSchema2, jsonSchema7Schema2, uiSchemaSchema2, webhookHandlerSchema2, triggerHandlerSchema2, handlerSchema2, taskActionInputSchema2, taskActionSchema2, uiFieldSchemaSchema2, contextUiSchema2, contextDataSchema2, TASK_CONTEXT_FORMAT_VERSION2, taskContextObjectBaseSchema2, taskContextObjectSchema2, taskContextSchema2, assignToSchema2, threadUpdateMessageSchema2, threadUpdateStatuses2, threadUpdateStatusSchema2, threadUpdateInputSchema2, taskPriorities2, taskPrioritySchema2, agentTelemetrySchema2, createTaskBodySchema2, threadUpdateBodySchema;
|
|
496
519
|
var init_schemas2 = __esm({
|
|
497
520
|
"src/schemas/index.ts"() {
|
|
498
521
|
"use strict";
|
|
@@ -518,13 +541,15 @@ var init_schemas2 = __esm({
|
|
|
518
541
|
tokenId: z2.string().min(1)
|
|
519
542
|
});
|
|
520
543
|
handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
|
|
521
|
-
|
|
544
|
+
taskActionInputSchema2 = z2.object({
|
|
522
545
|
id: z2.string().min(1),
|
|
523
546
|
title: z2.string().min(1),
|
|
524
547
|
description: z2.string().optional(),
|
|
525
548
|
schema: jsonSchema7Schema2.optional(),
|
|
526
549
|
ui: uiSchemaSchema2.optional(),
|
|
527
|
-
data: z2.record(z2.string(), z2.unknown()).optional()
|
|
550
|
+
data: z2.record(z2.string(), z2.unknown()).optional()
|
|
551
|
+
});
|
|
552
|
+
taskActionSchema2 = taskActionInputSchema2.extend({
|
|
528
553
|
handlers: z2.array(handlerSchema2).min(1).optional()
|
|
529
554
|
});
|
|
530
555
|
uiFieldSchemaSchema2 = z2.object({
|
|
@@ -539,16 +564,22 @@ var init_schemas2 = __esm({
|
|
|
539
564
|
data: z2.record(z2.string(), z2.unknown()),
|
|
540
565
|
ui: contextUiSchema2
|
|
541
566
|
}).optional();
|
|
542
|
-
|
|
567
|
+
TASK_CONTEXT_FORMAT_VERSION2 = 2;
|
|
568
|
+
taskContextObjectBaseSchema2 = z2.object({
|
|
543
569
|
app: z2.string().min(1).optional(),
|
|
544
570
|
type: z2.string().min(1),
|
|
545
571
|
name: z2.string().min(1),
|
|
546
572
|
description: z2.string().optional(),
|
|
547
573
|
validUntil: z2.string().optional(),
|
|
548
574
|
context: contextDataSchema2,
|
|
575
|
+
contextVersion: z2.literal(2).optional(),
|
|
576
|
+
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
549
577
|
version: z2.literal(2).optional(),
|
|
550
578
|
actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
|
|
551
579
|
});
|
|
580
|
+
taskContextObjectSchema2 = taskContextObjectBaseSchema2.transform(
|
|
581
|
+
normalizeTaskContextVersion2
|
|
582
|
+
);
|
|
552
583
|
taskContextSchema2 = taskContextObjectSchema2.superRefine(
|
|
553
584
|
refineContextPublicUrls2
|
|
554
585
|
);
|
|
@@ -582,56 +613,10 @@ var init_schemas2 = __esm({
|
|
|
582
613
|
});
|
|
583
614
|
taskPriorities2 = ["low", "normal", "high", "urgent"];
|
|
584
615
|
taskPrioritySchema2 = z2.enum(taskPriorities2);
|
|
585
|
-
nonNegativeInt2 = z2.number().int().nonnegative();
|
|
586
|
-
agentCostTokensSchema2 = z2.object({
|
|
587
|
-
input: nonNegativeInt2.optional(),
|
|
588
|
-
output: nonNegativeInt2.optional(),
|
|
589
|
-
total: nonNegativeInt2.optional()
|
|
590
|
-
});
|
|
591
|
-
agentCostSchema2 = z2.object({
|
|
592
|
-
tokens: agentCostTokensSchema2.optional(),
|
|
593
|
-
eur: z2.number().nonnegative().optional(),
|
|
594
|
-
usd: z2.number().nonnegative().optional()
|
|
595
|
-
});
|
|
596
|
-
AGENT_INFO_MAX_KEYS2 = 32;
|
|
597
|
-
AGENT_TOOL_CALLS_MAX_KEYS2 = 64;
|
|
598
|
-
AGENT_OTEL_SPANS_MAX2 = 32;
|
|
599
|
-
agentToolCallsSchema2 = z2.record(z2.string().min(1), nonNegativeInt2);
|
|
600
|
-
agentOtelSpanStatusSchema2 = z2.enum(["ok", "error"]);
|
|
601
|
-
agentOtelSpanSummarySchema2 = z2.object({
|
|
602
|
-
name: z2.string().min(1),
|
|
603
|
-
durationMs: z2.number().nonnegative(),
|
|
604
|
-
status: agentOtelSpanStatusSchema2
|
|
605
|
-
});
|
|
606
|
-
agentOtelSchema2 = z2.object({
|
|
607
|
-
traceId: z2.string().min(1),
|
|
608
|
-
spanId: z2.string().min(1).optional(),
|
|
609
|
-
rootDurationMs: z2.number().nonnegative().optional(),
|
|
610
|
-
spans: z2.array(agentOtelSpanSummarySchema2).max(AGENT_OTEL_SPANS_MAX2).optional()
|
|
611
|
-
});
|
|
612
616
|
agentTelemetrySchema2 = z2.object({
|
|
613
|
-
version: z2.string().min(1)
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
cost: agentCostSchema2.optional(),
|
|
617
|
-
info: z2.record(z2.string(), z2.unknown()).optional(),
|
|
618
|
-
otel: agentOtelSchema2.optional()
|
|
619
|
-
}).refine(
|
|
620
|
-
(data) => {
|
|
621
|
-
const keys = data.info ? Object.keys(data.info) : [];
|
|
622
|
-
return keys.length <= AGENT_INFO_MAX_KEYS2;
|
|
623
|
-
},
|
|
624
|
-
{ message: `agent.info may contain at most ${AGENT_INFO_MAX_KEYS2} keys` }
|
|
625
|
-
).refine(
|
|
626
|
-
(data) => {
|
|
627
|
-
const keys = data.toolCalls ? Object.keys(data.toolCalls) : [];
|
|
628
|
-
return keys.length <= AGENT_TOOL_CALLS_MAX_KEYS2;
|
|
629
|
-
},
|
|
630
|
-
{
|
|
631
|
-
message: `agent.toolCalls may contain at most ${AGENT_TOOL_CALLS_MAX_KEYS2} tool names`
|
|
632
|
-
}
|
|
633
|
-
);
|
|
634
|
-
createTaskBodySchema2 = taskContextObjectSchema2.extend({
|
|
617
|
+
version: z2.string().min(1)
|
|
618
|
+
});
|
|
619
|
+
createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
|
|
635
620
|
assignTo: assignToSchema2.optional(),
|
|
636
621
|
/**
|
|
637
622
|
* Groups related tasks together. When omitted, the server generates one and
|
|
@@ -649,7 +634,7 @@ var init_schemas2 = __esm({
|
|
|
649
634
|
*/
|
|
650
635
|
update: threadUpdateInputSchema2.optional(),
|
|
651
636
|
agent: agentTelemetrySchema2.optional()
|
|
652
|
-
}).superRefine(refineContextPublicUrls2);
|
|
637
|
+
}).transform(normalizeTaskContextVersion2).superRefine(refineContextPublicUrls2);
|
|
653
638
|
threadUpdateBodySchema = threadUpdateInputSchema2;
|
|
654
639
|
}
|
|
655
640
|
});
|
|
@@ -687,10 +672,248 @@ var init_approval_result = __esm({
|
|
|
687
672
|
}
|
|
688
673
|
});
|
|
689
674
|
|
|
675
|
+
// src/http.ts
|
|
676
|
+
async function parseResponseBody(response) {
|
|
677
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
678
|
+
const bodyText = await response.text();
|
|
679
|
+
if (!bodyText) {
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
682
|
+
if (contentType.toLowerCase().includes("application/json")) {
|
|
683
|
+
try {
|
|
684
|
+
return JSON.parse(bodyText);
|
|
685
|
+
} catch {
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
try {
|
|
689
|
+
return JSON.parse(bodyText);
|
|
690
|
+
} catch {
|
|
691
|
+
return bodyText;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
function getErrorMessage(data, fallback) {
|
|
695
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
696
|
+
const maybeMessage = data.message;
|
|
697
|
+
if (typeof maybeMessage === "string" && maybeMessage.trim()) {
|
|
698
|
+
return maybeMessage;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if (typeof data === "string" && data.trim()) {
|
|
702
|
+
const compact = data.replace(/\s+/g, " ").trim();
|
|
703
|
+
const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
704
|
+
return `${fallback}. Server returned non-JSON response: ${snippet}`;
|
|
705
|
+
}
|
|
706
|
+
return fallback;
|
|
707
|
+
}
|
|
708
|
+
var RobotRockError;
|
|
709
|
+
var init_http = __esm({
|
|
710
|
+
"src/http.ts"() {
|
|
711
|
+
"use strict";
|
|
712
|
+
RobotRockError = class extends Error {
|
|
713
|
+
constructor(message, statusCode, response) {
|
|
714
|
+
super(message);
|
|
715
|
+
this.statusCode = statusCode;
|
|
716
|
+
this.response = response;
|
|
717
|
+
this.name = "RobotRockError";
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
// ../core/src/types/task.ts
|
|
724
|
+
var init_task2 = __esm({
|
|
725
|
+
"../core/src/types/task.ts"() {
|
|
726
|
+
"use strict";
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// ../core/src/types/json-schema-infer.ts
|
|
731
|
+
var init_json_schema_infer = __esm({
|
|
732
|
+
"../core/src/types/json-schema-infer.ts"() {
|
|
733
|
+
"use strict";
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
// ../core/src/types/index.ts
|
|
738
|
+
var init_types = __esm({
|
|
739
|
+
"../core/src/types/index.ts"() {
|
|
740
|
+
"use strict";
|
|
741
|
+
init_task2();
|
|
742
|
+
init_json_schema_infer();
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
// ../core/src/plans/index.ts
|
|
747
|
+
var init_plans = __esm({
|
|
748
|
+
"../core/src/plans/index.ts"() {
|
|
749
|
+
"use strict";
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
// ../core/src/handler-retry.ts
|
|
754
|
+
var HANDLER_RETRY_DELAYS_MS, HANDLER_MAX_ATTEMPTS;
|
|
755
|
+
var init_handler_retry = __esm({
|
|
756
|
+
"../core/src/handler-retry.ts"() {
|
|
757
|
+
"use strict";
|
|
758
|
+
HANDLER_RETRY_DELAYS_MS = [
|
|
759
|
+
6e4,
|
|
760
|
+
// 1m
|
|
761
|
+
3e5,
|
|
762
|
+
// 5m
|
|
763
|
+
18e5,
|
|
764
|
+
// 30m
|
|
765
|
+
36e5,
|
|
766
|
+
// 1h
|
|
767
|
+
216e5,
|
|
768
|
+
// 6h
|
|
769
|
+
864e5,
|
|
770
|
+
// 24h
|
|
771
|
+
1728e5
|
|
772
|
+
// 48h
|
|
773
|
+
];
|
|
774
|
+
HANDLER_MAX_ATTEMPTS = HANDLER_RETRY_DELAYS_MS.length + 1;
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
// ../core/src/legal.ts
|
|
779
|
+
var init_legal = __esm({
|
|
780
|
+
"../core/src/legal.ts"() {
|
|
781
|
+
"use strict";
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
// ../core/src/welcome-task.ts
|
|
786
|
+
var init_welcome_task = __esm({
|
|
787
|
+
"../core/src/welcome-task.ts"() {
|
|
788
|
+
"use strict";
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
// ../core/src/app-url.ts
|
|
793
|
+
var PRODUCTION_APP_URL, APP_SIGNUP_URL;
|
|
794
|
+
var init_app_url = __esm({
|
|
795
|
+
"../core/src/app-url.ts"() {
|
|
796
|
+
"use strict";
|
|
797
|
+
PRODUCTION_APP_URL = "https://app.robotrock.io";
|
|
798
|
+
APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
// ../core/src/attribution/index.ts
|
|
803
|
+
import { z as z3 } from "zod";
|
|
804
|
+
var ATTRIBUTION_COOKIE_MAX_AGE, attributionSchema;
|
|
805
|
+
var init_attribution = __esm({
|
|
806
|
+
"../core/src/attribution/index.ts"() {
|
|
807
|
+
"use strict";
|
|
808
|
+
init_app_url();
|
|
809
|
+
init_app_url();
|
|
810
|
+
ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
|
|
811
|
+
attributionSchema = z3.object({
|
|
812
|
+
utmSource: z3.string().optional(),
|
|
813
|
+
utmMedium: z3.string().optional(),
|
|
814
|
+
utmCampaign: z3.string().optional(),
|
|
815
|
+
utmContent: z3.string().optional(),
|
|
816
|
+
utmTerm: z3.string().optional(),
|
|
817
|
+
gclid: z3.string().optional(),
|
|
818
|
+
landingUrl: z3.string().optional(),
|
|
819
|
+
referrer: z3.string().optional(),
|
|
820
|
+
capturedAt: z3.number()
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
// ../core/src/index.ts
|
|
826
|
+
var init_src = __esm({
|
|
827
|
+
"../core/src/index.ts"() {
|
|
828
|
+
"use strict";
|
|
829
|
+
init_schemas();
|
|
830
|
+
init_types();
|
|
831
|
+
init_utils();
|
|
832
|
+
init_plans();
|
|
833
|
+
init_handler_retry();
|
|
834
|
+
init_legal();
|
|
835
|
+
init_welcome_task();
|
|
836
|
+
init_attribution();
|
|
837
|
+
init_app_url();
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
// src/chats.ts
|
|
842
|
+
function createChatsApi(config) {
|
|
843
|
+
const headers = () => ({
|
|
844
|
+
"Content-Type": "application/json",
|
|
845
|
+
"X-Api-Key": config.apiKey
|
|
846
|
+
});
|
|
847
|
+
return {
|
|
848
|
+
async create(input) {
|
|
849
|
+
const bodyPayload = {
|
|
850
|
+
...input,
|
|
851
|
+
app: input.app ?? config.app,
|
|
852
|
+
messages: input.messages ?? []
|
|
853
|
+
};
|
|
854
|
+
const validation = createAgentChatBodySchema.safeParse(bodyPayload);
|
|
855
|
+
if (!validation.success) {
|
|
856
|
+
throw new RobotRockError(
|
|
857
|
+
`Invalid chat: ${validation.error.issues[0]?.message}`,
|
|
858
|
+
400,
|
|
859
|
+
validation.error.issues
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
const response = await fetch(`${config.baseUrl}/agent-chats`, {
|
|
863
|
+
method: "POST",
|
|
864
|
+
headers: headers(),
|
|
865
|
+
body: JSON.stringify(validation.data)
|
|
866
|
+
});
|
|
867
|
+
const data = await parseResponseBody(response);
|
|
868
|
+
if (!response.ok) {
|
|
869
|
+
throw new RobotRockError(
|
|
870
|
+
getErrorMessage(data, "Failed to create chat"),
|
|
871
|
+
response.status,
|
|
872
|
+
data
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
const result = data;
|
|
876
|
+
return { tenantSlug: result.tenantSlug, chats: result.chats };
|
|
877
|
+
},
|
|
878
|
+
async close(chatId, options) {
|
|
879
|
+
if (!chatId) {
|
|
880
|
+
throw new RobotRockError("chatId is required to close a chat", 400);
|
|
881
|
+
}
|
|
882
|
+
const response = await fetch(
|
|
883
|
+
`${config.baseUrl}/agent-chats/${encodeURIComponent(chatId)}/close`,
|
|
884
|
+
{
|
|
885
|
+
method: "POST",
|
|
886
|
+
headers: headers(),
|
|
887
|
+
body: JSON.stringify({ reason: options?.reason })
|
|
888
|
+
}
|
|
889
|
+
);
|
|
890
|
+
if (!response.ok) {
|
|
891
|
+
const data = await parseResponseBody(response);
|
|
892
|
+
throw new RobotRockError(
|
|
893
|
+
getErrorMessage(data, "Failed to close chat"),
|
|
894
|
+
response.status,
|
|
895
|
+
data
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
var init_chats = __esm({
|
|
902
|
+
"src/chats.ts"() {
|
|
903
|
+
"use strict";
|
|
904
|
+
init_src();
|
|
905
|
+
init_http();
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
|
|
690
909
|
// src/client.ts
|
|
691
910
|
function sleep(ms) {
|
|
692
911
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
693
912
|
}
|
|
913
|
+
function resolveAgentVersionFromEnv() {
|
|
914
|
+
const fromEnv = process.env.AGENT_VERSION?.trim() || process.env.ROBOTROCK_AGENT_VERSION?.trim();
|
|
915
|
+
return fromEnv || void 0;
|
|
916
|
+
}
|
|
694
917
|
function parseValidUntilMs(value) {
|
|
695
918
|
if (value === void 0) {
|
|
696
919
|
return void 0;
|
|
@@ -744,6 +967,7 @@ function normalizeSendToHumanInput(task2, clientDefaults) {
|
|
|
744
967
|
threadId: _threadId,
|
|
745
968
|
priority: _priority,
|
|
746
969
|
update: _update,
|
|
970
|
+
version: _version,
|
|
747
971
|
validUntil,
|
|
748
972
|
app: taskApp,
|
|
749
973
|
...rest
|
|
@@ -753,67 +977,35 @@ function normalizeSendToHumanInput(task2, clientDefaults) {
|
|
|
753
977
|
const app = taskApp ?? clientDefaults.app;
|
|
754
978
|
return {
|
|
755
979
|
...rest,
|
|
756
|
-
|
|
980
|
+
contextVersion: clientDefaults.contextVersion,
|
|
757
981
|
...app ? { app } : {},
|
|
758
982
|
...validUntil !== void 0 ? { validUntil: serializeValidUntil(validUntil) } : {},
|
|
759
983
|
actions: normalizedActions
|
|
760
984
|
};
|
|
761
985
|
}
|
|
762
|
-
|
|
763
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
764
|
-
const bodyText = await response.text();
|
|
765
|
-
if (!bodyText) {
|
|
766
|
-
return null;
|
|
767
|
-
}
|
|
768
|
-
if (contentType.toLowerCase().includes("application/json")) {
|
|
769
|
-
try {
|
|
770
|
-
return JSON.parse(bodyText);
|
|
771
|
-
} catch {
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
try {
|
|
775
|
-
return JSON.parse(bodyText);
|
|
776
|
-
} catch {
|
|
777
|
-
return bodyText;
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
function getErrorMessage(data, fallback) {
|
|
781
|
-
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
782
|
-
const maybeMessage = data.message;
|
|
783
|
-
if (typeof maybeMessage === "string" && maybeMessage.trim()) {
|
|
784
|
-
return maybeMessage;
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
if (typeof data === "string" && data.trim()) {
|
|
788
|
-
const compact = data.replace(/\s+/g, " ").trim();
|
|
789
|
-
const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
|
|
790
|
-
return `${fallback}. Server returned non-JSON response: ${snippet}`;
|
|
791
|
-
}
|
|
792
|
-
return fallback;
|
|
793
|
-
}
|
|
794
|
-
var DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, RobotRockError, RobotRock;
|
|
986
|
+
var DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, RobotRock;
|
|
795
987
|
var init_client = __esm({
|
|
796
988
|
"src/client.ts"() {
|
|
797
989
|
"use strict";
|
|
798
990
|
init_schemas2();
|
|
799
991
|
init_approval_result();
|
|
992
|
+
init_http();
|
|
993
|
+
init_chats();
|
|
994
|
+
init_http();
|
|
800
995
|
DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
801
996
|
DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
802
|
-
RobotRockError = class extends Error {
|
|
803
|
-
constructor(message, statusCode, response) {
|
|
804
|
-
super(message);
|
|
805
|
-
this.statusCode = statusCode;
|
|
806
|
-
this.response = response;
|
|
807
|
-
this.name = "RobotRockError";
|
|
808
|
-
}
|
|
809
|
-
};
|
|
810
997
|
RobotRock = class {
|
|
811
998
|
apiKey;
|
|
812
999
|
baseUrl;
|
|
813
1000
|
app;
|
|
814
|
-
|
|
1001
|
+
agentVersion;
|
|
1002
|
+
contextVersion;
|
|
815
1003
|
webhook;
|
|
816
1004
|
polling;
|
|
1005
|
+
/** Task CRUD: `create`, `get`, `cancel`, `sendUpdate`. */
|
|
1006
|
+
tasks;
|
|
1007
|
+
/** Chat CRUD: `create`, `close`. */
|
|
1008
|
+
chats;
|
|
817
1009
|
constructor(config) {
|
|
818
1010
|
if (config.webhook && config.polling) {
|
|
819
1011
|
throw new Error(
|
|
@@ -830,26 +1022,37 @@ var init_client = __esm({
|
|
|
830
1022
|
const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
|
|
831
1023
|
this.baseUrl = rawBase.replace(/\/+$/, "");
|
|
832
1024
|
this.app = config.app;
|
|
833
|
-
this.
|
|
1025
|
+
this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
|
|
1026
|
+
this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
|
|
834
1027
|
this.webhook = config.webhook;
|
|
835
1028
|
this.polling = config.polling ?? {};
|
|
1029
|
+
this.tasks = {
|
|
1030
|
+
create: (task2) => this.createTaskRequest(task2),
|
|
1031
|
+
get: (taskId) => this.getTaskById(taskId),
|
|
1032
|
+
cancel: (taskId) => this.cancelTaskRequest(taskId),
|
|
1033
|
+
sendUpdate: (input) => this.sendThreadUpdate(input)
|
|
1034
|
+
};
|
|
1035
|
+
this.chats = createChatsApi({
|
|
1036
|
+
baseUrl: this.baseUrl,
|
|
1037
|
+
apiKey: this.apiKey,
|
|
1038
|
+
app: this.app
|
|
1039
|
+
});
|
|
836
1040
|
}
|
|
837
|
-
|
|
838
|
-
* Create a task via POST /v1 without waiting for a human response.
|
|
839
|
-
*/
|
|
840
|
-
async createTask(task2) {
|
|
1041
|
+
async createTaskRequest(task2) {
|
|
841
1042
|
const normalizedTask = normalizeSendToHumanInput(task2, {
|
|
842
1043
|
webhook: this.webhook,
|
|
843
1044
|
app: this.app,
|
|
844
|
-
|
|
1045
|
+
contextVersion: this.contextVersion,
|
|
1046
|
+
agentVersion: this.agentVersion
|
|
845
1047
|
});
|
|
1048
|
+
const agentVersion = task2.version ?? this.agentVersion;
|
|
846
1049
|
const bodyPayload = {
|
|
847
1050
|
...normalizedTask,
|
|
848
1051
|
...task2.assignTo !== void 0 ? { assignTo: task2.assignTo } : {},
|
|
849
1052
|
...task2.threadId !== void 0 ? { threadId: task2.threadId } : {},
|
|
850
1053
|
...task2.priority !== void 0 ? { priority: task2.priority } : {},
|
|
851
1054
|
...task2.update !== void 0 ? { update: task2.update } : {},
|
|
852
|
-
...
|
|
1055
|
+
...agentVersion !== void 0 ? { agent: { version: agentVersion } } : {}
|
|
853
1056
|
};
|
|
854
1057
|
const validation = createTaskBodySchema2.safeParse(bodyPayload);
|
|
855
1058
|
if (!validation.success) {
|
|
@@ -885,9 +1088,10 @@ var init_client = __esm({
|
|
|
885
1088
|
const normalizedTask = normalizeSendToHumanInput(task2, {
|
|
886
1089
|
webhook: this.webhook,
|
|
887
1090
|
app: this.app,
|
|
888
|
-
|
|
1091
|
+
contextVersion: this.contextVersion,
|
|
1092
|
+
agentVersion: this.agentVersion
|
|
889
1093
|
});
|
|
890
|
-
const createdTaskTask = await this.
|
|
1094
|
+
const createdTaskTask = await this.createTaskRequest(task2);
|
|
891
1095
|
const hasHandlers = normalizedTask.actions.some(
|
|
892
1096
|
(action) => Array.isArray(action.handlers) && action.handlers.length > 0
|
|
893
1097
|
);
|
|
@@ -904,7 +1108,7 @@ var init_client = __esm({
|
|
|
904
1108
|
const deadline = validUntilMs !== void 0 ? Math.min(pollingDeadline, validUntilMs) : pollingDeadline;
|
|
905
1109
|
const taskId = createdTaskTask.taskId;
|
|
906
1110
|
while (Date.now() < deadline) {
|
|
907
|
-
const existing = await this.
|
|
1111
|
+
const existing = await this.getTaskById(taskId);
|
|
908
1112
|
if (existing?.status === "handled" && existing.handled) {
|
|
909
1113
|
return {
|
|
910
1114
|
mode: "handled",
|
|
@@ -926,10 +1130,35 @@ var init_client = __esm({
|
|
|
926
1130
|
}
|
|
927
1131
|
throw new TaskTimeoutError(`No human response within ${timeoutMs}ms`);
|
|
928
1132
|
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Create a task via POST /v1 without waiting for a human response.
|
|
1135
|
+
* @deprecated Use `client.tasks.create()` instead.
|
|
1136
|
+
*/
|
|
1137
|
+
async createTask(task2) {
|
|
1138
|
+
return this.tasks.create(task2);
|
|
1139
|
+
}
|
|
929
1140
|
/**
|
|
930
1141
|
* Get a task by public task id (returned as `task.taskId` from {@link sendToHuman}).
|
|
1142
|
+
* @deprecated Use `client.tasks.get()` instead.
|
|
931
1143
|
*/
|
|
932
1144
|
async getTask(taskId) {
|
|
1145
|
+
return this.tasks.get(taskId);
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Log a status update against a thread.
|
|
1149
|
+
* @deprecated Use `client.tasks.sendUpdate()` instead.
|
|
1150
|
+
*/
|
|
1151
|
+
async sendUpdate(input) {
|
|
1152
|
+
return this.tasks.sendUpdate(input);
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Cancel a task by public task id.
|
|
1156
|
+
* @deprecated Use `client.tasks.cancel()` instead.
|
|
1157
|
+
*/
|
|
1158
|
+
async cancelTask(taskId) {
|
|
1159
|
+
return this.tasks.cancel(taskId);
|
|
1160
|
+
}
|
|
1161
|
+
async getTaskById(taskId) {
|
|
933
1162
|
const response = await fetch(`${this.baseUrl}/tasks/${taskId}`, {
|
|
934
1163
|
method: "GET",
|
|
935
1164
|
headers: {
|
|
@@ -949,11 +1178,11 @@ var init_client = __esm({
|
|
|
949
1178
|
}
|
|
950
1179
|
return data;
|
|
951
1180
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1181
|
+
async sendThreadUpdate({
|
|
1182
|
+
threadId,
|
|
1183
|
+
message,
|
|
1184
|
+
status
|
|
1185
|
+
}) {
|
|
957
1186
|
if (!threadId) {
|
|
958
1187
|
throw new RobotRockError("threadId is required to send an update", 400);
|
|
959
1188
|
}
|
|
@@ -986,7 +1215,7 @@ var init_client = __esm({
|
|
|
986
1215
|
}
|
|
987
1216
|
return data.update;
|
|
988
1217
|
}
|
|
989
|
-
async
|
|
1218
|
+
async cancelTaskRequest(taskId) {
|
|
990
1219
|
const response = await fetch(`${this.baseUrl}/tasks/${taskId}/cancel`, {
|
|
991
1220
|
method: "POST",
|
|
992
1221
|
headers: {
|
|
@@ -1027,6 +1256,212 @@ var init_env = __esm({
|
|
|
1027
1256
|
}
|
|
1028
1257
|
});
|
|
1029
1258
|
|
|
1259
|
+
// src/record-handled-to-otel.ts
|
|
1260
|
+
import {
|
|
1261
|
+
context,
|
|
1262
|
+
trace,
|
|
1263
|
+
SpanStatusCode
|
|
1264
|
+
} from "@opentelemetry/api";
|
|
1265
|
+
function isValidTraceId(traceId) {
|
|
1266
|
+
return typeof traceId === "string" && traceId.length > 0 && traceId !== INVALID_TRACE_ID;
|
|
1267
|
+
}
|
|
1268
|
+
function resolveSpanContext(span) {
|
|
1269
|
+
const active = span ?? trace.getActiveSpan();
|
|
1270
|
+
const ctx = active?.spanContext();
|
|
1271
|
+
if (!ctx || !isValidTraceId(ctx.traceId)) {
|
|
1272
|
+
return void 0;
|
|
1273
|
+
}
|
|
1274
|
+
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
|
1275
|
+
}
|
|
1276
|
+
function parseTaskCreatedAt(submittedAt) {
|
|
1277
|
+
if (submittedAt) {
|
|
1278
|
+
const parsed = Date.parse(submittedAt);
|
|
1279
|
+
if (!Number.isNaN(parsed)) {
|
|
1280
|
+
return parsed;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
return Date.now();
|
|
1284
|
+
}
|
|
1285
|
+
function parseHandledAtMs(handledAt) {
|
|
1286
|
+
if (handledAt instanceof Date) {
|
|
1287
|
+
return handledAt.getTime();
|
|
1288
|
+
}
|
|
1289
|
+
if (typeof handledAt === "number") {
|
|
1290
|
+
return handledAt;
|
|
1291
|
+
}
|
|
1292
|
+
const parsed = Date.parse(handledAt);
|
|
1293
|
+
return Number.isNaN(parsed) ? Date.now() : parsed;
|
|
1294
|
+
}
|
|
1295
|
+
function toRobotRockHandledOtelInput(handled) {
|
|
1296
|
+
if ("actionId" in handled) {
|
|
1297
|
+
return {
|
|
1298
|
+
taskId: handled.taskId,
|
|
1299
|
+
action: {
|
|
1300
|
+
id: handled.actionId,
|
|
1301
|
+
data: handled.data
|
|
1302
|
+
},
|
|
1303
|
+
handledBy: handled.handledBy,
|
|
1304
|
+
handledAt: handled.handledAt
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
return {
|
|
1308
|
+
taskId: handled.taskId,
|
|
1309
|
+
action: {
|
|
1310
|
+
id: handled.action.id,
|
|
1311
|
+
title: handled.action.title,
|
|
1312
|
+
data: handled.action.data
|
|
1313
|
+
},
|
|
1314
|
+
handledBy: handled.handledBy,
|
|
1315
|
+
handledAt: handled.handledAt
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
function captureRobotRockOtelHandle(task2, options) {
|
|
1319
|
+
const spanCtx = resolveSpanContext(options?.span);
|
|
1320
|
+
return {
|
|
1321
|
+
traceId: spanCtx?.traceId ?? "",
|
|
1322
|
+
spanId: spanCtx?.spanId ?? "",
|
|
1323
|
+
taskId: task2.taskId,
|
|
1324
|
+
threadId: task2.threadId,
|
|
1325
|
+
taskCreatedAt: parseTaskCreatedAt(task2.submittedAt)
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function startRobotRockHumanWaitSpan(handle, options) {
|
|
1329
|
+
const parent = options?.span ?? trace.getActiveSpan();
|
|
1330
|
+
if (!parent) {
|
|
1331
|
+
return void 0;
|
|
1332
|
+
}
|
|
1333
|
+
const tracer = trace.getTracer(options?.tracerName ?? TRACER_NAME);
|
|
1334
|
+
const span = tracer.startSpan(
|
|
1335
|
+
WAIT_SPAN_NAME,
|
|
1336
|
+
{},
|
|
1337
|
+
trace.setSpan(context.active(), parent)
|
|
1338
|
+
);
|
|
1339
|
+
span.setAttribute("robotrock.task_id", handle.taskId);
|
|
1340
|
+
if (handle.threadId) {
|
|
1341
|
+
span.setAttribute("robotrock.thread_id", handle.threadId);
|
|
1342
|
+
}
|
|
1343
|
+
return span;
|
|
1344
|
+
}
|
|
1345
|
+
function recordRobotRockHandledToOtel(handled, options = {}) {
|
|
1346
|
+
const span = options.span ?? trace.getActiveSpan();
|
|
1347
|
+
if (!span) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const input = toRobotRockHandledOtelInput(handled);
|
|
1351
|
+
const handledAtMs = parseHandledAtMs(input.handledAt);
|
|
1352
|
+
const handle = options.handle;
|
|
1353
|
+
const humanWaitMs = handle != null ? Math.max(0, handledAtMs - handle.taskCreatedAt) : void 0;
|
|
1354
|
+
span.setAttribute("robotrock.task_id", input.taskId);
|
|
1355
|
+
span.setAttribute("robotrock.action.id", input.action.id);
|
|
1356
|
+
if (input.action.title) {
|
|
1357
|
+
span.setAttribute("robotrock.action.title", input.action.title);
|
|
1358
|
+
}
|
|
1359
|
+
if (input.handledBy) {
|
|
1360
|
+
span.setAttribute("robotrock.handled_by", input.handledBy);
|
|
1361
|
+
}
|
|
1362
|
+
span.setAttribute("robotrock.handled_at", new Date(handledAtMs).toISOString());
|
|
1363
|
+
if (humanWaitMs != null) {
|
|
1364
|
+
span.setAttribute("robotrock.human_wait_ms", humanWaitMs);
|
|
1365
|
+
}
|
|
1366
|
+
if (input.threadId) {
|
|
1367
|
+
span.setAttribute("robotrock.thread_id", input.threadId);
|
|
1368
|
+
}
|
|
1369
|
+
const eventAttributes = {
|
|
1370
|
+
"robotrock.task_id": input.taskId,
|
|
1371
|
+
"robotrock.action.id": input.action.id
|
|
1372
|
+
};
|
|
1373
|
+
if (input.handledBy) {
|
|
1374
|
+
eventAttributes["robotrock.handled_by"] = input.handledBy;
|
|
1375
|
+
}
|
|
1376
|
+
if (humanWaitMs != null) {
|
|
1377
|
+
eventAttributes["robotrock.human_wait_ms"] = humanWaitMs;
|
|
1378
|
+
}
|
|
1379
|
+
if (options.includeActionData && input.action.data != null) {
|
|
1380
|
+
const serialized = JSON.stringify(input.action.data);
|
|
1381
|
+
const truncated = serialized.length > 512 ? `${serialized.slice(0, 512)}\u2026` : serialized;
|
|
1382
|
+
span.setAttribute("robotrock.action.data", truncated);
|
|
1383
|
+
eventAttributes["robotrock.action.data"] = truncated;
|
|
1384
|
+
}
|
|
1385
|
+
span.addEvent(HANDLED_EVENT_NAME, eventAttributes);
|
|
1386
|
+
}
|
|
1387
|
+
function endRobotRockHumanWaitSpan(span, handled, options = {}) {
|
|
1388
|
+
if (!span) {
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
const outcome = options.outcome ?? (handled ? "handled" : "timeout");
|
|
1392
|
+
if (handled && outcome === "handled") {
|
|
1393
|
+
recordRobotRockHandledToOtel(handled, {
|
|
1394
|
+
span,
|
|
1395
|
+
handle: options.handle,
|
|
1396
|
+
includeActionData: options.includeActionData
|
|
1397
|
+
});
|
|
1398
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1399
|
+
} else {
|
|
1400
|
+
span.setAttribute("robotrock.outcome", outcome);
|
|
1401
|
+
span.setStatus({
|
|
1402
|
+
code: SpanStatusCode.ERROR,
|
|
1403
|
+
message: outcome === "timeout" ? "Human response timed out before validUntil" : "Human wait failed"
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
span.end();
|
|
1407
|
+
}
|
|
1408
|
+
var TRACER_NAME, WAIT_SPAN_NAME, HANDLED_EVENT_NAME, INVALID_TRACE_ID;
|
|
1409
|
+
var init_record_handled_to_otel = __esm({
|
|
1410
|
+
"src/record-handled-to-otel.ts"() {
|
|
1411
|
+
"use strict";
|
|
1412
|
+
TRACER_NAME = "robotrock";
|
|
1413
|
+
WAIT_SPAN_NAME = "robotrock.wait_for_human";
|
|
1414
|
+
HANDLED_EVENT_NAME = "robotrock.task_handled";
|
|
1415
|
+
INVALID_TRACE_ID = "00000000000000000000000000000000";
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
// src/otel-platform.ts
|
|
1420
|
+
function shouldRecordRobotRockOtel(recordOtel) {
|
|
1421
|
+
if (recordOtel === true) {
|
|
1422
|
+
return true;
|
|
1423
|
+
}
|
|
1424
|
+
if (recordOtel === false) {
|
|
1425
|
+
return false;
|
|
1426
|
+
}
|
|
1427
|
+
const env = process.env.ROBOTROCK_OTEL_RECORD_HANDLED;
|
|
1428
|
+
return env === "true" || env === "1";
|
|
1429
|
+
}
|
|
1430
|
+
function stripPlatformOtelFields(payload) {
|
|
1431
|
+
const { recordOtel: _recordOtel, otelIncludeActionData: _otelIncludeActionData, ...rest } = payload;
|
|
1432
|
+
return rest;
|
|
1433
|
+
}
|
|
1434
|
+
function beginRobotRockHumanWaitOtel(task2, options = {}) {
|
|
1435
|
+
const recordOtel = shouldRecordRobotRockOtel(options.recordOtel);
|
|
1436
|
+
if (!recordOtel) {
|
|
1437
|
+
return { recordOtel: false };
|
|
1438
|
+
}
|
|
1439
|
+
const handle = captureRobotRockOtelHandle(task2);
|
|
1440
|
+
const waitSpan = startRobotRockHumanWaitSpan(handle);
|
|
1441
|
+
return {
|
|
1442
|
+
recordOtel: true,
|
|
1443
|
+
handle,
|
|
1444
|
+
waitSpan,
|
|
1445
|
+
includeActionData: options.otelIncludeActionData
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
function finishRobotRockHumanWaitOtel(session, handled, outcome) {
|
|
1449
|
+
if (!session.recordOtel) {
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
endRobotRockHumanWaitSpan(session.waitSpan, handled, {
|
|
1453
|
+
handle: session.handle,
|
|
1454
|
+
outcome,
|
|
1455
|
+
includeActionData: session.includeActionData
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
var init_otel_platform = __esm({
|
|
1459
|
+
"src/otel-platform.ts"() {
|
|
1460
|
+
"use strict";
|
|
1461
|
+
init_record_handled_to_otel();
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1464
|
+
|
|
1030
1465
|
// src/handler-webhook.ts
|
|
1031
1466
|
function isRobotRockHandlerWebhookPayload(value) {
|
|
1032
1467
|
if (typeof value !== "object" || value === null) {
|
|
@@ -1107,7 +1542,7 @@ __export(trigger_exports, {
|
|
|
1107
1542
|
});
|
|
1108
1543
|
import { task, wait } from "@trigger.dev/sdk";
|
|
1109
1544
|
async function runSendToHuman(payload) {
|
|
1110
|
-
const { validUntil: validUntilInput, ...
|
|
1545
|
+
const { validUntil: validUntilInput, app, recordOtel, otelIncludeActionData, ...taskFields } = payload;
|
|
1111
1546
|
const { validUntil, timeout } = resolveWaitTiming(validUntilInput);
|
|
1112
1547
|
const token = await wait.createToken({ timeout });
|
|
1113
1548
|
const baseConfig = resolveRobotRockConfig();
|
|
@@ -1116,45 +1551,74 @@ async function runSendToHuman(payload) {
|
|
|
1116
1551
|
baseUrl: baseConfig.baseUrl,
|
|
1117
1552
|
...baseConfig.app ? { app: baseConfig.app } : {},
|
|
1118
1553
|
...baseConfig.version ? { version: baseConfig.version } : {},
|
|
1554
|
+
...baseConfig.advanced ? { advanced: baseConfig.advanced } : {},
|
|
1119
1555
|
webhook: { url: token.url }
|
|
1120
1556
|
});
|
|
1557
|
+
const taskInput = stripPlatformOtelFields(taskFields);
|
|
1121
1558
|
const sendResult = await client.sendToHuman({
|
|
1122
1559
|
...taskInput,
|
|
1123
|
-
validUntil
|
|
1560
|
+
validUntil,
|
|
1561
|
+
...app !== void 0 ? { app } : {}
|
|
1124
1562
|
});
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
)
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1563
|
+
const otelSession = beginRobotRockHumanWaitOtel(sendResult.task, {
|
|
1564
|
+
recordOtel,
|
|
1565
|
+
otelIncludeActionData
|
|
1566
|
+
});
|
|
1567
|
+
let handledPayload = null;
|
|
1568
|
+
let waitOutcome = "pending";
|
|
1569
|
+
try {
|
|
1570
|
+
const outcome = await wait.forToken(token.id);
|
|
1571
|
+
if (!outcome.ok) {
|
|
1572
|
+
waitOutcome = "timeout";
|
|
1573
|
+
throw new Error(`Human response timed out before validUntil (${timeout})`);
|
|
1574
|
+
}
|
|
1575
|
+
const output = outcome.output;
|
|
1576
|
+
if (!isRobotRockHandlerWebhookPayload(output)) {
|
|
1577
|
+
waitOutcome = "error";
|
|
1578
|
+
throw new Error(
|
|
1579
|
+
"Wait token completed with unexpected payload; expected RobotRock handler body (taskId, action.id, action.data)."
|
|
1580
|
+
);
|
|
1581
|
+
}
|
|
1582
|
+
handledPayload = output;
|
|
1583
|
+
waitOutcome = "handled";
|
|
1584
|
+
return toDiscriminatedApprovalResult(
|
|
1585
|
+
payload.actions,
|
|
1586
|
+
{
|
|
1587
|
+
id: output.taskId,
|
|
1588
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1589
|
+
status: "handled",
|
|
1590
|
+
context: sendResult.task.context,
|
|
1591
|
+
validUntil: Date.now(),
|
|
1592
|
+
handledAt: new Date(output.handledAt).getTime(),
|
|
1593
|
+
handled: {
|
|
1594
|
+
action: {
|
|
1595
|
+
id: output.action.id,
|
|
1596
|
+
data: output.action.data
|
|
1597
|
+
},
|
|
1598
|
+
handledBy: output.handledBy
|
|
1599
|
+
}
|
|
1150
1600
|
}
|
|
1601
|
+
);
|
|
1602
|
+
} catch (error) {
|
|
1603
|
+
if (waitOutcome === "pending") {
|
|
1604
|
+
waitOutcome = "error";
|
|
1151
1605
|
}
|
|
1152
|
-
|
|
1606
|
+
throw error;
|
|
1607
|
+
} finally {
|
|
1608
|
+
if (waitOutcome !== "pending") {
|
|
1609
|
+
finishRobotRockHumanWaitOtel(
|
|
1610
|
+
otelSession,
|
|
1611
|
+
handledPayload,
|
|
1612
|
+
waitOutcome === "handled" ? "handled" : waitOutcome
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1153
1616
|
}
|
|
1154
1617
|
var APPROVE_BY_HUMAN_ACTIONS, sendToHumanTask, approveByHumanTask;
|
|
1155
1618
|
var init_trigger = __esm({
|
|
1156
1619
|
"src/trigger/index.ts"() {
|
|
1157
1620
|
"use strict";
|
|
1621
|
+
init_otel_platform();
|
|
1158
1622
|
init_client();
|
|
1159
1623
|
init_env();
|
|
1160
1624
|
init_approval_result();
|
|
@@ -1194,6 +1658,7 @@ async function createRobotRockTaskForWebhook(input) {
|
|
|
1194
1658
|
baseUrl: baseConfig.baseUrl,
|
|
1195
1659
|
...input.app ?? baseConfig.app ? { app: input.app ?? baseConfig.app } : {},
|
|
1196
1660
|
...baseConfig.version ? { version: baseConfig.version } : {},
|
|
1661
|
+
...baseConfig.advanced ? { advanced: baseConfig.advanced } : {},
|
|
1197
1662
|
webhook: { url: input.webhookUrl }
|
|
1198
1663
|
});
|
|
1199
1664
|
return client.sendToHuman({
|
|
@@ -1214,7 +1679,7 @@ async function parseRobotRockWebhookRequest(request) {
|
|
|
1214
1679
|
async function sendToHumanInWorkflow(payload) {
|
|
1215
1680
|
var _stack = [];
|
|
1216
1681
|
try {
|
|
1217
|
-
const { validUntil: validUntilInput, app, ...
|
|
1682
|
+
const { validUntil: validUntilInput, app, recordOtel, otelIncludeActionData, ...taskFields } = payload;
|
|
1218
1683
|
const { validUntil, timeout } = resolveWaitTiming(validUntilInput);
|
|
1219
1684
|
const timeoutMs = parseValidUntilMs2(validUntil) - Date.now();
|
|
1220
1685
|
const webhook = __using(_stack, createWebhook());
|
|
@@ -1222,31 +1687,54 @@ async function sendToHumanInWorkflow(payload) {
|
|
|
1222
1687
|
webhookUrl: webhook.url,
|
|
1223
1688
|
app,
|
|
1224
1689
|
validUntil,
|
|
1225
|
-
taskInput
|
|
1690
|
+
taskInput: stripPlatformOtelFields(taskFields)
|
|
1226
1691
|
});
|
|
1227
|
-
const
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
]);
|
|
1231
|
-
if ("timedOut" in outcome) {
|
|
1232
|
-
throw new Error(`Human response timed out before validUntil (${timeout})`);
|
|
1233
|
-
}
|
|
1234
|
-
const output = outcome;
|
|
1235
|
-
return toDiscriminatedApprovalResult(payload.actions, {
|
|
1236
|
-
id: output.taskId,
|
|
1237
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1238
|
-
status: "handled",
|
|
1239
|
-
context: sendResult.task.context,
|
|
1240
|
-
validUntil: Date.now(),
|
|
1241
|
-
handledAt: new Date(output.handledAt).getTime(),
|
|
1242
|
-
handled: {
|
|
1243
|
-
action: {
|
|
1244
|
-
id: output.action.id,
|
|
1245
|
-
data: output.action.data
|
|
1246
|
-
},
|
|
1247
|
-
handledBy: output.handledBy
|
|
1248
|
-
}
|
|
1692
|
+
const otelSession = beginRobotRockHumanWaitOtel(sendResult.task, {
|
|
1693
|
+
recordOtel,
|
|
1694
|
+
otelIncludeActionData
|
|
1249
1695
|
});
|
|
1696
|
+
let handledPayload = null;
|
|
1697
|
+
let waitOutcome = "pending";
|
|
1698
|
+
try {
|
|
1699
|
+
const outcome = await Promise.race([
|
|
1700
|
+
webhook.then((request) => parseRobotRockWebhookRequest(request)),
|
|
1701
|
+
sleep2(timeoutMs).then(() => ({ timedOut: true }))
|
|
1702
|
+
]);
|
|
1703
|
+
if ("timedOut" in outcome) {
|
|
1704
|
+
waitOutcome = "timeout";
|
|
1705
|
+
throw new Error(`Human response timed out before validUntil (${timeout})`);
|
|
1706
|
+
}
|
|
1707
|
+
handledPayload = outcome;
|
|
1708
|
+
waitOutcome = "handled";
|
|
1709
|
+
return toDiscriminatedApprovalResult(payload.actions, {
|
|
1710
|
+
id: outcome.taskId,
|
|
1711
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1712
|
+
status: "handled",
|
|
1713
|
+
context: sendResult.task.context,
|
|
1714
|
+
validUntil: Date.now(),
|
|
1715
|
+
handledAt: new Date(outcome.handledAt).getTime(),
|
|
1716
|
+
handled: {
|
|
1717
|
+
action: {
|
|
1718
|
+
id: outcome.action.id,
|
|
1719
|
+
data: outcome.action.data
|
|
1720
|
+
},
|
|
1721
|
+
handledBy: outcome.handledBy
|
|
1722
|
+
}
|
|
1723
|
+
});
|
|
1724
|
+
} catch (error) {
|
|
1725
|
+
if (waitOutcome === "pending") {
|
|
1726
|
+
waitOutcome = "error";
|
|
1727
|
+
}
|
|
1728
|
+
throw error;
|
|
1729
|
+
} finally {
|
|
1730
|
+
if (waitOutcome !== "pending") {
|
|
1731
|
+
finishRobotRockHumanWaitOtel(
|
|
1732
|
+
otelSession,
|
|
1733
|
+
handledPayload,
|
|
1734
|
+
waitOutcome === "handled" ? "handled" : waitOutcome
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1250
1738
|
} catch (_) {
|
|
1251
1739
|
var _error = _, _hasError = true;
|
|
1252
1740
|
} finally {
|
|
@@ -1267,9 +1755,10 @@ async function sendRobotRockUpdate(payload) {
|
|
|
1267
1755
|
apiKey: baseConfig.apiKey,
|
|
1268
1756
|
baseUrl: baseConfig.baseUrl,
|
|
1269
1757
|
...app ?? baseConfig.app ? { app: app ?? baseConfig.app } : {},
|
|
1270
|
-
...baseConfig.version ? { version: baseConfig.version } : {}
|
|
1758
|
+
...baseConfig.version ? { version: baseConfig.version } : {},
|
|
1759
|
+
...baseConfig.advanced ? { advanced: baseConfig.advanced } : {}
|
|
1271
1760
|
});
|
|
1272
|
-
return client.sendUpdate(update);
|
|
1761
|
+
return client.tasks.sendUpdate(update);
|
|
1273
1762
|
}
|
|
1274
1763
|
async function sendUpdateInWorkflow(payload) {
|
|
1275
1764
|
return sendRobotRockUpdate(payload);
|
|
@@ -1283,6 +1772,7 @@ var init_workflow = __esm({
|
|
|
1283
1772
|
init_approval_result();
|
|
1284
1773
|
init_handler_webhook();
|
|
1285
1774
|
init_wait_timing();
|
|
1775
|
+
init_otel_platform();
|
|
1286
1776
|
APPROVE_BY_HUMAN_ACTIONS2 = [
|
|
1287
1777
|
{ id: "approve", title: "Approve" },
|
|
1288
1778
|
{ id: "decline", title: "Decline" }
|
|
@@ -1291,7 +1781,7 @@ var init_workflow = __esm({
|
|
|
1291
1781
|
});
|
|
1292
1782
|
|
|
1293
1783
|
// src/ai/approve-by-human-tool-core.ts
|
|
1294
|
-
import { z as
|
|
1784
|
+
import { z as z4 } from "zod";
|
|
1295
1785
|
|
|
1296
1786
|
// src/ai/context.ts
|
|
1297
1787
|
init_client();
|
|
@@ -1321,27 +1811,27 @@ function normalizeRobotRockAiContext(clientOrContext) {
|
|
|
1321
1811
|
}
|
|
1322
1812
|
throw new Error(`Unknown RobotRock AI mode: ${String(clientOrContext.mode)}`);
|
|
1323
1813
|
}
|
|
1324
|
-
async function sendToHumanForAi(
|
|
1325
|
-
if (
|
|
1814
|
+
async function sendToHumanForAi(context2, payload) {
|
|
1815
|
+
if (context2.mode === "trigger") {
|
|
1326
1816
|
const { sendToHumanTask: sendToHumanTask2 } = await Promise.resolve().then(() => (init_trigger(), trigger_exports));
|
|
1327
1817
|
const waitResult = await sendToHumanTask2.triggerAndWait({
|
|
1328
1818
|
...payload,
|
|
1329
|
-
...
|
|
1819
|
+
...context2.app ? { app: context2.app } : {}
|
|
1330
1820
|
});
|
|
1331
1821
|
if (!waitResult.ok) {
|
|
1332
1822
|
throw waitResult.error;
|
|
1333
1823
|
}
|
|
1334
1824
|
return waitResult.output;
|
|
1335
1825
|
}
|
|
1336
|
-
if (
|
|
1826
|
+
if (context2.mode === "workflow") {
|
|
1337
1827
|
const { sendToHumanInWorkflow: sendToHumanInWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1338
1828
|
const result2 = await sendToHumanInWorkflow2({
|
|
1339
1829
|
...payload,
|
|
1340
|
-
...
|
|
1830
|
+
...context2.app ? { app: context2.app } : {}
|
|
1341
1831
|
});
|
|
1342
1832
|
return result2;
|
|
1343
1833
|
}
|
|
1344
|
-
const result = await
|
|
1834
|
+
const result = await context2.client.sendToHuman(payload);
|
|
1345
1835
|
if (result.mode !== "handled") {
|
|
1346
1836
|
throw new Error(
|
|
1347
1837
|
"RobotRock task was created but not handled. Configure client polling or webhook, or use mode: 'trigger' / 'workflow' for durable waits."
|
|
@@ -1355,42 +1845,42 @@ async function sendToHumanForAi(context, payload) {
|
|
|
1355
1845
|
taskId: result.taskId
|
|
1356
1846
|
};
|
|
1357
1847
|
}
|
|
1358
|
-
async function sendUpdateForAi(
|
|
1359
|
-
if (
|
|
1848
|
+
async function sendUpdateForAi(context2, payload) {
|
|
1849
|
+
if (context2.mode === "workflow") {
|
|
1360
1850
|
const { sendUpdateInWorkflow: sendUpdateInWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1361
1851
|
return sendUpdateInWorkflow2({
|
|
1362
1852
|
...payload,
|
|
1363
|
-
...
|
|
1853
|
+
...context2.app ? { app: context2.app } : {}
|
|
1364
1854
|
});
|
|
1365
1855
|
}
|
|
1366
|
-
if (
|
|
1856
|
+
if (context2.mode === "trigger") {
|
|
1367
1857
|
const client = createClient(
|
|
1368
|
-
resolveRobotRockConfig(
|
|
1858
|
+
resolveRobotRockConfig(context2.app ? { app: context2.app } : void 0)
|
|
1369
1859
|
);
|
|
1370
|
-
return client.sendUpdate(payload);
|
|
1860
|
+
return client.tasks.sendUpdate(payload);
|
|
1371
1861
|
}
|
|
1372
|
-
return
|
|
1862
|
+
return context2.client.tasks.sendUpdate(payload);
|
|
1373
1863
|
}
|
|
1374
|
-
async function approveByHumanForAi(
|
|
1375
|
-
if (
|
|
1864
|
+
async function approveByHumanForAi(context2, payload) {
|
|
1865
|
+
if (context2.mode === "trigger") {
|
|
1376
1866
|
const { approveByHumanTask: approveByHumanTask2 } = await Promise.resolve().then(() => (init_trigger(), trigger_exports));
|
|
1377
1867
|
const waitResult = await approveByHumanTask2.triggerAndWait({
|
|
1378
1868
|
...payload,
|
|
1379
|
-
...
|
|
1869
|
+
...context2.app ? { app: context2.app } : {}
|
|
1380
1870
|
});
|
|
1381
1871
|
if (!waitResult.ok) {
|
|
1382
1872
|
throw waitResult.error;
|
|
1383
1873
|
}
|
|
1384
1874
|
return waitResult.output;
|
|
1385
1875
|
}
|
|
1386
|
-
if (
|
|
1876
|
+
if (context2.mode === "workflow") {
|
|
1387
1877
|
const { approveByHumanInWorkflow: approveByHumanInWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), workflow_exports));
|
|
1388
1878
|
return await approveByHumanInWorkflow2({
|
|
1389
1879
|
...payload,
|
|
1390
|
-
...
|
|
1880
|
+
...context2.app ? { app: context2.app } : {}
|
|
1391
1881
|
});
|
|
1392
1882
|
}
|
|
1393
|
-
const result = await
|
|
1883
|
+
const result = await context2.client.sendToHuman({
|
|
1394
1884
|
...payload,
|
|
1395
1885
|
actions: APPROVE_BY_HUMAN_ACTIONS3
|
|
1396
1886
|
});
|
|
@@ -1428,11 +1918,11 @@ function toHumanToolResult(result) {
|
|
|
1428
1918
|
}
|
|
1429
1919
|
|
|
1430
1920
|
// src/ai/approve-by-human-tool-core.ts
|
|
1431
|
-
var approveByHumanInputSchema =
|
|
1432
|
-
type:
|
|
1433
|
-
name:
|
|
1434
|
-
description:
|
|
1435
|
-
contextSummary:
|
|
1921
|
+
var approveByHumanInputSchema = z4.object({
|
|
1922
|
+
type: z4.string().optional().describe("Task type slug; defaults to ai-approval"),
|
|
1923
|
+
name: z4.string().describe("Short title for the approval request"),
|
|
1924
|
+
description: z4.string().describe("What needs approval and the consequences of approving or declining"),
|
|
1925
|
+
contextSummary: z4.string().optional().describe("Optional markdown summary shown to the reviewer")
|
|
1436
1926
|
});
|
|
1437
1927
|
function resolveApproveByHumanToolConfig(clientOrContext, maybeOptions = {}) {
|
|
1438
1928
|
const isDurable = typeof clientOrContext === "object" && clientOrContext !== null && "mode" in clientOrContext && (clientOrContext.mode === "trigger" || clientOrContext.mode === "workflow");
|
|
@@ -1474,16 +1964,16 @@ function buildApproveByHumanToolDefinition(clientOrContext, maybeOptions = {}) {
|
|
|
1474
1964
|
|
|
1475
1965
|
// src/ai/create-send-to-human-tool-core.ts
|
|
1476
1966
|
init_schemas2();
|
|
1477
|
-
import { z as
|
|
1478
|
-
var sendToHumanToolInputSchema =
|
|
1479
|
-
type:
|
|
1480
|
-
name:
|
|
1481
|
-
description:
|
|
1482
|
-
context:
|
|
1483
|
-
data:
|
|
1484
|
-
ui:
|
|
1967
|
+
import { z as z5 } from "zod";
|
|
1968
|
+
var sendToHumanToolInputSchema = z5.object({
|
|
1969
|
+
type: z5.string().describe("Task type slug shown in the RobotRock inbox"),
|
|
1970
|
+
name: z5.string().describe("Short title for the human reviewer"),
|
|
1971
|
+
description: z5.string().optional().describe("What you need from the human and why you cannot proceed alone"),
|
|
1972
|
+
context: z5.object({
|
|
1973
|
+
data: z5.record(z5.string(), z5.unknown()).optional(),
|
|
1974
|
+
ui: z5.record(z5.string(), z5.unknown()).optional()
|
|
1485
1975
|
}).optional().describe("Optional structured context for the inbox UI"),
|
|
1486
|
-
validUntil:
|
|
1976
|
+
validUntil: z5.string().datetime().optional().describe("Optional ISO deadline for the task"),
|
|
1487
1977
|
assignTo: assignToSchema2.optional().describe(
|
|
1488
1978
|
"Assign to tenant member emails and/or group slugs; narrows who sees the task in the inbox"
|
|
1489
1979
|
)
|
|
@@ -1529,12 +2019,12 @@ function buildSendToHumanToolDefinition(clientOrOptions, maybeOptions) {
|
|
|
1529
2019
|
// src/ai/create-send-update-tool-core.ts
|
|
1530
2020
|
init_schemas2();
|
|
1531
2021
|
init_client();
|
|
1532
|
-
import { z as
|
|
1533
|
-
var sendUpdateToolInputSchema =
|
|
1534
|
-
threadId:
|
|
2022
|
+
import { z as z6 } from "zod";
|
|
2023
|
+
var sendUpdateToolInputSchema = z6.object({
|
|
2024
|
+
threadId: z6.string().optional().describe(
|
|
1535
2025
|
"Thread to post the update to. Use the `threadId` returned by a prior send-to-human task. Omit only when a session threadId is configured on the tool."
|
|
1536
2026
|
),
|
|
1537
|
-
message:
|
|
2027
|
+
message: z6.string().describe("Short progress update (1-2 sentences) shown in the inbox status bar"),
|
|
1538
2028
|
status: threadUpdateStatusSchema2.optional().describe(
|
|
1539
2029
|
"Lifecycle status driving the status-bar icon/color: info, queued, running, waiting, succeeded, failed, cancelled"
|
|
1540
2030
|
)
|
|
@@ -1585,6 +2075,84 @@ function buildSendUpdateToolDefinition(clientOrOptions, maybeOptions = {}) {
|
|
|
1585
2075
|
};
|
|
1586
2076
|
}
|
|
1587
2077
|
|
|
2078
|
+
// src/ai/request-action-input-tool-core.ts
|
|
2079
|
+
import { z as z7 } from "zod";
|
|
2080
|
+
var requestActionInputActionSchema = z7.object({
|
|
2081
|
+
id: z7.string().min(1).optional().describe(
|
|
2082
|
+
"Stable action identifier echoed in tool output (e.g. pick-blog-topic). Strongly recommended \u2014 auto-derived from title when omitted."
|
|
2083
|
+
),
|
|
2084
|
+
title: z7.string().min(1),
|
|
2085
|
+
description: z7.string().optional(),
|
|
2086
|
+
schema: z7.record(z7.string(), z7.unknown()).optional().describe("JSON Schema object for the human feedback form"),
|
|
2087
|
+
ui: z7.record(z7.string(), z7.unknown()).optional().describe(
|
|
2088
|
+
'RJSF ui schema overrides (ui:widget, ui:enumNames, etc.). Use ui:widget "radio" for 2\u20136 discrete choices rendered as tappable cards.'
|
|
2089
|
+
),
|
|
2090
|
+
data: z7.record(z7.string(), z7.unknown()).optional().describe("Optional default form field values")
|
|
2091
|
+
});
|
|
2092
|
+
var requestActionInputToolOutputSchema = z7.object({
|
|
2093
|
+
actionId: z7.string().min(1),
|
|
2094
|
+
data: z7.record(z7.string(), z7.unknown())
|
|
2095
|
+
});
|
|
2096
|
+
var requestActionInputToolInputSchema = z7.object({
|
|
2097
|
+
prompt: z7.string().optional().describe("Optional heading shown above the action widget in chat"),
|
|
2098
|
+
action: requestActionInputActionSchema.describe(
|
|
2099
|
+
"Action widget config: JSON Schema form fields and optional RJSF ui overrides (same shape as RobotRock inbox actions)"
|
|
2100
|
+
)
|
|
2101
|
+
});
|
|
2102
|
+
function buildRequestActionInputToolDefinition(options = {}) {
|
|
2103
|
+
const description = options.description ?? `Ask the user for structured input via a RobotRock action widget in chat. Always set action.id (e.g. "pick-blog-topic") and action.title. Provide action.schema and optional action.ui using the same JSON Schema and RJSF ui shape as inbox action widgets. Put every field you need in a single call \u2014 never invoke this tool more than once per turn. For 2\u20136 discrete options, use a string enum with ui:widget "radio" and ui:enumNames \u2014 never markdown bullet lists. After the tool returns, act on the user's data immediately; do not ask them to confirm choices they already submitted.`;
|
|
2104
|
+
return {
|
|
2105
|
+
description,
|
|
2106
|
+
inputSchema: requestActionInputToolInputSchema,
|
|
2107
|
+
outputSchema: requestActionInputToolOutputSchema
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
// src/ai/report-status-tool-core.ts
|
|
2112
|
+
import { z as z8 } from "zod";
|
|
2113
|
+
var reportStatusPhaseSchema = z8.enum([
|
|
2114
|
+
"info",
|
|
2115
|
+
"running",
|
|
2116
|
+
"waiting",
|
|
2117
|
+
"succeeded",
|
|
2118
|
+
"failed"
|
|
2119
|
+
]);
|
|
2120
|
+
var reportStatusToolInputSchema = z8.object({
|
|
2121
|
+
message: z8.string().min(1).describe(
|
|
2122
|
+
"Short progress update shown in chat (1-2 sentences). Use while researching, drafting, or waiting on external work."
|
|
2123
|
+
),
|
|
2124
|
+
phase: reportStatusPhaseSchema.optional().describe(
|
|
2125
|
+
"Lifecycle phase for the status marker. Defaults to running. Use succeeded or failed when a step finishes."
|
|
2126
|
+
)
|
|
2127
|
+
});
|
|
2128
|
+
var reportStatusToolOutputSchema = z8.object({
|
|
2129
|
+
message: z8.string().min(1),
|
|
2130
|
+
phase: reportStatusPhaseSchema
|
|
2131
|
+
});
|
|
2132
|
+
function normalizeReportStatusToolInput(input) {
|
|
2133
|
+
const parsed = reportStatusToolInputSchema.parse(input);
|
|
2134
|
+
return {
|
|
2135
|
+
message: parsed.message.trim(),
|
|
2136
|
+
phase: parsed.phase
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
async function executeReportStatusTool(input) {
|
|
2140
|
+
const normalized = normalizeReportStatusToolInput(input);
|
|
2141
|
+
return {
|
|
2142
|
+
message: normalized.message,
|
|
2143
|
+
phase: normalized.phase ?? "running"
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
function buildReportStatusToolDefinition(options = {}) {
|
|
2147
|
+
const description = options.description ?? 'Post a short progress update to the chat UI while you work. Call this before and during long steps (research, drafting, tool runs) so the user sees what is happening. Use phase "running" while in progress, "succeeded" or "failed" when a step completes, and "waiting" when blocked on external input.';
|
|
2148
|
+
return {
|
|
2149
|
+
description,
|
|
2150
|
+
inputSchema: reportStatusToolInputSchema,
|
|
2151
|
+
outputSchema: reportStatusToolOutputSchema,
|
|
2152
|
+
execute: executeReportStatusTool
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
|
|
1588
2156
|
// src/ai/workflow-tools.ts
|
|
1589
2157
|
function approveByHumanTool(clientOrContext, maybeOptions = {}) {
|
|
1590
2158
|
return buildApproveByHumanToolDefinition(clientOrContext, maybeOptions);
|
|
@@ -1595,21 +2163,29 @@ function createSendToHumanTool(clientOrOptions, maybeOptions) {
|
|
|
1595
2163
|
function createSendUpdateTool(clientOrOptions, maybeOptions = {}) {
|
|
1596
2164
|
return buildSendUpdateToolDefinition(clientOrOptions, maybeOptions);
|
|
1597
2165
|
}
|
|
2166
|
+
function requestActionInputTool(options = {}) {
|
|
2167
|
+
return buildRequestActionInputToolDefinition(options);
|
|
2168
|
+
}
|
|
2169
|
+
function reportStatusTool(options = {}) {
|
|
2170
|
+
return buildReportStatusToolDefinition(options);
|
|
2171
|
+
}
|
|
1598
2172
|
function createRobotRockAiTools(options = {}) {
|
|
1599
|
-
const
|
|
2173
|
+
const context2 = { mode: "workflow", app: options.app };
|
|
1600
2174
|
return {
|
|
1601
|
-
context,
|
|
1602
|
-
approveByHuman: (toolOptions) => buildApproveByHumanToolDefinition({ ...
|
|
2175
|
+
context: context2,
|
|
2176
|
+
approveByHuman: (toolOptions) => buildApproveByHumanToolDefinition({ ...context2, ...toolOptions }),
|
|
1603
2177
|
sendToHuman: (toolOptions) => buildSendToHumanToolDefinition({
|
|
1604
|
-
...
|
|
2178
|
+
...context2,
|
|
1605
2179
|
...options.threadId ? { threadId: options.threadId } : {},
|
|
1606
2180
|
...toolOptions
|
|
1607
2181
|
}),
|
|
1608
2182
|
sendUpdate: (toolOptions = {}) => buildSendUpdateToolDefinition({
|
|
1609
|
-
...
|
|
2183
|
+
...context2,
|
|
1610
2184
|
...options.threadId ? { threadId: options.threadId } : {},
|
|
1611
2185
|
...toolOptions
|
|
1612
|
-
})
|
|
2186
|
+
}),
|
|
2187
|
+
requestActionInput: (toolOptions = {}) => buildRequestActionInputToolDefinition(toolOptions),
|
|
2188
|
+
reportStatus: (toolOptions = {}) => buildReportStatusToolDefinition(toolOptions)
|
|
1613
2189
|
};
|
|
1614
2190
|
}
|
|
1615
2191
|
|
|
@@ -1617,12 +2193,6 @@ function createRobotRockAiTools(options = {}) {
|
|
|
1617
2193
|
function defaultFormatToolApprovalTask(toolCall, options = {}) {
|
|
1618
2194
|
const approveId = options.approveActionId ?? "approve";
|
|
1619
2195
|
const denyId = options.denyActionId ?? "deny";
|
|
1620
|
-
let inputPreview;
|
|
1621
|
-
try {
|
|
1622
|
-
inputPreview = JSON.stringify(toolCall.input, null, 2);
|
|
1623
|
-
} catch {
|
|
1624
|
-
inputPreview = String(toolCall.input);
|
|
1625
|
-
}
|
|
1626
2196
|
return {
|
|
1627
2197
|
type: options.type ?? "ai-tool-approval",
|
|
1628
2198
|
name: `Approve: ${toolCall.toolName}`,
|
|
@@ -1820,7 +2390,7 @@ function resolveToolCallForRequest(request, source, messages) {
|
|
|
1820
2390
|
);
|
|
1821
2391
|
}
|
|
1822
2392
|
async function resolveToolApprovalsViaRobotRock(clientOrContext, source, options = {}) {
|
|
1823
|
-
const
|
|
2393
|
+
const context2 = normalizeRobotRockAiContext(clientOrContext);
|
|
1824
2394
|
const approveId = options.approveActionId ?? "approve";
|
|
1825
2395
|
const denyId = options.denyActionId ?? "deny";
|
|
1826
2396
|
const formatTask = options.formatTask ?? defaultFormatToolApprovalTask;
|
|
@@ -1833,7 +2403,7 @@ async function resolveToolApprovalsViaRobotRock(clientOrContext, source, options
|
|
|
1833
2403
|
approveActionId: approveId,
|
|
1834
2404
|
denyActionId: denyId
|
|
1835
2405
|
});
|
|
1836
|
-
const result = await sendToHumanForAi(
|
|
2406
|
+
const result = await sendToHumanForAi(context2, taskInput);
|
|
1837
2407
|
const approved = result.actionId === approveId;
|
|
1838
2408
|
const reason = typeof result.data === "object" && result.data !== null && "reason" in result.data && typeof result.data.reason === "string" ? result.data.reason : approved ? "Approved in RobotRock inbox" : "Denied in RobotRock inbox";
|
|
1839
2409
|
responses.push({
|
|
@@ -1879,6 +2449,8 @@ export {
|
|
|
1879
2449
|
createRobotRockToolApproval,
|
|
1880
2450
|
createSendToHumanTool,
|
|
1881
2451
|
createSendUpdateTool,
|
|
2452
|
+
reportStatusTool,
|
|
2453
|
+
requestActionInputTool,
|
|
1882
2454
|
resolveToolApprovalsViaRobotRock,
|
|
1883
2455
|
runWithRobotRockApprovals
|
|
1884
2456
|
};
|