robotrock 0.9.0 → 1.1.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.
Files changed (52) hide show
  1. package/dist/ai/index.d.ts +18 -7
  2. package/dist/ai/index.js +852 -115
  3. package/dist/ai/index.js.map +1 -1
  4. package/dist/ai/trigger.d.ts +4 -3
  5. package/dist/ai/trigger.js +810 -115
  6. package/dist/ai/trigger.js.map +1 -1
  7. package/dist/ai/workflow.d.ts +15 -4
  8. package/dist/ai/workflow.js +729 -115
  9. package/dist/ai/workflow.js.map +1 -1
  10. package/dist/client-XTnFHGFE.d.ts +248 -0
  11. package/dist/eve/agent/index.d.ts +188 -0
  12. package/dist/eve/agent/index.js +2322 -0
  13. package/dist/eve/agent/index.js.map +1 -0
  14. package/dist/eve/index.d.ts +5 -0
  15. package/dist/eve/index.js +446 -0
  16. package/dist/eve/index.js.map +1 -0
  17. package/dist/eve/tools/identity/index.d.ts +6 -0
  18. package/dist/eve/tools/identity/index.js +144 -0
  19. package/dist/eve/tools/identity/index.js.map +1 -0
  20. package/dist/eve/tools/identity/my-access.d.ts +58 -0
  21. package/dist/eve/tools/identity/my-access.js +106 -0
  22. package/dist/eve/tools/identity/my-access.js.map +1 -0
  23. package/dist/eve/tools/identity/whoami.d.ts +45 -0
  24. package/dist/eve/tools/identity/whoami.js +101 -0
  25. package/dist/eve/tools/identity/whoami.js.map +1 -0
  26. package/dist/eve/tools/inbox/create-task.d.ts +113 -0
  27. package/dist/eve/tools/inbox/create-task.js +1557 -0
  28. package/dist/eve/tools/inbox/create-task.js.map +1 -0
  29. package/dist/eve/tools/inbox/index.d.ts +5 -0
  30. package/dist/eve/tools/inbox/index.js +1557 -0
  31. package/dist/eve/tools/inbox/index.js.map +1 -0
  32. package/dist/eve/tools/index.d.ts +17 -0
  33. package/dist/eve/tools/index.js +1654 -0
  34. package/dist/eve/tools/index.js.map +1 -0
  35. package/dist/index-BL9qKHA8.d.ts +141 -0
  36. package/dist/index.d.ts +12 -44
  37. package/dist/index.js +793 -97
  38. package/dist/index.js.map +1 -1
  39. package/dist/schemas/index.d.ts +11 -1
  40. package/dist/schemas/index.js +126 -8
  41. package/dist/schemas/index.js.map +1 -1
  42. package/dist/tenant-5YKDrdC-.d.ts +23 -0
  43. package/dist/{tool-approval-bridge-G765kMJR.d.ts → tool-approval-bridge-C4bTm8vu.d.ts} +93 -2
  44. package/dist/trigger/index.d.ts +2 -1
  45. package/dist/trigger/index.js +495 -87
  46. package/dist/trigger/index.js.map +1 -1
  47. package/dist/{trigger-D0shjqk0.d.ts → trigger-Dn0DFiyU.d.ts} +64 -3
  48. package/dist/workflow/index.d.ts +2 -1
  49. package/dist/workflow/index.js +496 -88
  50. package/dist/workflow/index.js.map +1 -1
  51. package/package.json +44 -7
  52. package/dist/client-Cy7YLxms.d.ts +0 -145
package/dist/index.js CHANGED
@@ -108,6 +108,25 @@ function isBlockedHostname(hostname) {
108
108
  }
109
109
  return isBlockedIpv4(host) || isBlockedIpv6(host);
110
110
  }
111
+ function isLoopbackHandlerUrl(urlString) {
112
+ let url;
113
+ try {
114
+ url = new URL(urlString);
115
+ } catch {
116
+ return false;
117
+ }
118
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
119
+ return false;
120
+ }
121
+ if (url.username || url.password) {
122
+ return false;
123
+ }
124
+ const host = url.hostname.toLowerCase();
125
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]" || host.endsWith(".localhost");
126
+ }
127
+ function isAllowedHandlerUrl(urlString) {
128
+ return isPublicHttpUrl(urlString) || isLoopbackHandlerUrl(urlString);
129
+ }
111
130
  function isPublicHttpUrl(urlString) {
112
131
  let url;
113
132
  try {
@@ -124,6 +143,7 @@ function isPublicHttpUrl(urlString) {
124
143
  return !isBlockedHostname(url.hostname);
125
144
  }
126
145
  var PUBLIC_HTTP_URL_ERROR = "URL must be a public http:// or https:// address";
146
+ var HANDLER_URL_ERROR = "Handler URL must be a public or loopback http:// or https:// address";
127
147
 
128
148
  // ../core/src/schemas/task.ts
129
149
  import { z } from "zod";
@@ -185,6 +205,9 @@ function validateContextPublicUrls(context2) {
185
205
  var safeUrlSchema = z.string().refine((url) => isPublicHttpUrl(url), {
186
206
  message: PUBLIC_HTTP_URL_ERROR
187
207
  });
208
+ var handlerUrlSchema = z.string().refine((url) => isAllowedHandlerUrl(url), {
209
+ message: HANDLER_URL_ERROR
210
+ });
188
211
  var jsonSchema7Schema = z.custom(
189
212
  (val) => typeof val === "object" && val !== null,
190
213
  { message: "Must be a valid JSON Schema object" }
@@ -194,7 +217,7 @@ var uiSchemaSchema = z.custom((val) => typeof val === "object" && val !== null,
194
217
  });
195
218
  var webhookHandlerSchema = z.object({
196
219
  type: z.literal("webhook"),
197
- url: safeUrlSchema,
220
+ url: handlerUrlSchema,
198
221
  headers: z.record(z.string(), z.string())
199
222
  });
200
223
  var triggerHandlerSchema = webhookHandlerSchema.extend({
@@ -202,13 +225,15 @@ var triggerHandlerSchema = webhookHandlerSchema.extend({
202
225
  tokenId: z.string().min(1)
203
226
  });
204
227
  var handlerSchema = z.discriminatedUnion("type", [webhookHandlerSchema, triggerHandlerSchema]);
205
- var taskActionSchema = z.object({
228
+ var taskActionInputSchema = z.object({
206
229
  id: z.string().min(1),
207
230
  title: z.string().min(1),
208
231
  description: z.string().optional(),
209
232
  schema: jsonSchema7Schema.optional(),
210
233
  ui: uiSchemaSchema.optional(),
211
- data: z.record(z.string(), z.unknown()).optional(),
234
+ data: z.record(z.string(), z.unknown()).optional()
235
+ });
236
+ var taskActionSchema = taskActionInputSchema.extend({
212
237
  // Optional handlers for this action - if present, must have at least 1
213
238
  handlers: z.array(handlerSchema).min(1).optional()
214
239
  });
@@ -316,10 +341,100 @@ var createTaskBodySchema = taskContextObjectBaseSchema.extend({
316
341
  /** Agent release version — not shown in inbox UI. */
317
342
  agent: agentTelemetrySchema.optional()
318
343
  }).transform(normalizeTaskContextVersion).superRefine(refineContextPublicUrls);
344
+ var agentChatSeedActionSchema = z.object({
345
+ /** Stable action id echoed back on submit; auto-derived from title when omitted. */
346
+ id: z.string().min(1).optional(),
347
+ title: z.string().min(1),
348
+ description: z.string().optional(),
349
+ /** JSON Schema object for the form fields. */
350
+ schema: z.record(z.string(), z.unknown()).optional(),
351
+ /** RJSF ui schema overrides (ui:widget, ui:enumNames, etc.). */
352
+ ui: z.record(z.string(), z.unknown()).optional(),
353
+ /** Optional default field values. */
354
+ data: z.record(z.string(), z.unknown()).optional()
355
+ });
356
+ var agentChatSeedMessageSchema = z.object({
357
+ role: z.enum(["user", "assistant"]),
358
+ text: z.string().min(1),
359
+ /** Optional display-name override for the message sender. */
360
+ senderName: z.string().min(1).optional(),
361
+ /**
362
+ * Optional structured input request rendered as a styled RobotRock action
363
+ * widget below the message text. Use this instead of asking the user to reply
364
+ * in plain text so the request is always a proper action form.
365
+ */
366
+ requestActionInput: z.object({
367
+ prompt: z.string().optional(),
368
+ action: agentChatSeedActionSchema
369
+ }).optional()
370
+ });
371
+ var eveAgentChatTransportSchema = z.object({
372
+ kind: z.literal("eve"),
373
+ chatId: z.string().min(1),
374
+ baseUrl: z.string().url(),
375
+ sessionId: z.string().optional(),
376
+ continuationToken: z.string().optional(),
377
+ streamIndex: z.number().int().nonnegative().optional(),
378
+ isStreaming: z.boolean().optional()
379
+ });
380
+ var createAgentChatBodySchema = z.object({
381
+ /** Agent id (eve agent name). Required unless `parentChatId` is set. */
382
+ agentIdentifier: z.string().min(1).optional(),
383
+ /** Inherit tenant/connection/agent from an existing chat (agent-spawned chats). */
384
+ parentChatId: z.string().min(1).optional(),
385
+ /** Convex tenantEveConnections id; resolved from the tenant when omitted. */
386
+ eveConnectionId: z.string().min(1).optional(),
387
+ /** Source application id; groups the chat under an inbox section. */
388
+ app: z.string().min(1).optional(),
389
+ assignTo: assignToSchema.optional(),
390
+ title: z.string().min(1),
391
+ messages: z.array(agentChatSeedMessageSchema).default([]),
392
+ /** Provenance label stored on the session ("cron" | "agent" | ...). */
393
+ source: z.string().min(1).optional()
394
+ }).refine((data) => Boolean(data.agentIdentifier || data.parentChatId), {
395
+ message: "Provide either agentIdentifier or parentChatId"
396
+ });
397
+ var agentChatAuditInputBodySchema = z.object({
398
+ eveSessionId: z.string().min(1),
399
+ userId: z.string().min(1),
400
+ actionId: z.string().min(1),
401
+ actionTitle: z.string().optional(),
402
+ prompt: z.string().optional(),
403
+ data: z.record(z.string(), z.unknown()).optional(),
404
+ idempotencyKey: z.string().optional(),
405
+ /** Eve input request id — used to merge staged HITL metadata. */
406
+ requestId: z.string().optional(),
407
+ /** Eve tool call id — fallback lookup for staged HITL metadata. */
408
+ toolCallId: z.string().optional()
409
+ });
410
+ var eveHitlStagedOptionSchema = z.object({
411
+ id: z.string(),
412
+ label: z.string()
413
+ });
414
+ var agentChatStageHitlBodySchema = z.object({
415
+ eveSessionId: z.string().min(1),
416
+ requests: z.array(
417
+ z.object({
418
+ requestId: z.string().min(1),
419
+ toolCallId: z.string().min(1),
420
+ toolName: z.string().min(1),
421
+ prompt: z.string().min(1),
422
+ display: z.enum(["confirmation", "select", "text"]).optional(),
423
+ allowFreeform: z.boolean().optional(),
424
+ options: z.array(eveHitlStagedOptionSchema).optional(),
425
+ toolInput: z.record(z.string(), z.unknown()).optional()
426
+ })
427
+ )
428
+ });
429
+ var agentChatLinkTaskBodySchema = z.object({
430
+ eveSessionId: z.string().min(1),
431
+ publicTaskId: z.string().min(1),
432
+ toolCallId: z.string().min(1)
433
+ });
319
434
 
320
435
  // src/schemas/index.ts
321
- var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
322
- message: PUBLIC_HTTP_URL_ERROR
436
+ var handlerUrlSchema2 = z2.string().refine((url) => isAllowedHandlerUrl(url), {
437
+ message: HANDLER_URL_ERROR
323
438
  });
324
439
  var jsonSchema7Schema2 = z2.custom(
325
440
  (val) => typeof val === "object" && val !== null,
@@ -330,7 +445,7 @@ var uiSchemaSchema2 = z2.custom((val) => typeof val === "object" && val !== null
330
445
  });
331
446
  var webhookHandlerSchema2 = z2.object({
332
447
  type: z2.literal("webhook"),
333
- url: safeUrlSchema2,
448
+ url: handlerUrlSchema2,
334
449
  headers: z2.record(z2.string(), z2.string())
335
450
  });
336
451
  var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
@@ -338,13 +453,15 @@ var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
338
453
  tokenId: z2.string().min(1)
339
454
  });
340
455
  var handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
341
- var taskActionSchema2 = z2.object({
456
+ var taskActionInputSchema2 = z2.object({
342
457
  id: z2.string().min(1),
343
458
  title: z2.string().min(1),
344
459
  description: z2.string().optional(),
345
460
  schema: jsonSchema7Schema2.optional(),
346
461
  ui: uiSchemaSchema2.optional(),
347
- data: z2.record(z2.string(), z2.unknown()).optional(),
462
+ data: z2.record(z2.string(), z2.unknown()).optional()
463
+ });
464
+ var taskActionSchema2 = taskActionInputSchema2.extend({
348
465
  handlers: z2.array(handlerSchema2).min(1).optional()
349
466
  });
350
467
  var uiFieldSchemaSchema2 = z2.object({
@@ -485,6 +602,293 @@ function toDiscriminatedApprovalResult(actions, task) {
485
602
  };
486
603
  }
487
604
 
605
+ // src/http.ts
606
+ var RobotRockError = class extends Error {
607
+ constructor(message, statusCode, response) {
608
+ super(message);
609
+ this.statusCode = statusCode;
610
+ this.response = response;
611
+ this.name = "RobotRockError";
612
+ }
613
+ };
614
+ async function parseResponseBody(response) {
615
+ const contentType = response.headers.get("content-type") ?? "";
616
+ const bodyText = await response.text();
617
+ if (!bodyText) {
618
+ return null;
619
+ }
620
+ if (contentType.toLowerCase().includes("application/json")) {
621
+ try {
622
+ return JSON.parse(bodyText);
623
+ } catch {
624
+ }
625
+ }
626
+ try {
627
+ return JSON.parse(bodyText);
628
+ } catch {
629
+ return bodyText;
630
+ }
631
+ }
632
+ function getErrorMessage(data, fallback) {
633
+ if (data && typeof data === "object" && !Array.isArray(data)) {
634
+ const record = data;
635
+ const maybeMessage = record.message;
636
+ const maybeHint = record.hint;
637
+ if (typeof maybeMessage === "string" && maybeMessage.trim()) {
638
+ if (typeof maybeHint === "string" && maybeHint.trim()) {
639
+ return `${maybeMessage.trim()} ${maybeHint.trim()}`;
640
+ }
641
+ return maybeMessage;
642
+ }
643
+ }
644
+ if (typeof data === "string" && data.trim()) {
645
+ const compact = data.replace(/\s+/g, " ").trim();
646
+ const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
647
+ return `${fallback}. Server returned non-JSON response: ${snippet}`;
648
+ }
649
+ return fallback;
650
+ }
651
+
652
+ // ../core/src/handler-retry.ts
653
+ var HANDLER_RETRY_DELAYS_MS = [
654
+ 6e4,
655
+ // 1m
656
+ 3e5,
657
+ // 5m
658
+ 18e5,
659
+ // 30m
660
+ 36e5,
661
+ // 1h
662
+ 216e5,
663
+ // 6h
664
+ 864e5,
665
+ // 24h
666
+ 1728e5
667
+ // 48h
668
+ ];
669
+ var HANDLER_MAX_ATTEMPTS = HANDLER_RETRY_DELAYS_MS.length + 1;
670
+
671
+ // ../core/src/attribution/index.ts
672
+ import { z as z3 } from "zod";
673
+
674
+ // ../core/src/app-url.ts
675
+ var PRODUCTION_APP_URL = "https://app.robotrock.io";
676
+ var PRODUCTION_API_URL = "https://api.robotrock.io/v1";
677
+ var DEV_API_URL = "http://localhost:4001/v1";
678
+ var APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
679
+ function normalizeRobotRockApiBaseUrl(baseUrl) {
680
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
681
+ if (trimmed.endsWith("/v1")) {
682
+ return trimmed;
683
+ }
684
+ return `${trimmed}/v1`;
685
+ }
686
+ function getRobotRockApiBaseUrl() {
687
+ const explicit = process.env.ROBOTROCK_BASE_URL?.trim() || process.env.ROBOTROCK_API_URL?.trim();
688
+ if (explicit) {
689
+ return normalizeRobotRockApiBaseUrl(explicit);
690
+ }
691
+ if (process.env.NODE_ENV === "production") {
692
+ return PRODUCTION_API_URL;
693
+ }
694
+ return DEV_API_URL;
695
+ }
696
+
697
+ // ../core/src/attribution/index.ts
698
+ var ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
699
+ var attributionSchema = z3.object({
700
+ utmSource: z3.string().optional(),
701
+ utmMedium: z3.string().optional(),
702
+ utmCampaign: z3.string().optional(),
703
+ utmContent: z3.string().optional(),
704
+ utmTerm: z3.string().optional(),
705
+ gclid: z3.string().optional(),
706
+ landingUrl: z3.string().optional(),
707
+ referrer: z3.string().optional(),
708
+ capturedAt: z3.number()
709
+ });
710
+
711
+ // src/auth-headers.ts
712
+ function buildRobotRockAuthHeaders(auth) {
713
+ if (auth.kind === "apiKey") {
714
+ return {
715
+ "X-Api-Key": auth.apiKey
716
+ };
717
+ }
718
+ return {
719
+ Authorization: `Bearer ${auth.token}`,
720
+ "X-RobotRock-Tenant-Slug": auth.tenantSlug,
721
+ "X-RobotRock-Connection-Id": auth.connectionId
722
+ };
723
+ }
724
+ function resolveRobotRockAuthConfig(overrides) {
725
+ if (overrides?.agentService) {
726
+ return {
727
+ kind: "agentService",
728
+ ...overrides.agentService
729
+ };
730
+ }
731
+ const apiKey = overrides?.apiKey ?? process.env.ROBOTROCK_API_KEY;
732
+ if (!apiKey) {
733
+ throw new Error(
734
+ "RobotRock auth is required. Set ROBOTROCK_API_KEY, ROBOTROCK_AGENT_SERVICE_TOKEN with tenant context, or pass auth when creating the client."
735
+ );
736
+ }
737
+ return { kind: "apiKey", apiKey };
738
+ }
739
+
740
+ // src/chats.ts
741
+ function createChatsApi(config) {
742
+ const headers = () => ({
743
+ "Content-Type": "application/json",
744
+ ...buildRobotRockAuthHeaders(config.auth)
745
+ });
746
+ return {
747
+ async create(input) {
748
+ const bodyPayload = {
749
+ ...input,
750
+ app: input.app ?? config.app,
751
+ messages: input.messages ?? []
752
+ };
753
+ const validation = createAgentChatBodySchema.safeParse(bodyPayload);
754
+ if (!validation.success) {
755
+ throw new RobotRockError(
756
+ `Invalid chat: ${validation.error.issues[0]?.message}`,
757
+ 400,
758
+ validation.error.issues
759
+ );
760
+ }
761
+ const response = await fetch(`${config.baseUrl}/agent-chats`, {
762
+ method: "POST",
763
+ headers: headers(),
764
+ body: JSON.stringify(validation.data)
765
+ });
766
+ const data = await parseResponseBody(response);
767
+ if (!response.ok) {
768
+ throw new RobotRockError(
769
+ getErrorMessage(data, "Failed to create chat"),
770
+ response.status,
771
+ data
772
+ );
773
+ }
774
+ const result = data;
775
+ return { tenantSlug: result.tenantSlug, chats: result.chats };
776
+ },
777
+ async close(chatId, options) {
778
+ if (!chatId) {
779
+ throw new RobotRockError("chatId is required to close a chat", 400);
780
+ }
781
+ const response = await fetch(
782
+ `${config.baseUrl}/agent-chats/${encodeURIComponent(chatId)}/close`,
783
+ {
784
+ method: "POST",
785
+ headers: headers(),
786
+ body: JSON.stringify({ reason: options?.reason })
787
+ }
788
+ );
789
+ if (!response.ok) {
790
+ const data = await parseResponseBody(response);
791
+ throw new RobotRockError(
792
+ getErrorMessage(data, "Failed to close chat"),
793
+ response.status,
794
+ data
795
+ );
796
+ }
797
+ },
798
+ async stageHitlRequests(input) {
799
+ const validation = agentChatStageHitlBodySchema.safeParse(input);
800
+ if (!validation.success) {
801
+ throw new RobotRockError(
802
+ `Invalid stage HITL input: ${validation.error.issues[0]?.message}`,
803
+ 400,
804
+ validation.error.issues
805
+ );
806
+ }
807
+ const response = await fetch(`${config.baseUrl}/agent-chats/stage-hitl`, {
808
+ method: "POST",
809
+ headers: headers(),
810
+ body: JSON.stringify(validation.data)
811
+ });
812
+ if (!response.ok) {
813
+ const data = await parseResponseBody(response);
814
+ throw new RobotRockError(
815
+ getErrorMessage(data, "Failed to stage chat HITL requests"),
816
+ response.status,
817
+ data
818
+ );
819
+ }
820
+ },
821
+ async getStagedHitlRequests(eveSessionId) {
822
+ const trimmed = eveSessionId.trim();
823
+ if (!trimmed) {
824
+ throw new RobotRockError("eveSessionId is required", 400);
825
+ }
826
+ const url = new URL(`${config.baseUrl}/agent-chats/staged-hitl`);
827
+ url.searchParams.set("eveSessionId", trimmed);
828
+ const response = await fetch(url.toString(), {
829
+ method: "GET",
830
+ headers: headers()
831
+ });
832
+ const data = await parseResponseBody(response);
833
+ if (!response.ok) {
834
+ throw new RobotRockError(
835
+ getErrorMessage(data, "Failed to fetch staged chat HITL requests"),
836
+ response.status,
837
+ data
838
+ );
839
+ }
840
+ const requests = data.requests;
841
+ return Array.isArray(requests) ? requests : [];
842
+ },
843
+ async logInputSubmission(input) {
844
+ const validation = agentChatAuditInputBodySchema.safeParse(input);
845
+ if (!validation.success) {
846
+ throw new RobotRockError(
847
+ `Invalid audit input: ${validation.error.issues[0]?.message}`,
848
+ 400,
849
+ validation.error.issues
850
+ );
851
+ }
852
+ const response = await fetch(`${config.baseUrl}/agent-chats/audit-input`, {
853
+ method: "POST",
854
+ headers: headers(),
855
+ body: JSON.stringify(validation.data)
856
+ });
857
+ if (!response.ok) {
858
+ const data = await parseResponseBody(response);
859
+ throw new RobotRockError(
860
+ getErrorMessage(data, "Failed to log chat input submission"),
861
+ response.status,
862
+ data
863
+ );
864
+ }
865
+ },
866
+ async linkTask(input) {
867
+ const validation = agentChatLinkTaskBodySchema.safeParse(input);
868
+ if (!validation.success) {
869
+ throw new RobotRockError(
870
+ `Invalid link task input: ${validation.error.issues[0]?.message}`,
871
+ 400,
872
+ validation.error.issues
873
+ );
874
+ }
875
+ const response = await fetch(`${config.baseUrl}/agent-chats/link-task`, {
876
+ method: "POST",
877
+ headers: headers(),
878
+ body: JSON.stringify(validation.data)
879
+ });
880
+ if (!response.ok) {
881
+ const data = await parseResponseBody(response);
882
+ throw new RobotRockError(
883
+ getErrorMessage(data, "Failed to link inbox task to chat"),
884
+ response.status,
885
+ data
886
+ );
887
+ }
888
+ }
889
+ };
890
+ }
891
+
488
892
  // src/client.ts
489
893
  var DEFAULT_POLL_INTERVAL_MS = 2e3;
490
894
  var DEFAULT_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
@@ -522,22 +926,18 @@ function serializeValidUntil(value) {
522
926
  }
523
927
  throw new RobotRockError("Invalid validUntil: expected a Date or parseable date string", 400);
524
928
  }
525
- var RobotRockError = class extends Error {
526
- constructor(message, statusCode, response) {
527
- super(message);
528
- this.statusCode = statusCode;
529
- this.response = response;
530
- this.name = "RobotRockError";
531
- }
532
- };
533
929
  var RobotRock = class {
534
- apiKey;
930
+ auth;
535
931
  baseUrl;
536
932
  app;
537
933
  agentVersion;
538
934
  contextVersion;
539
935
  webhook;
540
936
  polling;
937
+ /** Task CRUD: `create`, `get`, `cancel`, `sendUpdate`. */
938
+ tasks;
939
+ /** Chat CRUD: `create`, `close`. */
940
+ chats;
541
941
  constructor(config) {
542
942
  if (config.webhook && config.polling) {
543
943
  throw new Error(
@@ -545,24 +945,42 @@ var RobotRock = class {
545
945
  );
546
946
  }
547
947
  const apiKey = config.apiKey ?? process.env.ROBOTROCK_API_KEY;
548
- if (!apiKey) {
948
+ const agentService = config.agentService;
949
+ if (apiKey && agentService) {
549
950
  throw new Error(
550
- "RobotRock API key is required. Set ROBOTROCK_API_KEY or pass apiKey when creating the client."
951
+ "RobotRock client cannot configure both apiKey and agentService."
551
952
  );
552
953
  }
553
- this.apiKey = apiKey;
554
- const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
555
- this.baseUrl = rawBase.replace(/\/+$/, "");
954
+ this.auth = resolveRobotRockAuthConfig({
955
+ ...apiKey ? { apiKey } : {},
956
+ ...agentService ? { agentService } : {}
957
+ });
958
+ this.baseUrl = config.baseUrl ?? getRobotRockApiBaseUrl();
556
959
  this.app = config.app;
557
960
  this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
558
961
  this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
559
962
  this.webhook = config.webhook;
560
963
  this.polling = config.polling ?? {};
964
+ this.tasks = {
965
+ create: (task) => this.createTaskRequest(task),
966
+ get: (taskId) => this.getTaskById(taskId),
967
+ cancel: (taskId) => this.cancelTaskRequest(taskId),
968
+ sendUpdate: (input) => this.sendThreadUpdate(input)
969
+ };
970
+ this.chats = createChatsApi({
971
+ baseUrl: this.baseUrl,
972
+ auth: this.auth,
973
+ app: this.app
974
+ });
561
975
  }
562
- /**
563
- * Create a task via POST /v1 without waiting for a human response.
564
- */
565
- async createTask(task) {
976
+ authHeaders(extra) {
977
+ return {
978
+ "Content-Type": "application/json",
979
+ ...buildRobotRockAuthHeaders(this.auth),
980
+ ...extra
981
+ };
982
+ }
983
+ async createTaskRequest(task) {
566
984
  const normalizedTask = normalizeSendToHumanInput(task, {
567
985
  webhook: this.webhook,
568
986
  app: this.app,
@@ -586,13 +1004,9 @@ var RobotRock = class {
586
1004
  validation.error.issues
587
1005
  );
588
1006
  }
589
- const headers = {
590
- "Content-Type": "application/json",
591
- "X-Api-Key": this.apiKey
592
- };
593
- if (task.idempotencyKey) {
594
- headers["Idempotency-Key"] = task.idempotencyKey;
595
- }
1007
+ const headers = this.authHeaders(
1008
+ task.idempotencyKey ? { "Idempotency-Key": task.idempotencyKey } : void 0
1009
+ );
596
1010
  const response = await fetch(`${this.baseUrl}/`, {
597
1011
  method: "POST",
598
1012
  headers,
@@ -615,7 +1029,7 @@ var RobotRock = class {
615
1029
  contextVersion: this.contextVersion,
616
1030
  agentVersion: this.agentVersion
617
1031
  });
618
- const createdTaskTask = await this.createTask(task);
1032
+ const createdTaskTask = await this.createTaskRequest(task);
619
1033
  const hasHandlers = normalizedTask.actions.some(
620
1034
  (action) => Array.isArray(action.handlers) && action.handlers.length > 0
621
1035
  );
@@ -632,7 +1046,7 @@ var RobotRock = class {
632
1046
  const deadline = validUntilMs !== void 0 ? Math.min(pollingDeadline, validUntilMs) : pollingDeadline;
633
1047
  const taskId = createdTaskTask.taskId;
634
1048
  while (Date.now() < deadline) {
635
- const existing = await this.getTask(taskId);
1049
+ const existing = await this.getTaskById(taskId);
636
1050
  if (existing?.status === "handled" && existing.handled) {
637
1051
  return {
638
1052
  mode: "handled",
@@ -654,15 +1068,38 @@ var RobotRock = class {
654
1068
  }
655
1069
  throw new TaskTimeoutError(`No human response within ${timeoutMs}ms`);
656
1070
  }
1071
+ /**
1072
+ * Create a task via POST /v1 without waiting for a human response.
1073
+ * @deprecated Use `client.tasks.create()` instead.
1074
+ */
1075
+ async createTask(task) {
1076
+ return this.tasks.create(task);
1077
+ }
657
1078
  /**
658
1079
  * Get a task by public task id (returned as `task.taskId` from {@link sendToHuman}).
1080
+ * @deprecated Use `client.tasks.get()` instead.
659
1081
  */
660
1082
  async getTask(taskId) {
1083
+ return this.tasks.get(taskId);
1084
+ }
1085
+ /**
1086
+ * Log a status update against a thread.
1087
+ * @deprecated Use `client.tasks.sendUpdate()` instead.
1088
+ */
1089
+ async sendUpdate(input) {
1090
+ return this.tasks.sendUpdate(input);
1091
+ }
1092
+ /**
1093
+ * Cancel a task by public task id.
1094
+ * @deprecated Use `client.tasks.cancel()` instead.
1095
+ */
1096
+ async cancelTask(taskId) {
1097
+ return this.tasks.cancel(taskId);
1098
+ }
1099
+ async getTaskById(taskId) {
661
1100
  const response = await fetch(`${this.baseUrl}/tasks/${taskId}`, {
662
1101
  method: "GET",
663
- headers: {
664
- "X-Api-Key": this.apiKey
665
- }
1102
+ headers: this.authHeaders()
666
1103
  });
667
1104
  if (response.status === 404) {
668
1105
  return null;
@@ -677,11 +1114,11 @@ var RobotRock = class {
677
1114
  }
678
1115
  return data;
679
1116
  }
680
- /**
681
- * Log a status update against a thread. The update shows in the inbox status
682
- * bar and thread update log for every task in the thread.
683
- */
684
- async sendUpdate({ threadId, message, status }) {
1117
+ async sendThreadUpdate({
1118
+ threadId,
1119
+ message,
1120
+ status
1121
+ }) {
685
1122
  if (!threadId) {
686
1123
  throw new RobotRockError("threadId is required to send an update", 400);
687
1124
  }
@@ -697,10 +1134,7 @@ var RobotRock = class {
697
1134
  `${this.baseUrl}/threads/${encodeURIComponent(threadId)}/updates`,
698
1135
  {
699
1136
  method: "POST",
700
- headers: {
701
- "Content-Type": "application/json",
702
- "X-Api-Key": this.apiKey
703
- },
1137
+ headers: this.authHeaders(),
704
1138
  body: JSON.stringify(validation.data)
705
1139
  }
706
1140
  );
@@ -714,12 +1148,10 @@ var RobotRock = class {
714
1148
  }
715
1149
  return data.update;
716
1150
  }
717
- async cancelTask(taskId) {
1151
+ async cancelTaskRequest(taskId) {
718
1152
  const response = await fetch(`${this.baseUrl}/tasks/${taskId}/cancel`, {
719
1153
  method: "POST",
720
- headers: {
721
- "X-Api-Key": this.apiKey
722
- }
1154
+ headers: this.authHeaders()
723
1155
  });
724
1156
  if (!response.ok) {
725
1157
  const data = await parseResponseBody(response);
@@ -773,50 +1205,26 @@ function normalizeSendToHumanInput(task, clientDefaults) {
773
1205
  actions: normalizedActions
774
1206
  };
775
1207
  }
776
- async function parseResponseBody(response) {
777
- const contentType = response.headers.get("content-type") ?? "";
778
- const bodyText = await response.text();
779
- if (!bodyText) {
780
- return null;
781
- }
782
- if (contentType.toLowerCase().includes("application/json")) {
783
- try {
784
- return JSON.parse(bodyText);
785
- } catch {
786
- }
787
- }
788
- try {
789
- return JSON.parse(bodyText);
790
- } catch {
791
- return bodyText;
792
- }
793
- }
794
- function getErrorMessage(data, fallback) {
795
- if (data && typeof data === "object" && !Array.isArray(data)) {
796
- const maybeMessage = data.message;
797
- if (typeof maybeMessage === "string" && maybeMessage.trim()) {
798
- return maybeMessage;
799
- }
800
- }
801
- if (typeof data === "string" && data.trim()) {
802
- const compact = data.replace(/\s+/g, " ").trim();
803
- const snippet = compact.length > 180 ? `${compact.slice(0, 180)}...` : compact;
804
- return `${fallback}. Server returned non-JSON response: ${snippet}`;
805
- }
806
- return fallback;
807
- }
808
1208
 
809
1209
  // src/env.ts
810
- var DEFAULT_BASE_URL = "https://api.robotrock.io/v1";
811
1210
  function resolveRobotRockConfig(overrides) {
1211
+ const agentService = overrides?.agentService;
812
1212
  const apiKey = overrides?.apiKey ?? process.env.ROBOTROCK_API_KEY;
813
- if (!apiKey) {
1213
+ if (agentService && apiKey) {
814
1214
  throw new Error(
815
- "RobotRock API key is required. Set ROBOTROCK_API_KEY or pass apiKey when creating the client."
1215
+ "RobotRock client cannot configure both apiKey and agentService."
816
1216
  );
817
1217
  }
818
- const baseUrl = overrides?.baseUrl ?? process.env.ROBOTROCK_BASE_URL ?? process.env.ROBOTROCK_API_URL ?? DEFAULT_BASE_URL;
1218
+ const baseUrl = overrides?.baseUrl ?? getRobotRockApiBaseUrl();
819
1219
  const app = overrides?.app ?? process.env.ROBOTROCK_APP;
1220
+ if (agentService) {
1221
+ return app ? { agentService, baseUrl, app } : { agentService, baseUrl };
1222
+ }
1223
+ if (!apiKey) {
1224
+ throw new Error(
1225
+ "RobotRock API key is required. Set ROBOTROCK_API_KEY or pass agentService when creating the client."
1226
+ );
1227
+ }
820
1228
  return app ? { apiKey, baseUrl, app } : { apiKey, baseUrl };
821
1229
  }
822
1230
  function resolveRobotRockClient(client, configOverrides) {
@@ -917,20 +1325,291 @@ function shouldStopAgentForHandledAction(actionId) {
917
1325
  return isPlatformTerminalAction(actionId);
918
1326
  }
919
1327
 
1328
+ // src/eve/input-request.ts
1329
+ var EVE_INPUT_SUBMIT_ACTION_ID = "submit";
1330
+ var EVE_INPUT_OTHER_CHOICE_ID = "__other__";
1331
+ var EVE_INPUT_OTHER_CHOICE_LABEL = "Type your own answer";
1332
+ var CONFIRMATION_DEFAULT_OPTIONS = [
1333
+ { id: "approve", label: "Approve", style: "primary" },
1334
+ { id: "deny", label: "Deny", style: "danger" }
1335
+ ];
1336
+ var SELECT_PER_OPTION_THRESHOLD = 6;
1337
+ function asRecord(value) {
1338
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
1339
+ return null;
1340
+ }
1341
+ return value;
1342
+ }
1343
+ function readStringField(data, key) {
1344
+ const value = data[key];
1345
+ if (typeof value !== "string") {
1346
+ return void 0;
1347
+ }
1348
+ const trimmed = value.trim();
1349
+ return trimmed.length > 0 ? trimmed : void 0;
1350
+ }
1351
+ function resolveEveInputDisplay(request, toolName) {
1352
+ if (request.display) {
1353
+ return request.display;
1354
+ }
1355
+ if (toolName === "ask_question") {
1356
+ return request.options && request.options.length > 0 ? "select" : "text";
1357
+ }
1358
+ if (request.options && request.options.length > 0) {
1359
+ return "select";
1360
+ }
1361
+ return "confirmation";
1362
+ }
1363
+ function confirmationActions(request) {
1364
+ const options = request.options && request.options.length > 0 ? request.options : CONFIRMATION_DEFAULT_OPTIONS;
1365
+ return options.map((option) => ({
1366
+ id: option.id,
1367
+ title: option.label,
1368
+ ...option.description ? { description: option.description } : {}
1369
+ }));
1370
+ }
1371
+ function textSubmitAction(prompt) {
1372
+ return {
1373
+ id: EVE_INPUT_SUBMIT_ACTION_ID,
1374
+ title: "Submit",
1375
+ schema: {
1376
+ type: "object",
1377
+ required: ["answer"],
1378
+ properties: {
1379
+ answer: {
1380
+ type: "string",
1381
+ title: "Your answer"
1382
+ }
1383
+ }
1384
+ },
1385
+ ui: {
1386
+ answer: {
1387
+ "ui:title": prompt.trim() || "Your answer",
1388
+ "ui:widget": "textarea"
1389
+ }
1390
+ }
1391
+ };
1392
+ }
1393
+ function selectPerOptionActions(options) {
1394
+ return options.map((option) => ({
1395
+ id: option.id,
1396
+ title: option.label,
1397
+ ...option.description ? { description: option.description } : {}
1398
+ }));
1399
+ }
1400
+ function selectFormAction(request) {
1401
+ const options = request.options ?? [];
1402
+ const allowFreeform = request.allowFreeform === true;
1403
+ const enumValues = options.map((option) => option.id);
1404
+ const enumNames = options.map((option) => option.label);
1405
+ if (allowFreeform) {
1406
+ enumValues.push(EVE_INPUT_OTHER_CHOICE_ID);
1407
+ enumNames.push(EVE_INPUT_OTHER_CHOICE_LABEL);
1408
+ }
1409
+ const properties = {
1410
+ choice: {
1411
+ type: "string",
1412
+ title: "Choose one",
1413
+ enum: enumValues
1414
+ }
1415
+ };
1416
+ if (allowFreeform) {
1417
+ properties.other = {
1418
+ type: "string",
1419
+ title: "Your answer"
1420
+ };
1421
+ }
1422
+ const schema = {
1423
+ type: "object",
1424
+ required: ["choice"],
1425
+ properties
1426
+ };
1427
+ if (allowFreeform) {
1428
+ schema.allOf = [
1429
+ {
1430
+ if: {
1431
+ properties: {
1432
+ choice: { const: EVE_INPUT_OTHER_CHOICE_ID }
1433
+ },
1434
+ required: ["choice"]
1435
+ },
1436
+ then: {
1437
+ required: ["other"],
1438
+ properties: {
1439
+ other: {
1440
+ type: "string",
1441
+ minLength: 1
1442
+ }
1443
+ }
1444
+ }
1445
+ }
1446
+ ];
1447
+ }
1448
+ const ui = {
1449
+ choice: {
1450
+ "ui:widget": "radio",
1451
+ "ui:enumNames": enumNames
1452
+ }
1453
+ };
1454
+ if (allowFreeform) {
1455
+ ui.other = {
1456
+ "ui:placeholder": "Enter your answer"
1457
+ };
1458
+ }
1459
+ return {
1460
+ id: EVE_INPUT_SUBMIT_ACTION_ID,
1461
+ title: "Submit",
1462
+ schema,
1463
+ ui
1464
+ };
1465
+ }
1466
+ function normalizeEveSelectFormData(data) {
1467
+ const choice = typeof data.choice === "string" ? data.choice.trim() : void 0;
1468
+ if (!choice) {
1469
+ return data;
1470
+ }
1471
+ if (choice === EVE_INPUT_OTHER_CHOICE_ID) {
1472
+ return {
1473
+ choice,
1474
+ ...data.other !== void 0 ? { other: data.other } : {}
1475
+ };
1476
+ }
1477
+ return { choice };
1478
+ }
1479
+ function eveInputRequestToActions(request, options) {
1480
+ const display = resolveEveInputDisplay(request, options?.toolName);
1481
+ switch (display) {
1482
+ case "confirmation":
1483
+ return confirmationActions(request);
1484
+ case "text":
1485
+ return [textSubmitAction(request.prompt)];
1486
+ case "select": {
1487
+ const selectOptions = request.options ?? [];
1488
+ if (selectOptions.length === 0) {
1489
+ return [textSubmitAction(request.prompt)];
1490
+ }
1491
+ if (selectOptions.length <= SELECT_PER_OPTION_THRESHOLD && request.allowFreeform !== true) {
1492
+ return selectPerOptionActions(selectOptions);
1493
+ }
1494
+ return [selectFormAction(request)];
1495
+ }
1496
+ }
1497
+ }
1498
+ function eveInputRequestTaskType(request, options) {
1499
+ const display = resolveEveInputDisplay(request, options?.toolName);
1500
+ if (display === "confirmation" && options?.toolName) {
1501
+ return `eve-approval:${options.toolName}`;
1502
+ }
1503
+ return `eve-input:${display}`;
1504
+ }
1505
+ function taskHandledToEveInputResponse(request, actionId, actionData, options) {
1506
+ const base = { requestId: request.requestId };
1507
+ if (isPlatformTerminalAction(actionId)) {
1508
+ const feedback = parsePlatformRejectRequestData(actionData)?.feedback;
1509
+ return {
1510
+ ...base,
1511
+ optionId: "deny",
1512
+ ...feedback ? { text: feedback } : {}
1513
+ };
1514
+ }
1515
+ const display = resolveEveInputDisplay(request, options?.toolName);
1516
+ const selectOptions = request.options ?? [];
1517
+ const data = asRecord(actionData);
1518
+ if (display === "confirmation") {
1519
+ return { ...base, optionId: actionId };
1520
+ }
1521
+ const matchingOption = selectOptions.find((option) => option.id === actionId);
1522
+ if (matchingOption) {
1523
+ return { ...base, optionId: actionId };
1524
+ }
1525
+ if (actionId === EVE_INPUT_SUBMIT_ACTION_ID && data) {
1526
+ const submissionData = display === "select" && request.allowFreeform === true ? normalizeEveSelectFormData(data) : data;
1527
+ const answer = readStringField(submissionData, "answer");
1528
+ if (answer) {
1529
+ return { ...base, text: answer };
1530
+ }
1531
+ const choice = readStringField(submissionData, "choice");
1532
+ if (choice === EVE_INPUT_OTHER_CHOICE_ID) {
1533
+ const other = readStringField(submissionData, "other");
1534
+ if (other) {
1535
+ return { ...base, text: other };
1536
+ }
1537
+ }
1538
+ if (choice) {
1539
+ if (selectOptions.some((option) => option.id === choice)) {
1540
+ return { ...base, optionId: choice };
1541
+ }
1542
+ return { ...base, text: choice };
1543
+ }
1544
+ }
1545
+ if (data) {
1546
+ const answer = readStringField(data, "answer");
1547
+ if (answer) {
1548
+ return { ...base, text: answer };
1549
+ }
1550
+ }
1551
+ return { ...base, optionId: actionId };
1552
+ }
1553
+
1554
+ // src/eve/tool-display.ts
1555
+ var DEFAULT_TOOL_DISPLAY_LABELS = {
1556
+ refund_charge: "Refund a customer charge",
1557
+ deploy_release: "Deploy a release",
1558
+ get_weather: "Get weather",
1559
+ get_my_access: "Check my access",
1560
+ whoami: "Who am I",
1561
+ create_robotrock_task: "Create a RobotRock task"
1562
+ };
1563
+ var toolDisplayLabelOverrides = {};
1564
+ function setToolDisplayLabelOverrides(overrides) {
1565
+ toolDisplayLabelOverrides = overrides;
1566
+ }
1567
+ function formatToolName(toolName) {
1568
+ const spaced = toolName.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").trim();
1569
+ if (!spaced) {
1570
+ return "Tool";
1571
+ }
1572
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
1573
+ }
1574
+ function getToolDisplayLabel(toolName) {
1575
+ const trimmed = toolName.trim();
1576
+ if (!trimmed) {
1577
+ return "Tool";
1578
+ }
1579
+ return toolDisplayLabelOverrides[trimmed] ?? DEFAULT_TOOL_DISPLAY_LABELS[trimmed] ?? formatToolName(trimmed);
1580
+ }
1581
+ function formatEveApprovalTitle(request, toolName) {
1582
+ const display = resolveEveInputDisplay(request, toolName);
1583
+ if (display !== "confirmation" || !toolName) {
1584
+ return request.prompt;
1585
+ }
1586
+ return `Approve: ${getToolDisplayLabel(toolName)}`;
1587
+ }
1588
+
1589
+ // src/eve/resume-message.ts
1590
+ function buildTaskHandledResumeMessage(payload) {
1591
+ const handledBy = payload.handledBy?.trim() || "someone";
1592
+ const actionTitle = payload.action.title.trim();
1593
+ return `RobotRock task ${payload.taskId} was handled: ${actionTitle} by ${handledBy}. Briefly tell the user what was decided and what happens next.`;
1594
+ }
1595
+
1596
+ // src/eve/index.ts
1597
+ var ROBOTROCK_READY_HOOK_SLUG = "robotrock-ready";
1598
+
920
1599
  // src/webhook.ts
921
1600
  import { createHmac, timingSafeEqual } from "crypto";
922
- import { z as z3 } from "zod";
1601
+ import { z as z4 } from "zod";
923
1602
  var ROBOTROCK_SIGNATURE_HEADER = "x-robotrock-signature";
924
- var robotRockWebhookPayloadBodySchema = z3.object({
925
- taskId: z3.string().min(1),
926
- action: z3.object({
927
- id: z3.string().min(1),
928
- title: z3.string().min(1),
929
- data: z3.unknown()
1603
+ var robotRockWebhookPayloadBodySchema = z4.object({
1604
+ taskId: z4.string().min(1),
1605
+ action: z4.object({
1606
+ id: z4.string().min(1),
1607
+ title: z4.string().min(1),
1608
+ data: z4.unknown()
930
1609
  }),
931
- handledBy: z3.string().min(1).optional(),
932
- handledAt: z3.string().min(1),
933
- handlerType: z3.string().min(1)
1610
+ handledBy: z4.string().min(1).optional(),
1611
+ handledAt: z4.string().min(1),
1612
+ handlerType: z4.string().min(1)
934
1613
  });
935
1614
  var RobotRockWebhookError = class extends Error {
936
1615
  constructor(message, code, details) {
@@ -1216,6 +1895,10 @@ function finishRobotRockHumanWaitOtel(session, handled, outcome) {
1216
1895
  export {
1217
1896
  DEFAULT_TASK_PRIORITY,
1218
1897
  DEFAULT_THREAD_UPDATE_STATUS,
1898
+ DEFAULT_TOOL_DISPLAY_LABELS,
1899
+ EVE_INPUT_OTHER_CHOICE_ID,
1900
+ EVE_INPUT_OTHER_CHOICE_LABEL,
1901
+ EVE_INPUT_SUBMIT_ACTION_ID,
1219
1902
  LOWEST_TASK_PRIORITY,
1220
1903
  PLATFORM_MARK_DONE_ACTION_ID,
1221
1904
  PLATFORM_MARK_DONE_ACTION_TITLE,
@@ -1223,6 +1906,7 @@ export {
1223
1906
  PLATFORM_REJECT_REQUEST_ACTION_TITLE,
1224
1907
  PLATFORM_TERMINAL_ACTION_IDS,
1225
1908
  PlatformRejectRequestError,
1909
+ ROBOTROCK_READY_HOOK_SLUG,
1226
1910
  RobotRock,
1227
1911
  RobotRockError,
1228
1912
  RobotRockWebhookError,
@@ -1230,29 +1914,41 @@ export {
1230
1914
  TASK_PRIORITY_RANK,
1231
1915
  TaskExpiredError,
1232
1916
  TaskTimeoutError,
1917
+ agentChatSeedMessageSchema,
1233
1918
  agentTelemetrySchema2 as agentTelemetrySchema,
1234
1919
  assertNotPlatformRejectRequest,
1235
1920
  assignToSchema2 as assignToSchema,
1236
1921
  attachWebhookToActions,
1237
1922
  beginRobotRockHumanWaitOtel,
1923
+ buildTaskHandledResumeMessage,
1238
1924
  captureRobotRockOtelHandle,
1925
+ createAgentChatBodySchema,
1926
+ createChatsApi,
1239
1927
  createClient,
1240
1928
  createTaskBodySchema2 as createTaskBodySchema,
1241
1929
  endRobotRockHumanWaitSpan,
1930
+ eveInputRequestTaskType,
1931
+ eveInputRequestToActions,
1242
1932
  finishRobotRockHumanWaitOtel,
1933
+ formatEveApprovalTitle,
1934
+ getToolDisplayLabel,
1243
1935
  isPlatformMarkDoneAction,
1244
1936
  isPlatformRejectRequestAction,
1245
1937
  isPlatformTerminalAction,
1938
+ normalizeEveSelectFormData,
1246
1939
  parseHandledOutcome,
1247
1940
  parsePlatformRejectRequestData,
1248
1941
  recordRobotRockHandledToOtel,
1942
+ resolveEveInputDisplay,
1249
1943
  resolveRobotRockClient,
1250
1944
  resolveRobotRockConfig,
1945
+ setToolDisplayLabelOverrides,
1251
1946
  shouldRecordRobotRockOtel,
1252
1947
  shouldStopAgentForHandledAction,
1253
1948
  startRobotRockHumanWaitSpan,
1254
1949
  stripPlatformOtelFields,
1255
1950
  taskContextSchema2 as taskContextSchema,
1951
+ taskHandledToEveInputResponse,
1256
1952
  taskPriorities2 as taskPriorities,
1257
1953
  taskPrioritySchema2 as taskPrioritySchema,
1258
1954
  threadUpdateBodySchema,