@agenticmail/enterprise 0.5.170 → 0.5.172

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.
@@ -0,0 +1,49 @@
1
+ import {
2
+ AgentRuntime,
3
+ EmailChannel,
4
+ FollowUpScheduler,
5
+ SessionManager,
6
+ SubAgentManager,
7
+ ToolRegistry,
8
+ callLLM,
9
+ createAgentRuntime,
10
+ createNoopHooks,
11
+ createRuntimeHooks,
12
+ estimateMessageTokens,
13
+ estimateTokens,
14
+ executeTool,
15
+ runAgentLoop,
16
+ toolsToDefinitions
17
+ } from "./chunk-XY3B3MYT.js";
18
+ import "./chunk-AQH4DFYV.js";
19
+ import "./chunk-JLSQOQ5L.js";
20
+ import {
21
+ PROVIDER_REGISTRY,
22
+ listAllProviders,
23
+ resolveApiKeyForProvider,
24
+ resolveProvider
25
+ } from "./chunk-67KZYSLU.js";
26
+ import "./chunk-NRF3YRF7.js";
27
+ import "./chunk-TYW5XTOW.js";
28
+ import "./chunk-KFQGP6VL.js";
29
+ export {
30
+ AgentRuntime,
31
+ EmailChannel,
32
+ FollowUpScheduler,
33
+ PROVIDER_REGISTRY,
34
+ SessionManager,
35
+ SubAgentManager,
36
+ ToolRegistry,
37
+ callLLM,
38
+ createAgentRuntime,
39
+ createNoopHooks,
40
+ createRuntimeHooks,
41
+ estimateMessageTokens,
42
+ estimateTokens,
43
+ executeTool,
44
+ listAllProviders,
45
+ resolveApiKeyForProvider,
46
+ resolveProvider,
47
+ runAgentLoop,
48
+ toolsToDefinitions
49
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-TX2QYPQN.js";
4
+ import "./chunk-3SMTCIR4.js";
5
+ import "./chunk-JLSQOQ5L.js";
6
+ import "./chunk-RO537U6H.js";
7
+ import "./chunk-DRXMYYKN.js";
8
+ import "./chunk-67KZYSLU.js";
9
+ import "./chunk-KFQGP6VL.js";
10
+ export {
11
+ createServer
12
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-LSANOO23.js";
10
+ import "./chunk-MHIFVS5L.js";
11
+ import "./chunk-KFQGP6VL.js";
12
+ export {
13
+ promptCompanyInfo,
14
+ promptDatabase,
15
+ promptDeployment,
16
+ promptDomain,
17
+ promptRegistration,
18
+ provision,
19
+ runSetupWizard
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.170",
3
+ "version": "0.5.172",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Google Chat API Tools
3
+ *
4
+ * Lets agents participate in Google Chat spaces — list spaces, read messages,
5
+ * send messages, create spaces, manage memberships.
6
+ * Uses Google Chat API v1.
7
+ *
8
+ * Required OAuth scope: https://www.googleapis.com/auth/chat.spaces
9
+ * https://www.googleapis.com/auth/chat.messages
10
+ * https://www.googleapis.com/auth/chat.memberships
11
+ */
12
+
13
+ import type { AnyAgentTool, ToolCreationOptions } from '../../types.js';
14
+ import type { GoogleToolsConfig } from './index.js';
15
+ import { jsonResult, errorResult } from '../../common.js';
16
+
17
+ // ─── Helper ─────────────────────────────────────────────
18
+
19
+ async function chatApi(token: string, path: string, opts?: { method?: string; body?: any; query?: Record<string, string> }): Promise<any> {
20
+ const url = new URL(`https://chat.googleapis.com/v1${path}`);
21
+ if (opts?.query) for (const [k, v] of Object.entries(opts.query)) url.searchParams.set(k, v);
22
+ const res = await fetch(url.toString(), {
23
+ method: opts?.method || 'GET',
24
+ headers: {
25
+ Authorization: `Bearer ${token}`,
26
+ ...(opts?.body ? { 'Content-Type': 'application/json' } : {}),
27
+ },
28
+ ...(opts?.body ? { body: JSON.stringify(opts.body) } : {}),
29
+ });
30
+ if (!res.ok) {
31
+ const errText = await res.text();
32
+ throw new Error(`Google Chat API ${res.status}: ${errText}`);
33
+ }
34
+ if (res.status === 204) return {};
35
+ return res.json();
36
+ }
37
+
38
+ // ─── Tool Definitions ───────────────────────────────────
39
+
40
+ export function createGoogleChatTools(config: GoogleToolsConfig, _options?: ToolCreationOptions): AnyAgentTool[] {
41
+ const tp = config.tokenProvider;
42
+
43
+ return [
44
+ // ─── List Spaces ────────────────────────────────────
45
+ {
46
+ name: 'google_chat_list_spaces',
47
+ description: 'List Google Chat spaces (rooms, DMs, group conversations) the agent has access to. Returns space names, display names, and types.',
48
+ category: 'communication' as const,
49
+ parameters: {
50
+ type: 'object' as const,
51
+ properties: {
52
+ pageSize: { type: 'string', description: 'Max results (default: 20, max: 1000)' },
53
+ filter: { type: 'string', description: 'Filter string, e.g. "spaceType = SPACE" for named spaces only' },
54
+ },
55
+ required: [],
56
+ },
57
+ async execute(_id: string, input: any) {
58
+ try {
59
+ const token = await tp.getAccessToken();
60
+ const query: Record<string, string> = {};
61
+ if (input.pageSize) query.pageSize = input.pageSize;
62
+ if (input.filter) query.filter = input.filter;
63
+ const result = await chatApi(token, '/spaces', { query });
64
+ const spaces = (result.spaces || []).map((s: any) => ({
65
+ name: s.name,
66
+ displayName: s.displayName,
67
+ type: s.spaceType || s.type,
68
+ threaded: s.threaded,
69
+ singleUserBotDm: s.singleUserBotDm,
70
+ }));
71
+ return jsonResult({ spaces, count: spaces.length });
72
+ } catch (e: any) { return errorResult(e.message); }
73
+ },
74
+ },
75
+
76
+ // ─── Get Space Details ──────────────────────────────
77
+ {
78
+ name: 'google_chat_get_space',
79
+ description: 'Get details about a specific Google Chat space by its resource name (e.g. "spaces/AAAA...").',
80
+ category: 'communication' as const,
81
+ parameters: {
82
+ type: 'object' as const,
83
+ properties: {
84
+ spaceName: { type: 'string', description: 'Space resource name (e.g. "spaces/AAAAxyz...")' },
85
+ },
86
+ required: ['spaceName'],
87
+ },
88
+ async execute(_id: string, input: any) {
89
+ try {
90
+ const token = await tp.getAccessToken();
91
+ const result = await chatApi(token, `/${input.spaceName}`);
92
+ return jsonResult(result);
93
+ } catch (e: any) { return errorResult(e.message); }
94
+ },
95
+ },
96
+
97
+ // ─── List Messages in Space ─────────────────────────
98
+ {
99
+ name: 'google_chat_list_messages',
100
+ description: 'List recent messages in a Google Chat space. Returns message text, sender, and timestamps.',
101
+ category: 'communication' as const,
102
+ parameters: {
103
+ type: 'object' as const,
104
+ properties: {
105
+ spaceName: { type: 'string', description: 'Space resource name (e.g. "spaces/AAAAxyz...")' },
106
+ pageSize: { type: 'string', description: 'Max messages to return (default: 25, max: 1000)' },
107
+ orderBy: { type: 'string', description: '"createTime asc" or "createTime desc" (default: desc)' },
108
+ filter: { type: 'string', description: 'Filter, e.g. \'createTime > "2024-01-01T00:00:00Z"\'' },
109
+ showDeleted: { type: 'string', description: '"true" to include deleted messages' },
110
+ },
111
+ required: ['spaceName'],
112
+ },
113
+ async execute(_id: string, input: any) {
114
+ try {
115
+ const token = await tp.getAccessToken();
116
+ const query: Record<string, string> = {};
117
+ if (input.pageSize) query.pageSize = input.pageSize;
118
+ if (input.orderBy) query.orderBy = input.orderBy;
119
+ if (input.filter) query.filter = input.filter;
120
+ if (input.showDeleted === 'true') query.showDeleted = 'true';
121
+ const result = await chatApi(token, `/${input.spaceName}/messages`, { query });
122
+ const messages = (result.messages || []).map((m: any) => ({
123
+ name: m.name,
124
+ sender: m.sender?.displayName || m.sender?.name || 'unknown',
125
+ senderType: m.sender?.type,
126
+ text: m.text || m.formattedText || '',
127
+ createTime: m.createTime,
128
+ threadName: m.thread?.name,
129
+ attachments: (m.attachment || []).length,
130
+ }));
131
+ return jsonResult({ messages, count: messages.length });
132
+ } catch (e: any) { return errorResult(e.message); }
133
+ },
134
+ },
135
+
136
+ // ─── Send Message ───────────────────────────────────
137
+ {
138
+ name: 'google_chat_send_message',
139
+ description: 'Send a message to a Google Chat space. Supports plain text and cards.',
140
+ category: 'communication' as const,
141
+ parameters: {
142
+ type: 'object' as const,
143
+ properties: {
144
+ spaceName: { type: 'string', description: 'Space resource name (e.g. "spaces/AAAAxyz...")' },
145
+ text: { type: 'string', description: 'Message text (supports Chat markdown)' },
146
+ threadKey: { type: 'string', description: 'Thread key to reply in a specific thread' },
147
+ threadName: { type: 'string', description: 'Thread resource name to reply to an existing thread' },
148
+ },
149
+ required: ['spaceName', 'text'],
150
+ },
151
+ async execute(_id: string, input: any) {
152
+ try {
153
+ const token = await tp.getAccessToken();
154
+ const body: any = { text: input.text };
155
+ if (input.threadName || input.threadKey) {
156
+ body.thread = {};
157
+ if (input.threadName) body.thread.name = input.threadName;
158
+ if (input.threadKey) body.thread.threadKey = input.threadKey;
159
+ }
160
+ const query: Record<string, string> = {};
161
+ if (input.threadKey) query.messageReplyOption = 'REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD';
162
+ const result = await chatApi(token, `/${input.spaceName}/messages`, { method: 'POST', body, query });
163
+ return jsonResult({ sent: true, messageName: result.name, createTime: result.createTime });
164
+ } catch (e: any) { return errorResult(e.message); }
165
+ },
166
+ },
167
+
168
+ // ─── Update Message ─────────────────────────────────
169
+ {
170
+ name: 'google_chat_update_message',
171
+ description: 'Update (edit) an existing message in Google Chat.',
172
+ category: 'communication' as const,
173
+ parameters: {
174
+ type: 'object' as const,
175
+ properties: {
176
+ messageName: { type: 'string', description: 'Message resource name (e.g. "spaces/AAAA.../messages/BBBB...")' },
177
+ text: { type: 'string', description: 'New message text' },
178
+ },
179
+ required: ['messageName', 'text'],
180
+ },
181
+ async execute(_id: string, input: any) {
182
+ try {
183
+ const token = await tp.getAccessToken();
184
+ const result = await chatApi(token, `/${input.messageName}`, {
185
+ method: 'PATCH',
186
+ body: { text: input.text },
187
+ query: { updateMask: 'text' },
188
+ });
189
+ return jsonResult({ updated: true, messageName: result.name });
190
+ } catch (e: any) { return errorResult(e.message); }
191
+ },
192
+ },
193
+
194
+ // ─── Delete Message ─────────────────────────────────
195
+ {
196
+ name: 'google_chat_delete_message',
197
+ description: 'Delete a message in Google Chat.',
198
+ category: 'communication' as const,
199
+ parameters: {
200
+ type: 'object' as const,
201
+ properties: {
202
+ messageName: { type: 'string', description: 'Message resource name to delete' },
203
+ },
204
+ required: ['messageName'],
205
+ },
206
+ async execute(_id: string, input: any) {
207
+ try {
208
+ const token = await tp.getAccessToken();
209
+ await chatApi(token, `/${input.messageName}`, { method: 'DELETE' });
210
+ return jsonResult({ deleted: true });
211
+ } catch (e: any) { return errorResult(e.message); }
212
+ },
213
+ },
214
+
215
+ // ─── List Members ───────────────────────────────────
216
+ {
217
+ name: 'google_chat_list_members',
218
+ description: 'List members of a Google Chat space. Shows who is in a room/conversation.',
219
+ category: 'communication' as const,
220
+ parameters: {
221
+ type: 'object' as const,
222
+ properties: {
223
+ spaceName: { type: 'string', description: 'Space resource name' },
224
+ pageSize: { type: 'string', description: 'Max results (default: 100)' },
225
+ filter: { type: 'string', description: 'Filter, e.g. \'role = "ROLE_MANAGER"\'' },
226
+ },
227
+ required: ['spaceName'],
228
+ },
229
+ async execute(_id: string, input: any) {
230
+ try {
231
+ const token = await tp.getAccessToken();
232
+ const query: Record<string, string> = {};
233
+ if (input.pageSize) query.pageSize = input.pageSize;
234
+ if (input.filter) query.filter = input.filter;
235
+ const result = await chatApi(token, `/${input.spaceName}/members`, { query });
236
+ const members = (result.memberships || []).map((m: any) => ({
237
+ name: m.name,
238
+ role: m.role,
239
+ memberType: m.member?.type,
240
+ displayName: m.member?.displayName,
241
+ email: m.member?.domainId || '',
242
+ state: m.state,
243
+ }));
244
+ return jsonResult({ members, count: members.length });
245
+ } catch (e: any) { return errorResult(e.message); }
246
+ },
247
+ },
248
+
249
+ // ─── Create Space ───────────────────────────────────
250
+ {
251
+ name: 'google_chat_create_space',
252
+ description: 'Create a new Google Chat space (room). Can set display name, description, and type.',
253
+ category: 'communication' as const,
254
+ parameters: {
255
+ type: 'object' as const,
256
+ properties: {
257
+ displayName: { type: 'string', description: 'Space display name' },
258
+ description: { type: 'string', description: 'Space description' },
259
+ spaceType: { type: 'string', description: '"SPACE" for named space (default), "GROUP_CHAT" for group DM' },
260
+ externalUserAllowed: { type: 'string', description: '"true" to allow external users' },
261
+ },
262
+ required: ['displayName'],
263
+ },
264
+ async execute(_id: string, input: any) {
265
+ try {
266
+ const token = await tp.getAccessToken();
267
+ const body: any = {
268
+ displayName: input.displayName,
269
+ spaceType: input.spaceType || 'SPACE',
270
+ };
271
+ if (input.description) body.spaceDetails = { description: input.description };
272
+ if (input.externalUserAllowed === 'true') body.externalUserAllowed = true;
273
+ const result = await chatApi(token, '/spaces', { method: 'POST', body });
274
+ return jsonResult({ created: true, spaceName: result.name, displayName: result.displayName });
275
+ } catch (e: any) { return errorResult(e.message); }
276
+ },
277
+ },
278
+
279
+ // ─── Add Member to Space ────────────────────────────
280
+ {
281
+ name: 'google_chat_add_member',
282
+ description: 'Add a user to a Google Chat space by their email address.',
283
+ category: 'communication' as const,
284
+ parameters: {
285
+ type: 'object' as const,
286
+ properties: {
287
+ spaceName: { type: 'string', description: 'Space resource name' },
288
+ email: { type: 'string', description: 'Email address of user to add' },
289
+ },
290
+ required: ['spaceName', 'email'],
291
+ },
292
+ async execute(_id: string, input: any) {
293
+ try {
294
+ const token = await tp.getAccessToken();
295
+ const body = {
296
+ member: {
297
+ name: `users/${input.email}`,
298
+ type: 'HUMAN',
299
+ },
300
+ };
301
+ const result = await chatApi(token, `/${input.spaceName}/members`, { method: 'POST', body });
302
+ return jsonResult({ added: true, membershipName: result.name });
303
+ } catch (e: any) { return errorResult(e.message); }
304
+ },
305
+ },
306
+
307
+ // ─── Search Messages ────────────────────────────────
308
+ {
309
+ name: 'google_chat_search',
310
+ description: 'Search for messages across all spaces the agent has access to. Use for finding specific conversations or information.',
311
+ category: 'communication' as const,
312
+ parameters: {
313
+ type: 'object' as const,
314
+ properties: {
315
+ query: { type: 'string', description: 'Search query text' },
316
+ spaceName: { type: 'string', description: 'Limit search to a specific space (optional)' },
317
+ pageSize: { type: 'string', description: 'Max results (default: 10)' },
318
+ },
319
+ required: ['query'],
320
+ },
321
+ async execute(_id: string, input: any) {
322
+ try {
323
+ const token = await tp.getAccessToken();
324
+ // Use list messages with filter for text matching within a space
325
+ if (input.spaceName) {
326
+ const query: Record<string, string> = {
327
+ pageSize: input.pageSize || '10',
328
+ filter: `text : "${input.query}"`,
329
+ orderBy: 'createTime desc',
330
+ };
331
+ const result = await chatApi(token, `/${input.spaceName}/messages`, { query });
332
+ const messages = (result.messages || []).map((m: any) => ({
333
+ name: m.name,
334
+ sender: m.sender?.displayName || 'unknown',
335
+ text: m.text || '',
336
+ createTime: m.createTime,
337
+ space: m.space?.displayName,
338
+ }));
339
+ return jsonResult({ messages, count: messages.length });
340
+ }
341
+ // Without space, list spaces and search each (limited)
342
+ const spacesResult = await chatApi(token, '/spaces', { query: { pageSize: '20' } });
343
+ const allMessages: any[] = [];
344
+ const queryLower = input.query.toLowerCase();
345
+ for (const space of (spacesResult.spaces || []).slice(0, 5)) {
346
+ try {
347
+ const msgs = await chatApi(token, `/${space.name}/messages`, {
348
+ query: { pageSize: '20', orderBy: 'createTime desc' },
349
+ });
350
+ for (const m of (msgs.messages || [])) {
351
+ if ((m.text || '').toLowerCase().includes(queryLower)) {
352
+ allMessages.push({
353
+ name: m.name,
354
+ sender: m.sender?.displayName || 'unknown',
355
+ text: m.text,
356
+ createTime: m.createTime,
357
+ space: space.displayName,
358
+ });
359
+ }
360
+ }
361
+ } catch { /* skip inaccessible spaces */ }
362
+ }
363
+ return jsonResult({ messages: allMessages.slice(0, parseInt(input.pageSize) || 10), count: allMessages.length });
364
+ } catch (e: any) { return errorResult(e.message); }
365
+ },
366
+ },
367
+
368
+ // ─── Create Reaction ────────────────────────────────
369
+ {
370
+ name: 'google_chat_react',
371
+ description: 'Add an emoji reaction to a message in Google Chat.',
372
+ category: 'communication' as const,
373
+ parameters: {
374
+ type: 'object' as const,
375
+ properties: {
376
+ messageName: { type: 'string', description: 'Message resource name' },
377
+ emoji: { type: 'string', description: 'Unicode emoji character (e.g. "👍", "❤️", "✅")' },
378
+ },
379
+ required: ['messageName', 'emoji'],
380
+ },
381
+ async execute(_id: string, input: any) {
382
+ try {
383
+ const token = await tp.getAccessToken();
384
+ const result = await chatApi(token, `/${input.messageName}/reactions`, {
385
+ method: 'POST',
386
+ body: { emoji: { unicode: input.emoji } },
387
+ });
388
+ return jsonResult({ reacted: true, reactionName: result.name });
389
+ } catch (e: any) { return errorResult(e.message); }
390
+ },
391
+ },
392
+ ];
393
+ }