@hahnfeld/teams-adapter 1.0.9

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +286 -0
  3. package/dist/activity.d.ts +23 -0
  4. package/dist/activity.d.ts.map +1 -0
  5. package/dist/activity.js +3 -0
  6. package/dist/activity.js.map +1 -0
  7. package/dist/adapter.d.ts +174 -0
  8. package/dist/adapter.d.ts.map +1 -0
  9. package/dist/adapter.js +1583 -0
  10. package/dist/adapter.js.map +1 -0
  11. package/dist/app-package.d.ts +7 -0
  12. package/dist/app-package.d.ts.map +1 -0
  13. package/dist/app-package.js +158 -0
  14. package/dist/app-package.js.map +1 -0
  15. package/dist/assistant.d.ts +7 -0
  16. package/dist/assistant.d.ts.map +1 -0
  17. package/dist/assistant.js +32 -0
  18. package/dist/assistant.js.map +1 -0
  19. package/dist/commands/admin.d.ts +27 -0
  20. package/dist/commands/admin.d.ts.map +1 -0
  21. package/dist/commands/admin.js +146 -0
  22. package/dist/commands/admin.js.map +1 -0
  23. package/dist/commands/agents.d.ts +13 -0
  24. package/dist/commands/agents.d.ts.map +1 -0
  25. package/dist/commands/agents.js +98 -0
  26. package/dist/commands/agents.js.map +1 -0
  27. package/dist/commands/doctor.d.ts +8 -0
  28. package/dist/commands/doctor.d.ts.map +1 -0
  29. package/dist/commands/doctor.js +49 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/index.d.ts +16 -0
  32. package/dist/commands/index.d.ts.map +1 -0
  33. package/dist/commands/index.js +253 -0
  34. package/dist/commands/index.js.map +1 -0
  35. package/dist/commands/integrate.d.ts +8 -0
  36. package/dist/commands/integrate.d.ts.map +1 -0
  37. package/dist/commands/integrate.js +45 -0
  38. package/dist/commands/integrate.js.map +1 -0
  39. package/dist/commands/menu.d.ts +16 -0
  40. package/dist/commands/menu.d.ts.map +1 -0
  41. package/dist/commands/menu.js +92 -0
  42. package/dist/commands/menu.js.map +1 -0
  43. package/dist/commands/new-session.d.ts +13 -0
  44. package/dist/commands/new-session.d.ts.map +1 -0
  45. package/dist/commands/new-session.js +105 -0
  46. package/dist/commands/new-session.js.map +1 -0
  47. package/dist/commands/session.d.ts +22 -0
  48. package/dist/commands/session.d.ts.map +1 -0
  49. package/dist/commands/session.js +110 -0
  50. package/dist/commands/session.js.map +1 -0
  51. package/dist/commands/settings.d.ts +8 -0
  52. package/dist/commands/settings.d.ts.map +1 -0
  53. package/dist/commands/settings.js +54 -0
  54. package/dist/commands/settings.js.map +1 -0
  55. package/dist/conversation-store.d.ts +38 -0
  56. package/dist/conversation-store.d.ts.map +1 -0
  57. package/dist/conversation-store.js +101 -0
  58. package/dist/conversation-store.js.map +1 -0
  59. package/dist/draft-manager.d.ts +47 -0
  60. package/dist/draft-manager.d.ts.map +1 -0
  61. package/dist/draft-manager.js +136 -0
  62. package/dist/draft-manager.js.map +1 -0
  63. package/dist/formatting.d.ts +121 -0
  64. package/dist/formatting.d.ts.map +1 -0
  65. package/dist/formatting.js +392 -0
  66. package/dist/formatting.js.map +1 -0
  67. package/dist/graph.d.ts +59 -0
  68. package/dist/graph.d.ts.map +1 -0
  69. package/dist/graph.js +261 -0
  70. package/dist/graph.js.map +1 -0
  71. package/dist/index.d.ts +16 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +10 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/media.d.ts +29 -0
  76. package/dist/media.d.ts.map +1 -0
  77. package/dist/media.js +120 -0
  78. package/dist/media.js.map +1 -0
  79. package/dist/permissions.d.ts +15 -0
  80. package/dist/permissions.d.ts.map +1 -0
  81. package/dist/permissions.js +221 -0
  82. package/dist/permissions.js.map +1 -0
  83. package/dist/plugin.d.ts +13 -0
  84. package/dist/plugin.d.ts.map +1 -0
  85. package/dist/plugin.js +689 -0
  86. package/dist/plugin.js.map +1 -0
  87. package/dist/renderer.d.ts +49 -0
  88. package/dist/renderer.d.ts.map +1 -0
  89. package/dist/renderer.js +55 -0
  90. package/dist/renderer.js.map +1 -0
  91. package/dist/send-utils.d.ts +15 -0
  92. package/dist/send-utils.d.ts.map +1 -0
  93. package/dist/send-utils.js +64 -0
  94. package/dist/send-utils.js.map +1 -0
  95. package/dist/task-modules.d.ts +34 -0
  96. package/dist/task-modules.d.ts.map +1 -0
  97. package/dist/task-modules.js +136 -0
  98. package/dist/task-modules.js.map +1 -0
  99. package/dist/types.d.ts +26 -0
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +3 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/validators.d.ts +54 -0
  104. package/dist/validators.d.ts.map +1 -0
  105. package/dist/validators.js +142 -0
  106. package/dist/validators.js.map +1 -0
  107. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenACP
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # @hahnfeld/teams-adapter
2
+
3
+ Microsoft Teams adapter plugin for [OpenACP](https://github.com/Open-ACP/OpenACP) — Adaptive Cards, slash commands, streaming.
4
+
5
+ ## Features
6
+
7
+ - **Adaptive Cards** — Rich tool card rendering with progress indicators and action buttons
8
+ - **Slash Commands** — Full command suite: `/new`, `/cancel`, `/agents`, `/menu`, and more
9
+ - **Streaming** — Real-time text updates via Teams message editing
10
+ - **Threads** — Session threads within Teams channels
11
+ - **Permissions** — Allow/Deny/Always Allow via Adaptive Card buttons
12
+ - **Output Modes** — Low/Medium/High detail levels
13
+ - **File Sharing** — Upload and share files via Microsoft Graph / OneDrive
14
+ - **Interactive Install Wizard** — Guided setup with credential validation, auto-discovery, and app package generation
15
+ - **Auto-session Creation** — First message automatically creates a session with the default agent
16
+
17
+ ## Prerequisites
18
+
19
+ - [OpenACP CLI](https://github.com/Open-ACP/OpenACP) `>= 2026.0.0`
20
+ - Node.js 18+
21
+ - An **Azure Bot registration** with the Microsoft Teams channel enabled
22
+ - A Microsoft 365 tenant with a Teams team and channel (a [Business Basic trial](https://www.microsoft.com/en-us/microsoft-365/business/compare-all-plans) works for testing)
23
+
24
+ ## Installation
25
+
26
+ ### Option A: OpenACP plugin install (recommended)
27
+
28
+ ```bash
29
+ openacp plugin install @hahnfeld/teams-adapter
30
+ ```
31
+
32
+ This launches an interactive wizard that walks you through Azure Bot setup, credential validation, team/channel selection, and generates a Teams app package for sideloading.
33
+
34
+ ### Option B: Manual npm install
35
+
36
+ ```bash
37
+ npm install @hahnfeld/teams-adapter
38
+ # or
39
+ pnpm add @hahnfeld/teams-adapter
40
+ ```
41
+
42
+ ## Azure Bot Setup
43
+
44
+ Before configuring the adapter you need an Azure Bot registration. If you don't have one yet:
45
+
46
+ 1. Go to the [Azure Bot creation page](https://portal.azure.com/#create/Microsoft.AzureBot)
47
+ 2. Fill in:
48
+ - **Bot handle**: any unique name (e.g. `openacp-bot`)
49
+ - **Pricing tier**: Free (F0) for testing
50
+ - **App type**: "Single Tenant" for enterprise use
51
+ - **Creation type**: "Create new Microsoft App ID"
52
+ 3. Click **Create** and wait for deployment
53
+ 4. Go to the Bot resource > **Settings** > **Configuration**
54
+ - Copy the **Microsoft App ID** — this is your `botAppId`
55
+ 5. Click **Manage Password** > **New client secret**
56
+ - Copy the secret value immediately (shown only once) — this is your `botAppPassword`
57
+ 6. Under **Channels**, add the **Microsoft Teams** channel
58
+
59
+ For full details see the [Azure Bot Service docs](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration).
60
+
61
+ ## Configuration
62
+
63
+ ### Interactive wizard
64
+
65
+ If you installed via `openacp plugin install`, the wizard runs automatically. To re-run it later:
66
+
67
+ ```bash
68
+ openacp plugin configure @hahnfeld/teams-adapter
69
+ ```
70
+
71
+ The wizard guides you through:
72
+ 1. Bot credential entry and real-time validation
73
+ 2. Tenant type selection (single-tenant enterprise vs. multi-tenant)
74
+ 3. Team and channel selection — auto-discovered via Graph API, or paste a Teams channel link
75
+ 4. Optional notification channel for session completions and errors
76
+ 5. Optional Graph API file sharing (OneDrive)
77
+ 6. **Auto-generates a Teams app package** (`openacp-bot.zip`) for sideloading
78
+
79
+ ### Adding the bot to Teams
80
+
81
+ After the wizard completes, you need to upload the app package to Teams:
82
+
83
+ 1. The wizard generates `openacp-bot.zip` — note the path it prints
84
+ 2. Open Microsoft Teams
85
+ 3. Go to **Apps** (left sidebar) > **Manage your apps** > **Upload a custom app**
86
+ 4. Select the `openacp-bot.zip` file
87
+ 5. Click **Add to a team** > select your team > **Set up a bot**
88
+
89
+ The bot will now appear in your team. You can @mention it in channels or DM it directly.
90
+
91
+ ### Manual configuration
92
+
93
+ Add the following to your `openacp.yaml`:
94
+
95
+ ```yaml
96
+ channels:
97
+ teams:
98
+ enabled: true
99
+ botAppId: "${TEAMS_BOT_APP_ID}"
100
+ botAppPassword: "${TEAMS_BOT_APP_PASSWORD}"
101
+ tenantId: "${TEAMS_TENANT_ID}"
102
+ teamId: "${TEAMS_TEAM_ID}"
103
+ channelId: "${TEAMS_CHANNEL_ID}"
104
+ botPort: 3978 # Bot Framework port (default)
105
+ notificationChannelId: "${TEAMS_NOTIFICATION_CHANNEL_ID}" # optional
106
+ assistantThreadId: null # auto-set after first run
107
+ graphClientSecret: "${TEAMS_GRAPH_CLIENT_SECRET}" # optional, for file sharing
108
+ ```
109
+
110
+ ### Configuration reference
111
+
112
+ | Field | Type | Required | Description |
113
+ |-------|------|----------|-------------|
114
+ | `enabled` | `boolean` | Yes | Enable the Teams adapter |
115
+ | `botAppId` | `string` | Yes | Azure AD App ID for the bot |
116
+ | `botAppPassword` | `string` | Yes | Bot client secret |
117
+ | `tenantId` | `string` | Yes | Microsoft tenant ID (GUID), or `botframework.com` for multi-tenant |
118
+ | `teamId` | `string` | Yes | Default team ID (groupId GUID) |
119
+ | `channelId` | `string` | Yes | Primary channel for sessions (e.g. `19:abc@thread.tacv2`) |
120
+ | `botPort` | `number` | No | Bot Framework HTTP server port (default: `3978`) |
121
+ | `notificationChannelId` | `string \| null` | No | Separate channel for notifications |
122
+ | `assistantThreadId` | `string \| null` | No | Thread for the assistant (auto-populated) |
123
+ | `graphClientSecret` | `string` | No | Azure AD client secret for Graph API file sharing |
124
+
125
+ ### Finding your Team and Channel IDs
126
+
127
+ **From a channel link (easiest):**
128
+ 1. Open Microsoft Teams
129
+ 2. Right-click the channel name > **Get link to channel**
130
+ 3. The link contains `groupId` (Team ID) and the channel path
131
+
132
+ Both `teams.microsoft.com` and `teams.cloud.microsoft` link formats are supported.
133
+
134
+ **From the Azure/Graph API:**
135
+ - Team ID = the `groupId` parameter from the Teams URL
136
+ - Channel ID = the encoded string like `19:xxx@thread.tacv2`
137
+
138
+ ### Networking: Bot port vs API port
139
+
140
+ The Teams adapter runs its **own HTTP server** for Bot Framework webhook traffic. This is separate from the OpenACP API server:
141
+
142
+ | Server | Default Port | Purpose |
143
+ |--------|-------------|---------|
144
+ | **Bot Framework** (this adapter) | `3978` | Receives messages from Azure Bot Service |
145
+ | **OpenACP API** | `21420` | REST API, SSE, web UI |
146
+
147
+ **Your tunnel must point to the bot port (3978), not the OpenACP API port.** If you use OpenACP's built-in tunnel, it tunnels the API port — the Teams adapter requests its own separate tunnel on the bot port automatically.
148
+
149
+ The bot port is configurable via the `botPort` setting (default: `3978`, the Bot Framework standard).
150
+
151
+ ### Messaging endpoint
152
+
153
+ After installation, set the bot's messaging endpoint in Azure:
154
+
155
+ 1. Azure Portal > Bot resource > **Configuration** > **Messaging endpoint**
156
+ 2. Set it to: `https://<your-tunnel-url>/api/messages`
157
+ 3. The URL must reach port 3978 (or your configured `botPort`) on the machine running OpenACP
158
+
159
+ ### Tunneling
160
+
161
+ The adapter automatically requests a tunnel on the bot port at startup if an OpenACP tunnel provider is available. The tunnel URL is logged on boot.
162
+
163
+ **Recommended: `@hahnfeld/devtunnel-provider`** — a tunnel provider plugin using [Microsoft Dev Tunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started), which aligns with the Microsoft/Azure ecosystem:
164
+
165
+ ```bash
166
+ openacp plugin install @hahnfeld/devtunnel-provider
167
+ ```
168
+
169
+ **Manual tunnel setup** (if not using an OpenACP tunnel provider):
170
+
171
+ ```bash
172
+ # Install Dev Tunnels CLI
173
+ brew install --cask devtunnel # macOS
174
+
175
+ # Login and create a persistent tunnel
176
+ devtunnel user login
177
+ devtunnel create --allow-anonymous
178
+ devtunnel port create -p 3978
179
+
180
+ # Host it (use the same tunnel ID each time for a stable URL)
181
+ devtunnel host <tunnel-id> --allow-anonymous
182
+ ```
183
+
184
+ Set the tunnel URL as the messaging endpoint in Azure: `https://<id>.devtunnels.ms/api/messages`
185
+
186
+ > **Important:** Always use `--allow-anonymous` — Azure Bot Service cannot authenticate with Dev Tunnel auth.
187
+
188
+ ## Slash Commands
189
+
190
+ | Command | Description |
191
+ |---------|-------------|
192
+ | `/new [agent]` | Create a new agent session |
193
+ | `/newchat` | New chat, same agent & workspace |
194
+ | `/cancel` | Cancel the current session |
195
+ | `/status` | Show session or global status |
196
+ | `/sessions` | List all sessions |
197
+ | `/agents` | List available agents |
198
+ | `/install <name>` | Install an agent by name |
199
+ | `/menu` | Show the action menu |
200
+ | `/help` | Show help |
201
+ | `/outputmode low\|medium\|high` | Set output detail level |
202
+ | `/bypass` | Auto-approve permissions |
203
+ | `/doctor` | Run system diagnostics |
204
+ | `/handoff` | Generate terminal resume command |
205
+ | `/restart` | Restart OpenACP |
206
+ | `/respawn` | Restart the assistant session |
207
+ | `/update` | Update to latest version |
208
+ | `/settings` | Show configuration settings |
209
+ | `/integrate` | Manage agent integrations |
210
+ | `/clear` | Reset the assistant session |
211
+ | `/tts [on\|off]` | Toggle Text to Speech |
212
+ | `/mode` | Switch session mode |
213
+ | `/model` | Switch AI model |
214
+ | `/thought` | Adjust thinking level |
215
+
216
+ ## Uninstalling
217
+
218
+ ```bash
219
+ openacp plugin uninstall @hahnfeld/teams-adapter --purge
220
+ ```
221
+
222
+ The `--purge` flag removes all saved settings. After uninstalling, you may also want to:
223
+ 1. Remove the bot from your Teams team
224
+ 2. Delete the Azure Bot resource in the Azure Portal
225
+
226
+ ## Development
227
+
228
+ ```bash
229
+ # Install dependencies
230
+ pnpm install
231
+
232
+ # Build
233
+ pnpm build
234
+
235
+ # Watch mode
236
+ pnpm dev
237
+
238
+ # Run tests
239
+ pnpm test
240
+ ```
241
+
242
+ ## Architecture
243
+
244
+ ```
245
+ src/
246
+ ├── index.ts # Plugin entry point & public exports
247
+ ├── plugin.ts # Plugin factory (install wizard, configure, setup/teardown)
248
+ ├── adapter.ts # TeamsAdapter — extends MessagingAdapter
249
+ ├── app-package.ts # Teams app manifest package generator
250
+ ├── renderer.ts # TeamsRenderer (Adaptive Card rendering)
251
+ ├── activity.ts # ActivityTracker (tool card state, streaming)
252
+ ├── formatting.ts # Tool card formatting, usage cards, citations
253
+ ├── draft-manager.ts # Message draft handling
254
+ ├── permissions.ts # PermissionHandler (Adaptive Card buttons)
255
+ ├── graph.ts # GraphFileClient (OneDrive file sharing)
256
+ ├── media.ts # File download/upload utilities
257
+ ├── conversation-store.ts # Conversation reference storage
258
+ ├── send-utils.ts # Message sending helpers (Teams SDK compat)
259
+ ├── task-modules.ts # Task module dialogs (new session, settings)
260
+ ├── assistant.ts # Assistant session spawning
261
+ ├── validators.ts # Credential & tenant validation, Teams link parsing
262
+ ├── types.ts # TeamsChannelConfig, TeamsPlatformData
263
+ └── commands/
264
+ ├── index.ts # Command router + SLASH_COMMANDS registry
265
+ ├── new-session.ts # /new, /newchat
266
+ ├── session.ts # /cancel, /status, /sessions, /handoff
267
+ ├── admin.ts # /bypass, /tts, /restart, /respawn, /update, /outputmode
268
+ ├── menu.ts # /menu, /help, /clear
269
+ ├── agents.ts # /agents, /install
270
+ ├── doctor.ts # /doctor
271
+ ├── integrate.ts # /integrate
272
+ └── settings.ts # /settings
273
+ ```
274
+
275
+ ## Tech Stack
276
+
277
+ - [`@microsoft/teams.apps`](https://www.npmjs.com/package/@microsoft/teams.apps) — App class, server hosting, activity routing
278
+ - [`@microsoft/teams.botbuilder`](https://www.npmjs.com/package/@microsoft/teams.botbuilder) — Bot Framework adapter plugin
279
+ - [`@microsoft/agents-hosting`](https://www.npmjs.com/package/@microsoft/agents-hosting) — Express server hosting
280
+ - [`botbuilder`](https://www.npmjs.com/package/botbuilder) — CloudAdapter for single-tenant auth
281
+ - [`botframework-connector`](https://www.npmjs.com/package/botframework-connector) — Credential factory for token validation
282
+ - [`@openacp/plugin-sdk`](https://github.com/Open-ACP/OpenACP) — OpenACP plugin interface
283
+
284
+ ## License
285
+
286
+ MIT
@@ -0,0 +1,23 @@
1
+ export { ToolStateMap, ThoughtBuffer, DisplaySpecBuilder } from "@openacp/plugin-sdk";
2
+ export type { OutputMode, ToolDisplaySpec, ToolCardSnapshot, PlanEntry, ToolCallMeta, ViewerLinks, } from "@openacp/plugin-sdk";
3
+ export interface ToolEntry {
4
+ id: string;
5
+ name: string;
6
+ kind: string;
7
+ rawInput: unknown;
8
+ content: string | null;
9
+ status: string;
10
+ viewerLinks?: {
11
+ file?: string;
12
+ diff?: string;
13
+ };
14
+ diffStats?: {
15
+ added: number;
16
+ removed: number;
17
+ };
18
+ displaySummary?: string;
19
+ displayTitle?: string;
20
+ displayKind?: string;
21
+ isNoise: boolean;
22
+ }
23
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEtF,YAAY,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB"}
@@ -0,0 +1,3 @@
1
+ // Re-export activity tracking types from plugin-sdk
2
+ export { ToolStateMap, ThoughtBuffer, DisplaySpecBuilder } from "@openacp/plugin-sdk";
3
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,174 @@
1
+ import type { TurnContext } from "@microsoft/agents-hosting";
2
+ import type { OutgoingMessage, PermissionRequest, NotificationMessage, OpenACPCore, DisplayVerbosity, AdapterCapabilities, IRenderer } from "@openacp/plugin-sdk";
3
+ import { MessagingAdapter } from "@openacp/plugin-sdk";
4
+ import type { TeamsChannelConfig } from "./types.js";
5
+ export declare class TeamsAdapter extends MessagingAdapter {
6
+ readonly name = "teams";
7
+ readonly renderer: IRenderer;
8
+ readonly capabilities: AdapterCapabilities;
9
+ readonly core: OpenACPCore;
10
+ private app;
11
+ private teamsConfig;
12
+ private sendQueue;
13
+ private draftManager;
14
+ private permissionHandler;
15
+ private notificationChannelId?;
16
+ private assistantSession;
17
+ private assistantInitializing;
18
+ private fileService;
19
+ private graphClient?;
20
+ private conversationStore;
21
+ /**
22
+ * Per-session TurnContext references, set during inbound message handling.
23
+ * Handler overrides read from this map during sendMessage dispatch.
24
+ */
25
+ private _sessionContexts;
26
+ private _sessionOutputModes;
27
+ /**
28
+ * Per-session serial dispatch queues — matches Telegram's _dispatchQueues pattern.
29
+ * SessionBridge fires sendMessage() as fire-and-forget, so multiple events can arrive
30
+ * concurrently. Without serialization, fast handlers overtake slow ones, causing
31
+ * out-of-order delivery. This queue ensures events are processed in arrival order.
32
+ *
33
+ * Entries are replaced with Promise.resolve() once their chain settles, preventing
34
+ * unbounded closure growth for long-lived sessions.
35
+ */
36
+ private _dispatchQueues;
37
+ /** Track processed activity IDs to handle Teams 15-second retry deduplication */
38
+ private _processedActivities;
39
+ private _processedCleanupTimer?;
40
+ /** Messages buffered during assistant initialization — replayed once ready. Capped to prevent unbounded growth. */
41
+ private static readonly MAX_INIT_BUFFER;
42
+ private _assistantInitBuffer;
43
+ /** Bot token cache for proactive messaging via connector REST API */
44
+ private _botTokenCache?;
45
+ constructor(core: OpenACPCore, config: TeamsChannelConfig);
46
+ private _started;
47
+ start(): Promise<void>;
48
+ stop(): Promise<void>;
49
+ private setupMessageHandler;
50
+ /**
51
+ * Handle Action.Submit payloads from Adaptive Cards.
52
+ *
53
+ * Action.Submit (v1.2 compatible) sends the card's data directly as
54
+ * activity.value with no text. This handles permission responses, command
55
+ * buttons, and output mode changes — all of which embed a `verb` field.
56
+ */
57
+ private handleSubmitAction;
58
+ /**
59
+ * Shared card action dispatch — handles verbs from both Action.Submit and
60
+ * Action.Execute (invoke) paths. Eliminates duplication between
61
+ * handleSubmitAction and cardActionHandler.
62
+ */
63
+ private dispatchCardVerb;
64
+ /**
65
+ * Handle message reactions (like, heart, laugh, surprised, sad, angry).
66
+ *
67
+ * Teams sends messageReaction activities when users react to bot messages.
68
+ * We log them as engagement signals and emit an event so plugins can act
69
+ * on them (e.g., aggregate feedback, adjust behavior).
70
+ */
71
+ private setupReactionHandler;
72
+ /**
73
+ * Create a session in the background — sends status updates to the conversation.
74
+ * Runs async without blocking the invoke response.
75
+ */
76
+ private createSessionInBackground;
77
+ /**
78
+ * Handle form submissions from inline wizard cards (dialogAction payloads).
79
+ * These come from Action.Execute buttons on cards rendered directly in chat.
80
+ */
81
+ private handleDialogAction;
82
+ private setupCardActionHandler;
83
+ private cardActionHandler;
84
+ private getCommandRegistry;
85
+ handleCommand(text: string, context: TurnContext, sessionId: string | null, userId: string): Promise<void>;
86
+ private renderCommandResponse;
87
+ private setupAssistant;
88
+ respawnAssistant(): Promise<void>;
89
+ restartAssistant(): Promise<void>;
90
+ /** Send a typing indicator to the user. Non-critical — failures are silently ignored. */
91
+ private sendTyping;
92
+ /**
93
+ * Acquire a bot framework token for proactive messaging via the MSA/AAD endpoint.
94
+ * Required when posting to the Bot Connector REST API outside of a turn context.
95
+ */
96
+ private acquireBotToken;
97
+ /**
98
+ * Validate that a serviceUrl is a trusted Bot Framework endpoint.
99
+ * Prevents SSRF where a spoofed serviceUrl could redirect bot tokens.
100
+ *
101
+ * @see https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference
102
+ */
103
+ private static readonly TRUSTED_SERVICE_URL_PATTERNS;
104
+ static isValidServiceUrl(url: string): boolean;
105
+ /** AI-generated content entity — attached to all outbound messages for the Teams "AI generated" badge */
106
+ private static readonly AI_ENTITY;
107
+ /**
108
+ * Send a Teams activity with exponential backoff retry on transient failures.
109
+ * Handles HTTP 429 (rate limited), 502, 504 per Microsoft best practices.
110
+ */
111
+ private sendActivityWithRetry;
112
+ private resolveMode;
113
+ /**
114
+ * Primary outbound dispatch — routes agent messages to Teams.
115
+ *
116
+ * Wraps the base class `sendMessage` in a per-session promise chain (_dispatchQueues)
117
+ * so concurrent events fired from SessionBridge are serialized and delivered in order,
118
+ * preventing fast handlers from overtaking slower ones (matches Telegram pattern).
119
+ *
120
+ * Context is NOT deleted after dispatch — it persists from the inbound message handler
121
+ * and is available for the entire session lifetime, avoiding the race condition where
122
+ * async handlers lose their context mid-execution.
123
+ */
124
+ sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>;
125
+ protected handleThought(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void>;
126
+ protected handleText(sessionId: string, content: OutgoingMessage): Promise<void>;
127
+ protected handleToolCall(sessionId: string, content: OutgoingMessage, verbosity: DisplayVerbosity): Promise<void>;
128
+ protected handleToolUpdate(sessionId: string, content: OutgoingMessage, verbosity: DisplayVerbosity): Promise<void>;
129
+ protected handlePlan(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void>;
130
+ protected handleUsage(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void>;
131
+ /** Suggested quick-reply actions (Teams restricts these to 1:1 personal chat only) */
132
+ private static readonly QUICK_ACTIONS;
133
+ /** Return QUICK_ACTIONS only if the conversation is 1:1 personal chat (Teams requirement) */
134
+ private getQuickActions;
135
+ /**
136
+ * Clean up all per-session state (contexts, drafts, dispatch queues, output modes).
137
+ * Removes both sessionId and threadId entries from _sessionContexts to prevent leaks.
138
+ */
139
+ private cleanupSessionState;
140
+ protected handleSessionEnd(sessionId: string, _content: OutgoingMessage): Promise<void>;
141
+ protected handleError(sessionId: string, content: OutgoingMessage): Promise<void>;
142
+ protected handleAttachment(sessionId: string, content: OutgoingMessage): Promise<void>;
143
+ protected handleSystem(sessionId: string, content: OutgoingMessage): Promise<void>;
144
+ protected handleModeChange(sessionId: string, content: OutgoingMessage): Promise<void>;
145
+ protected handleConfigUpdate(sessionId: string, content: OutgoingMessage): Promise<void>;
146
+ protected handleModelUpdate(sessionId: string, content: OutgoingMessage): Promise<void>;
147
+ protected handleUserReplay(sessionId: string, content: OutgoingMessage): Promise<void>;
148
+ protected handleResource(sessionId: string, content: OutgoingMessage): Promise<void>;
149
+ protected handleResourceLink(sessionId: string, content: OutgoingMessage): Promise<void>;
150
+ sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>;
151
+ sendNotification(notification: NotificationMessage): Promise<void>;
152
+ /**
153
+ * Create a new conversation thread for a session.
154
+ *
155
+ * Attempts to create a real Teams channel conversation via the Bot Framework
156
+ * connector API. If that fails (e.g., missing permissions, no stored conversation
157
+ * reference), falls back to using the existing conversation ID as thread context.
158
+ */
159
+ createSessionThread(sessionId: string, name: string): Promise<string>;
160
+ /**
161
+ * Rename a session thread. This is a no-op for Teams — the Teams API does not
162
+ * support renaming channel conversations. Renaming a group chat requires
163
+ * Graph API with Chat.ReadWrite.All permission, which most bot registrations
164
+ * don't have. The new name is stored in the session record for display purposes.
165
+ */
166
+ renameSessionThread(sessionId: string, newName: string): Promise<void>;
167
+ deleteSessionThread(sessionId: string): Promise<void>;
168
+ getChannelId(): string;
169
+ getTeamId(): string;
170
+ getAssistantSessionId(): string | null;
171
+ getAssistantThreadId(): string | null;
172
+ setSessionOutputMode(sessionId: string, mode: "low" | "medium" | "high"): void;
173
+ }
174
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}