Documentation
¶
Overview ¶
Package msteams implements the Microsoft Teams channel plugin via Graph API polling. It is outbound-only — no inbound webhooks, no public endpoint. See FORGE_MSTEAMS_CHANNEL_GRAPH_POLLING.md for the design.
Index ¶
- type AdmitMode
- type AuthFlow
- type ChatMessage
- type ChatRef
- type DeltaPage
- type MeResponse
- type Plugin
- func (p *Plugin) Init(cfg channels.ChannelConfig) error
- func (p *Plugin) Name() string
- func (p *Plugin) NormalizeEvent(raw []byte) (*channels.ChannelEvent, error)
- func (p *Plugin) SendResponse(event *channels.ChannelEvent, response *a2a.Message) error
- func (p *Plugin) Start(ctx context.Context, handler channels.EventHandler) error
- func (p *Plugin) Stop() error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AdmitMode ¶
type AdmitMode string
AdmitMode is the inbound message gating policy.
const ( // AdmitMention drops every message except those that @-mention the agent. AdmitMention AdmitMode = "mention" // AdmitDM drops every message except 1:1 chat messages. AdmitDM AdmitMode = "dm" // AdmitMentionOrDM admits messages that satisfy either condition. AdmitMentionOrDM AdmitMode = "mention_or_dm" )
type AuthFlow ¶
type AuthFlow string
AuthFlow identifies the OAuth2 grant the adapter uses.
const ( // FlowDelegated uses a long-lived refresh token captured at setup time // (via the device-code flow) to obtain access tokens that act as a // specific user. Refresh tokens rotate — the new token returned with // each refresh response should be persisted back to the secret store. FlowDelegated AuthFlow = "delegated" // FlowClientCredentials uses a client_id + client_secret pair to obtain // app-only tokens. Requires admin consent + appropriate application // permissions (RSC) on chats. user_id must be configured explicitly. FlowClientCredentials AuthFlow = "client_credentials" )
type ChatMessage ¶
type ChatMessage struct {
ID string `json:"id"`
ChatID string `json:"chatId"`
ChannelIdentity any `json:"channelIdentity,omitempty"` // present for team-channel messages; we ignore them
ChatType string `json:"chatType,omitempty"` // sometimes inlined; usually fetched separately
CreatedDateTime string `json:"createdDateTime"`
LastModifiedDateTime string `json:"lastModifiedDateTime"`
Subject string `json:"subject,omitempty"`
MessageType string `json:"messageType,omitempty"`
Importance string `json:"importance,omitempty"`
From *struct {
User *struct {
ID string `json:"id"`
DisplayName string `json:"displayName"`
UserIdentityType string `json:"userIdentityType,omitempty"`
TenantID string `json:"tenantId,omitempty"`
} `json:"user,omitempty"`
Application *struct {
ID string `json:"id"`
DisplayName string `json:"displayName"`
ApplicationIdentity string `json:"applicationIdentityType,omitempty"`
} `json:"application,omitempty"`
} `json:"from,omitempty"`
Body struct {
ContentType string `json:"contentType"` // "html" or "text"
Content string `json:"content"`
} `json:"body"`
Mentions []markdown.TeamsMention `json:"mentions,omitempty"`
}
ChatMessage is the trimmed Graph chatMessage representation the adapter cares about. Fields not modelled here decode silently.
type ChatRef ¶
type ChatRef struct {
ID string `json:"id"`
Topic string `json:"topic,omitempty"`
ChatType string `json:"chatType"`
}
ChatRef is the minimal shape returned by GET /me/chats / /chats — enough to drive per-chat polling. ChatType discriminates oneOnOne/group/meeting.
type DeltaPage ¶
type DeltaPage struct {
Messages []ChatMessage `json:"value"`
NextLink string `json:"@odata.nextLink,omitempty"`
DeltaLink string `json:"@odata.deltaLink,omitempty"`
}
DeltaPage is one page of a getAllMessages/delta response. Exactly one of NextLink or DeltaLink is set per page; the poll loop continues paging until DeltaLink appears, then persists it.
type MeResponse ¶
type MeResponse struct {
ID string `json:"id"`
DisplayName string `json:"displayName"`
UserPrincipalName string `json:"userPrincipalName"`
}
MeResponse is the trimmed Graph /me payload — only the fields the adapter caches at startup.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin implements channels.ChannelPlugin for Microsoft Teams.
func New ¶
func New() *Plugin
New returns an uninitialised plugin. Init must be called before Start.
func (*Plugin) NormalizeEvent ¶
func (p *Plugin) NormalizeEvent(raw []byte) (*channels.ChannelEvent, error)
NormalizeEvent decodes a raw Graph chatMessage JSON into a ChannelEvent. Used by the polling loop and by tests that want to feed a stored payload through the adapter.
func (*Plugin) SendResponse ¶
SendResponse delivers an agent reply back to the Teams chat. Mirrors the Slack/Telegram large-response handling: small responses inline, large responses summary + hosted-content attachment, fallback to chunked text.
Every successful outbound message ID is recorded in the dedup ring via markSent. In delegated mode the agent shares the user's Graph identity (delegated tokens act as the user), so messages we post come back via polling with the same from.user.id as messages the user types directly. The dedup ring is the ONLY way to tell our own posts apart from real inbound traffic before reaching the admission gate.