{"_id":"@ajac-zero/chat-adapter-zulip","name":"@ajac-zero/chat-adapter-zulip","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@ajac-zero/chat-adapter-zulip","version":"0.1.0","description":"Community Zulip adapter for the Chat SDK (https://chat-sdk.dev)","type":"module","engines":{"node":">=20"},"main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","clean":"rm -rf dist","prepublishOnly":"pnpm build && pnpm test && pnpm typecheck"},"dependencies":{"@chat-adapter/shared":"^4.28.1","chat":"^4.28.1"},"devDependencies":{"@types/node":"^25.3.2","tsup":"^8.5.1","typescript":"^5.7.2","vitest":"^4.0.18"},"peerDependencies":{"chat":"^4.28.1"},"author":{"name":"Anibal Angulo","email":"https://github.com/ajac-zero"},"repository":{"type":"git","url":"git+https://github.com/ajac-zero/chat-adapter-zulip.git"},"homepage":"https://github.com/ajac-zero/chat-adapter-zulip#readme","bugs":{"url":"https://github.com/ajac-zero/chat-adapter-zulip/issues"},"publishConfig":{"access":"public"},"keywords":["chat","chat-sdk","zulip","bot","adapter"],"license":"MIT","gitHead":"f4a16b0a1bcacff2dfcb0598133b9cf6071225d2","_id":"@ajac-zero/chat-adapter-zulip@0.1.0","_nodeVersion":"25.3.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-oQmdrQUzRaYwE+lg1Iy9OVCQkFWjfNbTBQb3XIlpMTLnLl/WP41qHwlDIp+u/iss5Fb3C7mI1JC6WsQC4UKF3w==","shasum":"466e92b8bff4485d697a54070ebeb86b11b06116","tarball":"https://registry.npmjs.org/@ajac-zero/chat-adapter-zulip/-/chat-adapter-zulip-0.1.0.tgz","fileCount":5,"unpackedSize":40305,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFzNED9GkuveYDpWb7YkGftFKU0Sqs43/HzHcSOG6bOkAiEAoYn6zMnMmmLfIk42saD3gw9fNY74M8gduLPGB0rFCf4="}]},"_npmUser":{"name":"ajac-zero","email":"ajcardoza2000@gmail.com"},"directories":{},"maintainers":[{"name":"ajac-zero","email":"ajcardoza2000@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/chat-adapter-zulip_0.1.0_1778712807948_0.7230251978654751"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-13T22:53:27.772Z","0.1.0":"2026-05-13T22:53:28.077Z","modified":"2026-05-13T22:53:28.362Z"},"maintainers":[{"name":"ajac-zero","email":"ajcardoza2000@gmail.com"}],"description":"Community Zulip adapter for the Chat SDK (https://chat-sdk.dev)","homepage":"https://github.com/ajac-zero/chat-adapter-zulip#readme","keywords":["chat","chat-sdk","zulip","bot","adapter"],"repository":{"type":"git","url":"git+https://github.com/ajac-zero/chat-adapter-zulip.git"},"author":{"name":"Anibal Angulo","email":"https://github.com/ajac-zero"},"bugs":{"url":"https://github.com/ajac-zero/chat-adapter-zulip/issues"},"license":"MIT","readme":"# @ajac-zero/chat-adapter-zulip\n\n[![npm version](https://img.shields.io/npm/v/@ajac-zero/chat-adapter-zulip)](https://www.npmjs.com/package/@ajac-zero/chat-adapter-zulip)\n[![npm downloads](https://img.shields.io/npm/dm/@ajac-zero/chat-adapter-zulip)](https://www.npmjs.com/package/@ajac-zero/chat-adapter-zulip)\n\nCommunity [Zulip](https://zulip.com) adapter for the [Chat SDK](https://chat-sdk.dev). Connects a Chat SDK bot to a Zulip organization via the outgoing-webhook integration for inbound traffic and the Zulip REST API for outbound traffic.\n\n> **Status:** community-maintained. A merge of this implementation into the official `@chat-adapter/*` scope is pending — track the upstream proposal at the Chat SDK repository. Once merged officially, this package will be deprecated in favour of `@chat-adapter/zulip`.\n\n## Installation\n\n```bash\npnpm add @ajac-zero/chat-adapter-zulip chat\n```\n\n`chat` is a peer dependency so the bot uses the same `Chat` instance as every other adapter.\n\n## Usage\n\nThe adapter auto-detects `ZULIP_SITE`, `ZULIP_BOT_EMAIL`, `ZULIP_API_KEY`, `ZULIP_BOT_USERNAME`, and `ZULIP_WEBHOOK_TOKEN` from the environment.\n\n```typescript\nimport { Chat } from \"chat\";\nimport { createZulipAdapter } from \"@ajac-zero/chat-adapter-zulip\";\n\nconst bot = new Chat({\n  userName: \"mybot\",\n  adapters: {\n    zulip: createZulipAdapter(),\n  },\n});\n\nbot.onNewMention(async (thread, message) => {\n  await thread.post(`You said: ${message.text}`);\n});\n```\n\n## Webhook route\n\n```typescript\nimport { bot } from \"@/lib/bot\";\n\nexport async function POST(request: Request): Promise<Response> {\n  return bot.webhooks.zulip(request);\n}\n```\n\nConfigure the URL as a Zulip outgoing-webhook bot under **Personal settings → Bots → Add a new bot → Outgoing webhook**, then point it at `https://your-domain.com/api/webhooks/zulip`. Copy the bot's webhook token (shown on the bot's settings page — **distinct** from the bot's API key, even though both look like 32-character tokens) into `ZULIP_WEBHOOK_TOKEN`.\n\n## Configuration\n\n| Option | Required | Description |\n|--------|----------|-------------|\n| `site` | Yes | Zulip organization base URL, e.g. `https://example.zulipchat.com`. Auto-detected from `ZULIP_SITE` |\n| `apiKey` | Yes | Bot API key. Auto-detected from `ZULIP_API_KEY` |\n| `botEmail` | No | Bot user email, used as the REST API Basic Auth username. Auto-detected from `ZULIP_BOT_EMAIL`. Falls back to the value reported in the first webhook payload |\n| `webhookToken` | No | Shared token embedded in outgoing-webhook payloads. Auto-detected from `ZULIP_WEBHOOK_TOKEN`. Distinct from `apiKey` — Zulip generates a separate value when you create an outgoing-webhook bot. When unset, incoming requests are accepted without verification (a warning is logged once) |\n| `userName` | No | Bot display name for mention detection. Auto-detected from `ZULIP_BOT_USERNAME` or `/api/v1/users/me` |\n| `logger` | No | Logger instance (defaults to `ConsoleLogger(\"info\")`) |\n\n## Environment variables\n\n```bash\nZULIP_SITE=https://example.zulipchat.com\nZULIP_BOT_EMAIL=mybot-bot@example.zulipchat.com\nZULIP_API_KEY=...\nZULIP_BOT_USERNAME=\"My Bot\"\nZULIP_WEBHOOK_TOKEN=...\n```\n\n## Thread IDs\n\n- Stream topics: `zulip:s:{streamId}:{base64UrlTopic}`\n- Direct messages: `zulip:p:{sortedUserIds}`\n\nTopics are base64url-encoded because they may contain colons and other delimiter characters.\n\n## Features\n\n### Messaging\n\n| Feature | Supported |\n|---------|-----------|\n| Post message | Yes |\n| Edit message | Yes |\n| Delete message | Yes |\n| File uploads | No |\n| Streaming | Post+Edit fallback |\n\n### Rich content\n\n| Feature | Supported |\n|---------|-----------|\n| Card format | Markdown fallback |\n| Buttons | No |\n| Link buttons | No |\n| Select menus | No |\n| Tables | GFM |\n| Fields | Yes |\n| Images in cards | No |\n| Modals | No |\n\n### Conversations\n\n| Feature | Supported |\n|---------|-----------|\n| Slash commands | No |\n| Mentions | Yes (outgoing-webhook trigger) |\n| Add reactions | Yes |\n| Remove reactions | Yes |\n| Reaction events | No (outgoing webhooks only fire on new messages) |\n| Typing indicator | Yes |\n| DMs | Yes |\n| Ephemeral messages | No |\n\n### Message history\n\n| Feature | Supported |\n|---------|-----------|\n| Fetch messages | Yes (REST `/api/v1/messages`) |\n| Fetch single message | No (planned) |\n| Fetch thread info | Yes |\n| Fetch channel info | Yes (streams only) |\n| List threads | No |\n| Fetch channel messages | No (planned) |\n| Post channel message | Use `Thread.post` |\n\n## Notes\n\n- This adapter intentionally limits its surface to what Zulip's outgoing-webhook integration delivers: new stream messages where the bot is `@`-mentioned, and DMs addressed to the bot. Reaction events, message edits, and presence updates are **not** received via the webhook channel. Layer a Zulip event-queue poller on top if you need them.\n- Cards render as Zulip markdown using the SDK's standard `cardToFallbackText` helper. Buttons and select menus have no Zulip equivalent and are dropped from the rendered output.\n- Bodies are truncated to fit Zulip's 10 000-character per-message limit, with an ellipsis appended.\n- Stream sending uses `type: \"stream\"` with the numeric stream id; DMs use `type: \"direct\"` with a JSON-encoded list of recipient ids.\n- SDK emoji placeholders (`{{emoji:wave}}`) are substituted with Unicode emoji before sending so the literal text never leaks into your Zulip channel.\n\n## Building from source\n\n```bash\npnpm install\npnpm test\npnpm typecheck\npnpm build\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-09bda4920dd3de80ecc3fdb84c997de8"}