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.
- package/README.md +2 -2
- package/dist/agent-admin.d.ts +82 -0
- package/dist/agent-admin.js +938 -0
- package/dist/agent-admin.js.map +1 -0
- package/dist/ai/index.d.ts +6 -5
- package/dist/ai/index.js +407 -188
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/trigger.d.ts +4 -3
- package/dist/ai/trigger.js +407 -188
- package/dist/ai/trigger.js.map +1 -1
- package/dist/ai/workflow.d.ts +4 -3
- package/dist/ai/workflow.js +404 -185
- package/dist/ai/workflow.js.map +1 -1
- package/dist/auth-headers-qL-ZeEtd.d.ts +13 -0
- package/dist/{client-XTnFHGFE.d.ts → client-YO9Y1rkH.d.ts} +29 -17
- package/dist/eve/agent/index.d.ts +11 -35
- package/dist/eve/agent/index.js +678 -146
- package/dist/eve/agent/index.js.map +1 -1
- package/dist/eve/index.d.ts +5 -2
- package/dist/eve/index.js +195 -2
- package/dist/eve/index.js.map +1 -1
- package/dist/eve/tools/admin/assign-tasks.d.ts +39 -0
- package/dist/eve/tools/admin/assign-tasks.js +1060 -0
- package/dist/eve/tools/admin/assign-tasks.js.map +1 -0
- package/dist/eve/tools/admin/manage-groups.d.ts +53 -0
- package/dist/eve/tools/admin/manage-groups.js +1218 -0
- package/dist/eve/tools/admin/manage-groups.js.map +1 -0
- package/dist/eve/tools/admin/manage-team-members.d.ts +45 -0
- package/dist/eve/tools/admin/manage-team-members.js +1160 -0
- package/dist/eve/tools/admin/manage-team-members.js.map +1 -0
- package/dist/eve/tools/admin/query-tasks.d.ts +71 -0
- package/dist/eve/tools/admin/query-tasks.js +1161 -0
- package/dist/eve/tools/admin/query-tasks.js.map +1 -0
- package/dist/eve/tools/catalog/search-products.d.ts +57 -0
- package/dist/eve/tools/catalog/search-products.js +94 -0
- package/dist/eve/tools/catalog/search-products.js.map +1 -0
- package/dist/eve/tools/identity/index.d.ts +2 -0
- package/dist/eve/tools/identity/index.js +117 -27
- package/dist/eve/tools/identity/index.js.map +1 -1
- package/dist/eve/tools/identity/my-access.d.ts +6 -46
- package/dist/eve/tools/identity/my-access.js +91 -10
- package/dist/eve/tools/identity/my-access.js.map +1 -1
- package/dist/eve/tools/identity/whoami.d.ts +7 -8
- package/dist/eve/tools/identity/whoami.js +33 -17
- package/dist/eve/tools/identity/whoami.js.map +1 -1
- package/dist/eve/tools/inbox/create-task.d.ts +5 -4
- package/dist/eve/tools/inbox/create-task.js +365 -137
- package/dist/eve/tools/inbox/create-task.js.map +1 -1
- package/dist/eve/tools/inbox/index.d.ts +1 -0
- package/dist/eve/tools/inbox/index.js +365 -137
- package/dist/eve/tools/inbox/index.js.map +1 -1
- package/dist/eve/tools/index.d.ts +7 -0
- package/dist/eve/tools/index.js +1362 -168
- package/dist/eve/tools/index.js.map +1 -1
- package/dist/{index-BL9qKHA8.d.ts → index-DoQN48Bm.d.ts} +61 -2
- package/dist/index.d.ts +6 -3
- package/dist/index.js +325 -119
- package/dist/index.js.map +1 -1
- package/dist/schemas/index.d.ts +6 -1
- package/dist/schemas/index.js +177 -48
- package/dist/schemas/index.js.map +1 -1
- package/dist/{tool-approval-bridge-C4bTm8vu.d.ts → tool-approval-bridge-aMA79Z1B.d.ts} +1 -1
- package/dist/tool-reply-guidance-C3qrT1In.d.ts +25 -0
- package/dist/trigger/index.d.ts +2 -1
- package/dist/trigger/index.js +310 -108
- package/dist/trigger/index.js.map +1 -1
- package/dist/{trigger-Dn0DFiyU.d.ts → trigger-CXrbKVCL.d.ts} +2 -2
- package/dist/workflow/index.d.ts +2 -1
- package/dist/workflow/index.js +310 -108
- package/dist/workflow/index.js.map +1 -1
- package/package.json +30 -6
package/dist/eve/agent/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 =
|
|
1310
|
+
var handlerUrlSchema2 = z4.string().refine((url) => isAllowedHandlerUrl(url), {
|
|
1101
1311
|
message: HANDLER_URL_ERROR
|
|
1102
1312
|
});
|
|
1103
|
-
var jsonSchema7Schema2 =
|
|
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 =
|
|
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 =
|
|
1111
|
-
type:
|
|
1320
|
+
var webhookHandlerSchema2 = z4.object({
|
|
1321
|
+
type: z4.literal("webhook"),
|
|
1112
1322
|
url: handlerUrlSchema2,
|
|
1113
|
-
headers:
|
|
1323
|
+
headers: z4.record(z4.string(), z4.string())
|
|
1114
1324
|
});
|
|
1115
1325
|
var triggerHandlerSchema2 = webhookHandlerSchema2.extend({
|
|
1116
|
-
type:
|
|
1117
|
-
tokenId:
|
|
1326
|
+
type: z4.literal("trigger"),
|
|
1327
|
+
tokenId: z4.string().min(1)
|
|
1118
1328
|
});
|
|
1119
|
-
var handlerSchema2 =
|
|
1120
|
-
var taskActionInputSchema2 =
|
|
1121
|
-
id:
|
|
1122
|
-
title:
|
|
1123
|
-
description:
|
|
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:
|
|
1336
|
+
data: z4.record(z4.string(), z4.unknown()).optional()
|
|
1127
1337
|
});
|
|
1128
1338
|
var taskActionSchema2 = taskActionInputSchema2.extend({
|
|
1129
|
-
handlers:
|
|
1339
|
+
handlers: z4.array(handlerSchema2).min(1).optional()
|
|
1130
1340
|
});
|
|
1131
|
-
var uiFieldSchemaSchema2 =
|
|
1132
|
-
"ui:widget":
|
|
1133
|
-
"ui:title":
|
|
1134
|
-
"ui:description":
|
|
1135
|
-
"ui:options":
|
|
1136
|
-
items:
|
|
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 =
|
|
1139
|
-
var contextDataSchema2 =
|
|
1140
|
-
data:
|
|
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 =
|
|
1145
|
-
app:
|
|
1146
|
-
type:
|
|
1147
|
-
name:
|
|
1148
|
-
description:
|
|
1149
|
-
validUntil:
|
|
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:
|
|
1361
|
+
contextVersion: z4.literal(2).optional(),
|
|
1152
1362
|
/** @deprecated Use `contextVersion`. Accepted on ingest only. */
|
|
1153
|
-
version:
|
|
1154
|
-
actions:
|
|
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:
|
|
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 =
|
|
1180
|
-
users:
|
|
1181
|
-
groups:
|
|
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 =
|
|
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 =
|
|
1203
|
-
var threadUpdateInputSchema2 =
|
|
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 =
|
|
1209
|
-
var agentTelemetrySchema2 =
|
|
1210
|
-
version:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
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,
|