@arbium/enterprise-agent-connect 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +117 -2
  3. package/dist/connectors/dell-techdirect/connector.json +39 -0
  4. package/dist/connectors/dell-techdirect/index.js +7 -0
  5. package/dist/connectors/dell-techdirect/index.js.map +1 -0
  6. package/dist/connectors/dell-techdirect/tools.js +49 -0
  7. package/dist/connectors/dell-techdirect/tools.js.map +1 -0
  8. package/dist/connectors/dell-techdirect/vendor.js +57 -0
  9. package/dist/connectors/dell-techdirect/vendor.js.map +1 -0
  10. package/dist/connectors/entra/connector.json +85 -0
  11. package/dist/connectors/entra/index.js +4 -0
  12. package/dist/connectors/entra/index.js.map +1 -0
  13. package/dist/connectors/entra/tools.js +262 -0
  14. package/dist/connectors/entra/tools.js.map +1 -0
  15. package/dist/connectors/fedex/connector.json +118 -0
  16. package/dist/connectors/fedex/index.js +7 -0
  17. package/dist/connectors/fedex/index.js.map +1 -0
  18. package/dist/connectors/fedex/tools.js +152 -0
  19. package/dist/connectors/fedex/tools.js.map +1 -0
  20. package/dist/connectors/fedex/vendor.js +98 -0
  21. package/dist/connectors/fedex/vendor.js.map +1 -0
  22. package/dist/connectors/http/index.js +235 -0
  23. package/dist/connectors/http/index.js.map +1 -0
  24. package/dist/connectors/intune/connector.json +106 -0
  25. package/dist/connectors/intune/index.js +4 -0
  26. package/dist/connectors/intune/index.js.map +1 -0
  27. package/dist/connectors/intune/tools.js +416 -0
  28. package/dist/connectors/intune/tools.js.map +1 -0
  29. package/dist/connectors/jira/connector.json +129 -0
  30. package/dist/connectors/jira/index.js +7 -0
  31. package/dist/connectors/jira/index.js.map +1 -0
  32. package/dist/connectors/jira/jql.js +67 -0
  33. package/dist/connectors/jira/jql.js.map +1 -0
  34. package/dist/connectors/jira/tools.js +464 -0
  35. package/dist/connectors/jira/tools.js.map +1 -0
  36. package/dist/connectors/jira/vendor.js +94 -0
  37. package/dist/connectors/jira/vendor.js.map +1 -0
  38. package/dist/connectors/microsoft/client.js +434 -0
  39. package/dist/connectors/microsoft/client.js.map +1 -0
  40. package/dist/connectors/microsoft/provider.json +118 -0
  41. package/dist/connectors/outlook-calendar/connector.json +136 -0
  42. package/dist/connectors/outlook-calendar/index.js +4 -0
  43. package/dist/connectors/outlook-calendar/index.js.map +1 -0
  44. package/dist/connectors/outlook-calendar/tools.js +398 -0
  45. package/dist/connectors/outlook-calendar/tools.js.map +1 -0
  46. package/dist/connectors/outlook-mail/connector.json +154 -0
  47. package/dist/connectors/outlook-mail/index.js +4 -0
  48. package/dist/connectors/outlook-mail/index.js.map +1 -0
  49. package/dist/connectors/outlook-mail/tools.js +236 -0
  50. package/dist/connectors/outlook-mail/tools.js.map +1 -0
  51. package/dist/connectors/salesforce/connector.json +122 -0
  52. package/dist/connectors/salesforce/index.js +7 -0
  53. package/dist/connectors/salesforce/index.js.map +1 -0
  54. package/dist/connectors/salesforce/soql.js +60 -0
  55. package/dist/connectors/salesforce/soql.js.map +1 -0
  56. package/dist/connectors/salesforce/tools.js +234 -0
  57. package/dist/connectors/salesforce/tools.js.map +1 -0
  58. package/dist/connectors/salesforce/vendor.js +107 -0
  59. package/dist/connectors/salesforce/vendor.js.map +1 -0
  60. package/dist/connectors/sharepoint-files/connector.json +194 -0
  61. package/dist/connectors/sharepoint-files/excel.js +300 -0
  62. package/dist/connectors/sharepoint-files/excel.js.map +1 -0
  63. package/dist/connectors/sharepoint-files/index.js +12 -0
  64. package/dist/connectors/sharepoint-files/index.js.map +1 -0
  65. package/dist/connectors/sharepoint-files/tools.js +365 -0
  66. package/dist/connectors/sharepoint-files/tools.js.map +1 -0
  67. package/dist/connectors/sharepoint-files/vendor.js +167 -0
  68. package/dist/connectors/sharepoint-files/vendor.js.map +1 -0
  69. package/dist/connectors/teams/connector.json +298 -0
  70. package/dist/connectors/teams/index.js +5 -0
  71. package/dist/connectors/teams/index.js.map +1 -0
  72. package/dist/connectors/teams/tools.js +391 -0
  73. package/dist/connectors/teams/tools.js.map +1 -0
  74. package/dist/packages/connector-kit/src/branding.js +102 -0
  75. package/dist/packages/connector-kit/src/branding.js.map +1 -0
  76. package/dist/packages/connector-kit/src/certificate.js +84 -0
  77. package/dist/packages/connector-kit/src/certificate.js.map +1 -0
  78. package/dist/packages/connector-kit/src/common.js +107 -0
  79. package/dist/packages/connector-kit/src/common.js.map +1 -0
  80. package/dist/packages/connector-kit/src/connector.js +492 -0
  81. package/dist/packages/connector-kit/src/connector.js.map +1 -0
  82. package/dist/packages/connector-kit/src/oauth.js +79 -0
  83. package/dist/packages/connector-kit/src/oauth.js.map +1 -0
  84. package/dist/packages/connector-kit/src/types.js +20 -0
  85. package/dist/packages/connector-kit/src/types.js.map +1 -0
  86. package/dist/packages/server/migrations/0001_tables.sql +268 -0
  87. package/dist/packages/server/migrations/0002_organizations.sql +72 -0
  88. package/dist/packages/server/migrations/0003_drop_unused.sql +3 -0
  89. package/dist/packages/server/migrations/0004_trigger_runners.sql +15 -0
  90. package/dist/packages/server/migrations/0005_run_runner.sql +3 -0
  91. package/dist/packages/server/migrations/0006_approvals.sql +36 -0
  92. package/dist/packages/server/migrations/rollback/to-legacy.sql +87 -0
  93. package/dist/packages/server/src/api.js +684 -0
  94. package/dist/packages/server/src/api.js.map +1 -0
  95. package/dist/packages/server/src/app.js +444 -0
  96. package/dist/packages/server/src/app.js.map +1 -0
  97. package/dist/packages/server/src/builtin.js +24 -0
  98. package/dist/packages/server/src/builtin.js.map +1 -0
  99. package/dist/packages/server/src/consent.js +36 -0
  100. package/dist/packages/server/src/consent.js.map +1 -0
  101. package/dist/packages/server/src/index.js +129 -0
  102. package/dist/packages/server/src/index.js.map +1 -0
  103. package/dist/packages/server/src/migrate.js +134 -0
  104. package/dist/packages/server/src/migrate.js.map +1 -0
  105. package/dist/packages/server/src/openapi.js +101 -0
  106. package/dist/packages/server/src/openapi.js.map +1 -0
  107. package/dist/packages/server/src/secrets.js +76 -0
  108. package/dist/packages/server/src/secrets.js.map +1 -0
  109. package/dist/packages/server/src/server.js +69 -0
  110. package/dist/packages/server/src/server.js.map +1 -0
  111. package/dist/packages/server/src/service.js +908 -0
  112. package/dist/packages/server/src/service.js.map +1 -0
  113. package/dist/packages/server/src/store.js +411 -0
  114. package/dist/packages/server/src/store.js.map +1 -0
  115. package/dist/packages/server/src/teams/activity.js +187 -0
  116. package/dist/packages/server/src/teams/activity.js.map +1 -0
  117. package/dist/packages/server/src/teams/admin.js +699 -0
  118. package/dist/packages/server/src/teams/admin.js.map +1 -0
  119. package/dist/packages/server/src/teams/approval.js +118 -0
  120. package/dist/packages/server/src/teams/approval.js.map +1 -0
  121. package/dist/packages/server/src/teams/bot.js +124 -0
  122. package/dist/packages/server/src/teams/bot.js.map +1 -0
  123. package/dist/packages/server/src/teams/claude.js +165 -0
  124. package/dist/packages/server/src/teams/claude.js.map +1 -0
  125. package/dist/packages/server/src/teams/jwt.js +121 -0
  126. package/dist/packages/server/src/teams/jwt.js.map +1 -0
  127. package/dist/packages/server/src/teams/package.js +319 -0
  128. package/dist/packages/server/src/teams/package.js.map +1 -0
  129. package/dist/packages/server/src/teams/provision.js +505 -0
  130. package/dist/packages/server/src/teams/provision.js.map +1 -0
  131. package/dist/packages/server/src/teams/runner.js +143 -0
  132. package/dist/packages/server/src/teams/runner.js.map +1 -0
  133. package/dist/packages/server/src/teams/runtime.js +701 -0
  134. package/dist/packages/server/src/teams/runtime.js.map +1 -0
  135. package/dist/packages/server/src/teams/store.js +507 -0
  136. package/dist/packages/server/src/teams/store.js.map +1 -0
  137. package/package.json +42 -4
@@ -0,0 +1,391 @@
1
+ import { z } from "zod";
2
+ import { hashReplyToken, looksLikeReplyToken } from "../../packages/server/src/teams/activity.js";
3
+ import { APPROVAL_DAYS, approvalCard, approvalStatus, hashApprovalToken, looksLikeApprovalToken, newApprovalToken, } from "../../packages/server/src/teams/approval.js";
4
+ import { simplify, } from "../../packages/server/src/teams/runtime.js";
5
+ import { audited, Denied, json, listLimit, VendorFailed, } from "../../packages/connector-kit/src/common.js";
6
+ // Teams, as the agent's own bot. Every tool reaches only where that bot is installed, within
7
+ // the key's `teams` and `channels` limits. A key with either limit reaches teams only, never
8
+ // chats. No tool takes a bot: the key's bot is the only one.
9
+ const GUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10
+ const CHANNEL = /^19:[A-Za-z0-9_.-]+@thread\.(tacv2|skype)$/;
11
+ const CHAT = /^(19:[A-Za-z0-9_.-]+@(thread\.v2|unq\.gbl\.spaces)|a:[A-Za-z0-9_.-]+)$/;
12
+ const MESSAGE = /^\d{1,20}$/;
13
+ const MAX_TEXT = 20_000;
14
+ function access(ctx) {
15
+ if (!ctx.teams)
16
+ throw new Error("Teams tools need the agent's bot");
17
+ return ctx.teams;
18
+ }
19
+ const teamsLimit = (ctx) => listLimit(ctx.limits, "teams");
20
+ const channelsLimit = (ctx) => listLimit(ctx.limits, "channels");
21
+ const confined = (ctx) => Boolean(teamsLimit(ctx) || channelsLimit(ctx));
22
+ async function places(ctx) {
23
+ const all = await access(ctx).places();
24
+ const allowed = teamsLimit(ctx);
25
+ return {
26
+ teams: all.filter((p) => p.kind === "team" &&
27
+ p.teamGroupId &&
28
+ (!allowed || allowed.includes(p.teamGroupId.toLowerCase()))),
29
+ chats: confined(ctx) ? [] : all.filter((p) => p.kind !== "team"),
30
+ };
31
+ }
32
+ async function team(ctx, id) {
33
+ if (!GUID.test(id))
34
+ throw new Denied("Give a team id from teams_list_teams");
35
+ const found = (await places(ctx)).teams.find((t) => t.teamGroupId === id.toLowerCase());
36
+ if (!found)
37
+ throw new Denied("This agent cannot reach that team");
38
+ return found;
39
+ }
40
+ // Posts and reads address a channel by its id alone, so it must be one of the team's
41
+ // channels, or a key limited to one team could reach another team's channel.
42
+ async function channel(ctx, place, id, mark) {
43
+ if (!CHANNEL.test(id))
44
+ throw new Denied("Give a channel id from teams_list_channels");
45
+ const allowed = channelsLimit(ctx);
46
+ if (allowed && !allowed.includes(id))
47
+ throw new Denied("This agent cannot reach that channel");
48
+ const data = ok(await access(ctx).listChannels(place), mark);
49
+ if (!(data?.conversations ?? []).some((c) => c.id === id))
50
+ throw new Denied("That channel is not in this team");
51
+ return id;
52
+ }
53
+ async function chat(ctx, id, { readable = false } = {}) {
54
+ if (!CHAT.test(id))
55
+ throw new Denied("Give a chat id from teams_list_teams");
56
+ const found = (await places(ctx)).chats.find((c) => c.conversationId === id);
57
+ if (!found)
58
+ throw new Denied("This agent cannot reach that chat");
59
+ if (readable && found.kind === "personal")
60
+ throw new Denied("Direct chats can't be read; earlier turns are in this session");
61
+ return found;
62
+ }
63
+ function ok(res, mark) {
64
+ mark(res.status);
65
+ if (res.status < 200 || res.status >= 300) {
66
+ const d = res.data;
67
+ const message = d?.error?.message ?? d?.message;
68
+ throw new VendorFailed(res.status, `Microsoft Teams answered ${res.status}${message ? `: ${message}` : ""}`);
69
+ }
70
+ return res.data;
71
+ }
72
+ // Who sent a message: Graph's chatMessageFromIdentitySet names a user (teamworkUserIdentity, its
73
+ // id the person's Entra object id) or an application (a bot). A display name can be anything, so
74
+ // from_id is what identifies a person; it is left null for anyone Graph does not call an Entra
75
+ // user (anonymous, federated, consumer or phone users: their id is no object in this directory).
76
+ const ENTRA_USER = new Set(["aadUser", "onPremiseAadUser"]);
77
+ function sender(m) {
78
+ const user = m.from?.user;
79
+ if (user)
80
+ return {
81
+ from_id: typeof user.id === "string" &&
82
+ GUID.test(user.id) &&
83
+ (user.userIdentityType === undefined || ENTRA_USER.has(user.userIdentityType))
84
+ ? user.id.toLowerCase()
85
+ : null,
86
+ from_kind: "user",
87
+ };
88
+ return { from_id: null, from_kind: m.from?.application ? "application" : null };
89
+ }
90
+ const message = (m) => ({
91
+ id: m.id,
92
+ created: m.createdDateTime ?? null,
93
+ ...simplify([m])[0],
94
+ ...sender(m),
95
+ ...(m.replies ? { replies: m.replies.length } : {}),
96
+ });
97
+ // A place given as a team and channel, or as a chat.
98
+ const where = {
99
+ team: z.string().optional().describe("Team id, with channel."),
100
+ channel: z.string().optional().describe("Channel id in that team."),
101
+ chat: z.string().optional().describe("Chat id, instead of a team and channel."),
102
+ };
103
+ async function resolve(ctx, input, mark, opts = {}) {
104
+ if (input.chat && !input.team && !input.channel)
105
+ return { kind: "chat", place: await chat(ctx, input.chat, opts) };
106
+ if (input.team && input.channel && !input.chat) {
107
+ const place = await team(ctx, input.team);
108
+ return {
109
+ kind: "channel",
110
+ place,
111
+ channel: await channel(ctx, place, input.channel, mark),
112
+ };
113
+ }
114
+ throw new Denied("Give either a team and a channel, or a chat");
115
+ }
116
+ // A sign-in name (UPN, guests' #EXT# form too) or an Entra object id.
117
+ const SIGN_IN = /^[A-Za-z0-9._%+'#-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
118
+ // The approver as the Microsoft connection's directory knows them (User.ReadBasic.All, which
119
+ // every Teams ceiling expects): their object id, whatever was given, and their name. The agent
120
+ // names them, so this tells it whether a sign-in name exists here (docs/teams.md "Approval
121
+ // cards").
122
+ async function approver(ctx, value, mark) {
123
+ const given = value.trim();
124
+ if (!GUID.test(given) && !SIGN_IN.test(given))
125
+ throw new Denied("Give the approver's sign-in name (e.g. ann@contoso.com) or Entra object id");
126
+ const res = await ctx.call({
127
+ method: "GET",
128
+ path: `/v1.0/users/${encodeURIComponent(given)}?$select=id,displayName`,
129
+ });
130
+ if (res.status === 404) {
131
+ mark(res.status);
132
+ throw new Denied(`No one in this organization signs in as ${given}`);
133
+ }
134
+ const user = ok(res, mark);
135
+ if (!user?.id || !GUID.test(user.id))
136
+ throw new Error("Microsoft Graph answered a user with no id");
137
+ return { id: user.id.toLowerCase(), name: (user.displayName ?? given).slice(0, 200) };
138
+ }
139
+ function text(value) {
140
+ if (!value.trim())
141
+ throw new Denied("The message is empty");
142
+ if (value.length > MAX_TEXT)
143
+ throw new Denied(`Messages are at most ${MAX_TEXT} characters`);
144
+ return value;
145
+ }
146
+ export const teamsTools = {
147
+ names: [
148
+ "teams_list_teams",
149
+ "teams_list_channels",
150
+ "teams_read_messages",
151
+ "teams_read_thread",
152
+ "teams_post_message",
153
+ "teams_reply",
154
+ "teams_request_approval",
155
+ "teams_get_approval",
156
+ ],
157
+ register(server, ctx, allowed) {
158
+ const readOnly = { readOnlyHint: true, openWorldHint: true };
159
+ const sends = { readOnlyHint: false, destructiveHint: false, openWorldHint: true };
160
+ if (allowed.has("teams_list_teams"))
161
+ server.registerTool("teams_list_teams", {
162
+ description: "List the teams and chats this agent's bot was added to and may use. Team ids are what other Teams tools take. " +
163
+ "A direct chat carries user: the Entra object id of the person in it (Teams gives such chats no name).",
164
+ inputSchema: z.object({}),
165
+ annotations: readOnly,
166
+ }, () => audited(ctx, "teams_list_teams", null, async () => {
167
+ const { teams, chats } = await places(ctx);
168
+ return json({
169
+ teams: teams.map((t) => ({ team: t.teamGroupId, name: t.name })),
170
+ chats: chats.map((c) => ({
171
+ chat: c.conversationId,
172
+ kind: c.kind === "personal" ? "direct" : "group",
173
+ name: c.name,
174
+ user: c.kind === "personal" ? c.userAadId : null,
175
+ })),
176
+ });
177
+ }));
178
+ if (allowed.has("teams_list_channels"))
179
+ server.registerTool("teams_list_channels", {
180
+ description: "List the channels of a team this agent may use.",
181
+ inputSchema: z.object({ team: z.string().describe("Team id from teams_list_teams.") }),
182
+ annotations: readOnly,
183
+ }, ({ team: id }) => audited(ctx, "teams_list_channels", id, async (mark) => {
184
+ const place = await team(ctx, id);
185
+ const data = ok(await access(ctx).listChannels(place), mark);
186
+ const allowedChannels = channelsLimit(ctx);
187
+ const channels = (data?.conversations ?? [])
188
+ .filter((c) => !allowedChannels || allowedChannels.includes(c.id))
189
+ .map((c) => ({ channel: c.id, name: c.name ?? "General" }));
190
+ return json({ channels });
191
+ }));
192
+ if (allowed.has("teams_read_messages"))
193
+ server.registerTool("teams_read_messages", {
194
+ description: "Read recent messages in a channel (top-level posts, newest first, with reply counts) or a group chat. Direct chats can't be read. " +
195
+ "Each message has from (a display name, which anyone can set), from_id (the sender's Microsoft Entra object id; null for apps) and from_kind (user or application).",
196
+ inputSchema: z.object({
197
+ ...where,
198
+ max_results: z.number().int().min(1).max(50).default(20),
199
+ }),
200
+ annotations: readOnly,
201
+ }, (input) => audited(ctx, "teams_read_messages", input.chat ?? `${input.team ?? ""}/${input.channel ?? ""}`, async (mark) => {
202
+ const r = await resolve(ctx, input, mark, { readable: true });
203
+ const path = r.kind === "chat"
204
+ ? `/v1.0/chats/${encodeURIComponent(r.place.conversationId)}/messages?$top=${input.max_results}&$orderby=createdDateTime desc`
205
+ : `/v1.0/teams/${r.place.teamGroupId}/channels/${encodeURIComponent(r.channel)}/messages?$top=${input.max_results}&$expand=replies`;
206
+ const data = ok(await access(ctx).graph(path), mark);
207
+ const messages = (data?.value ?? [])
208
+ .filter((m) => (m.messageType ?? "message") === "message")
209
+ .map(message);
210
+ return json({ messages, more: Boolean(data?.["@odata.nextLink"]) });
211
+ }));
212
+ if (allowed.has("teams_read_thread"))
213
+ server.registerTool("teams_read_thread", {
214
+ description: "Read a channel post and its replies, oldest first. Each message has from, from_id (the sender's Microsoft Entra object id; null for apps) and from_kind (user or application).",
215
+ inputSchema: z.object({
216
+ team: z.string().describe("Team id from teams_list_teams."),
217
+ channel: z.string().describe("Channel id from teams_list_channels."),
218
+ message_id: z.string().describe("The post's id, from teams_read_messages."),
219
+ }),
220
+ annotations: readOnly,
221
+ }, (input) => audited(ctx, "teams_read_thread", `${input.channel}/${input.message_id}`, async (mark) => {
222
+ const place = await team(ctx, input.team);
223
+ const ch = await channel(ctx, place, input.channel, mark);
224
+ if (!MESSAGE.test(input.message_id))
225
+ throw new Denied("Give a message id from teams_read_messages");
226
+ const base = `/v1.0/teams/${place.teamGroupId}/channels/${encodeURIComponent(ch)}/messages/${input.message_id}`;
227
+ const root = ok(await access(ctx).graph(base), mark);
228
+ const replies = ok(await access(ctx).graph(`${base}/replies?$top=50`), mark);
229
+ const list = (replies?.value ?? []).reverse();
230
+ return json({
231
+ post: message(root),
232
+ replies: list
233
+ .filter((m) => (m.messageType ?? "message") === "message")
234
+ .map(message),
235
+ });
236
+ }));
237
+ if (allowed.has("teams_post_message"))
238
+ server.registerTool("teams_post_message", {
239
+ description: "Post a message as this agent's bot: a new post in a channel (or a reply to a post with reply_to), or a message in a chat. Markdown is supported.",
240
+ inputSchema: z.object({
241
+ ...where,
242
+ text: z.string(),
243
+ reply_to: z.string().optional().describe("A channel post's id, to reply under it."),
244
+ }),
245
+ annotations: sends,
246
+ }, (input) => audited(ctx, "teams_post_message", input.chat ?? `${input.channel ?? ""}${input.reply_to ? `/${input.reply_to}` : ""}`, async (mark) => {
247
+ const body = text(input.text);
248
+ const r = await resolve(ctx, input, mark);
249
+ const teams = access(ctx);
250
+ let data;
251
+ if (r.kind === "chat") {
252
+ if (input.reply_to)
253
+ throw new Denied("reply_to is for channel posts");
254
+ data = ok(await teams.post(r.place.serviceUrl, r.place.conversationId, body), mark);
255
+ }
256
+ else if (input.reply_to) {
257
+ if (!MESSAGE.test(input.reply_to))
258
+ throw new Denied("Give a post id from teams_read_messages");
259
+ data = ok(await teams.post(r.place.serviceUrl, `${r.channel};messageid=${input.reply_to}`, body, input.reply_to), mark);
260
+ }
261
+ else
262
+ data = ok(await teams.newThread(r.place, r.channel, body), mark);
263
+ return json({ posted: true, id: data?.activityId ?? data?.id ?? null });
264
+ }));
265
+ if (allowed.has("teams_request_approval"))
266
+ server.registerTool("teams_request_approval", {
267
+ description: "Ask one person to approve or reject something: posts a card as this agent's bot, in a channel (a new post) or a chat, with Approve and Reject buttons and an optional comment. " +
268
+ "Only that person's click counts, in that team or chat: the click arrives in a request authenticated by a Bot Framework token, and the approver is matched on the Entra object id Teams sends. " +
269
+ "You choose the approver; nothing here checks that they are the right person to approve this. The guarantee is that the person you named clicked, not that this is the right person. " +
270
+ "Returns approval_id: read the answer later with teams_get_approval. Requests expire after 7 days.",
271
+ inputSchema: z.object({
272
+ ...where,
273
+ approver: z
274
+ .string()
275
+ .max(320)
276
+ .describe("The person's sign-in name (e.g. ann@contoso.com) or Entra object id."),
277
+ title: z.string().min(1).max(200),
278
+ text: z.string().min(1).max(4000).describe("What is asked, shown on the card."),
279
+ facts: z
280
+ .array(z.object({ name: z.string().min(1).max(100), value: z.string().max(1000) }))
281
+ .max(20)
282
+ .optional()
283
+ .describe("Name and value pairs shown on the card, e.g. Amount: 1,200 USD."),
284
+ }),
285
+ annotations: sends,
286
+ }, (input) => audited(ctx, "teams_request_approval", `${input.chat ?? `${input.team ?? ""}/${input.channel ?? ""}`} → ${input.approver}`, async (mark, retarget) => {
287
+ if (!input.title.trim() || !input.text.trim())
288
+ throw new Denied("The card is empty");
289
+ const r = await resolve(ctx, input, mark);
290
+ const person = await approver(ctx, input.approver, mark);
291
+ const where = r.kind === "chat" ? r.place.conversationId : r.channel;
292
+ retarget(`${where} → ${person.id}`);
293
+ const teams = access(ctx);
294
+ const token = newApprovalToken();
295
+ const row = await teams.createApproval({
296
+ tokenHash: hashApprovalToken(token),
297
+ conversationId: r.place.conversationId,
298
+ serviceUrl: r.place.serviceUrl,
299
+ approverAadId: person.id,
300
+ approverName: person.name,
301
+ title: input.title.trim(),
302
+ body: input.text.trim(),
303
+ facts: input.facts ?? [],
304
+ days: APPROVAL_DAYS,
305
+ });
306
+ let threadId;
307
+ let messageId;
308
+ try {
309
+ if (r.kind === "chat") {
310
+ const data = ok(await teams.postCard(r.place.serviceUrl, r.place.conversationId, approvalCard(row)), mark);
311
+ threadId = r.place.conversationId;
312
+ messageId = data?.id ?? null;
313
+ }
314
+ else {
315
+ const data = ok(await teams.newThreadCard(r.place, r.channel, approvalCard(row)), mark);
316
+ messageId = data?.activityId ?? null;
317
+ threadId =
318
+ data?.id ?? (messageId ? `${r.channel};messageid=${messageId}` : r.channel);
319
+ }
320
+ }
321
+ catch (error) {
322
+ await teams.discardApproval(row.id);
323
+ throw error;
324
+ }
325
+ // Without the message id the card cannot be edited later; the answer still counts.
326
+ if (messageId)
327
+ await teams.approvalPosted(row.id, threadId, messageId);
328
+ return json({ approval_id: token, message_id: messageId, expires: row.expiresAt });
329
+ }));
330
+ if (allowed.has("teams_get_approval"))
331
+ server.registerTool("teams_get_approval", {
332
+ description: "Read the answer to an approval this agent asked for with teams_request_approval: pending, approved, rejected or expired, who answered (their Entra object id and name), when, and their comment.",
333
+ inputSchema: z.object({ approval_id: z.string().max(100) }),
334
+ annotations: readOnly,
335
+ }, (input) => audited(ctx, "teams_get_approval", null, async (_mark, retarget) => {
336
+ if (!looksLikeApprovalToken(input.approval_id))
337
+ throw new Denied("That approval id is not valid");
338
+ // Another agent's id finds nothing, the same as a made-up one.
339
+ const a = await access(ctx).approval(hashApprovalToken(input.approval_id));
340
+ if (!a)
341
+ throw new Denied("No approval of this agent has that id");
342
+ retarget(a.id);
343
+ return json({
344
+ status: approvalStatus(a),
345
+ title: a.title,
346
+ approver: { id: a.approverAadId, name: a.approverName },
347
+ decided_by: a.decidedByAadId ? { id: a.decidedByAadId, name: a.decidedByName } : null,
348
+ decided_at: a.decidedAt,
349
+ comment: a.comment,
350
+ expires: a.expiresAt,
351
+ });
352
+ }));
353
+ if (allowed.has("teams_reply"))
354
+ server.registerTool("teams_reply", {
355
+ description: "Answer the Teams message that started this session, in the same thread. Use the reply_token given with the message.",
356
+ inputSchema: z.object({ reply_token: z.string(), text: z.string() }),
357
+ annotations: sends,
358
+ }, (input) => audited(ctx, "teams_reply", null, async (mark, retarget) => {
359
+ const body = text(input.text);
360
+ if (!looksLikeReplyToken(input.reply_token))
361
+ throw new Denied("That reply token is not valid");
362
+ const teams = access(ctx);
363
+ // Another agent's token, an old one or a made-up one all find nothing.
364
+ const run = await teams.runForReply(hashReplyToken(input.reply_token));
365
+ if (!run)
366
+ throw new Denied("That reply token is not valid or has expired");
367
+ retarget(run.threadId);
368
+ const place = (await teams.places()).find((p) => p.conversationId === run.conversationId);
369
+ if (!place)
370
+ throw new Denied("The bot is no longer in that conversation");
371
+ // The key's limits may have changed since the message arrived.
372
+ if (place.kind === "team") {
373
+ await channel(ctx, await team(ctx, place.teamGroupId ?? ""), run.threadId.split(";")[0], mark);
374
+ }
375
+ else if (confined(ctx))
376
+ throw new Denied("This agent cannot reach that chat");
377
+ // A reply is used only by a post that went through.
378
+ if (!(await teams.claimReply(run.id)))
379
+ throw new Denied("That reply token is not valid or has expired");
380
+ try {
381
+ ok(await teams.post(place.serviceUrl, run.threadId, body, run.triggerActivityId), mark);
382
+ }
383
+ catch (error) {
384
+ await teams.releaseReply(run.id);
385
+ throw error;
386
+ }
387
+ return json({ replied: true });
388
+ }));
389
+ },
390
+ };
391
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../connectors/teams/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { z } from "zod";
2
+ import { ConnectError } from "./types.js";
3
+ // The names this deployment shows and creates: in copy, in the connectors' steps (as
4
+ // {brand.*} placeholders) and in what it makes in a customer's tenant. The names it creates
5
+ // (mailbox group, Azure role, resource group, bot and app names) must not change once
6
+ // customers have made them, so an install sets them once.
7
+ const https = z.url({ protocol: /^https$/ });
8
+ // Names go into copy and into PowerShell strings, double- and single-quoted, so none of
9
+ // $ " ' ` { } < >.
10
+ const nameText = z
11
+ .string()
12
+ .trim()
13
+ .regex(/^[\p{L}\p{N} .,&()-]{1,80}$/u);
14
+ const name = (fallback) => nameText.default(fallback);
15
+ export const brandingSchema = z.strictObject({
16
+ productName: name("Enterprise Agent Connect"),
17
+ logoUrl: https.optional(),
18
+ // Prefix of what it names in a tenant (bot app `<prefix>-bot-<id>`, Azure Bot `<prefix>-<8>`).
19
+ resourcePrefix: z
20
+ .string()
21
+ .regex(/^[a-z][a-z0-9-]{1,20}$/)
22
+ .default("eac"),
23
+ microsoft: z
24
+ .strictObject({
25
+ appName: name("Enterprise Agent Connect"),
26
+ mailboxGroup: name("Agent Mailboxes"),
27
+ mailboxGroupAlias: z
28
+ .string()
29
+ .regex(/^[a-z0-9-]{1,64}$/)
30
+ .default("agent-mailboxes"),
31
+ botRole: name("Agent Connect bots"),
32
+ })
33
+ .default({
34
+ appName: "Enterprise Agent Connect",
35
+ mailboxGroup: "Agent Mailboxes",
36
+ mailboxGroupAlias: "agent-mailboxes",
37
+ botRole: "Agent Connect bots",
38
+ }),
39
+ teams: z
40
+ .strictObject({
41
+ resourceGroup: z
42
+ .string()
43
+ .regex(/^[A-Za-z0-9._()-]{1,90}$/)
44
+ .default("agent-connect"),
45
+ // The Teams app manifest's developer. Unset: no Teams package can be made until it is.
46
+ developer: z
47
+ .strictObject({
48
+ name: nameText.max(32),
49
+ websiteUrl: https,
50
+ privacyUrl: https,
51
+ termsOfUseUrl: https,
52
+ })
53
+ .optional(),
54
+ })
55
+ .default({ resourceGroup: "agent-connect" }),
56
+ });
57
+ export const DEFAULT_BRANDING = brandingSchema.parse({});
58
+ export function parseBranding(raw) {
59
+ const parsed = brandingSchema.safeParse(raw ?? {});
60
+ if (!parsed.success)
61
+ throw new Error(`branding: ${z.prettifyError(parsed.error)}`);
62
+ return parsed.data;
63
+ }
64
+ // ponytail: one branding per process (set by createAgentConnect before anything reads it);
65
+ // thread it through the deps if two differently branded instances must share a process.
66
+ let current = DEFAULT_BRANDING;
67
+ let set = false;
68
+ export const brand = () => current;
69
+ export function setBranding(b) {
70
+ if (set && JSON.stringify(b) !== JSON.stringify(current))
71
+ throw new Error("This process already runs with another branding");
72
+ current = b;
73
+ set = true;
74
+ }
75
+ /** Fills `{brand.a.b}` placeholders; one naming no text field of the branding throws. */
76
+ export function fillBrand(text, b = current) {
77
+ return text.replace(/\{brand\.([A-Za-z.]+)\}/g, (whole, path) => {
78
+ let v = b;
79
+ for (const part of path.split("."))
80
+ v = v?.[part];
81
+ if (typeof v !== "string")
82
+ throw new Error(`${whole} names no branding text`);
83
+ return v;
84
+ });
85
+ }
86
+ /** fillBrand over every string in a parsed JSON value. */
87
+ export function fillBrandDeep(value, b = current) {
88
+ if (typeof value === "string")
89
+ return fillBrand(value, b);
90
+ if (Array.isArray(value))
91
+ return value.map((v) => fillBrandDeep(v, b));
92
+ if (value && typeof value === "object")
93
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, fillBrandDeep(v, b)]));
94
+ return value;
95
+ }
96
+ /** The Teams manifest's developer, which a package needs. */
97
+ export function teamsDeveloper(b = current) {
98
+ if (!b.teams.developer)
99
+ throw new ConnectError("Set branding.teams.developer (name and https website, privacy and terms addresses) to make Teams packages");
100
+ return b.teams.developer;
101
+ }
102
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../../../../packages/connector-kit/src/branding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { constants, createHash, generateKeyPairSync, randomBytes, randomUUID, sign, X509Certificate, } from "node:crypto";
2
+ // A key pair the service makes for one connection: the private key is sealed with the connection's
3
+ // credential and never leaves the service; the self-signed certificate is what the admin
4
+ // uploads to their own app registration. Node can parse X.509 but not create it, so the
5
+ // certificate's DER is written here (RFC 5280, no extensions).
6
+ const VALID_DAYS = 730;
7
+ function der(tag, ...parts) {
8
+ const body = Buffer.concat(parts);
9
+ let length;
10
+ if (body.length < 0x80)
11
+ length = Buffer.from([body.length]);
12
+ else {
13
+ const bytes = [];
14
+ for (let n = body.length; n > 0; n = Math.floor(n / 256))
15
+ bytes.unshift(n % 256);
16
+ length = Buffer.from([0x80 | bytes.length, ...bytes]);
17
+ }
18
+ return Buffer.concat([Buffer.from([tag]), length, body]);
19
+ }
20
+ const seq = (...parts) => der(0x30, ...parts);
21
+ function oid(dotted) {
22
+ const [a, b, ...rest] = dotted.split(".").map(Number);
23
+ const bytes = [40 * a + b];
24
+ for (const n of rest) {
25
+ const chunk = [n & 0x7f];
26
+ for (let v = n >> 7; v > 0; v >>= 7)
27
+ chunk.unshift((v & 0x7f) | 0x80);
28
+ bytes.push(...chunk);
29
+ }
30
+ return der(0x06, Buffer.from(bytes));
31
+ }
32
+ // UTCTime, YYMMDDHHMMSSZ: valid for dates before 2050.
33
+ const utcTime = (d) => der(0x17, Buffer.from(d.toISOString().replace(/[-:T]/g, "").slice(2, 14) + "Z"));
34
+ const name = (cn) => seq(der(0x31, seq(oid("2.5.4.3"), der(0x0c, Buffer.from(cn, "utf8")))));
35
+ export function newCertificate(commonName, now = new Date()) {
36
+ const { privateKey, publicKey } = generateKeyPairSync("rsa", { modulusLength: 2048 });
37
+ const serial = randomBytes(16);
38
+ serial[0] = (serial[0] & 0x7f) | 0x01;
39
+ const sha256WithRsa = seq(oid("1.2.840.113549.1.1.11"), der(0x05));
40
+ const tbs = seq(der(0xa0, der(0x02, Buffer.from([2]))), der(0x02, serial), sha256WithRsa, name(commonName), seq(utcTime(now), utcTime(new Date(now.getTime() + VALID_DAYS * 86_400_000))), name(commonName), publicKey.export({ type: "spki", format: "der" }));
41
+ const signature = sign("sha256", tbs, privateKey);
42
+ const cert = seq(tbs, sha256WithRsa, der(0x03, Buffer.from([0]), signature));
43
+ const lines = cert.toString("base64").match(/.{1,64}/g);
44
+ return {
45
+ certificate: `-----BEGIN CERTIFICATE-----\n${lines.join("\n")}\n-----END CERTIFICATE-----\n`,
46
+ privateKey: privateKey.export({ type: "pkcs8", format: "pem" }).toString(),
47
+ };
48
+ }
49
+ /** What the admin sees of a certificate: Entra lists it by its SHA-1 thumbprint. */
50
+ export function describeCertificate(pem) {
51
+ const cert = new X509Certificate(pem);
52
+ return {
53
+ thumbprint: cert.fingerprint.replaceAll(":", ""),
54
+ expiresAt: new Date(cert.validTo).toISOString(),
55
+ };
56
+ }
57
+ const b64url = (v) => Buffer.from(v).toString("base64url");
58
+ /** A signed client assertion (RFC 7523) for Microsoft's token endpoint, valid five minutes.
59
+ * Microsoft pairs the x5t#S256 header with PS256 (RSA-PSS). */
60
+ export function clientAssertion(input) {
61
+ const raw = new X509Certificate(input.certificate).raw;
62
+ const now = Math.floor((input.now ?? Date.now()) / 1000);
63
+ const header = b64url(JSON.stringify({
64
+ alg: "PS256",
65
+ typ: "JWT",
66
+ "x5t#S256": b64url(createHash("sha256").update(raw).digest()),
67
+ }));
68
+ const payload = b64url(JSON.stringify({
69
+ aud: input.tokenUrl,
70
+ iss: input.clientId,
71
+ sub: input.clientId,
72
+ jti: randomUUID(),
73
+ nbf: now,
74
+ iat: now,
75
+ exp: now + 300,
76
+ }));
77
+ const signature = sign("sha256", Buffer.from(`${header}.${payload}`), {
78
+ key: input.privateKey,
79
+ padding: constants.RSA_PKCS1_PSS_PADDING,
80
+ saltLength: constants.RSA_PSS_SALTLEN_DIGEST,
81
+ });
82
+ return `${header}.${payload}.${b64url(signature)}`;
83
+ }
84
+ //# sourceMappingURL=certificate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.js","sourceRoot":"","sources":["../../../../packages/connector-kit/src/certificate.ts"],"names":[],"mappings":"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"}