feat(integrations): add Feishu (Lark) integration - #157
Conversation
…client, ws parser, repos)
|
I found one functional gap in the outbound Feishu path: The created session instead receives Could we wire |
…client, ws parser, repos)
|
I found one functional gap in the outbound Feishu path: The created session instead receives Could we wire |
Summary
Adds a Feishu (Lark) integration to Open Managed Agents, alongside the existing Slack / GitHub / Linear providers. This brings the full publish → configure → live lifecycle, including an outbound WebSocket long-connection runner so a Feishu bot needs no public webhook tunnel to receive messages.
The change is split into layered, conventional commits (schema → package → wiring → runner → console → docs).
What's included
packages/db-schema): Feishu publication/installation tables + a D1 adapter, the generated Drizzle migrations for both Node-SQLite and Node-Postgres, and the Cloudflare integrations migration.@open-managed-agents/feishupackage: a worker-compatible provider (event dispatch, publication/installation repos with WebCrypto AES-GCM credential encryption at rest), a Feishu OpenAPI client (tenant-access-token mint + cache + single-flight), a webhook frame parser/signature verifier, and the installation/install-proxy lifecycle.apps/integrations, publication-first install routes, and the shared install-proxy gateway entry.apps/main-nodeWS runner (src/lib/ws-feishu-runner.ts): the production event-ingest path. Dials out to Feishu via the official@larksuiteoapi/node-sdkWSClient, drives theawaiting_install → livestatus flip on a successful handshake, dedups redelivered frames, and dispatches into agent sessions. Opt-in viaFEISHU_WS_RUNNER=1.How credentials flow
Credentials are never read from env vars. The Console publish wizard issues a short-lived
formToken(JWT, 60 min); the user fills appId / appSecret / encryptKey / verificationToken on a rendered setup page; the secret is AES-GCM encrypted before being persisted to thefeishu_publicationsrow (status → credentials_filled). The runner decrypts it at runtime via the repo.Commit breakdown
feat(db)— feishu publication/installation schema, D1 adapter, migration (+ node sqlite/pg ops migrations)feat(feishu)—@open-managed-agents/feishupackagefeat(integrations)— provider wiring, publication-first install routes, gatewayfeat(main-node)— WS long-connection runner + install-bridge wiringchore(deps)—better-sqlite3^11.5 → ^13.0 (Node 24)feat(console)— integration pages + publish wizarddocs(feishu)— PRD, lifecycle, SDS, secrets, ADRschore— gitignore local D1 persist + coverage dirsTesting
@open-managed-agents/feishu— 70 unit tests (API client, webhook parse/signature, provider dispatch, repos).apps/main-node— WS-runner orchestration (envelope reconstruction, dedup, status flip, backoff, error isolation) + feishu-ops table schema/migration tests (FK=ON correctness and FK=OFF prod-shape trigger enforcement).integrations-adapters-cf— D1 feishu adapter tests.tsc --noEmit+ node-app typecheck clean.Out of scope / notes
recordIfNewdedup protects against duplicate delivery if two replicas ever connect.@larksuiteoapi/node-sdk(Node-only; added toapps/main-nodeonly, not the worker-compatiblepackages/feishu).Happy to restructure commits, split the PR, or adjust scope based on maintainer feedback.