robotrock 1.0.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 (50) hide show
  1. package/dist/ai/index.d.ts +5 -5
  2. package/dist/ai/index.js +285 -47
  3. package/dist/ai/index.js.map +1 -1
  4. package/dist/ai/trigger.d.ts +3 -3
  5. package/dist/ai/trigger.js +285 -47
  6. package/dist/ai/trigger.js.map +1 -1
  7. package/dist/ai/workflow.d.ts +3 -3
  8. package/dist/ai/workflow.js +285 -47
  9. package/dist/ai/workflow.js.map +1 -1
  10. package/dist/{client-CzVmjXpz.d.ts → client-XTnFHGFE.d.ts} +34 -5
  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 +5 -44
  37. package/dist/index.js +541 -42
  38. package/dist/index.js.map +1 -1
  39. package/dist/schemas/index.js +75 -12
  40. package/dist/schemas/index.js.map +1 -1
  41. package/dist/tenant-5YKDrdC-.d.ts +23 -0
  42. package/dist/{tool-approval-bridge-DbwUEBHv.d.ts → tool-approval-bridge-C4bTm8vu.d.ts} +1 -1
  43. package/dist/trigger/index.d.ts +1 -1
  44. package/dist/trigger/index.js +256 -42
  45. package/dist/trigger/index.js.map +1 -1
  46. package/dist/{trigger-BCKBbAV7.d.ts → trigger-Dn0DFiyU.d.ts} +2 -2
  47. package/dist/workflow/index.d.ts +1 -1
  48. package/dist/workflow/index.js +256 -42
  49. package/dist/workflow/index.js.map +1 -1
  50. package/package.json +44 -7
@@ -305,6 +305,25 @@ function isBlockedHostname(hostname) {
305
305
  }
306
306
  return isBlockedIpv4(host) || isBlockedIpv6(host);
307
307
  }
308
+ function isLoopbackHandlerUrl(urlString) {
309
+ let url;
310
+ try {
311
+ url = new URL(urlString);
312
+ } catch {
313
+ return false;
314
+ }
315
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
316
+ return false;
317
+ }
318
+ if (url.username || url.password) {
319
+ return false;
320
+ }
321
+ const host = url.hostname.toLowerCase();
322
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]" || host.endsWith(".localhost");
323
+ }
324
+ function isAllowedHandlerUrl(urlString) {
325
+ return isPublicHttpUrl(urlString) || isLoopbackHandlerUrl(urlString);
326
+ }
308
327
  function isPublicHttpUrl(urlString) {
309
328
  let url;
310
329
  try {
@@ -321,6 +340,7 @@ function isPublicHttpUrl(urlString) {
321
340
  return !isBlockedHostname(url.hostname);
322
341
  }
323
342
  var PUBLIC_HTTP_URL_ERROR = "URL must be a public http:// or https:// address";
343
+ var HANDLER_URL_ERROR = "Handler URL must be a public or loopback http:// or https:// address";
324
344
 
325
345
  // ../core/src/schemas/task.ts
326
346
  import { z } from "zod";
@@ -382,6 +402,9 @@ function validateContextPublicUrls(context2) {
382
402
  var safeUrlSchema = z.string().refine((url) => isPublicHttpUrl(url), {
383
403
  message: PUBLIC_HTTP_URL_ERROR
384
404
  });
405
+ var handlerUrlSchema = z.string().refine((url) => isAllowedHandlerUrl(url), {
406
+ message: HANDLER_URL_ERROR
407
+ });
385
408
  var jsonSchema7Schema = z.custom(
386
409
  (val) => typeof val === "object" && val !== null,
387
410
  { message: "Must be a valid JSON Schema object" }
@@ -391,7 +414,7 @@ var uiSchemaSchema = z.custom((val) => typeof val === "object" && val !== null,
391
414
  });
392
415
  var webhookHandlerSchema = z.object({
393
416
  type: z.literal("webhook"),
394
- url: safeUrlSchema,
417
+ url: handlerUrlSchema,
395
418
  headers: z.record(z.string(), z.string())
396
419
  });
397
420
  var triggerHandlerSchema = webhookHandlerSchema.extend({
@@ -542,13 +565,22 @@ var agentChatSeedMessageSchema = z.object({
542
565
  action: agentChatSeedActionSchema
543
566
  }).optional()
544
567
  });
568
+ var eveAgentChatTransportSchema = z.object({
569
+ kind: z.literal("eve"),
570
+ chatId: z.string().min(1),
571
+ baseUrl: z.string().url(),
572
+ sessionId: z.string().optional(),
573
+ continuationToken: z.string().optional(),
574
+ streamIndex: z.number().int().nonnegative().optional(),
575
+ isStreaming: z.boolean().optional()
576
+ });
545
577
  var createAgentChatBodySchema = z.object({
546
- /** Trigger chat agent id (task slug). Required unless `parentChatId` is set. */
578
+ /** Agent id (eve agent name). Required unless `parentChatId` is set. */
547
579
  agentIdentifier: z.string().min(1).optional(),
548
580
  /** Inherit tenant/connection/agent from an existing chat (agent-spawned chats). */
549
581
  parentChatId: z.string().min(1).optional(),
550
- /** Convex tenantTriggerConnections id; resolved from the tenant when omitted. */
551
- connectionId: z.string().min(1).optional(),
582
+ /** Convex tenantEveConnections id; resolved from the tenant when omitted. */
583
+ eveConnectionId: z.string().min(1).optional(),
552
584
  /** Source application id; groups the chat under an inbox section. */
553
585
  app: z.string().min(1).optional(),
554
586
  assignTo: assignToSchema.optional(),
@@ -559,16 +591,47 @@ var createAgentChatBodySchema = z.object({
559
591
  }).refine((data) => Boolean(data.agentIdentifier || data.parentChatId), {
560
592
  message: "Provide either agentIdentifier or parentChatId"
561
593
  });
562
- var agentChatTransportBodySchema = z.object({
563
- chatId: z.string().min(1),
564
- publicAccessToken: z.string().min(1),
565
- lastEventId: z.string().optional(),
566
- isStreaming: z.boolean().optional()
594
+ var agentChatAuditInputBodySchema = z.object({
595
+ eveSessionId: z.string().min(1),
596
+ userId: z.string().min(1),
597
+ actionId: z.string().min(1),
598
+ actionTitle: z.string().optional(),
599
+ prompt: z.string().optional(),
600
+ data: z.record(z.string(), z.unknown()).optional(),
601
+ idempotencyKey: z.string().optional(),
602
+ /** Eve input request id — used to merge staged HITL metadata. */
603
+ requestId: z.string().optional(),
604
+ /** Eve tool call id — fallback lookup for staged HITL metadata. */
605
+ toolCallId: z.string().optional()
606
+ });
607
+ var eveHitlStagedOptionSchema = z.object({
608
+ id: z.string(),
609
+ label: z.string()
610
+ });
611
+ var agentChatStageHitlBodySchema = z.object({
612
+ eveSessionId: z.string().min(1),
613
+ requests: z.array(
614
+ z.object({
615
+ requestId: z.string().min(1),
616
+ toolCallId: z.string().min(1),
617
+ toolName: z.string().min(1),
618
+ prompt: z.string().min(1),
619
+ display: z.enum(["confirmation", "select", "text"]).optional(),
620
+ allowFreeform: z.boolean().optional(),
621
+ options: z.array(eveHitlStagedOptionSchema).optional(),
622
+ toolInput: z.record(z.string(), z.unknown()).optional()
623
+ })
624
+ )
625
+ });
626
+ var agentChatLinkTaskBodySchema = z.object({
627
+ eveSessionId: z.string().min(1),
628
+ publicTaskId: z.string().min(1),
629
+ toolCallId: z.string().min(1)
567
630
  });
568
631
 
569
632
  // src/schemas/index.ts
570
- var safeUrlSchema2 = z2.string().refine((url) => isPublicHttpUrl(url), {
571
- message: PUBLIC_HTTP_URL_ERROR
633
+ var handlerUrlSchema2 = z2.string().refine((url) => isAllowedHandlerUrl(url), {
634
+ message: HANDLER_URL_ERROR
572
635
  });
573
636
  var jsonSchema7Schema2 = z2.custom(
574
637
  (val) => typeof val === "object" && val !== null,
@@ -579,7 +642,7 @@ var uiSchemaSchema2 = z2.custom((val) => typeof val === "object" && val !== null
579
642
  });
580
643
  var webhookHandlerSchema2 = z2.object({
581
644
  type: z2.literal("webhook"),
582
- url: safeUrlSchema2,
645
+ url: handlerUrlSchema2,
583
646
  headers: z2.record(z2.string(), z2.string())
584
647
  });
585
648
  var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
@@ -756,8 +819,13 @@ async function parseResponseBody(response) {
756
819
  }
757
820
  function getErrorMessage(data, fallback) {
758
821
  if (data && typeof data === "object" && !Array.isArray(data)) {
759
- const maybeMessage = data.message;
822
+ const record = data;
823
+ const maybeMessage = record.message;
824
+ const maybeHint = record.hint;
760
825
  if (typeof maybeMessage === "string" && maybeMessage.trim()) {
826
+ if (typeof maybeHint === "string" && maybeHint.trim()) {
827
+ return `${maybeMessage.trim()} ${maybeHint.trim()}`;
828
+ }
761
829
  return maybeMessage;
762
830
  }
763
831
  }
@@ -793,7 +861,26 @@ import { z as z3 } from "zod";
793
861
 
794
862
  // ../core/src/app-url.ts
795
863
  var PRODUCTION_APP_URL = "https://app.robotrock.io";
864
+ var PRODUCTION_API_URL = "https://api.robotrock.io/v1";
865
+ var DEV_API_URL = "http://localhost:4001/v1";
796
866
  var APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
867
+ function normalizeRobotRockApiBaseUrl(baseUrl) {
868
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
869
+ if (trimmed.endsWith("/v1")) {
870
+ return trimmed;
871
+ }
872
+ return `${trimmed}/v1`;
873
+ }
874
+ function getRobotRockApiBaseUrl() {
875
+ const explicit = process.env.ROBOTROCK_BASE_URL?.trim() || process.env.ROBOTROCK_API_URL?.trim();
876
+ if (explicit) {
877
+ return normalizeRobotRockApiBaseUrl(explicit);
878
+ }
879
+ if (process.env.NODE_ENV === "production") {
880
+ return PRODUCTION_API_URL;
881
+ }
882
+ return DEV_API_URL;
883
+ }
797
884
 
798
885
  // ../core/src/attribution/index.ts
799
886
  var ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
@@ -809,11 +896,40 @@ var attributionSchema = z3.object({
809
896
  capturedAt: z3.number()
810
897
  });
811
898
 
899
+ // src/auth-headers.ts
900
+ function buildRobotRockAuthHeaders(auth) {
901
+ if (auth.kind === "apiKey") {
902
+ return {
903
+ "X-Api-Key": auth.apiKey
904
+ };
905
+ }
906
+ return {
907
+ Authorization: `Bearer ${auth.token}`,
908
+ "X-RobotRock-Tenant-Slug": auth.tenantSlug,
909
+ "X-RobotRock-Connection-Id": auth.connectionId
910
+ };
911
+ }
912
+ function resolveRobotRockAuthConfig(overrides) {
913
+ if (overrides?.agentService) {
914
+ return {
915
+ kind: "agentService",
916
+ ...overrides.agentService
917
+ };
918
+ }
919
+ const apiKey = overrides?.apiKey ?? process.env.ROBOTROCK_API_KEY;
920
+ if (!apiKey) {
921
+ throw new Error(
922
+ "RobotRock auth is required. Set ROBOTROCK_API_KEY, ROBOTROCK_AGENT_SERVICE_TOKEN with tenant context, or pass auth when creating the client."
923
+ );
924
+ }
925
+ return { kind: "apiKey", apiKey };
926
+ }
927
+
812
928
  // src/chats.ts
813
929
  function createChatsApi(config) {
814
930
  const headers = () => ({
815
931
  "Content-Type": "application/json",
816
- "X-Api-Key": config.apiKey
932
+ ...buildRobotRockAuthHeaders(config.auth)
817
933
  });
818
934
  return {
819
935
  async create(input) {
@@ -866,6 +982,97 @@ function createChatsApi(config) {
866
982
  data
867
983
  );
868
984
  }
985
+ },
986
+ async stageHitlRequests(input) {
987
+ const validation = agentChatStageHitlBodySchema.safeParse(input);
988
+ if (!validation.success) {
989
+ throw new RobotRockError(
990
+ `Invalid stage HITL input: ${validation.error.issues[0]?.message}`,
991
+ 400,
992
+ validation.error.issues
993
+ );
994
+ }
995
+ const response = await fetch(`${config.baseUrl}/agent-chats/stage-hitl`, {
996
+ method: "POST",
997
+ headers: headers(),
998
+ body: JSON.stringify(validation.data)
999
+ });
1000
+ if (!response.ok) {
1001
+ const data = await parseResponseBody(response);
1002
+ throw new RobotRockError(
1003
+ getErrorMessage(data, "Failed to stage chat HITL requests"),
1004
+ response.status,
1005
+ data
1006
+ );
1007
+ }
1008
+ },
1009
+ async getStagedHitlRequests(eveSessionId) {
1010
+ const trimmed = eveSessionId.trim();
1011
+ if (!trimmed) {
1012
+ throw new RobotRockError("eveSessionId is required", 400);
1013
+ }
1014
+ const url = new URL(`${config.baseUrl}/agent-chats/staged-hitl`);
1015
+ url.searchParams.set("eveSessionId", trimmed);
1016
+ const response = await fetch(url.toString(), {
1017
+ method: "GET",
1018
+ headers: headers()
1019
+ });
1020
+ const data = await parseResponseBody(response);
1021
+ if (!response.ok) {
1022
+ throw new RobotRockError(
1023
+ getErrorMessage(data, "Failed to fetch staged chat HITL requests"),
1024
+ response.status,
1025
+ data
1026
+ );
1027
+ }
1028
+ const requests = data.requests;
1029
+ return Array.isArray(requests) ? requests : [];
1030
+ },
1031
+ async logInputSubmission(input) {
1032
+ const validation = agentChatAuditInputBodySchema.safeParse(input);
1033
+ if (!validation.success) {
1034
+ throw new RobotRockError(
1035
+ `Invalid audit input: ${validation.error.issues[0]?.message}`,
1036
+ 400,
1037
+ validation.error.issues
1038
+ );
1039
+ }
1040
+ const response = await fetch(`${config.baseUrl}/agent-chats/audit-input`, {
1041
+ method: "POST",
1042
+ headers: headers(),
1043
+ body: JSON.stringify(validation.data)
1044
+ });
1045
+ if (!response.ok) {
1046
+ const data = await parseResponseBody(response);
1047
+ throw new RobotRockError(
1048
+ getErrorMessage(data, "Failed to log chat input submission"),
1049
+ response.status,
1050
+ data
1051
+ );
1052
+ }
1053
+ },
1054
+ async linkTask(input) {
1055
+ const validation = agentChatLinkTaskBodySchema.safeParse(input);
1056
+ if (!validation.success) {
1057
+ throw new RobotRockError(
1058
+ `Invalid link task input: ${validation.error.issues[0]?.message}`,
1059
+ 400,
1060
+ validation.error.issues
1061
+ );
1062
+ }
1063
+ const response = await fetch(`${config.baseUrl}/agent-chats/link-task`, {
1064
+ method: "POST",
1065
+ headers: headers(),
1066
+ body: JSON.stringify(validation.data)
1067
+ });
1068
+ if (!response.ok) {
1069
+ const data = await parseResponseBody(response);
1070
+ throw new RobotRockError(
1071
+ getErrorMessage(data, "Failed to link inbox task to chat"),
1072
+ response.status,
1073
+ data
1074
+ );
1075
+ }
869
1076
  }
870
1077
  };
871
1078
  }
@@ -908,7 +1115,7 @@ function serializeValidUntil(value) {
908
1115
  throw new RobotRockError("Invalid validUntil: expected a Date or parseable date string", 400);
909
1116
  }
910
1117
  var RobotRock = class {
911
- apiKey;
1118
+ auth;
912
1119
  baseUrl;
913
1120
  app;
914
1121
  agentVersion;
@@ -926,14 +1133,17 @@ var RobotRock = class {
926
1133
  );
927
1134
  }
928
1135
  const apiKey = config.apiKey ?? process.env.ROBOTROCK_API_KEY;
929
- if (!apiKey) {
1136
+ const agentService = config.agentService;
1137
+ if (apiKey && agentService) {
930
1138
  throw new Error(
931
- "RobotRock API key is required. Set ROBOTROCK_API_KEY or pass apiKey when creating the client."
1139
+ "RobotRock client cannot configure both apiKey and agentService."
932
1140
  );
933
1141
  }
934
- this.apiKey = apiKey;
935
- const rawBase = config.baseUrl ?? "https://api.robotrock.io/v1";
936
- this.baseUrl = rawBase.replace(/\/+$/, "");
1142
+ this.auth = resolveRobotRockAuthConfig({
1143
+ ...apiKey ? { apiKey } : {},
1144
+ ...agentService ? { agentService } : {}
1145
+ });
1146
+ this.baseUrl = config.baseUrl ?? getRobotRockApiBaseUrl();
937
1147
  this.app = config.app;
938
1148
  this.agentVersion = config.version ?? resolveAgentVersionFromEnv();
939
1149
  this.contextVersion = config.advanced?.contextVersion ?? TASK_CONTEXT_FORMAT_VERSION2;
@@ -947,10 +1157,17 @@ var RobotRock = class {
947
1157
  };
948
1158
  this.chats = createChatsApi({
949
1159
  baseUrl: this.baseUrl,
950
- apiKey: this.apiKey,
1160
+ auth: this.auth,
951
1161
  app: this.app
952
1162
  });
953
1163
  }
1164
+ authHeaders(extra) {
1165
+ return {
1166
+ "Content-Type": "application/json",
1167
+ ...buildRobotRockAuthHeaders(this.auth),
1168
+ ...extra
1169
+ };
1170
+ }
954
1171
  async createTaskRequest(task2) {
955
1172
  const normalizedTask = normalizeSendToHumanInput(task2, {
956
1173
  webhook: this.webhook,
@@ -975,13 +1192,9 @@ var RobotRock = class {
975
1192
  validation.error.issues
976
1193
  );
977
1194
  }
978
- const headers = {
979
- "Content-Type": "application/json",
980
- "X-Api-Key": this.apiKey
981
- };
982
- if (task2.idempotencyKey) {
983
- headers["Idempotency-Key"] = task2.idempotencyKey;
984
- }
1195
+ const headers = this.authHeaders(
1196
+ task2.idempotencyKey ? { "Idempotency-Key": task2.idempotencyKey } : void 0
1197
+ );
985
1198
  const response = await fetch(`${this.baseUrl}/`, {
986
1199
  method: "POST",
987
1200
  headers,
@@ -1074,9 +1287,7 @@ var RobotRock = class {
1074
1287
  async getTaskById(taskId) {
1075
1288
  const response = await fetch(`${this.baseUrl}/tasks/${taskId}`, {
1076
1289
  method: "GET",
1077
- headers: {
1078
- "X-Api-Key": this.apiKey
1079
- }
1290
+ headers: this.authHeaders()
1080
1291
  });
1081
1292
  if (response.status === 404) {
1082
1293
  return null;
@@ -1111,10 +1322,7 @@ var RobotRock = class {
1111
1322
  `${this.baseUrl}/threads/${encodeURIComponent(threadId)}/updates`,
1112
1323
  {
1113
1324
  method: "POST",
1114
- headers: {
1115
- "Content-Type": "application/json",
1116
- "X-Api-Key": this.apiKey
1117
- },
1325
+ headers: this.authHeaders(),
1118
1326
  body: JSON.stringify(validation.data)
1119
1327
  }
1120
1328
  );
@@ -1131,9 +1339,7 @@ var RobotRock = class {
1131
1339
  async cancelTaskRequest(taskId) {
1132
1340
  const response = await fetch(`${this.baseUrl}/tasks/${taskId}/cancel`, {
1133
1341
  method: "POST",
1134
- headers: {
1135
- "X-Api-Key": this.apiKey
1136
- }
1342
+ headers: this.authHeaders()
1137
1343
  });
1138
1344
  if (!response.ok) {
1139
1345
  const data = await parseResponseBody(response);
@@ -1189,16 +1395,24 @@ function normalizeSendToHumanInput(task2, clientDefaults) {
1189
1395
  }
1190
1396
 
1191
1397
  // src/env.ts
1192
- var DEFAULT_BASE_URL = "https://api.robotrock.io/v1";
1193
1398
  function resolveRobotRockConfig(overrides) {
1399
+ const agentService = overrides?.agentService;
1194
1400
  const apiKey = overrides?.apiKey ?? process.env.ROBOTROCK_API_KEY;
1195
- if (!apiKey) {
1401
+ if (agentService && apiKey) {
1196
1402
  throw new Error(
1197
- "RobotRock API key is required. Set ROBOTROCK_API_KEY or pass apiKey when creating the client."
1403
+ "RobotRock client cannot configure both apiKey and agentService."
1198
1404
  );
1199
1405
  }
1200
- const baseUrl = overrides?.baseUrl ?? process.env.ROBOTROCK_BASE_URL ?? process.env.ROBOTROCK_API_URL ?? DEFAULT_BASE_URL;
1406
+ const baseUrl = overrides?.baseUrl ?? getRobotRockApiBaseUrl();
1201
1407
  const app = overrides?.app ?? process.env.ROBOTROCK_APP;
1408
+ if (agentService) {
1409
+ return app ? { agentService, baseUrl, app } : { agentService, baseUrl };
1410
+ }
1411
+ if (!apiKey) {
1412
+ throw new Error(
1413
+ "RobotRock API key is required. Set ROBOTROCK_API_KEY or pass agentService when creating the client."
1414
+ );
1415
+ }
1202
1416
  return app ? { apiKey, baseUrl, app } : { apiKey, baseUrl };
1203
1417
  }
1204
1418