robotrock 1.3.4 → 1.5.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 (80) hide show
  1. package/README.md +11 -1
  2. package/dist/agent-admin.d.ts +5 -0
  3. package/dist/agent-admin.js +75 -2
  4. package/dist/agent-admin.js.map +1 -1
  5. package/dist/ai/index.d.ts +5 -5
  6. package/dist/ai/index.js +120 -4
  7. package/dist/ai/index.js.map +1 -1
  8. package/dist/ai/trigger.d.ts +3 -3
  9. package/dist/ai/trigger.js +120 -4
  10. package/dist/ai/trigger.js.map +1 -1
  11. package/dist/ai/workflow.d.ts +3 -3
  12. package/dist/ai/workflow.js +120 -4
  13. package/dist/ai/workflow.js.map +1 -1
  14. package/dist/{client-CZ5eWH5v.d.ts → client-BxbxttFH.d.ts} +19 -1
  15. package/dist/eve/agent/index.d.ts +4 -4
  16. package/dist/eve/agent/index.js +577 -261
  17. package/dist/eve/agent/index.js.map +1 -1
  18. package/dist/eve/index.d.ts +4 -4
  19. package/dist/eve/index.js +507 -7
  20. package/dist/eve/index.js.map +1 -1
  21. package/dist/eve/tools/admin/assign-tasks.d.ts +40 -19
  22. package/dist/eve/tools/admin/assign-tasks.js +334 -25
  23. package/dist/eve/tools/admin/assign-tasks.js.map +1 -1
  24. package/dist/eve/tools/admin/get-workspace-usage.d.ts +71 -0
  25. package/dist/eve/tools/admin/get-workspace-usage.js +1365 -0
  26. package/dist/eve/tools/admin/get-workspace-usage.js.map +1 -0
  27. package/dist/eve/tools/admin/manage-groups.d.ts +122 -7
  28. package/dist/eve/tools/admin/manage-groups.js +350 -31
  29. package/dist/eve/tools/admin/manage-groups.js.map +1 -1
  30. package/dist/eve/tools/admin/manage-team-members.d.ts +86 -7
  31. package/dist/eve/tools/admin/manage-team-members.js +318 -16
  32. package/dist/eve/tools/admin/manage-team-members.js.map +1 -1
  33. package/dist/eve/tools/admin/query-tasks.d.ts +82 -7
  34. package/dist/eve/tools/admin/query-tasks.js +363 -40
  35. package/dist/eve/tools/admin/query-tasks.js.map +1 -1
  36. package/dist/eve/tools/catalog/generate-image.d.ts +64 -0
  37. package/dist/eve/tools/catalog/generate-image.js +2077 -0
  38. package/dist/eve/tools/catalog/generate-image.js.map +1 -0
  39. package/dist/eve/tools/catalog/generate-random-chart.d.ts +77 -0
  40. package/dist/eve/tools/catalog/generate-random-chart.js +411 -0
  41. package/dist/eve/tools/catalog/generate-random-chart.js.map +1 -0
  42. package/dist/eve/tools/catalog/search-products.d.ts +36 -43
  43. package/dist/eve/tools/catalog/search-products.js +253 -6
  44. package/dist/eve/tools/catalog/search-products.js.map +1 -1
  45. package/dist/eve/tools/identity/index.d.ts +2 -1
  46. package/dist/eve/tools/identity/index.js +26 -6
  47. package/dist/eve/tools/identity/index.js.map +1 -1
  48. package/dist/eve/tools/identity/my-access.d.ts +88 -3
  49. package/dist/eve/tools/identity/my-access.js +26 -6
  50. package/dist/eve/tools/identity/my-access.js.map +1 -1
  51. package/dist/eve/tools/identity/whoami.d.ts +1 -1
  52. package/dist/eve/tools/identity/whoami.js.map +1 -1
  53. package/dist/eve/tools/inbox/create-task.d.ts +1 -1
  54. package/dist/eve/tools/inbox/create-task.js +119 -2
  55. package/dist/eve/tools/inbox/create-task.js.map +1 -1
  56. package/dist/eve/tools/inbox/index.d.ts +1 -1
  57. package/dist/eve/tools/inbox/index.js +119 -2
  58. package/dist/eve/tools/inbox/index.js.map +1 -1
  59. package/dist/eve/tools/index.d.ts +5 -2
  60. package/dist/eve/tools/index.js +964 -115
  61. package/dist/eve/tools/index.js.map +1 -1
  62. package/dist/index-amkHKVGs.d.ts +1054 -0
  63. package/dist/index.d.ts +5 -5
  64. package/dist/index.js +328 -13
  65. package/dist/index.js.map +1 -1
  66. package/dist/schemas/index.js +67 -1
  67. package/dist/schemas/index.js.map +1 -1
  68. package/dist/{tool-approval-bridge-DnGaRES4.d.ts → tool-approval-bridge-Cz7qQUpw.d.ts} +1 -1
  69. package/dist/{tool-reply-guidance-C3qrT1In.d.ts → tool-reply-guidance-CJko9liH.d.ts} +5 -2
  70. package/dist/tool-result-ui-meta-KT0VafEO.d.ts +52 -0
  71. package/dist/trigger/index.d.ts +1 -1
  72. package/dist/trigger/index.js +118 -2
  73. package/dist/trigger/index.js.map +1 -1
  74. package/dist/{trigger--qTIK0s6.d.ts → trigger-C1ooSegc.d.ts} +2 -2
  75. package/dist/workflow/index.d.ts +1 -1
  76. package/dist/workflow/index.js +118 -2
  77. package/dist/workflow/index.js.map +1 -1
  78. package/package.json +21 -4
  79. package/dist/index-Blq0XoAr.d.ts +0 -204
  80. package/dist/tool-ui-hint-CMpug5sC.d.ts +0 -13
@@ -449,6 +449,40 @@ var agentChatLinkTaskBodySchema = z.object({
449
449
  publicTaskId: z.string().min(1),
450
450
  toolCallId: z.string().min(1)
451
451
  });
452
+ var AGENT_FILE_TAGS_MAX = 20;
453
+ var AGENT_FILE_TAG_MAX_LENGTH = 64;
454
+ function normalizeAgentFileTags(tags) {
455
+ if (!tags?.length) return void 0;
456
+ const seen = /* @__PURE__ */ new Set();
457
+ const out = [];
458
+ for (const raw of tags) {
459
+ const tag = raw.trim().toLowerCase().slice(0, AGENT_FILE_TAG_MAX_LENGTH);
460
+ if (!tag || seen.has(tag)) continue;
461
+ seen.add(tag);
462
+ out.push(tag);
463
+ if (out.length >= AGENT_FILE_TAGS_MAX) break;
464
+ }
465
+ return out.length > 0 ? out : void 0;
466
+ }
467
+ var agentChatUploadImageBodySchema = z.object({
468
+ mediaType: z.string().min(1),
469
+ /** Raw base64 (no data: URL prefix). */
470
+ base64: z.string().min(1),
471
+ chatId: z.string().min(1).optional(),
472
+ publicTaskId: z.string().min(1).optional(),
473
+ source: z.string().min(1).optional(),
474
+ /** Display / search name (e.g. `sunset-robot.png`). */
475
+ filename: z.string().min(1).max(255).optional(),
476
+ /** Human-readable description (e.g. generation prompt). */
477
+ description: z.string().min(1).max(2e3).optional(),
478
+ /**
479
+ * Optional labels for later grouping/filtering.
480
+ * Normalized to lowercase trimmed unique strings (max 20, 64 chars each).
481
+ */
482
+ tags: z.array(z.string().min(1).max(AGENT_FILE_TAG_MAX_LENGTH)).max(AGENT_FILE_TAGS_MAX).optional().transform((tags) => normalizeAgentFileTags(tags))
483
+ }).refine((data) => Boolean(data.chatId || data.publicTaskId), {
484
+ message: "Provide chatId and/or publicTaskId"
485
+ });
452
486
 
453
487
  // ../core/src/schemas/tool-result-display.ts
454
488
  import { z as z2 } from "zod";
@@ -477,7 +511,8 @@ var tenantRoleSchema = z3.enum(["admin", "member"]);
477
511
  var agentAdminUserSchema = z3.object({
478
512
  id: z3.string(),
479
513
  email: z3.string().email(),
480
- name: z3.string()
514
+ name: z3.string(),
515
+ profilePictureUrl: z3.string().nullable().optional()
481
516
  });
482
517
  var agentAdminMemberSchema = z3.object({
483
518
  userId: z3.string(),
@@ -562,6 +597,37 @@ var assignTasksBodySchema = z3.object({
562
597
  { message: "assignTo needs at least one user email or group slug." }
563
598
  )
564
599
  });
600
+ var agentAdminPlanLimitsSchema = z3.object({
601
+ tasksPerDay: z3.number(),
602
+ members: z3.number(),
603
+ apiKeys: z3.number(),
604
+ groups: z3.number(),
605
+ auditLogRetention: z3.number(),
606
+ rateLimitPerSecond: z3.number(),
607
+ taskRetentionDays: z3.number()
608
+ });
609
+ var agentAdminUsageSchema = z3.object({
610
+ workspace: z3.string(),
611
+ planName: z3.string(),
612
+ planType: z3.string(),
613
+ trialState: z3.enum(["none", "active", "expired"]),
614
+ daysRemaining: z3.number().nullable(),
615
+ isPaidPro: z3.boolean(),
616
+ subscriptionStatus: z3.string().nullable(),
617
+ tasksToday: z3.number(),
618
+ maxTasksPerDay: z3.number().nullable(),
619
+ tasksResetAt: z3.number(),
620
+ openTasks: z3.number(),
621
+ totalTasks: z3.number(),
622
+ seatsCurrent: z3.number(),
623
+ seatsMax: z3.number().nullable(),
624
+ groupsCurrent: z3.number(),
625
+ groupsMax: z3.number().nullable(),
626
+ apiKeysCurrent: z3.number(),
627
+ apiKeysMax: z3.number().nullable(),
628
+ rateLimitPerSecond: z3.number(),
629
+ limits: agentAdminPlanLimitsSchema
630
+ });
565
631
 
566
632
  // src/schemas/index.ts
567
633
  var handlerUrlSchema2 = z4.string().refine((url) => isAllowedHandlerUrl(url), {
@@ -865,7 +931,11 @@ function resolveRobotRockAuthConfig(overrides) {
865
931
  "RobotRock auth is required. Set ROBOTROCK_API_KEY, ROBOTROCK_AGENT_SERVICE_TOKEN with tenant context, or pass auth when creating the client."
866
932
  );
867
933
  }
868
- return { kind: "apiKey", apiKey };
934
+ return {
935
+ kind: "apiKey",
936
+ apiKey,
937
+ ...overrides?.actingUserId?.trim() ? { actingUserId: overrides.actingUserId.trim() } : {}
938
+ };
869
939
  }
870
940
 
871
941
  // src/chat-correlation.ts
@@ -1070,6 +1140,51 @@ function createChatsApi(config) {
1070
1140
  data
1071
1141
  );
1072
1142
  }
1143
+ },
1144
+ async uploadImage(input) {
1145
+ const validation = agentChatUploadImageBodySchema.safeParse(input);
1146
+ if (!validation.success) {
1147
+ throw new RobotRockError(
1148
+ `Invalid image upload: ${validation.error.issues[0]?.message}`,
1149
+ 400,
1150
+ validation.error.issues
1151
+ );
1152
+ }
1153
+ const response = await fetch(`${config.baseUrl}/agent-chats/images`, {
1154
+ method: "POST",
1155
+ headers: headers(),
1156
+ body: JSON.stringify(validation.data)
1157
+ });
1158
+ const data = await parseResponseBody(response);
1159
+ if (!response.ok) {
1160
+ throw new RobotRockError(
1161
+ getErrorMessage(data, "Failed to upload chat image"),
1162
+ response.status,
1163
+ data
1164
+ );
1165
+ }
1166
+ const uploaded = data;
1167
+ if (typeof uploaded.storageId !== "string" || typeof uploaded.url !== "string" || typeof uploaded.mediaType !== "string") {
1168
+ throw new RobotRockError(
1169
+ "Image upload returned an invalid response",
1170
+ 500,
1171
+ data
1172
+ );
1173
+ }
1174
+ return {
1175
+ storageId: uploaded.storageId,
1176
+ url: uploaded.url,
1177
+ mediaType: uploaded.mediaType,
1178
+ ...typeof uploaded.chatId === "string" ? { chatId: uploaded.chatId } : {},
1179
+ ...typeof uploaded.publicTaskId === "string" ? { publicTaskId: uploaded.publicTaskId } : {},
1180
+ ...typeof uploaded.filename === "string" ? { filename: uploaded.filename } : {},
1181
+ ...typeof uploaded.description === "string" ? { description: uploaded.description } : {},
1182
+ ...Array.isArray(uploaded.tags) ? {
1183
+ tags: uploaded.tags.filter(
1184
+ (tag) => typeof tag === "string"
1185
+ )
1186
+ } : {}
1187
+ };
1073
1188
  }
1074
1189
  };
1075
1190
  }
@@ -1139,6 +1254,7 @@ var RobotRock = class {
1139
1254
  }
1140
1255
  this.auth = resolveRobotRockAuthConfig({
1141
1256
  ...apiKey ? { apiKey } : {},
1257
+ ...config.actingUserId ? { actingUserId: config.actingUserId } : {},
1142
1258
  ...agentService ? { agentService } : {}
1143
1259
  });
1144
1260
  this.chatCorrelation = config.chatCorrelation;
@@ -1543,6 +1659,7 @@ function tryCreateBoundRobotRockClient(ctx) {
1543
1659
  if (apiKey) {
1544
1660
  return createClient({
1545
1661
  apiKey,
1662
+ ...caller?.userId ? { actingUserId: caller.userId } : {},
1546
1663
  baseUrl: process.env.ROBOTROCK_BASE_URL?.trim(),
1547
1664
  chatCorrelation
1548
1665
  });
@@ -1719,12 +1836,29 @@ function withUiHint(result, hint) {
1719
1836
  };
1720
1837
  }
1721
1838
 
1839
+ // src/eve/tool-result-ui-meta.ts
1840
+ var TOOL_UI_FIELD = "ui";
1841
+ var TOOL_RESULT_UI_ENTITY_ID_RE = /^[a-z][a-z0-9_]{0,63}$/;
1842
+ function withToolUi(result, ui) {
1843
+ const existing = typeof result[TOOL_UI_FIELD] === "object" && result[TOOL_UI_FIELD] !== null && !Array.isArray(result[TOOL_UI_FIELD]) ? result[TOOL_UI_FIELD] : {};
1844
+ return {
1845
+ ...result,
1846
+ [TOOL_UI_FIELD]: {
1847
+ ...existing,
1848
+ ...ui
1849
+ }
1850
+ };
1851
+ }
1852
+
1722
1853
  // src/eve/tool-reply-guidance.ts
1723
1854
  var TOOL_REPLY_GUIDANCE_FIELD = "replyGuidance";
1724
1855
  var WHOAMI_REPLY_GUIDANCE = "The dashboard shows a profile card with name, email, workspace, role, and groups. Do not restate those in your reply. Only add context not in the card (e.g. permissions, refund approval rules, missing group membership).";
1725
- var MY_ACCESS_REPLY_GUIDANCE = "Access details may render in chat UI. Do not restate role, groups, or admin capabilities if already visible. Only explain what the user can or cannot do for their question (e.g. finance group required for refunds \u2265 $10,000). When access.tenantAdmin is false and the user needs manageTeam, manageGroups, or query-tasks capabilities, explain briefly then call ask_question to offer sending an admin request to tenant admins \u2014 do not tell them to find an admin manually without offering delegation first.";
1856
+ var MY_ACCESS_REPLY_GUIDANCE = "Access details may render in chat UI. Do not restate role, groups, or admin capabilities if already visible. Only explain what the user can or cannot do for their question (e.g. finance group required for refunds \u2265 $10,000). When access.tenantAdmin is false and the user needs manageTeam, manageGroups, query-tasks, or workspace-usage capabilities, explain briefly then call ask_question to offer sending an admin request to tenant admins \u2014 do not tell them to find an admin manually without offering delegation first.";
1857
+ var GET_WORKSPACE_USAGE_REPLY_GUIDANCE = "Workspace plan and usage render as a card in chat. Do not restate plan name, task counts, seats, groups, API keys, or rate limits from the card. Only add context not shown (e.g. upgrade options, that LLM token/cost meters are not tracked, or next steps). Never invent token or dollar spend numbers.";
1726
1858
  var CREATE_INBOX_TASK_REPLY_GUIDANCE = "A task card shows title, assignee, and inbox status in chat. Do not restate task ID, assignee, or delegation details from the card. Only mention next steps or answer the user's question.";
1727
1859
  var SEARCH_PRODUCTS_REPLY_GUIDANCE = "Product results render as a list card in chat. Do not restate product names, prices, or SKUs. Only add context not in the list (e.g. no matches, recommendations).";
1860
+ var GENERATE_RANDOM_CHART_REPLY_GUIDANCE = "Chart metrics render as a chart card in chat. Do not restate series values, dates, or categories from the chart. Only add brief context (e.g. that this is demo data).";
1861
+ var GENERATE_IMAGE_REPLY_GUIDANCE = "The generated image renders in chat UI. Do not describe the image pixels or restate the prompt. Only add a short acknowledgement or next-step question if useful.";
1728
1862
  var MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE = "Team members render as a list card in chat. Do not restate names, emails, or roles from the list. Only add context not shown (e.g. duplicates, next admin actions).";
1729
1863
  var MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE = "Team member details render in chat UI. Do not restate name, email, or role from the card. Only add next steps or policy context.";
1730
1864
  var MANAGE_GROUPS_LIST_REPLY_GUIDANCE = "Groups render as a list card in chat. Do not restate group names, slugs, or descriptions from the list. Use slug (not internal id) for get, update, delete, and membership actions. Only add context not shown.";
@@ -1835,15 +1969,31 @@ import { z as z7 } from "zod";
1835
1969
 
1836
1970
  // src/eve/tool-display-format.ts
1837
1971
  function formatToolObjectResult(data, options) {
1838
- const withGuidance = withReplyGuidance(data, options.replyGuidance);
1972
+ let result = withReplyGuidance(
1973
+ data,
1974
+ options.replyGuidance
1975
+ );
1976
+ if (options.ui) {
1977
+ result = withToolUi(result, options.ui);
1978
+ }
1839
1979
  if (options.uiHint) {
1840
- return withUiHint(withGuidance, options.uiHint);
1980
+ result = withUiHint(result, options.uiHint);
1841
1981
  }
1842
- return withGuidance;
1982
+ return result;
1843
1983
  }
1844
1984
  function formatToolListResult(listKey, items, options) {
1985
+ const ui = {
1986
+ ...options.ui,
1987
+ layout: "list",
1988
+ rowsPath: listKey,
1989
+ ...options.entity ? { entity: options.entity } : {},
1990
+ ...options.present !== void 0 ? { present: options.present } : {}
1991
+ };
1845
1992
  return withUiHint(
1846
- withReplyGuidance({ [listKey]: items }, options.replyGuidance),
1993
+ withToolUi(
1994
+ withReplyGuidance({ [listKey]: items }, options.replyGuidance),
1995
+ ui
1996
+ ),
1847
1997
  "list"
1848
1998
  );
1849
1999
  }
@@ -1865,7 +2015,8 @@ function formatMyAccessResult(input) {
1865
2015
  }
1866
2016
  },
1867
2017
  {
1868
- replyGuidance: MY_ACCESS_REPLY_GUIDANCE
2018
+ replyGuidance: MY_ACCESS_REPLY_GUIDANCE,
2019
+ ui: { entity: "access" }
1869
2020
  }
1870
2021
  );
1871
2022
  }
@@ -1883,7 +2034,7 @@ function tenantCapabilities(isAdmin) {
1883
2034
  }
1884
2035
  function defineMyAccessTool() {
1885
2036
  return defineTool2({
1886
- description: "Check the authenticated user's tenant role, group memberships, and admin capabilities in RobotRock. Always call this before tenant-admin tools (manage_team_members, manage_groups, query_tasks) in the same turn \u2014 including read-only requests like listing users. Results render as a visible access tool card in chat like other tools; do not restate role, groups, or capabilities in your reply.",
2037
+ description: "Check the authenticated user's tenant role, group memberships, and admin capabilities in RobotRock. Always call this before tenant-admin tools (manage_team_members, manage_groups, query_tasks, get_workspace_usage) in the same turn \u2014 including read-only requests like listing users or usage. Results render as a visible access tool card in chat like other tools; do not restate role, groups, or capabilities in your reply.",
1887
2038
  inputSchema: myAccessInputSchema,
1888
2039
  async execute(_input, ctx) {
1889
2040
  const caller = tryResolveTenantCaller(ctx);
@@ -1951,10 +2102,219 @@ var whoamiTool = defineWhoamiTool();
1951
2102
 
1952
2103
  // src/eve/tools/catalog/search-products.ts
1953
2104
  import { defineTool as defineTool4 } from "eve/tools";
2105
+ import { z as z10 } from "zod";
2106
+
2107
+ // src/eve/entity-schemas.ts
1954
2108
  import { z as z9 } from "zod";
2109
+ function buildTenantTaskUrl(tenantSlug, task) {
2110
+ const q = new URLSearchParams();
2111
+ if (task.app && task.app !== "default") {
2112
+ q.set("app", task.app);
2113
+ }
2114
+ if (task.type?.trim()) {
2115
+ q.set("type", task.type.trim());
2116
+ }
2117
+ q.set("selected", task.id);
2118
+ return `/${tenantSlug}/inbox?${q.toString()}`;
2119
+ }
2120
+ function buildTenantGroupUrl(tenantSlug, slug) {
2121
+ return `/${tenantSlug}/team/groups/${slug}`;
2122
+ }
2123
+ var toolResultUiMetaSchema = z9.object({
2124
+ present: z9.boolean().optional(),
2125
+ entity: z9.string().regex(TOOL_RESULT_UI_ENTITY_ID_RE).optional(),
2126
+ rowsPath: z9.string().min(1).optional(),
2127
+ layout: z9.enum(["list", "chart", "table"]).optional()
2128
+ }).strict();
2129
+ var agentOnlyFields = {
2130
+ replyGuidance: z9.string().optional(),
2131
+ ui: toolResultUiMetaSchema.optional(),
2132
+ uiHint: z9.enum(["list", "chart", "table"]).optional()
2133
+ };
2134
+ function withAgentOnlyFields(shape) {
2135
+ return z9.object({
2136
+ ...shape,
2137
+ ...agentOnlyFields
2138
+ });
2139
+ }
2140
+ var productEntityRowSchema = z9.object({
2141
+ id: z9.string().min(1),
2142
+ name: z9.string().min(1),
2143
+ price: z9.number(),
2144
+ currency: z9.string().min(1),
2145
+ inStock: z9.boolean(),
2146
+ url: z9.string().min(1)
2147
+ });
2148
+ var metricPointEntityRowSchema = z9.object({
2149
+ date: z9.string().optional().describe("X-axis value when xKey is date/time"),
2150
+ category: z9.string().optional().describe("X-axis value when xKey is category"),
2151
+ label: z9.string().optional().describe("X-axis value when xKey is label")
2152
+ }).catchall(z9.union([z9.string(), z9.number()])).describe(
2153
+ "Wide chart point: x-axis field + numeric columns named by yKeys (one series per column)"
2154
+ );
2155
+ var toolChartResultSchema = withAgentOnlyFields({
2156
+ title: z9.string().min(1).optional().describe("Chart title shown above the plot"),
2157
+ description: z9.string().min(1).optional().describe("Optional short subtitle"),
2158
+ type: z9.enum(["line", "bar", "area"]).describe("TRL/shadcn chart variant (time series \u2192 line, categories \u2192 bar)"),
2159
+ xKey: z9.string().min(1).describe('Field on each series row for the x-axis, e.g. "date" or "category"'),
2160
+ yKeys: z9.array(z9.string().min(1)).min(1).describe(
2161
+ 'Numeric series column names on each row, e.g. ["NL","BE"] or ["created","handled"]'
2162
+ ),
2163
+ series: z9.array(metricPointEntityRowSchema).describe(
2164
+ "Wide-format points only \u2014 one object per x value with yKeys as numeric fields"
2165
+ )
2166
+ });
2167
+ var memberEntityRowSchema = z9.object({
2168
+ name: z9.string(),
2169
+ email: z9.string(),
2170
+ role: z9.string(),
2171
+ membershipKind: z9.string(),
2172
+ profilePictureUrl: z9.string().nullable()
2173
+ });
2174
+ var taskEntityRowSchema = z9.object({
2175
+ id: z9.string().min(1),
2176
+ name: z9.string().min(1),
2177
+ status: z9.string().min(1),
2178
+ type: z9.string().nullable(),
2179
+ description: z9.string().nullable(),
2180
+ validUntil: z9.number(),
2181
+ createdAt: z9.number(),
2182
+ url: z9.string().min(1),
2183
+ threadPriority: z9.string().nullable().optional()
2184
+ });
2185
+ var groupEntityRowSchema = z9.object({
2186
+ name: z9.string().min(1),
2187
+ slug: z9.string().min(1),
2188
+ description: z9.string().nullable(),
2189
+ memberCount: z9.number().nullable(),
2190
+ url: z9.string().min(1)
2191
+ });
2192
+ var groupDetailEntitySchema = z9.object({
2193
+ name: z9.string().min(1),
2194
+ slug: z9.string().min(1),
2195
+ description: z9.string().nullable(),
2196
+ url: z9.string().min(1),
2197
+ members: z9.array(
2198
+ z9.object({
2199
+ name: z9.string(),
2200
+ email: z9.string(),
2201
+ profilePictureUrl: z9.string().nullable()
2202
+ })
2203
+ )
2204
+ });
2205
+ var statusEntityRowSchema = z9.object({
2206
+ id: z9.string().min(1),
2207
+ name: z9.string().min(1),
2208
+ status: z9.string().min(1),
2209
+ url: z9.string().min(1),
2210
+ type: z9.string().nullable().optional(),
2211
+ description: z9.string().nullable().optional()
2212
+ });
2213
+ var agentAdminErrorResultSchema = z9.object({
2214
+ ok: z9.literal(false),
2215
+ status: z9.number().optional(),
2216
+ message: z9.string(),
2217
+ response: z9.unknown().optional()
2218
+ });
2219
+ var agentAdminMutationResultSchema = z9.object({
2220
+ ...agentOnlyFields
2221
+ }).passthrough();
2222
+ var searchProductsOutputSchema = withAgentOnlyFields({
2223
+ items: z9.array(productEntityRowSchema)
2224
+ });
2225
+ var generateRandomChartOutputSchema = toolChartResultSchema.extend({
2226
+ title: z9.string().min(1)
2227
+ });
2228
+ var generateImageOutputSchema = withAgentOnlyFields({
2229
+ prompt: z9.string().min(1),
2230
+ mediaType: z9.string().min(1),
2231
+ model: z9.string().min(1),
2232
+ storageId: z9.string().min(1),
2233
+ url: z9.string().min(1),
2234
+ /** @deprecated Legacy sessions only — prefer storageId/url. */
2235
+ base64: z9.string().min(1).optional()
2236
+ });
2237
+ var manageTeamMembersListOutputSchema = withAgentOnlyFields({
2238
+ members: z9.array(memberEntityRowSchema)
2239
+ });
2240
+ var manageTeamMembersDetailOutputSchema = withAgentOnlyFields(
2241
+ memberEntityRowSchema.shape
2242
+ );
2243
+ var manageTeamMembersOutputSchema = z9.union([
2244
+ manageTeamMembersListOutputSchema,
2245
+ manageTeamMembersDetailOutputSchema,
2246
+ agentAdminMutationResultSchema,
2247
+ agentAdminErrorResultSchema
2248
+ ]);
2249
+ var manageGroupsListOutputSchema = withAgentOnlyFields({
2250
+ groups: z9.array(groupEntityRowSchema)
2251
+ });
2252
+ var manageGroupsDetailOutputSchema = withAgentOnlyFields(
2253
+ groupDetailEntitySchema.shape
2254
+ );
2255
+ var manageGroupsSummaryOutputSchema = withAgentOnlyFields(
2256
+ groupEntityRowSchema.shape
2257
+ );
2258
+ var manageGroupsOutputSchema = z9.union([
2259
+ manageGroupsListOutputSchema,
2260
+ manageGroupsDetailOutputSchema,
2261
+ manageGroupsSummaryOutputSchema,
2262
+ agentAdminMutationResultSchema,
2263
+ agentAdminErrorResultSchema
2264
+ ]);
2265
+ var queryTasksListOutputSchema = withAgentOnlyFields({
2266
+ items: z9.array(taskEntityRowSchema),
2267
+ nextCursor: z9.string().nullable().optional()
2268
+ });
2269
+ var queryTasksDetailOutputSchema = withAgentOnlyFields({
2270
+ id: z9.string().nullable(),
2271
+ status: z9.string().nullable(),
2272
+ type: z9.string().nullable(),
2273
+ name: z9.string().nullable(),
2274
+ description: z9.string().nullable(),
2275
+ validUntil: z9.number().nullable(),
2276
+ createdAt: z9.number().nullable(),
2277
+ url: z9.string().min(1).nullable()
2278
+ });
2279
+ var queryTasksOutputSchema = z9.union([
2280
+ queryTasksListOutputSchema,
2281
+ queryTasksDetailOutputSchema,
2282
+ agentAdminErrorResultSchema
2283
+ ]);
2284
+ var assignTasksOutputSchema = z9.union([
2285
+ withAgentOnlyFields({
2286
+ results: z9.array(statusEntityRowSchema)
2287
+ }),
2288
+ agentAdminErrorResultSchema
2289
+ ]);
2290
+ var workspaceUsageEntitySchema = z9.object({
2291
+ workspace: z9.string(),
2292
+ plan: z9.string(),
2293
+ planType: z9.string(),
2294
+ trialState: z9.string(),
2295
+ daysRemaining: z9.number().nullable(),
2296
+ isPaidPro: z9.boolean(),
2297
+ subscriptionStatus: z9.string(),
2298
+ tasksToday: z9.string(),
2299
+ tasksResetAt: z9.string(),
2300
+ openTasks: z9.number(),
2301
+ totalTasks: z9.number(),
2302
+ seats: z9.string(),
2303
+ groups: z9.string(),
2304
+ apiKeys: z9.string(),
2305
+ rateLimitPerSecond: z9.number()
2306
+ });
2307
+ var getWorkspaceUsageOutputSchema = z9.union([
2308
+ withAgentOnlyFields({
2309
+ usage: workspaceUsageEntitySchema
2310
+ }),
2311
+ agentAdminErrorResultSchema
2312
+ ]);
2313
+
2314
+ // src/eve/tools/catalog/search-products.ts
1955
2315
  var SEARCH_PRODUCTS_TOOL_NAME = "search_products";
1956
- var searchProductsInputSchema = z9.object({
1957
- query: z9.string().min(1).describe("Product name or SKU to search for.")
2316
+ var searchProductsInputSchema = z10.object({
2317
+ query: z10.string().min(1).describe("Product name or SKU to search for.")
1958
2318
  });
1959
2319
  var DEMO_PRODUCTS = [
1960
2320
  {
@@ -1962,38 +2322,392 @@ var DEMO_PRODUCTS = [
1962
2322
  name: "Wireless Keyboard",
1963
2323
  price: 79.99,
1964
2324
  currency: "USD",
1965
- inStock: true
2325
+ inStock: true,
2326
+ url: "https://shop.example.com/products/sku-1001"
1966
2327
  },
1967
2328
  {
1968
2329
  id: "sku-2042",
1969
2330
  name: "USB-C Hub",
1970
2331
  price: 45.99,
1971
2332
  currency: "USD",
1972
- inStock: true
2333
+ inStock: true,
2334
+ url: "https://shop.example.com/products/sku-2042"
1973
2335
  },
1974
2336
  {
1975
2337
  id: "sku-3308",
1976
2338
  name: "Monitor Stand",
1977
2339
  price: 129.99,
1978
2340
  currency: "USD",
1979
- inStock: false
2341
+ inStock: false,
2342
+ url: "https://shop.example.com/products/sku-3308"
1980
2343
  }
1981
2344
  ];
1982
2345
  function defineSearchProductsTool() {
1983
2346
  return defineTool4({
1984
2347
  description: "Search the product catalog and return matching items. Results render in chat UI \u2014 do not restate product names, prices, or SKUs in your reply.",
1985
2348
  inputSchema: searchProductsInputSchema,
2349
+ outputSchema: searchProductsOutputSchema,
1986
2350
  async execute({ query }) {
1987
2351
  const normalized = query.trim().toLowerCase();
1988
2352
  const items = DEMO_PRODUCTS.filter(
1989
2353
  (product) => product.name.toLowerCase().includes(normalized) || product.id.toLowerCase().includes(normalized)
1990
2354
  );
1991
- return withReplyGuidance({ items: [...items] }, SEARCH_PRODUCTS_REPLY_GUIDANCE);
2355
+ return formatToolListResult(
2356
+ "items",
2357
+ items.map((product) => ({ ...product })),
2358
+ {
2359
+ replyGuidance: SEARCH_PRODUCTS_REPLY_GUIDANCE,
2360
+ entity: "product"
2361
+ }
2362
+ );
1992
2363
  }
1993
2364
  });
1994
2365
  }
1995
2366
  var searchProductsTool = defineSearchProductsTool();
1996
2367
 
2368
+ // src/eve/tools/catalog/generate-random-chart.ts
2369
+ import { defineTool as defineTool5 } from "eve/tools";
2370
+ import { z as z11 } from "zod";
2371
+
2372
+ // src/eve/tool-chart-format.ts
2373
+ var TIME_X_AXIS_KEY_PATTERN = /^(date|time|timestamp|month|day|week|period)$/i;
2374
+ function inferToolChartType(xKey) {
2375
+ return TIME_X_AXIS_KEY_PATTERN.test(xKey) ? "line" : "bar";
2376
+ }
2377
+ function formatToolChartResult(chart, options) {
2378
+ if (!chart.xKey.trim()) {
2379
+ throw new Error("formatToolChartResult: xKey is required");
2380
+ }
2381
+ const yKeys = chart.yKeys.map((key) => key.trim()).filter((key) => key.length > 0);
2382
+ if (yKeys.length === 0) {
2383
+ throw new Error("formatToolChartResult: yKeys must include at least one series key");
2384
+ }
2385
+ const data = {
2386
+ ...chart.title?.trim() ? { title: chart.title.trim() } : {},
2387
+ ...chart.description?.trim() ? { description: chart.description.trim() } : {},
2388
+ type: chart.type ?? inferToolChartType(chart.xKey),
2389
+ xKey: chart.xKey.trim(),
2390
+ yKeys,
2391
+ series: chart.series.map((row) => ({ ...row }))
2392
+ };
2393
+ const ui = {
2394
+ ...options.ui,
2395
+ layout: "chart",
2396
+ rowsPath: "series",
2397
+ entity: options.entity ?? options.ui?.entity ?? "metric_point",
2398
+ present: options.present ?? options.ui?.present ?? true
2399
+ };
2400
+ return withUiHint(
2401
+ withToolUi(withReplyGuidance(data, options.replyGuidance), ui),
2402
+ "chart"
2403
+ );
2404
+ }
2405
+
2406
+ // src/eve/tools/catalog/generate-random-chart.ts
2407
+ var GENERATE_RANDOM_CHART_TOOL_NAME = "generate_random_chart";
2408
+ var generateRandomChartInputSchema = z11.object({
2409
+ axis: z11.enum(["time", "category", "random"]).optional().describe(
2410
+ "X-axis style: time (line), category (bar), or random. Defaults to random."
2411
+ ),
2412
+ seriesCount: z11.number().int().min(1).max(3).optional().describe("Number of numeric series (1\u20133). Defaults to a random 1\u20132."),
2413
+ pointCount: z11.number().int().min(4).max(30).optional().describe("Number of data points (4\u201330). Defaults to a random 8\u201314."),
2414
+ seed: z11.number().int().optional().describe("Optional seed for reproducible random data.")
2415
+ });
2416
+ function createRng(seed) {
2417
+ let state = seed === void 0 ? (Math.floor(Math.random() * 2147483647) ^ Date.now()) >>> 0 : seed >>> 0;
2418
+ if (state === 0) {
2419
+ state = 1;
2420
+ }
2421
+ return () => {
2422
+ state ^= state << 13;
2423
+ state ^= state >>> 17;
2424
+ state ^= state << 5;
2425
+ return (state >>> 0) / 4294967296;
2426
+ };
2427
+ }
2428
+ function pick(rng, items) {
2429
+ return items[Math.floor(rng() * items.length)];
2430
+ }
2431
+ function randomInt(rng, min, max) {
2432
+ return min + Math.floor(rng() * (max - min + 1));
2433
+ }
2434
+ function roundMetric(value) {
2435
+ return Math.round(value * 10) / 10;
2436
+ }
2437
+ var TIME_TITLES = [
2438
+ "Task throughput",
2439
+ "Approvals over time",
2440
+ "Inbox volume",
2441
+ "Agent tool calls",
2442
+ "Webhook deliveries"
2443
+ ];
2444
+ var CATEGORY_TITLES = [
2445
+ "Tasks by status",
2446
+ "Approvals by team",
2447
+ "Volume by region",
2448
+ "Spend by category",
2449
+ "Tickets by priority"
2450
+ ];
2451
+ var TIME_SERIES_KEYS = [
2452
+ ["value"],
2453
+ ["created", "handled"],
2454
+ ["open", "handled", "expired"]
2455
+ ];
2456
+ var CATEGORY_SERIES_KEYS = [
2457
+ ["value"],
2458
+ ["revenue", "costs"],
2459
+ ["approved", "rejected", "pending"]
2460
+ ];
2461
+ var CATEGORIES = [
2462
+ ["North", "South", "East", "West", "Central"],
2463
+ ["Finance", "Ops", "Support", "Engineering", "Sales"],
2464
+ ["P0", "P1", "P2", "P3", "P4"],
2465
+ ["Draft", "Open", "Handled", "Expired", "Cancelled"]
2466
+ ];
2467
+ function formatDate(daysAgo) {
2468
+ const date = /* @__PURE__ */ new Date();
2469
+ date.setUTCHours(0, 0, 0, 0);
2470
+ date.setUTCDate(date.getUTCDate() - daysAgo);
2471
+ return date.toISOString().slice(0, 10);
2472
+ }
2473
+ function buildSeriesPoints(args) {
2474
+ const { rng, axis, seriesKeys, pointCount } = args;
2475
+ const baselines = seriesKeys.map(() => 20 + rng() * 80);
2476
+ if (axis === "time") {
2477
+ return Array.from({ length: pointCount }, (_, index) => {
2478
+ const point = {
2479
+ date: formatDate(pointCount - 1 - index)
2480
+ };
2481
+ for (let i = 0; i < seriesKeys.length; i++) {
2482
+ const drift = (rng() - 0.45) * 12;
2483
+ baselines[i] = Math.max(1, baselines[i] + drift);
2484
+ point[seriesKeys[i]] = roundMetric(baselines[i]);
2485
+ }
2486
+ return point;
2487
+ });
2488
+ }
2489
+ const labels = pick(rng, CATEGORIES).slice(0, pointCount);
2490
+ return labels.map((label) => {
2491
+ const point = { category: label };
2492
+ for (let i = 0; i < seriesKeys.length; i++) {
2493
+ point[seriesKeys[i]] = roundMetric(8 + rng() * 120);
2494
+ }
2495
+ return point;
2496
+ });
2497
+ }
2498
+ function buildRandomChartData(input = {}) {
2499
+ const rng = createRng(input.seed);
2500
+ const axis = input.axis === "time" || input.axis === "category" ? input.axis : pick(rng, ["time", "category"]);
2501
+ const seriesCount = input.seriesCount ?? randomInt(rng, 1, 2);
2502
+ const pointCount = input.pointCount ?? (axis === "time" ? randomInt(rng, 8, 14) : randomInt(rng, 4, 6));
2503
+ const keyPool = axis === "time" ? TIME_SERIES_KEYS : CATEGORY_SERIES_KEYS;
2504
+ const seriesKeys = keyPool.find((keys) => keys.length === seriesCount) ?? keyPool[0];
2505
+ const title = pick(rng, axis === "time" ? TIME_TITLES : CATEGORY_TITLES);
2506
+ const series = buildSeriesPoints({
2507
+ rng,
2508
+ axis,
2509
+ seriesKeys,
2510
+ pointCount
2511
+ });
2512
+ return { title, axis, series };
2513
+ }
2514
+ function defineGenerateRandomChartTool() {
2515
+ return defineTool5({
2516
+ description: "Generate random chart-ready demo metrics for testing chat chart UI. Results render as a chart card \u2014 do not restate series values in your reply.",
2517
+ inputSchema: generateRandomChartInputSchema,
2518
+ outputSchema: generateRandomChartOutputSchema,
2519
+ async execute(input) {
2520
+ const data = buildRandomChartData(input);
2521
+ const xKey = data.axis === "time" ? "date" : "category";
2522
+ const sample = data.series[0] ?? {};
2523
+ const yKeys = Object.keys(sample).filter((key) => key !== xKey);
2524
+ const result = formatToolChartResult(
2525
+ {
2526
+ title: data.title,
2527
+ type: data.axis === "time" ? "line" : "bar",
2528
+ xKey,
2529
+ yKeys,
2530
+ series: data.series
2531
+ },
2532
+ {
2533
+ replyGuidance: GENERATE_RANDOM_CHART_REPLY_GUIDANCE,
2534
+ entity: "metric_point",
2535
+ present: true
2536
+ }
2537
+ );
2538
+ return { ...result, title: data.title };
2539
+ }
2540
+ });
2541
+ }
2542
+ var generateRandomChartTool = defineGenerateRandomChartTool();
2543
+
2544
+ // src/eve/tools/catalog/generate-image.ts
2545
+ import { createOpenRouter } from "@openrouter/ai-sdk-provider";
2546
+ import { createGateway, generateImage } from "ai";
2547
+ import { defineTool as defineTool6 } from "eve/tools";
2548
+ import { z as z12 } from "zod";
2549
+ var GENERATE_IMAGE_TOOL_NAME = "generate_image";
2550
+ var DEFAULT_IMAGE_MODEL = "black-forest-labs/flux.2-klein-4b";
2551
+ var DEFAULT_IMAGE_SIZE = "512";
2552
+ var DEFAULT_IMAGE_ASPECT_RATIO = "1:1";
2553
+ var generateImageInputSchema = z12.object({
2554
+ prompt: z12.string().min(1).describe("Detailed description of the image to generate")
2555
+ });
2556
+ function normalizeEnvValue(value) {
2557
+ if (!value) {
2558
+ return void 0;
2559
+ }
2560
+ return value.replace(/^["']|["']$/g, "");
2561
+ }
2562
+ function isJwtExpired(token, bufferSeconds = 60) {
2563
+ try {
2564
+ const payload = JSON.parse(
2565
+ Buffer.from(token.split(".")[1] ?? "", "base64url").toString("utf8")
2566
+ );
2567
+ return typeof payload.exp !== "number" || Date.now() / 1e3 >= payload.exp - bufferSeconds;
2568
+ } catch {
2569
+ return true;
2570
+ }
2571
+ }
2572
+ function resolveAiImageModel(modelId = normalizeEnvValue(process.env.AI_IMAGE_MODEL) ?? DEFAULT_IMAGE_MODEL) {
2573
+ const openRouterKey = normalizeEnvValue(process.env.OPENROUTER_API_KEY);
2574
+ if (openRouterKey) {
2575
+ const openrouter = createOpenRouter({ apiKey: openRouterKey });
2576
+ return {
2577
+ provider: "openrouter",
2578
+ model: openrouter.imageModel(modelId),
2579
+ modelId
2580
+ };
2581
+ }
2582
+ const gatewayKey = normalizeEnvValue(process.env.AI_GATEWAY_API_KEY);
2583
+ if (gatewayKey) {
2584
+ const gateway2 = createGateway({ apiKey: gatewayKey });
2585
+ return {
2586
+ provider: "ai-gateway-api-key",
2587
+ model: gateway2.imageModel(modelId),
2588
+ modelId
2589
+ };
2590
+ }
2591
+ const oidcToken = normalizeEnvValue(process.env.VERCEL_OIDC_TOKEN);
2592
+ if (!oidcToken) {
2593
+ throw new Error(
2594
+ `No AI provider credentials for image model "${modelId}". Set OPENROUTER_API_KEY (preferred), or AI_GATEWAY_API_KEY / VERCEL_OIDC_TOKEN.`
2595
+ );
2596
+ }
2597
+ if (isJwtExpired(oidcToken)) {
2598
+ throw new Error(
2599
+ "VERCEL_OIDC_TOKEN is expired. Set OPENROUTER_API_KEY instead, or refresh the OIDC token."
2600
+ );
2601
+ }
2602
+ process.env.VERCEL_OIDC_TOKEN = oidcToken;
2603
+ const gateway = createGateway();
2604
+ return {
2605
+ provider: "ai-gateway-oidc",
2606
+ model: gateway.imageModel(modelId),
2607
+ modelId
2608
+ };
2609
+ }
2610
+ function resolveAiImageSize() {
2611
+ return normalizeEnvValue(process.env.AI_IMAGE_SIZE) ?? DEFAULT_IMAGE_SIZE;
2612
+ }
2613
+ function resolveAiImageAspectRatio() {
2614
+ return normalizeEnvValue(process.env.AI_IMAGE_ASPECT_RATIO) ?? DEFAULT_IMAGE_ASPECT_RATIO;
2615
+ }
2616
+ function extensionForMediaType(mediaType) {
2617
+ const normalized = mediaType.toLowerCase();
2618
+ if (normalized.includes("jpeg") || normalized.includes("jpg")) return "jpg";
2619
+ if (normalized.includes("webp")) return "webp";
2620
+ if (normalized.includes("gif")) return "gif";
2621
+ return "png";
2622
+ }
2623
+ function filenameFromImagePrompt(prompt, mediaType) {
2624
+ const slug = prompt.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
2625
+ return `${slug || "generated-image"}.${extensionForMediaType(mediaType)}`;
2626
+ }
2627
+ async function generateImageBytes(input, options) {
2628
+ const { model, modelId } = resolveAiImageModel();
2629
+ const size = resolveAiImageSize();
2630
+ const aspectRatio = resolveAiImageAspectRatio();
2631
+ try {
2632
+ const { image } = await generateImage({
2633
+ model,
2634
+ prompt: input.prompt,
2635
+ aspectRatio,
2636
+ abortSignal: options?.abortSignal,
2637
+ size
2638
+ });
2639
+ if (!image.base64) {
2640
+ throw new Error(`Image model "${modelId}" returned no image data.`);
2641
+ }
2642
+ return {
2643
+ prompt: input.prompt,
2644
+ mediaType: image.mediaType || "image/png",
2645
+ model: modelId,
2646
+ base64: image.base64
2647
+ };
2648
+ } catch (error) {
2649
+ const message = error instanceof Error ? error.message : "Image generation failed.";
2650
+ throw new Error(`Image generation failed (${modelId}): ${message}`);
2651
+ }
2652
+ }
2653
+ function defineGenerateImageTool() {
2654
+ return defineTool6({
2655
+ description: "Generate an image from a text prompt using a cheap/fast image model. Use when the user asks to draw, create, or generate a picture or illustration. The image renders in chat UI \u2014 do not describe the pixels in your reply.",
2656
+ inputSchema: generateImageInputSchema,
2657
+ outputSchema: generateImageOutputSchema,
2658
+ toModelOutput(output) {
2659
+ return {
2660
+ type: "text",
2661
+ value: `Generated an image for: "${output.prompt}" (model: ${output.model}).`
2662
+ };
2663
+ },
2664
+ async execute(input, ctx) {
2665
+ const caller = tryResolveTenantCaller(ctx);
2666
+ const chatId = caller?.chatId?.trim();
2667
+ if (!chatId) {
2668
+ throw new Error(
2669
+ "generate_image requires a dashboard chat session (missing chatId)."
2670
+ );
2671
+ }
2672
+ const client = tryCreateBoundRobotRockClient(ctx);
2673
+ if (!client) {
2674
+ throw new Error(
2675
+ "RobotRock auth is unset. Configure ROBOTROCK_AGENT_SERVICE_TOKEN for hosted agents or ROBOTROCK_API_KEY for self-hosted deployments."
2676
+ );
2677
+ }
2678
+ const generated = await generateImageBytes(input, {
2679
+ abortSignal: ctx?.abortSignal
2680
+ });
2681
+ const uploaded = await client.chats.uploadImage({
2682
+ mediaType: generated.mediaType,
2683
+ base64: generated.base64,
2684
+ chatId,
2685
+ source: GENERATE_IMAGE_TOOL_NAME,
2686
+ filename: filenameFromImagePrompt(generated.prompt, generated.mediaType),
2687
+ description: generated.prompt,
2688
+ tags: [GENERATE_IMAGE_TOOL_NAME]
2689
+ });
2690
+ return formatToolObjectResult(
2691
+ {
2692
+ prompt: generated.prompt,
2693
+ mediaType: uploaded.mediaType || generated.mediaType,
2694
+ model: generated.model,
2695
+ storageId: uploaded.storageId,
2696
+ url: uploaded.url
2697
+ },
2698
+ {
2699
+ replyGuidance: GENERATE_IMAGE_REPLY_GUIDANCE,
2700
+ ui: {
2701
+ present: true,
2702
+ entity: "generated_image"
2703
+ }
2704
+ }
2705
+ );
2706
+ }
2707
+ });
2708
+ }
2709
+ var generateImageTool = defineGenerateImageTool();
2710
+
1997
2711
  // src/agent-admin.ts
1998
2712
  async function agentAdminFetch(config, path, init) {
1999
2713
  const baseUrl = (config.baseUrl?.trim() || getRobotRockApiBaseUrl()).replace(
@@ -2022,6 +2736,9 @@ async function agentAdminFetch(config, path, init) {
2022
2736
  }
2023
2737
  function createAgentAdminApi(config) {
2024
2738
  return {
2739
+ usage: {
2740
+ get: () => agentAdminFetch(config, "/usage")
2741
+ },
2025
2742
  members: {
2026
2743
  list: () => agentAdminFetch(config, "/members"),
2027
2744
  get: (memberRef) => agentAdminFetch(config, `/members/${encodeURIComponent(memberRef)}`),
@@ -2170,7 +2887,8 @@ function serializeMemberRow(member) {
2170
2887
  name: member.user.name,
2171
2888
  email: member.user.email,
2172
2889
  role: member.role,
2173
- membershipKind: member.membershipKind
2890
+ membershipKind: member.membershipKind,
2891
+ profilePictureUrl: member.user.profilePictureUrl ?? null
2174
2892
  };
2175
2893
  }
2176
2894
  function formatTeamMembersListResult(members) {
@@ -2178,29 +2896,31 @@ function formatTeamMembersListResult(members) {
2178
2896
  "members",
2179
2897
  members.map(serializeMemberRow),
2180
2898
  {
2181
- replyGuidance: MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE
2899
+ replyGuidance: MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE,
2900
+ entity: "member"
2182
2901
  }
2183
2902
  );
2184
2903
  }
2185
2904
  function formatTeamMemberDetailResult(member) {
2186
2905
  return formatToolObjectResult(serializeMemberRow(member), {
2187
- replyGuidance: MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE
2906
+ replyGuidance: MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE,
2907
+ ui: { entity: "member" }
2188
2908
  });
2189
2909
  }
2190
2910
 
2191
2911
  // src/eve/tools/admin/manage-team-members.ts
2192
- import { defineTool as defineTool5 } from "eve/tools";
2193
- import { z as z10 } from "zod";
2912
+ import { defineTool as defineTool7 } from "eve/tools";
2913
+ import { z as z13 } from "zod";
2194
2914
  var MANAGE_TEAM_MEMBERS_TOOL_NAME = "manage_team_members";
2195
- var manageTeamMembersInputSchema = z10.object({
2196
- action: z10.enum(["list", "get", "invite", "update_role", "remove"]),
2197
- userId: z10.string().min(1).optional().describe(
2915
+ var manageTeamMembersInputSchema = z13.object({
2916
+ action: z13.enum(["list", "get", "invite", "update_role", "remove"]),
2917
+ userId: z13.string().min(1).optional().describe(
2198
2918
  "Convex users table id for get, update_role, and remove. Prefer email when the member list only shows email."
2199
2919
  ),
2200
- email: z10.string().email().optional().describe(
2920
+ email: z13.string().email().optional().describe(
2201
2921
  "Member email for get, update_role, and remove; invitee email for invite."
2202
2922
  ),
2203
- role: z10.enum(["admin", "member"]).optional().describe("Role for invite and update_role.")
2923
+ role: z13.enum(["admin", "member"]).optional().describe("Role for invite and update_role.")
2204
2924
  }).superRefine((input, ctx) => {
2205
2925
  const requireField = (field, message) => {
2206
2926
  if (!input[field]) {
@@ -2241,9 +2961,10 @@ function formatMemberMutationResult(payload) {
2241
2961
  });
2242
2962
  }
2243
2963
  function defineManageTeamMembersTool() {
2244
- return defineTool5({
2245
- description: "Tenant-admin tool for workspace team members: list, get, invite, change role, or remove. Requires tenant admin access. Call get_my_access in the same turn before this tool to verify admin access (the check renders as its own chat tool card). Use member email from list results for get, update_role, and remove \u2014 internal ids are optional. Results render as chat UI cards \u2014 do not restate member names, emails, or roles in your reply.",
2964
+ return defineTool7({
2965
+ description: "Tenant-admin tool for workspace team members: list, get, invite, change role, or remove. Requires tenant admin access. Call get_my_access in the same turn before this tool to verify admin access (the check stays a compact success marker unless it is the only presentable result). Use member email from list results for get, update_role, and remove \u2014 internal ids are optional. Results render as chat UI cards \u2014 do not restate member names, emails, or roles in your reply.",
2246
2966
  inputSchema: manageTeamMembersInputSchema,
2967
+ outputSchema: manageTeamMembersOutputSchema,
2247
2968
  async execute(input, ctx) {
2248
2969
  const api = requireBoundAgentAdminClient(ctx);
2249
2970
  try {
@@ -2306,53 +3027,59 @@ function defineManageTeamMembersTool() {
2306
3027
  var manageTeamMembersTool = defineManageTeamMembersTool();
2307
3028
 
2308
3029
  // src/eve/tools/admin/manage-groups.ts
2309
- import { defineTool as defineTool6 } from "eve/tools";
2310
- import { z as z11 } from "zod";
3030
+ import { defineTool as defineTool8 } from "eve/tools";
3031
+ import { z as z14 } from "zod";
2311
3032
 
2312
3033
  // src/eve/tools/admin/format-groups-list.ts
2313
- function serializeGroupRow(group) {
3034
+ function serializeGroupRow(group, tenantSlug) {
2314
3035
  return {
2315
3036
  name: group.name,
2316
3037
  slug: group.slug,
2317
3038
  description: group.description,
2318
- memberCount: group.memberCount ?? null
3039
+ memberCount: group.memberCount ?? null,
3040
+ url: buildTenantGroupUrl(tenantSlug, group.slug)
2319
3041
  };
2320
3042
  }
2321
- function formatGroupsListResult(groups) {
3043
+ function formatGroupsListResult(groups, options) {
2322
3044
  return formatToolListResult(
2323
3045
  "groups",
2324
- groups.map(serializeGroupRow),
3046
+ groups.map((group) => serializeGroupRow(group, options.tenantSlug)),
2325
3047
  {
2326
- replyGuidance: MANAGE_GROUPS_LIST_REPLY_GUIDANCE
3048
+ replyGuidance: MANAGE_GROUPS_LIST_REPLY_GUIDANCE,
3049
+ entity: "group"
2327
3050
  }
2328
3051
  );
2329
3052
  }
2330
- function formatGroupDetailResult(group) {
3053
+ function formatGroupDetailResult(group, options) {
2331
3054
  return formatToolObjectResult(
2332
3055
  {
2333
3056
  name: group.name,
2334
3057
  slug: group.slug,
2335
3058
  description: group.description,
3059
+ url: buildTenantGroupUrl(options.tenantSlug, group.slug),
2336
3060
  members: group.members.map((member) => ({
2337
3061
  name: member.user.name,
2338
- email: member.user.email
3062
+ email: member.user.email,
3063
+ profilePictureUrl: member.user.profilePictureUrl ?? null
2339
3064
  }))
2340
3065
  },
2341
3066
  {
2342
- replyGuidance: MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE
3067
+ replyGuidance: MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE,
3068
+ ui: { entity: "group" }
2343
3069
  }
2344
3070
  );
2345
3071
  }
2346
- function formatGroupSummaryResult(group) {
2347
- return formatToolObjectResult(serializeGroupRow(group), {
2348
- replyGuidance: MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE
3072
+ function formatGroupSummaryResult(group, options) {
3073
+ return formatToolObjectResult(serializeGroupRow(group, options.tenantSlug), {
3074
+ replyGuidance: MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE,
3075
+ ui: { entity: "group" }
2349
3076
  });
2350
3077
  }
2351
3078
 
2352
3079
  // src/eve/tools/admin/manage-groups.ts
2353
3080
  var MANAGE_GROUPS_TOOL_NAME = "manage_groups";
2354
- var manageGroupsInputSchema = z11.object({
2355
- action: z11.enum([
3081
+ var manageGroupsInputSchema = z14.object({
3082
+ action: z14.enum([
2356
3083
  "list",
2357
3084
  "get",
2358
3085
  "create",
@@ -2361,18 +3088,18 @@ var manageGroupsInputSchema = z11.object({
2361
3088
  "add_member",
2362
3089
  "remove_member"
2363
3090
  ]),
2364
- groupId: z11.string().min(1).optional().describe(
3091
+ groupId: z14.string().min(1).optional().describe(
2365
3092
  "Convex group id for get, update, delete, and membership actions. Prefer slug when the group list only shows slug."
2366
3093
  ),
2367
- slug: z11.string().min(1).optional().describe(
3094
+ slug: z14.string().min(1).optional().describe(
2368
3095
  "Group slug (e.g. finance) for get, update, delete, and membership actions."
2369
3096
  ),
2370
- userId: z11.string().min(1).optional().describe(
3097
+ userId: z14.string().min(1).optional().describe(
2371
3098
  "User id for add_member and remove_member. Prefer email when the member list only shows email."
2372
3099
  ),
2373
- email: z11.string().email().optional().describe("Member email for add_member and remove_member."),
2374
- name: z11.string().min(1).optional().describe("Group name for create and update."),
2375
- description: z11.string().optional().describe("Group description for create and update.")
3100
+ email: z14.string().email().optional().describe("Member email for add_member and remove_member."),
3101
+ name: z14.string().min(1).optional().describe("Group name for create and update."),
3102
+ description: z14.string().optional().describe("Group description for create and update.")
2376
3103
  }).superRefine((input, ctx) => {
2377
3104
  const requireField = (field, message) => {
2378
3105
  if (!input[field]) {
@@ -2425,34 +3152,46 @@ function resolveMemberRef2(input) {
2425
3152
  return input.userId ?? input.email;
2426
3153
  }
2427
3154
  function defineManageGroupsTool() {
2428
- return defineTool6({
2429
- description: "Tenant-admin tool for workspace groups: list, get, create, update, delete, and manage group membership. Requires tenant admin access. Call get_my_access in the same turn before this tool to verify admin access (the check renders as its own chat tool card). Use group slug (e.g. finance) from list results for get and membership actions \u2014 internal ids are optional. Use member email for add_member and remove_member when user ids are unknown. Results render as chat UI cards \u2014 do not restate group or member fields in your reply.",
3155
+ return defineTool8({
3156
+ description: "Tenant-admin tool for workspace groups: list, get, create, update, delete, and manage group membership. Requires tenant admin access. Call get_my_access in the same turn before this tool to verify admin access (the check stays a compact success marker unless it is the only presentable result). Use group slug (e.g. finance) from list results for get and membership actions \u2014 internal ids are optional. Use member email for add_member and remove_member when user ids are unknown. Results render as chat UI cards \u2014 do not restate group or member fields in your reply.",
2430
3157
  inputSchema: manageGroupsInputSchema,
3158
+ outputSchema: manageGroupsOutputSchema,
2431
3159
  async execute(input, ctx) {
3160
+ const caller = requireAdminCaller(ctx);
2432
3161
  const api = requireBoundAgentAdminClient(ctx);
3162
+ const tenantSlug = caller.tenantSlug;
2433
3163
  try {
2434
3164
  switch (input.action) {
2435
3165
  case "list": {
2436
3166
  const result = await api.groups.list();
2437
- return formatGroupsListResult(result.groups);
3167
+ return formatGroupsListResult(result.groups, {
3168
+ tenantSlug
3169
+ });
2438
3170
  }
2439
3171
  case "get": {
2440
3172
  const result = await api.groups.get(resolveGroupRef(input));
2441
- return formatGroupDetailResult(result.group);
3173
+ return formatGroupDetailResult(
3174
+ result.group,
3175
+ { tenantSlug }
3176
+ );
2442
3177
  }
2443
3178
  case "create": {
2444
3179
  const result = await api.groups.create({
2445
3180
  name: input.name,
2446
3181
  description: input.description
2447
3182
  });
2448
- return formatGroupSummaryResult(result.group);
3183
+ return formatGroupSummaryResult(result.group, {
3184
+ tenantSlug
3185
+ });
2449
3186
  }
2450
3187
  case "update": {
2451
3188
  const result = await api.groups.update(resolveGroupRef(input), {
2452
3189
  name: input.name,
2453
3190
  description: input.description
2454
3191
  });
2455
- return formatGroupSummaryResult(result.group);
3192
+ return formatGroupSummaryResult(result.group, {
3193
+ tenantSlug
3194
+ });
2456
3195
  }
2457
3196
  case "delete": {
2458
3197
  const result = await api.groups.delete(resolveGroupRef(input));
@@ -2496,83 +3235,101 @@ function defineManageGroupsTool() {
2496
3235
  var manageGroupsTool = defineManageGroupsTool();
2497
3236
 
2498
3237
  // src/eve/tools/admin/query-tasks.ts
2499
- import { defineTool as defineTool7 } from "eve/tools";
2500
- import { z as z12 } from "zod";
3238
+ import { defineTool as defineTool9 } from "eve/tools";
3239
+ import { z as z15 } from "zod";
2501
3240
 
2502
3241
  // src/eve/tools/admin/format-tasks-list.ts
2503
3242
  function resolveTaskCardLabel(task) {
2504
3243
  return task.name?.trim() || task.description?.trim() || task.type?.trim() || task.id?.trim() || "Untitled task";
2505
3244
  }
3245
+ function serializeTaskRow(task, tenantSlug) {
3246
+ return {
3247
+ id: task.id,
3248
+ name: resolveTaskCardLabel(task),
3249
+ status: task.status,
3250
+ type: task.type,
3251
+ description: task.description,
3252
+ validUntil: task.validUntil,
3253
+ createdAt: task.createdAt,
3254
+ threadPriority: task.threadPriority,
3255
+ url: buildTenantTaskUrl(tenantSlug, {
3256
+ id: task.id,
3257
+ type: task.type
3258
+ })
3259
+ };
3260
+ }
2506
3261
  function formatTasksListResult(items, options) {
2507
3262
  const payload = {
2508
- items: items.map((task) => ({
2509
- id: task.id,
2510
- name: resolveTaskCardLabel(task),
2511
- status: task.status,
2512
- type: task.type,
2513
- description: task.description
2514
- }))
3263
+ items: items.map((task) => serializeTaskRow(task, options.tenantSlug))
2515
3264
  };
2516
- if (options?.nextCursor) {
3265
+ if (options.nextCursor) {
2517
3266
  payload.nextCursor = options.nextCursor;
2518
3267
  }
2519
3268
  return formatToolObjectResult(payload, {
2520
- replyGuidance: QUERY_TASKS_LIST_REPLY_GUIDANCE
3269
+ replyGuidance: QUERY_TASKS_LIST_REPLY_GUIDANCE,
3270
+ ui: { layout: "list", entity: "task", rowsPath: "items" }
2521
3271
  });
2522
3272
  }
2523
- function formatTaskSearchResult(items) {
2524
- return formatTasksListResult(items);
3273
+ function formatTaskSearchResult(items, options) {
3274
+ return formatTasksListResult(items, options);
2525
3275
  }
2526
- function formatTaskDetailResult(task) {
3276
+ function formatTaskDetailResult(task, options) {
3277
+ const id = typeof task.id === "string" ? task.id : null;
3278
+ const type = typeof task.type === "string" ? task.type : null;
3279
+ const url = id !== null ? buildTenantTaskUrl(options.tenantSlug, { id, type }) : null;
2527
3280
  return formatToolObjectResult(
2528
3281
  {
2529
- id: task.id ?? null,
2530
- status: task.status ?? null,
2531
- type: task.type ?? null,
2532
- name: task.name ?? null,
2533
- description: task.description ?? null,
2534
- validUntil: task.validUntil ?? null,
2535
- createdAt: task.createdAt ?? null
3282
+ id,
3283
+ status: typeof task.status === "string" ? task.status : null,
3284
+ type,
3285
+ name: typeof task.name === "string" ? task.name : null,
3286
+ description: typeof task.description === "string" ? task.description : null,
3287
+ validUntil: typeof task.validUntil === "number" ? task.validUntil : null,
3288
+ createdAt: typeof task.createdAt === "number" ? task.createdAt : null,
3289
+ url
2536
3290
  },
2537
3291
  {
2538
- replyGuidance: QUERY_TASKS_DETAIL_REPLY_GUIDANCE
3292
+ replyGuidance: QUERY_TASKS_DETAIL_REPLY_GUIDANCE,
3293
+ ui: { entity: "task" }
2539
3294
  }
2540
3295
  );
2541
3296
  }
2542
- function formatAssignTasksResult(results, _assignTo) {
2543
- return formatToolListResult(
2544
- "results",
2545
- results.map((row) => ({
3297
+ function formatAssignTasksResult(results, _assignTo, options) {
3298
+ const rows = results.map((row) => ({
3299
+ id: row.taskId,
3300
+ name: resolveTaskCardLabel({
3301
+ name: row.name,
3302
+ description: row.description,
3303
+ type: row.type,
3304
+ id: row.taskId
3305
+ }),
3306
+ type: row.type ?? null,
3307
+ description: row.description ?? null,
3308
+ status: row.success ? "reassigned" : "failed",
3309
+ url: buildTenantTaskUrl(options.tenantSlug, {
2546
3310
  id: row.taskId,
2547
- name: resolveTaskCardLabel({
2548
- name: row.name,
2549
- description: row.description,
2550
- type: row.type,
2551
- id: row.taskId
2552
- }),
2553
- type: row.type ?? null,
2554
- description: row.description ?? null,
2555
- status: row.success ? "reassigned" : "failed"
2556
- })),
2557
- {
2558
- replyGuidance: ASSIGN_TASKS_REPLY_GUIDANCE
2559
- }
2560
- );
3311
+ type: row.type
3312
+ })
3313
+ }));
3314
+ return formatToolListResult("results", rows, {
3315
+ replyGuidance: ASSIGN_TASKS_REPLY_GUIDANCE,
3316
+ entity: "status"
3317
+ });
2561
3318
  }
2562
3319
 
2563
3320
  // src/eve/tools/admin/query-tasks.ts
2564
3321
  var QUERY_TASKS_TOOL_NAME = "query_tasks";
2565
- var queryTasksInputSchema = z12.object({
2566
- action: z12.enum(["list", "get", "search"]),
2567
- statusFilter: z12.enum(["all", "open", "handled", "expired"]).optional().describe("Filter by task status for list."),
2568
- typeFilter: z12.string().optional(),
2569
- appFilter: z12.string().optional(),
2570
- sortField: z12.enum(["type", "date", "status", "validUntil"]).optional(),
2571
- sortDirection: z12.enum(["asc", "desc"]).optional(),
2572
- limit: z12.number().int().positive().max(100).optional(),
2573
- cursor: z12.string().optional(),
2574
- taskId: z12.string().min(1).optional().describe("Public task id or Convex tasks table id for get."),
2575
- query: z12.string().min(1).optional().describe("Search type, name, description, or id for search.")
3322
+ var queryTasksInputSchema = z15.object({
3323
+ action: z15.enum(["list", "get", "search"]),
3324
+ statusFilter: z15.enum(["all", "open", "handled", "expired"]).optional().describe("Filter by task status for list."),
3325
+ typeFilter: z15.string().optional(),
3326
+ appFilter: z15.string().optional(),
3327
+ sortField: z15.enum(["type", "date", "status", "validUntil"]).optional(),
3328
+ sortDirection: z15.enum(["asc", "desc"]).optional(),
3329
+ limit: z15.number().int().positive().max(100).optional(),
3330
+ cursor: z15.string().optional(),
3331
+ taskId: z15.string().min(1).optional().describe("Public task id or Convex tasks table id for get."),
3332
+ query: z15.string().min(1).optional().describe("Search type, name, description, or id for search.")
2576
3333
  }).superRefine((input, ctx) => {
2577
3334
  switch (input.action) {
2578
3335
  case "get":
@@ -2596,11 +3353,14 @@ var queryTasksInputSchema = z12.object({
2596
3353
  }
2597
3354
  });
2598
3355
  function defineQueryTasksTool() {
2599
- return defineTool7({
2600
- description: "Tenant-admin tool to list, fetch detail, or search inbox tasks in the workspace. Requires tenant admin access. Call get_my_access in the same turn before this tool to verify admin access (the check renders as its own chat tool card). Results render as chat UI cards \u2014 do not restate task names, ids, or statuses in your reply.",
3356
+ return defineTool9({
3357
+ description: "Tenant-admin tool to list, fetch detail, or search inbox tasks in the workspace. Requires tenant admin access. Call get_my_access in the same turn before this tool to verify admin access (the check stays a compact success marker unless it is the only presentable result). Results render as chat UI cards \u2014 do not restate task names, ids, or statuses in your reply.",
2601
3358
  inputSchema: queryTasksInputSchema,
3359
+ outputSchema: queryTasksOutputSchema,
2602
3360
  async execute(input, ctx) {
3361
+ const caller = requireAdminCaller(ctx);
2603
3362
  const api = requireBoundAgentAdminClient(ctx);
3363
+ const tenantSlug = caller.tenantSlug;
2604
3364
  try {
2605
3365
  switch (input.action) {
2606
3366
  case "list": {
@@ -2614,17 +3374,22 @@ function defineQueryTasksTool() {
2614
3374
  cursor: input.cursor
2615
3375
  });
2616
3376
  return formatTasksListResult(result.items, {
3377
+ tenantSlug,
2617
3378
  nextCursor: result.nextCursor
2618
3379
  });
2619
3380
  }
2620
3381
  case "get": {
2621
3382
  const result = await api.tasks.get(input.taskId);
2622
- return formatTaskDetailResult(result.task);
3383
+ return formatTaskDetailResult(
3384
+ result.task,
3385
+ { tenantSlug }
3386
+ );
2623
3387
  }
2624
3388
  case "search": {
2625
3389
  const result = await api.tasks.search(input.query, input.limit);
2626
3390
  return formatTaskSearchResult(
2627
- result.items
3391
+ result.items,
3392
+ { tenantSlug }
2628
3393
  );
2629
3394
  }
2630
3395
  }
@@ -2645,11 +3410,11 @@ function defineQueryTasksTool() {
2645
3410
  var queryTasksTool = defineQueryTasksTool();
2646
3411
 
2647
3412
  // src/eve/tools/admin/assign-tasks.ts
2648
- import { defineTool as defineTool8 } from "eve/tools";
2649
- import { z as z13 } from "zod";
3413
+ import { defineTool as defineTool10 } from "eve/tools";
3414
+ import { z as z16 } from "zod";
2650
3415
  var ASSIGN_TASKS_TOOL_NAME = "assign_tasks";
2651
- var assignTasksInputSchema = z13.object({
2652
- taskIds: z13.array(z13.string().min(1)).min(1).max(100).describe(
3416
+ var assignTasksInputSchema = z16.object({
3417
+ taskIds: z16.array(z16.string().min(1)).min(1).max(100).describe(
2653
3418
  "Public task ids or Convex tasks table ids to reassign. Use query_tasks search/get to resolve ids first."
2654
3419
  ),
2655
3420
  assignTo: assignToSchema.refine(
@@ -2660,17 +3425,21 @@ var assignTasksInputSchema = z13.object({
2660
3425
  )
2661
3426
  });
2662
3427
  function defineAssignTasksTool() {
2663
- return defineTool8({
3428
+ return defineTool10({
2664
3429
  description: "Reassign existing inbox tasks to users or groups. Requires access to each task (tenant admins can reassign any task; others only tasks they can see). Use query_tasks to find task ids when needed. Results render as chat UI \u2014 do not restate task ids or assignees in your reply.",
2665
3430
  inputSchema: assignTasksInputSchema,
3431
+ outputSchema: assignTasksOutputSchema,
2666
3432
  async execute(input, ctx) {
3433
+ const caller = requireTenantCaller(ctx);
2667
3434
  const api = createBoundAgentAdminClient(ctx);
2668
3435
  try {
2669
3436
  const result = await api.tasks.assign({
2670
3437
  taskIds: input.taskIds,
2671
3438
  assignTo: input.assignTo
2672
3439
  });
2673
- return formatAssignTasksResult(result.results, input.assignTo);
3440
+ return formatAssignTasksResult(result.results, input.assignTo, {
3441
+ tenantSlug: caller.tenantSlug
3442
+ });
2674
3443
  } catch (error) {
2675
3444
  if (error instanceof RobotRockError) {
2676
3445
  return {
@@ -2687,6 +3456,72 @@ function defineAssignTasksTool() {
2687
3456
  }
2688
3457
  var assignTasksTool = defineAssignTasksTool();
2689
3458
 
3459
+ // src/eve/tools/admin/get-workspace-usage.ts
3460
+ import { defineTool as defineTool11 } from "eve/tools";
3461
+ import { z as z17 } from "zod";
3462
+
3463
+ // src/eve/tools/admin/format-workspace-usage.ts
3464
+ function formatLimit(current, max) {
3465
+ return max === null ? `${current} / unlimited` : `${current} / ${max}`;
3466
+ }
3467
+ function formatWorkspaceUsageResult(usage) {
3468
+ const tasksLimit = usage.maxTasksPerDay === null ? `${usage.tasksToday} / unlimited` : `${usage.tasksToday} / ${usage.maxTasksPerDay}`;
3469
+ return formatToolObjectResult(
3470
+ {
3471
+ usage: {
3472
+ workspace: usage.workspace,
3473
+ plan: usage.planName,
3474
+ planType: usage.planType,
3475
+ trialState: usage.trialState,
3476
+ daysRemaining: usage.daysRemaining,
3477
+ isPaidPro: usage.isPaidPro,
3478
+ subscriptionStatus: usage.subscriptionStatus ?? "\u2014",
3479
+ tasksToday: tasksLimit,
3480
+ tasksResetAt: new Date(usage.tasksResetAt).toISOString(),
3481
+ openTasks: usage.openTasks,
3482
+ totalTasks: usage.totalTasks,
3483
+ seats: formatLimit(usage.seatsCurrent, usage.seatsMax),
3484
+ groups: formatLimit(usage.groupsCurrent, usage.groupsMax),
3485
+ apiKeys: formatLimit(usage.apiKeysCurrent, usage.apiKeysMax),
3486
+ rateLimitPerSecond: usage.rateLimitPerSecond
3487
+ }
3488
+ },
3489
+ {
3490
+ replyGuidance: GET_WORKSPACE_USAGE_REPLY_GUIDANCE,
3491
+ ui: { entity: "usage" }
3492
+ }
3493
+ );
3494
+ }
3495
+
3496
+ // src/eve/tools/admin/get-workspace-usage.ts
3497
+ var GET_WORKSPACE_USAGE_TOOL_NAME = "get_workspace_usage";
3498
+ var getWorkspaceUsageInputSchema = z17.object({});
3499
+ function defineGetWorkspaceUsageTool() {
3500
+ return defineTool11({
3501
+ description: "Tenant-admin tool for workspace plan, limits, and usage (tasks today, seats, groups, API keys, rate limits). Does not include LLM token counts or dollar spend \u2014 those are not tracked. Requires tenant admin access. Call get_my_access in the same turn before this tool. Results render as a chat UI card \u2014 do not restate plan or usage numbers in your reply.",
3502
+ inputSchema: getWorkspaceUsageInputSchema,
3503
+ outputSchema: getWorkspaceUsageOutputSchema,
3504
+ async execute(_input, ctx) {
3505
+ const api = requireBoundAgentAdminClient(ctx);
3506
+ try {
3507
+ const result = await api.usage.get();
3508
+ return formatWorkspaceUsageResult(result.usage);
3509
+ } catch (error) {
3510
+ if (error instanceof RobotRockError) {
3511
+ return {
3512
+ ok: false,
3513
+ status: error.statusCode,
3514
+ message: error.message,
3515
+ response: error.response
3516
+ };
3517
+ }
3518
+ throw error;
3519
+ }
3520
+ }
3521
+ });
3522
+ }
3523
+ var getWorkspaceUsageTool = defineGetWorkspaceUsageTool();
3524
+
2690
3525
  // src/eve/tools/index.ts
2691
3526
  function createRobotrockTools(options) {
2692
3527
  const tools = {};
@@ -2704,6 +3539,9 @@ function createRobotrockTools(options) {
2704
3539
  export {
2705
3540
  ASSIGN_TASKS_TOOL_NAME,
2706
3541
  CREATE_INBOX_TASK_TOOL_NAME,
3542
+ GENERATE_IMAGE_TOOL_NAME,
3543
+ GENERATE_RANDOM_CHART_TOOL_NAME,
3544
+ GET_WORKSPACE_USAGE_TOOL_NAME,
2707
3545
  MANAGE_GROUPS_TOOL_NAME,
2708
3546
  MANAGE_TEAM_MEMBERS_TOOL_NAME,
2709
3547
  MY_ACCESS_TOOL_NAME,
@@ -2712,17 +3550,28 @@ export {
2712
3550
  WHOAMI_TOOL_NAME,
2713
3551
  assignTasksInputSchema,
2714
3552
  assignTasksTool,
3553
+ buildRandomChartData,
2715
3554
  createInboxTaskInputSchema,
2716
3555
  createInboxTaskTool,
2717
3556
  createRobotrockTools,
2718
3557
  defineAssignTasksTool,
2719
3558
  defineCreateInboxTaskTool,
3559
+ defineGenerateImageTool,
3560
+ defineGenerateRandomChartTool,
3561
+ defineGetWorkspaceUsageTool,
2720
3562
  defineManageGroupsTool,
2721
3563
  defineManageTeamMembersTool,
2722
3564
  defineMyAccessTool,
2723
3565
  defineQueryTasksTool,
2724
3566
  defineSearchProductsTool,
2725
3567
  defineWhoamiTool,
3568
+ generateImageBytes,
3569
+ generateImageInputSchema,
3570
+ generateImageTool,
3571
+ generateRandomChartInputSchema,
3572
+ generateRandomChartTool,
3573
+ getWorkspaceUsageInputSchema,
3574
+ getWorkspaceUsageTool,
2726
3575
  manageGroupsTool,
2727
3576
  manageTeamMembersTool,
2728
3577
  myAccessInputSchema,