npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-microsoft-teams

v0.1.0

Published

An Effect-native Microsoft Graph polling plugin for OpenCode 2

Readme

OpenCode Microsoft Teams

An Effect-native OpenCode plugin that polls selected Microsoft Teams chats through Microsoft Graph using the signed-in user's delegated permissions. It reads new messages, decides whether help would be useful, and runs the configured OpenCode agent when needed. Jira, GitHub, and other actions use the agent's existing tools and MCP connections.

The package uses Bun 1.4.2, Biome, TypeScript 7's native preview compiler, Effect 4, and @opencode/[email protected] through @opencode/plugin/effect. Effect and its platform packages are pinned to 4.0.0-rc.112; upgrade those packages together. The published bundle includes the Bun platform adapter while Effect and the OpenCode API remain shared peer dependencies.

Configure Microsoft Graph

Follow Graph setup to register a single-tenant public client, grant delegated Chat.Read and ChatMessage.Send, sign in, and find the exact chat IDs to allow. The plugin does not use a client secret.

Set these variables in the environment of the OpenCode process:

GRAPH_CLIENT_ID=your-application-client-id
GRAPH_TENANT_ID=your-tenant-id
GRAPH_TOKEN_CACHE=/absolute/path/to/graph-token-cache.json

The cache contains sensitive delegated authentication data in private plaintext. Keep it on an encrypted volume and restrict its file permissions. GRAPH_TOKEN_CACHE must be an absolute path.

Run the initial device login from the checkout:

bun run login

For the published package, use:

bunx --bun --package opencode-microsoft-teams opencode-teams-auth login

Complete login before starting OpenCode. The plugin silently refreshes the delegated token from the local MSAL cache while it runs. If the refresh fails, run the login command again.

Plugin configuration

After the package is published, add it to opencode.jsonc:

{
  "plugins": [
    {
      "package": "[email protected]",
      "options": {
        "chats": [
          { "id": "19:[email protected]" },
          {
            "id": "19:[email protected]",
            "agent": "reviewer",
            "prompt": "Help this team review pull requests. Keep replies concise."
          }
        ],
        "confidence": 0.85,
        "cooldownMs": 60000
      }
    }
  ]
}

chats is an exact allowlist. Only those Graph chat IDs are polled. The signed-in user's own messages are ignored so the plugin does not process its own replies. An omitted agent or model uses OpenCode's defaults. Configure named agents, model credentials, Jira/GitHub tools, and tool permissions in OpenCode before selecting them here. Permission requests are handled in OpenCode; this plugin does not add Teams controls.

See docs/opencode-config.example.jsonc for a copyable configuration example.

Behavior

Each configured chat is polled independently. The first poll starts at the current time by default, so existing history is not processed. On restart, the plugin uses persisted message timestamps and IDs to catch up across Graph pagination. A poll reads up to the configured history limit for the agent context.

In ambient mode, a tool-free model call evaluates recent conversation context. Low-confidence decisions, ordinary conversation, and malformed model output stay silent. In mentions mode, the plugin considers messages that mention the signed-in user. A qualifying request runs the selected OpenCode agent, and the final reply is sent as the signed-in user with the configured replyPrefix (default [OpenCode] ). The agent can return [SILENT] to suppress a reply. Replies are capped at 6,000 characters.

Messages are processed sequentially within each chat, while different chats can run concurrently. cooldownMs limits ambient replies; mention-triggered messages bypass the ambient cooldown. timeoutMs interrupts agent work that exceeds its limit.

| Option | Default | Purpose | | --- | --- | --- | | chats | Required | Nonempty list of exact { "id": "..." } Graph chat IDs | | agent | OpenCode default | Agent ID; also available per chat | | model | OpenCode default | provider/model or provider/model#variant; also per chat | | triageModel | OpenCode default | Model for tool-free triage; also per chat | | prompt | Built-in colleague prompt | Replaces the task prompt; also per chat | | triagePrompt | Built-in conservative policy | Decision prompt; also per chat | | mode | ambient | ambient or mentions; also per chat | | confidence | 0.85 | Minimum confidence for ambient responses; also per chat | | cooldownMs | 60000 | Minimum gap between ambient replies; also per chat | | pollIntervalMs | 30000 | Delay between Graph polls | | initialLookbackMs | 0 | How far before startup the first poll may read | | replyPrefix | [OpenCode] | Prefix added to automated replies | | historyLimit | 12 | Recent messages supplied as agent context | | timeoutMs | 180000 | Maximum agent execution time |

pollIntervalMs accepts 1,000–3,600,000 milliseconds. initialLookbackMs accepts up to seven days; configure it when the first run should process a recent window, or keep it at 0 to start at the current time. historyLimit accepts up to 100 messages. mentions mode means messages that mention the signed-in user; it does not require a separate identity or installation.

State and lifecycle

OpenCode plugin storage holds per-tenant, per-user, per-chat message timestamps and IDs, the OpenCode session ID, recent transcript state, and the last reply timestamp. Treat that storage as chat data. On first activation, the plugin persists a starting cursor at the current time or the configured lookback boundary. Later polls catch up across Graph pages using that cursor. Only newly created messages advance processing; edits, reactions, and deletions do not retrigger work. A message is claimed and persisted before tool work begins, which avoids repeating writes after a restart. Failed work, including a failed Graph send, is not automatically retried; inspect the OpenCode session and logs before asking for another attempt. Persistence reduces duplicate processing but does not provide an exactly-once guarantee for external actions.

The plugin's Effect scope owns the Graph client, token refresh boundary, polling workers, and OpenCode work. Reloading or unloading cancels the workers and interrupts active agent work. Use one plugin instance per OpenCode workspace.

Headless startup

OpenCode loads workspace plugins lazily. Follow headless startup to activate the workspace after starting opencode2 serve, then inspect the OpenCode logs for plugin activation and polling messages.

Develop

bun install --frozen-lockfile
bun run check
bun run typecheck
bun test
bun run build

To load this checkout before publication, run bun run build, then use the absolute path to this repository directory as the plugin's package value. OpenCode's local plugin discovery uses the root index.js, which forwards to the build. Set the Graph variables in the process that starts OpenCode. Rebuild after editing and reload the plugin through OpenCode to apply changes.

Tests cover triage, chat isolation, message claims, pagination, restart catch-up, session interaction, and scoped shutdown without real Graph credentials. A live Microsoft Graph account and a configured OpenCode model are needed for a full integration test.

The GitHub workflows run validation and publish public releases using npm OIDC. See publishing setup for initial package registration and trusted publisher configuration.