robotrock 1.3.4 → 1.4.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 +565 -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 +384 -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 +322 -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 +1353 -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 +338 -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 +306 -16
  32. package/dist/eve/tools/admin/manage-team-members.js.map +1 -1
  33. package/dist/eve/tools/admin/query-tasks.d.ts +85 -10
  34. package/dist/eve/tools/admin/query-tasks.js +351 -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 +2065 -0
  38. package/dist/eve/tools/catalog/generate-image.js.map +1 -0
  39. package/dist/eve/tools/catalog/generate-random-chart.d.ts +71 -0
  40. package/dist/eve/tools/catalog/generate-random-chart.js +372 -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 +241 -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 +90 -5
  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 +908 -115
  61. package/dist/eve/tools/index.js.map +1 -1
  62. package/dist/index-Drj0Rzf_.d.ts +905 -0
  63. package/dist/index.d.ts +5 -5
  64. package/dist/index.js +316 -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
@@ -1,7 +1,213 @@
1
1
  // src/eve/tools/catalog/search-products.ts
2
2
  import { defineTool } from "eve/tools";
3
+ import { z as z2 } from "zod";
4
+
5
+ // src/eve/entity-schemas.ts
3
6
  import { z } from "zod";
4
7
 
8
+ // src/eve/tool-ui-hint.ts
9
+ var TOOL_UI_HINT_FIELD = "uiHint";
10
+ function withUiHint(result, hint) {
11
+ return {
12
+ ...result,
13
+ [TOOL_UI_HINT_FIELD]: hint
14
+ };
15
+ }
16
+
17
+ // src/eve/tool-result-ui-meta.ts
18
+ var TOOL_UI_FIELD = "ui";
19
+ var TOOL_RESULT_UI_ENTITY_ID_RE = /^[a-z][a-z0-9_]{0,63}$/;
20
+ function withToolUi(result, ui) {
21
+ const existing = typeof result[TOOL_UI_FIELD] === "object" && result[TOOL_UI_FIELD] !== null && !Array.isArray(result[TOOL_UI_FIELD]) ? result[TOOL_UI_FIELD] : {};
22
+ return {
23
+ ...result,
24
+ [TOOL_UI_FIELD]: {
25
+ ...existing,
26
+ ...ui
27
+ }
28
+ };
29
+ }
30
+
31
+ // src/eve/entity-schemas.ts
32
+ var toolResultUiMetaSchema = z.object({
33
+ present: z.boolean().optional(),
34
+ entity: z.string().regex(TOOL_RESULT_UI_ENTITY_ID_RE).optional(),
35
+ rowsPath: z.string().min(1).optional(),
36
+ layout: z.enum(["list", "chart", "table"]).optional()
37
+ }).strict();
38
+ var agentOnlyFields = {
39
+ replyGuidance: z.string().optional(),
40
+ ui: toolResultUiMetaSchema.optional(),
41
+ uiHint: z.enum(["list", "chart", "table"]).optional()
42
+ };
43
+ function withAgentOnlyFields(shape) {
44
+ return z.object({
45
+ ...shape,
46
+ ...agentOnlyFields
47
+ });
48
+ }
49
+ var productEntityRowSchema = z.object({
50
+ id: z.string().min(1),
51
+ name: z.string().min(1),
52
+ price: z.number(),
53
+ currency: z.string().min(1),
54
+ inStock: z.boolean(),
55
+ url: z.string().min(1)
56
+ });
57
+ var metricPointEntityRowSchema = z.object({
58
+ date: z.string().optional(),
59
+ category: z.string().optional(),
60
+ label: z.string().optional()
61
+ }).catchall(z.union([z.string(), z.number()]));
62
+ var memberEntityRowSchema = z.object({
63
+ name: z.string(),
64
+ email: z.string(),
65
+ role: z.string(),
66
+ membershipKind: z.string(),
67
+ profilePictureUrl: z.string().nullable()
68
+ });
69
+ var taskEntityRowSchema = z.object({
70
+ id: z.string().min(1),
71
+ name: z.string().min(1),
72
+ status: z.string().min(1),
73
+ type: z.string().nullable(),
74
+ description: z.string().nullable(),
75
+ validUntil: z.number(),
76
+ createdAt: z.number(),
77
+ url: z.string().min(1),
78
+ threadPriority: z.string().nullable().optional()
79
+ });
80
+ var groupEntityRowSchema = z.object({
81
+ name: z.string().min(1),
82
+ slug: z.string().min(1),
83
+ description: z.string().nullable(),
84
+ memberCount: z.number().nullable(),
85
+ url: z.string().min(1)
86
+ });
87
+ var groupDetailEntitySchema = z.object({
88
+ name: z.string().min(1),
89
+ slug: z.string().min(1),
90
+ description: z.string().nullable(),
91
+ url: z.string().min(1),
92
+ members: z.array(
93
+ z.object({
94
+ name: z.string(),
95
+ email: z.string(),
96
+ profilePictureUrl: z.string().nullable()
97
+ })
98
+ )
99
+ });
100
+ var statusEntityRowSchema = z.object({
101
+ id: z.string().min(1),
102
+ name: z.string().min(1),
103
+ status: z.string().min(1),
104
+ url: z.string().min(1),
105
+ type: z.string().nullable().optional(),
106
+ description: z.string().nullable().optional()
107
+ });
108
+ var agentAdminErrorResultSchema = z.object({
109
+ ok: z.literal(false),
110
+ status: z.number().optional(),
111
+ message: z.string(),
112
+ response: z.unknown().optional()
113
+ });
114
+ var agentAdminMutationResultSchema = z.object({
115
+ ...agentOnlyFields
116
+ }).passthrough();
117
+ var searchProductsOutputSchema = withAgentOnlyFields({
118
+ items: z.array(productEntityRowSchema)
119
+ });
120
+ var generateRandomChartOutputSchema = withAgentOnlyFields({
121
+ title: z.string().min(1),
122
+ axis: z.enum(["time", "category"]),
123
+ series: z.array(metricPointEntityRowSchema)
124
+ });
125
+ var generateImageOutputSchema = withAgentOnlyFields({
126
+ prompt: z.string().min(1),
127
+ mediaType: z.string().min(1),
128
+ model: z.string().min(1),
129
+ storageId: z.string().min(1),
130
+ url: z.string().min(1),
131
+ /** @deprecated Legacy sessions only — prefer storageId/url. */
132
+ base64: z.string().min(1).optional()
133
+ });
134
+ var manageTeamMembersListOutputSchema = withAgentOnlyFields({
135
+ members: z.array(memberEntityRowSchema)
136
+ });
137
+ var manageTeamMembersDetailOutputSchema = withAgentOnlyFields(
138
+ memberEntityRowSchema.shape
139
+ );
140
+ var manageTeamMembersOutputSchema = z.union([
141
+ manageTeamMembersListOutputSchema,
142
+ manageTeamMembersDetailOutputSchema,
143
+ agentAdminMutationResultSchema,
144
+ agentAdminErrorResultSchema
145
+ ]);
146
+ var manageGroupsListOutputSchema = withAgentOnlyFields({
147
+ groups: z.array(groupEntityRowSchema)
148
+ });
149
+ var manageGroupsDetailOutputSchema = withAgentOnlyFields(
150
+ groupDetailEntitySchema.shape
151
+ );
152
+ var manageGroupsSummaryOutputSchema = withAgentOnlyFields(
153
+ groupEntityRowSchema.shape
154
+ );
155
+ var manageGroupsOutputSchema = z.union([
156
+ manageGroupsListOutputSchema,
157
+ manageGroupsDetailOutputSchema,
158
+ manageGroupsSummaryOutputSchema,
159
+ agentAdminMutationResultSchema,
160
+ agentAdminErrorResultSchema
161
+ ]);
162
+ var queryTasksListOutputSchema = withAgentOnlyFields({
163
+ items: z.array(taskEntityRowSchema),
164
+ nextCursor: z.string().nullable().optional()
165
+ });
166
+ var queryTasksDetailOutputSchema = withAgentOnlyFields({
167
+ id: z.string().nullable(),
168
+ status: z.string().nullable(),
169
+ type: z.string().nullable(),
170
+ name: z.string().nullable(),
171
+ description: z.string().nullable(),
172
+ validUntil: z.number().nullable(),
173
+ createdAt: z.number().nullable(),
174
+ url: z.string().min(1).nullable()
175
+ });
176
+ var queryTasksOutputSchema = z.union([
177
+ queryTasksListOutputSchema,
178
+ queryTasksDetailOutputSchema,
179
+ agentAdminErrorResultSchema
180
+ ]);
181
+ var assignTasksOutputSchema = z.union([
182
+ withAgentOnlyFields({
183
+ results: z.array(statusEntityRowSchema)
184
+ }),
185
+ agentAdminErrorResultSchema
186
+ ]);
187
+ var workspaceUsageEntitySchema = z.object({
188
+ workspace: z.string(),
189
+ plan: z.string(),
190
+ planType: z.string(),
191
+ trialState: z.string(),
192
+ daysRemaining: z.number().nullable(),
193
+ isPaidPro: z.boolean(),
194
+ subscriptionStatus: z.string(),
195
+ tasksToday: z.string(),
196
+ tasksResetAt: z.string(),
197
+ openTasks: z.number(),
198
+ totalTasks: z.number(),
199
+ seats: z.string(),
200
+ groups: z.string(),
201
+ apiKeys: z.string(),
202
+ rateLimitPerSecond: z.number()
203
+ });
204
+ var getWorkspaceUsageOutputSchema = z.union([
205
+ withAgentOnlyFields({
206
+ usage: workspaceUsageEntitySchema
207
+ }),
208
+ agentAdminErrorResultSchema
209
+ ]);
210
+
5
211
  // src/eve/tool-reply-guidance.ts
6
212
  var TOOL_REPLY_GUIDANCE_FIELD = "replyGuidance";
7
213
  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).";
@@ -12,10 +218,28 @@ function withReplyGuidance(result, guidance) {
12
218
  };
13
219
  }
14
220
 
221
+ // src/eve/tool-display-format.ts
222
+ function formatToolListResult(listKey, items, options) {
223
+ const ui = {
224
+ ...options.ui,
225
+ layout: "list",
226
+ rowsPath: listKey,
227
+ ...options.entity ? { entity: options.entity } : {},
228
+ ...options.present !== void 0 ? { present: options.present } : {}
229
+ };
230
+ return withUiHint(
231
+ withToolUi(
232
+ withReplyGuidance({ [listKey]: items }, options.replyGuidance),
233
+ ui
234
+ ),
235
+ "list"
236
+ );
237
+ }
238
+
15
239
  // src/eve/tools/catalog/search-products.ts
16
240
  var SEARCH_PRODUCTS_TOOL_NAME = "search_products";
17
- var searchProductsInputSchema = z.object({
18
- query: z.string().min(1).describe("Product name or SKU to search for.")
241
+ var searchProductsInputSchema = z2.object({
242
+ query: z2.string().min(1).describe("Product name or SKU to search for.")
19
243
  });
20
244
  var DEMO_PRODUCTS = [
21
245
  {
@@ -23,33 +247,44 @@ var DEMO_PRODUCTS = [
23
247
  name: "Wireless Keyboard",
24
248
  price: 79.99,
25
249
  currency: "USD",
26
- inStock: true
250
+ inStock: true,
251
+ url: "https://shop.example.com/products/sku-1001"
27
252
  },
28
253
  {
29
254
  id: "sku-2042",
30
255
  name: "USB-C Hub",
31
256
  price: 45.99,
32
257
  currency: "USD",
33
- inStock: true
258
+ inStock: true,
259
+ url: "https://shop.example.com/products/sku-2042"
34
260
  },
35
261
  {
36
262
  id: "sku-3308",
37
263
  name: "Monitor Stand",
38
264
  price: 129.99,
39
265
  currency: "USD",
40
- inStock: false
266
+ inStock: false,
267
+ url: "https://shop.example.com/products/sku-3308"
41
268
  }
42
269
  ];
43
270
  function defineSearchProductsTool() {
44
271
  return defineTool({
45
272
  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.",
46
273
  inputSchema: searchProductsInputSchema,
274
+ outputSchema: searchProductsOutputSchema,
47
275
  async execute({ query }) {
48
276
  const normalized = query.trim().toLowerCase();
49
277
  const items = DEMO_PRODUCTS.filter(
50
278
  (product) => product.name.toLowerCase().includes(normalized) || product.id.toLowerCase().includes(normalized)
51
279
  );
52
- return withReplyGuidance({ items: [...items] }, SEARCH_PRODUCTS_REPLY_GUIDANCE);
280
+ return formatToolListResult(
281
+ "items",
282
+ items.map((product) => ({ ...product })),
283
+ {
284
+ replyGuidance: SEARCH_PRODUCTS_REPLY_GUIDANCE,
285
+ entity: "product"
286
+ }
287
+ );
53
288
  }
54
289
  });
55
290
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/eve/tools/catalog/search-products.ts","../../../../src/eve/tool-reply-guidance.ts"],"sourcesContent":["import { defineTool } from \"eve/tools\";\nimport { z } from \"zod\";\nimport {\n SEARCH_PRODUCTS_REPLY_GUIDANCE,\n withReplyGuidance,\n} from \"../../tool-reply-guidance.js\";\n\nexport const SEARCH_PRODUCTS_TOOL_NAME = \"search_products\";\n\nexport const searchProductsInputSchema = z.object({\n query: z.string().min(1).describe(\"Product name or SKU to search for.\"),\n});\n\nconst DEMO_PRODUCTS = [\n {\n id: \"sku-1001\",\n name: \"Wireless Keyboard\",\n price: 79.99,\n currency: \"USD\",\n inStock: true,\n },\n {\n id: \"sku-2042\",\n name: \"USB-C Hub\",\n price: 45.99,\n currency: \"USD\",\n inStock: true,\n },\n {\n id: \"sku-3308\",\n name: \"Monitor Stand\",\n price: 129.99,\n currency: \"USD\",\n inStock: false,\n },\n] as const;\n\nexport function defineSearchProductsTool() {\n return defineTool({\n description:\n \"Search the product catalog and return matching items. \" +\n \"Results render in chat UI — do not restate product names, prices, or SKUs in your reply.\",\n inputSchema: searchProductsInputSchema,\n async execute({ query }) {\n const normalized = query.trim().toLowerCase();\n const items = DEMO_PRODUCTS.filter(\n (product) =>\n product.name.toLowerCase().includes(normalized) ||\n product.id.toLowerCase().includes(normalized)\n );\n\n return withReplyGuidance({ items: [...items] }, SEARCH_PRODUCTS_REPLY_GUIDANCE);\n },\n });\n}\n\nexport const searchProductsTool = defineSearchProductsTool();\n","import { TOOL_UI_HINT_FIELD } from \"./tool-ui-hint.js\";\n\n/** Field name agents read; dashboard widgets must ignore when rendering. */\nexport const TOOL_REPLY_GUIDANCE_FIELD = \"replyGuidance\" as const;\n\nexport const WHOAMI_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MY_ACCESS_REPLY_GUIDANCE =\n \"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 ≥ $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 — do not tell them to find an admin manually without offering delegation first.\";\n\nexport const CREATE_INBOX_TASK_REPLY_GUIDANCE =\n \"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.\";\n\nexport const SEARCH_PRODUCTS_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE =\n \"Team member details render in chat UI. Do not restate name, email, or role from the card. Only add next steps or policy context.\";\n\nexport const MANAGE_GROUPS_LIST_REPLY_GUIDANCE =\n \"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.\";\n\nexport const MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE =\n \"Group details render in chat UI. Do not restate fields already visible in the card. Only add next steps.\";\n\nexport const QUERY_TASKS_LIST_REPLY_GUIDANCE =\n \"Tasks render as a list card in chat. Do not restate task names, ids, or statuses from the list. Only add context not shown (e.g. filters applied, recommended next action).\";\n\nexport const QUERY_TASKS_DETAIL_REPLY_GUIDANCE =\n \"Task details render in chat UI. Do not restate fields already visible in the card. Only add analysis or next steps.\";\n\nexport const ASSIGN_TASKS_REPLY_GUIDANCE =\n \"Reassignment results render in chat UI. Do not restate task ids or assignee emails from the card. Only mention failures, partial success, or next steps.\";\n\nexport const REFUND_CHARGE_REPLY_GUIDANCE =\n \"Refund details render in chat UI. Do not restate charge id, amount, or status from the card. Only add policy context or next steps.\";\n\nexport const DEPLOY_RELEASE_REPLY_GUIDANCE =\n \"Deploy details render in chat UI. Do not restate service, version, or environment from the card. Only add rollout context or next steps.\";\n\nexport const GET_WEATHER_REPLY_GUIDANCE =\n \"Weather details render in chat UI. Do not restate city, condition, or temperature from the card. Only add conversational context if needed.\";\n\nexport const ADMIN_MUTATION_REPLY_GUIDANCE =\n \"The action result renders in chat UI. Do not restate fields already visible in the card. Confirm outcome briefly or add next steps only.\";\n\nexport type ToolResultWithReplyGuidance<T extends Record<string, unknown>> = T & {\n replyGuidance: string;\n};\n\n/** Attach model-facing narration hints to a tool execute result. */\nexport function withReplyGuidance<T extends Record<string, unknown>>(\n result: T,\n guidance: string\n): ToolResultWithReplyGuidance<T> {\n return {\n ...result,\n [TOOL_REPLY_GUIDANCE_FIELD]: guidance,\n };\n}\n\n/** Remove agent-only fields before showing raw JSON in the dashboard. */\nexport function stripAgentOnlyToolFields(output: unknown): unknown {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return output;\n }\n\n const record = { ...(output as Record<string, unknown>) };\n delete record[TOOL_REPLY_GUIDANCE_FIELD];\n delete record[TOOL_UI_HINT_FIELD];\n return record;\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS;;;ACEX,IAAM,4BAA4B;AAWlC,IAAM,iCACX;AAwCK,SAAS,kBACd,QACA,UACgC;AAChC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,yBAAyB,GAAG;AAAA,EAC/B;AACF;;;ADxDO,IAAM,4BAA4B;AAElC,IAAM,4BAA4B,EAAE,OAAO;AAAA,EAChD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oCAAoC;AACxE,CAAC;AAED,IAAM,gBAAgB;AAAA,EACpB;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AACF;AAEO,SAAS,2BAA2B;AACzC,SAAO,WAAW;AAAA,IAChB,aACE;AAAA,IAEF,aAAa;AAAA,IACb,MAAM,QAAQ,EAAE,MAAM,GAAG;AACvB,YAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,YAAM,QAAQ,cAAc;AAAA,QAC1B,CAAC,YACC,QAAQ,KAAK,YAAY,EAAE,SAAS,UAAU,KAC9C,QAAQ,GAAG,YAAY,EAAE,SAAS,UAAU;AAAA,MAChD;AAEA,aAAO,kBAAkB,EAAE,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,8BAA8B;AAAA,IAChF;AAAA,EACF,CAAC;AACH;AAEO,IAAM,qBAAqB,yBAAyB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/eve/tools/catalog/search-products.ts","../../../../src/eve/entity-schemas.ts","../../../../src/eve/tool-ui-hint.ts","../../../../src/eve/tool-result-ui-meta.ts","../../../../src/eve/tool-reply-guidance.ts","../../../../src/eve/tool-display-format.ts"],"sourcesContent":["import { defineTool } from \"eve/tools\";\nimport { z } from \"zod\";\nimport { searchProductsOutputSchema } from \"../../entity-schemas.js\";\nimport { formatToolListResult } from \"../../tool-display-format.js\";\nimport { SEARCH_PRODUCTS_REPLY_GUIDANCE } from \"../../tool-reply-guidance.js\";\n\nexport const SEARCH_PRODUCTS_TOOL_NAME = \"search_products\";\n\nexport const searchProductsInputSchema = z.object({\n query: z.string().min(1).describe(\"Product name or SKU to search for.\"),\n});\n\nconst DEMO_PRODUCTS = [\n {\n id: \"sku-1001\",\n name: \"Wireless Keyboard\",\n price: 79.99,\n currency: \"USD\",\n inStock: true,\n url: \"https://shop.example.com/products/sku-1001\",\n },\n {\n id: \"sku-2042\",\n name: \"USB-C Hub\",\n price: 45.99,\n currency: \"USD\",\n inStock: true,\n url: \"https://shop.example.com/products/sku-2042\",\n },\n {\n id: \"sku-3308\",\n name: \"Monitor Stand\",\n price: 129.99,\n currency: \"USD\",\n inStock: false,\n url: \"https://shop.example.com/products/sku-3308\",\n },\n] as const;\n\nexport function defineSearchProductsTool() {\n return defineTool({\n description:\n \"Search the product catalog and return matching items. \" +\n \"Results render in chat UI — do not restate product names, prices, or SKUs in your reply.\",\n inputSchema: searchProductsInputSchema,\n outputSchema: searchProductsOutputSchema,\n async execute({ query }) {\n const normalized = query.trim().toLowerCase();\n const items = DEMO_PRODUCTS.filter(\n (product) =>\n product.name.toLowerCase().includes(normalized) ||\n product.id.toLowerCase().includes(normalized)\n );\n\n return formatToolListResult(\n \"items\",\n items.map((product) => ({ ...product })),\n {\n replyGuidance: SEARCH_PRODUCTS_REPLY_GUIDANCE,\n entity: \"product\",\n }\n );\n },\n });\n}\n\nexport const searchProductsTool = defineSearchProductsTool();\n","import { z } from \"zod\";\nimport { TOOL_RESULT_UI_ENTITY_ID_RE } from \"./tool-result-ui-meta.js\";\n\n/** Tenant-relative inbox deep link for a task (matches dashboard inbox hrefs). */\nexport function buildTenantTaskUrl(\n tenantSlug: string,\n task: { id: string; type?: string | null; app?: string | null }\n): string {\n const q = new URLSearchParams();\n if (task.app && task.app !== \"default\") {\n q.set(\"app\", task.app);\n }\n if (task.type?.trim()) {\n q.set(\"type\", task.type.trim());\n }\n q.set(\"selected\", task.id);\n return `/${tenantSlug}/inbox?${q.toString()}`;\n}\n\n/** Tenant-relative group detail path (matches tenantGroup widget). */\nexport function buildTenantGroupUrl(tenantSlug: string, slug: string): string {\n return `/${tenantSlug}/team/groups/${slug}`;\n}\n\nexport const toolResultUiMetaSchema = z\n .object({\n present: z.boolean().optional(),\n entity: z.string().regex(TOOL_RESULT_UI_ENTITY_ID_RE).optional(),\n rowsPath: z.string().min(1).optional(),\n layout: z.enum([\"list\", \"chart\", \"table\"]).optional(),\n })\n .strict();\n\nconst agentOnlyFields = {\n replyGuidance: z.string().optional(),\n ui: toolResultUiMetaSchema.optional(),\n uiHint: z.enum([\"list\", \"chart\", \"table\"]).optional(),\n} as const;\n\nfunction withAgentOnlyFields<T extends z.ZodRawShape>(shape: T) {\n return z.object({\n ...shape,\n ...agentOnlyFields,\n });\n}\n\n/** Demo catalog product row (`search_products`). */\nexport const productEntityRowSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n price: z.number(),\n currency: z.string().min(1),\n inStock: z.boolean(),\n url: z.string().min(1),\n});\n\n/** Demo chart series point (`generate_random_chart`). */\nexport const metricPointEntityRowSchema = z\n .object({\n date: z.string().optional(),\n category: z.string().optional(),\n label: z.string().optional(),\n })\n .catchall(z.union([z.string(), z.number()]));\n\nexport const memberEntityRowSchema = z.object({\n name: z.string(),\n email: z.string(),\n role: z.string(),\n membershipKind: z.string(),\n profilePictureUrl: z.string().nullable(),\n});\n\nexport const taskEntityRowSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n status: z.string().min(1),\n type: z.string().nullable(),\n description: z.string().nullable(),\n validUntil: z.number(),\n createdAt: z.number(),\n url: z.string().min(1),\n threadPriority: z.string().nullable().optional(),\n});\n\nexport const groupEntityRowSchema = z.object({\n name: z.string().min(1),\n slug: z.string().min(1),\n description: z.string().nullable(),\n memberCount: z.number().nullable(),\n url: z.string().min(1),\n});\n\nexport const groupDetailEntitySchema = z.object({\n name: z.string().min(1),\n slug: z.string().min(1),\n description: z.string().nullable(),\n url: z.string().min(1),\n members: z.array(\n z.object({\n name: z.string(),\n email: z.string(),\n profilePictureUrl: z.string().nullable(),\n })\n ),\n});\n\n/** Assign-task / status list row — always includes task inbox url. */\nexport const statusEntityRowSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n status: z.string().min(1),\n url: z.string().min(1),\n type: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n});\n\nexport const agentAdminErrorResultSchema = z.object({\n ok: z.literal(false),\n status: z.number().optional(),\n message: z.string(),\n response: z.unknown().optional(),\n});\n\nexport const agentAdminMutationResultSchema = z\n .object({\n ...agentOnlyFields,\n })\n .passthrough();\n\nexport const searchProductsOutputSchema = withAgentOnlyFields({\n items: z.array(productEntityRowSchema),\n});\n\nexport const generateRandomChartOutputSchema = withAgentOnlyFields({\n title: z.string().min(1),\n axis: z.enum([\"time\", \"category\"]),\n series: z.array(metricPointEntityRowSchema),\n});\n\n/** Demo generated image (`generate_image`) — bytes live in Convex `_storage`. */\nexport const generateImageOutputSchema = withAgentOnlyFields({\n prompt: z.string().min(1),\n mediaType: z.string().min(1),\n model: z.string().min(1),\n storageId: z.string().min(1),\n url: z.string().min(1),\n /** @deprecated Legacy sessions only — prefer storageId/url. */\n base64: z.string().min(1).optional(),\n});\n\nexport const manageTeamMembersListOutputSchema = withAgentOnlyFields({\n members: z.array(memberEntityRowSchema),\n});\n\nexport const manageTeamMembersDetailOutputSchema = withAgentOnlyFields(\n memberEntityRowSchema.shape\n);\n\nexport const manageTeamMembersOutputSchema = z.union([\n manageTeamMembersListOutputSchema,\n manageTeamMembersDetailOutputSchema,\n agentAdminMutationResultSchema,\n agentAdminErrorResultSchema,\n]);\n\nexport const manageGroupsListOutputSchema = withAgentOnlyFields({\n groups: z.array(groupEntityRowSchema),\n});\n\nexport const manageGroupsDetailOutputSchema = withAgentOnlyFields(\n groupDetailEntitySchema.shape\n);\n\nexport const manageGroupsSummaryOutputSchema = withAgentOnlyFields(\n groupEntityRowSchema.shape\n);\n\nexport const manageGroupsOutputSchema = z.union([\n manageGroupsListOutputSchema,\n manageGroupsDetailOutputSchema,\n manageGroupsSummaryOutputSchema,\n agentAdminMutationResultSchema,\n agentAdminErrorResultSchema,\n]);\n\nexport const queryTasksListOutputSchema = withAgentOnlyFields({\n items: z.array(taskEntityRowSchema),\n nextCursor: z.string().nullable().optional(),\n});\n\nexport const queryTasksDetailOutputSchema = withAgentOnlyFields({\n id: z.string().nullable(),\n status: z.string().nullable(),\n type: z.string().nullable(),\n name: z.string().nullable(),\n description: z.string().nullable(),\n validUntil: z.number().nullable(),\n createdAt: z.number().nullable(),\n url: z.string().min(1).nullable(),\n});\n\nexport const queryTasksOutputSchema = z.union([\n queryTasksListOutputSchema,\n queryTasksDetailOutputSchema,\n agentAdminErrorResultSchema,\n]);\n\nexport const assignTasksOutputSchema = z.union([\n withAgentOnlyFields({\n results: z.array(statusEntityRowSchema),\n }),\n agentAdminErrorResultSchema,\n]);\n\nexport const workspaceUsageEntitySchema = z.object({\n workspace: z.string(),\n plan: z.string(),\n planType: z.string(),\n trialState: z.string(),\n daysRemaining: z.number().nullable(),\n isPaidPro: z.boolean(),\n subscriptionStatus: z.string(),\n tasksToday: z.string(),\n tasksResetAt: z.string(),\n openTasks: z.number(),\n totalTasks: z.number(),\n seats: z.string(),\n groups: z.string(),\n apiKeys: z.string(),\n rateLimitPerSecond: z.number(),\n});\n\nexport const getWorkspaceUsageOutputSchema = z.union([\n withAgentOnlyFields({\n usage: workspaceUsageEntitySchema,\n }),\n agentAdminErrorResultSchema,\n]);\n\nexport type ProductEntityRow = z.infer<typeof productEntityRowSchema>;\nexport type MetricPointEntityRow = z.infer<typeof metricPointEntityRowSchema>;\nexport type MemberEntityRow = z.infer<typeof memberEntityRowSchema>;\nexport type TaskEntityRow = z.infer<typeof taskEntityRowSchema>;\nexport type GroupEntityRow = z.infer<typeof groupEntityRowSchema>;\nexport type StatusEntityRow = z.infer<typeof statusEntityRowSchema>;\n","/** Field name for optional layout hints on tool execute results. */\nexport const TOOL_UI_HINT_FIELD = \"uiHint\" as const;\n\n/** Top-level layout hint for RobotRock TRL rendering. Optional — omit to let the dashboard infer. */\nexport type ToolUiHint = \"list\" | \"chart\" | \"table\";\n\nconst TOOL_UI_HINTS = new Set<ToolUiHint>([\"list\", \"chart\", \"table\"]);\n\nexport function isToolUiHint(value: unknown): value is ToolUiHint {\n return typeof value === \"string\" && TOOL_UI_HINTS.has(value as ToolUiHint);\n}\n\n/** Attach an optional layout hint to a tool execute result. */\nexport function withUiHint<T extends Record<string, unknown>>(\n result: T,\n hint: ToolUiHint\n): T & { uiHint: ToolUiHint } {\n return {\n ...result,\n [TOOL_UI_HINT_FIELD]: hint,\n };\n}\n\n/** Read a validated layout hint from tool output; unknown values are ignored. */\nexport function extractToolUiHint(output: unknown): ToolUiHint | undefined {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return undefined;\n }\n\n const hint = (output as Record<string, unknown>)[TOOL_UI_HINT_FIELD];\n return isToolUiHint(hint) ? hint : undefined;\n}\n","import { isToolUiHint, type ToolUiHint } from \"./tool-ui-hint.js\";\n\n/** Nested agent-only UI metadata on tool execute results. */\nexport const TOOL_UI_FIELD = \"ui\" as const;\n\n/** Free-form entity id: lowercase slug used as cache key (e.g. member, task). */\nexport const TOOL_RESULT_UI_ENTITY_ID_RE = /^[a-z][a-z0-9_]{0,63}$/;\n\n/**\n * Recommended entity ids for RobotRock tools. Not exhaustive — any valid slug is accepted.\n * @deprecated Prefer free-form `ui.entity` strings; this list is documentation only.\n */\nexport const TOOL_RESULT_UI_ENTITIES = [\n \"product\",\n \"member\",\n \"task\",\n \"group\",\n \"status\",\n \"object\",\n] as const;\n\nexport type ToolResultUiEntity = string;\n\n/** Render layout hint (not a cached atom). Derived from uiHint / legacy pattern. */\nexport type ToolResultUiLayout = ToolUiHint;\n\nexport type ToolResultUiMeta = {\n /** Hybrid presentation override: true = always show card, false = never. */\n present?: boolean;\n /** Entity id for row layout cache (free-form slug). */\n entity?: ToolResultUiEntity;\n /** Path to row array for list cards (e.g. \"rows\", \"items\"). */\n rowsPath?: string;\n /** Viz/collection layout hint — chart | table | list. Not a pattern atom. */\n layout?: ToolResultUiLayout;\n};\n\nexport function isToolResultUiEntityId(value: unknown): value is string {\n return typeof value === \"string\" && TOOL_RESULT_UI_ENTITY_ID_RE.test(value);\n}\n\n/** @deprecated Use isToolResultUiEntityId. */\nexport function isToolResultUiEntity(value: unknown): value is string {\n return isToolResultUiEntityId(value);\n}\n\n/** Map legacy top-level uiHint into a layout hint. */\nexport function uiHintToLayout(hint: ToolUiHint): ToolResultUiLayout {\n return hint;\n}\n\n/**\n * Map legacy `ui.pattern` values into layout / rowsPath behavior.\n * Patterns are no longer cached atoms.\n */\nexport function legacyPatternToLayout(\n pattern: string\n): ToolResultUiLayout | undefined {\n switch (pattern) {\n case \"chart\":\n return \"chart\";\n case \"table\":\n return \"table\";\n case \"list\":\n case \"query\":\n return \"list\";\n default:\n return undefined;\n }\n}\n\nfunction readPresent(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction readRowsPath(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readEntity(value: unknown): string | undefined {\n if (!isToolResultUiEntityId(value)) {\n return undefined;\n }\n return value;\n}\n\n/** Read and validate nested `ui` metadata (+ legacy uiHint / pattern → layout). */\nexport function extractToolResultUiMeta(\n output: unknown\n): ToolResultUiMeta | undefined {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return undefined;\n }\n\n const record = output as Record<string, unknown>;\n const rawUi = record[TOOL_UI_FIELD];\n const meta: ToolResultUiMeta = {};\n\n if (typeof rawUi === \"object\" && rawUi !== null && !Array.isArray(rawUi)) {\n const ui = rawUi as Record<string, unknown>;\n const present = readPresent(ui.present);\n if (present !== undefined) {\n meta.present = present;\n }\n const entity = readEntity(ui.entity);\n if (entity) {\n meta.entity = entity;\n }\n const rowsPath = readRowsPath(ui.rowsPath);\n if (rowsPath) {\n meta.rowsPath = rowsPath;\n }\n if (isToolUiHint(ui.layout)) {\n meta.layout = ui.layout;\n } else if (typeof ui.pattern === \"string\") {\n // Legacy nested pattern → layout hint only.\n const fromPattern = legacyPatternToLayout(ui.pattern);\n if (fromPattern) {\n meta.layout = fromPattern;\n }\n }\n }\n\n if (!meta.layout && isToolUiHint(record.uiHint)) {\n meta.layout = uiHintToLayout(record.uiHint);\n }\n\n if (\n meta.present === undefined &&\n meta.entity === undefined &&\n meta.rowsPath === undefined &&\n meta.layout === undefined\n ) {\n return undefined;\n }\n\n return meta;\n}\n\n/** Attach nested UI metadata to a tool execute result. */\nexport function withToolUi<T extends Record<string, unknown>>(\n result: T,\n ui: ToolResultUiMeta\n): T & { ui: ToolResultUiMeta } {\n const existing =\n typeof result[TOOL_UI_FIELD] === \"object\" &&\n result[TOOL_UI_FIELD] !== null &&\n !Array.isArray(result[TOOL_UI_FIELD])\n ? (result[TOOL_UI_FIELD] as ToolResultUiMeta)\n : {};\n\n return {\n ...result,\n [TOOL_UI_FIELD]: {\n ...existing,\n ...ui,\n },\n };\n}\n","import { TOOL_UI_FIELD } from \"./tool-result-ui-meta.js\";\nimport { TOOL_UI_HINT_FIELD } from \"./tool-ui-hint.js\";\n\n/** Field name agents read; dashboard widgets must ignore when rendering. */\nexport const TOOL_REPLY_GUIDANCE_FIELD = \"replyGuidance\" as const;\n\nexport const WHOAMI_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MY_ACCESS_REPLY_GUIDANCE =\n \"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 ≥ $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 — do not tell them to find an admin manually without offering delegation first.\";\n\nexport const GET_WORKSPACE_USAGE_REPLY_GUIDANCE =\n \"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.\";\n\nexport const CREATE_INBOX_TASK_REPLY_GUIDANCE =\n \"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.\";\n\nexport const SEARCH_PRODUCTS_REPLY_GUIDANCE =\n \"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).\";\n\nexport const GENERATE_RANDOM_CHART_REPLY_GUIDANCE =\n \"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).\";\n\nexport const GENERATE_IMAGE_REPLY_GUIDANCE =\n \"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.\";\n\nexport const MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE =\n \"Team member details render in chat UI. Do not restate name, email, or role from the card. Only add next steps or policy context.\";\n\nexport const MANAGE_GROUPS_LIST_REPLY_GUIDANCE =\n \"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.\";\n\nexport const MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE =\n \"Group details render in chat UI. Do not restate fields already visible in the card. Only add next steps.\";\n\nexport const QUERY_TASKS_LIST_REPLY_GUIDANCE =\n \"Tasks render as a list card in chat. Do not restate task names, ids, or statuses from the list. Only add context not shown (e.g. filters applied, recommended next action).\";\n\nexport const QUERY_TASKS_DETAIL_REPLY_GUIDANCE =\n \"Task details render in chat UI. Do not restate fields already visible in the card. Only add analysis or next steps.\";\n\nexport const ASSIGN_TASKS_REPLY_GUIDANCE =\n \"Reassignment results render in chat UI. Do not restate task ids or assignee emails from the card. Only mention failures, partial success, or next steps.\";\n\nexport const REFUND_CHARGE_REPLY_GUIDANCE =\n \"Refund details render in chat UI. Do not restate charge id, amount, or status from the card. Only add policy context or next steps.\";\n\nexport const DEPLOY_RELEASE_REPLY_GUIDANCE =\n \"Deploy details render in chat UI. Do not restate service, version, or environment from the card. Only add rollout context or next steps.\";\n\nexport const GET_WEATHER_REPLY_GUIDANCE =\n \"Weather details render in chat UI. Do not restate city, condition, or temperature from the card. Only add conversational context if needed.\";\n\nexport const ADMIN_MUTATION_REPLY_GUIDANCE =\n \"The action result renders in chat UI. Do not restate fields already visible in the card. Confirm outcome briefly or add next steps only.\";\n\nexport type ToolResultWithReplyGuidance<T extends Record<string, unknown>> = T & {\n replyGuidance: string;\n};\n\n/** Attach model-facing narration hints to a tool execute result. */\nexport function withReplyGuidance<T extends Record<string, unknown>>(\n result: T,\n guidance: string\n): ToolResultWithReplyGuidance<T> {\n return {\n ...result,\n [TOOL_REPLY_GUIDANCE_FIELD]: guidance,\n };\n}\n\n/** Remove agent-only fields before showing raw JSON in the dashboard. */\nexport function stripAgentOnlyToolFields(output: unknown): unknown {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return output;\n }\n\n const record = { ...(output as Record<string, unknown>) };\n delete record[TOOL_REPLY_GUIDANCE_FIELD];\n delete record[TOOL_UI_HINT_FIELD];\n delete record[TOOL_UI_FIELD];\n return record;\n}\n","import { withReplyGuidance } from \"./tool-reply-guidance.js\";\nimport {\n withToolUi,\n type ToolResultUiEntity,\n type ToolResultUiMeta,\n} from \"./tool-result-ui-meta.js\";\nimport { withUiHint, type ToolUiHint } from \"./tool-ui-hint.js\";\n\nexport type FormatToolObjectResultOptions = {\n replyGuidance: string;\n /** @deprecated Prefer `ui.layout`. Mapped for backward compatibility. */\n uiHint?: ToolUiHint;\n ui?: ToolResultUiMeta;\n};\n\nexport type FormatToolListResultOptions = {\n replyGuidance: string;\n entity?: ToolResultUiEntity;\n present?: boolean;\n ui?: Omit<ToolResultUiMeta, \"rowsPath\" | \"layout\">;\n};\n\nexport type FormatToolQueryResultOptions = {\n replyGuidance: string;\n entity?: ToolResultUiEntity;\n present?: boolean;\n rowsPath?: string;\n ui?: ToolResultUiMeta;\n};\n\ntype WithReplyGuidance<T> = T & { replyGuidance: string };\ntype WithUiMeta<T> = T & { ui: ToolResultUiMeta };\ntype WithUiHintField<T> = T & { uiHint: ToolUiHint };\n\n/** Attach agent narration hints to plain tool JSON. No display/ui envelope. */\nexport function formatToolObjectResult<T extends Record<string, unknown>>(\n data: T,\n options: FormatToolObjectResultOptions\n): WithReplyGuidance<T> &\n Partial<WithUiMeta<T>> &\n Partial<WithUiHintField<T>> {\n let result: Record<string, unknown> = withReplyGuidance(\n data,\n options.replyGuidance\n );\n if (options.ui) {\n result = withToolUi(result, options.ui);\n }\n if (options.uiHint) {\n result = withUiHint(result, options.uiHint);\n }\n return result as WithReplyGuidance<T> &\n Partial<WithUiMeta<T>> &\n Partial<WithUiHintField<T>>;\n}\n\n/** Wrap an array field as plain tool JSON with reply guidance and list layout hint.\n *\n * Include `url` on each item when you know a navigable link — the dashboard\n * renders clickable Item rows. Use `attachments` / `files` / `documents` keys\n * for file downloads (Attachment layout). Set `entity` so the dashboard caches\n * a reusable row layout under that name.\n */\nexport function formatToolListResult<\n const K extends string,\n T extends Record<string, unknown>,\n>(\n listKey: K,\n items: T[],\n options: FormatToolListResultOptions\n): WithReplyGuidance<Record<K, T[]>> &\n WithUiMeta<Record<K, T[]>> &\n WithUiHintField<Record<K, T[]>> {\n const ui: ToolResultUiMeta = {\n ...options.ui,\n layout: \"list\",\n rowsPath: listKey,\n ...(options.entity ? { entity: options.entity } : {}),\n ...(options.present !== undefined ? { present: options.present } : {}),\n };\n\n return withUiHint(\n withToolUi(\n withReplyGuidance({ [listKey]: items } as Record<K, T[]>, options.replyGuidance),\n ui\n ),\n \"list\"\n ) as WithReplyGuidance<Record<K, T[]>> &\n WithUiMeta<Record<K, T[]>> &\n WithUiHintField<Record<K, T[]>>;\n}\n\n/** Format a query-style result: shared meta fields + typed row array. */\nexport function formatToolQueryResult<\n M extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n meta: M,\n rows: T[],\n options: FormatToolQueryResultOptions\n): WithReplyGuidance<M & Record<string, T[]>> & WithUiMeta<M & Record<string, T[]>> {\n const rowsPath = options.rowsPath ?? options.ui?.rowsPath ?? \"rows\";\n const ui: ToolResultUiMeta = {\n ...options.ui,\n layout: options.ui?.layout ?? \"list\",\n rowsPath,\n ...(options.entity ? { entity: options.entity } : {}),\n ...(options.present !== undefined ? { present: options.present } : {}),\n };\n\n return withToolUi(\n withReplyGuidance(\n {\n ...meta,\n [rowsPath]: rows,\n } as M & Record<string, T[]>,\n options.replyGuidance\n ),\n ui\n ) as WithReplyGuidance<M & Record<string, T[]>> &\n WithUiMeta<M & Record<string, T[]>>;\n}\n\nexport function isAgentAdminErrorResult(\n result: unknown\n): result is { ok: false; message: string } {\n return (\n typeof result === \"object\" &&\n result !== null &&\n (result as { ok?: unknown }).ok === false &&\n typeof (result as { message?: unknown }).message === \"string\"\n );\n}\n"],"mappings":"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","names":["z","z"]}
@@ -3,5 +3,6 @@ export { MY_ACCESS_TOOL_NAME, defineMyAccessTool, myAccessInputSchema, myAccessT
3
3
  import 'eve/tools';
4
4
  import '../../../tenant-DmN0MMyC.js';
5
5
  import 'eve/context';
6
- import '../../../tool-reply-guidance-C3qrT1In.js';
6
+ import '../../../tool-reply-guidance-CJko9liH.js';
7
7
  import 'zod';
8
+ import '../../../tool-result-ui-meta-KT0VafEO.js';
@@ -72,10 +72,23 @@ function withUiHint(result, hint) {
72
72
  };
73
73
  }
74
74
 
75
+ // src/eve/tool-result-ui-meta.ts
76
+ var TOOL_UI_FIELD = "ui";
77
+ function withToolUi(result, ui) {
78
+ const existing = typeof result[TOOL_UI_FIELD] === "object" && result[TOOL_UI_FIELD] !== null && !Array.isArray(result[TOOL_UI_FIELD]) ? result[TOOL_UI_FIELD] : {};
79
+ return {
80
+ ...result,
81
+ [TOOL_UI_FIELD]: {
82
+ ...existing,
83
+ ...ui
84
+ }
85
+ };
86
+ }
87
+
75
88
  // src/eve/tool-reply-guidance.ts
76
89
  var TOOL_REPLY_GUIDANCE_FIELD = "replyGuidance";
77
90
  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).";
78
- 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.";
91
+ 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.";
79
92
  function withReplyGuidance(result, guidance) {
80
93
  return {
81
94
  ...result,
@@ -127,11 +140,17 @@ import { z as z2 } from "zod";
127
140
 
128
141
  // src/eve/tool-display-format.ts
129
142
  function formatToolObjectResult(data, options) {
130
- const withGuidance = withReplyGuidance(data, options.replyGuidance);
143
+ let result = withReplyGuidance(
144
+ data,
145
+ options.replyGuidance
146
+ );
147
+ if (options.ui) {
148
+ result = withToolUi(result, options.ui);
149
+ }
131
150
  if (options.uiHint) {
132
- return withUiHint(withGuidance, options.uiHint);
151
+ result = withUiHint(result, options.uiHint);
133
152
  }
134
- return withGuidance;
153
+ return result;
135
154
  }
136
155
 
137
156
  // src/eve/tools/identity/format-my-access.ts
@@ -151,7 +170,8 @@ function formatMyAccessResult(input) {
151
170
  }
152
171
  },
153
172
  {
154
- replyGuidance: MY_ACCESS_REPLY_GUIDANCE
173
+ replyGuidance: MY_ACCESS_REPLY_GUIDANCE,
174
+ ui: { entity: "access" }
155
175
  }
156
176
  );
157
177
  }
@@ -169,7 +189,7 @@ function tenantCapabilities(isAdmin) {
169
189
  }
170
190
  function defineMyAccessTool() {
171
191
  return defineTool2({
172
- 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.",
192
+ 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.",
173
193
  inputSchema: myAccessInputSchema,
174
194
  async execute(_input, ctx) {
175
195
  const caller = tryResolveTenantCaller(ctx);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/eve/tools/identity/whoami.ts","../../../../src/eve/agent/attributes.ts","../../../../src/eve/agent/tenant.ts","../../../../src/eve/tool-ui-hint.ts","../../../../src/eve/tool-reply-guidance.ts","../../../../src/eve/tools/identity/my-access.ts","../../../../src/eve/tool-display-format.ts","../../../../src/eve/tools/identity/format-my-access.ts"],"sourcesContent":["import { defineTool } from \"eve/tools\";\nimport { z } from \"zod\";\nimport { tryResolveTenantCaller } from \"../../agent/tenant.js\";\nimport {\n WHOAMI_REPLY_GUIDANCE,\n withReplyGuidance,\n} from \"../../tool-reply-guidance.js\";\n\nexport const WHOAMI_TOOL_NAME = \"whoami\";\n\nexport const whoamiInputSchema = z.object({});\n\nexport function defineWhoamiTool() {\n return defineTool({\n description:\n \"Return the authenticated RobotRock user, tenant, role, and group memberships for the current chat session. \" +\n \"The dashboard renders a profile card — do not repeat name, email, workspace, role, or groups in your reply; only add context not shown in the card.\",\n inputSchema: whoamiInputSchema,\n async execute(_input, ctx) {\n const caller = tryResolveTenantCaller(ctx);\n if (!caller) {\n return withReplyGuidance(\n {\n authenticated: false as const,\n message:\n \"No RobotRock user is attached to this session. Dashboard chat supplies user context via the Eve proxy.\",\n },\n \"Explain that no user is attached to this session. Do not invent identity details.\"\n );\n }\n\n return withReplyGuidance(\n {\n authenticated: true as const,\n userId: caller.userId,\n name: caller.name,\n email: caller.email,\n tenantSlug: caller.tenantSlug,\n role: caller.role,\n isAdmin: caller.isAdmin,\n groups: caller.groups.map((slug) => ({ slug })),\n ...(caller.workosUserId ? { workosUserId: caller.workosUserId } : {}),\n sessionId: ctx.session.id,\n },\n WHOAMI_REPLY_GUIDANCE\n );\n },\n });\n}\n\nexport const whoamiTool = defineWhoamiTool();\n","export function readStringAttribute(\n attributes: Readonly<Record<string, string | readonly string[]>> | undefined,\n key: string\n): string | undefined {\n const value = attributes?.[key];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n if (Array.isArray(value) && typeof value[0] === \"string\" && value[0].length > 0) {\n return value[0];\n }\n return undefined;\n}\n\nexport function readStringArrayAttribute(\n attributes: Readonly<Record<string, string | readonly string[]>> | undefined,\n key: string\n): string[] {\n const value = attributes?.[key];\n if (typeof value === \"string\" && value.length > 0) {\n return [value];\n }\n if (Array.isArray(value)) {\n return value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0\n );\n }\n return [];\n}\n\nexport function parseTenantRole(\n value: string | undefined\n): \"admin\" | \"member\" | null {\n if (value === \"admin\" || value === \"member\") {\n return value;\n }\n return null;\n}\n","import type { SessionContext } from \"eve/context\";\nimport {\n parseTenantRole,\n readStringArrayAttribute,\n readStringAttribute,\n} from \"./attributes.js\";\n\nexport type TenantRole = \"admin\" | \"member\";\n\nexport type TenantCaller = {\n userId: string;\n email: string;\n name: string;\n tenantSlug: string;\n connectionId?: string;\n chatId?: string;\n role: TenantRole;\n isAdmin: boolean;\n groups: string[];\n workosUserId?: string;\n};\n\n/** Resolve the authenticated RobotRock dashboard user for the current session. */\nexport function tryResolveTenantCaller(ctx: SessionContext): TenantCaller | null {\n const caller = ctx.session.auth.initiator ?? ctx.session.auth.current;\n if (caller?.principalType !== \"user\") {\n return null;\n }\n\n const email = readStringAttribute(caller.attributes, \"email\");\n const name = readStringAttribute(caller.attributes, \"name\");\n const tenantSlug =\n readStringAttribute(caller.attributes, \"tenantSlug\") ??\n readStringAttribute(caller.attributes, \"tenantId\");\n const role = parseTenantRole(readStringAttribute(caller.attributes, \"role\"));\n if (!email || !tenantSlug || !caller.principalId || !role) {\n return null;\n }\n\n const workosUserId = readStringAttribute(caller.attributes, \"workosUserId\");\n const connectionId = readStringAttribute(caller.attributes, \"connectionId\");\n const chatId = readStringAttribute(caller.attributes, \"chatId\");\n const groups = readStringArrayAttribute(caller.attributes, \"groups\");\n\n return {\n userId: caller.principalId,\n email,\n name: name ?? email.split(\"@\")[0] ?? email,\n tenantSlug,\n ...(connectionId ? { connectionId } : {}),\n ...(chatId ? { chatId } : {}),\n role,\n isAdmin: role === \"admin\",\n groups,\n ...(workosUserId ? { workosUserId } : {}),\n };\n}\n\n/** Like {@link tryResolveTenantCaller} but throws when the session has no user. */\nexport function requireTenantCaller(ctx: SessionContext): TenantCaller {\n const caller = tryResolveTenantCaller(ctx);\n if (!caller) {\n throw new Error(\"An authenticated RobotRock tenant user is required.\");\n }\n return caller;\n}\n\nexport function isAdminCaller(ctx: SessionContext): boolean {\n return tryResolveTenantCaller(ctx)?.isAdmin === true;\n}\n\n/** Require an authenticated tenant admin for the current session. */\nexport function requireAdminCaller(ctx: SessionContext): TenantCaller {\n const caller = requireTenantCaller(ctx);\n if (!caller.isAdmin) {\n throw new Error(\"Tenant admin access is required.\");\n }\n return caller;\n}\n","/** Field name for optional layout hints on tool execute results. */\nexport const TOOL_UI_HINT_FIELD = \"uiHint\" as const;\n\n/** Top-level layout hint for RobotRock TRL rendering. Optional — omit to let the dashboard infer. */\nexport type ToolUiHint = \"list\" | \"chart\" | \"table\";\n\nconst TOOL_UI_HINTS = new Set<ToolUiHint>([\"list\", \"chart\", \"table\"]);\n\nexport function isToolUiHint(value: unknown): value is ToolUiHint {\n return typeof value === \"string\" && TOOL_UI_HINTS.has(value as ToolUiHint);\n}\n\n/** Attach an optional layout hint to a tool execute result. */\nexport function withUiHint<T extends Record<string, unknown>>(\n result: T,\n hint: ToolUiHint\n): T & { uiHint: ToolUiHint } {\n return {\n ...result,\n [TOOL_UI_HINT_FIELD]: hint,\n };\n}\n\n/** Read a validated layout hint from tool output; unknown values are ignored. */\nexport function extractToolUiHint(output: unknown): ToolUiHint | undefined {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return undefined;\n }\n\n const hint = (output as Record<string, unknown>)[TOOL_UI_HINT_FIELD];\n return isToolUiHint(hint) ? hint : undefined;\n}\n","import { TOOL_UI_HINT_FIELD } from \"./tool-ui-hint.js\";\n\n/** Field name agents read; dashboard widgets must ignore when rendering. */\nexport const TOOL_REPLY_GUIDANCE_FIELD = \"replyGuidance\" as const;\n\nexport const WHOAMI_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MY_ACCESS_REPLY_GUIDANCE =\n \"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 ≥ $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 — do not tell them to find an admin manually without offering delegation first.\";\n\nexport const CREATE_INBOX_TASK_REPLY_GUIDANCE =\n \"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.\";\n\nexport const SEARCH_PRODUCTS_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE =\n \"Team member details render in chat UI. Do not restate name, email, or role from the card. Only add next steps or policy context.\";\n\nexport const MANAGE_GROUPS_LIST_REPLY_GUIDANCE =\n \"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.\";\n\nexport const MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE =\n \"Group details render in chat UI. Do not restate fields already visible in the card. Only add next steps.\";\n\nexport const QUERY_TASKS_LIST_REPLY_GUIDANCE =\n \"Tasks render as a list card in chat. Do not restate task names, ids, or statuses from the list. Only add context not shown (e.g. filters applied, recommended next action).\";\n\nexport const QUERY_TASKS_DETAIL_REPLY_GUIDANCE =\n \"Task details render in chat UI. Do not restate fields already visible in the card. Only add analysis or next steps.\";\n\nexport const ASSIGN_TASKS_REPLY_GUIDANCE =\n \"Reassignment results render in chat UI. Do not restate task ids or assignee emails from the card. Only mention failures, partial success, or next steps.\";\n\nexport const REFUND_CHARGE_REPLY_GUIDANCE =\n \"Refund details render in chat UI. Do not restate charge id, amount, or status from the card. Only add policy context or next steps.\";\n\nexport const DEPLOY_RELEASE_REPLY_GUIDANCE =\n \"Deploy details render in chat UI. Do not restate service, version, or environment from the card. Only add rollout context or next steps.\";\n\nexport const GET_WEATHER_REPLY_GUIDANCE =\n \"Weather details render in chat UI. Do not restate city, condition, or temperature from the card. Only add conversational context if needed.\";\n\nexport const ADMIN_MUTATION_REPLY_GUIDANCE =\n \"The action result renders in chat UI. Do not restate fields already visible in the card. Confirm outcome briefly or add next steps only.\";\n\nexport type ToolResultWithReplyGuidance<T extends Record<string, unknown>> = T & {\n replyGuidance: string;\n};\n\n/** Attach model-facing narration hints to a tool execute result. */\nexport function withReplyGuidance<T extends Record<string, unknown>>(\n result: T,\n guidance: string\n): ToolResultWithReplyGuidance<T> {\n return {\n ...result,\n [TOOL_REPLY_GUIDANCE_FIELD]: guidance,\n };\n}\n\n/** Remove agent-only fields before showing raw JSON in the dashboard. */\nexport function stripAgentOnlyToolFields(output: unknown): unknown {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return output;\n }\n\n const record = { ...(output as Record<string, unknown>) };\n delete record[TOOL_REPLY_GUIDANCE_FIELD];\n delete record[TOOL_UI_HINT_FIELD];\n return record;\n}\n","import { defineTool } from \"eve/tools\";\nimport { z } from \"zod\";\nimport { tryResolveTenantCaller } from \"../../agent/tenant.js\";\nimport {\n MY_ACCESS_REPLY_GUIDANCE,\n withReplyGuidance,\n} from \"../../tool-reply-guidance.js\";\nimport { formatMyAccessResult } from \"./format-my-access.js\";\n\n/** Eve tool slug — must match the agent tool filename `get_my_access.ts`. */\nexport const MY_ACCESS_TOOL_NAME = \"get_my_access\";\n\nexport const myAccessInputSchema = z.object({});\n\nfunction tenantCapabilities(isAdmin: boolean) {\n return {\n manageSettings: isAdmin,\n manageBilling: isAdmin,\n manageTeam: isAdmin,\n manageIntegrations: isAdmin,\n };\n}\n\nexport function defineMyAccessTool() {\n return defineTool({\n description:\n \"Check the authenticated user's tenant role, group memberships, and admin capabilities in RobotRock. \" +\n \"Always call this before tenant-admin tools (manage_team_members, manage_groups, query_tasks) in the same turn — \" +\n \"including read-only requests like listing users. Results render as a visible access tool card in chat like other tools; \" +\n \"do not restate role, groups, or capabilities in your reply.\",\n inputSchema: myAccessInputSchema,\n async execute(_input, ctx) {\n const caller = tryResolveTenantCaller(ctx);\n if (!caller) {\n return withReplyGuidance(\n {\n authenticated: false as const,\n message:\n \"No RobotRock user is attached to this session. Dashboard chat supplies user context via the Eve proxy.\",\n },\n \"Explain that no user is attached to this session. Do not invent access details.\"\n );\n }\n\n return formatMyAccessResult({\n tenantSlug: caller.tenantSlug,\n tenantRole: caller.role,\n isTenantAdmin: caller.isAdmin,\n groupSlugs: caller.groups,\n capabilities: tenantCapabilities(caller.isAdmin),\n email: caller.email,\n });\n },\n });\n}\n\nexport const myAccessTool = defineMyAccessTool();\n","import { withReplyGuidance } from \"./tool-reply-guidance.js\";\nimport { withUiHint, type ToolUiHint } from \"./tool-ui-hint.js\";\n\nexport type FormatToolObjectResultOptions = {\n replyGuidance: string;\n /** Optional layout hint for TRL rendering. Omit to let the dashboard infer. */\n uiHint?: ToolUiHint;\n};\n\nexport type FormatToolListResultOptions = {\n replyGuidance: string;\n};\n\n/** Attach agent narration hints to plain tool JSON. No display/ui envelope. */\nexport function formatToolObjectResult(\n data: Record<string, unknown>,\n options: FormatToolObjectResultOptions\n) {\n const withGuidance = withReplyGuidance(data, options.replyGuidance);\n if (options.uiHint) {\n return withUiHint(withGuidance, options.uiHint);\n }\n return withGuidance;\n}\n\n/** Wrap an array field as plain tool JSON with reply guidance and list layout hint. */\nexport function formatToolListResult(\n listKey: string,\n items: Record<string, unknown>[],\n options: FormatToolListResultOptions\n) {\n return withUiHint(\n withReplyGuidance({ [listKey]: items }, options.replyGuidance),\n \"list\"\n );\n}\n\nexport function isAgentAdminErrorResult(\n result: unknown\n): result is { ok: false; message: string } {\n return (\n typeof result === \"object\" &&\n result !== null &&\n (result as { ok?: unknown }).ok === false &&\n typeof (result as { message?: unknown }).message === \"string\"\n );\n}\n","import { formatToolObjectResult } from \"../../tool-display-format.js\";\nimport { MY_ACCESS_REPLY_GUIDANCE } from \"../../tool-reply-guidance.js\";\n\ntype MyAccessResultInput = {\n tenantSlug: string;\n tenantRole?: string;\n isTenantAdmin: boolean;\n groupSlugs: string[];\n capabilities: {\n manageSettings: boolean;\n manageBilling: boolean;\n manageTeam: boolean;\n manageIntegrations: boolean;\n };\n email?: string;\n};\n\nexport function formatMyAccessResult(input: MyAccessResultInput) {\n return formatToolObjectResult(\n {\n access: {\n workspace: input.tenantSlug,\n role: input.tenantRole ?? \"member\",\n tenantAdmin: input.isTenantAdmin,\n groups: input.groupSlugs.join(\", \") || \"—\",\n manageSettings: input.capabilities.manageSettings,\n manageBilling: input.capabilities.manageBilling,\n manageTeam: input.capabilities.manageTeam,\n manageIntegrations: input.capabilities.manageIntegrations,\n ...(input.email ? { email: input.email } : {}),\n },\n },\n {\n replyGuidance: MY_ACCESS_REPLY_GUIDANCE,\n }\n );\n}\n"],"mappings":"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","names":["defineTool","z","z","defineTool"]}
1
+ {"version":3,"sources":["../../../../src/eve/tools/identity/whoami.ts","../../../../src/eve/agent/attributes.ts","../../../../src/eve/agent/tenant.ts","../../../../src/eve/tool-ui-hint.ts","../../../../src/eve/tool-result-ui-meta.ts","../../../../src/eve/tool-reply-guidance.ts","../../../../src/eve/tools/identity/my-access.ts","../../../../src/eve/tool-display-format.ts","../../../../src/eve/tools/identity/format-my-access.ts"],"sourcesContent":["import { defineTool } from \"eve/tools\";\nimport { z } from \"zod\";\nimport { tryResolveTenantCaller } from \"../../agent/tenant.js\";\nimport {\n WHOAMI_REPLY_GUIDANCE,\n withReplyGuidance,\n} from \"../../tool-reply-guidance.js\";\n\nexport const WHOAMI_TOOL_NAME = \"whoami\";\n\nexport const whoamiInputSchema = z.object({});\n\nexport function defineWhoamiTool() {\n return defineTool({\n description:\n \"Return the authenticated RobotRock user, tenant, role, and group memberships for the current chat session. \" +\n \"The dashboard renders a profile card — do not repeat name, email, workspace, role, or groups in your reply; only add context not shown in the card.\",\n inputSchema: whoamiInputSchema,\n async execute(_input, ctx) {\n const caller = tryResolveTenantCaller(ctx);\n if (!caller) {\n return withReplyGuidance(\n {\n authenticated: false as const,\n message:\n \"No RobotRock user is attached to this session. Dashboard chat supplies user context via the Eve proxy.\",\n },\n \"Explain that no user is attached to this session. Do not invent identity details.\"\n );\n }\n\n return withReplyGuidance(\n {\n authenticated: true as const,\n userId: caller.userId,\n name: caller.name,\n email: caller.email,\n tenantSlug: caller.tenantSlug,\n role: caller.role,\n isAdmin: caller.isAdmin,\n groups: caller.groups.map((slug) => ({ slug })),\n ...(caller.workosUserId ? { workosUserId: caller.workosUserId } : {}),\n sessionId: ctx.session.id,\n },\n WHOAMI_REPLY_GUIDANCE\n );\n },\n });\n}\n\nexport const whoamiTool = defineWhoamiTool();\n","export function readStringAttribute(\n attributes: Readonly<Record<string, string | readonly string[]>> | undefined,\n key: string\n): string | undefined {\n const value = attributes?.[key];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n if (Array.isArray(value) && typeof value[0] === \"string\" && value[0].length > 0) {\n return value[0];\n }\n return undefined;\n}\n\nexport function readStringArrayAttribute(\n attributes: Readonly<Record<string, string | readonly string[]>> | undefined,\n key: string\n): string[] {\n const value = attributes?.[key];\n if (typeof value === \"string\" && value.length > 0) {\n return [value];\n }\n if (Array.isArray(value)) {\n return value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0\n );\n }\n return [];\n}\n\nexport function parseTenantRole(\n value: string | undefined\n): \"admin\" | \"member\" | null {\n if (value === \"admin\" || value === \"member\") {\n return value;\n }\n return null;\n}\n","import type { SessionContext } from \"eve/context\";\nimport {\n parseTenantRole,\n readStringArrayAttribute,\n readStringAttribute,\n} from \"./attributes.js\";\n\nexport type TenantRole = \"admin\" | \"member\";\n\nexport type TenantCaller = {\n userId: string;\n email: string;\n name: string;\n tenantSlug: string;\n connectionId?: string;\n chatId?: string;\n role: TenantRole;\n isAdmin: boolean;\n groups: string[];\n workosUserId?: string;\n};\n\n/** Resolve the authenticated RobotRock dashboard user for the current session. */\nexport function tryResolveTenantCaller(ctx: SessionContext): TenantCaller | null {\n const caller = ctx.session.auth.initiator ?? ctx.session.auth.current;\n if (caller?.principalType !== \"user\") {\n return null;\n }\n\n const email = readStringAttribute(caller.attributes, \"email\");\n const name = readStringAttribute(caller.attributes, \"name\");\n const tenantSlug =\n readStringAttribute(caller.attributes, \"tenantSlug\") ??\n readStringAttribute(caller.attributes, \"tenantId\");\n const role = parseTenantRole(readStringAttribute(caller.attributes, \"role\"));\n if (!email || !tenantSlug || !caller.principalId || !role) {\n return null;\n }\n\n const workosUserId = readStringAttribute(caller.attributes, \"workosUserId\");\n const connectionId = readStringAttribute(caller.attributes, \"connectionId\");\n const chatId = readStringAttribute(caller.attributes, \"chatId\");\n const groups = readStringArrayAttribute(caller.attributes, \"groups\");\n\n return {\n userId: caller.principalId,\n email,\n name: name ?? email.split(\"@\")[0] ?? email,\n tenantSlug,\n ...(connectionId ? { connectionId } : {}),\n ...(chatId ? { chatId } : {}),\n role,\n isAdmin: role === \"admin\",\n groups,\n ...(workosUserId ? { workosUserId } : {}),\n };\n}\n\n/** Like {@link tryResolveTenantCaller} but throws when the session has no user. */\nexport function requireTenantCaller(ctx: SessionContext): TenantCaller {\n const caller = tryResolveTenantCaller(ctx);\n if (!caller) {\n throw new Error(\"An authenticated RobotRock tenant user is required.\");\n }\n return caller;\n}\n\nexport function isAdminCaller(ctx: SessionContext): boolean {\n return tryResolveTenantCaller(ctx)?.isAdmin === true;\n}\n\n/** Require an authenticated tenant admin for the current session. */\nexport function requireAdminCaller(ctx: SessionContext): TenantCaller {\n const caller = requireTenantCaller(ctx);\n if (!caller.isAdmin) {\n throw new Error(\"Tenant admin access is required.\");\n }\n return caller;\n}\n","/** Field name for optional layout hints on tool execute results. */\nexport const TOOL_UI_HINT_FIELD = \"uiHint\" as const;\n\n/** Top-level layout hint for RobotRock TRL rendering. Optional — omit to let the dashboard infer. */\nexport type ToolUiHint = \"list\" | \"chart\" | \"table\";\n\nconst TOOL_UI_HINTS = new Set<ToolUiHint>([\"list\", \"chart\", \"table\"]);\n\nexport function isToolUiHint(value: unknown): value is ToolUiHint {\n return typeof value === \"string\" && TOOL_UI_HINTS.has(value as ToolUiHint);\n}\n\n/** Attach an optional layout hint to a tool execute result. */\nexport function withUiHint<T extends Record<string, unknown>>(\n result: T,\n hint: ToolUiHint\n): T & { uiHint: ToolUiHint } {\n return {\n ...result,\n [TOOL_UI_HINT_FIELD]: hint,\n };\n}\n\n/** Read a validated layout hint from tool output; unknown values are ignored. */\nexport function extractToolUiHint(output: unknown): ToolUiHint | undefined {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return undefined;\n }\n\n const hint = (output as Record<string, unknown>)[TOOL_UI_HINT_FIELD];\n return isToolUiHint(hint) ? hint : undefined;\n}\n","import { isToolUiHint, type ToolUiHint } from \"./tool-ui-hint.js\";\n\n/** Nested agent-only UI metadata on tool execute results. */\nexport const TOOL_UI_FIELD = \"ui\" as const;\n\n/** Free-form entity id: lowercase slug used as cache key (e.g. member, task). */\nexport const TOOL_RESULT_UI_ENTITY_ID_RE = /^[a-z][a-z0-9_]{0,63}$/;\n\n/**\n * Recommended entity ids for RobotRock tools. Not exhaustive — any valid slug is accepted.\n * @deprecated Prefer free-form `ui.entity` strings; this list is documentation only.\n */\nexport const TOOL_RESULT_UI_ENTITIES = [\n \"product\",\n \"member\",\n \"task\",\n \"group\",\n \"status\",\n \"object\",\n] as const;\n\nexport type ToolResultUiEntity = string;\n\n/** Render layout hint (not a cached atom). Derived from uiHint / legacy pattern. */\nexport type ToolResultUiLayout = ToolUiHint;\n\nexport type ToolResultUiMeta = {\n /** Hybrid presentation override: true = always show card, false = never. */\n present?: boolean;\n /** Entity id for row layout cache (free-form slug). */\n entity?: ToolResultUiEntity;\n /** Path to row array for list cards (e.g. \"rows\", \"items\"). */\n rowsPath?: string;\n /** Viz/collection layout hint — chart | table | list. Not a pattern atom. */\n layout?: ToolResultUiLayout;\n};\n\nexport function isToolResultUiEntityId(value: unknown): value is string {\n return typeof value === \"string\" && TOOL_RESULT_UI_ENTITY_ID_RE.test(value);\n}\n\n/** @deprecated Use isToolResultUiEntityId. */\nexport function isToolResultUiEntity(value: unknown): value is string {\n return isToolResultUiEntityId(value);\n}\n\n/** Map legacy top-level uiHint into a layout hint. */\nexport function uiHintToLayout(hint: ToolUiHint): ToolResultUiLayout {\n return hint;\n}\n\n/**\n * Map legacy `ui.pattern` values into layout / rowsPath behavior.\n * Patterns are no longer cached atoms.\n */\nexport function legacyPatternToLayout(\n pattern: string\n): ToolResultUiLayout | undefined {\n switch (pattern) {\n case \"chart\":\n return \"chart\";\n case \"table\":\n return \"table\";\n case \"list\":\n case \"query\":\n return \"list\";\n default:\n return undefined;\n }\n}\n\nfunction readPresent(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction readRowsPath(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readEntity(value: unknown): string | undefined {\n if (!isToolResultUiEntityId(value)) {\n return undefined;\n }\n return value;\n}\n\n/** Read and validate nested `ui` metadata (+ legacy uiHint / pattern → layout). */\nexport function extractToolResultUiMeta(\n output: unknown\n): ToolResultUiMeta | undefined {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return undefined;\n }\n\n const record = output as Record<string, unknown>;\n const rawUi = record[TOOL_UI_FIELD];\n const meta: ToolResultUiMeta = {};\n\n if (typeof rawUi === \"object\" && rawUi !== null && !Array.isArray(rawUi)) {\n const ui = rawUi as Record<string, unknown>;\n const present = readPresent(ui.present);\n if (present !== undefined) {\n meta.present = present;\n }\n const entity = readEntity(ui.entity);\n if (entity) {\n meta.entity = entity;\n }\n const rowsPath = readRowsPath(ui.rowsPath);\n if (rowsPath) {\n meta.rowsPath = rowsPath;\n }\n if (isToolUiHint(ui.layout)) {\n meta.layout = ui.layout;\n } else if (typeof ui.pattern === \"string\") {\n // Legacy nested pattern → layout hint only.\n const fromPattern = legacyPatternToLayout(ui.pattern);\n if (fromPattern) {\n meta.layout = fromPattern;\n }\n }\n }\n\n if (!meta.layout && isToolUiHint(record.uiHint)) {\n meta.layout = uiHintToLayout(record.uiHint);\n }\n\n if (\n meta.present === undefined &&\n meta.entity === undefined &&\n meta.rowsPath === undefined &&\n meta.layout === undefined\n ) {\n return undefined;\n }\n\n return meta;\n}\n\n/** Attach nested UI metadata to a tool execute result. */\nexport function withToolUi<T extends Record<string, unknown>>(\n result: T,\n ui: ToolResultUiMeta\n): T & { ui: ToolResultUiMeta } {\n const existing =\n typeof result[TOOL_UI_FIELD] === \"object\" &&\n result[TOOL_UI_FIELD] !== null &&\n !Array.isArray(result[TOOL_UI_FIELD])\n ? (result[TOOL_UI_FIELD] as ToolResultUiMeta)\n : {};\n\n return {\n ...result,\n [TOOL_UI_FIELD]: {\n ...existing,\n ...ui,\n },\n };\n}\n","import { TOOL_UI_FIELD } from \"./tool-result-ui-meta.js\";\nimport { TOOL_UI_HINT_FIELD } from \"./tool-ui-hint.js\";\n\n/** Field name agents read; dashboard widgets must ignore when rendering. */\nexport const TOOL_REPLY_GUIDANCE_FIELD = \"replyGuidance\" as const;\n\nexport const WHOAMI_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MY_ACCESS_REPLY_GUIDANCE =\n \"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 ≥ $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 — do not tell them to find an admin manually without offering delegation first.\";\n\nexport const GET_WORKSPACE_USAGE_REPLY_GUIDANCE =\n \"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.\";\n\nexport const CREATE_INBOX_TASK_REPLY_GUIDANCE =\n \"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.\";\n\nexport const SEARCH_PRODUCTS_REPLY_GUIDANCE =\n \"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).\";\n\nexport const GENERATE_RANDOM_CHART_REPLY_GUIDANCE =\n \"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).\";\n\nexport const GENERATE_IMAGE_REPLY_GUIDANCE =\n \"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.\";\n\nexport const MANAGE_TEAM_MEMBERS_LIST_REPLY_GUIDANCE =\n \"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).\";\n\nexport const MANAGE_TEAM_MEMBERS_DETAIL_REPLY_GUIDANCE =\n \"Team member details render in chat UI. Do not restate name, email, or role from the card. Only add next steps or policy context.\";\n\nexport const MANAGE_GROUPS_LIST_REPLY_GUIDANCE =\n \"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.\";\n\nexport const MANAGE_GROUPS_DETAIL_REPLY_GUIDANCE =\n \"Group details render in chat UI. Do not restate fields already visible in the card. Only add next steps.\";\n\nexport const QUERY_TASKS_LIST_REPLY_GUIDANCE =\n \"Tasks render as a list card in chat. Do not restate task names, ids, or statuses from the list. Only add context not shown (e.g. filters applied, recommended next action).\";\n\nexport const QUERY_TASKS_DETAIL_REPLY_GUIDANCE =\n \"Task details render in chat UI. Do not restate fields already visible in the card. Only add analysis or next steps.\";\n\nexport const ASSIGN_TASKS_REPLY_GUIDANCE =\n \"Reassignment results render in chat UI. Do not restate task ids or assignee emails from the card. Only mention failures, partial success, or next steps.\";\n\nexport const REFUND_CHARGE_REPLY_GUIDANCE =\n \"Refund details render in chat UI. Do not restate charge id, amount, or status from the card. Only add policy context or next steps.\";\n\nexport const DEPLOY_RELEASE_REPLY_GUIDANCE =\n \"Deploy details render in chat UI. Do not restate service, version, or environment from the card. Only add rollout context or next steps.\";\n\nexport const GET_WEATHER_REPLY_GUIDANCE =\n \"Weather details render in chat UI. Do not restate city, condition, or temperature from the card. Only add conversational context if needed.\";\n\nexport const ADMIN_MUTATION_REPLY_GUIDANCE =\n \"The action result renders in chat UI. Do not restate fields already visible in the card. Confirm outcome briefly or add next steps only.\";\n\nexport type ToolResultWithReplyGuidance<T extends Record<string, unknown>> = T & {\n replyGuidance: string;\n};\n\n/** Attach model-facing narration hints to a tool execute result. */\nexport function withReplyGuidance<T extends Record<string, unknown>>(\n result: T,\n guidance: string\n): ToolResultWithReplyGuidance<T> {\n return {\n ...result,\n [TOOL_REPLY_GUIDANCE_FIELD]: guidance,\n };\n}\n\n/** Remove agent-only fields before showing raw JSON in the dashboard. */\nexport function stripAgentOnlyToolFields(output: unknown): unknown {\n if (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n return output;\n }\n\n const record = { ...(output as Record<string, unknown>) };\n delete record[TOOL_REPLY_GUIDANCE_FIELD];\n delete record[TOOL_UI_HINT_FIELD];\n delete record[TOOL_UI_FIELD];\n return record;\n}\n","import { defineTool } from \"eve/tools\";\nimport { z } from \"zod\";\nimport { tryResolveTenantCaller } from \"../../agent/tenant.js\";\nimport {\n MY_ACCESS_REPLY_GUIDANCE,\n withReplyGuidance,\n} from \"../../tool-reply-guidance.js\";\nimport { formatMyAccessResult } from \"./format-my-access.js\";\n\n/** Eve tool slug — must match the agent tool filename `get_my_access.ts`. */\nexport const MY_ACCESS_TOOL_NAME = \"get_my_access\";\n\nexport const myAccessInputSchema = z.object({});\n\nfunction tenantCapabilities(isAdmin: boolean) {\n return {\n manageSettings: isAdmin,\n manageBilling: isAdmin,\n manageTeam: isAdmin,\n manageIntegrations: isAdmin,\n };\n}\n\nexport function defineMyAccessTool() {\n return defineTool({\n description:\n \"Check the authenticated user's tenant role, group memberships, and admin capabilities in RobotRock. \" +\n \"Always call this before tenant-admin tools (manage_team_members, manage_groups, query_tasks, get_workspace_usage) in the same turn — \" +\n \"including read-only requests like listing users or usage. Results render as a visible access tool card in chat like other tools; \" +\n \"do not restate role, groups, or capabilities in your reply.\",\n inputSchema: myAccessInputSchema,\n async execute(_input, ctx) {\n const caller = tryResolveTenantCaller(ctx);\n if (!caller) {\n return withReplyGuidance(\n {\n authenticated: false as const,\n message:\n \"No RobotRock user is attached to this session. Dashboard chat supplies user context via the Eve proxy.\",\n },\n \"Explain that no user is attached to this session. Do not invent access details.\"\n );\n }\n\n return formatMyAccessResult({\n tenantSlug: caller.tenantSlug,\n tenantRole: caller.role,\n isTenantAdmin: caller.isAdmin,\n groupSlugs: caller.groups,\n capabilities: tenantCapabilities(caller.isAdmin),\n email: caller.email,\n });\n },\n });\n}\n\nexport const myAccessTool = defineMyAccessTool();\n","import { withReplyGuidance } from \"./tool-reply-guidance.js\";\nimport {\n withToolUi,\n type ToolResultUiEntity,\n type ToolResultUiMeta,\n} from \"./tool-result-ui-meta.js\";\nimport { withUiHint, type ToolUiHint } from \"./tool-ui-hint.js\";\n\nexport type FormatToolObjectResultOptions = {\n replyGuidance: string;\n /** @deprecated Prefer `ui.layout`. Mapped for backward compatibility. */\n uiHint?: ToolUiHint;\n ui?: ToolResultUiMeta;\n};\n\nexport type FormatToolListResultOptions = {\n replyGuidance: string;\n entity?: ToolResultUiEntity;\n present?: boolean;\n ui?: Omit<ToolResultUiMeta, \"rowsPath\" | \"layout\">;\n};\n\nexport type FormatToolQueryResultOptions = {\n replyGuidance: string;\n entity?: ToolResultUiEntity;\n present?: boolean;\n rowsPath?: string;\n ui?: ToolResultUiMeta;\n};\n\ntype WithReplyGuidance<T> = T & { replyGuidance: string };\ntype WithUiMeta<T> = T & { ui: ToolResultUiMeta };\ntype WithUiHintField<T> = T & { uiHint: ToolUiHint };\n\n/** Attach agent narration hints to plain tool JSON. No display/ui envelope. */\nexport function formatToolObjectResult<T extends Record<string, unknown>>(\n data: T,\n options: FormatToolObjectResultOptions\n): WithReplyGuidance<T> &\n Partial<WithUiMeta<T>> &\n Partial<WithUiHintField<T>> {\n let result: Record<string, unknown> = withReplyGuidance(\n data,\n options.replyGuidance\n );\n if (options.ui) {\n result = withToolUi(result, options.ui);\n }\n if (options.uiHint) {\n result = withUiHint(result, options.uiHint);\n }\n return result as WithReplyGuidance<T> &\n Partial<WithUiMeta<T>> &\n Partial<WithUiHintField<T>>;\n}\n\n/** Wrap an array field as plain tool JSON with reply guidance and list layout hint.\n *\n * Include `url` on each item when you know a navigable link — the dashboard\n * renders clickable Item rows. Use `attachments` / `files` / `documents` keys\n * for file downloads (Attachment layout). Set `entity` so the dashboard caches\n * a reusable row layout under that name.\n */\nexport function formatToolListResult<\n const K extends string,\n T extends Record<string, unknown>,\n>(\n listKey: K,\n items: T[],\n options: FormatToolListResultOptions\n): WithReplyGuidance<Record<K, T[]>> &\n WithUiMeta<Record<K, T[]>> &\n WithUiHintField<Record<K, T[]>> {\n const ui: ToolResultUiMeta = {\n ...options.ui,\n layout: \"list\",\n rowsPath: listKey,\n ...(options.entity ? { entity: options.entity } : {}),\n ...(options.present !== undefined ? { present: options.present } : {}),\n };\n\n return withUiHint(\n withToolUi(\n withReplyGuidance({ [listKey]: items } as Record<K, T[]>, options.replyGuidance),\n ui\n ),\n \"list\"\n ) as WithReplyGuidance<Record<K, T[]>> &\n WithUiMeta<Record<K, T[]>> &\n WithUiHintField<Record<K, T[]>>;\n}\n\n/** Format a query-style result: shared meta fields + typed row array. */\nexport function formatToolQueryResult<\n M extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n meta: M,\n rows: T[],\n options: FormatToolQueryResultOptions\n): WithReplyGuidance<M & Record<string, T[]>> & WithUiMeta<M & Record<string, T[]>> {\n const rowsPath = options.rowsPath ?? options.ui?.rowsPath ?? \"rows\";\n const ui: ToolResultUiMeta = {\n ...options.ui,\n layout: options.ui?.layout ?? \"list\",\n rowsPath,\n ...(options.entity ? { entity: options.entity } : {}),\n ...(options.present !== undefined ? { present: options.present } : {}),\n };\n\n return withToolUi(\n withReplyGuidance(\n {\n ...meta,\n [rowsPath]: rows,\n } as M & Record<string, T[]>,\n options.replyGuidance\n ),\n ui\n ) as WithReplyGuidance<M & Record<string, T[]>> &\n WithUiMeta<M & Record<string, T[]>>;\n}\n\nexport function isAgentAdminErrorResult(\n result: unknown\n): result is { ok: false; message: string } {\n return (\n typeof result === \"object\" &&\n result !== null &&\n (result as { ok?: unknown }).ok === false &&\n typeof (result as { message?: unknown }).message === \"string\"\n );\n}\n","import { formatToolObjectResult } from \"../../tool-display-format.js\";\nimport { MY_ACCESS_REPLY_GUIDANCE } from \"../../tool-reply-guidance.js\";\n\ntype MyAccessResultInput = {\n tenantSlug: string;\n tenantRole?: string;\n isTenantAdmin: boolean;\n groupSlugs: string[];\n capabilities: {\n manageSettings: boolean;\n manageBilling: boolean;\n manageTeam: boolean;\n manageIntegrations: boolean;\n };\n email?: string;\n};\n\nexport function formatMyAccessResult(input: MyAccessResultInput) {\n return formatToolObjectResult(\n {\n access: {\n workspace: input.tenantSlug,\n role: input.tenantRole ?? \"member\",\n tenantAdmin: input.isTenantAdmin,\n groups: input.groupSlugs.join(\", \") || \"—\",\n manageSettings: input.capabilities.manageSettings,\n manageBilling: input.capabilities.manageBilling,\n manageTeam: input.capabilities.manageTeam,\n manageIntegrations: input.capabilities.manageIntegrations,\n ...(input.email ? { email: input.email } : {}),\n },\n },\n {\n replyGuidance: MY_ACCESS_REPLY_GUIDANCE,\n ui: { entity: \"access\" },\n }\n );\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS;;;ACDX,SAAS,oBACd,YACA,KACoB;AACpB,QAAM,QAAQ,aAAa,GAAG;AAC9B,MAAI,OAAO,UAAU,YAAY,MAAM,SAAS,GAAG;AACjD,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,KAAK,OAAO,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,EAAE,SAAS,GAAG;AAC/E,WAAO,MAAM,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEO,SAAS,yBACd,YACA,KACU;AACV,QAAM,QAAQ,aAAa,GAAG;AAC9B,MAAI,OAAO,UAAU,YAAY,MAAM,SAAS,GAAG;AACjD,WAAO,CAAC,KAAK;AAAA,EACf;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM;AAAA,MACX,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS;AAAA,IAC1E;AAAA,EACF;AACA,SAAO,CAAC;AACV;AAEO,SAAS,gBACd,OAC2B;AAC3B,MAAI,UAAU,WAAW,UAAU,UAAU;AAC3C,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACdO,SAAS,uBAAuB,KAA0C;AAC/E,QAAM,SAAS,IAAI,QAAQ,KAAK,aAAa,IAAI,QAAQ,KAAK;AAC9D,MAAI,QAAQ,kBAAkB,QAAQ;AACpC,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,oBAAoB,OAAO,YAAY,OAAO;AAC5D,QAAM,OAAO,oBAAoB,OAAO,YAAY,MAAM;AAC1D,QAAM,aACJ,oBAAoB,OAAO,YAAY,YAAY,KACnD,oBAAoB,OAAO,YAAY,UAAU;AACnD,QAAM,OAAO,gBAAgB,oBAAoB,OAAO,YAAY,MAAM,CAAC;AAC3E,MAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,MAAM;AACzD,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,oBAAoB,OAAO,YAAY,cAAc;AAC1E,QAAM,eAAe,oBAAoB,OAAO,YAAY,cAAc;AAC1E,QAAM,SAAS,oBAAoB,OAAO,YAAY,QAAQ;AAC9D,QAAM,SAAS,yBAAyB,OAAO,YAAY,QAAQ;AAEnE,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,MAAM,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,IACrC;AAAA,IACA,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,EACzC;AACF;;;ACvDO,IAAM,qBAAqB;AAY3B,SAAS,WACd,QACA,MAC4B;AAC5B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,kBAAkB,GAAG;AAAA,EACxB;AACF;;;AClBO,IAAM,gBAAgB;AA6ItB,SAAS,WACd,QACA,IAC8B;AAC9B,QAAM,WACJ,OAAO,OAAO,aAAa,MAAM,YACjC,OAAO,aAAa,MAAM,QAC1B,CAAC,MAAM,QAAQ,OAAO,aAAa,CAAC,IAC/B,OAAO,aAAa,IACrB,CAAC;AAEP,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,aAAa,GAAG;AAAA,MACf,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AACF;;;AC9JO,IAAM,4BAA4B;AAElC,IAAM,wBACX;AAEK,IAAM,2BACX;AAuDK,SAAS,kBACd,QACA,UACgC;AAChC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,yBAAyB,GAAG;AAAA,EAC/B;AACF;;;ALjEO,IAAM,mBAAmB;AAEzB,IAAM,oBAAoB,EAAE,OAAO,CAAC,CAAC;AAErC,SAAS,mBAAmB;AACjC,SAAO,WAAW;AAAA,IAChB,aACE;AAAA,IAEF,aAAa;AAAA,IACb,MAAM,QAAQ,QAAQ,KAAK;AACzB,YAAM,SAAS,uBAAuB,GAAG;AACzC,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SACE;AAAA,UACJ;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL;AAAA,UACE,eAAe;AAAA,UACf,QAAQ,OAAO;AAAA,UACf,MAAM,OAAO;AAAA,UACb,OAAO,OAAO;AAAA,UACd,YAAY,OAAO;AAAA,UACnB,MAAM,OAAO;AAAA,UACb,SAAS,OAAO;AAAA,UAChB,QAAQ,OAAO,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE;AAAA,UAC9C,GAAI,OAAO,eAAe,EAAE,cAAc,OAAO,aAAa,IAAI,CAAC;AAAA,UACnE,WAAW,IAAI,QAAQ;AAAA,QACzB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,IAAM,aAAa,iBAAiB;;;AMlD3C,SAAS,cAAAA,mBAAkB;AAC3B,SAAS,KAAAC,UAAS;;;ACkCX,SAAS,uBACd,MACA,SAG4B;AAC5B,MAAI,SAAkC;AAAA,IACpC;AAAA,IACA,QAAQ;AAAA,EACV;AACA,MAAI,QAAQ,IAAI;AACd,aAAS,WAAW,QAAQ,QAAQ,EAAE;AAAA,EACxC;AACA,MAAI,QAAQ,QAAQ;AAClB,aAAS,WAAW,QAAQ,QAAQ,MAAM;AAAA,EAC5C;AACA,SAAO;AAGT;;;ACrCO,SAAS,qBAAqB,OAA4B;AAC/D,SAAO;AAAA,IACL;AAAA,MACE,QAAQ;AAAA,QACN,WAAW,MAAM;AAAA,QACjB,MAAM,MAAM,cAAc;AAAA,QAC1B,aAAa,MAAM;AAAA,QACnB,QAAQ,MAAM,WAAW,KAAK,IAAI,KAAK;AAAA,QACvC,gBAAgB,MAAM,aAAa;AAAA,QACnC,eAAe,MAAM,aAAa;AAAA,QAClC,YAAY,MAAM,aAAa;AAAA,QAC/B,oBAAoB,MAAM,aAAa;AAAA,QACvC,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC9C;AAAA,IACF;AAAA,IACA;AAAA,MACE,eAAe;AAAA,MACf,IAAI,EAAE,QAAQ,SAAS;AAAA,IACzB;AAAA,EACF;AACF;;;AF3BO,IAAM,sBAAsB;AAE5B,IAAM,sBAAsBC,GAAE,OAAO,CAAC,CAAC;AAE9C,SAAS,mBAAmB,SAAkB;AAC5C,SAAO;AAAA,IACL,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,oBAAoB;AAAA,EACtB;AACF;AAEO,SAAS,qBAAqB;AACnC,SAAOC,YAAW;AAAA,IAChB,aACE;AAAA,IAIF,aAAa;AAAA,IACb,MAAM,QAAQ,QAAQ,KAAK;AACzB,YAAM,SAAS,uBAAuB,GAAG;AACzC,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SACE;AAAA,UACJ;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,aAAO,qBAAqB;AAAA,QAC1B,YAAY,OAAO;AAAA,QACnB,YAAY,OAAO;AAAA,QACnB,eAAe,OAAO;AAAA,QACtB,YAAY,OAAO;AAAA,QACnB,cAAc,mBAAmB,OAAO,OAAO;AAAA,QAC/C,OAAO,OAAO;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAEO,IAAM,eAAe,mBAAmB;","names":["defineTool","z","z","defineTool"]}