@cuylabs/agent-channel-teams 0.10.0 → 0.12.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.
@@ -0,0 +1,165 @@
1
+ # Teams Handler Model
2
+
3
+ `agent-channel-teams` keeps the app-facing API centered on cuylabs handlers and
4
+ context objects, not Microsoft router classes.
5
+
6
+ ## Primary Entry Point
7
+
8
+ Use `createTeamsChannelAdapter()` when you need Teams-native behavior on top of
9
+ the generic M365 transport.
10
+
11
+ Ordinary message turns still flow through the underlying M365 adapter. Teams
12
+ specific activities are intercepted by the Teams layer first.
13
+
14
+ ## Handler Capability Groups
15
+
16
+ The handler surface is grouped by capability:
17
+
18
+ - `TeamsConversationUpdateHandlers`
19
+ - `TeamsMessageActivityHandlers`
20
+ - `TeamsCardActionHandlers`
21
+ - `TeamsConfigHandlers`
22
+ - `TeamsTaskModuleHandlers`
23
+ - `TeamsMessageExtensionHandlers`
24
+ - `TeamsTabHandlers`
25
+ - `TeamsMeetingHandlers`
26
+
27
+ `TeamsActivityHandlers` composes all of these into one shape for convenience.
28
+
29
+ This grouping is meant to reflect Teams concepts rather than Microsoft
30
+ `AgentApplication` routing classes.
31
+
32
+ ## Handler Context
33
+
34
+ Every Teams handler gets a `TeamsHandlerContext` with:
35
+
36
+ - `turnContext` for raw SDK access when needed
37
+ - `teams` for parsed Teams-specific activity metadata
38
+ - `channelData` for typed Teams channel data
39
+ - `runAgent()` to delegate work back into `agent-core`
40
+ - `sendInvoke()` to respond with a Teams invoke payload
41
+
42
+ Invoke handlers may either call `sendInvoke(...)` or return a `TeamsInvokeResult`
43
+ (`{ status, body }`). If a handled invoke returns nothing, the adapter sends an
44
+ empty `200` acknowledgement. If no Teams handler handles the invoke, the Teams
45
+ layer returns `501`.
46
+
47
+ Example:
48
+
49
+ ```ts
50
+ handlers: {
51
+ async taskSubmit(ctx) {
52
+ const payload = JSON.stringify(ctx.turnContext.activity.value);
53
+ const events = ctx.runAgent(`Handle this Teams dialog payload:\n${payload}`);
54
+ let text = "";
55
+
56
+ for await (const event of events) {
57
+ if (event.type === "text-delta") {
58
+ text += event.text;
59
+ }
60
+ }
61
+
62
+ return {
63
+ status: 200,
64
+ body: createTeamsDialogMessage(text),
65
+ };
66
+ },
67
+ }
68
+ ```
69
+
70
+ ## `prepareTurn()` Context
71
+
72
+ `prepareTurn()` receives both the parsed `teams` metadata and the typed
73
+ `channelData` projection. Use this when you need tenant IDs, meeting IDs, or
74
+ other Teams-specific context in the agent scope or system prompt.
75
+
76
+ ```ts
77
+ prepareTurn: ({ teams, channelData, user }) => ({
78
+ system: `Help ${user.userName} in tenant ${channelData?.tenant?.id ?? teams.tenantId}.`,
79
+ });
80
+ ```
81
+
82
+ ## Meeting Routing
83
+
84
+ The Teams layer maps the Microsoft meeting event names into cuylabs handler
85
+ slots.
86
+
87
+ - Event activities map through `TEAMS_MEETING_EVENT_NAMES`
88
+ - Invoke meeting activities map through `TEAMS_MEETING_INVOKE_NAMES`
89
+
90
+ Meeting-specific handlers include:
91
+
92
+ - `meetingStart`
93
+ - `meetingEnd`
94
+ - `participantsJoin`
95
+ - `participantsLeave`
96
+ - `meetingStageView`
97
+ - `meetingSmartReply`
98
+ - and the rest of the supported meeting event set
99
+
100
+ ## Conversation Updates
101
+
102
+ Teams conversation updates are no longer flattened into a single generic bucket.
103
+ The handler surface supports both the coarse and specific shapes:
104
+
105
+ - `conversationUpdate`
106
+ - `membersAdded`
107
+ - `membersRemoved`
108
+ - `channelCreated`
109
+ - `channelDeleted`
110
+ - `channelRenamed`
111
+ - `channelRestored`
112
+ - `channelShared`
113
+ - `channelUnshared`
114
+ - `teamRenamed`
115
+ - `teamArchived`
116
+ - `teamUnarchived`
117
+ - `teamDeleted`
118
+ - `teamHardDeleted`
119
+ - `teamRestored`
120
+
121
+ ## Task Modules, Message Extensions, Tabs, And Config
122
+
123
+ The Teams layer supports both grouped Teams concepts and the narrower invoke
124
+ families that exist in Microsoft's SDK:
125
+
126
+ - `dialogOpen`
127
+ - `dialogSubmit`
128
+ - `searchCommand`
129
+ - `selectResult`
130
+ - `cardSubmit`
131
+ - `feedbackSubmit`
132
+ - `taskFetch`
133
+ - `taskSubmit`
134
+ - `messageExtensionQuery`
135
+ - `messageExtensionQueryLink`
136
+ - `messageExtensionAnonymousQueryLink`
137
+ - `messageExtensionSelectItem`
138
+ - `messageExtensionSubmitAction`
139
+ - `messageExtensionFetchTask`
140
+ - `messageExtensionQuerySettingUrl`
141
+ - `messageExtensionSetting`
142
+ - `messageExtensionCardButtonClicked`
143
+ - `configFetch`
144
+ - `configSubmit`
145
+ - `tabFetch`
146
+ - `tabSubmit`
147
+ - `fileConsent`
148
+ - `actionableMessageExecuteAction`
149
+
150
+ The adapter still falls back from the narrow names into the grouped handlers
151
+ where that is the ergonomic default, so existing `dialogOpen`, `searchCommand`,
152
+ and `selectResult` handlers keep working.
153
+
154
+ ## `onTurn` Middleware
155
+
156
+ Use `onTurn(context, next)` when you need a pre-handler hook with full
157
+ `TurnContext` access.
158
+
159
+ Typical uses:
160
+
161
+ - logging or observability
162
+ - host-specific short-circuiting
163
+ - calling SDK helpers before cuylabs processing begins
164
+
165
+ If you do not call `next()`, normal Teams and M365 processing is skipped.
@@ -0,0 +1,91 @@
1
+ # Teams Helpers And Typed Data
2
+
3
+ `@cuylabs/agent-channel-teams` exposes a curated safe slice of
4
+ `@microsoft/agents-hosting-extensions-teams` so callers can use Teams helper
5
+ APIs without adopting Microsoft `AgentApplication` as the app model.
6
+
7
+ ## Main Helper Exports
8
+
9
+ Available from the main package:
10
+
11
+ - `TeamsInfo`
12
+ - `TeamsAttachmentDownloader`
13
+ - `parseTeamsChannelData`
14
+ - Teams channel data DTOs
15
+ - Teams event-name constants
16
+ - Teams team, tenant, notification, and meeting-related types that fit the
17
+ public bridge
18
+
19
+ The same helper surface is also available from:
20
+
21
+ ```ts
22
+ import {
23
+ TeamsInfo,
24
+ parseTeamsChannelData,
25
+ } from "@cuylabs/agent-channel-teams/extensions";
26
+ ```
27
+
28
+ Use the main package when you want the simplest app-facing import path. Use the
29
+ subpath when you want to make the helper grouping explicit in your codebase.
30
+
31
+ ## Typed Channel Data
32
+
33
+ `parseTeamsChannelData()` validates and returns Teams channel data with the SDK
34
+ types:
35
+
36
+ ```ts
37
+ import { parseTeamsChannelData } from "@cuylabs/agent-channel-teams";
38
+
39
+ const channelData = parseTeamsChannelData(turnContext.activity.channelData);
40
+ console.log(channelData.team?.id, channelData.tenant?.id);
41
+ ```
42
+
43
+ This parsing is strict by design. The adapter now uses the same strict parsing
44
+ path internally, so malformed Teams channel data fails fast instead of being
45
+ silently downgraded to `undefined`.
46
+
47
+ The Teams adapter also projects parsed channel data automatically into:
48
+
49
+ - `TeamsActivityInfo.channelData`
50
+ - `TeamsHandlerContext.channelData`
51
+ - `TeamsTurnRequestContext.channelData`
52
+
53
+ That means you often do not need to call `parseTeamsChannelData()` yourself.
54
+
55
+ ## `TeamsInfo`
56
+
57
+ Use `TeamsInfo` when you need Teams REST and connector-backed helpers from the
58
+ same `TurnContext` already flowing through the cuylabs adapter layer.
59
+
60
+ Examples:
61
+
62
+ ```ts
63
+ const details = await TeamsInfo.getTeamDetails(ctx.turnContext);
64
+ const members = await TeamsInfo.getPagedMembers(ctx.turnContext);
65
+ const participant = await TeamsInfo.getMeetingParticipant(ctx.turnContext);
66
+ ```
67
+
68
+ When the incoming activity carries files or hosted content, `TeamsAttachmentDownloader`
69
+ is also available from the curated surface for attachment-oriented flows.
70
+
71
+ This is the main reason `@microsoft/agents-hosting-extensions-teams` is a
72
+ required dependency of `agent-channel-teams`: the helper surface is part of the
73
+ supported bridge contract, not an optional afterthought.
74
+
75
+ ## Public Boundary
76
+
77
+ The curated helper bridge intentionally excludes Microsoft runtime routing
78
+ objects such as:
79
+
80
+ - `TeamsAgentExtension`
81
+ - `Meeting`
82
+ - `MessageExtension`
83
+ - `TaskModule`
84
+
85
+ Those classes are useful inside Microsoft's `AgentApplication` model, but the
86
+ cuylabs bridge keeps app code centered on:
87
+
88
+ - `createTeamsChannelAdapter()`
89
+ - Teams handler groups
90
+ - Teams helper functions and DTOs
91
+ - `agent-core` as the only execution engine
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuylabs/agent-channel-teams",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Teams-native channel layer for @cuylabs/agent-core built on top of @cuylabs/agent-channel-m365",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -10,19 +10,26 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js",
12
12
  "default": "./dist/index.js"
13
+ },
14
+ "./extensions": {
15
+ "types": "./dist/extensions.d.ts",
16
+ "import": "./dist/extensions.js",
17
+ "default": "./dist/extensions.js"
13
18
  }
14
19
  },
15
20
  "files": [
16
21
  "dist",
22
+ "docs",
17
23
  "README.md"
18
24
  ],
19
25
  "dependencies": {
20
- "@cuylabs/agent-channel-m365": "^0.10.0",
21
- "@cuylabs/agent-core": "^0.10.0"
26
+ "@microsoft/agents-activity": "^1.4.2",
27
+ "@microsoft/agents-hosting": "^1.4.2",
28
+ "@microsoft/agents-hosting-extensions-teams": "^1.4.2",
29
+ "@cuylabs/agent-channel-m365": "^0.12.0",
30
+ "@cuylabs/agent-core": "^0.12.0"
22
31
  },
23
32
  "peerDependencies": {
24
- "@microsoft/agents-activity": ">=0.1.0",
25
- "@microsoft/agents-hosting": ">=0.1.0",
26
33
  "express": ">=4.21.0 || >=5.0.0"
27
34
  },
28
35
  "peerDependenciesMeta": {
@@ -31,8 +38,6 @@
31
38
  }
32
39
  },
33
40
  "devDependencies": {
34
- "@microsoft/agents-activity": "^1.4.2",
35
- "@microsoft/agents-hosting": "^1.4.2",
36
41
  "@types/express": "^5.0.0",
37
42
  "@types/node": "^22.0.0",
38
43
  "express": "^5.2.1",
@@ -62,8 +67,8 @@
62
67
  "access": "public"
63
68
  },
64
69
  "scripts": {
65
- "build": "tsup src/index.ts --format esm --dts --clean",
66
- "dev": "tsup src/index.ts --format esm --dts --watch",
70
+ "build": "tsup src/index.ts src/extensions.ts --format esm --dts --clean",
71
+ "dev": "tsup src/index.ts src/extensions.ts --format esm --dts --watch",
67
72
  "typecheck": "tsc --noEmit",
68
73
  "test": "vitest run",
69
74
  "test:watch": "vitest",