robotrock 0.9.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/ai/index.d.ts +18 -7
  2. package/dist/ai/index.js +852 -115
  3. package/dist/ai/index.js.map +1 -1
  4. package/dist/ai/trigger.d.ts +4 -3
  5. package/dist/ai/trigger.js +810 -115
  6. package/dist/ai/trigger.js.map +1 -1
  7. package/dist/ai/workflow.d.ts +15 -4
  8. package/dist/ai/workflow.js +729 -115
  9. package/dist/ai/workflow.js.map +1 -1
  10. package/dist/client-XTnFHGFE.d.ts +248 -0
  11. package/dist/eve/agent/index.d.ts +188 -0
  12. package/dist/eve/agent/index.js +2322 -0
  13. package/dist/eve/agent/index.js.map +1 -0
  14. package/dist/eve/index.d.ts +5 -0
  15. package/dist/eve/index.js +446 -0
  16. package/dist/eve/index.js.map +1 -0
  17. package/dist/eve/tools/identity/index.d.ts +6 -0
  18. package/dist/eve/tools/identity/index.js +144 -0
  19. package/dist/eve/tools/identity/index.js.map +1 -0
  20. package/dist/eve/tools/identity/my-access.d.ts +58 -0
  21. package/dist/eve/tools/identity/my-access.js +106 -0
  22. package/dist/eve/tools/identity/my-access.js.map +1 -0
  23. package/dist/eve/tools/identity/whoami.d.ts +45 -0
  24. package/dist/eve/tools/identity/whoami.js +101 -0
  25. package/dist/eve/tools/identity/whoami.js.map +1 -0
  26. package/dist/eve/tools/inbox/create-task.d.ts +113 -0
  27. package/dist/eve/tools/inbox/create-task.js +1557 -0
  28. package/dist/eve/tools/inbox/create-task.js.map +1 -0
  29. package/dist/eve/tools/inbox/index.d.ts +5 -0
  30. package/dist/eve/tools/inbox/index.js +1557 -0
  31. package/dist/eve/tools/inbox/index.js.map +1 -0
  32. package/dist/eve/tools/index.d.ts +17 -0
  33. package/dist/eve/tools/index.js +1654 -0
  34. package/dist/eve/tools/index.js.map +1 -0
  35. package/dist/index-BL9qKHA8.d.ts +141 -0
  36. package/dist/index.d.ts +12 -44
  37. package/dist/index.js +793 -97
  38. package/dist/index.js.map +1 -1
  39. package/dist/schemas/index.d.ts +11 -1
  40. package/dist/schemas/index.js +126 -8
  41. package/dist/schemas/index.js.map +1 -1
  42. package/dist/tenant-5YKDrdC-.d.ts +23 -0
  43. package/dist/{tool-approval-bridge-G765kMJR.d.ts → tool-approval-bridge-C4bTm8vu.d.ts} +93 -2
  44. package/dist/trigger/index.d.ts +2 -1
  45. package/dist/trigger/index.js +495 -87
  46. package/dist/trigger/index.js.map +1 -1
  47. package/dist/{trigger-D0shjqk0.d.ts → trigger-Dn0DFiyU.d.ts} +64 -3
  48. package/dist/workflow/index.d.ts +2 -1
  49. package/dist/workflow/index.js +496 -88
  50. package/dist/workflow/index.js.map +1 -1
  51. package/package.json +44 -7
  52. package/dist/client-Cy7YLxms.d.ts +0 -145
@@ -0,0 +1,446 @@
1
+ // src/platform-actions.ts
2
+ var PLATFORM_MARK_DONE_ACTION_ID = "robotrock:mark-done";
3
+ var PLATFORM_REJECT_REQUEST_ACTION_ID = "robotrock:reject-request";
4
+ function isPlatformMarkDoneAction(actionId) {
5
+ return actionId === PLATFORM_MARK_DONE_ACTION_ID;
6
+ }
7
+ function isPlatformRejectRequestAction(actionId) {
8
+ return actionId === PLATFORM_REJECT_REQUEST_ACTION_ID;
9
+ }
10
+ function isPlatformTerminalAction(actionId) {
11
+ return isPlatformMarkDoneAction(actionId) || isPlatformRejectRequestAction(actionId);
12
+ }
13
+ function parsePlatformRejectRequestData(data) {
14
+ if (data == null || typeof data !== "object") {
15
+ return null;
16
+ }
17
+ const feedback = data.feedback;
18
+ if (typeof feedback !== "string") {
19
+ return null;
20
+ }
21
+ const trimmed = feedback.trim();
22
+ if (!trimmed) {
23
+ return null;
24
+ }
25
+ return { feedback: trimmed };
26
+ }
27
+
28
+ // src/eve/input-request.ts
29
+ var EVE_INPUT_SUBMIT_ACTION_ID = "submit";
30
+ var EVE_INPUT_OTHER_CHOICE_ID = "__other__";
31
+ var EVE_INPUT_OTHER_CHOICE_LABEL = "Type your own answer";
32
+ var CONFIRMATION_DEFAULT_OPTIONS = [
33
+ { id: "approve", label: "Approve", style: "primary" },
34
+ { id: "deny", label: "Deny", style: "danger" }
35
+ ];
36
+ var SELECT_PER_OPTION_THRESHOLD = 6;
37
+ function asRecord(value) {
38
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
39
+ return null;
40
+ }
41
+ return value;
42
+ }
43
+ function readStringField(data, key) {
44
+ const value = data[key];
45
+ if (typeof value !== "string") {
46
+ return void 0;
47
+ }
48
+ const trimmed = value.trim();
49
+ return trimmed.length > 0 ? trimmed : void 0;
50
+ }
51
+ function resolveEveInputDisplay(request, toolName) {
52
+ if (request.display) {
53
+ return request.display;
54
+ }
55
+ if (toolName === "ask_question") {
56
+ return request.options && request.options.length > 0 ? "select" : "text";
57
+ }
58
+ if (request.options && request.options.length > 0) {
59
+ return "select";
60
+ }
61
+ return "confirmation";
62
+ }
63
+ function confirmationActions(request) {
64
+ const options = request.options && request.options.length > 0 ? request.options : CONFIRMATION_DEFAULT_OPTIONS;
65
+ return options.map((option) => ({
66
+ id: option.id,
67
+ title: option.label,
68
+ ...option.description ? { description: option.description } : {}
69
+ }));
70
+ }
71
+ function textSubmitAction(prompt) {
72
+ return {
73
+ id: EVE_INPUT_SUBMIT_ACTION_ID,
74
+ title: "Submit",
75
+ schema: {
76
+ type: "object",
77
+ required: ["answer"],
78
+ properties: {
79
+ answer: {
80
+ type: "string",
81
+ title: "Your answer"
82
+ }
83
+ }
84
+ },
85
+ ui: {
86
+ answer: {
87
+ "ui:title": prompt.trim() || "Your answer",
88
+ "ui:widget": "textarea"
89
+ }
90
+ }
91
+ };
92
+ }
93
+ function selectPerOptionActions(options) {
94
+ return options.map((option) => ({
95
+ id: option.id,
96
+ title: option.label,
97
+ ...option.description ? { description: option.description } : {}
98
+ }));
99
+ }
100
+ function selectFormAction(request) {
101
+ const options = request.options ?? [];
102
+ const allowFreeform = request.allowFreeform === true;
103
+ const enumValues = options.map((option) => option.id);
104
+ const enumNames = options.map((option) => option.label);
105
+ if (allowFreeform) {
106
+ enumValues.push(EVE_INPUT_OTHER_CHOICE_ID);
107
+ enumNames.push(EVE_INPUT_OTHER_CHOICE_LABEL);
108
+ }
109
+ const properties = {
110
+ choice: {
111
+ type: "string",
112
+ title: "Choose one",
113
+ enum: enumValues
114
+ }
115
+ };
116
+ if (allowFreeform) {
117
+ properties.other = {
118
+ type: "string",
119
+ title: "Your answer"
120
+ };
121
+ }
122
+ const schema = {
123
+ type: "object",
124
+ required: ["choice"],
125
+ properties
126
+ };
127
+ if (allowFreeform) {
128
+ schema.allOf = [
129
+ {
130
+ if: {
131
+ properties: {
132
+ choice: { const: EVE_INPUT_OTHER_CHOICE_ID }
133
+ },
134
+ required: ["choice"]
135
+ },
136
+ then: {
137
+ required: ["other"],
138
+ properties: {
139
+ other: {
140
+ type: "string",
141
+ minLength: 1
142
+ }
143
+ }
144
+ }
145
+ }
146
+ ];
147
+ }
148
+ const ui = {
149
+ choice: {
150
+ "ui:widget": "radio",
151
+ "ui:enumNames": enumNames
152
+ }
153
+ };
154
+ if (allowFreeform) {
155
+ ui.other = {
156
+ "ui:placeholder": "Enter your answer"
157
+ };
158
+ }
159
+ return {
160
+ id: EVE_INPUT_SUBMIT_ACTION_ID,
161
+ title: "Submit",
162
+ schema,
163
+ ui
164
+ };
165
+ }
166
+ function normalizeEveSelectFormData(data) {
167
+ const choice = typeof data.choice === "string" ? data.choice.trim() : void 0;
168
+ if (!choice) {
169
+ return data;
170
+ }
171
+ if (choice === EVE_INPUT_OTHER_CHOICE_ID) {
172
+ return {
173
+ choice,
174
+ ...data.other !== void 0 ? { other: data.other } : {}
175
+ };
176
+ }
177
+ return { choice };
178
+ }
179
+ function eveInputRequestToActions(request, options) {
180
+ const display = resolveEveInputDisplay(request, options?.toolName);
181
+ switch (display) {
182
+ case "confirmation":
183
+ return confirmationActions(request);
184
+ case "text":
185
+ return [textSubmitAction(request.prompt)];
186
+ case "select": {
187
+ const selectOptions = request.options ?? [];
188
+ if (selectOptions.length === 0) {
189
+ return [textSubmitAction(request.prompt)];
190
+ }
191
+ if (selectOptions.length <= SELECT_PER_OPTION_THRESHOLD && request.allowFreeform !== true) {
192
+ return selectPerOptionActions(selectOptions);
193
+ }
194
+ return [selectFormAction(request)];
195
+ }
196
+ }
197
+ }
198
+ function eveInputRequestTaskType(request, options) {
199
+ const display = resolveEveInputDisplay(request, options?.toolName);
200
+ if (display === "confirmation" && options?.toolName) {
201
+ return `eve-approval:${options.toolName}`;
202
+ }
203
+ return `eve-input:${display}`;
204
+ }
205
+ function taskHandledToEveInputResponse(request, actionId, actionData, options) {
206
+ const base = { requestId: request.requestId };
207
+ if (isPlatformTerminalAction(actionId)) {
208
+ const feedback = parsePlatformRejectRequestData(actionData)?.feedback;
209
+ return {
210
+ ...base,
211
+ optionId: "deny",
212
+ ...feedback ? { text: feedback } : {}
213
+ };
214
+ }
215
+ const display = resolveEveInputDisplay(request, options?.toolName);
216
+ const selectOptions = request.options ?? [];
217
+ const data = asRecord(actionData);
218
+ if (display === "confirmation") {
219
+ return { ...base, optionId: actionId };
220
+ }
221
+ const matchingOption = selectOptions.find((option) => option.id === actionId);
222
+ if (matchingOption) {
223
+ return { ...base, optionId: actionId };
224
+ }
225
+ if (actionId === EVE_INPUT_SUBMIT_ACTION_ID && data) {
226
+ const submissionData = display === "select" && request.allowFreeform === true ? normalizeEveSelectFormData(data) : data;
227
+ const answer = readStringField(submissionData, "answer");
228
+ if (answer) {
229
+ return { ...base, text: answer };
230
+ }
231
+ const choice = readStringField(submissionData, "choice");
232
+ if (choice === EVE_INPUT_OTHER_CHOICE_ID) {
233
+ const other = readStringField(submissionData, "other");
234
+ if (other) {
235
+ return { ...base, text: other };
236
+ }
237
+ }
238
+ if (choice) {
239
+ if (selectOptions.some((option) => option.id === choice)) {
240
+ return { ...base, optionId: choice };
241
+ }
242
+ return { ...base, text: choice };
243
+ }
244
+ }
245
+ if (data) {
246
+ const answer = readStringField(data, "answer");
247
+ if (answer) {
248
+ return { ...base, text: answer };
249
+ }
250
+ }
251
+ return { ...base, optionId: actionId };
252
+ }
253
+
254
+ // src/eve/input-audit.ts
255
+ function matchOptionByText(text, options) {
256
+ const normalized = text.trim().toLowerCase();
257
+ if (normalized.length === 0) {
258
+ return void 0;
259
+ }
260
+ const byId = options.find((option) => option.id.toLowerCase() === normalized);
261
+ if (byId) {
262
+ return byId;
263
+ }
264
+ const byLabel = options.find((option) => option.label.toLowerCase() === normalized);
265
+ if (byLabel) {
266
+ return byLabel;
267
+ }
268
+ const index = Number(normalized);
269
+ if (Number.isInteger(index) && index > 0 && index <= options.length) {
270
+ return options[index - 1];
271
+ }
272
+ return void 0;
273
+ }
274
+ function resolveEveFreeformTextToInputResponse(request, text) {
275
+ const trimmed = text.trim();
276
+ if (trimmed.length === 0) {
277
+ return void 0;
278
+ }
279
+ const options = request.options ?? [];
280
+ if (options.length > 0) {
281
+ const matched = matchOptionByText(trimmed, options);
282
+ if (matched) {
283
+ return { requestId: request.requestId, optionId: matched.id };
284
+ }
285
+ }
286
+ if (request.allowFreeform === true || options.length === 0) {
287
+ return { requestId: request.requestId, text: trimmed };
288
+ }
289
+ return void 0;
290
+ }
291
+ function isEveApprovalInputRequest(request) {
292
+ const options = request.options ?? [];
293
+ return options.length === 2 && options[0]?.id === "approve" && options[1]?.id === "deny";
294
+ }
295
+ function eveInputResponseToActionSubmission(request, response, options) {
296
+ const display = resolveEveInputDisplay(request, options?.toolName);
297
+ const actions = eveInputRequestToActions(request, options);
298
+ if (response.optionId) {
299
+ const action = actions.find((entry) => entry.id === response.optionId);
300
+ if (action) {
301
+ return {
302
+ actionId: response.optionId,
303
+ actionTitle: action.title,
304
+ formData: {}
305
+ };
306
+ }
307
+ const option = request.options?.find((entry) => entry.id === response.optionId);
308
+ if (option) {
309
+ return {
310
+ actionId: response.optionId,
311
+ actionTitle: option.label,
312
+ formData: {}
313
+ };
314
+ }
315
+ return {
316
+ actionId: response.optionId,
317
+ actionTitle: response.optionId,
318
+ formData: {}
319
+ };
320
+ }
321
+ const text = response.text?.trim();
322
+ if (text) {
323
+ if (display === "text") {
324
+ return {
325
+ actionId: EVE_INPUT_SUBMIT_ACTION_ID,
326
+ actionTitle: text,
327
+ formData: { answer: text }
328
+ };
329
+ }
330
+ if (display === "select") {
331
+ const option = request.options?.find((entry) => entry.id === text);
332
+ if (option) {
333
+ return {
334
+ actionId: EVE_INPUT_SUBMIT_ACTION_ID,
335
+ actionTitle: option.label,
336
+ formData: { choice: option.id }
337
+ };
338
+ }
339
+ return {
340
+ actionId: EVE_INPUT_SUBMIT_ACTION_ID,
341
+ actionTitle: text,
342
+ formData: { choice: text }
343
+ };
344
+ }
345
+ return {
346
+ actionId: EVE_INPUT_SUBMIT_ACTION_ID,
347
+ actionTitle: text,
348
+ formData: { answer: text }
349
+ };
350
+ }
351
+ return {
352
+ actionId: EVE_INPUT_SUBMIT_ACTION_ID,
353
+ actionTitle: "Responded",
354
+ formData: {}
355
+ };
356
+ }
357
+ function buildEveInputAuditSubmissionData(context, formData) {
358
+ return {
359
+ toolCallId: context.toolCallId,
360
+ ...context.toolName ? { toolName: context.toolName } : {},
361
+ ...context.requestId ? { requestId: context.requestId } : {},
362
+ ...context.display ? { display: context.display } : {},
363
+ ...context.toolInput !== void 0 ? { toolInput: context.toolInput } : {},
364
+ ...formData
365
+ };
366
+ }
367
+ function parseEveAskQuestionToolOutput(output) {
368
+ if (output == null || typeof output !== "object") {
369
+ return null;
370
+ }
371
+ const record = output;
372
+ const value = record.type === "json" && record.value != null && typeof record.value === "object" ? record.value : record;
373
+ const optionId = typeof value.optionId === "string" ? value.optionId : void 0;
374
+ const text = typeof value.text === "string" ? value.text : void 0;
375
+ if (!optionId && !text) {
376
+ return null;
377
+ }
378
+ return { ...optionId ? { optionId } : {}, ...text ? { text } : {} };
379
+ }
380
+
381
+ // src/eve/tool-display.ts
382
+ var DEFAULT_TOOL_DISPLAY_LABELS = {
383
+ refund_charge: "Refund a customer charge",
384
+ deploy_release: "Deploy a release",
385
+ get_weather: "Get weather",
386
+ get_my_access: "Check my access",
387
+ whoami: "Who am I",
388
+ create_robotrock_task: "Create a RobotRock task"
389
+ };
390
+ var toolDisplayLabelOverrides = {};
391
+ function setToolDisplayLabelOverrides(overrides) {
392
+ toolDisplayLabelOverrides = overrides;
393
+ }
394
+ function formatToolName(toolName) {
395
+ const spaced = toolName.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").trim();
396
+ if (!spaced) {
397
+ return "Tool";
398
+ }
399
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
400
+ }
401
+ function getToolDisplayLabel(toolName) {
402
+ const trimmed = toolName.trim();
403
+ if (!trimmed) {
404
+ return "Tool";
405
+ }
406
+ return toolDisplayLabelOverrides[trimmed] ?? DEFAULT_TOOL_DISPLAY_LABELS[trimmed] ?? formatToolName(trimmed);
407
+ }
408
+ function formatEveApprovalTitle(request, toolName) {
409
+ const display = resolveEveInputDisplay(request, toolName);
410
+ if (display !== "confirmation" || !toolName) {
411
+ return request.prompt;
412
+ }
413
+ return `Approve: ${getToolDisplayLabel(toolName)}`;
414
+ }
415
+
416
+ // src/eve/resume-message.ts
417
+ function buildTaskHandledResumeMessage(payload) {
418
+ const handledBy = payload.handledBy?.trim() || "someone";
419
+ const actionTitle = payload.action.title.trim();
420
+ return `RobotRock task ${payload.taskId} was handled: ${actionTitle} by ${handledBy}. Briefly tell the user what was decided and what happens next.`;
421
+ }
422
+
423
+ // src/eve/index.ts
424
+ var ROBOTROCK_READY_HOOK_SLUG = "robotrock-ready";
425
+ export {
426
+ DEFAULT_TOOL_DISPLAY_LABELS,
427
+ EVE_INPUT_OTHER_CHOICE_ID,
428
+ EVE_INPUT_OTHER_CHOICE_LABEL,
429
+ EVE_INPUT_SUBMIT_ACTION_ID,
430
+ ROBOTROCK_READY_HOOK_SLUG,
431
+ buildEveInputAuditSubmissionData,
432
+ buildTaskHandledResumeMessage,
433
+ eveInputRequestTaskType,
434
+ eveInputRequestToActions,
435
+ eveInputResponseToActionSubmission,
436
+ formatEveApprovalTitle,
437
+ getToolDisplayLabel,
438
+ isEveApprovalInputRequest,
439
+ normalizeEveSelectFormData,
440
+ parseEveAskQuestionToolOutput,
441
+ resolveEveFreeformTextToInputResponse,
442
+ resolveEveInputDisplay,
443
+ setToolDisplayLabelOverrides,
444
+ taskHandledToEveInputResponse
445
+ };
446
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/platform-actions.ts","../../src/eve/input-request.ts","../../src/eve/input-audit.ts","../../src/eve/tool-display.ts","../../src/eve/resume-message.ts","../../src/eve/index.ts"],"sourcesContent":["/**\n * Reserved inbox actions that reviewers can take outside your task's defined actions.\n * Agents and integrations must treat these as terminal — stop the run and do not retry sendToHuman.\n */\n\nexport const PLATFORM_MARK_DONE_ACTION_ID = \"robotrock:mark-done\" as const;\nexport const PLATFORM_REJECT_REQUEST_ACTION_ID = \"robotrock:reject-request\" as const;\n\nexport const PLATFORM_MARK_DONE_ACTION_TITLE = \"Mark as done\";\nexport const PLATFORM_REJECT_REQUEST_ACTION_TITLE = \"Reject request\";\n\nexport const PLATFORM_TERMINAL_ACTION_IDS = [\n PLATFORM_MARK_DONE_ACTION_ID,\n PLATFORM_REJECT_REQUEST_ACTION_ID,\n] as const;\n\nexport type PlatformTerminalActionId = (typeof PLATFORM_TERMINAL_ACTION_IDS)[number];\n\nexport type PlatformRejectRequestData = {\n feedback: string;\n};\n\nexport type HandledActionInput = {\n actionId: string;\n data?: unknown;\n handledBy?: string;\n handledAt?: number | Date;\n};\n\nexport type PlatformMarkDoneOutcome = {\n source: \"platform\";\n kind: \"mark-done\";\n actionId: typeof PLATFORM_MARK_DONE_ACTION_ID;\n data: Record<string, never>;\n handledBy?: string;\n handledAt?: Date;\n};\n\nexport type PlatformRejectRequestOutcome = {\n source: \"platform\";\n kind: \"reject-request\";\n actionId: typeof PLATFORM_REJECT_REQUEST_ACTION_ID;\n data: PlatformRejectRequestData;\n handledBy?: string;\n handledAt?: Date;\n};\n\nexport type TaskActionOutcome = {\n source: \"task\";\n actionId: string;\n data: unknown;\n handledBy?: string;\n handledAt?: Date;\n};\n\nexport type HandledOutcome =\n | PlatformMarkDoneOutcome\n | PlatformRejectRequestOutcome\n | TaskActionOutcome;\n\nexport class PlatformRejectRequestError extends Error {\n readonly actionId = PLATFORM_REJECT_REQUEST_ACTION_ID;\n readonly feedback: string;\n\n constructor(feedback: string, message?: string) {\n super(message ?? `Human rejected the request: ${feedback}`);\n this.name = \"PlatformRejectRequestError\";\n this.feedback = feedback;\n }\n}\n\nexport function isPlatformMarkDoneAction(\n actionId: string | undefined\n): actionId is typeof PLATFORM_MARK_DONE_ACTION_ID {\n return actionId === PLATFORM_MARK_DONE_ACTION_ID;\n}\n\nexport function isPlatformRejectRequestAction(\n actionId: string | undefined\n): actionId is typeof PLATFORM_REJECT_REQUEST_ACTION_ID {\n return actionId === PLATFORM_REJECT_REQUEST_ACTION_ID;\n}\n\nexport function isPlatformTerminalAction(\n actionId: string | undefined\n): actionId is PlatformTerminalActionId {\n return (\n isPlatformMarkDoneAction(actionId) || isPlatformRejectRequestAction(actionId)\n );\n}\n\nexport function parsePlatformRejectRequestData(\n data: unknown\n): PlatformRejectRequestData | null {\n if (data == null || typeof data !== \"object\") {\n return null;\n }\n const feedback = (data as { feedback?: unknown }).feedback;\n if (typeof feedback !== \"string\") {\n return null;\n }\n const trimmed = feedback.trim();\n if (!trimmed) {\n return null;\n }\n return { feedback: trimmed };\n}\n\nfunction toHandledAt(value: number | Date | undefined): Date | undefined {\n if (value === undefined) {\n return undefined;\n }\n return value instanceof Date ? value : new Date(value);\n}\n\n/**\n * Classify a handled task action as a platform terminal outcome or a normal task action.\n */\nexport function parseHandledOutcome(input: HandledActionInput): HandledOutcome {\n const handledAt = toHandledAt(input.handledAt);\n const handledBy = input.handledBy;\n\n if (isPlatformMarkDoneAction(input.actionId)) {\n return {\n source: \"platform\",\n kind: \"mark-done\",\n actionId: PLATFORM_MARK_DONE_ACTION_ID,\n data: {},\n handledBy,\n handledAt,\n };\n }\n\n if (isPlatformRejectRequestAction(input.actionId)) {\n return {\n source: \"platform\",\n kind: \"reject-request\",\n actionId: PLATFORM_REJECT_REQUEST_ACTION_ID,\n data: parsePlatformRejectRequestData(input.data) ?? { feedback: \"\" },\n handledBy,\n handledAt,\n };\n }\n\n return {\n source: \"task\",\n actionId: input.actionId,\n data: input.data ?? {},\n handledBy,\n handledAt,\n };\n}\n\n/**\n * Throw when a human rejected the request from the inbox (not your task's reject action).\n * Use after polling, webhooks, or getTask when you want agents to stop immediately.\n */\nexport function assertNotPlatformRejectRequest(\n actionId: string,\n data?: unknown\n): void {\n if (!isPlatformRejectRequestAction(actionId)) {\n return;\n }\n const parsed = parsePlatformRejectRequestData(data);\n throw new PlatformRejectRequestError(\n parsed?.feedback ?? \"No feedback provided\"\n );\n}\n\n/**\n * Returns true when the agent should stop — platform mark-done or reject-request.\n */\nexport function shouldStopAgentForHandledAction(actionId: string | undefined): boolean {\n return isPlatformTerminalAction(actionId);\n}\n","import type { SendToHumanActionInput } from \"../client.js\";\nimport {\n isPlatformTerminalAction,\n parsePlatformRejectRequestData,\n} from \"../platform-actions.js\";\n\n/** One selectable option in an Eve HITL input request. */\nexport type EveInputOption = {\n readonly id: string;\n readonly label: string;\n readonly description?: string;\n readonly style?: \"danger\" | \"default\" | \"primary\";\n};\n\n/** Eve HITL display mode — mirrors `InputRequest.display` from the eve runtime. */\nexport type EveInputRequestDisplay = \"confirmation\" | \"select\" | \"text\";\n\n/**\n * Minimal Eve `InputRequest` shape for RobotRock bridging. Intentionally\n * self-contained so the SDK does not depend on the `eve` package.\n */\nexport type EveInputRequest = {\n readonly requestId: string;\n readonly prompt: string;\n readonly display?: EveInputRequestDisplay;\n readonly allowFreeform?: boolean;\n readonly options?: readonly EveInputOption[];\n};\n\n/** Eve `InputResponse` shape returned when resuming a parked session. */\nexport type EveInputResponse = {\n readonly requestId: string;\n readonly optionId?: string;\n readonly text?: string;\n};\n\nexport const EVE_INPUT_SUBMIT_ACTION_ID = \"submit\" as const;\nexport const EVE_INPUT_OTHER_CHOICE_ID = \"__other__\" as const;\nexport const EVE_INPUT_OTHER_CHOICE_LABEL = \"Type your own answer\" as const;\n\nconst CONFIRMATION_DEFAULT_OPTIONS: readonly EveInputOption[] = [\n { id: \"approve\", label: \"Approve\", style: \"primary\" },\n { id: \"deny\", label: \"Deny\", style: \"danger\" },\n];\n\nconst SELECT_PER_OPTION_THRESHOLD = 6;\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n return value as Record<string, unknown>;\n}\n\nfunction readStringField(data: Record<string, unknown>, key: string): string | undefined {\n const value = data[key];\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\n/** Resolve the effective display mode when Eve omits `display`. */\nexport function resolveEveInputDisplay(\n request: EveInputRequest,\n toolName?: string\n): EveInputRequestDisplay {\n if (request.display) {\n return request.display;\n }\n if (toolName === \"ask_question\") {\n return request.options && request.options.length > 0 ? \"select\" : \"text\";\n }\n if (request.options && request.options.length > 0) {\n return \"select\";\n }\n return \"confirmation\";\n}\n\nfunction confirmationActions(request: EveInputRequest): readonly SendToHumanActionInput[] {\n const options =\n request.options && request.options.length > 0\n ? request.options\n : CONFIRMATION_DEFAULT_OPTIONS;\n\n return options.map((option) => ({\n id: option.id,\n title: option.label,\n ...(option.description ? { description: option.description } : {}),\n }));\n}\n\nfunction textSubmitAction(prompt: string): SendToHumanActionInput {\n return {\n id: EVE_INPUT_SUBMIT_ACTION_ID,\n title: \"Submit\",\n schema: {\n type: \"object\",\n required: [\"answer\"],\n properties: {\n answer: {\n type: \"string\",\n title: \"Your answer\",\n },\n },\n },\n ui: {\n answer: {\n \"ui:title\": prompt.trim() || \"Your answer\",\n \"ui:widget\": \"textarea\",\n },\n },\n };\n}\n\nfunction selectPerOptionActions(\n options: readonly EveInputOption[]\n): readonly SendToHumanActionInput[] {\n return options.map((option) => ({\n id: option.id,\n title: option.label,\n ...(option.description ? { description: option.description } : {}),\n }));\n}\n\nfunction selectFormAction(request: EveInputRequest): SendToHumanActionInput {\n const options = request.options ?? [];\n const allowFreeform = request.allowFreeform === true;\n const enumValues = options.map((option) => option.id);\n const enumNames = options.map((option) => option.label);\n\n if (allowFreeform) {\n enumValues.push(EVE_INPUT_OTHER_CHOICE_ID);\n enumNames.push(EVE_INPUT_OTHER_CHOICE_LABEL);\n }\n\n const properties: Record<string, unknown> = {\n choice: {\n type: \"string\",\n title: \"Choose one\",\n enum: enumValues,\n },\n };\n\n if (allowFreeform) {\n properties.other = {\n type: \"string\",\n title: \"Your answer\",\n };\n }\n\n const schema: Record<string, unknown> = {\n type: \"object\",\n required: [\"choice\"],\n properties,\n };\n\n if (allowFreeform) {\n schema.allOf = [\n {\n if: {\n properties: {\n choice: { const: EVE_INPUT_OTHER_CHOICE_ID },\n },\n required: [\"choice\"],\n },\n then: {\n required: [\"other\"],\n properties: {\n other: {\n type: \"string\",\n minLength: 1,\n },\n },\n },\n },\n ];\n }\n\n const ui: Record<string, unknown> = {\n choice: {\n \"ui:widget\": \"radio\",\n \"ui:enumNames\": enumNames,\n },\n };\n\n if (allowFreeform) {\n ui.other = {\n \"ui:placeholder\": \"Enter your answer\",\n };\n }\n\n return {\n id: EVE_INPUT_SUBMIT_ACTION_ID,\n title: \"Submit\",\n schema: schema as SendToHumanActionInput[\"schema\"],\n ui: ui as SendToHumanActionInput[\"ui\"],\n };\n}\n\n/** Keep select-form submissions mutually exclusive between preset choice and freeform other. */\nexport function normalizeEveSelectFormData(\n data: Record<string, unknown>\n): Record<string, unknown> {\n const choice =\n typeof data.choice === \"string\" ? data.choice.trim() : undefined;\n if (!choice) {\n return data;\n }\n if (choice === EVE_INPUT_OTHER_CHOICE_ID) {\n return {\n choice,\n ...(data.other !== undefined ? { other: data.other } : {}),\n };\n }\n return { choice };\n}\n\n/**\n * Map an Eve `InputRequest` to RobotRock inbox actions.\n */\nexport function eveInputRequestToActions(\n request: EveInputRequest,\n options?: { toolName?: string }\n): readonly SendToHumanActionInput[] {\n const display = resolveEveInputDisplay(request, options?.toolName);\n\n switch (display) {\n case \"confirmation\":\n return confirmationActions(request);\n case \"text\":\n return [textSubmitAction(request.prompt)];\n case \"select\": {\n const selectOptions = request.options ?? [];\n if (selectOptions.length === 0) {\n return [textSubmitAction(request.prompt)];\n }\n if (\n selectOptions.length <= SELECT_PER_OPTION_THRESHOLD &&\n request.allowFreeform !== true\n ) {\n return selectPerOptionActions(selectOptions);\n }\n return [selectFormAction(request)];\n }\n }\n}\n\n/** Task type slug for an Eve input request. */\nexport function eveInputRequestTaskType(\n request: EveInputRequest,\n options?: { toolName?: string }\n): string {\n const display = resolveEveInputDisplay(request, options?.toolName);\n if (display === \"confirmation\" && options?.toolName) {\n return `eve-approval:${options.toolName}`;\n }\n return `eve-input:${display}`;\n}\n\n/**\n * Map a handled RobotRock task action back to an Eve `InputResponse`.\n */\nexport function taskHandledToEveInputResponse(\n request: EveInputRequest,\n actionId: string,\n actionData: unknown,\n options?: { toolName?: string }\n): EveInputResponse {\n const base = { requestId: request.requestId };\n\n if (isPlatformTerminalAction(actionId)) {\n const feedback = parsePlatformRejectRequestData(actionData)?.feedback;\n return {\n ...base,\n optionId: \"deny\",\n ...(feedback ? { text: feedback } : {}),\n };\n }\n\n const display = resolveEveInputDisplay(request, options?.toolName);\n const selectOptions = request.options ?? [];\n const data = asRecord(actionData);\n\n if (display === \"confirmation\") {\n return { ...base, optionId: actionId };\n }\n\n const matchingOption = selectOptions.find((option) => option.id === actionId);\n if (matchingOption) {\n return { ...base, optionId: actionId };\n }\n\n if (actionId === EVE_INPUT_SUBMIT_ACTION_ID && data) {\n const submissionData =\n display === \"select\" && request.allowFreeform === true\n ? normalizeEveSelectFormData(data)\n : data;\n\n const answer = readStringField(submissionData, \"answer\");\n if (answer) {\n return { ...base, text: answer };\n }\n\n const choice = readStringField(submissionData, \"choice\");\n if (choice === EVE_INPUT_OTHER_CHOICE_ID) {\n const other = readStringField(submissionData, \"other\");\n if (other) {\n return { ...base, text: other };\n }\n }\n\n if (choice) {\n if (selectOptions.some((option) => option.id === choice)) {\n return { ...base, optionId: choice };\n }\n return { ...base, text: choice };\n }\n }\n\n if (data) {\n const answer = readStringField(data, \"answer\");\n if (answer) {\n return { ...base, text: answer };\n }\n }\n\n return { ...base, optionId: actionId };\n}\n","import {\n EVE_INPUT_SUBMIT_ACTION_ID,\n eveInputRequestToActions,\n resolveEveInputDisplay,\n type EveInputOption,\n type EveInputRequest,\n type EveInputRequestDisplay,\n type EveInputResponse,\n} from \"./input-request.js\";\n\nexport type EveInputAuditContext = {\n toolCallId: string;\n toolName?: string;\n requestId?: string;\n display?: EveInputRequestDisplay;\n toolInput?: unknown;\n};\n\nfunction matchOptionByText(\n text: string,\n options: readonly EveInputOption[]\n): EveInputOption | undefined {\n const normalized = text.trim().toLowerCase();\n if (normalized.length === 0) {\n return undefined;\n }\n\n const byId = options.find((option) => option.id.toLowerCase() === normalized);\n if (byId) {\n return byId;\n }\n\n const byLabel = options.find((option) => option.label.toLowerCase() === normalized);\n if (byLabel) {\n return byLabel;\n }\n\n const index = Number(normalized);\n if (Number.isInteger(index) && index > 0 && index <= options.length) {\n return options[index - 1];\n }\n\n return undefined;\n}\n\n/**\n * Map freeform composer text to an Eve `InputResponse`, mirroring Eve's\n * `resolveTextToResponse` rules (option id/label, numeric index, freeform text).\n */\nexport function resolveEveFreeformTextToInputResponse(\n request: EveInputRequest,\n text: string\n): EveInputResponse | undefined {\n const trimmed = text.trim();\n if (trimmed.length === 0) {\n return undefined;\n }\n\n const options = request.options ?? [];\n if (options.length > 0) {\n const matched = matchOptionByText(trimmed, options);\n if (matched) {\n return { requestId: request.requestId, optionId: matched.id };\n }\n }\n\n if (request.allowFreeform === true || options.length === 0) {\n return { requestId: request.requestId, text: trimmed };\n }\n\n return undefined;\n}\n\n/** Returns true for Eve's default approval gate (approve / deny options). */\nexport function isEveApprovalInputRequest(request: EveInputRequest): boolean {\n const options = request.options ?? [];\n return (\n options.length === 2 &&\n options[0]?.id === \"approve\" &&\n options[1]?.id === \"deny\"\n );\n}\n\nexport type EveInputActionSubmission = {\n actionId: string;\n actionTitle: string;\n formData: Record<string, unknown>;\n};\n\n/**\n * Map a resolved Eve `InputResponse` to RobotRock audit fields (action id/title).\n */\nexport function eveInputResponseToActionSubmission(\n request: EveInputRequest,\n response: EveInputResponse,\n options?: { toolName?: string }\n): EveInputActionSubmission {\n const display = resolveEveInputDisplay(request, options?.toolName);\n const actions = eveInputRequestToActions(request, options);\n\n if (response.optionId) {\n const action = actions.find((entry) => entry.id === response.optionId);\n if (action) {\n return {\n actionId: response.optionId,\n actionTitle: action.title,\n formData: {},\n };\n }\n\n const option = request.options?.find((entry) => entry.id === response.optionId);\n if (option) {\n return {\n actionId: response.optionId,\n actionTitle: option.label,\n formData: {},\n };\n }\n\n return {\n actionId: response.optionId,\n actionTitle: response.optionId,\n formData: {},\n };\n }\n\n const text = response.text?.trim();\n if (text) {\n if (display === \"text\") {\n return {\n actionId: EVE_INPUT_SUBMIT_ACTION_ID,\n actionTitle: text,\n formData: { answer: text },\n };\n }\n\n if (display === \"select\") {\n const option = request.options?.find((entry) => entry.id === text);\n if (option) {\n return {\n actionId: EVE_INPUT_SUBMIT_ACTION_ID,\n actionTitle: option.label,\n formData: { choice: option.id },\n };\n }\n return {\n actionId: EVE_INPUT_SUBMIT_ACTION_ID,\n actionTitle: text,\n formData: { choice: text },\n };\n }\n\n return {\n actionId: EVE_INPUT_SUBMIT_ACTION_ID,\n actionTitle: text,\n formData: { answer: text },\n };\n }\n\n return {\n actionId: EVE_INPUT_SUBMIT_ACTION_ID,\n actionTitle: \"Responded\",\n formData: {},\n };\n}\n\n/** Audit payload for `chat_action_input_submitted`. */\nexport function buildEveInputAuditSubmissionData(\n context: EveInputAuditContext,\n formData: Record<string, unknown>\n): Record<string, unknown> {\n return {\n toolCallId: context.toolCallId,\n ...(context.toolName ? { toolName: context.toolName } : {}),\n ...(context.requestId ? { requestId: context.requestId } : {}),\n ...(context.display ? { display: context.display } : {}),\n ...(context.toolInput !== undefined ? { toolInput: context.toolInput } : {}),\n ...formData,\n };\n}\n\n/**\n * Parse an `ask_question` tool result output into an Eve input response shape.\n */\nexport function parseEveAskQuestionToolOutput(\n output: unknown\n): Pick<EveInputResponse, \"optionId\" | \"text\"> | null {\n if (output == null || typeof output !== \"object\") {\n return null;\n }\n\n const record = output as Record<string, unknown>;\n const value =\n record.type === \"json\" && record.value != null && typeof record.value === \"object\"\n ? (record.value as Record<string, unknown>)\n : record;\n\n const optionId = typeof value.optionId === \"string\" ? value.optionId : undefined;\n const text = typeof value.text === \"string\" ? value.text : undefined;\n\n if (!optionId && !text) {\n return null;\n }\n\n return { ...(optionId ? { optionId } : {}), ...(text ? { text } : {}) };\n}\n","import {\n resolveEveInputDisplay,\n type EveInputRequest,\n} from \"./input-request.js\";\n\n/** Default per-tool labels for common Eve demo/integration tools. */\nexport const DEFAULT_TOOL_DISPLAY_LABELS: Readonly<Record<string, string>> = {\n refund_charge: \"Refund a customer charge\",\n deploy_release: \"Deploy a release\",\n get_weather: \"Get weather\",\n get_my_access: \"Check my access\",\n whoami: \"Who am I\",\n create_robotrock_task: \"Create a RobotRock task\",\n};\n\nlet toolDisplayLabelOverrides: Readonly<Record<string, string>> = {};\n\n/** Register additional or overriding tool display labels at runtime. */\nexport function setToolDisplayLabelOverrides(\n overrides: Readonly<Record<string, string>>\n): void {\n toolDisplayLabelOverrides = overrides;\n}\n\nfunction formatToolName(toolName: string): string {\n const spaced = toolName\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/[-_]+/g, \" \")\n .trim();\n\n if (!spaced) {\n return \"Tool\";\n }\n\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\n/** Resolve a user-facing label for a tool slug. */\nexport function getToolDisplayLabel(toolName: string): string {\n const trimmed = toolName.trim();\n if (!trimmed) {\n return \"Tool\";\n }\n\n return (\n toolDisplayLabelOverrides[trimmed] ??\n DEFAULT_TOOL_DISPLAY_LABELS[trimmed] ??\n formatToolName(trimmed)\n );\n}\n\n/** Format an Eve input request prompt for human-facing approval UIs. */\nexport function formatEveApprovalTitle(\n request: EveInputRequest,\n toolName?: string\n): string {\n const display = resolveEveInputDisplay(request, toolName);\n if (display !== \"confirmation\" || !toolName) {\n return request.prompt;\n }\n\n return `Approve: ${getToolDisplayLabel(toolName)}`;\n}\n","import type { RobotRockWebhookPayload } from \"../webhook.js\";\n\n/** Build the assistant resume prompt when an inbox task linked to a chat is handled. */\nexport function buildTaskHandledResumeMessage(\n payload: RobotRockWebhookPayload\n): string {\n const handledBy = payload.handledBy?.trim() || \"someone\";\n const actionTitle = payload.action.title.trim();\n return `RobotRock task ${payload.taskId} was handled: ${actionTitle} by ${handledBy}. Briefly tell the user what was decided and what happens next.`;\n}\n","export {\n EVE_INPUT_OTHER_CHOICE_ID,\n EVE_INPUT_OTHER_CHOICE_LABEL,\n EVE_INPUT_SUBMIT_ACTION_ID,\n eveInputRequestTaskType,\n eveInputRequestToActions,\n normalizeEveSelectFormData,\n resolveEveInputDisplay,\n taskHandledToEveInputResponse,\n type EveInputOption,\n type EveInputRequest,\n type EveInputRequestDisplay,\n type EveInputResponse,\n} from \"./input-request.js\";\nexport {\n buildEveInputAuditSubmissionData,\n eveInputResponseToActionSubmission,\n isEveApprovalInputRequest,\n parseEveAskQuestionToolOutput,\n resolveEveFreeformTextToInputResponse,\n type EveInputActionSubmission,\n type EveInputAuditContext,\n} from \"./input-audit.js\";\nexport {\n DEFAULT_TOOL_DISPLAY_LABELS,\n formatEveApprovalTitle,\n getToolDisplayLabel,\n setToolDisplayLabelOverrides,\n} from \"./tool-display.js\";\n/** Hook slug advertised in GET /eve/v1/info for RobotRock-ready auto-detection. */\nexport const ROBOTROCK_READY_HOOK_SLUG = \"robotrock-ready\";\n\nexport { buildTaskHandledResumeMessage } from \"./resume-message.js\";\n"],"mappings":"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","names":[]}
@@ -0,0 +1,6 @@
1
+ export { WHOAMI_TOOL_NAME, defineWhoamiTool, whoamiInputSchema, whoamiTool } from './whoami.js';
2
+ export { MY_ACCESS_TOOL_NAME, defineMyAccessTool, myAccessInputSchema, myAccessTool } from './my-access.js';
3
+ import 'eve/tools';
4
+ import '../../../tenant-5YKDrdC-.js';
5
+ import 'eve/context';
6
+ import 'zod';
@@ -0,0 +1,144 @@
1
+ // src/eve/tools/identity/whoami.ts
2
+ import { defineTool } from "eve/tools";
3
+ import { z } from "zod";
4
+
5
+ // src/eve/agent/attributes.ts
6
+ function readStringAttribute(attributes, key) {
7
+ const value = attributes?.[key];
8
+ if (typeof value === "string" && value.length > 0) {
9
+ return value;
10
+ }
11
+ if (Array.isArray(value) && typeof value[0] === "string" && value[0].length > 0) {
12
+ return value[0];
13
+ }
14
+ return void 0;
15
+ }
16
+ function readStringArrayAttribute(attributes, key) {
17
+ const value = attributes?.[key];
18
+ if (typeof value === "string" && value.length > 0) {
19
+ return [value];
20
+ }
21
+ if (Array.isArray(value)) {
22
+ return value.filter(
23
+ (entry) => typeof entry === "string" && entry.length > 0
24
+ );
25
+ }
26
+ return [];
27
+ }
28
+ function parseTenantRole(value) {
29
+ if (value === "admin" || value === "member") {
30
+ return value;
31
+ }
32
+ return null;
33
+ }
34
+
35
+ // src/eve/agent/tenant.ts
36
+ function tryResolveTenantCaller(ctx) {
37
+ const caller = ctx.session.auth.initiator ?? ctx.session.auth.current;
38
+ if (caller?.principalType !== "user") {
39
+ return null;
40
+ }
41
+ const email = readStringAttribute(caller.attributes, "email");
42
+ const name = readStringAttribute(caller.attributes, "name");
43
+ const tenantSlug = readStringAttribute(caller.attributes, "tenantSlug") ?? readStringAttribute(caller.attributes, "tenantId");
44
+ const role = parseTenantRole(readStringAttribute(caller.attributes, "role"));
45
+ if (!email || !tenantSlug || !caller.principalId || !role) {
46
+ return null;
47
+ }
48
+ const workosUserId = readStringAttribute(caller.attributes, "workosUserId");
49
+ const connectionId = readStringAttribute(caller.attributes, "connectionId");
50
+ const groups = readStringArrayAttribute(caller.attributes, "groups");
51
+ return {
52
+ userId: caller.principalId,
53
+ email,
54
+ name: name ?? email.split("@")[0] ?? email,
55
+ tenantSlug,
56
+ ...connectionId ? { connectionId } : {},
57
+ role,
58
+ isAdmin: role === "admin",
59
+ groups,
60
+ ...workosUserId ? { workosUserId } : {}
61
+ };
62
+ }
63
+
64
+ // src/eve/tools/identity/whoami.ts
65
+ var WHOAMI_TOOL_NAME = "whoami";
66
+ var whoamiInputSchema = z.object({});
67
+ function defineWhoamiTool() {
68
+ return defineTool({
69
+ description: "Return the authenticated RobotRock user, tenant, role, and group memberships for the current chat session.",
70
+ inputSchema: whoamiInputSchema,
71
+ async execute(_input, ctx) {
72
+ const caller = tryResolveTenantCaller(ctx);
73
+ if (!caller) {
74
+ return {
75
+ authenticated: false,
76
+ message: "No RobotRock user is attached to this session. Dashboard chat supplies user context via the Eve proxy."
77
+ };
78
+ }
79
+ return {
80
+ authenticated: true,
81
+ userId: caller.userId,
82
+ name: caller.name,
83
+ email: caller.email,
84
+ tenantSlug: caller.tenantSlug,
85
+ role: caller.role,
86
+ isAdmin: caller.isAdmin,
87
+ groups: caller.groups.map((slug) => ({ slug })),
88
+ ...caller.workosUserId ? { workosUserId: caller.workosUserId } : {},
89
+ sessionId: ctx.session.id
90
+ };
91
+ }
92
+ });
93
+ }
94
+ var whoamiTool = defineWhoamiTool();
95
+
96
+ // src/eve/tools/identity/my-access.ts
97
+ import { defineTool as defineTool2 } from "eve/tools";
98
+ import { z as z2 } from "zod";
99
+ var MY_ACCESS_TOOL_NAME = "get_my_access";
100
+ var myAccessInputSchema = z2.object({});
101
+ function tenantCapabilities(isAdmin) {
102
+ return {
103
+ manageSettings: isAdmin,
104
+ manageBilling: isAdmin,
105
+ manageTeam: isAdmin,
106
+ manageIntegrations: isAdmin
107
+ };
108
+ }
109
+ function defineMyAccessTool() {
110
+ return defineTool2({
111
+ description: "Check the authenticated user's tenant role, group memberships, and admin capabilities in RobotRock.",
112
+ inputSchema: myAccessInputSchema,
113
+ async execute(_input, ctx) {
114
+ const caller = tryResolveTenantCaller(ctx);
115
+ if (!caller) {
116
+ return {
117
+ authenticated: false,
118
+ message: "No RobotRock user is attached to this session. Dashboard chat supplies user context via the Eve proxy."
119
+ };
120
+ }
121
+ return {
122
+ authenticated: true,
123
+ tenantRole: caller.role,
124
+ isTenantAdmin: caller.isAdmin,
125
+ groupSlugs: caller.groups,
126
+ capabilities: tenantCapabilities(caller.isAdmin),
127
+ email: caller.email,
128
+ tenantSlug: caller.tenantSlug
129
+ };
130
+ }
131
+ });
132
+ }
133
+ var myAccessTool = defineMyAccessTool();
134
+ export {
135
+ MY_ACCESS_TOOL_NAME,
136
+ WHOAMI_TOOL_NAME,
137
+ defineMyAccessTool,
138
+ defineWhoamiTool,
139
+ myAccessInputSchema,
140
+ myAccessTool,
141
+ whoamiInputSchema,
142
+ whoamiTool
143
+ };
144
+ //# sourceMappingURL=index.js.map