robotrock 1.1.0 → 1.3.1

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 (71) hide show
  1. package/README.md +2 -2
  2. package/dist/agent-admin.d.ts +82 -0
  3. package/dist/agent-admin.js +938 -0
  4. package/dist/agent-admin.js.map +1 -0
  5. package/dist/ai/index.d.ts +6 -5
  6. package/dist/ai/index.js +407 -188
  7. package/dist/ai/index.js.map +1 -1
  8. package/dist/ai/trigger.d.ts +4 -3
  9. package/dist/ai/trigger.js +407 -188
  10. package/dist/ai/trigger.js.map +1 -1
  11. package/dist/ai/workflow.d.ts +4 -3
  12. package/dist/ai/workflow.js +404 -185
  13. package/dist/ai/workflow.js.map +1 -1
  14. package/dist/auth-headers-qL-ZeEtd.d.ts +13 -0
  15. package/dist/{client-XTnFHGFE.d.ts → client-YO9Y1rkH.d.ts} +29 -17
  16. package/dist/eve/agent/index.d.ts +11 -35
  17. package/dist/eve/agent/index.js +678 -146
  18. package/dist/eve/agent/index.js.map +1 -1
  19. package/dist/eve/index.d.ts +5 -2
  20. package/dist/eve/index.js +195 -2
  21. package/dist/eve/index.js.map +1 -1
  22. package/dist/eve/tools/admin/assign-tasks.d.ts +39 -0
  23. package/dist/eve/tools/admin/assign-tasks.js +1060 -0
  24. package/dist/eve/tools/admin/assign-tasks.js.map +1 -0
  25. package/dist/eve/tools/admin/manage-groups.d.ts +53 -0
  26. package/dist/eve/tools/admin/manage-groups.js +1218 -0
  27. package/dist/eve/tools/admin/manage-groups.js.map +1 -0
  28. package/dist/eve/tools/admin/manage-team-members.d.ts +45 -0
  29. package/dist/eve/tools/admin/manage-team-members.js +1160 -0
  30. package/dist/eve/tools/admin/manage-team-members.js.map +1 -0
  31. package/dist/eve/tools/admin/query-tasks.d.ts +71 -0
  32. package/dist/eve/tools/admin/query-tasks.js +1161 -0
  33. package/dist/eve/tools/admin/query-tasks.js.map +1 -0
  34. package/dist/eve/tools/catalog/search-products.d.ts +57 -0
  35. package/dist/eve/tools/catalog/search-products.js +94 -0
  36. package/dist/eve/tools/catalog/search-products.js.map +1 -0
  37. package/dist/eve/tools/identity/index.d.ts +2 -0
  38. package/dist/eve/tools/identity/index.js +117 -27
  39. package/dist/eve/tools/identity/index.js.map +1 -1
  40. package/dist/eve/tools/identity/my-access.d.ts +6 -46
  41. package/dist/eve/tools/identity/my-access.js +91 -10
  42. package/dist/eve/tools/identity/my-access.js.map +1 -1
  43. package/dist/eve/tools/identity/whoami.d.ts +7 -8
  44. package/dist/eve/tools/identity/whoami.js +33 -17
  45. package/dist/eve/tools/identity/whoami.js.map +1 -1
  46. package/dist/eve/tools/inbox/create-task.d.ts +5 -4
  47. package/dist/eve/tools/inbox/create-task.js +365 -137
  48. package/dist/eve/tools/inbox/create-task.js.map +1 -1
  49. package/dist/eve/tools/inbox/index.d.ts +1 -0
  50. package/dist/eve/tools/inbox/index.js +365 -137
  51. package/dist/eve/tools/inbox/index.js.map +1 -1
  52. package/dist/eve/tools/index.d.ts +7 -0
  53. package/dist/eve/tools/index.js +1362 -168
  54. package/dist/eve/tools/index.js.map +1 -1
  55. package/dist/{index-BL9qKHA8.d.ts → index-DoQN48Bm.d.ts} +61 -2
  56. package/dist/index.d.ts +6 -3
  57. package/dist/index.js +325 -119
  58. package/dist/index.js.map +1 -1
  59. package/dist/schemas/index.d.ts +6 -1
  60. package/dist/schemas/index.js +177 -48
  61. package/dist/schemas/index.js.map +1 -1
  62. package/dist/{tool-approval-bridge-C4bTm8vu.d.ts → tool-approval-bridge-aMA79Z1B.d.ts} +1 -1
  63. package/dist/tool-reply-guidance-C3qrT1In.d.ts +25 -0
  64. package/dist/trigger/index.d.ts +2 -1
  65. package/dist/trigger/index.js +310 -108
  66. package/dist/trigger/index.js.map +1 -1
  67. package/dist/{trigger-Dn0DFiyU.d.ts → trigger-CXrbKVCL.d.ts} +2 -2
  68. package/dist/workflow/index.d.ts +2 -1
  69. package/dist/workflow/index.js +310 -108
  70. package/dist/workflow/index.js.map +1 -1
  71. package/package.json +30 -6
@@ -387,6 +387,89 @@ function parseEveAskQuestionToolOutput(output) {
387
387
  return { ...optionId ? { optionId } : {}, ...text ? { text } : {} };
388
388
  }
389
389
 
390
+ // src/eve/tool-audit.ts
391
+ var MANAGE_TEAM_MEMBERS_TOOL_NAME = "manage_team_members";
392
+ var MANAGE_GROUPS_TOOL_NAME = "manage_groups";
393
+ var CREATE_INBOX_TASK_TOOL_NAME = "create_robotrock_task";
394
+ var MUTATING_TEAM_MEMBER_ACTIONS = /* @__PURE__ */ new Set([
395
+ "invite",
396
+ "update_role",
397
+ "remove"
398
+ ]);
399
+ var MUTATING_GROUP_ACTIONS = /* @__PURE__ */ new Set([
400
+ "create",
401
+ "update",
402
+ "delete",
403
+ "add_member",
404
+ "remove_member"
405
+ ]);
406
+ var SKIP_TOOL_NAMES = /* @__PURE__ */ new Set([
407
+ CREATE_INBOX_TASK_TOOL_NAME,
408
+ "ask_question",
409
+ "closeChat",
410
+ "requestActionInput"
411
+ ]);
412
+ function readAction(input) {
413
+ const action = input.action;
414
+ return typeof action === "string" && action.trim().length > 0 ? action.trim() : void 0;
415
+ }
416
+ function shouldAuditToolExecution(toolName, input) {
417
+ if (SKIP_TOOL_NAMES.has(toolName)) {
418
+ return false;
419
+ }
420
+ const action = readAction(input);
421
+ if (toolName === MANAGE_TEAM_MEMBERS_TOOL_NAME) {
422
+ return action != null && MUTATING_TEAM_MEMBER_ACTIONS.has(action);
423
+ }
424
+ if (toolName === MANAGE_GROUPS_TOOL_NAME) {
425
+ return action != null && MUTATING_GROUP_ACTIONS.has(action);
426
+ }
427
+ return false;
428
+ }
429
+ var AUDIT_INPUT_KEYS = /* @__PURE__ */ new Set([
430
+ "action",
431
+ "email",
432
+ "userId",
433
+ "role",
434
+ "name",
435
+ "groupId",
436
+ "description"
437
+ ]);
438
+ function sanitizeToolAuditInput(input) {
439
+ const sanitized = {};
440
+ for (const [key, value] of Object.entries(input)) {
441
+ if (!AUDIT_INPUT_KEYS.has(key)) {
442
+ continue;
443
+ }
444
+ if (value == null || value === "") {
445
+ continue;
446
+ }
447
+ if (typeof value === "string" || typeof value === "boolean") {
448
+ sanitized[key] = value;
449
+ continue;
450
+ }
451
+ if (typeof value === "number") {
452
+ sanitized[key] = value;
453
+ }
454
+ }
455
+ return sanitized;
456
+ }
457
+ function buildChatToolAuditPayload(input) {
458
+ const sanitized = sanitizeToolAuditInput(input.toolInput);
459
+ if (!shouldAuditToolExecution(input.toolName, sanitized)) {
460
+ return null;
461
+ }
462
+ const success = input.status === "completed" && input.isError !== true;
463
+ return {
464
+ toolCallId: input.toolCallId,
465
+ toolName: input.toolName,
466
+ input: sanitized,
467
+ success,
468
+ status: input.status,
469
+ ...input.error ? { error: input.error } : {}
470
+ };
471
+ }
472
+
390
473
  // src/eve/index.ts
391
474
  var ROBOTROCK_READY_HOOK_SLUG = "robotrock-ready";
392
475
 
@@ -663,7 +746,7 @@ function robotrockEveChannel(options) {
663
746
  }
664
747
 
665
748
  // src/schemas/index.ts
666
- import { z as z2 } from "zod";
749
+ import { z as z4 } from "zod";
667
750
 
668
751
  // ../core/src/utils/safe-url.ts
669
752
  var BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set([
@@ -1050,13 +1133,27 @@ var createAgentChatBodySchema = z.object({
1050
1133
  eveConnectionId: z.string().min(1).optional(),
1051
1134
  /** Source application id; groups the chat under an inbox section. */
1052
1135
  app: z.string().min(1).optional(),
1053
- assignTo: assignToSchema.optional(),
1136
+ /** Email of the user who owns the chat. Required unless `parentChatId` is set. */
1137
+ ownerEmail: z.string().email().optional(),
1054
1138
  title: z.string().min(1),
1055
1139
  messages: z.array(agentChatSeedMessageSchema).default([]),
1056
1140
  /** Provenance label stored on the session ("cron" | "agent" | ...). */
1057
1141
  source: z.string().min(1).optional()
1058
1142
  }).refine((data) => Boolean(data.agentIdentifier || data.parentChatId), {
1059
1143
  message: "Provide either agentIdentifier or parentChatId"
1144
+ }).refine((data) => Boolean(data.ownerEmail || data.parentChatId), {
1145
+ message: "Provide ownerEmail unless parentChatId is set"
1146
+ });
1147
+ var agentChatAuditToolBodySchema = z.object({
1148
+ eveSessionId: z.string().min(1),
1149
+ userId: z.string().min(1),
1150
+ toolCallId: z.string().min(1),
1151
+ toolName: z.string().min(1),
1152
+ input: z.record(z.string(), z.unknown()).default({}),
1153
+ success: z.boolean(),
1154
+ status: z.enum(["completed", "failed", "rejected"]),
1155
+ error: z.string().optional(),
1156
+ idempotencyKey: z.string().optional()
1060
1157
  });
1061
1158
  var agentChatAuditInputBodySchema = z.object({
1062
1159
  eveSessionId: z.string().min(1),
@@ -1096,62 +1193,175 @@ var agentChatLinkTaskBodySchema = z.object({
1096
1193
  toolCallId: z.string().min(1)
1097
1194
  });
1098
1195
 
1196
+ // ../core/src/schemas/tool-result-display.ts
1197
+ import { z as z2 } from "zod";
1198
+ var toolDisplayMetadataSchema = z2.object({
1199
+ widget: z2.string().optional(),
1200
+ title: z2.string().optional(),
1201
+ description: z2.string().optional()
1202
+ });
1203
+ var toolDisplayEnvelopeSchema = z2.object({
1204
+ display: toolDisplayMetadataSchema.optional(),
1205
+ data: z2.record(z2.string(), z2.unknown()),
1206
+ ui: z2.record(
1207
+ z2.string(),
1208
+ z2.object({
1209
+ "ui:widget": z2.string().optional(),
1210
+ "ui:title": z2.string().optional(),
1211
+ "ui:description": z2.string().optional(),
1212
+ "ui:options": z2.record(z2.string(), z2.unknown()).optional()
1213
+ }).passthrough()
1214
+ ).optional()
1215
+ });
1216
+
1217
+ // ../core/src/schemas/agent-admin.ts
1218
+ import { z as z3 } from "zod";
1219
+ var tenantRoleSchema = z3.enum(["admin", "member"]);
1220
+ var agentAdminUserSchema = z3.object({
1221
+ id: z3.string(),
1222
+ email: z3.string().email(),
1223
+ name: z3.string()
1224
+ });
1225
+ var agentAdminMemberSchema = z3.object({
1226
+ userId: z3.string(),
1227
+ role: z3.string(),
1228
+ membershipKind: z3.enum(["team", "assignee"]),
1229
+ hasLoggedIn: z3.boolean(),
1230
+ user: agentAdminUserSchema
1231
+ });
1232
+ var agentAdminGroupSchema = z3.object({
1233
+ id: z3.string(),
1234
+ name: z3.string(),
1235
+ slug: z3.string(),
1236
+ description: z3.string().nullable(),
1237
+ memberCount: z3.number().optional()
1238
+ });
1239
+ var agentAdminGroupDetailSchema = agentAdminGroupSchema.extend({
1240
+ members: z3.array(
1241
+ z3.object({
1242
+ userId: z3.string(),
1243
+ user: agentAdminUserSchema
1244
+ })
1245
+ )
1246
+ });
1247
+ var agentAdminTaskSummarySchema = z3.object({
1248
+ id: z3.string(),
1249
+ convexId: z3.string(),
1250
+ status: z3.string(),
1251
+ type: z3.string().nullable(),
1252
+ name: z3.string().nullable(),
1253
+ description: z3.string().nullable(),
1254
+ validUntil: z3.number(),
1255
+ createdAt: z3.number(),
1256
+ threadPriority: z3.string().nullable(),
1257
+ handledByUserId: z3.string().nullable()
1258
+ });
1259
+ var inviteMemberBodySchema = z3.object({
1260
+ email: z3.string().email(),
1261
+ role: tenantRoleSchema.optional()
1262
+ });
1263
+ var updateMemberRoleBodySchema = z3.object({
1264
+ role: tenantRoleSchema
1265
+ });
1266
+ var createGroupBodySchema = z3.object({
1267
+ name: z3.string().min(1),
1268
+ description: z3.string().optional()
1269
+ });
1270
+ var updateGroupBodySchema = z3.object({
1271
+ name: z3.string().min(1).optional(),
1272
+ description: z3.string().optional()
1273
+ });
1274
+ var addGroupMemberBodySchema = z3.object({
1275
+ userId: z3.string().min(1).describe("Convex user id or member email.")
1276
+ });
1277
+ var listTasksQuerySchema = z3.object({
1278
+ statusFilter: z3.enum(["all", "open", "handled", "expired"]).optional(),
1279
+ typeFilter: z3.string().optional(),
1280
+ appFilter: z3.string().optional(),
1281
+ sortField: z3.enum(["type", "date", "status", "validUntil"]).optional(),
1282
+ sortDirection: z3.enum(["asc", "desc"]).optional(),
1283
+ limit: z3.coerce.number().int().positive().max(100).optional(),
1284
+ cursor: z3.string().optional()
1285
+ });
1286
+ var searchTasksQuerySchema = z3.object({
1287
+ q: z3.string().min(1),
1288
+ limit: z3.coerce.number().int().positive().max(100).optional()
1289
+ });
1290
+ var assignTasksResultSchema = z3.object({
1291
+ taskId: z3.string(),
1292
+ success: z3.boolean(),
1293
+ message: z3.string().optional(),
1294
+ name: z3.string().nullable().optional(),
1295
+ description: z3.string().nullable().optional(),
1296
+ type: z3.string().nullable().optional()
1297
+ });
1298
+ var assignTasksResponseSchema = z3.object({
1299
+ results: z3.array(assignTasksResultSchema)
1300
+ });
1301
+ var assignTasksBodySchema = z3.object({
1302
+ taskIds: z3.array(z3.string().min(1)).min(1).max(100),
1303
+ assignTo: assignToSchema.refine(
1304
+ (value) => (value.users?.length ?? 0) > 0 || (value.groups?.length ?? 0) > 0,
1305
+ { message: "assignTo needs at least one user email or group slug." }
1306
+ )
1307
+ });
1308
+
1099
1309
  // src/schemas/index.ts
1100
- var handlerUrlSchema2 = z2.string().refine((url) => isAllowedHandlerUrl(url), {
1310
+ var handlerUrlSchema2 = z4.string().refine((url) => isAllowedHandlerUrl(url), {
1101
1311
  message: HANDLER_URL_ERROR
1102
1312
  });
1103
- var jsonSchema7Schema2 = z2.custom(
1313
+ var jsonSchema7Schema2 = z4.custom(
1104
1314
  (val) => typeof val === "object" && val !== null,
1105
1315
  { message: "Must be a valid JSON Schema object" }
1106
1316
  );
1107
- var uiSchemaSchema2 = z2.custom((val) => typeof val === "object" && val !== null, {
1317
+ var uiSchemaSchema2 = z4.custom((val) => typeof val === "object" && val !== null, {
1108
1318
  message: "Must be a valid UiSchema object"
1109
1319
  });
1110
- var webhookHandlerSchema2 = z2.object({
1111
- type: z2.literal("webhook"),
1320
+ var webhookHandlerSchema2 = z4.object({
1321
+ type: z4.literal("webhook"),
1112
1322
  url: handlerUrlSchema2,
1113
- headers: z2.record(z2.string(), z2.string())
1323
+ headers: z4.record(z4.string(), z4.string())
1114
1324
  });
1115
1325
  var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
1116
- type: z2.literal("trigger"),
1117
- tokenId: z2.string().min(1)
1326
+ type: z4.literal("trigger"),
1327
+ tokenId: z4.string().min(1)
1118
1328
  });
1119
- var handlerSchema2 = z2.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
1120
- var taskActionInputSchema2 = z2.object({
1121
- id: z2.string().min(1),
1122
- title: z2.string().min(1),
1123
- description: z2.string().optional(),
1329
+ var handlerSchema2 = z4.discriminatedUnion("type", [webhookHandlerSchema2, triggerHandlerSchema2]);
1330
+ var taskActionInputSchema2 = z4.object({
1331
+ id: z4.string().min(1),
1332
+ title: z4.string().min(1),
1333
+ description: z4.string().optional(),
1124
1334
  schema: jsonSchema7Schema2.optional(),
1125
1335
  ui: uiSchemaSchema2.optional(),
1126
- data: z2.record(z2.string(), z2.unknown()).optional()
1336
+ data: z4.record(z4.string(), z4.unknown()).optional()
1127
1337
  });
1128
1338
  var taskActionSchema2 = taskActionInputSchema2.extend({
1129
- handlers: z2.array(handlerSchema2).min(1).optional()
1339
+ handlers: z4.array(handlerSchema2).min(1).optional()
1130
1340
  });
1131
- var uiFieldSchemaSchema2 = z2.object({
1132
- "ui:widget": z2.string().optional(),
1133
- "ui:title": z2.string().optional(),
1134
- "ui:description": z2.string().optional(),
1135
- "ui:options": z2.record(z2.string(), z2.unknown()).optional(),
1136
- items: z2.lazy(() => z2.record(z2.string(), uiFieldSchemaSchema2)).optional()
1341
+ var uiFieldSchemaSchema2 = z4.object({
1342
+ "ui:widget": z4.string().optional(),
1343
+ "ui:title": z4.string().optional(),
1344
+ "ui:description": z4.string().optional(),
1345
+ "ui:options": z4.record(z4.string(), z4.unknown()).optional(),
1346
+ items: z4.lazy(() => z4.record(z4.string(), uiFieldSchemaSchema2)).optional()
1137
1347
  }).passthrough();
1138
- var contextUiSchema2 = z2.record(z2.string(), uiFieldSchemaSchema2).optional();
1139
- var contextDataSchema2 = z2.object({
1140
- data: z2.record(z2.string(), z2.unknown()),
1348
+ var contextUiSchema2 = z4.record(z4.string(), uiFieldSchemaSchema2).optional();
1349
+ var contextDataSchema2 = z4.object({
1350
+ data: z4.record(z4.string(), z4.unknown()),
1141
1351
  ui: contextUiSchema2
1142
1352
  }).optional();
1143
1353
  var TASK_CONTEXT_FORMAT_VERSION2 = 2;
1144
- var taskContextObjectBaseSchema2 = z2.object({
1145
- app: z2.string().min(1).optional(),
1146
- type: z2.string().min(1),
1147
- name: z2.string().min(1),
1148
- description: z2.string().optional(),
1149
- validUntil: z2.string().optional(),
1354
+ var taskContextObjectBaseSchema2 = z4.object({
1355
+ app: z4.string().min(1).optional(),
1356
+ type: z4.string().min(1),
1357
+ name: z4.string().min(1),
1358
+ description: z4.string().optional(),
1359
+ validUntil: z4.string().optional(),
1150
1360
  context: contextDataSchema2,
1151
- contextVersion: z2.literal(2).optional(),
1361
+ contextVersion: z4.literal(2).optional(),
1152
1362
  /** @deprecated Use `contextVersion`. Accepted on ingest only. */
1153
- version: z2.literal(2).optional(),
1154
- actions: z2.array(taskActionSchema2).min(1, "At least one action is required")
1363
+ version: z4.literal(2).optional(),
1364
+ actions: z4.array(taskActionSchema2).min(1, "At least one action is required")
1155
1365
  });
1156
1366
  function normalizeTaskContextVersion2(data) {
1157
1367
  const { version: legacyVersion, contextVersion, ...rest } = data;
@@ -1167,7 +1377,7 @@ function refineContextPublicUrls2(data, ctx) {
1167
1377
  const error = validateContextPublicUrls(data.context);
1168
1378
  if (error) {
1169
1379
  ctx.addIssue({
1170
- code: z2.ZodIssueCode.custom,
1380
+ code: z4.ZodIssueCode.custom,
1171
1381
  message: error,
1172
1382
  path: ["context"]
1173
1383
  });
@@ -1176,9 +1386,9 @@ function refineContextPublicUrls2(data, ctx) {
1176
1386
  var taskContextSchema2 = taskContextObjectSchema2.superRefine(
1177
1387
  refineContextPublicUrls2
1178
1388
  );
1179
- var assignToSchema2 = z2.object({
1180
- users: z2.array(z2.string().email()).optional(),
1181
- groups: z2.array(z2.string().min(1)).optional()
1389
+ var assignToSchema2 = z4.object({
1390
+ users: z4.array(z4.string().email()).optional(),
1391
+ groups: z4.array(z4.string().min(1)).optional()
1182
1392
  }).refine(
1183
1393
  (data) => {
1184
1394
  const groups = data.groups ?? [];
@@ -1189,7 +1399,7 @@ var assignToSchema2 = z2.object({
1189
1399
  },
1190
1400
  { message: 'Cannot combine "all" with other group slugs' }
1191
1401
  );
1192
- var threadUpdateMessageSchema2 = z2.string().min(1).max(500);
1402
+ var threadUpdateMessageSchema2 = z4.string().min(1).max(500);
1193
1403
  var threadUpdateStatuses2 = [
1194
1404
  "info",
1195
1405
  "queued",
@@ -1199,15 +1409,15 @@ var threadUpdateStatuses2 = [
1199
1409
  "failed",
1200
1410
  "cancelled"
1201
1411
  ];
1202
- var threadUpdateStatusSchema2 = z2.enum(threadUpdateStatuses2);
1203
- var threadUpdateInputSchema2 = z2.object({
1412
+ var threadUpdateStatusSchema2 = z4.enum(threadUpdateStatuses2);
1413
+ var threadUpdateInputSchema2 = z4.object({
1204
1414
  message: threadUpdateMessageSchema2,
1205
1415
  status: threadUpdateStatusSchema2.optional()
1206
1416
  });
1207
1417
  var taskPriorities2 = ["low", "normal", "high", "urgent"];
1208
- var taskPrioritySchema2 = z2.enum(taskPriorities2);
1209
- var agentTelemetrySchema2 = z2.object({
1210
- version: z2.string().min(1)
1418
+ var taskPrioritySchema2 = z4.enum(taskPriorities2);
1419
+ var agentTelemetrySchema2 = z4.object({
1420
+ version: z4.string().min(1)
1211
1421
  });
1212
1422
  var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
1213
1423
  assignTo: assignToSchema2.optional(),
@@ -1215,7 +1425,7 @@ var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
1215
1425
  * Groups related tasks together. When omitted, the server generates one and
1216
1426
  * returns it so the caller can reuse it on later tasks in the same thread.
1217
1427
  */
1218
- threadId: z2.string().min(1).optional(),
1428
+ threadId: z4.string().min(1).optional(),
1219
1429
  /**
1220
1430
  * Optional thread priority. When set, applies to the whole thread and
1221
1431
  * overwrites any previous priority. Omit on later tasks to leave unchanged.
@@ -1230,6 +1440,65 @@ var createTaskBodySchema2 = taskContextObjectBaseSchema2.extend({
1230
1440
  }).transform(normalizeTaskContextVersion2).superRefine(refineContextPublicUrls2);
1231
1441
  var threadUpdateBodySchema = threadUpdateInputSchema2;
1232
1442
 
1443
+ // ../core/src/handler-retry.ts
1444
+ var HANDLER_RETRY_DELAYS_MS = [
1445
+ 6e4,
1446
+ // 1m
1447
+ 3e5,
1448
+ // 5m
1449
+ 18e5,
1450
+ // 30m
1451
+ 36e5,
1452
+ // 1h
1453
+ 216e5,
1454
+ // 6h
1455
+ 864e5,
1456
+ // 24h
1457
+ 1728e5
1458
+ // 48h
1459
+ ];
1460
+ var HANDLER_MAX_ATTEMPTS = HANDLER_RETRY_DELAYS_MS.length + 1;
1461
+
1462
+ // ../core/src/attribution/index.ts
1463
+ import { z as z5 } from "zod";
1464
+
1465
+ // ../core/src/app-url.ts
1466
+ var PRODUCTION_APP_URL = "https://app.robotrock.io";
1467
+ var PRODUCTION_API_URL = "https://api.robotrock.io/v1";
1468
+ var DEV_API_URL = "http://localhost:4001/v1";
1469
+ var APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
1470
+ function normalizeRobotRockApiBaseUrl(baseUrl) {
1471
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
1472
+ if (trimmed.endsWith("/v1")) {
1473
+ return trimmed;
1474
+ }
1475
+ return `${trimmed}/v1`;
1476
+ }
1477
+ function getRobotRockApiBaseUrl() {
1478
+ const explicit = process.env.ROBOTROCK_BASE_URL?.trim() || process.env.ROBOTROCK_API_URL?.trim();
1479
+ if (explicit) {
1480
+ return normalizeRobotRockApiBaseUrl(explicit);
1481
+ }
1482
+ if (process.env.NODE_ENV === "production") {
1483
+ return PRODUCTION_API_URL;
1484
+ }
1485
+ return DEV_API_URL;
1486
+ }
1487
+
1488
+ // ../core/src/attribution/index.ts
1489
+ var ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
1490
+ var attributionSchema = z5.object({
1491
+ utmSource: z5.string().optional(),
1492
+ utmMedium: z5.string().optional(),
1493
+ utmCampaign: z5.string().optional(),
1494
+ utmContent: z5.string().optional(),
1495
+ utmTerm: z5.string().optional(),
1496
+ gclid: z5.string().optional(),
1497
+ landingUrl: z5.string().optional(),
1498
+ referrer: z5.string().optional(),
1499
+ capturedAt: z5.number()
1500
+ });
1501
+
1233
1502
  // src/approval-result.ts
1234
1503
  var TaskTimeoutError = class extends Error {
1235
1504
  constructor(message) {
@@ -1304,77 +1573,27 @@ function getErrorMessage(data, fallback) {
1304
1573
  return fallback;
1305
1574
  }
1306
1575
 
1307
- // ../core/src/handler-retry.ts
1308
- var HANDLER_RETRY_DELAYS_MS = [
1309
- 6e4,
1310
- // 1m
1311
- 3e5,
1312
- // 5m
1313
- 18e5,
1314
- // 30m
1315
- 36e5,
1316
- // 1h
1317
- 216e5,
1318
- // 6h
1319
- 864e5,
1320
- // 24h
1321
- 1728e5
1322
- // 48h
1323
- ];
1324
- var HANDLER_MAX_ATTEMPTS = HANDLER_RETRY_DELAYS_MS.length + 1;
1325
-
1326
- // ../core/src/attribution/index.ts
1327
- import { z as z3 } from "zod";
1328
-
1329
- // ../core/src/app-url.ts
1330
- var PRODUCTION_APP_URL = "https://app.robotrock.io";
1331
- var PRODUCTION_API_URL = "https://api.robotrock.io/v1";
1332
- var DEV_API_URL = "http://localhost:4001/v1";
1333
- var APP_SIGNUP_URL = `${PRODUCTION_APP_URL}/sign-up`;
1334
- function normalizeRobotRockApiBaseUrl(baseUrl) {
1335
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
1336
- if (trimmed.endsWith("/v1")) {
1337
- return trimmed;
1338
- }
1339
- return `${trimmed}/v1`;
1340
- }
1341
- function getRobotRockApiBaseUrl() {
1342
- const explicit = process.env.ROBOTROCK_BASE_URL?.trim() || process.env.ROBOTROCK_API_URL?.trim();
1343
- if (explicit) {
1344
- return normalizeRobotRockApiBaseUrl(explicit);
1345
- }
1346
- if (process.env.NODE_ENV === "production") {
1347
- return PRODUCTION_API_URL;
1348
- }
1349
- return DEV_API_URL;
1350
- }
1351
-
1352
- // ../core/src/attribution/index.ts
1353
- var ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 90;
1354
- var attributionSchema = z3.object({
1355
- utmSource: z3.string().optional(),
1356
- utmMedium: z3.string().optional(),
1357
- utmCampaign: z3.string().optional(),
1358
- utmContent: z3.string().optional(),
1359
- utmTerm: z3.string().optional(),
1360
- gclid: z3.string().optional(),
1361
- landingUrl: z3.string().optional(),
1362
- referrer: z3.string().optional(),
1363
- capturedAt: z3.number()
1364
- });
1365
-
1366
1576
  // src/auth-headers.ts
1577
+ var ROBOTROCK_ACTING_USER_ID_HEADER = "x-robotrock-acting-user-id";
1367
1578
  function buildRobotRockAuthHeaders(auth) {
1368
1579
  if (auth.kind === "apiKey") {
1369
- return {
1580
+ const headers2 = {
1370
1581
  "X-Api-Key": auth.apiKey
1371
1582
  };
1583
+ if (auth.actingUserId?.trim()) {
1584
+ headers2[ROBOTROCK_ACTING_USER_ID_HEADER] = auth.actingUserId.trim();
1585
+ }
1586
+ return headers2;
1372
1587
  }
1373
- return {
1588
+ const headers = {
1374
1589
  Authorization: `Bearer ${auth.token}`,
1375
1590
  "X-RobotRock-Tenant-Slug": auth.tenantSlug,
1376
1591
  "X-RobotRock-Connection-Id": auth.connectionId
1377
1592
  };
1593
+ if (auth.actingUserId?.trim()) {
1594
+ headers[ROBOTROCK_ACTING_USER_ID_HEADER] = auth.actingUserId.trim();
1595
+ }
1596
+ return headers;
1378
1597
  }
1379
1598
  function resolveRobotRockAuthConfig(overrides) {
1380
1599
  if (overrides?.agentService) {
@@ -1518,6 +1737,29 @@ function createChatsApi(config) {
1518
1737
  );
1519
1738
  }
1520
1739
  },
1740
+ async logToolExecution(input) {
1741
+ const validation = agentChatAuditToolBodySchema.safeParse(input);
1742
+ if (!validation.success) {
1743
+ throw new RobotRockError(
1744
+ `Invalid audit tool input: ${validation.error.issues[0]?.message}`,
1745
+ 400,
1746
+ validation.error.issues
1747
+ );
1748
+ }
1749
+ const response = await fetch(`${config.baseUrl}/agent-chats/audit-tool`, {
1750
+ method: "POST",
1751
+ headers: headers(),
1752
+ body: JSON.stringify(validation.data)
1753
+ });
1754
+ if (!response.ok) {
1755
+ const data = await parseResponseBody(response);
1756
+ throw new RobotRockError(
1757
+ getErrorMessage(data, "Failed to log chat tool execution"),
1758
+ response.status,
1759
+ data
1760
+ );
1761
+ }
1762
+ },
1521
1763
  async linkTask(input) {
1522
1764
  const validation = agentChatLinkTaskBodySchema.safeParse(input);
1523
1765
  if (!validation.success) {
@@ -1620,7 +1862,9 @@ var RobotRock = class {
1620
1862
  create: (task) => this.createTaskRequest(task),
1621
1863
  get: (taskId) => this.getTaskById(taskId),
1622
1864
  cancel: (taskId) => this.cancelTaskRequest(taskId),
1623
- sendUpdate: (input) => this.sendThreadUpdate(input)
1865
+ sendUpdate: (input) => this.sendThreadUpdate(input),
1866
+ list: (input) => this.listTasksRequest(input),
1867
+ search: (input) => this.searchTasksRequest(input)
1624
1868
  };
1625
1869
  this.chats = createChatsApi({
1626
1870
  baseUrl: this.baseUrl,
@@ -1817,6 +2061,47 @@ var RobotRock = class {
1817
2061
  );
1818
2062
  }
1819
2063
  }
2064
+ async listTasksRequest(input) {
2065
+ const params = new URLSearchParams();
2066
+ for (const [key, value] of Object.entries(input ?? {})) {
2067
+ if (value !== void 0 && value !== "") {
2068
+ params.set(key, String(value));
2069
+ }
2070
+ }
2071
+ const suffix = params.size > 0 ? `?${params.toString()}` : "";
2072
+ const response = await fetch(`${this.baseUrl}/tasks${suffix}`, {
2073
+ method: "GET",
2074
+ headers: this.authHeaders()
2075
+ });
2076
+ const data = await parseResponseBody(response);
2077
+ if (!response.ok) {
2078
+ throw new RobotRockError(
2079
+ getErrorMessage(data, "Failed to list tasks"),
2080
+ response.status,
2081
+ data
2082
+ );
2083
+ }
2084
+ return data;
2085
+ }
2086
+ async searchTasksRequest(input) {
2087
+ const params = new URLSearchParams({ q: input.q });
2088
+ if (input.limit !== void 0) {
2089
+ params.set("limit", String(input.limit));
2090
+ }
2091
+ const response = await fetch(`${this.baseUrl}/tasks/search?${params.toString()}`, {
2092
+ method: "GET",
2093
+ headers: this.authHeaders()
2094
+ });
2095
+ const data = await parseResponseBody(response);
2096
+ if (!response.ok) {
2097
+ throw new RobotRockError(
2098
+ getErrorMessage(data, "Failed to search tasks"),
2099
+ response.status,
2100
+ data
2101
+ );
2102
+ }
2103
+ return data;
2104
+ }
1820
2105
  };
1821
2106
  function createClient(config) {
1822
2107
  return new RobotRock(config);
@@ -1953,6 +2238,23 @@ function logAuditFailure(label, error) {
1953
2238
  const hint = error instanceof RobotRockError && error.statusCode === 405 ? " \u2014 set ROBOTROCK_BASE_URL=http://localhost:4001/v1 and run the local API" : "";
1954
2239
  console.warn(`robotrock-chat-audit: failed to ${label}${hint}`, error);
1955
2240
  }
2241
+ async function postRobotRockChatToolAudit(ctx, payload) {
2242
+ const client = tryCreateBoundRobotRockClient(ctx);
2243
+ if (!client) {
2244
+ if (!warnedMissingAuth2) {
2245
+ warnedMissingAuth2 = true;
2246
+ console.warn(
2247
+ "robotrock-chat-audit: RobotRock auth is unset; skipping tool audit logging."
2248
+ );
2249
+ }
2250
+ return;
2251
+ }
2252
+ try {
2253
+ await client.chats.logToolExecution(payload);
2254
+ } catch (error) {
2255
+ logAuditFailure("log tool execution", error);
2256
+ }
2257
+ }
1956
2258
  async function postRobotRockChatInputAudit(ctx, payload) {
1957
2259
  const client = tryCreateBoundRobotRockClient(ctx);
1958
2260
  if (!client) {
@@ -2135,7 +2437,7 @@ async function createRobotRockCronChat(input) {
2135
2437
  title: input.title,
2136
2438
  messages: input.messages,
2137
2439
  source: "cron",
2138
- assignTo: input.assignTo
2440
+ ownerEmail: input.ownerEmail
2139
2441
  });
2140
2442
  }
2141
2443
 
@@ -2149,6 +2451,8 @@ function defineRobotRockReadyHook() {
2149
2451
  // src/eve/agent/hooks/chat-audit.ts
2150
2452
  import { defineHook as defineHook2 } from "eve/hooks";
2151
2453
  var loggedIdempotencyKeys = /* @__PURE__ */ new Set();
2454
+ var loggedToolCallIds = /* @__PURE__ */ new Set();
2455
+ var pendingToolCallsBySession = /* @__PURE__ */ new Map();
2152
2456
  function toEveInputRequest(request) {
2153
2457
  return {
2154
2458
  requestId: request.requestId,
@@ -2158,6 +2462,22 @@ function toEveInputRequest(request) {
2158
2462
  ...request.options ? { options: request.options } : {}
2159
2463
  };
2160
2464
  }
2465
+ function stashPendingToolCall(sessionId, callId, toolName, input) {
2466
+ const sessionCalls = pendingToolCallsBySession.get(sessionId) ?? /* @__PURE__ */ new Map();
2467
+ sessionCalls.set(callId, { toolName, input });
2468
+ pendingToolCallsBySession.set(sessionId, sessionCalls);
2469
+ }
2470
+ function takePendingToolCall(sessionId, callId) {
2471
+ const sessionCalls = pendingToolCallsBySession.get(sessionId);
2472
+ const pending = sessionCalls?.get(callId);
2473
+ if (pending && sessionCalls) {
2474
+ sessionCalls.delete(callId);
2475
+ if (sessionCalls.size === 0) {
2476
+ pendingToolCallsBySession.delete(sessionId);
2477
+ }
2478
+ }
2479
+ return pending;
2480
+ }
2161
2481
  async function logPendingInputResponse(ctx, pending, response) {
2162
2482
  const caller = tryResolveTenantCaller(ctx);
2163
2483
  if (!caller) {
@@ -2194,11 +2514,70 @@ async function logPendingInputResponse(ctx, pending, response) {
2194
2514
  });
2195
2515
  loggedIdempotencyKeys.add(idempotencyKey);
2196
2516
  }
2517
+ async function logToolExecutionFromResult(ctx, event) {
2518
+ const result = event.data.result;
2519
+ if (result.kind !== "tool-result") {
2520
+ return;
2521
+ }
2522
+ const callId = result.callId;
2523
+ const toolName = result.toolName;
2524
+ if (!callId || !toolName) {
2525
+ return;
2526
+ }
2527
+ const dedupeKey = `${ctx.session.id}:${callId}`;
2528
+ if (loggedToolCallIds.has(dedupeKey)) {
2529
+ return;
2530
+ }
2531
+ const pending = takePendingToolCall(ctx.session.id, callId) ?? { toolName, input: {} };
2532
+ const payload = buildChatToolAuditPayload({
2533
+ toolCallId: callId,
2534
+ toolName: pending.toolName,
2535
+ toolInput: pending.input,
2536
+ status: event.data.status,
2537
+ isError: result.isError,
2538
+ error: event.data.error?.message
2539
+ });
2540
+ if (!payload) {
2541
+ return;
2542
+ }
2543
+ const caller = tryResolveTenantCaller(ctx);
2544
+ if (!caller) {
2545
+ return;
2546
+ }
2547
+ await postRobotRockChatToolAudit(ctx, {
2548
+ eveSessionId: ctx.session.id,
2549
+ userId: caller.userId,
2550
+ toolCallId: payload.toolCallId,
2551
+ toolName: payload.toolName,
2552
+ input: payload.input,
2553
+ success: payload.success,
2554
+ status: payload.status,
2555
+ ...payload.error ? { error: payload.error } : {},
2556
+ idempotencyKey: dedupeKey
2557
+ });
2558
+ loggedToolCallIds.add(dedupeKey);
2559
+ }
2197
2560
  function resetRobotrockChatAuditIdempotencyKeys() {
2198
2561
  loggedIdempotencyKeys.clear();
2562
+ loggedToolCallIds.clear();
2563
+ pendingToolCallsBySession.clear();
2199
2564
  }
2200
2565
  var robotrockChatAuditHook = defineHook2({
2201
2566
  events: {
2567
+ async "actions.requested"(event, ctx) {
2568
+ for (const action of event.data.actions) {
2569
+ if (action.kind !== "tool-call") {
2570
+ continue;
2571
+ }
2572
+ const input = action.input != null && typeof action.input === "object" && !Array.isArray(action.input) ? action.input : {};
2573
+ stashPendingToolCall(
2574
+ ctx.session.id,
2575
+ action.callId,
2576
+ action.toolName,
2577
+ input
2578
+ );
2579
+ }
2580
+ },
2202
2581
  async "input.requested"(event, ctx) {
2203
2582
  const requests = [];
2204
2583
  for (const request of event.data.requests) {
@@ -2242,51 +2621,201 @@ var robotrockChatAuditHook = defineHook2({
2242
2621
  },
2243
2622
  async "action.result"(event, ctx) {
2244
2623
  const result = event.data.result;
2245
- if (result.kind !== "tool-result") {
2246
- return;
2247
- }
2248
- const staged = await fetchRobotRockStagedHitl(ctx, ctx.session.id);
2249
- const pending = staged.find((entry) => entry.toolCallId === result.callId);
2250
- if (!pending) {
2251
- return;
2252
- }
2253
- const idempotencyKey = `${ctx.session.id}:${pending.requestId}`;
2254
- if (loggedIdempotencyKeys.has(idempotencyKey)) {
2255
- return;
2256
- }
2257
- if (pending.toolName === "ask_question") {
2258
- const parsed = parseEveAskQuestionToolOutput(result.output);
2259
- if (!parsed) {
2260
- return;
2624
+ if (result.kind === "tool-result") {
2625
+ const staged = await fetchRobotRockStagedHitl(ctx, ctx.session.id);
2626
+ const pending = staged.find((entry) => entry.toolCallId === result.callId);
2627
+ if (pending) {
2628
+ const idempotencyKey = `${ctx.session.id}:${pending.requestId}`;
2629
+ if (!loggedIdempotencyKeys.has(idempotencyKey)) {
2630
+ if (pending.toolName === "ask_question") {
2631
+ const parsed = parseEveAskQuestionToolOutput(result.output);
2632
+ if (parsed) {
2633
+ await logPendingInputResponse(ctx, pending, {
2634
+ requestId: pending.requestId,
2635
+ ...parsed
2636
+ });
2637
+ }
2638
+ } else if (isEveApprovalInputRequest(toEveInputRequest(pending))) {
2639
+ if (event.data.status === "rejected") {
2640
+ await logPendingInputResponse(ctx, pending, {
2641
+ requestId: pending.requestId,
2642
+ optionId: "deny"
2643
+ });
2644
+ } else if (event.data.status === "completed") {
2645
+ await logPendingInputResponse(ctx, pending, {
2646
+ requestId: pending.requestId,
2647
+ optionId: "approve"
2648
+ });
2649
+ }
2650
+ }
2651
+ }
2261
2652
  }
2262
- await logPendingInputResponse(ctx, pending, {
2263
- requestId: pending.requestId,
2264
- ...parsed
2265
- });
2266
- return;
2267
- }
2268
- if (!isEveApprovalInputRequest(toEveInputRequest(pending))) {
2269
- return;
2270
- }
2271
- if (event.data.status === "rejected") {
2272
- await logPendingInputResponse(ctx, pending, {
2273
- requestId: pending.requestId,
2274
- optionId: "deny"
2275
- });
2276
- return;
2277
- }
2278
- if (event.data.status === "completed") {
2279
- await logPendingInputResponse(ctx, pending, {
2280
- requestId: pending.requestId,
2281
- optionId: "approve"
2282
- });
2283
2653
  }
2654
+ await logToolExecutionFromResult(ctx, event);
2284
2655
  }
2285
2656
  }
2286
2657
  });
2287
2658
  function defineRobotRockChatAuditHook() {
2288
2659
  return robotrockChatAuditHook;
2289
2660
  }
2661
+
2662
+ // src/agent-admin.ts
2663
+ async function agentAdminFetch(config, path, init) {
2664
+ const baseUrl = (config.baseUrl?.trim() || getRobotRockApiBaseUrl()).replace(
2665
+ /\/+$/,
2666
+ ""
2667
+ );
2668
+ const url = `${baseUrl}/agent-admin${path}`;
2669
+ const response = await fetch(url, {
2670
+ ...init,
2671
+ headers: {
2672
+ "Content-Type": "application/json",
2673
+ ...buildRobotRockAuthHeaders(config.auth),
2674
+ ...init?.headers ?? {}
2675
+ }
2676
+ });
2677
+ const data = await parseResponseBody(response);
2678
+ if (!response.ok) {
2679
+ throw new RobotRockError(
2680
+ getErrorMessage(data, `Agent admin request failed (${response.status})`),
2681
+ response.status,
2682
+ data
2683
+ );
2684
+ }
2685
+ return data;
2686
+ }
2687
+ function createAgentAdminApi(config) {
2688
+ return {
2689
+ members: {
2690
+ list: () => agentAdminFetch(config, "/members"),
2691
+ get: (memberRef) => agentAdminFetch(config, `/members/${encodeURIComponent(memberRef)}`),
2692
+ invite: (body) => agentAdminFetch(config, "/members", {
2693
+ method: "POST",
2694
+ body: JSON.stringify(body)
2695
+ }),
2696
+ updateRole: (memberRef, role) => agentAdminFetch(
2697
+ config,
2698
+ `/members/${encodeURIComponent(memberRef)}/role`,
2699
+ {
2700
+ method: "PATCH",
2701
+ body: JSON.stringify({ role })
2702
+ }
2703
+ ),
2704
+ remove: (memberId) => agentAdminFetch(
2705
+ config,
2706
+ `/members/${encodeURIComponent(memberId)}`,
2707
+ {
2708
+ method: "DELETE"
2709
+ }
2710
+ )
2711
+ },
2712
+ groups: {
2713
+ list: () => agentAdminFetch(config, "/groups"),
2714
+ get: (groupId) => agentAdminFetch(
2715
+ config,
2716
+ `/groups/${encodeURIComponent(groupId)}`
2717
+ ),
2718
+ create: (body) => agentAdminFetch(config, "/groups", {
2719
+ method: "POST",
2720
+ body: JSON.stringify(body)
2721
+ }),
2722
+ update: (groupId, body) => agentAdminFetch(
2723
+ config,
2724
+ `/groups/${encodeURIComponent(groupId)}`,
2725
+ {
2726
+ method: "PATCH",
2727
+ body: JSON.stringify(body)
2728
+ }
2729
+ ),
2730
+ delete: (groupId) => agentAdminFetch(
2731
+ config,
2732
+ `/groups/${encodeURIComponent(groupId)}`,
2733
+ {
2734
+ method: "DELETE"
2735
+ }
2736
+ ),
2737
+ addMember: (groupRef, memberRef) => agentAdminFetch(
2738
+ config,
2739
+ `/groups/${encodeURIComponent(groupRef)}/members`,
2740
+ {
2741
+ method: "POST",
2742
+ body: JSON.stringify({ userId: memberRef })
2743
+ }
2744
+ ),
2745
+ removeMember: (groupRef, memberRef) => agentAdminFetch(
2746
+ config,
2747
+ `/groups/${encodeURIComponent(groupRef)}/members/${encodeURIComponent(memberRef)}`,
2748
+ { method: "DELETE" }
2749
+ )
2750
+ },
2751
+ tasks: {
2752
+ list: (query) => {
2753
+ const params = new URLSearchParams();
2754
+ for (const [key, value] of Object.entries(query ?? {})) {
2755
+ if (value !== void 0 && value !== "") {
2756
+ params.set(key, String(value));
2757
+ }
2758
+ }
2759
+ const suffix = params.size > 0 ? `?${params.toString()}` : "";
2760
+ return agentAdminFetch(
2761
+ config,
2762
+ `/tasks${suffix}`
2763
+ );
2764
+ },
2765
+ search: (q, limit) => {
2766
+ const params = new URLSearchParams({ q });
2767
+ if (limit !== void 0) {
2768
+ params.set("limit", String(limit));
2769
+ }
2770
+ return agentAdminFetch(
2771
+ config,
2772
+ `/tasks/search?${params.toString()}`
2773
+ );
2774
+ },
2775
+ get: (taskId) => agentAdminFetch(config, `/tasks/${taskId}`),
2776
+ assign: (body) => agentAdminFetch(config, "/tasks/assign", {
2777
+ method: "POST",
2778
+ body: JSON.stringify(body)
2779
+ })
2780
+ }
2781
+ };
2782
+ }
2783
+ function createBoundAgentAdminClient(ctx) {
2784
+ const caller = requireTenantCaller(ctx);
2785
+ const baseUrl = process.env.ROBOTROCK_BASE_URL?.trim();
2786
+ const serviceToken = process.env.ROBOTROCK_AGENT_SERVICE_TOKEN?.trim();
2787
+ if (caller.connectionId && serviceToken) {
2788
+ return createAgentAdminApi({
2789
+ baseUrl,
2790
+ auth: resolveRobotRockAuthConfig({
2791
+ agentService: {
2792
+ token: serviceToken,
2793
+ tenantSlug: caller.tenantSlug,
2794
+ connectionId: caller.connectionId,
2795
+ actingUserId: caller.userId
2796
+ }
2797
+ })
2798
+ });
2799
+ }
2800
+ const apiKey = process.env.ROBOTROCK_API_KEY?.trim();
2801
+ if (apiKey) {
2802
+ return createAgentAdminApi({
2803
+ baseUrl,
2804
+ auth: {
2805
+ kind: "apiKey",
2806
+ apiKey,
2807
+ actingUserId: caller.userId
2808
+ }
2809
+ });
2810
+ }
2811
+ throw new Error(
2812
+ "Agent admin auth is unset. Set ROBOTROCK_AGENT_SERVICE_TOKEN for hosted multi-tenant agents, or ROBOTROCK_API_KEY for self-hosted and localhost deployments."
2813
+ );
2814
+ }
2815
+ function requireBoundAgentAdminClient(ctx) {
2816
+ requireAdminCaller(ctx);
2817
+ return createBoundAgentAdminClient(ctx);
2818
+ }
2290
2819
  export {
2291
2820
  ROBOTROCK_PLATFORM_USER_CONTEXT_PUBLIC_KEY_URL,
2292
2821
  ROBOTROCK_READY_HOOK_SLUG,
@@ -2294,6 +2823,8 @@ export {
2294
2823
  ROBOTROCK_USER_CONTEXT_HEADER,
2295
2824
  ROBOTROCK_USER_CONTEXT_ISSUER,
2296
2825
  buildRobotRockTaskPayload,
2826
+ createAgentAdminApi,
2827
+ createBoundAgentAdminClient,
2297
2828
  createRobotRockCronChat,
2298
2829
  createRobotRockTask,
2299
2830
  defineRobotRockChatAuditHook,
@@ -2305,6 +2836,7 @@ export {
2305
2836
  postRobotRockLinkChatTask,
2306
2837
  postRobotRockStageHitl,
2307
2838
  requireAdminCaller,
2839
+ requireBoundAgentAdminClient,
2308
2840
  requireTenantCaller,
2309
2841
  resetBoundClientAuthWarning,
2310
2842
  resetChatAuditWarnings,