@cuylabs/agent-channel-teams 0.10.0 → 0.11.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.
- package/README.md +223 -6
- package/dist/chunk-B5KRH22J.js +12 -0
- package/dist/extensions.d.ts +1 -0
- package/dist/extensions.js +10 -0
- package/dist/index.d.ts +150 -26
- package/dist/index.js +336 -27
- package/docs/README.md +33 -0
- package/docs/architecture.md +71 -0
- package/docs/handler-model.md +165 -0
- package/docs/teams-helpers.md +91 -0
- package/package.json +14 -9
|
@@ -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.
|
|
3
|
+
"version": "0.11.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
|
-
"@
|
|
21
|
-
"@
|
|
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.11.0",
|
|
30
|
+
"@cuylabs/agent-core": "^0.11.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",
|