lark-acp 1.0.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.
Files changed (3) hide show
  1. package/README.md +242 -0
  2. package/dist/index.js +122 -0
  3. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # Lark ACP Bridge
2
+
3
+ Bridge Lark/Feishu messages to any ACP-compatible AI agent.
4
+
5
+ `lark-acp` connects to the Lark/Feishu messaging platform via WebSocket, polls incoming direct messages and group mentions, forwards them to an ACP agent over stdio, and sends agent replies back to Lark.
6
+
7
+ Inspired by [wechat-acp](https://github.com/formulahendry/wechat-acp), but for Lark/Feishu.
8
+
9
+ ## Features
10
+
11
+ - Lark/Feishu WebSocket event streaming (not polling)
12
+ - One ACP agent session per Lark conversation (1:1 DM or group chat)
13
+ - Built-in ACP agent presets for common CLIs
14
+ - Custom raw agent command support
15
+ - Agent thinking/reasoning display in Lark (optional)
16
+ - File system access for agents (read/write)
17
+ - Auto-approve tool permission requests
18
+ - Group chat support with `@mention` filtering
19
+ - Real-time typing indicator (emoji reaction)
20
+ - Built with Bun + TypeScript for speed
21
+
22
+ ## Requirements
23
+
24
+ - [Bun](https://bun.sh) 1.0.0+
25
+ - Lark/Feishu bot app credentials (App ID + App Secret)
26
+ - An ACP-compatible agent available locally or through `bunx`
27
+
28
+ ## Quick Start
29
+
30
+ Start with a built-in agent preset:
31
+
32
+ ```bash
33
+ # Install from npm (recommended)
34
+ npm install -g lark-acp
35
+ # or via Bun
36
+ bun install -g lark-acp
37
+
38
+ # Initialize config
39
+ lark-acp init # creates lark-acp.json, configure with your Lark credentials
40
+
41
+ # Start the bridge
42
+ lark-acp start # or: lark-acp start --agent copilot
43
+ ```
44
+
45
+ Or use a raw custom command:
46
+
47
+ ```bash
48
+ lark-acp start --agent "bunx my-agent --acp"
49
+ ```
50
+
51
+ On first run, the bridge will:
52
+
53
+ 1. Load config from `lark-acp.json` (or `~/.lark-acp/config.json`)
54
+ 2. Connect to Lark via WebSocket
55
+ 3. Begin polling for direct messages and group mentions
56
+ 4. Route each message to an isolated ACP session per chat
57
+
58
+ ## Configuration
59
+
60
+ ### Config File
61
+
62
+ Create or edit `lark-acp.json` (search order: `$LARK_ACP_CONFIG` → `./lark-acp.json` → `~/.lark-acp/config.json`):
63
+
64
+ ```json
65
+ {
66
+ "lark": {
67
+ "appId": "cli_xxxxxxxxxxxx",
68
+ "appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
69
+ "botName": "AI Assistant",
70
+ "encryptKey": "",
71
+ "verificationToken": ""
72
+ },
73
+ "agent": "claude",
74
+ "acp": {
75
+ "cwd": "",
76
+ "idleTimeoutMs": 1800000,
77
+ "maxConcurrent": 10,
78
+ "showThoughts": false,
79
+ "mcpServers": []
80
+ },
81
+ "autoApprovePermissions": true
82
+ }
83
+ ```
84
+
85
+ See `lark-acp.example.json` for the full schema.
86
+
87
+ ### CLI Options
88
+
89
+ ```text
90
+ lark-acp init [options] initialize config file
91
+ lark-acp agents list built-in agent presets
92
+ lark-acp start [options] start the bridge
93
+ lark-acp --help show help
94
+ lark-acp --version show version
95
+ ```
96
+
97
+ Start options:
98
+
99
+ - `--agent <preset|command>`: Built-in preset name (e.g., `claude`, `copilot`) or raw command string
100
+ - `--cwd <dir>`: Working directory for the agent process
101
+ - `--config <file>`: Load JSON config file (overrides default search)
102
+ - `--idle-timeout <minutes>`: Session idle timeout in minutes (default: 30; use 0 for unlimited)
103
+ - `--max-concurrent <count>`: Maximum concurrent agent sessions (default: 10)
104
+ - `--show-thoughts`: Display agent thinking/reasoning in Lark (default: off)
105
+
106
+ Examples:
107
+
108
+ ```bash
109
+ lark-acp start --agent copilot
110
+ lark-acp start --agent claude --cwd ~/my-project
111
+ lark-acp start --agent "bunx my-agent --acp" --show-thoughts
112
+ ```
113
+
114
+ ## Built-in Agent Presets
115
+
116
+ List available presets:
117
+
118
+ ```bash
119
+ lark-acp agents
120
+ ```
121
+
122
+ Current presets:
123
+
124
+ | Preset | Agent | Command |
125
+ |--------|-------|---------|
126
+ | `claude` | Claude Code | `bunx @zed-industries/claude-code-acp` |
127
+ | `copilot` | GitHub Copilot | `bunx @github/copilot --acp --yolo` |
128
+ | `gemini` | Google Gemini | `bunx @google/gemini-cli --experimental-acp` |
129
+ | `qwen` | Qwen Code | `bunx @qwen-code/qwen-code --acp --experimental-skills` |
130
+ | `codex` | OpenAI Codex | `bunx @zed-industries/codex-acp` |
131
+ | `opencode` | OpenCode | `bunx opencode-ai acp` |
132
+ | `pi` | Pi | `bunx -y pi-acp` |
133
+
134
+ ## Getting Lark Credentials
135
+
136
+ 1. Go to [Lark Open Platform](https://open.larkoffice.com/)
137
+ 2. Create a new app → enable "Bot" capability
138
+ 3. Get App ID and App Secret from "Credentials & Basic Info"
139
+ 4. Subscribe to `im.message.receive_v1` events
140
+ 5. Configure the webhook URL to your bridge's public address (if using WebSocket mode)
141
+
142
+ ## Architecture
143
+
144
+ ```
145
+ src/
146
+ ├── config/ # Config loading, validation, singleton
147
+ ├── services/
148
+ │ ├── lark.ts # Lark SDK: event dispatcher, reply handling, dedup
149
+ │ └── acp.ts # ACP session manager: spawn, queue, evict
150
+ ├── agents.ts # Built-in agent preset registry and resolver
151
+ ├── cli.ts # CLI arg parsing (init, agents, start)
152
+ └── index.ts # Entry point: boot sequence
153
+ ```
154
+
155
+ ## How It Works
156
+
157
+ 1. **Event Dispatcher**: Listens for incoming messages via Lark WebSocket
158
+ - Filters duplicates, validates mentions (for group chats)
159
+ - Routes to ACP session manager
160
+ 2. **Session Manager**: One ACP agent process per chat (group or DM)
161
+ - Queues messages and processes them sequentially per user
162
+ - Auto-evicts oldest sessions when max concurrent reached
163
+ - Spawns fresh process on first message, reuses for subsequent messages
164
+ 3. **ACP Protocol**: Bidirectional communication over stdin/stdout ndjson
165
+ - Streams message chunks in real-time
166
+ - Handles tool calls with permission gating
167
+ - Captures and displays agent thinking (if enabled)
168
+ 4. **Reply Handler**: Sends agent responses back to Lark
169
+ - Splits long replies into Lark-safe chunks (≤4000 chars at paragraph breaks)
170
+ - Removes typing indicator emoji reaction
171
+ 5. **Idle Cleanup**: Every 5 minutes, kills sessions idle for `idleTimeoutMs`
172
+
173
+ ## Runtime Behavior
174
+
175
+ - Each Lark conversation (1:1 DM or group) gets a dedicated ACP session and subprocess
176
+ - Messages are processed serially per conversation
177
+ - Replies are formatted for Lark before sending (markdown → text)
178
+ - A thinking emoji (💭) is added while processing; removed when reply is sent
179
+ - Sessions are cleaned up after inactivity (set `idleTimeoutMs` to `0` to disable)
180
+ - Tool calls are logged in real-time for debugging
181
+
182
+ ## Storage
183
+
184
+ By default, runtime files are stored at:
185
+
186
+ ```text
187
+ ~/.lark-acp/config.json # fallback config location
188
+ ```
189
+
190
+ The bridge does NOT persist any conversation history or state — each session is ephemeral.
191
+
192
+ ## Current Limitations
193
+
194
+ - **Text messages only** — Non-text messages (images, files, voice) are rejected with a friendly message
195
+ - **Sequential processing** — Messages per conversation are processed one-by-one (not in parallel)
196
+ - **No group context reuse** — Group chats do not share agent context with 1:1 DMs with the same user
197
+ - **No MCP server support yet** — `mcpServers` config is parsed but not wired to the ACP protocol
198
+ - **Permission requests are auto-approved** — No user confirmation dialog (configurable via `autoApprovePermissions`)
199
+ - **Agent communication is subprocess-only over stdio** — No network-based agent support
200
+ - **Some preset agents may require separate auth** — e.g., Claude Code requires API key setup
201
+
202
+ ## Development
203
+
204
+ ### Local Setup
205
+
206
+ ```bash
207
+ git clone <repo-url>
208
+ cd lark-acp
209
+ bun install
210
+ ```
211
+
212
+ ### Development Commands
213
+
214
+ ```bash
215
+ bun run dev # start with file watching
216
+ bun run start # start without watching
217
+ bun run build # compile to single binary at dist/lark-acp
218
+ bun run typecheck # run TypeScript type checker
219
+ bun run check # run Biome lint + format check
220
+ bun run format # auto-format code in place
221
+ ```
222
+
223
+ ### Installing Locally
224
+
225
+ ```bash
226
+ bun run install-bin # build and install to ~/.local/bin/lark-acp
227
+ ~/.local/bin/lark-acp --help
228
+ ```
229
+
230
+ ## Contributing
231
+
232
+ Contributions are welcome! Please ensure:
233
+
234
+ - `bun run check` passes (lint + format)
235
+ - `bun run typecheck` passes
236
+ - Code follows the existing style in `CLAUDE.md`
237
+
238
+ For release/publishing workflow, see [.github/RELEASE.md](.github/RELEASE.md).
239
+
240
+ ## License
241
+
242
+ MIT